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:
oepen
2011-07-29 16:32:58 +00:00
parent 14c6690eb7
commit 039da1c64a

View File

@@ -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