Coverage for admin/sgx_attestation.py: 96%

45 statements  

« prev     ^ index     » next       coverage.py v7.5.3, created at 2025-07-10 13:43 +0000

1# The MIT License (MIT) 

2# 

3# Copyright (c) 2021 RSK Labs Ltd 

4# 

5# Permission is hereby granted, free of charge, to any person obtaining a copy of 

6# this software and associated documentation files (the "Software"), to deal in 

7# the Software without restriction, including without limitation the rights to 

8# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 

9# of the Software, and to permit persons to whom the Software is furnished to do 

10# so, subject to the following conditions: 

11# 

12# The above copyright notice and this permission notice shall be included in all 

13# copies or substantial portions of the Software. 

14# 

15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 

16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 

17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 

18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 

19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 

20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 

21# SOFTWARE. 

22 

23import ecdsa 

24from .misc import info, head, get_hsm, AdminError, get_ud_value_for_attestation 

25from .unlock import do_unlock 

26from sgx.envelope import SgxEnvelope 

27from .certificate import HSMCertificateV2, HSMCertificateV2ElementSGXQuote, \ 

28 HSMCertificateV2ElementSGXAttestationKey, \ 

29 HSMCertificateV2ElementX509 

30 

31 

32def do_attestation(options): 

33 head("### -> Get powHSM attestation", fill="#") 

34 hsm = None 

35 

36 # Require an output file 

37 if options.output_file_path is None: 

38 raise AdminError("No output file path given") 

39 

40 # Get the UD value for the attestation 

41 info("Gathering user-defined attestation value... ", options.verbose) 

42 ud_value = get_ud_value_for_attestation(options.attestation_ud_source) 

43 info(f"Using {ud_value} as the user-defined attestation value") 

44 

45 # Attempt to unlock the device 

46 if not options.no_unlock: 

47 try: 

48 do_unlock(options, label=False) 

49 except Exception as e: 

50 raise AdminError(f"Failed to unlock device: {str(e)}") 

51 

52 # Connection 

53 hsm = get_hsm(options.verbose) 

54 

55 # powHSM attestation 

56 info("Gathering powHSM attestation... ", options.verbose) 

57 try: 

58 powhsm_attestation = hsm.get_powhsm_attestation(ud_value) 

59 except Exception as e: 

60 raise AdminError(f"Failed to gather powHSM attestation: {str(e)}") 

61 info("powHSM attestation gathered") 

62 

63 hsm.disconnect() 

64 

65 # Parse envelope 

66 info("Parsing the powHSM attestation envelope...") 

67 try: 

68 envelope = SgxEnvelope( 

69 bytes.fromhex(powhsm_attestation["envelope"]), 

70 bytes.fromhex(powhsm_attestation["message"])) 

71 except Exception as e: 

72 raise AdminError(f"SGX envelope parse error: {str(e)}") 

73 

74 # Conversions 

75 quote_signature = ecdsa.util.sigdecode_string( 

76 envelope.quote_auth_data.signature.r + 

77 envelope.quote_auth_data.signature.s, 

78 ecdsa.NIST256p.order) 

79 quote_signature = ecdsa.util.sigencode_der( 

80 quote_signature[0], 

81 quote_signature[1], 

82 ecdsa.NIST256p.order) 

83 att_key = ecdsa.VerifyingKey.from_string( 

84 envelope.quote_auth_data.attestation_key.x + 

85 envelope.quote_auth_data.attestation_key.y, 

86 ecdsa.NIST256p) 

87 qe_rb_signature = ecdsa.util.sigdecode_string( 

88 envelope.quote_auth_data.qe_report_body_signature.r + 

89 envelope.quote_auth_data.qe_report_body_signature.s, 

90 ecdsa.NIST256p.order) 

91 qe_rb_signature = ecdsa.util.sigencode_der( 

92 qe_rb_signature[0], 

93 qe_rb_signature[1], 

94 ecdsa.NIST256p.order) 

95 

96 # Generate and save the attestation certificate 

97 info("Generating the attestation certificate... ", options.verbose) 

98 att_cert = HSMCertificateV2() 

99 

100 att_cert.add_element( 

101 HSMCertificateV2ElementSGXQuote({ 

102 "name": "quote", 

103 "message": envelope.quote.get_raw_data().hex(), 

104 "custom_data": envelope.custom_message.hex(), 

105 "signature": quote_signature.hex(), 

106 "signed_by": "attestation", 

107 })) 

108 att_cert.add_element( 

109 HSMCertificateV2ElementSGXAttestationKey({ 

110 "name": "attestation", 

111 "message": envelope.quote_auth_data.qe_report_body.get_raw_data().hex(), 

112 "key": att_key.to_string("uncompressed").hex(), 

113 "auth_data": envelope.qe_auth_data.data.hex(), 

114 "signature": qe_rb_signature.hex(), 

115 "signed_by": "quoting_enclave", 

116 })) 

117 att_cert.add_element( 

118 HSMCertificateV2ElementX509({ 

119 "name": "quoting_enclave", 

120 "message": envelope.qe_cert_data.certs[0], 

121 "signed_by": "platform_ca", 

122 })) 

123 att_cert.add_element( 

124 HSMCertificateV2ElementX509({ 

125 "name": "platform_ca", 

126 "message": envelope.qe_cert_data.certs[1], 

127 "signed_by": "sgx_root", 

128 })) 

129 

130 att_cert.add_target("quote") 

131 att_cert.save_to_jsonfile(options.output_file_path) 

132 

133 info(f"Attestation certificate saved to {options.output_file_path}")