Code style improvements and bugfixing in mutual_authenticate
git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@453 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
@@ -21,7 +21,7 @@ import random, struct, hashlib
|
|||||||
from pickle import dumps, loads
|
from pickle import dumps, loads
|
||||||
|
|
||||||
import SmartcardFilesystem, TLVutils
|
import SmartcardFilesystem, TLVutils
|
||||||
import virtualsmartcard.CryptoUtils
|
import virtualsmartcard.CryptoUtils as vsCrypto
|
||||||
from virtualsmartcard.SWutils import SwError, SW
|
from virtualsmartcard.SWutils import SwError, SW
|
||||||
from virtualsmartcard.utils import inttostring, stringtoint, hexdump, C_APDU
|
from virtualsmartcard.utils import inttostring, stringtoint, hexdump, C_APDU
|
||||||
from virtualsmartcard.ConstantDefinitions import *
|
from virtualsmartcard.ConstantDefinitions import *
|
||||||
@@ -61,12 +61,12 @@ class CardContainer:
|
|||||||
|
|
||||||
def __init__(self, PIN=None, cardNumber=None, cardSecret=None):
|
def __init__(self, PIN=None, cardNumber=None, cardSecret=None):
|
||||||
from os import urandom
|
from os import urandom
|
||||||
from virtualsmartcard.CryptoUtils import get_cipher_keylen, cipher
|
from vsCrypto import get_cipher_keylen, cipher
|
||||||
|
|
||||||
self.cardNumber = cardNumber
|
self.cardNumber = cardNumber
|
||||||
self.PIN = PIN
|
self.PIN = PIN
|
||||||
self.FSkeys = {}
|
self.FSkeys = {}
|
||||||
self.cipher = 0x01 # Algorithm reference defined in __get_referenced_algorithm(p1)
|
self.cipher = 0x01 #Algorithm reference for __get_referenced_algorithm(p1)
|
||||||
self.master_password = None
|
self.master_password = None
|
||||||
self.master_key = None
|
self.master_key = None
|
||||||
self.salt = None
|
self.salt = None
|
||||||
@@ -117,7 +117,8 @@ class CardContainer:
|
|||||||
@return: key if the key is in the container, otherwise None
|
@return: key if the key is in the container, otherwise None
|
||||||
"""
|
"""
|
||||||
if(self.FSkeys.has_key(path)):
|
if(self.FSkeys.has_key(path)):
|
||||||
plain_key = cipher(False, self.cipher, self.master_password, self.FSkeys[path]) #TODO: Error checking:
|
plain_key = cipher(False, self.cipher, self.master_password,
|
||||||
|
self.FSkeys[path]) #TODO: Error checking
|
||||||
return plain_key
|
return plain_key
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
@@ -158,8 +159,10 @@ class SAM(object):
|
|||||||
raise ValueError
|
raise ValueError
|
||||||
|
|
||||||
cipher = get_referenced_cipher(self.CardContainer.cipher)
|
cipher = get_referenced_cipher(self.CardContainer.cipher)
|
||||||
padded_data = virtualsmartcard.CryptoUtils.append_padding(cipher, data)
|
padded_data = vsCrypto.append_padding(cipher, data)
|
||||||
crypted_data = virtualsmartcard.CryptoUtils.cipher(True, cipher, self.CardContainer.master_key, padded_data)
|
crypted_data = vsCrypto.cipher(True, cipher,
|
||||||
|
self.CardContainer.master_key,
|
||||||
|
padded_data)
|
||||||
return crypted_data
|
return crypted_data
|
||||||
|
|
||||||
def FSdecrypt(self, data):
|
def FSdecrypt(self, data):
|
||||||
@@ -170,8 +173,10 @@ class SAM(object):
|
|||||||
raise ValueError, "No master key set."
|
raise ValueError, "No master key set."
|
||||||
|
|
||||||
cipher = get_referenced_cipher(self.CardContainer.cipher)
|
cipher = get_referenced_cipher(self.CardContainer.cipher)
|
||||||
decrypted_data = virtualsmartcard.CryptoUtils.cipher(False, cipher, self.CardContainer.master_key, data)
|
decrypted_data = vsCrypto.cipher(False, cipher,
|
||||||
unpadded_data = virtualsmartcard.CryptoUtils.strip_padding(cipher, decrypted_data)
|
self.CardContainer.master_key,
|
||||||
|
data)
|
||||||
|
unpadded_data = vsCrypto.strip_padding(cipher, decrypted_data)
|
||||||
return unpadded_data
|
return unpadded_data
|
||||||
|
|
||||||
def set_algorithm(self, algo):
|
def set_algorithm(self, algo):
|
||||||
@@ -243,7 +248,7 @@ class SAM(object):
|
|||||||
crypted_challenge = inttostring(crypted_challenge)
|
crypted_challenge = inttostring(crypted_challenge)
|
||||||
else:
|
else:
|
||||||
key = self._get_referenced_key(p1, p2)
|
key = self._get_referenced_key(p1, p2)
|
||||||
crypted_challenge = virtualsmartcard.CryptoUtils.cipher(True, cipher, key, data)
|
crypted_challenge = vsCrypto.cipher(True, cipher, key, data)
|
||||||
|
|
||||||
return SW["NORMAL"], crypted_challenge
|
return SW["NORMAL"], crypted_challenge
|
||||||
|
|
||||||
@@ -261,14 +266,14 @@ class SAM(object):
|
|||||||
else:
|
else:
|
||||||
cipher = get_referenced_cipher(p1)
|
cipher = get_referenced_cipher(p1)
|
||||||
|
|
||||||
reference = virtualsmartcard.CryptoUtils.append_padding(cipher, self.last_challenge)
|
reference = vsCrypto.append_padding(cipher, self.last_challenge)
|
||||||
reference = virtualsmartcard.CryptoUtils.cipher(True, cipher, key, reference)
|
reference = vsCrypto.cipher(True, cipher, key, reference)
|
||||||
if(reference == data):
|
if(reference == data):
|
||||||
#Invalidate last challenge
|
#Invalidate last challenge
|
||||||
self.last_challenge = None
|
self.last_challenge = None
|
||||||
return SW["NORMAL"], ""
|
return SW["NORMAL"], ""
|
||||||
else:
|
else:
|
||||||
plain = virtualsmartcard.CryptoUtils.cipher(False, cipher, key, data)
|
plain = vsCrypto.cipher(False, cipher, key, data)
|
||||||
print plain
|
print plain
|
||||||
print "Reference: " + hexdump(reference)
|
print "Reference: " + hexdump(reference)
|
||||||
print "Data: " + hexdump(data)
|
print "Data: " + hexdump(data)
|
||||||
@@ -296,19 +301,20 @@ class SAM(object):
|
|||||||
|
|
||||||
if (cipher == None):
|
if (cipher == None):
|
||||||
raise SwError(SW["ERR_INCORRECTP1P2"])
|
raise SwError(SW["ERR_INCORRECTP1P2"])
|
||||||
plain = virtualsmartcard.CryptoUtils.cipher(False, cipher, key, mutual_challenge)
|
|
||||||
terminal_challenge = plain[:len(self.last_challenge)-1]
|
plain = vsCrypto.cipher(False, cipher, key, mutual_challenge)
|
||||||
card_challenge = plain[len(self.last_challenge):len(challenge)-len(card_number)-1]
|
last_challenge_len = len(self.last_challenge)
|
||||||
serial_number = plain[(challenge)-len(card_number):]
|
terminal_challenge = plain[:last_challenge_len-1]
|
||||||
|
card_challenge = plain[last_challenge_len:-len(card_number)-1]
|
||||||
|
serial_number = plain[-len(card_number):]
|
||||||
|
|
||||||
if terminal_challenge != self.last_challenge:
|
if terminal_challenge != self.last_challenge:
|
||||||
print "Mutual authentication failed!"
|
|
||||||
raise SwError(SW["WARN_NOINFO63"])
|
raise SwError(SW["WARN_NOINFO63"])
|
||||||
elif serial_number != card_number:
|
elif serial_number != card_number:
|
||||||
print "Mutual authentication failed!"
|
|
||||||
raise SwError(SW["WARN_NOINFO63"])
|
raise SwError(SW["WARN_NOINFO63"])
|
||||||
|
|
||||||
result = card_challenge + terminal_challenge
|
result = card_challenge + terminal_challenge
|
||||||
return SW["NORMAL"], virtualsmartcard.CryptoUtils.cipher(True, cipher, key, result)
|
return SW["NORMAL"], vsCrypto.cipher(True, cipher, key, result)
|
||||||
|
|
||||||
def get_challenge(self, p1, p2, data):
|
def get_challenge(self, p1, p2, data):
|
||||||
"""
|
"""
|
||||||
@@ -353,7 +359,7 @@ class SAM(object):
|
|||||||
key = None
|
key = None
|
||||||
qualifier = p2 & 0x1F
|
qualifier = p2 & 0x1F
|
||||||
algo = get_referenced_cipher(p1)
|
algo = get_referenced_cipher(p1)
|
||||||
keylength = virtualsmartcard.CryptoUtils.get_cipher_keylen(algo)
|
keylength = vsCrypto.get_cipher_keylen(algo)
|
||||||
|
|
||||||
if (p2 == 0x00): #No information given, use the global card key
|
if (p2 == 0x00): #No information given, use the global card key
|
||||||
key = self.CardContainer.cardSecret
|
key = self.CardContainer.cardSecret
|
||||||
@@ -465,7 +471,7 @@ class PassportSAM(SAM):
|
|||||||
if not Mifd == resp_data[-8:]:
|
if not Mifd == resp_data[-8:]:
|
||||||
raise ValueError, "Passport authentication failed: Wrong MAC on incoming data during Mutual Authenticate"
|
raise ValueError, "Passport authentication failed: Wrong MAC on incoming data during Mutual Authenticate"
|
||||||
#Decrypt the data
|
#Decrypt the data
|
||||||
plain = virtualsmartcard.CryptoUtils.cipher(False, "DES3-CBC", self.KEnc, resp_data[:-8])
|
plain = vsCrypto.cipher(False, "DES3-CBC", self.KEnc, resp_data[:-8])
|
||||||
#Split decrypted data into the two nonces and
|
#Split decrypted data into the two nonces and
|
||||||
if plain[8:16] != rnd_icc:
|
if plain[8:16] != rnd_icc:
|
||||||
raise SwError(SW["WARN_NOINFO63"])
|
raise SwError(SW["WARN_NOINFO63"])
|
||||||
@@ -477,10 +483,10 @@ class PassportSAM(SAM):
|
|||||||
Kicc = inttostring(random.randint(0, int(max, 16)))
|
Kicc = inttostring(random.randint(0, int(max, 16)))
|
||||||
#Generate Answer
|
#Generate Answer
|
||||||
data = plain[8:16] + plain[:8] + Kicc
|
data = plain[8:16] + plain[:8] + Kicc
|
||||||
Eicc = virtualsmartcard.CryptoUtils.cipher(True, "DES3-CBC", self.KEnc, data)
|
Eicc = vsCrypto.cipher(True, "DES3-CBC", self.KEnc, data)
|
||||||
Micc = self._mac(self.KMac, Eicc)
|
Micc = self._mac(self.KMac, Eicc)
|
||||||
#Derive the final keys
|
#Derive the final keys
|
||||||
KSseed = virtualsmartcard.CryptoUtils.operation_on_string(Kicc, Kifd, lambda a,b: a^b)
|
KSseed = vsCrypto.operation_on_string(Kicc, Kifd, lambda a,b: a^b)
|
||||||
self.KSenc = self.derive_key(KSseed, 1)
|
self.KSenc = self.derive_key(KSseed, 1)
|
||||||
self.KSmac = self.derive_key(KSseed, 2)
|
self.KSmac = self.derive_key(KSseed, 2)
|
||||||
#self.ssc = rnd_icc[-4:] + rnd_ifd[-4:]
|
#self.ssc = rnd_icc[-4:] + rnd_ifd[-4:]
|
||||||
@@ -498,9 +504,9 @@ class PassportSAM(SAM):
|
|||||||
if dopad:
|
if dopad:
|
||||||
topad = 8 - len(data) % 8
|
topad = 8 - len(data) % 8
|
||||||
data = data + "\x80" + ("\x00" * (topad-1))
|
data = data + "\x80" + ("\x00" * (topad-1))
|
||||||
a = virtualsmartcard.CryptoUtils.cipher(True, "des-cbc", key[:8], data)
|
a = vsCrypto.cipher(True, "des-cbc", key[:8], data)
|
||||||
b = virtualsmartcard.CryptoUtils.cipher(False, "des-ecb", key[8:16], a[-8:])
|
b = vsCrypto.cipher(False, "des-ecb", key[8:16], a[-8:])
|
||||||
c = virtualsmartcard.CryptoUtils.cipher(True, "des-ecb", key[:8], b)
|
c = vsCrypto.cipher(True, "des-ecb", key[:8], b)
|
||||||
return c
|
return c
|
||||||
|
|
||||||
class CryptoflexSAM(SAM):
|
class CryptoflexSAM(SAM):
|
||||||
@@ -697,7 +703,7 @@ class Secure_Messaging(object):
|
|||||||
|
|
||||||
if header_authentication:
|
if header_authentication:
|
||||||
to_authenticate = inttostring(CAPDU.cla) + inttostring(CAPDU.ins) + inttostring(CAPDU.p1) + inttostring(CAPDU.p2)
|
to_authenticate = inttostring(CAPDU.cla) + inttostring(CAPDU.ins) + inttostring(CAPDU.p1) + inttostring(CAPDU.p2)
|
||||||
to_authenticate = virtualsmartcard.CryptoUtils.append_padding("DES-CBC", to_authenticate)
|
to_authenticate = vsCrypto.append_padding("DES-CBC", to_authenticate)
|
||||||
else:
|
else:
|
||||||
to_authenticate = ""
|
to_authenticate = ""
|
||||||
|
|
||||||
@@ -760,12 +766,12 @@ class Secure_Messaging(object):
|
|||||||
sw, plain = self.decipher(tag, 0x80, value[1:])
|
sw, plain = self.decipher(tag, 0x80, value[1:])
|
||||||
if sw != 0x9000:
|
if sw != 0x9000:
|
||||||
raise ValueError
|
raise ValueError
|
||||||
plain = virtualsmartcard.CryptoUtils.strip_padding(self.current_SE.ct.algorithm, plain, padding_indicator)
|
plain = vsCrypto.strip_padding(self.current_SE.ct.algorithm, plain, padding_indicator)
|
||||||
return_data.append(plain)
|
return_data.append(plain)
|
||||||
|
|
||||||
#SM data objects for authentication
|
#SM data objects for authentication
|
||||||
if tag == SM_Class["CHECKSUM"]:
|
if tag == SM_Class["CHECKSUM"]:
|
||||||
auth = virtualsmartcard.CryptoUtils.append_padding("DES-CBC", to_authenticate)
|
auth = vsCrypto.append_padding("DES-CBC", to_authenticate)
|
||||||
sw, checksum = self.compute_cryptographic_checksum(0x8E, 0x80, auth)
|
sw, checksum = self.compute_cryptographic_checksum(0x8E, 0x80, auth)
|
||||||
if checksum != value:
|
if checksum != value:
|
||||||
raise SwError(SW["ERR_SECMESSOBJECTSINCORRECT"])
|
raise SwError(SW["ERR_SECMESSOBJECTSINCORRECT"])
|
||||||
@@ -832,7 +838,7 @@ class Secure_Messaging(object):
|
|||||||
raise SwError(SW["CONDITIONSNOTSATISFIED"])
|
raise SwError(SW["CONDITIONSNOTSATISFIED"])
|
||||||
elif self.current_SE.cct.algorithm == "CCT":
|
elif self.current_SE.cct.algorithm == "CCT":
|
||||||
tag = SM_Class["CHECKSUM"]
|
tag = SM_Class["CHECKSUM"]
|
||||||
to_auth = virtualsmartcard.CryptoUtils.append_padding("DES-ECB", return_data)
|
to_auth = vsCrypto.append_padding("DES-ECB", return_data)
|
||||||
sw, auth = self.compute_cryptographic_checksum(0x8E, 0x80, to_auth)
|
sw, auth = self.compute_cryptographic_checksum(0x8E, 0x80, to_auth)
|
||||||
length = len(auth)
|
length = len(auth)
|
||||||
return_data += TLVutils.pack([(tag, length, auth)])
|
return_data += TLVutils.pack([(tag, length, auth)])
|
||||||
@@ -891,7 +897,7 @@ class Secure_Messaging(object):
|
|||||||
if self.current_SE.cct.key == None:
|
if self.current_SE.cct.key == None:
|
||||||
raise SwError(SW["ERR_CONDITIONNOTSATISFIED"])
|
raise SwError(SW["ERR_CONDITIONNOTSATISFIED"])
|
||||||
|
|
||||||
checksum = virtualsmartcard.CryptoUtils.crypto_checksum(self.current_SE.cct.algorithm,
|
checksum = vsCrypto.crypto_checksum(self.current_SE.cct.algorithm,
|
||||||
self.current_SE.cct.key,
|
self.current_SE.cct.key,
|
||||||
data,
|
data,
|
||||||
self.current_SE.cct.iv)
|
self.current_SE.cct.iv)
|
||||||
@@ -938,7 +944,7 @@ class Secure_Messaging(object):
|
|||||||
if algo == None:
|
if algo == None:
|
||||||
raise SwError(SW["ERR_CONDITIONNOTSATISFIED"])
|
raise SwError(SW["ERR_CONDITIONNOTSATISFIED"])
|
||||||
try:
|
try:
|
||||||
hash = virtualsmartcard.CryptoUtils.hash(algo, data)
|
hash = vsCrypto.hash(algo, data)
|
||||||
except ValueError: #FIXME: Type of error
|
except ValueError: #FIXME: Type of error
|
||||||
raise SwError(SW["ERR_SECMESSNOTSUPPORTED"])
|
raise SwError(SW["ERR_SECMESSNOTSUPPORTED"])
|
||||||
|
|
||||||
@@ -967,7 +973,7 @@ class Secure_Messaging(object):
|
|||||||
if plain == "" or cct == "":
|
if plain == "" or cct == "":
|
||||||
raise SwError(SW["ERR_SECMESSOBJECTSMISSING"])
|
raise SwError(SW["ERR_SECMESSOBJECTSMISSING"])
|
||||||
else:
|
else:
|
||||||
my_cct = virtualsmartcard.CryptoUtils.crypto_checksum(algo, key, plain, iv)
|
my_cct = vsCrypto.crypto_checksum(algo, key, plain, iv)
|
||||||
if my_cct == cct:
|
if my_cct == cct:
|
||||||
return SW["NORMAL"], ""
|
return SW["NORMAL"], ""
|
||||||
else:
|
else:
|
||||||
@@ -1022,8 +1028,8 @@ class Secure_Messaging(object):
|
|||||||
if key == None or algo == None:
|
if key == None or algo == None:
|
||||||
return SW["ERR_CONDITIONNOTSATISFIED"], ""
|
return SW["ERR_CONDITIONNOTSATISFIED"], ""
|
||||||
else:
|
else:
|
||||||
padded = virtualsmartcard.CryptoUtils.append_padding(algo, data)
|
padded = vsCrypto.append_padding(algo, data)
|
||||||
crypted = virtualsmartcard.CryptoUtils.cipher(True, algo, key, padded, self.current_SE.ct.iv)
|
crypted = vsCrypto.cipher(True, algo, key, padded, self.current_SE.ct.iv)
|
||||||
return SW["NORMAL"], crypted
|
return SW["NORMAL"], crypted
|
||||||
|
|
||||||
def decipher(self, p1, p2, data):
|
def decipher(self, p1, p2, data):
|
||||||
@@ -1037,7 +1043,7 @@ class Secure_Messaging(object):
|
|||||||
if key == None or algo == None:
|
if key == None or algo == None:
|
||||||
return SW["ERR_CONDITIONNOTSATISFIED"], ""
|
return SW["ERR_CONDITIONNOTSATISFIED"], ""
|
||||||
else:
|
else:
|
||||||
plain = virtualsmartcard.CryptoUtils.cipher(False, algo, key, data, self.current_SE.ct.iv)
|
plain = vsCrypto.cipher(False, algo, key, data, self.current_SE.ct.iv)
|
||||||
return SW["NORMAL"], plain
|
return SW["NORMAL"], plain
|
||||||
|
|
||||||
def generate_public_key_pair(self, p1, p2, data):
|
def generate_public_key_pair(self, p1, p2, data):
|
||||||
@@ -1161,9 +1167,9 @@ class ePass_SM(Secure_Messaging):
|
|||||||
if p1 != 0x8E or p2 != 0x80:
|
if p1 != 0x8E or p2 != 0x80:
|
||||||
raise SwError(SW["ERR_INCORRECTP1P2"])
|
raise SwError(SW["ERR_INCORRECTP1P2"])
|
||||||
|
|
||||||
#checksum = virtualsmartcard.CryptoUtils.calculate_MAC(self.current_SE.cct.key,data,self.current_SE_SE.cct.iv)
|
#checksum = vsCrypto.calculate_MAC(self.current_SE.cct.key,data,self.current_SE_SE.cct.iv)
|
||||||
self.ssc += 1
|
self.ssc += 1
|
||||||
checksum = virtualsmartcard.CryptoUtils.crypto_checksum(self.current_SE.cct.algorithm,
|
checksum = vsCrypto.crypto_checksum(self.current_SE.cct.algorithm,
|
||||||
self.current_SE.cct.key,
|
self.current_SE.cct.key,
|
||||||
data,
|
data,
|
||||||
self.current_SE.cct.iv,
|
self.current_SE.cct.iv,
|
||||||
@@ -1190,7 +1196,7 @@ if __name__ == "__main__":
|
|||||||
print "Counter = " + str(MyCard.counter)
|
print "Counter = " + str(MyCard.counter)
|
||||||
sw, challenge = MyCard.get_challenge(0x00, 0x00, "")
|
sw, challenge = MyCard.get_challenge(0x00, 0x00, "")
|
||||||
print "Before encryption: " + challenge
|
print "Before encryption: " + challenge
|
||||||
padded = virtualsmartcard.CryptoUtils.append_padding("DES3-ECB", challenge)
|
padded = vsCrypto.append_padding("DES3-ECB", challenge)
|
||||||
sw, result = MyCard.internal_authenticate(0x00, 0x00, padded)
|
sw, result = MyCard.internal_authenticate(0x00, 0x00, padded)
|
||||||
print "Internal Authenticate status code: %x" % sw
|
print "Internal Authenticate status code: %x" % sw
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user