From dc2d277c4f32ce77526e5192d371a739555186f3 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Fri, 31 Aug 2012 18:00:12 +0200 Subject: [PATCH] nPA: use given credentials for CA The user can now specify an EF.CardSecurity, CA private/public key and CHR of the trust anchor via the command line. --- virtualsmartcard/src/vpicc/vicc.in | 35 +++++++++++++++++- .../virtualsmartcard/VirtualSmartcard.py | 16 ++++++-- .../src/vpicc/virtualsmartcard/cards/nPA.py | 37 +++++++++---------- 3 files changed, 65 insertions(+), 23 deletions(-) diff --git a/virtualsmartcard/src/vpicc/vicc.in b/virtualsmartcard/src/vpicc/vicc.in index a24360e..ab940c6 100644 --- a/virtualsmartcard/src/vpicc/vicc.in +++ b/virtualsmartcard/src/vpicc/vicc.in @@ -60,9 +60,42 @@ relay.add_argument("-r", "--reader", type=int, help="number of the reader which contains the smart card to be relayed.") +npa = parser.add_argument_group('options for nPA emulation') +npa.add_argument("-e", "--ef-cardsecurity", + action="store", + type=argparse.FileType('r'), + help="EF.CardSecurity with the signed CA public key.") +npa.add_argument("-k", "--ca-key", + action="store", + type=argparse.FileType('r'), + help="CA private key.") +npa.add_argument("-p", "--ca-pubkey", + action="store", + type=argparse.FileType('r'), + help="CA public key.") +npa.add_argument("-c", "--ca", + action="store", + type=str, + help="CHR of the CVCA.") + args = parser.parse_args() from virtualsmartcard.VirtualSmartcard import VirtualICC + +ef_cardsecurity_data = None +ca_key_data = None +ca_pubkey_data = None +if (args.ef_cardsecurity): + ef_cardsecurity_data = args.ef_cardsecurity.read() + args.ef_cardsecurity.close() +if (args.ca_key): + ca_key_data = args.ca_key.read() + args.ca_key.close() +if (args.ca_pubkey): + ca_pubkey_data = args.ca_pubkey.read() + args.ca_pubkey.close() vicc = VirtualICC(args.file, args.type, - args.hostname, args.port, readernum=args.reader) + args.hostname, args.port, readernum=args.reader, + ef_cardsecurity=ef_cardsecurity_data, ca_pubkey=ca_pubkey_data, + ca_key=ca_key_data, ca=args.ca) vicc.run() diff --git a/virtualsmartcard/src/vpicc/virtualsmartcard/VirtualSmartcard.py b/virtualsmartcard/src/vpicc/virtualsmartcard/VirtualSmartcard.py index f4357b2..c3c1ca4 100644 --- a/virtualsmartcard/src/vpicc/virtualsmartcard/VirtualSmartcard.py +++ b/virtualsmartcard/src/vpicc/virtualsmartcard/VirtualSmartcard.py @@ -499,11 +499,21 @@ class RelayOS(SmartcardOS): class NPAOS(Iso7816OS): - def __init__(self, mf, sam, ins2handler=None, maxle=MAX_EXTENDED_LE): + def __init__(self, mf, sam, ins2handler=None, maxle=MAX_EXTENDED_LE, ef_cardsecurity=None, ca_key=None, ca_pubkey=None, ca=None): Iso7816OS.__init__(self, mf, sam, ins2handler, maxle) self.ins2handler[0x86] = self.SAM.general_authenticate self.ins2handler[0x2c] = self.SAM.reset_retry_counter self.atr = '\x3B\x8A\x80\x01\x80\x31\xF8\x73\xF7\x41\xE0\x82\x90\x00\x75' + if ef_cardsecurity: + ef = self.mf.select('fid', 0x011d) + ef.setdec('data', ef_cardsecurity) + if ca: + self.SAM.current_SE.ca = ca + if ca_key: + self.SAM.current_SE.ca_key = ca_key + if ca_pubkey: + self.SAM.current_SE.ca_pubkey = ca_pubkey + def formatResult(self, seekable, le, data, sw, sm): if seekable: @@ -543,7 +553,7 @@ class VirtualICC(object): the vpcd, which forwards it to the application. """ - def __init__(self, filename, card_type, host, port, lenlen=3, readernum=None): + def __init__(self, filename, card_type, host, port, lenlen=3, readernum=None, ef_cardsecurity=None, ca_key=None, ca_pubkey=None, ca=None): from os.path import exists logging.basicConfig(level = logging.INFO, @@ -568,7 +578,7 @@ class VirtualICC(object): if card_type == "iso7816" or card_type == "ePass": self.os = Iso7816OS(MF, SAM) elif card_type == "nPA": - self.os = NPAOS(MF, SAM) + self.os = NPAOS(MF, SAM, ef_cardsecurity=ef_cardsecurity, ca_key=ca_key, ca_pubkey=ca_pubkey, ca=ca) elif card_type == "cryptoflex": self.os = CryptoflexOS(MF, SAM) elif card_type == "relay": diff --git a/virtualsmartcard/src/vpicc/virtualsmartcard/cards/nPA.py b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/nPA.py index de70b22..1b6897b 100644 --- a/virtualsmartcard/src/vpicc/virtualsmartcard/cards/nPA.py +++ b/virtualsmartcard/src/vpicc/virtualsmartcard/cards/nPA.py @@ -110,6 +110,8 @@ class nPA_SE(Security_Environment): self.eac_ctx = None self.ssc = 0 self.ca = "DECVCAeID00102" + self.ca_key = None + self.ca_pubkey = None def _set_SE(self, p2, data): sw, resp = Security_Environment._set_SE(self, p2, data) @@ -199,26 +201,21 @@ class nPA_SE(Security_Environment): ef_card_access = self.mf.select('fid', 0x011c) ef_card_access_data = ef_card_access.getenc('data') pace.EAC_CTX_init_ef_cardaccess(ef_card_access_data, self.eac_ctx) - pace.EAC_CTX_init_ca(self.eac_ctx, pace.id_CA_ECDH_AES_CBC_CMAC_128, 13, None, None) + pace.EAC_CTX_init_ca(self.eac_ctx, pace.id_CA_ECDH_AES_CBC_CMAC_128, 13, self.ca_key, self.ca_pubkey) - # we don't have a good CA key, so we simply generate an ephemeral one - comp_pubkey = pace.TA_STEP3_generate_ephemeral_key(self.eac_ctx) - pubkey = pace.CA_STEP2_get_eph_pubkey(self.eac_ctx) - if not comp_pubkey or not pubkey: - pace.print_ossl_err() - raise SwError(SW["WARN_NOINFO63"]) + if not self.ca_key: + # we don't have a good CA key, so we simply generate an ephemeral one + comp_pubkey = pace.TA_STEP3_generate_ephemeral_key(self.eac_ctx) + pubkey = pace.CA_STEP2_get_eph_pubkey(self.eac_ctx) + if not comp_pubkey or not pubkey: + pace.print_ossl_err() + raise SwError(SW["WARN_NOINFO63"]) - # save public key in EF.CardSecurity (and invalidate the signature) - ef_card_security = self.mf.select('fid', 0x011d) - ef_card_security_data = ef_card_security.getenc('data') - ef_card_security_data = ef_card_security_data[:61+4+239+2+1] + pubkey + ef_card_security_data[61+4+239+2+1+len(pubkey):] - ef_card_security.setdec('data', ef_card_security_data) - - #print 'pubkey' - #print hexdump(pubkey) - #f=open('test', 'w') - #f.write(ef_card_security_data) - #f.close() + # save public key in EF.CardSecurity (and invalidate the signature) + ef_card_security = self.mf.select('fid', 0x011d) + ef_card_security_data = ef_card_security.getenc('data') + ef_card_security_data = ef_card_security_data[:61+4+239+2+1] + pubkey + ef_card_security_data[61+4+239+2+1+len(pubkey):] + ef_card_security.setdec('data', ef_card_security_data) nonce = pace.PACE_STEP1_enc_nonce(self.eac_ctx, self.sec) @@ -300,7 +297,9 @@ class nPA_SE(Security_Environment): pace.EAC_CTX_set_encryption_ctx(self.eac_ctx, pace.EAC_ID_PACE) result = [[0x86, len(my_token), my_token]] if self.at.chat: - pace.EAC_CTX_init_ta(self.eac_ctx, None, None, self.ca) + if not pace.EAC_CTX_init_ta(self.eac_ctx, None, None, self.ca): + pace.print_ossl_err() + raise SwError(SW["WARN_NOINFO63"]) result.append([0x87, len(self.ca), self.ca]) return 0x9000, nPA_SE.__pack_general_authenticate(result)