Skip to content

Commit 824d6c2

Browse files
authored
Merge pull request #142 from LedgerHQ/mru-fix-aes-init
AES init with an IV
2 parents c3609d5 + b908bc3 commit 824d6c2

File tree

2 files changed

+57
-55
lines changed

2 files changed

+57
-55
lines changed

.git-blame-ignore-revs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
# git config blame.ignoreRevsFile .git-blame-ignore-revs
33

44
# Formatting commit
5-
3d2c9960d987b6ff0be180cadc9f9a895ee70f37
5+
10e7047631b5807a951676eab6ede37200011283
6+
8a8b4c89769dcd2ee4c890c14518759aa4e62394

ledgerblue/hexLoader.py

Lines changed: 55 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,15 @@
1717
********************************************************************************
1818
"""
1919

20-
from Cryptodome.Cipher import AES
21-
import sys
22-
import struct
23-
import hashlib
2420
import binascii
25-
from .ecWrapper import PrivateKey
26-
from ecpy.curves import Curve
21+
import hashlib
2722
import os
23+
import struct
24+
25+
from Cryptodome.Cipher import AES
26+
from ecpy.curves import Curve
27+
28+
from .ecWrapper import PrivateKey
2829

2930
LOAD_SEGMENT_CHUNK_HEADER_LENGTH = 3
3031
MIN_PADDING_LENGTH = 1
@@ -43,33 +44,33 @@ def string_to_bytes(x):
4344

4445

4546
def encodelv(v):
46-
l = len(v)
47+
L = len(v)
4748
s = b""
48-
if l < 128:
49-
s += struct.pack(">B", l)
50-
elif l < 256:
49+
if L < 128:
50+
s += struct.pack(">B", L)
51+
elif L < 256:
5152
s += struct.pack(">B", 0x81)
52-
s += struct.pack(">B", l)
53-
elif l < 65536:
53+
s += struct.pack(">B", L)
54+
elif L < 65536:
5455
s += struct.pack(">B", 0x82)
55-
s += struct.pack(">H", l)
56+
s += struct.pack(">H", L)
5657
else:
5758
raise Exception("Unimplemented LV encoding")
5859
s += v
5960
return s
6061

6162

6263
def encodetlv(t, v):
63-
l = len(v)
64+
L = len(v)
6465
s = struct.pack(">B", t)
65-
if l < 128:
66-
s += struct.pack(">B", l)
67-
elif l < 256:
66+
if L < 128:
67+
s += struct.pack(">B", L)
68+
elif L < 256:
6869
s += struct.pack(">B", 0x81)
69-
s += struct.pack(">B", l)
70-
elif l < 65536:
70+
s += struct.pack(">B", L)
71+
elif L < 65536:
7172
s += struct.pack(">B", 0x82)
72-
s += struct.pack(">H", l)
73+
s += struct.pack(">H", L)
7374
else:
7475
raise Exception("Unimplemented TLV encoding")
7576
s += v
@@ -89,10 +90,11 @@ class HexLoader:
8990
def scp_derive_key(self, ecdh_secret, keyindex):
9091
if self.scpv3:
9192
mac_block = b"\x01" * 16
92-
cipher = AES.new(ecdh_secret, AES.MODE_ECB)
93+
iv = b"\x00" * 16
94+
cipher = AES.new(ecdh_secret, AES.MODE_CBC, iv=iv)
9395
mac_key = cipher.encrypt(mac_block)
9496
enc_block = b"\x02" * 16
95-
cipher = AES.new(ecdh_secret, AES.MODE_ECB)
97+
cipher = AES.new(ecdh_secret, AES.MODE_CBC, iv=iv)
9698
enc_key = cipher.encrypt(enc_block)
9799
return mac_key + enc_key
98100
retry = 0
@@ -137,7 +139,7 @@ def __init__(
137139

138140
# legacy unsecure SCP (pre nanos-1.4, pre blue-2.1)
139141
self.max_mtu = 0xFE
140-
if not self.card is None:
142+
if self.card is not None:
141143
self.max_mtu = min(self.max_mtu, self.card.apduMaxDataSize())
142144
self.scpVersion = 2
143145
self.key = mutauth_result
@@ -146,22 +148,22 @@ def __init__(
146148

147149
# store the aligned block len to be transported if requested
148150
self.cleardata_block_len = cleardata_block_len
149-
if not (self.cleardata_block_len is None):
150-
if not self.card is None:
151+
if self.cleardata_block_len is not None:
152+
if self.card is not None:
151153
self.cleardata_block_len = min(
152154
self.cleardata_block_len, self.card.apduMaxDataSize()
153155
)
154156

155-
if scpv3 == True:
157+
if scpv3:
156158
self.scp_enc_key = self.scp_derive_key(mutauth_result, 0)
157159
self.scpVersion = 3
158160
self.max_mtu = 0xFE
159-
if not self.card is None:
161+
if self.card is not None:
160162
self.max_mtu = min(self.max_mtu, self.card.apduMaxDataSize() & 0xF0)
161163
return
162164

163165
# try:
164-
if type(mutauth_result) is dict and "ecdh_secret" in mutauth_result:
166+
if isinstance(mutauth_result, dict) and "ecdh_secret" in mutauth_result:
165167
self.scp_enc_key = self.scp_derive_key(mutauth_result["ecdh_secret"], 0)[
166168
0:16
167169
]
@@ -172,7 +174,7 @@ def __init__(
172174
self.scp_mac_iv = b"\x00" * 16
173175
self.scpVersion = 3
174176
self.max_mtu = 0xFE
175-
if not self.card is None:
177+
if self.card is not None:
176178
self.max_mtu = min(self.max_mtu, self.card.apduMaxDataSize() & 0xF0)
177179

178180
def crc16(self, data):
@@ -445,7 +447,7 @@ def exchange(self, cla, ins, p1, p2, data):
445447
# wrap
446448
data = self.scpWrap(data)
447449
apdu = bytearray([cla, ins, p1, p2, len(data)]) + bytearray(data)
448-
if self.card == None:
450+
if self.card is None:
449451
print("%s" % binascii.hexlify(apdu))
450452
else:
451453
# unwrap after exchanged
@@ -454,7 +456,7 @@ def exchange(self, cla, ins, p1, p2, data):
454456
def scpWrap(self, data):
455457
if not self.secure or data is None or len(data) == 0:
456458
return data
457-
if self.scpv3 == True:
459+
if self.scpv3:
458460
cipher = AES.new(self.scp_enc_key, mode=AES.MODE_SIV)
459461
ciphertext, tag = cipher.encrypt_and_digest(data)
460462
encryptedData = tag + ciphertext
@@ -499,7 +501,7 @@ def scpWrap(self, data):
499501
def scpUnwrap(self, data):
500502
if not self.secure or data is None or len(data) == 0 or len(data) == 2:
501503
return data
502-
if self.scpv3 == True:
504+
if self.scpv3:
503505
cipher = AES.new(self.scp_enc_key, mode=AES.MODE_SIV)
504506
tag = data[:16]
505507
decryptedData = cipher.decrypt_and_verify(data[16:], tag)
@@ -525,12 +527,12 @@ def scpUnwrap(self, data):
525527
cipher = AES.new(self.scp_enc_key, AES.MODE_CBC, self.scp_enc_iv)
526528
self.scp_enc_iv = bytes(data[-16:])
527529
data = cipher.decrypt(bytes(data))
528-
l = len(data) - 1
529-
while data[l] != padding_char:
530-
l -= 1
531-
if l == -1:
530+
L = len(data) - 1
531+
while data[L] != padding_char:
532+
L -= 1
533+
if L == -1:
532534
raise BaseException("Invalid SCP ENC padding")
533-
data = data[0:l]
535+
data = data[0:L]
534536
decryptedData = data
535537

536538
if SCP_DEBUG:
@@ -540,12 +542,12 @@ def scpUnwrap(self, data):
540542
decryptedData = cipher.decrypt(data)
541543
if SCP_DEBUG:
542544
print("unwrap_old: " + binascii.hexlify(decryptedData))
543-
l = len(decryptedData) - 1
544-
while decryptedData[l] != padding_char:
545-
l -= 1
546-
if l == -1:
545+
L = len(decryptedData) - 1
546+
while decryptedData[L] != padding_char:
547+
L -= 1
548+
if L == -1:
547549
raise BaseException("Invalid SCP ENC padding")
548-
decryptedData = decryptedData[0:l]
550+
decryptedData = decryptedData[0:L]
549551
self.iv = data[-16:]
550552

551553
# print ("<<")
@@ -580,13 +582,13 @@ def boot(self, bootadr, signature=None):
580582
# Force jump into Thumb mode
581583
bootadr |= 1
582584
data = b"\x09" + struct.pack(">I", bootadr)
583-
if signature != None:
585+
if signature is not None:
584586
data += struct.pack(">B", len(signature)) + signature
585587
self.exchange(self.cla, 0x00, 0x00, 0x00, data)
586588

587589
def commit(self, signature=None):
588590
data = b"\x09"
589-
if signature != None:
591+
if signature is not None:
590592
data += struct.pack(">B", len(signature)) + signature
591593
self.exchange(self.cla, 0x00, 0x00, 0x00, data)
592594

@@ -609,20 +611,20 @@ def createAppNoInstallParams(
609611
+ appname
610612
)
611613
if iconOffset is None:
612-
if not (icon is None):
614+
if icon is not None:
613615
data += struct.pack(">B", len(icon)) + icon
614616
else:
615617
data += b"\x00"
616618

617-
if not (path is None):
619+
if path is not None:
618620
data += struct.pack(">B", len(path)) + path
619621
else:
620622
data += b"\x00"
621623

622-
if not iconOffset is None:
624+
if iconOffset is not None:
623625
data += struct.pack(">I", iconOffset) + struct.pack(">H", iconSize)
624626

625-
if not appversion is None:
627+
if appversion is not None:
626628
data += struct.pack(">B", len(appversion)) + appversion
627629

628630
# in previous version, appparams are not part of the application hash yet
@@ -681,11 +683,10 @@ def createPack(self, language, code_length):
681683

682684
def loadPackSegmentChunk(self, offset, chunk):
683685
data = struct.pack(">I", offset) + chunk
684-
# print(f"Inside loadPackSegmentChunk, offset={offset}, len(chunk)={len(chunk)}")
685686
self.exchange(self.cla, 0x31, self.language, 0x00, data)
686687

687688
def commitPack(self, signature=None):
688-
if signature != None:
689+
if signature is not None:
689690
data = struct.pack(">B", len(signature)) + signature
690691
else:
691692
data = b""
@@ -884,8 +885,8 @@ def load(
884885
initialAddress = hexFile.minAddr()
885886
sha256 = hashlib.new("sha256")
886887
# stat by hashing the create app params to ensure complete app signature
887-
if targetId != None and (targetId & 0xF) > 3:
888-
if targetVersion == None:
888+
if targetId is not None and (targetId & 0xF) > 3:
889+
if targetVersion is None:
889890
print("Target version is not set, application hash will not match!")
890891
targetVersion = ""
891892
# encore targetId U4LE, and version string bytes
@@ -934,7 +935,7 @@ def load(
934935
if self.cleardata_block_len and chunkLen % self.cleardata_block_len:
935936
if chunkLen < self.cleardata_block_len:
936937
raise Exception(
937-
"Cannot transport not block aligned data with fixed block len"
938+
"Cannot transport data that is not block-aligned"
938939
)
939940
chunkLen -= chunkLen % self.cleardata_block_len
940941
# pad with 00's when not complete block and performing NENC
@@ -1009,7 +1010,7 @@ def recoverDeleteCA(self, name, key):
10091010
self.exchange(self.cla, 0x00, 0x00, 0x00, data)
10101011

10111012
def recoverValidateCertificate(self, version, role, name, key, sign, last=False):
1012-
if last == True:
1013+
if last:
10131014
p1 = b"\x80"
10141015
else:
10151016
p1 = b"\x00"

0 commit comments

Comments
 (0)