diff options
Diffstat (limited to 'circuitpython/lib/nrfutil/nordicsemi/dfu/signing.py')
| -rw-r--r-- | circuitpython/lib/nrfutil/nordicsemi/dfu/signing.py | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/circuitpython/lib/nrfutil/nordicsemi/dfu/signing.py b/circuitpython/lib/nrfutil/nordicsemi/dfu/signing.py new file mode 100644 index 0000000..ca98eb1 --- /dev/null +++ b/circuitpython/lib/nrfutil/nordicsemi/dfu/signing.py @@ -0,0 +1,149 @@ +# Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved. +# +# The information contained herein is property of Nordic Semiconductor ASA. +# Terms and conditions of usage are described in detail in NORDIC +# SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. +# +# Licensees are granted free, non-transferable use of the information. NO +# WARRANTY of ANY KIND is provided. This heading must NOT be removed from +# the file. + +import hashlib +import binascii + +try: + from ecdsa import SigningKey + from ecdsa.curves import NIST256p + from ecdsa.keys import sigencode_string +except Exception: + print "Failed to import ecdsa, cannot do signing" + +from nordicsemi.exceptions import InvalidArgumentException, IllegalStateException + + +class Signing(object): + """ + Class for singing of hex-files + """ + def gen_key(self, filename): + """ + Generate a new Signing key using NIST P-256 curve + """ + self.sk = SigningKey.generate(curve=NIST256p) + + with open(filename, "w") as sk_file: + sk_file.write(self.sk.to_pem()) + + def load_key(self, filename): + """ + Load signing key (from pem file) + """ + with open(filename, "r") as sk_file: + sk_pem = sk_file.read() + + self.sk = SigningKey.from_pem(sk_pem) + + sk_hex = "".join(c.encode('hex') for c in self.sk.to_string()) + + def sign(self, init_packet_data): + """ + Create signature for init package using P-256 curve and SHA-256 as hashing algorithm + Returns R and S keys combined in a 64 byte array + """ + # Add assertion of init_packet + if self.sk is None: + raise IllegalStateException("Can't save key. No key created/loaded") + + # Sign the init-packet + signature = self.sk.sign(init_packet_data, hashfunc=hashlib.sha256, sigencode=sigencode_string) + return signature + + def verify(self, init_packet, signature): + """ + Verify init packet + """ + # Add assertion of init_packet + if self.sk is None: + raise IllegalStateException("Can't save key. No key created/loaded") + + vk = self.sk.get_verifying_key() + + # Verify init packet + try: + vk.verify(signature, init_packet, hashfunc=hashlib.sha256) + except: + return False + + return True + + def get_vk(self, output_type): + """ + Get verification key (as hex, code or pem) + """ + if self.sk is None: + raise IllegalStateException("Can't get key. No key created/loaded") + + if output_type is None: + raise InvalidArgumentException("Invalid output type for signature.") + elif output_type == 'hex': + return self.get_vk_hex() + elif output_type == 'code': + return self.get_vk_code() + elif output_type == 'pem': + return self.get_vk_pem() + else: + raise InvalidArgumentException("Invalid argument. Can't get key") + + def get_vk_hex(self): + """ + Get the verification key as hex + """ + if self.sk is None: + raise IllegalStateException("Can't get key. No key created/loaded") + + vk = self.sk.get_verifying_key() + vk_hexlify = binascii.hexlify(vk.to_string()) + + vk_hex = "Verification key Qx: {0}\n".format(vk_hexlify[0:64]) + vk_hex += "Verification key Qy: {0}".format(vk_hexlify[64:128]) + + return vk_hex + + def get_vk_code(self): + """ + Get the verification key as code + """ + if self.sk is None: + raise IllegalStateException("Can't get key. No key created/loaded") + + vk = self.sk.get_verifying_key() + vk_hex = binascii.hexlify(vk.to_string()) + + vk_x_separated = "" + vk_x_str = vk_hex[0:64] + for i in xrange(0, len(vk_x_str), 2): + vk_x_separated += "0x" + vk_x_str[i:i+2] + ", " + vk_x_separated = vk_x_separated[:-2] + + vk_y_separated = "" + vk_y_str = vk_hex[64:128] + for i in xrange(0, len(vk_y_str), 2): + vk_y_separated += "0x" + vk_y_str[i:i+2] + ", " + vk_y_separated = vk_y_separated[:-2] + + vk_code = "static uint8_t Qx[] = {{ {0} }};\n".format(vk_x_separated) + vk_code += "static uint8_t Qy[] = {{ {0} }};".format(vk_y_separated) + + return vk_code + + def get_vk_pem(self): + """ + Get the verification key as PEM + """ + if self.sk is None: + raise IllegalStateException("Can't get key. No key created/loaded") + + vk = self.sk.get_verifying_key() + vk_pem = vk.to_pem() + + return vk_pem |
