Skip to content
This repository was archived by the owner on Oct 16, 2024. It is now read-only.

Commit 30a5d0b

Browse files
committed
Fix INPUT FINAIZE FULL on current firmware, add support for new firmware message signing calls
1 parent 1a5e2c6 commit 30a5d0b

File tree

1 file changed

+64
-12
lines changed

1 file changed

+64
-12
lines changed

btchip/btchip.py

Lines changed: 64 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,13 @@ def finalizeInputFull(self, outputData):
323323
response = self.dongle.exchange(bytearray(apdu))
324324
encryptedOutputData = encryptedOutputData + response[1 : 1 + response[0]]
325325
offset += dataLength
326-
result['confirmationNeeded'] = response[1 + response[0]] <> 0x00
327-
result['confirmationType'] = response[1 + response[0]]
326+
if len(response) > 1:
327+
result['confirmationNeeded'] = response[1 + response[0]] <> 0x00
328+
result['confirmationType'] = response[1 + response[0]]
329+
else:
330+
# Support for old style API before 1.0.2
331+
result['confirmationNeeded'] = response[0] <> 0x00
332+
result['confirmationType'] = response[0]
328333
if result['confirmationType'] == 0x02:
329334
result['keycardData'] = response[1 + response[0] + 1:] # legacy
330335
if result['confirmationType'] == 0x03:
@@ -358,7 +363,7 @@ def untrustedHashSign(self, path, pin="", lockTime=0, sighashType=0x01):
358363
result[0] = 0x30
359364
return result
360365

361-
def signMessagePrepare(self, path, message):
366+
def signMessagePrepareV1(self, path, message):
362367
donglePath = parse_bip32_path(path)
363368
if self.needKeyCache:
364369
self.resolvePublicKeysInPath(path)
@@ -373,10 +378,57 @@ def signMessagePrepare(self, path, message):
373378
response = self.dongle.exchange(bytearray(apdu))
374379
result['confirmationNeeded'] = response[0] <> 0x00
375380
result['confirmationType'] = response[0]
376-
if result['confirmationType'] == 0x02:
377-
result['keycardData'] = response[1:]
378-
if result['confirmationType'] == 0x03:
379-
result['secureScreenData'] = response[1:]
381+
if result['confirmationType'] == 0x02:
382+
result['keycardData'] = response[1:]
383+
if result['confirmationType'] == 0x03:
384+
result['secureScreenData'] = response[1:]
385+
return result
386+
387+
def signMessagePrepareV2(self, path, message):
388+
donglePath = parse_bip32_path(path)
389+
if self.needKeyCache:
390+
self.resolvePublicKeysInPath(path)
391+
result = {}
392+
offset = 0
393+
encryptedOutputData = ""
394+
while (offset < len(message)):
395+
params = [];
396+
if offset == 0:
397+
params.extend(donglePath)
398+
params.append((len(message) >> 8) & 0xff)
399+
params.append(len(message) & 0xff)
400+
p2 = 0x01
401+
else:
402+
p2 = 0x80
403+
blockLength = 255 - len(params)
404+
if ((offset + blockLength) < len(message)):
405+
dataLength = blockLength
406+
else:
407+
dataLength = len(message) - offset
408+
params.extend(bytearray(message[offset : offset + dataLength]))
409+
apdu = [ self.BTCHIP_CLA, self.BTCHIP_INS_SIGN_MESSAGE, 0x00, p2 ]
410+
apdu.append(len(params))
411+
apdu.extend(params)
412+
response = self.dongle.exchange(bytearray(apdu))
413+
encryptedOutputData = encryptedOutputData + response[1 : 1 + response[0]]
414+
offset += blockLength
415+
result['confirmationNeeded'] = response[1 + response[0]] <> 0x00
416+
result['confirmationType'] = response[1 + response[0]]
417+
if result['confirmationType'] == 0x03:
418+
offset = 1 + response[0] + 1
419+
result['secureScreenData'] = response[offset:]
420+
result['encryptedOutputData'] = encryptedOutputData
421+
422+
return result
423+
424+
def signMessagePrepare(self, path, message):
425+
try:
426+
result = self.signMessagePrepareV2(path, message)
427+
except BTChipException as e:
428+
if (e.sw == 0x6b00): # Old firmware version, try older method
429+
result = self.signMessagePrepareV1(path, message)
430+
else:
431+
raise
380432
return result
381433

382434
def signMessageSign(self, pin=""):
@@ -423,11 +475,11 @@ def setup(self, operationModeFlags, featuresFlag, keyVersion, keyVersionP2SH, us
423475
self.setKeymapEncoding(keymapEncoding)
424476
try:
425477
self.setTypingBehaviour(0xff, 0xff, 0xff, 0x10)
426-
except BTChipException as e:
427-
if (e.sw == 0x6700): # Old firmware version, command not supported
428-
pass
429-
else:
430-
raise
478+
except BTChipException as e:
479+
if (e.sw == 0x6700): # Old firmware version, command not supported
480+
pass
481+
else:
482+
raise
431483
return result
432484

433485
def setKeymapEncoding(self, keymapEncoding):

0 commit comments

Comments
 (0)