def load_key(keyfile): # TODO: better handling of invalid pass-phrase key = keys.load(keyfile) if key is not None: return key passwd = getpass.getpass("Enter key passphrase: ").encode('utf-8') return keys.load(keyfile, passwd)
def do_sign(args): payload = [] with open(args.infile, 'rb') as f: payload = f.read() # Removing the padding because the hashlib pads properly (512 bit alignment) for SHA256 # payload = pad(payload) key = keys.load(args.key) if args.key else None if key.has_sign(): if key.has_nonce(): nonce = [] try: with open(args.nonce, 'rb') as f: nonce = f.read() except: nonce = [] encrytpted, signature, nonce_used = key.encrypt(payload, nonce) if nonce != nonce_used: try: f = open(args.nonce, 'wb') f.write(nonce_used) f.close() except: print("nonce filename required") exit(1) else: signature = key.sign(payload) f = open(args.outfile, "wb") f.write(signature) f.close() else: print("Provided Key is not useable to sign ") exit(1)
def do_inject(args): key = keys.load(args.key) np_key = numpy.frombuffer(key.get_key(args.type), numpy.uint8) # DEBUG______________________________ #print(key.get_key("public")) #l = list() #for ite in range(0, np_key.size): # l.append(np_key[ite]) #print(l) # DEBUG______________________________ with open(args.file, 'r') as f: with open(args.outfile, 'w') as o: for line in f.readlines(): # DEBUG______________________________ #print(line) # DEBUG______________________________ if args.pattern in line: # DEBUG______________________________ #print("Found:{}".format(line)) # DEBUG______________________________ if "CKA_VALUE" in line: value = "{},".format(np_key.size) for ite in range(0, round(np_key.size / 4 + 0.5)): value += " 0x{:02x}{:02x}{:02x}{:02x},".format( np_key[ite * 4], np_key[ite * 4 + 1], np_key[ite * 4 + 2], np_key[ite * 4 + 3]) # DEBUG______________________________ #print("Value:{}".format(value)) # DEBUG______________________________ line = line.replace(args.pattern, value) elif "CKA_EC_POINT" in line: np_key2 = numpy.zeros(np_key.size + 2, numpy.uint8) for ite in range(0, np_key.size): np_key2[ite + 2] = np_key[ite] np_key2[0] = 0x04 np_key2[1] = np_key.size value = "{},".format(np_key2.size) for ite in range(0, round(np_key2.size / 4 + 0.5)): if ite * 4 + 3 < np_key2.size: value += " 0x{:02x}{:02x}{:02x}{:02x}U,".format( np_key2[ite * 4], np_key2[ite * 4 + 1], np_key2[ite * 4 + 2], np_key2[ite * 4 + 3]) elif ite * 4 + 2 < np_key2.size: value += " 0x{:02x}{:02x}{:02x}U,".format( np_key2[ite * 4], np_key2[ite * 4 + 1], np_key2[ite * 4 + 2]) elif ite * 4 + 1 < np_key2.size: value += " 0x{:02x}{:02x}U,".format( np_key2[ite * 4], np_key2[ite * 4 + 1]) else: value += " 0x{:02x}U,".format(np_key2[ite * 4]) # DEBUG______________________________ #print("Value:{}".format(value)) # DEBUG______________________________ line = line.replace(args.pattern, value) # DEBUG______________________________ #print("Altered line:{}".format(line)) # DEBUG______________________________ o.write(line) o.close()
def otp_write_key(infile, index, segment, uart, baudrate): key = bytearray() try: with open(infile, "rb") as f: if segment == 'signature': # read key from ED25519 pem file try: sig = keys.load(infile) except ValueError: raise SystemExit("Invalid PEM file") buf = sig._get_public().public_bytes( encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw) else: # read key from base64 encoded AES key file buf = f.read() try: buf = base64.decodestring(buf) except ValueError: raise SystemExit("Invalid base 64 file") if len(buf) != 32: raise SystemExit("AES key file has incorrect length") key = struct.unpack('IIIIIIII', buf) except IOError: raise SystemExit("Failed to read key from file") seg_map = {'signature': 0, 'data': 1, 'qspi': 2} ser = get_serial_port(uart, baudrate, 1, 8, serial.STOPBITS_ONE) cmd = cmd_write_key(0xaa55aa55, Cmd.OTP_WRITE_KEY, seg_map[segment], index) # swap endianness of data to little endian msg = struct.pack('IIII', *cmd) key_bytes = struct.pack('>IIIIIIII', *key) msg += (key_bytes) msg += struct.pack('H', crc16(key_bytes, 0, 32)) ser.write(msg) data = read_exact(ser, 16) response = cmd_response._make(struct.unpack_from('IIII', data)) validate_response(response) if response.status == 0: print("Key successfully updated") else: raise SystemExit('Error writing key with status %s ' % hex(response.status))
def do_header_lib(args): if (os.path.isfile(args.firmware)): size = os.path.getsize(args.firmware) else: print("no fw file") exit(1) if os.path.isfile(args.tag): f = open(args.tag, 'rb') tag = f.read() key = keys.load(args.key) if args.key else None #empty nonce nonce = b'' protocol = args.protocol magic = args.magic.encode() version = args.version reserved = b'\0' * args.reserved if args.nonce and args.iv: print("either IV or Nonce Required !!!") exit(1) iv_nonce = "" if args.nonce: iv_nonce = args.nonce elif args.iv: iv_nonce = args.iv if iv_nonce: with open(iv_nonce, 'rb') as f: nonce = f.read() header = pack( '<' + str(len(magic)) + 'sH' + str(len(nonce)) + 's' + 'HI' + str(len(tag)) + 's' + str(args.reserved) + 's', magic, protocol, nonce, version, size, tag, reserved) #GCM needs Nonce to sign #AES cannot sign if key.has_sign(): if key.has_nonce() and iv_nonce == "": print("sign key required nonce, provide nonce") exit(1) if key.has_nonce(): if nonce != b'': signature, nonce_used = key.sign(header, nonce) if nonce_used != nonce: print("error nonce used differs") exit(1) else: print("nonce required for this key") exit(1) else: signature = key.sign(header) header += pack(str(len(signature)) + 's', signature) else: print("Provided Key is not useable to sign header") exit(1) return header, signature
def do_trans(args): key = keys.load(args.key) end = False if args.end: end = True if args.assembly=="ARM" or args.assembly=="IAR" or args.assembly=="GNU": if args.version=="V6M" or args.version=="V7M": out = key.trans(args.section, args.function, end, args.assembly, args.version) print (str(out)) else: print ("-v option : Cortex M architecture not supported") exit(1) else: print ("-a option : assembly option not supported") exit(1)
def do_encrypt(args): payload = [] with open(args.infile, 'rb') as f: payload = f.read() f.close() key = keys.load(args.key) if args.key else None if key.has_encrypt(): if key.has_nonce(): nonce = [] if args.nonce and args.iv: print("either IV or Nonce Required for this key!!!") exit(1) if args.nonce: iv_nonce = args.nonce elif args.iv: iv_nonce = args.iv else: print("either IV or Nonce Required for this key!!!") exit(1) if os.path.isfile(iv_nonce): with open(iv_nonce, 'rb') as f: nonce = f.read() if args.poffset: with open(args.poffset, 'r') as f: offset = int(f.read()) # AES CTR : remove 4 LSB bits to the address offset = int(offset / 16) else: offset = 0 if args.address: address = args.address + offset encrypted, signature, nonce_used = key.encrypt( payload, address, nonce) else: encrypted, signature, nonce_used = key.encrypt(payload, nonce) if nonce != nonce_used: f = open(iv_nonce, 'wb') f.write(nonce_used) f.close() else: encrypted, signature = key.encrypt(payload) f = open(args.outfile, "wb") f.write(encrypted) f.close() else: print("Key does not support encrypt") exit(1)
def __init__(self, path, encrypt_file, sig_file, sig_slot, decrypt_slot, revoke, version): header = product_header(self.PROD_ID, 0x2000, 0x2000, 0xa8a500eb, 0x66, self.FLASH_SECT_ID, 3, b'\x01\x40\07') self.img = struct.pack('<2sIIII2sH3s', *header) self.img += struct.pack('<H', crc16(self.img, 0, len(self.img))) self.img += b'\xff' * (4096 * 2 - len(self.img)) self.img_size = os.path.getsize(path) self.aes_key = None self.sig_key = None self.sig_slot = None self.decrypt_slot = None self.revocation_list = revoke if version: self.version = version.encode() else: self.version = b'\x00' * 16 with open(path, "rb") as binary_file: # Read the whole file at once self.data = binary_file.read() if encrypt_file is not None: with open(encrypt_file, "rb") as aes_file: # Read the whole file at once self.aes_key = aes_file.read() self.aes_key = base64.b64decode(self.aes_key) if sig_file is not None: self.sig_key = keys.load(sig_file) if sig_slot is not None: self.sig_slot = sig_slot if decrypt_slot is not None: self.decrypt_slot = decrypt_slot
def do_encrypt(args): payload = [] with open(args.infile, 'rb') as f: payload = f.read() f.close() key = keys.load(args.key) if args.key else None if key.has_encrypt(): if key.has_nonce(): nonce = [] if args.nonce and args.iv: print("either IV or Nonce Required for this key!!!") exit(1) if args.nonce: iv_nonce = args.nonce elif args.iv: iv_nonce = args.iv else: print("either IV or Nonce Required for this key!!!") exit(1) if os.path.isfile(iv_nonce): with open(iv_nonce, 'rb') as f: nonce = f.read() encrypted, signature, nonce_used = key.encrypt(payload, nonce) if nonce != nonce_used: f = open(iv_nonce, 'wb') f.write(nonce_used) f.close() else: encrypted, signature = key.encrypt(payload) f = open(args.outfile, "wb") f.write(encrypted) f.close() else: print("Key does not support encrypt") exit(1)
def do_getpub(args): key = keys.load(args.key) key.emit_c()
def do_header_lib(args): if (os.path.isfile(args.firmware)): size = os.path.getsize(args.firmware) else: print("no fw file") exit(1) if os.path.isfile(args.tag): f = open(args.tag, 'rb') tag = f.read() if args.cert_fw_leaf: if os.path.isfile(args.cert_fw_leaf): print("Loading cert: " + args.cert_fw_leaf) f = open(args.cert_fw_leaf, 'rb') cert_fw_leaf = f.read() if args.cert_fw_inter: if os.path.isfile(args.cert_fw_inter): print("Loading cert: " + args.cert_fw_inter) f = open(args.cert_fw_inter, 'rb') cert_fw_inter = f.read() key = keys.load(args.key) if args.key else None #empty nonce nonce = b'' protocol = args.protocol magic = args.magic.encode() version = args.version reserved = b'\0' * args.reserved if args.nonce and args.iv: print("either IV or Nonce Required !!!") exit(1) iv_nonce = "" if args.nonce: iv_nonce = args.nonce elif args.iv: iv_nonce = args.iv if iv_nonce: with open(iv_nonce, 'rb') as f: nonce = f.read() if args.pfw: pfwsize = os.path.getsize(args.pfw) else: pfwsize = size if args.poffset: with open(args.poffset, 'r') as f: pfwoffset = int(f.read()) else: pfwoffset = 0 if args.ptag: f = open(args.ptag, 'rb') pfwtag = f.read() f.close() else: pfwtag = tag header = pack( '<' + str(len(magic)) + 'sHHIII' + str(len(tag)) + 's' + str(len(pfwtag)) + 's' + str(len(nonce)) + 's' + str(args.reserved) + 's', magic, protocol, version, size, pfwoffset, pfwsize, tag, pfwtag, nonce, reserved) #add certs # Add certificates if args.cert_fw_leaf: print("adding leaf cert of length " + str(str(len(cert_fw_leaf)))) header += pack(str(len(cert_fw_leaf)) + 's', cert_fw_leaf) if args.cert_fw_inter: print("adding intermediate cert of length " + str(str(len(cert_fw_inter)))) header += pack(str(len(cert_fw_inter)) + 's', cert_fw_inter) # Pad, leaving 64 bytes for signature + 32*3 bytes for valid info if (args.cert_fw_leaf or args.cert_fw_inter): padding = args.offset - (len(header) + 3 * 32 + 64) header += b'\0' * padding #GCM needs Nonce to sign #AES cannot sign if key.has_sign(): if key.has_nonce() and iv_nonce == "": print("sign key required nonce, provide nonce") exit(1) if key.has_nonce(): if nonce != b'': signature, nonce_used = key.sign(header, nonce) if nonce_used != nonce: print("error nonce used differs") exit(1) else: print("nonce required for this key") exit(1) else: signature = key.sign(header) header += pack(str(len(signature)) + 's', signature) else: print("Provided Key is not useable to sign header") exit(1) return header, signature