Merge pull request #4 from cslashm/py3
Python 3 port with keeping Python 2 compliance
This commit is contained in:
commit
cf74f4836c
|
@ -57,7 +57,7 @@ class BLEDongle(Dongle):
|
|||
|
||||
def exchange(self, apdu, timeout=20000):
|
||||
if self.debug:
|
||||
print "=> %s" % hexlify(apdu)
|
||||
print("=> %s" % hexlify(apdu))
|
||||
apdu = wrapCommandAPDU(0, apdu, DEFAULT_BLE_CHUNK, True)
|
||||
offset = 0
|
||||
while(offset < len(apdu)):
|
||||
|
@ -78,7 +78,7 @@ class BLEDongle(Dongle):
|
|||
sw = (result[swOffset] << 8) + result[swOffset + 1]
|
||||
response = result[dataStart : dataLength + dataStart]
|
||||
if self.debug:
|
||||
print "<= %s%.2x" % (hexlify(response), sw)
|
||||
print("<= %s%.2x" % (hexlify(response), sw))
|
||||
if sw <> 0x9000:
|
||||
raise CommException("Invalid status %04x" % sw, sw)
|
||||
return response
|
||||
|
|
|
@ -23,6 +23,7 @@ from .ledgerWrapper import wrapCommandAPDU, unwrapResponseAPDU
|
|||
from binascii import hexlify
|
||||
import hid
|
||||
import time
|
||||
import sys
|
||||
|
||||
try:
|
||||
from smartcard.Exceptions import NoCardException
|
||||
|
@ -32,6 +33,14 @@ try:
|
|||
except ImportError:
|
||||
SCARD = False
|
||||
|
||||
|
||||
def hexstr(bstr):
|
||||
if (sys.version_info.major == 3):
|
||||
return hexlify(bstr).decode()
|
||||
if (sys.version_info.major == 2):
|
||||
return hexlify(bstr)
|
||||
return "<undecoded APDU<"
|
||||
|
||||
class DongleWait(object):
|
||||
__metaclass__ = ABCMeta
|
||||
|
||||
|
@ -64,15 +73,15 @@ class HIDDongleHIDAPI(Dongle, DongleWait):
|
|||
|
||||
def exchange(self, apdu, timeout=20):
|
||||
if self.debug:
|
||||
print "=> %s" % hexlify(apdu)
|
||||
print("=> %s" % hexstr(apdu))
|
||||
if self.ledger:
|
||||
apdu = wrapCommandAPDU(0x0101, apdu, 64)
|
||||
padSize = len(apdu) % 64
|
||||
tmp = apdu
|
||||
if padSize <> 0:
|
||||
if padSize != 0:
|
||||
tmp.extend([0] * (64 - padSize))
|
||||
offset = 0
|
||||
while(offset <> len(tmp)):
|
||||
while(offset != len(tmp)):
|
||||
data = tmp[offset:offset + 64]
|
||||
data = bytearray([0]) + data
|
||||
self.device.write(data)
|
||||
|
@ -114,8 +123,8 @@ class HIDDongleHIDAPI(Dongle, DongleWait):
|
|||
sw = (result[swOffset] << 8) + result[swOffset + 1]
|
||||
response = result[dataStart : dataLength + dataStart]
|
||||
if self.debug:
|
||||
print "<= %s%.2x" % (hexlify(response), sw)
|
||||
if sw <> 0x9000:
|
||||
print("<= %s%.2x" % (hexstr(response), sw))
|
||||
if sw != 0x9000:
|
||||
raise CommException("Invalid status %04x" % sw, sw)
|
||||
return response
|
||||
|
||||
|
@ -148,12 +157,12 @@ class DongleSmartcard(Dongle):
|
|||
|
||||
def exchange(self, apdu, timeout=20):
|
||||
if self.debug:
|
||||
print "=> %s" % hexlify(apdu)
|
||||
print("=> %s" % hexstr(apdu))
|
||||
response, sw1, sw2 = self.device.transmit(toBytes(hexlify(apdu)))
|
||||
sw = (sw1 << 8) | sw2
|
||||
if self.debug:
|
||||
print "<= %s%.2x" % (toHexString(response).replace(" ", ""), sw)
|
||||
if sw <> 0x9000:
|
||||
print("<= %s%.2x" % (hexstr(response).replace(" ", ""), sw))
|
||||
if sw != 0x9000:
|
||||
raise CommException("Invalid status %04x" % sw, sw)
|
||||
return bytearray(response)
|
||||
|
||||
|
@ -183,7 +192,7 @@ def getDongle(debug=False, selectCommand=None):
|
|||
try:
|
||||
connection = reader.createConnection()
|
||||
connection.connect()
|
||||
if selectCommand <> None:
|
||||
if selectCommand != None:
|
||||
response, sw1, sw2 = connection.transmit(toBytes("00A4040010FF4C4547522E57414C5430312E493031"))
|
||||
sw = (sw1 << 8) | sw2
|
||||
if sw == 0x9000:
|
||||
|
|
|
@ -22,6 +22,8 @@ from .comm import getDongle
|
|||
from .deployed import getDeployedSecretV1, getDeployedSecretV2
|
||||
from .hexLoader import HexLoader
|
||||
import argparse
|
||||
import binascii
|
||||
import sys
|
||||
|
||||
def auto_int(x):
|
||||
return int(x, 0)
|
||||
|
@ -37,13 +39,19 @@ args = parser.parse_args()
|
|||
|
||||
if args.appName == None:
|
||||
raise Exception("Missing appName")
|
||||
|
||||
if (sys.version_info.major == 3):
|
||||
args.appName = bytes(args.appName,'ascii')
|
||||
if (sys.version_info.major == 2):
|
||||
args.appName = bytes(args.appName)
|
||||
|
||||
if args.targetId == None:
|
||||
args.targetId = 0x31000002
|
||||
if args.rootPrivateKey == None:
|
||||
privateKey = PrivateKey()
|
||||
publicKey = str(privateKey.pubkey.serialize(compressed=False)).encode('hex')
|
||||
print "Generated random root public key : " + publicKey
|
||||
args.rootPrivateKey = privateKey.serialize().encode('ascii')
|
||||
publicKey = binascii.hexlify(privateKey.pubkey.serialize(compressed=False))
|
||||
print("Generated random root public key : %s" % publicKey)
|
||||
args.rootPrivateKey = privateKey.serialize()
|
||||
|
||||
dongle = getDongle(args.apdu)
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import sys
|
|||
import struct
|
||||
from .hexParser import IntelHexParser
|
||||
from .hexLoader import HexLoader
|
||||
import binascii
|
||||
|
||||
def getDeployedSecretV1(dongle, masterPrivate, targetid):
|
||||
testMaster = PrivateKey(bytes(masterPrivate))
|
||||
|
@ -38,13 +39,13 @@ def getDeployedSecretV1(dongle, masterPrivate, targetid):
|
|||
cardKey = batch_info[5:5 + batch_info[4]]
|
||||
|
||||
# if not found, get another pair
|
||||
#if cardKey <> testMasterPublic:
|
||||
#if cardKey != testMasterPublic:
|
||||
# raise Exception("Invalid batch public key")
|
||||
|
||||
# provide the ephemeral certificate
|
||||
ephemeralPrivate = PrivateKey()
|
||||
ephemeralPublic = bytearray(ephemeralPrivate.pubkey.serialize(compressed=False))
|
||||
print "Using ephemeral key " + str(ephemeralPublic).encode('hex')
|
||||
print("Using ephemeral key %s" %binascii.hexlify(ephemeralPublic))
|
||||
signature = testMaster.ecdsa_sign(bytes(ephemeralPublic))
|
||||
signature = testMaster.ecdsa_serialize(signature)
|
||||
certificate = bytearray([len(ephemeralPublic)]) + ephemeralPublic + bytearray([len(signature)]) + signature
|
||||
|
@ -63,7 +64,7 @@ def getDeployedSecretV1(dongle, masterPrivate, targetid):
|
|||
if not last_pub_key.ecdsa_verify(bytes(certificatePublic), certificateSignature):
|
||||
if index == 0:
|
||||
# Not an error if loading from user key
|
||||
print "Broken certificate chain - loading from user key"
|
||||
print("Broken certificate chain - loading from user key")
|
||||
else:
|
||||
raise Exception("Broken certificate chain")
|
||||
last_pub_key = PublicKey(bytes(certificatePublic), raw=True)
|
||||
|
@ -72,7 +73,7 @@ def getDeployedSecretV1(dongle, masterPrivate, targetid):
|
|||
# Commit device ECDH channel
|
||||
dongle.exchange(bytearray.fromhex('E053000000'))
|
||||
secret = last_pub_key.ecdh(bytes(ephemeralPrivate.serialize().decode('hex')))
|
||||
return str(secret[0:16])
|
||||
return secret[0:16]
|
||||
|
||||
def getDeployedSecretV2(dongle, masterPrivate, targetid):
|
||||
testMaster = PrivateKey(bytes(masterPrivate))
|
||||
|
@ -91,10 +92,10 @@ def getDeployedSecretV2(dongle, masterPrivate, targetid):
|
|||
deviceNonce = auth_info[4:12]
|
||||
|
||||
# if not found, get another pair
|
||||
#if cardKey <> testMasterPublic:
|
||||
#if cardKey != testMasterPublic:
|
||||
# raise Exception("Invalid batch public key")
|
||||
|
||||
print "Using test master key " + str(testMasterPublic).encode('hex')
|
||||
print("Using test master key %s " % binascii.hexlify(testMasterPublic))
|
||||
dataToSign = bytes(bytearray([0x01]) + testMasterPublic)
|
||||
signature = testMaster.ecdsa_sign(bytes(dataToSign))
|
||||
signature = testMaster.ecdsa_serialize(signature)
|
||||
|
@ -105,7 +106,7 @@ def getDeployedSecretV2(dongle, masterPrivate, targetid):
|
|||
# provide the ephemeral certificate
|
||||
ephemeralPrivate = PrivateKey()
|
||||
ephemeralPublic = bytearray(ephemeralPrivate.pubkey.serialize(compressed=False))
|
||||
print "Using ephemeral key " + str(ephemeralPublic).encode('hex')
|
||||
print("Using ephemeral key %s" %binascii.hexlify(ephemeralPublic))
|
||||
dataToSign = bytes(bytearray([0x11]) + nonce + deviceNonce + ephemeralPublic)
|
||||
signature = testMaster.ecdsa_sign(bytes(dataToSign))
|
||||
signature = testMaster.ecdsa_serialize(signature)
|
||||
|
@ -122,10 +123,10 @@ def getDeployedSecretV2(dongle, masterPrivate, targetid):
|
|||
elif index == 1:
|
||||
certificate = bytearray(dongle.exchange(bytearray.fromhex('E052800000')))
|
||||
else:
|
||||
break
|
||||
break
|
||||
if len(certificate) == 0:
|
||||
break
|
||||
offset = 1
|
||||
offset = 1
|
||||
certificateHeader = certificate[offset : offset + certificate[offset-1]]
|
||||
offset += certificate[offset-1] + 1
|
||||
certificatePublicKey = certificate[offset : offset + certificate[offset-1]]
|
||||
|
@ -142,7 +143,7 @@ def getDeployedSecretV2(dongle, masterPrivate, targetid):
|
|||
if not last_pub_key.ecdsa_verify(bytes(certificateSignedData), certificateSignature):
|
||||
if index == 0:
|
||||
# Not an error if loading from user key
|
||||
print "Broken certificate chain - loading from user key"
|
||||
print("Broken certificate chain - loading from user key")
|
||||
else:
|
||||
raise Exception("Broken certificate chain")
|
||||
last_pub_key = PublicKey(bytes(certificatePublicKey), raw=True)
|
||||
|
@ -150,5 +151,5 @@ def getDeployedSecretV2(dongle, masterPrivate, targetid):
|
|||
|
||||
# Commit device ECDH channel
|
||||
dongle.exchange(bytearray.fromhex('E053000000'))
|
||||
secret = last_pub_key.ecdh(bytes(ephemeralPrivate.serialize().decode('hex')))
|
||||
return str(secret[0:16])
|
||||
secret = last_pub_key.ecdh(binascii.unhexlify(ephemeralPrivate.serialize()))
|
||||
return secret[0:16]
|
||||
|
|
|
@ -58,23 +58,23 @@ class PublicKey(object):
|
|||
return self.obj.serialize(compressed)
|
||||
else:
|
||||
if not compressed:
|
||||
out = "\x04"
|
||||
out += str(bytearray(self.obj.W.x.to_bytes(32, 'big')))
|
||||
out += str(bytearray(self.obj.W.y.to_bytes(32, 'big')))
|
||||
out = b"\x04"
|
||||
out += self.obj.W.x.to_bytes(32, 'big')
|
||||
out += self.obj.W.y.to_bytes(32, 'big')
|
||||
else:
|
||||
out = "\x03" if ((self.obj.W.y & 1) <> 0) else "\x02"
|
||||
out += str(bytearray(self.obj.W.x.to_bytes(32, 'big')))
|
||||
out = b"\x03" if ((self.obj.W.y & 1) != 0) else "\x02"
|
||||
out += self.obj.W.x.to_bytes(32, 'big')
|
||||
return out
|
||||
|
||||
def ecdh(self, scalar):
|
||||
if USE_SECP:
|
||||
return self.obj.ecdh(scalar)
|
||||
else:
|
||||
scalar = int.from_bytes(scalar)
|
||||
scalar = int.from_bytes(scalar, 'big')
|
||||
point = self.obj.W * scalar
|
||||
# libsecp256k1 style secret
|
||||
out = "\x03" if ((point.y & 1) <> 0) else "\x02"
|
||||
out += str(bytearray(point.x.to_bytes(32, 'big')))
|
||||
out = b"\x03" if ((point.y & 1) != 0) else b"\x02"
|
||||
out += point.x.to_bytes(32, 'big')
|
||||
hash = hashlib.sha256()
|
||||
hash.update(out)
|
||||
return hash.digest()
|
||||
|
@ -104,19 +104,19 @@ class PrivateKey(object):
|
|||
if privkey == None:
|
||||
privkey = ecpy.ecrand.rnd(CURVE_SECP256K1.order)
|
||||
else:
|
||||
privkey = int.from_bytes(privkey)
|
||||
privkey = int.from_bytes(privkey,'big')
|
||||
self.obj = ECPrivateKey(privkey, CURVE_SECP256K1)
|
||||
pubkey = self.obj.get_public_key().W
|
||||
out = "\x04"
|
||||
out += str(bytearray(pubkey.x.to_bytes(32, 'big')))
|
||||
out += str(bytearray(pubkey.y.to_bytes(32, 'big')))
|
||||
out = b"\x04"
|
||||
out += pubkey.x.to_bytes(32, 'big')
|
||||
out += pubkey.y.to_bytes(32, 'big')
|
||||
self.pubkey = PublicKey(out, raw=True)
|
||||
|
||||
def serialize(self):
|
||||
if USE_SECP:
|
||||
return self.obj.serialize()
|
||||
else:
|
||||
return str(bytearray(self.obj.d.to_bytes(32, 'big'))).encode('hex')
|
||||
return "%.64x"%self.obj.d
|
||||
|
||||
def ecdsa_serialize(self, raw_sig):
|
||||
if USE_SECP:
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
from Crypto.Cipher import AES
|
||||
import struct
|
||||
import hashlib
|
||||
import binascii
|
||||
|
||||
class HexLoader:
|
||||
def __init__(self, card, cla=0xF0, secure=False, key=None, relative=True):
|
||||
|
@ -27,9 +28,11 @@ class HexLoader:
|
|||
self.cla = cla
|
||||
self.secure = secure
|
||||
self.key = key
|
||||
self.iv = "\x00" * 16
|
||||
self.iv = b"\x00" * 16
|
||||
self.relative = relative
|
||||
|
||||
|
||||
|
||||
def crc16(self, data):
|
||||
TABLE_CRC16_CCITT = [
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
|
||||
|
@ -73,40 +76,40 @@ class HexLoader:
|
|||
return crc
|
||||
|
||||
def exchange(self, cla, ins, p1, p2, data):
|
||||
apdu = bytearray(chr(cla) + chr(ins) + chr(p1) + chr(p2) + chr(len(data))) + bytearray(data)
|
||||
apdu = bytearray([cla, ins, p1, p2, len(data)]) + bytearray(data)
|
||||
if self.card == None:
|
||||
print str(apdu).encode('hex')
|
||||
print("%s" % binascii.hexlify(apdu))
|
||||
else:
|
||||
self.card.exchange(apdu)
|
||||
|
||||
def encryptAES(self, data):
|
||||
if not self.secure:
|
||||
return data
|
||||
paddedData = data + '\x80'
|
||||
while (len(paddedData) % 16) <> 0:
|
||||
paddedData += '\x00'
|
||||
paddedData = data + b'\x80'
|
||||
while (len(paddedData) % 16) != 0:
|
||||
paddedData += b'\x00'
|
||||
cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
|
||||
encryptedData = cipher.encrypt(str(paddedData))
|
||||
encryptedData = cipher.encrypt(paddedData)
|
||||
self.iv = encryptedData[len(encryptedData) - 16:]
|
||||
return encryptedData
|
||||
|
||||
def selectSegment(self, baseAddress):
|
||||
data = '\x05' + struct.pack('>I', baseAddress)
|
||||
data = b'\x05' + struct.pack('>I', baseAddress)
|
||||
data = self.encryptAES(data)
|
||||
self.exchange(self.cla, 0x00, 0x00, 0x00, data)
|
||||
|
||||
def loadSegmentChunk(self, offset, chunk):
|
||||
data = '\x06' + struct.pack('>H', offset) + chunk
|
||||
data = b'\x06' + struct.pack('>H', offset) + chunk
|
||||
data = self.encryptAES(data)
|
||||
self.exchange(self.cla, 0x00, 0x00, 0x00, data)
|
||||
|
||||
def flushSegment(self):
|
||||
data = '\x07'
|
||||
data = b'\x07'
|
||||
data = self.encryptAES(data)
|
||||
self.exchange(self.cla, 0x00, 0x00, 0x00, data)
|
||||
|
||||
def crcSegment(self, offsetSegment, lengthSegment, crcExpected):
|
||||
data = '\x08' + struct.pack('>H', offsetSegment) + struct.pack('>I', lengthSegment) + struct.pack('>H', crcExpected)
|
||||
data = b'\x08' + struct.pack('>H', offsetSegment) + struct.pack('>I', lengthSegment) + struct.pack('>H', crcExpected)
|
||||
data = self.encryptAES(data)
|
||||
self.exchange(self.cla, 0x00, 0x00, 0x00, data)
|
||||
|
||||
|
@ -117,29 +120,30 @@ class HexLoader:
|
|||
def boot(self, bootadr, signature=None):
|
||||
# Force jump into Thumb mode
|
||||
bootadr |= 1
|
||||
data = '\x09' + struct.pack('>I', bootadr)
|
||||
data = b'\x09' + struct.pack('>I', bootadr)
|
||||
if (signature != None):
|
||||
data += chr(len(signature)) + signature
|
||||
data = self.encryptAES(data)
|
||||
self.exchange(self.cla, 0x00, 0x00, 0x00, data)
|
||||
|
||||
def createApp(self, appflags, applength, appname, icon=None, path=None):
|
||||
data = '\x0B' + struct.pack('>I', applength) + struct.pack('>I', appflags) + chr(len(appname)) + appname
|
||||
data = b'\x0B' + struct.pack('>I', applength) + struct.pack('>I', appflags) + struct.pack('>B', len(appname)) + appname
|
||||
if (icon != None):
|
||||
data += chr(len(icon)) + icon
|
||||
data += struct.pack('>B', len(icon))+ icon
|
||||
if (path != None):
|
||||
data += chr(len(path)) + path
|
||||
data += struct.pack('>B', len(path)) + path
|
||||
|
||||
data = self.encryptAES(data)
|
||||
self.exchange(self.cla, 0x00, 0x00, 0x00, data)
|
||||
|
||||
def deleteApp(self, appname):
|
||||
data = '\x0C' + chr(len(appname)) + appname
|
||||
data = b'\x0C' + struct.pack('>B',len(appname)) + appname
|
||||
data = self.encryptAES(data)
|
||||
self.exchange(self.cla, 0x00, 0x00, 0x00, data)
|
||||
|
||||
def load(self, erase_u8, max_length_per_apdu, hexAreas, bootaddr):
|
||||
initialAddress = 0
|
||||
if (len(hexAreas) <> 0) and self.relative:
|
||||
if (len(hexAreas) != 0) and self.relative:
|
||||
initialAddress = hexAreas[0].getStart()
|
||||
sha256 = hashlib.new('sha256')
|
||||
for area in hexAreas:
|
||||
|
@ -160,7 +164,7 @@ class HexLoader:
|
|||
chunkLen = length
|
||||
chunk = data[offset : offset + chunkLen]
|
||||
sha256.update(chunk)
|
||||
self.loadSegmentChunk(offset, chunk)
|
||||
self.loadSegmentChunk(offset, bytes(chunk))
|
||||
offset += chunkLen
|
||||
length -= chunkLen
|
||||
self.flushSegment()
|
||||
|
@ -169,7 +173,7 @@ class HexLoader:
|
|||
|
||||
def run(self, hexAreas, bootaddr, signature=None):
|
||||
initialAddress = 0
|
||||
if (len(hexAreas) <> 0) and self.relative:
|
||||
if (len(hexAreas) != 0) and self.relative:
|
||||
initialAddress = hexAreas[0].getStart()
|
||||
self.boot(bootaddr - initialAddress, signature)
|
||||
|
||||
|
|
|
@ -36,16 +36,16 @@ class IntelHexParser:
|
|||
startZone = None
|
||||
startFirst = None
|
||||
current = None
|
||||
zoneData = ""
|
||||
zoneData = b''
|
||||
file = open(fileName, "r")
|
||||
for data in file:
|
||||
lineNumber += 1
|
||||
data = data.rstrip('\r\n')
|
||||
if len(data) == 0:
|
||||
continue
|
||||
if data[0] <> ':':
|
||||
raise Exception("Invalid data at line " + str(lineNumber))
|
||||
data = bytearray(data[1:].decode('hex'))
|
||||
if data[0] != ':':
|
||||
raise Exception("Invalid data at line %d" % lineNumber)
|
||||
data = bytearray.fromhex(data[1:]) #binascii.unhexlify(data[1:])
|
||||
count = data[0]
|
||||
address = (data[1] << 8) + data[2]
|
||||
recordType = data[3]
|
||||
|
@ -55,7 +55,7 @@ class IntelHexParser:
|
|||
if startFirst == None:
|
||||
startFirst = address
|
||||
current = startFirst
|
||||
if address <> current:
|
||||
if address != current:
|
||||
self.areas.append(IntelHexArea((startZone << 16) + startFirst, zoneData))
|
||||
zoneData = ""
|
||||
startFirst = address
|
||||
|
@ -63,7 +63,7 @@ class IntelHexParser:
|
|||
zoneData += data[4:4 + count]
|
||||
current += count
|
||||
if recordType == 0x01:
|
||||
if len(zoneData) <> 0:
|
||||
if len(zoneData) != 0:
|
||||
self.areas.append(IntelHexArea((startZone << 16) + startFirst, zoneData))
|
||||
zoneData = ""
|
||||
startZone = None
|
||||
|
@ -74,7 +74,7 @@ class IntelHexParser:
|
|||
if recordType == 0x03:
|
||||
raise Exception("Unsupported record 03")
|
||||
if recordType == 0x04:
|
||||
if len(zoneData) <> 0:
|
||||
if len(zoneData) != 0:
|
||||
self.areas.append(IntelHexArea((startZone << 16) + startFirst, zoneData))
|
||||
zoneData = ""
|
||||
startZone = None
|
||||
|
|
|
@ -39,7 +39,7 @@ def wrapCommandAPDU(channel, command, packetSize, ble=False):
|
|||
blockSize = len(command)
|
||||
result += command[offset : offset + blockSize]
|
||||
offset = offset + blockSize
|
||||
while offset <> len(command):
|
||||
while offset != len(command):
|
||||
if not ble:
|
||||
result += struct.pack(">H", channel)
|
||||
result += struct.pack(">BH", 0x05, sequenceIdx)
|
||||
|
@ -51,8 +51,8 @@ def wrapCommandAPDU(channel, command, packetSize, ble=False):
|
|||
result += command[offset : offset + blockSize]
|
||||
offset = offset + blockSize
|
||||
if not ble:
|
||||
while (len(result) % packetSize) <> 0:
|
||||
result += "\x00"
|
||||
while (len(result) % packetSize) != 0:
|
||||
result += b"\x00"
|
||||
return bytearray(result)
|
||||
|
||||
def unwrapResponseAPDU(channel, data, packetSize, ble=False):
|
||||
|
@ -65,16 +65,16 @@ def unwrapResponseAPDU(channel, data, packetSize, ble=False):
|
|||
if ((data is None) or (len(data) < 5 + extraHeaderSize + 5)):
|
||||
return None
|
||||
if not ble:
|
||||
if struct.unpack(">H", str(data[offset : offset + 2]))[0] <> channel:
|
||||
if struct.unpack(">H", data[offset : offset + 2])[0] != channel:
|
||||
raise CommException("Invalid channel")
|
||||
offset += 2
|
||||
if data[offset] <> 0x05:
|
||||
if data[offset] != 0x05:
|
||||
raise CommException("Invalid tag")
|
||||
offset += 1
|
||||
if struct.unpack(">H", str(data[offset : offset + 2]))[0] <> sequenceIdx:
|
||||
if struct.unpack(">H", data[offset : offset + 2])[0] != sequenceIdx:
|
||||
raise CommException("Invalid sequence")
|
||||
offset += 2
|
||||
responseLength = struct.unpack(">H", str(data[offset : offset + 2]))[0]
|
||||
responseLength = struct.unpack(">H", data[offset : offset + 2])[0]
|
||||
offset += 2
|
||||
if len(data) < 5 + extraHeaderSize + responseLength:
|
||||
return None
|
||||
|
@ -84,18 +84,18 @@ def unwrapResponseAPDU(channel, data, packetSize, ble=False):
|
|||
blockSize = responseLength
|
||||
result = data[offset : offset + blockSize]
|
||||
offset += blockSize
|
||||
while (len(result) <> responseLength):
|
||||
while (len(result) != responseLength):
|
||||
sequenceIdx = sequenceIdx + 1
|
||||
if (offset == len(data)):
|
||||
return None
|
||||
if not ble:
|
||||
if struct.unpack(">H", str(data[offset : offset + 2]))[0] <> channel:
|
||||
if struct.unpack(">H", data[offset : offset + 2])[0] != channel:
|
||||
raise CommException("Invalid channel")
|
||||
offset += 2
|
||||
if data[offset] <> 0x05:
|
||||
if data[offset] != 0x05:
|
||||
raise CommException("Invalid tag")
|
||||
offset += 1
|
||||
if struct.unpack(">H", str(data[offset : offset + 2]))[0] <> sequenceIdx:
|
||||
if struct.unpack(">H", data[offset : offset + 2])[0] != sequenceIdx:
|
||||
raise CommException("Invalid sequence")
|
||||
offset += 2
|
||||
if (responseLength - len(result)) > packetSize - 3 - extraHeaderSize:
|
||||
|
|
|
@ -24,14 +24,16 @@ from .hexLoader import HexLoader
|
|||
from .deployed import getDeployedSecretV1, getDeployedSecretV2
|
||||
import argparse
|
||||
import struct
|
||||
import binascii
|
||||
import sys
|
||||
|
||||
def auto_int(x):
|
||||
return int(x, 0)
|
||||
|
||||
def parse_bip32_path(path, apilevel):
|
||||
if len(path) == 0:
|
||||
return ""
|
||||
result = ""
|
||||
return b""
|
||||
result = b""
|
||||
elements = path.split('/')
|
||||
if apilevel >= 5:
|
||||
result = result + chr(len(elements))
|
||||
|
@ -72,15 +74,21 @@ if args.appFlags == None:
|
|||
args.appFlags = 0
|
||||
if args.rootPrivateKey == None:
|
||||
privateKey = PrivateKey()
|
||||
publicKey = str(privateKey.pubkey.serialize(compressed=False)).encode('hex')
|
||||
print "Generated random root public key : " + publicKey
|
||||
args.rootPrivateKey = privateKey.serialize().encode('ascii')
|
||||
publicKey = binascii.hexlify(privateKey.pubkey.serialize(compressed=False))
|
||||
print("Generated random root public key : %s" % publicKey)
|
||||
args.rootPrivateKey = privateKey.serialize()
|
||||
|
||||
|
||||
if (sys.version_info.major == 3):
|
||||
args.appName = bytes(args.appName,'ascii')
|
||||
if (sys.version_info.major == 2):
|
||||
args.appName = bytes(args.appName)
|
||||
|
||||
parser = IntelHexParser(args.fileName)
|
||||
if args.bootAddr == None:
|
||||
args.bootAddr = parser.getBootAddr()
|
||||
|
||||
path = ""
|
||||
path = b""
|
||||
curveMask = 0xff
|
||||
if args.curve != None:
|
||||
curveMask = 0x00
|
||||
|
@ -95,17 +103,17 @@ if args.curve != None:
|
|||
raise Exception("Unknown curve " + curve)
|
||||
|
||||
if args.apilevel >= 5:
|
||||
path += chr(curveMask)
|
||||
path += struct.pack('>B',curveMask)
|
||||
if args.path != None:
|
||||
for item in args.path:
|
||||
if len(item) <> 0:
|
||||
if len(item) != 0:
|
||||
path += parse_bip32_path(item, args.apilevel)
|
||||
else:
|
||||
if args.curve != None:
|
||||
print "Curve not supported using this API level, ignoring"
|
||||
print("Curve not supported using this API level, ignoring")
|
||||
if args.path != None:
|
||||
if len(args.path) > 1:
|
||||
print "Multiple path levels not supported using this API level, ignoring"
|
||||
print("Multiple path levels not supported using this API level, ignoring")
|
||||
else:
|
||||
path = parse_bip32_path(args.path[0], args.apilevel)
|
||||
|
||||
|
@ -126,13 +134,14 @@ for area in parser.getAreas():
|
|||
|
||||
icon = None
|
||||
if args.icon != None:
|
||||
icon = bytearray.fromhex(args.icon)
|
||||
icon = bytes(bytearray.fromhex(args.icon))
|
||||
|
||||
signature = None
|
||||
if args.signature != None:
|
||||
signature = bytearray.fromhex(args.signature)
|
||||
signature = bytes(bytearray.fromhex(args.signature))
|
||||
|
||||
|
||||
loader.createApp(args.appFlags, appLength, args.appName, icon, path)
|
||||
hash = loader.load(0x0, 0xE0, parser.getAreas(), args.bootAddr)
|
||||
print "Application hash : " + hash
|
||||
print("Application hash : " + hash)
|
||||
loader.run(parser.getAreas(), args.bootAddr, signature)
|
||||
|
|
|
@ -48,14 +48,14 @@ else:
|
|||
class SCP:
|
||||
def __init__(self, dongle, targetId, rootPrivateKey):
|
||||
self.key = getDeployedSecretV2(dongle, rootPrivateKey, targetId)
|
||||
self.iv = "\x00" * 16;
|
||||
self.iv = b'\x00' * 16;
|
||||
|
||||
def encryptAES(self, data):
|
||||
paddedData = data + '\x80'
|
||||
while (len(paddedData) % 16) <> 0:
|
||||
paddedData += '\x00'
|
||||
paddedData = data + b'\x80'
|
||||
while (len(paddedData) % 16) != 0:
|
||||
paddedData += b'\x00'
|
||||
cipher = AES.new(self.key, AES.MODE_CBC, self.iv)
|
||||
encryptedData = cipher.encrypt(str(paddedData))
|
||||
encryptedData = cipher.encrypt(paddedData)
|
||||
self.iv = encryptedData[len(encryptedData) - 16:]
|
||||
return encryptedData
|
||||
|
||||
|
@ -64,9 +64,9 @@ dongle = getDongle(args.apdu)
|
|||
if args.scp:
|
||||
if args.rootPrivateKey == None:
|
||||
privateKey = PrivateKey()
|
||||
publicKey = str(privateKey.pubkey.serialize(compressed=False)).encode('hex')
|
||||
print "Generated random root public key : " + publicKey
|
||||
args.rootPrivateKey = privateKey.serialize().encode('ascii')
|
||||
publicKey = binascii.hexlify(privateKey.pubkey.serialize(compressed=False))
|
||||
print("Generated random root public key : %s" % publicKey)
|
||||
args.rootPrivateKey = privateKey.serialize()
|
||||
scp = SCP(dongle, args.targetId, bytearray.fromhex(args.rootPrivateKey))
|
||||
|
||||
for data in file:
|
||||
|
|
|
@ -50,11 +50,11 @@ dataToSign = m.digest()
|
|||
|
||||
MASTER_PRIVATE = bytearray.fromhex(args.key)
|
||||
testMaster = PrivateKey(bytes(MASTER_PRIVATE))
|
||||
testMasterPublic = bytearray(testMaster.pubkey.serialize(compressed=False))
|
||||
#testMasterPublic = bytearray(testMaster.pubkey.serialize(compressed=False))
|
||||
|
||||
signature = testMaster.ecdsa_sign(bytes(dataToSign), raw=True)
|
||||
|
||||
# test signature before printing it
|
||||
if testMaster.pubkey.ecdsa_verify(dataToSign, signature, raw=True):
|
||||
#print "Signer's public: " + binascii.hexlify(testMasterPublic)
|
||||
print testMaster.ecdsa_serialize(signature).encode('hex')
|
||||
#print("Signer's public: " + binascii.hexlify(testMasterPublic))
|
||||
print(testMaster.ecdsa_serialize(signature).encode('hex'))
|
||||
|
|
|
@ -56,4 +56,4 @@ signature = publicKey.ecdsa_deserialize(bytes(bytearray.fromhex(args.signature))
|
|||
if not publicKey.ecdsa_verify(bytes(dataToSign), signature, raw=True):
|
||||
raise Exception("Signature not verified")
|
||||
|
||||
print "Signature verified"
|
||||
print("Signature verified")
|
||||
|
|
Loading…
Reference in New Issue