Coverage for ledger/hsm2dongle_cmds/powhsm_attestation.py: 100%
33 statements
« prev ^ index » next coverage.py v7.5.3, created at 2025-07-10 13:43 +0000
« 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.
23from enum import IntEnum
24from .command import HSM2DongleCommand
27class Op(IntEnum):
28 OP_GET = 0x01
29 OP_GET_MESSAGE = 0x02
30 OP_APP_HASH = 0x03
31 OP_GET_ENVELOPE = 0x04
34LEGACY_HEADER = b"HSM:SIGNER:"
37# Implements the powhsm attestation protocol against a
38# running powhsm
39class PowHsmAttestation(HSM2DongleCommand):
40 Command = 0x50
42 def run(self, ud_value_hex):
43 # Retrieve attestation signature
44 signature = self.send(Op.OP_GET,
45 bytes.fromhex(ud_value_hex))[self.Offset.DATA:]
47 # Retrieve message and envelope
48 bufs = {}
49 brk = False
50 msgoffset = 1 # For legacy behavior handling
51 for (op, name) in \
52 [(Op.OP_GET_MESSAGE, "message"), (Op.OP_GET_ENVELOPE, "envelope")]:
53 # Legacy behavior handling
54 if brk:
55 bufs["envelope"] = bufs["message"]
56 break
57 bufs[name] = b''
58 more = True
59 page = 0
60 while more:
61 result = self.send(op, bytes([page]))
62 more = result[self.Offset.DATA] == 1
63 # Legacy behavior handling
64 if name == "message" and \
65 result[self.Offset.DATA:self.Offset.DATA+len(LEGACY_HEADER)] == \
66 LEGACY_HEADER:
67 msgoffset = 0
68 more = False
69 brk = True
70 bufs[name] += result[self.Offset.DATA+msgoffset:]
71 page += 1
73 # Get signer hash
74 signer_hash = self.send(Op.OP_APP_HASH)[self.Offset.DATA:]
76 return {
77 "app_hash": signer_hash.hex(),
78 "envelope": bufs["envelope"].hex(),
79 "message": bufs["message"].hex(),
80 "signature": signature.hex(),
81 }