-pycrypto should now only be imported if an instance of the SAM class is created

-Removed deprecated unit tests
-fixed some bugs caused by incorrect naming


git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@320 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
oepen
2010-10-11 15:53:16 +00:00
parent 9517bcd8fa
commit 690caf4060

View File

@@ -16,13 +16,13 @@
# You should have received a copy of the GNU General Public License along with # You should have received a copy of the GNU General Public License along with
# virtualsmartcard. If not, see <http://www.gnu.org/licenses/>. # virtualsmartcard. If not, see <http://www.gnu.org/licenses/>.
# #
import SmartcardFilesystem, CryptoUtils, TLVutils import SmartcardFilesystem, TLVutils #,CryptoUtils
import random, re, struct, Crypto import random, re, struct#, Crypto
import hashlib import hashlib
from SWutils import SwError, SW, SW_MESSAGES from SWutils import SwError, SW, SW_MESSAGES
from pickle import dumps, loads from pickle import dumps, loads
from utils import inttostring, stringtoint, hexdump, C_APDU, R_APDU from utils import inttostring, stringtoint, hexdump, C_APDU, R_APDU
from Crypto.Cipher import DES3 #from Crypto.Cipher import DES3
from ConstantDefinitions import * from ConstantDefinitions import *
from SEutils import ControlReferenceTemplate as CRT from SEutils import ControlReferenceTemplate as CRT
@@ -60,6 +60,7 @@ 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
import CryptoUtils
self.cardNumber = cardNumber self.cardNumber = cardNumber
self.PIN = PIN self.PIN = PIN
@@ -123,6 +124,7 @@ class CardContainer:
class SAM(object): class SAM(object):
def __init__(self, PIN, cardNumber, mf=None): def __init__(self, PIN, cardNumber, mf=None):
import CryptoUtils
self.CardContainer = CardContainer(PIN, cardNumber) self.CardContainer = CardContainer(PIN, cardNumber)
#self.CardContainer.loadConfiguration(path, password) #self.CardContainer.loadConfiguration(path, password)
@@ -425,10 +427,10 @@ class PassportSAM(SAM):
#SAM.__init__(self, path, key,None) #SAM.__init__(self, path, key,None)
SAM.__init__(self, None, None, mf) SAM.__init__(self, None, None, mf)
self.SM_handler = ePass_SM(mf, None, None, None) self.SM_handler = ePass_SM(mf, None, None, None)
self.SM_handler.CAPDU_SE.cct.algo = "CC" self.SM_handler.CAPDU_SE.cct.algorithm = "CC"
self.SM_handler.RAPDU_SE.cct.algo = "CC" self.SM_handler.RAPDU_SE.cct.algorithm = "CC"
self.SM_handler.CAPDU_SE.ct.algo = "DES3-CBC" self.SM_handler.CAPDU_SE.ct.algorithm = "DES3-CBC"
self.SM_handler.RAPDU_SE.ct.algo = "DES3-CBC" self.SM_handler.RAPDU_SE.ct.algorithm = "DES3-CBC"
def __computeKeys(self): def __computeKeys(self):
"""Computes the keys depending on the machine readable """Computes the keys depending on the machine readable
@@ -490,10 +492,10 @@ class PassportSAM(SAM):
self.SM_handler.RAPDU_SE.ct.key = self.KSenc self.SM_handler.RAPDU_SE.ct.key = self.KSenc
self.SM_handler.RAPDU_SE.cct.key = self.KSmac self.SM_handler.RAPDU_SE.cct.key = self.KSmac
self.SM_handler.ssc = stringtoint(rnd_icc[-4:] + rnd_ifd[-4:]) self.SM_handler.ssc = stringtoint(rnd_icc[-4:] + rnd_ifd[-4:])
self.SM_handler.CAPDU_SE.ct.algo = "DES3-CBC" self.SM_handler.CAPDU_SE.ct.algorithm = "DES3-CBC"
self.SM_handler.RAPDU_SE.ct.algo = "DES3-CBC" self.SM_handler.RAPDU_SE.ct.algorithm = "DES3-CBC"
self.SM_handler.CAPDU_SE.cct.algo = "CC" self.SM_handler.CAPDU_SE.cct.algorithm = "CC"
self.SM_handler.RAPDU_SE.cct.algo = "CC" self.SM_handler.RAPDU_SE.cct.algorithm = "CC"
return SW["NORMAL"], Eicc + Micc return SW["NORMAL"], Eicc + Micc
def _mac(self, key, data, ssc = None, dopad=True): def _mac(self, key, data, ssc = None, dopad=True):
@@ -575,7 +577,10 @@ class Security_Environment(object):
raise ValueError raise ValueError
class Secure_Messaging(object): class Secure_Messaging(object):
def __init__(self,MF,CAPDU_SE=None,RAPDU_SE=None): def __init__(self,MF,CAPDU_SE=None,RAPDU_SE=None):
import CryptoUtils
self.mf = MF self.mf = MF
if not CAPDU_SE: if not CAPDU_SE:
self.CAPDU_SE = Security_Environment() self.CAPDU_SE = Security_Environment()
@@ -784,7 +789,7 @@ 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 = CryptoUtils.strip_padding(self.CAPDU_SE.ct.algo,plain,padding_indicator) plain = CryptoUtils.strip_padding(self.CAPDU_SE.ct.algorithm,plain,padding_indicator)
return_data.append(plain) return_data.append(plain)
#SM data objects for authentication #SM data objects for authentication
@@ -872,15 +877,15 @@ class Secure_Messaging(object):
return_data += encrypted_tlv return_data += encrypted_tlv
if sw == SW["NORMAL"]: if sw == SW["NORMAL"]:
if self.CAPDU_SE.cct.algo == None: if self.CAPDU_SE.cct.algorithm == None:
raise SwError(SW["CONDITIONSNOTSATISFIED"]) raise SwError(SW["CONDITIONSNOTSATISFIED"])
elif self.CAPDU_SE.cct.algo == "CCT": elif self.CAPDU_SE.cct.algorithm == "CCT":
tag = SM_Class["CHECKSUM"] tag = SM_Class["CHECKSUM"]
to_auth = CryptoUtils.append_padding("DES-ECB", return_data) to_auth = CryptoUtils.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)])
elif self.CAPDU_SE.cct.algo == "SIGNATURE": elif self.CAPDU_SE.cct.algorithm == "SIGNATURE":
tag = SM_Class["DIGITAL_SIGNATURE"] tag = SM_Class["DIGITAL_SIGNATURE"]
hash = self.hash(0x90, 0x80, return_data) hash = self.hash(0x90, 0x80, return_data)
sw, auth = self.compute_digital_signature(0x9E, 0x9A, hash) sw, auth = self.compute_digital_signature(0x9E, 0x9A, hash)
@@ -932,10 +937,10 @@ class Secure_Messaging(object):
""" """
if p1 != 0x8E or p2 != 0x80: if p1 != 0x8E or p2 != 0x80:
raise SwError(SW["ERR_INCORRECTP1P2"]) raise SwError(SW["ERR_INCORRECTP1P2"])
if self.CAPDU_SE.cct.algo == None or self.current_SE.cct.key == None: if self.CAPDU_SE.cct.algorithm == None or self.current_SE.cct.key == None:
raise SWError(SE["ERR_CONDITIONNOTSATISFIED"]) raise SWError(SE["ERR_CONDITIONNOTSATISFIED"])
checksum = CryptoUtils.crypto_checksum(self.current_SE.cct.algo, checksum = CryptoUtils.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)
@@ -976,7 +981,7 @@ class Secure_Messaging(object):
""" """
if p1 != 0x90 or not p2 in (0x80,0xA0): if p1 != 0x90 or not p2 in (0x80,0xA0):
raise SwError(SW["ERR_INCORRECTP1P2"]) raise SwError(SW["ERR_INCORRECTP1P2"])
algo = self.current_SE.ht.algo algo = self.current_SE.ht.algorithm
if algo == None: if algo == None:
raise SwError(SW["ERR_CONDITIONNOTSATISFIED"]) raise SwError(SW["ERR_CONDITIONNOTSATISFIED"])
try: try:
@@ -994,7 +999,7 @@ class Secure_Messaging(object):
plain = "" plain = ""
cct = "" cct = ""
algo = self.current_SE.cct.algo algo = self.current_SE.cct.algorithm
key = self.current_SE.cct.key key = self.current_SE.cct.key
iv = self.current_SE.cct.iv iv = self.current_SE.cct.iv
if algo == None or key == None: if algo == None or key == None:
@@ -1059,7 +1064,7 @@ class Secure_Messaging(object):
by the current Security environment. by the current Security environment.
Return raw data (no TLV coding). Return raw data (no TLV coding).
""" """
algo = self.current_SE.ct.algo algo = self.current_SE.ct.algorithm
key = self.current_SE.ct.key key = self.current_SE.ct.key
if key == None or algo == None: if key == None or algo == None:
return SW["ERR_CONDITIONNOTSATISFIED"], "" return SW["ERR_CONDITIONNOTSATISFIED"], ""
@@ -1074,7 +1079,7 @@ class Secure_Messaging(object):
by the current Security environment. by the current Security environment.
Return raw data (no TLV coding). Padding is not removed!!! Return raw data (no TLV coding). Padding is not removed!!!
""" """
algo = self.current_SE.ct.algo algo = self.current_SE.ct.algorithm
key = self.current_SE.ct.key key = self.current_SE.ct.key
if key == None or algo == None: if key == None or algo == None:
return SW["ERR_CONDITIONNOTSATISFIED"], "" return SW["ERR_CONDITIONNOTSATISFIED"], ""
@@ -1090,7 +1095,7 @@ class Secure_Messaging(object):
from Crypto.Util.randpool import RandomPool from Crypto.Util.randpool import RandomPool
rnd = RandomPool() rnd = RandomPool()
cipher = self.CAPDU_SE.ct.algo #FIXME: Current SE? cipher = self.CAPDU_SE.ct.algorithm #FIXME: Current SE?
c_class = locals().get(cipher, None) c_class = locals().get(cipher, None)
if c_class is None: if c_class is None:
@@ -1203,7 +1208,7 @@ class ePass_SM(Secure_Messaging):
#checksum = CryptoUtils.calculate_MAC(self.CAPDU_SE.cct.key,data,self.CAPDU_SE.cct.iv) #checksum = CryptoUtils.calculate_MAC(self.CAPDU_SE.cct.key,data,self.CAPDU_SE.cct.iv)
self.ssc += 1 self.ssc += 1
checksum = CryptoUtils.crypto_checksum(self.CAPDU_SE.cct.algo, checksum = CryptoUtils.crypto_checksum(self.CAPDU_SE.cct.algorithm,
self.CAPDU_SE.cct.key, self.CAPDU_SE.cct.key,
data, data,
self.CAPDU_SE.cct.iv, self.CAPDU_SE.cct.iv,
@@ -1216,6 +1221,8 @@ if __name__ == "__main__":
Unit test: Unit test:
""" """
import CryptoUtils
password = "DUMMYKEYDUMMYKEY" password = "DUMMYKEYDUMMYKEY"
#generate_SAM_config("1234567890", "1234", "keykeykeykeykeyk", path, password) #generate_SAM_config("1234567890", "1234", "keykeykeykeykeyk", path, password)
@@ -1241,21 +1248,21 @@ if __name__ == "__main__":
sw = e.sw sw = e.sw
print "Decryption Status code: %x" % sw print "Decryption Status code: %x" % sw
SM = Secure_Messaging(None) #SM = Secure_Messaging(None)
testvektor = "foobar" #testvektor = "foobar"
print "Testvektor = %s" % testvektor #print "Testvektor = %s" % testvektor
sw, hash = SM.hash(0x90,0x80,testvektor) #sw, hash = SM.hash(0x90,0x80,testvektor)
print "SW after hashing = %s" % sw #print "SW after hashing = %s" % sw
print "Hash = %s" % hash #print "Hash = %s" % hash
sw, crypted = SM.encipher(0x00, 0x00, testvektor) #sw, crypted = SM.encipher(0x00, 0x00, testvektor)
print "SW after encryption = %s" % sw #print "SW after encryption = %s" % sw
sw, plain = SM.decipher(0x00, 0x00, crypted) #sw, plain = SM.decipher(0x00, 0x00, crypted)
print "SW after encryption = %s" % sw #print "SW after encryption = %s" % sw
print "Testvektor after en- and deciphering: %s" % plain #print "Testvektor after en- and deciphering: %s" % plain
sw, pk = SM.generate_public_key_pair(0x02, 0x00, "") #sw, pk = SM.generate_public_key_pair(0x02, 0x00, "")
print "SW after keygen = %s" % sw #print "SW after keygen = %s" % sw
print "Public Key = %s" % pk #print "Public Key = %s" % pk
CF = CryptoflexSM(None) #CF = CryptoflexSM(None)
print CF.generate_public_key_pair(0x00, 0x80, "\x01\x00\x01\x00") #print CF.generate_public_key_pair(0x00, 0x80, "\x01\x00\x01\x00")
print MyCard._read_FS_data(0x01, 16) #print MyCard._read_FS_data(0x01, 16)
print MyCard._get_referenced_key(0x01) #print MyCard._get_referenced_key(0x01)