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.
This commit is contained in:
@@ -60,9 +60,42 @@ relay.add_argument("-r", "--reader",
|
|||||||
type=int,
|
type=int,
|
||||||
help="number of the reader which contains the smart card to be relayed.")
|
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()
|
args = parser.parse_args()
|
||||||
|
|
||||||
from virtualsmartcard.VirtualSmartcard import VirtualICC
|
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,
|
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()
|
vicc.run()
|
||||||
|
|||||||
@@ -499,11 +499,21 @@ class RelayOS(SmartcardOS):
|
|||||||
|
|
||||||
|
|
||||||
class NPAOS(Iso7816OS):
|
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)
|
Iso7816OS.__init__(self, mf, sam, ins2handler, maxle)
|
||||||
self.ins2handler[0x86] = self.SAM.general_authenticate
|
self.ins2handler[0x86] = self.SAM.general_authenticate
|
||||||
self.ins2handler[0x2c] = self.SAM.reset_retry_counter
|
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'
|
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):
|
def formatResult(self, seekable, le, data, sw, sm):
|
||||||
if seekable:
|
if seekable:
|
||||||
@@ -543,7 +553,7 @@ class VirtualICC(object):
|
|||||||
the vpcd, which forwards it to the application.
|
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
|
from os.path import exists
|
||||||
|
|
||||||
logging.basicConfig(level = logging.INFO,
|
logging.basicConfig(level = logging.INFO,
|
||||||
@@ -568,7 +578,7 @@ class VirtualICC(object):
|
|||||||
if card_type == "iso7816" or card_type == "ePass":
|
if card_type == "iso7816" or card_type == "ePass":
|
||||||
self.os = Iso7816OS(MF, SAM)
|
self.os = Iso7816OS(MF, SAM)
|
||||||
elif card_type == "nPA":
|
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":
|
elif card_type == "cryptoflex":
|
||||||
self.os = CryptoflexOS(MF, SAM)
|
self.os = CryptoflexOS(MF, SAM)
|
||||||
elif card_type == "relay":
|
elif card_type == "relay":
|
||||||
|
|||||||
@@ -110,6 +110,8 @@ class nPA_SE(Security_Environment):
|
|||||||
self.eac_ctx = None
|
self.eac_ctx = None
|
||||||
self.ssc = 0
|
self.ssc = 0
|
||||||
self.ca = "DECVCAeID00102"
|
self.ca = "DECVCAeID00102"
|
||||||
|
self.ca_key = None
|
||||||
|
self.ca_pubkey = None
|
||||||
|
|
||||||
def _set_SE(self, p2, data):
|
def _set_SE(self, p2, data):
|
||||||
sw, resp = Security_Environment._set_SE(self, p2, data)
|
sw, resp = Security_Environment._set_SE(self, p2, data)
|
||||||
@@ -199,8 +201,9 @@ class nPA_SE(Security_Environment):
|
|||||||
ef_card_access = self.mf.select('fid', 0x011c)
|
ef_card_access = self.mf.select('fid', 0x011c)
|
||||||
ef_card_access_data = ef_card_access.getenc('data')
|
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_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)
|
||||||
|
|
||||||
|
if not self.ca_key:
|
||||||
# we don't have a good CA key, so we simply generate an ephemeral one
|
# 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)
|
comp_pubkey = pace.TA_STEP3_generate_ephemeral_key(self.eac_ctx)
|
||||||
pubkey = pace.CA_STEP2_get_eph_pubkey(self.eac_ctx)
|
pubkey = pace.CA_STEP2_get_eph_pubkey(self.eac_ctx)
|
||||||
@@ -214,12 +217,6 @@ class nPA_SE(Security_Environment):
|
|||||||
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_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)
|
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()
|
|
||||||
|
|
||||||
nonce = pace.PACE_STEP1_enc_nonce(self.eac_ctx, self.sec)
|
nonce = pace.PACE_STEP1_enc_nonce(self.eac_ctx, self.sec)
|
||||||
|
|
||||||
resp = nPA_SE.__pack_general_authenticate([[0x80, len(nonce), nonce]])
|
resp = nPA_SE.__pack_general_authenticate([[0x80, len(nonce), nonce]])
|
||||||
@@ -300,7 +297,9 @@ class nPA_SE(Security_Environment):
|
|||||||
pace.EAC_CTX_set_encryption_ctx(self.eac_ctx, pace.EAC_ID_PACE)
|
pace.EAC_CTX_set_encryption_ctx(self.eac_ctx, pace.EAC_ID_PACE)
|
||||||
result = [[0x86, len(my_token), my_token]]
|
result = [[0x86, len(my_token), my_token]]
|
||||||
if self.at.chat:
|
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])
|
result.append([0x87, len(self.ca), self.ca])
|
||||||
|
|
||||||
return 0x9000, nPA_SE.__pack_general_authenticate(result)
|
return 0x9000, nPA_SE.__pack_general_authenticate(result)
|
||||||
|
|||||||
Reference in New Issue
Block a user