diff --git a/bin/smartpgp-cli b/bin/smartpgp-cli index dec8254..5a2b7de 100755 --- a/bin/smartpgp-cli +++ b/bin/smartpgp-cli @@ -38,6 +38,7 @@ VALID_COMMANDS={ 'switch-p384': CardConnectionContext.cmd_switch_p384, 'switch-p521': CardConnectionContext.cmd_switch_p521, 'generate-sm-key': CardConnectionContext.cmd_generate_sm_key, + 'get-sm-key': CardConnectionContext.cmd_get_sm_key, 'set-resetting-code': CardConnectionContext.cmd_set_resetting_code, 'unblock-pin': CardConnectionContext.cmd_unblock_pin, 'put-sm-key': CardConnectionContext.cmd_put_sm_key, diff --git a/bin/smartpgp/commands.py b/bin/smartpgp/commands.py index bd98745..7b78e02 100644 --- a/bin/smartpgp/commands.py +++ b/bin/smartpgp/commands.py @@ -40,6 +40,7 @@ ACTIVATE = [0x00, 0x44, 0x00, 0x00] ACTIVATE_FULL = [0x00, 0x44, 0x00, 0x01] GET_SM_CURVE_OID = [0x00, 0xca, 0x00, 0xd4] GENERATE_ASYMETRIC_KEYPAIR = [0x00, 0x47, 0x80, 0x00] +GET_ASYMETRIC_KEYPAIR = [0x00, 0x47, 0x81, 0x00] ALGS_ALIASES = { 'ansix9p256r1': 'ansix9p256r1', @@ -232,6 +233,11 @@ def generate_sm_key(connection): apdu = apdu + [0x00] return _raw_send_apdu(connection,"Generate SM key",apdu) +def get_sm_key(connection): + apdu = assemble_with_len(GET_ASYMETRIC_KEYPAIR, [0xA6, 0x00]) + apdu = apdu + [0x00] + return _raw_send_apdu(connection,"Get SM key",apdu) + def set_resetting_code(connection, resetting_code): apdu = assemble_with_len([0x00, 0xDA, 0x00, 0xD3], ascii_encode_pin(resetting_code)) _raw_send_apdu(connection,"Define the resetting code (PUK)",apdu) diff --git a/bin/smartpgp/highlevel.py b/bin/smartpgp/highlevel.py index a1f9309..a06fda4 100644 --- a/bin/smartpgp/highlevel.py +++ b/bin/smartpgp/highlevel.py @@ -189,6 +189,48 @@ class CardConnectionContext: f.write(pubkey_der) f.close() + def cmd_get_sm_key(self): + if not self.output: + print "Missing output file name" + return + self.connect() + (data,sw1,sw2) = get_sm_key(self.connection) + if sw1!=0x90 or sw2!=0x00: + print "get_sm_key failed" + return + if len(data) < 4 or data[0]!=0x7f or data[1]!=0x49: + print "Strange reply for get_sm_key" + return + blob_len = data[2] + blob = data[3:] + assert(blob_len == len(blob)) + if blob[0]!=0x86: + print "get_sm_key something not a public key" + return + assert(blob[1]==len(blob[2:])) + pubkey = blob[2:] + # get curve OID + curve_oid_der = get_sm_curve_oid(self.connection) + if not curve_oid_der: + print "Error getting SM curve OID" + return + (curve_oid,_) = der_decoder.decode(str(curve_oid_der)) + # now format it to DER [RFC5480] + s = univ.Sequence() + oid_elliptic_curve_pubkey = univ.ObjectIdentifier('1.2.840.10045.2.1') + s.setComponentByPosition(0,oid_elliptic_curve_pubkey) + s.setComponentByPosition(1,curve_oid) + bs = univ.BitString("'%s'H" % binascii.hexlify(bytearray(pubkey))) + s2 = univ.Sequence() + s2.setComponentByPosition(0,s) + s2.setComponentByPosition(1,bs) + pubkey_der = der_encoder.encode(s2) + print binascii.hexlify(pubkey_der) + # and write result + with open(self.output,"wb") as f: + f.write(pubkey_der) + f.close() + def cmd_put_sm_key(self): if self.input is None: print "No input key file"