Coverage for ledger/protocol_v1.py: 100%

48 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 

23from comm.protocol_v1 import HSM1Protocol 

24from .protocol import HSM2ProtocolLedger, HSM2ProtocolError 

25from ledger.hsm2dongle import ( 

26 HSM2Dongle, 

27 HSM2DongleError, 

28 HSM2DongleErrorResult, 

29 HSM2DongleTimeoutError, 

30 HSM2DongleCommError, 

31) 

32 

33 

34class HSM1ProtocolLedger(HSM1Protocol): 

35 def __init__(self, pin, dongle): 

36 super().__init__() 

37 self.hsm2dongle = dongle 

38 self.pin = pin 

39 self.protocol_v2 = HSM2ProtocolLedger(pin, dongle) 

40 

41 # Delegate initialization to the v2 protocol 

42 def initialize_device(self): 

43 return self.protocol_v2.initialize_device() 

44 

45 def _get_pubkey(self, request): 

46 try: 

47 self.protocol_v2.ensure_connection() 

48 return ( 

49 self.ERROR_CODE_OK, 

50 {"pubKey": self.hsm2dongle.get_public_key(request["keyId"])}, 

51 ) 

52 except HSM2DongleErrorResult: 

53 return (self.ERROR_CODE_INVALID_KEYID,) 

54 except HSM2DongleTimeoutError: 

55 self.logger.error("Dongle timeout getting public key") 

56 return (self.ERROR_CODE_DEVICE,) 

57 except HSM2DongleCommError: 

58 # Signal a communication problem and return a device error 

59 self.protocol_v2.report_comm_issue() 

60 self.logger.error("Dongle communication error getting public key") 

61 return (self.ERROR_CODE_DEVICE,) 

62 except HSM2DongleError as e: 

63 return self._error("Dongle error in get_pubkey: %s" % str(e)) 

64 

65 def _sign(self, request): 

66 try: 

67 self.protocol_v2.ensure_connection() 

68 sign_result = self.hsm2dongle.sign_unauthorized( 

69 key_id=request["keyId"], hash=request["message"] 

70 ) 

71 except HSM2DongleTimeoutError: 

72 self.logger.error("Dongle timeout signing") 

73 return (self.ERROR_CODE_DEVICE,) 

74 except HSM2DongleCommError: 

75 # Signal a communication problem and return a device error 

76 self.protocol_v2.report_comm_issue() 

77 self.logger.error("Dongle communication error signing") 

78 return (self.ERROR_CODE_DEVICE,) 

79 except HSM2DongleError as e: 

80 self._error("Dongle error in sign: %s" % str(e)) 

81 

82 if not sign_result[0]: 

83 return (self._translate_sign_error(sign_result[1]),) 

84 signature = sign_result[1] 

85 

86 return (self.ERROR_CODE_OK, {"signature": {"r": signature.r, "s": signature.s}}) 

87 

88 def _translate_sign_error(self, error_code): 

89 return ( 

90 { 

91 HSM2Dongle.RESPONSE.SIGN.ERROR_PATH: self.ERROR_CODE_INVALID_KEYID, 

92 HSM2Dongle.RESPONSE.SIGN.ERROR_HASH: self.ERROR_CODE_INVALID_MESSAGE, 

93 HSM2Dongle.RESPONSE.SIGN.ERROR_UNEXPECTED: self.ERROR_CODE_DEVICE, 

94 } 

95 ).get(error_code, self.ERROR_CODE_UNKNOWN) 

96 

97 def _error(self, msg): 

98 self.logger.error(msg) 

99 raise HSM2ProtocolError(msg)