-Fixed two unhandled exceptions
-Removed some trailing whitespaces git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@164 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
@@ -1,18 +1,18 @@
|
|||||||
#
|
#
|
||||||
# Copyright (C) 2009 Dominik Oepen
|
# Copyright (C) 2009 Dominik Oepen
|
||||||
#
|
#
|
||||||
# This file is part of virtualsmartcard.
|
# This file is part of virtualsmartcard.
|
||||||
#
|
#
|
||||||
# virtualsmartcard is free software: you can redistribute it and/or modify it
|
# virtualsmartcard is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU General Public License as published by the Free
|
# under the terms of the GNU General Public License as published by the Free
|
||||||
# Software Foundation, either version 3 of the License, or (at your option) any
|
# Software Foundation, either version 3 of the License, or (at your option) any
|
||||||
# later version.
|
# later version.
|
||||||
#
|
#
|
||||||
# virtualsmartcard is distributed in the hope that it will be useful, but
|
# virtualsmartcard is distributed in the hope that it will be useful, but
|
||||||
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
# more details.
|
# more details.
|
||||||
#
|
#
|
||||||
# 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/>.
|
||||||
#
|
#
|
||||||
@@ -26,12 +26,12 @@ from Crypto.Cipher import DES3
|
|||||||
from ConstantDefinitions import *
|
from ConstantDefinitions import *
|
||||||
from SEutils import ControlReferenceTemplate as CRT
|
from SEutils import ControlReferenceTemplate as CRT
|
||||||
|
|
||||||
def get_referenced_cipher(p1):
|
def get_referenced_cipher(p1):
|
||||||
"""
|
"""
|
||||||
P1 defines the algorithm and mode to use. We dispatch it and return a
|
P1 defines the algorithm and mode to use. We dispatch it and return a
|
||||||
string that is understood by CryptoUtils.py functions
|
string that is understood by CryptoUtils.py functions
|
||||||
"""
|
"""
|
||||||
|
|
||||||
ciphertable = {
|
ciphertable = {
|
||||||
0x00: "DES3-ECB",
|
0x00: "DES3-ECB",
|
||||||
0x01: "DES3-ECB",
|
0x01: "DES3-ECB",
|
||||||
@@ -41,18 +41,18 @@ def get_referenced_cipher(p1):
|
|||||||
0x05: "AES-ECB",
|
0x05: "AES-ECB",
|
||||||
0x06: "AES-CBC",
|
0x06: "AES-CBC",
|
||||||
0x07: "RSA",
|
0x07: "RSA",
|
||||||
0x08: "DSA"
|
0x08: "DSA"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ciphertable.has_key(p1)):
|
if (ciphertable.has_key(p1)):
|
||||||
return ciphertable[p1]
|
return ciphertable[p1]
|
||||||
else:
|
else:
|
||||||
raise SwError(SW["ERR_INCORRECTP1P2"])
|
raise SwError(SW["ERR_INCORRECTP1P2"])
|
||||||
|
|
||||||
class CardContainer:
|
class CardContainer:
|
||||||
"""
|
"""
|
||||||
This class is used to store the data needed by the SAM
|
This class is used to store the data needed by the SAM
|
||||||
It includes the PIN, the master key of the SAM and a
|
It includes the PIN, the master key of the SAM and a
|
||||||
hashmap containing all the keys used by the file encryption
|
hashmap containing all the keys used by the file encryption
|
||||||
system. The keys in the hashmap are indexed via the path
|
system. The keys in the hashmap are indexed via the path
|
||||||
to the corresponding container.
|
to the corresponding container.
|
||||||
@@ -985,7 +985,7 @@ class Secure_Messaging(object):
|
|||||||
raise SwError(SW["ERR_SECMESSNOTSUPPORTED"])
|
raise SwError(SW["ERR_SECMESSNOTSUPPORTED"])
|
||||||
|
|
||||||
return SW["NORMAL"], hash
|
return SW["NORMAL"], hash
|
||||||
|
|
||||||
def verify_cryptographic_checksum(self,p1,p2,data):
|
def verify_cryptographic_checksum(self,p1,p2,data):
|
||||||
"""
|
"""
|
||||||
Verify the cryptographic checksum contained in the data field. Data field must contain
|
Verify the cryptographic checksum contained in the data field. Data field must contain
|
||||||
@@ -993,13 +993,13 @@ class Secure_Messaging(object):
|
|||||||
"""
|
"""
|
||||||
plain = ""
|
plain = ""
|
||||||
cct = ""
|
cct = ""
|
||||||
|
|
||||||
algo = self.current_SE.cct.algo
|
algo = self.current_SE.cct.algo
|
||||||
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:
|
||||||
raise SwError(SW["ERR_CONDITIONNOTSATISFIED"])
|
raise SwError(SW["ERR_CONDITIONNOTSATISFIED"])
|
||||||
|
|
||||||
structure = TLVutils.unpack(config)
|
structure = TLVutils.unpack(config)
|
||||||
for tag, length, value in structure:
|
for tag, length, value in structure:
|
||||||
if tag == 0x80:
|
if tag == 0x80:
|
||||||
@@ -1014,19 +1014,19 @@ class Secure_Messaging(object):
|
|||||||
return SW["NORMAL"], ""
|
return SW["NORMAL"], ""
|
||||||
else:
|
else:
|
||||||
raise SwError["ERR_SECMESSOBJECTSINCORRECT"]
|
raise SwError["ERR_SECMESSOBJECTSINCORRECT"]
|
||||||
|
|
||||||
def verify_digital_signature(self,p1,p2,data):
|
def verify_digital_signature(self,p1,p2,data):
|
||||||
"""
|
"""
|
||||||
Verify the digital signature contained in the data field. Data must contain
|
Verify the digital signature contained in the data field. Data must contain
|
||||||
a data to sign (tag 0x9A, 0xAC or 0xBC) and a digital signature (0x9E)
|
a data to sign (tag 0x9A, 0xAC or 0xBC) and a digital signature (0x9E)
|
||||||
"""
|
"""
|
||||||
key = self.current_SE.dst.key
|
key = self.current_SE.dst.key
|
||||||
to_sign = ""
|
to_sign = ""
|
||||||
signature = ""
|
signature = ""
|
||||||
|
|
||||||
if key == None:
|
if key == None:
|
||||||
raise SwError(SW["ERR_CONDITIONNOTSATISFIED"])
|
raise SwError(SW["ERR_CONDITIONNOTSATISFIED"])
|
||||||
|
|
||||||
structure = TLVutils.unpack(config)
|
structure = TLVutils.unpack(config)
|
||||||
for tag, length, value in structure:
|
for tag, length, value in structure:
|
||||||
if tag == 0x9E:
|
if tag == 0x9E:
|
||||||
@@ -1037,24 +1037,22 @@ class Secure_Messaging(object):
|
|||||||
pass
|
pass
|
||||||
elif tag == 0xBC:
|
elif tag == 0xBC:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if to_sign == "" or signature == "":
|
if to_sign == "" or signature == "":
|
||||||
raise SwError(SW["ERR_SECMESSOBJECTSMISSING"])
|
raise SwError(SW["ERR_SECMESSOBJECTSMISSING"])
|
||||||
|
|
||||||
try:
|
my_signature = key.sign(value)
|
||||||
my_signature = key.sign(value)
|
|
||||||
except error, e: #FIXME: Foobar
|
|
||||||
pass
|
|
||||||
if my_signature == signature:
|
if my_signature == signature:
|
||||||
return SW["NORMAL"], ""
|
return SW["NORMAL"], ""
|
||||||
else:
|
else:
|
||||||
raise SwError(["ERR_SECMESSOBJECTSINCORRECT"])
|
raise SwError(["ERR_SECMESSOBJECTSINCORRECT"])
|
||||||
|
|
||||||
def verify_certificate(self,p1,p2,data):
|
def verify_certificate(self,p1,p2,data):
|
||||||
if p1 != 0x00 or p2 not in (0x92,0xAE,0xBE):
|
if p1 != 0x00 or p2 not in (0x92,0xAE,0xBE):
|
||||||
raise SwError(SW["ERR_INCORRECTP1P2"])
|
raise SwError(SW["ERR_INCORRECTP1P2"])
|
||||||
pass
|
else:
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
def encipher(self,p1,p2,data):
|
def encipher(self,p1,p2,data):
|
||||||
"""
|
"""
|
||||||
Encipher data using key, algorithm, IV and Padding specified
|
Encipher data using key, algorithm, IV and Padding specified
|
||||||
@@ -1069,7 +1067,7 @@ class Secure_Messaging(object):
|
|||||||
padded = CryptoUtils.append_padding(algo, data)
|
padded = CryptoUtils.append_padding(algo, data)
|
||||||
crypted = CryptoUtils.cipher(True, algo, key, padded, self.current_SE.ct.iv)
|
crypted = CryptoUtils.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):
|
||||||
"""
|
"""
|
||||||
Decipher data using key, algorithm, IV and Padding specified
|
Decipher data using key, algorithm, IV and Padding specified
|
||||||
@@ -1082,8 +1080,8 @@ class Secure_Messaging(object):
|
|||||||
return SW["ERR_CONDITIONNOTSATISFIED"], ""
|
return SW["ERR_CONDITIONNOTSATISFIED"], ""
|
||||||
else:
|
else:
|
||||||
plain = CryptoUtils.cipher(False,algo,key,data,self.current_SE.ct.iv)
|
plain = CryptoUtils.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):
|
||||||
"""
|
"""
|
||||||
Generate a new public-private key pair.
|
Generate a new public-private key pair.
|
||||||
@@ -1091,19 +1089,19 @@ class Secure_Messaging(object):
|
|||||||
from Crypto.PublicKey import RSA, DSA
|
from Crypto.PublicKey import RSA, DSA
|
||||||
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.algo #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:
|
||||||
raise SwError(SW["ERR_CONDITIONNOTSATISFIED"])
|
raise SwError(SW["ERR_CONDITIONNOTSATISFIED"])
|
||||||
|
|
||||||
if p1 & 0x01 == 0x00: #Generate key
|
if p1 & 0x01 == 0x00: #Generate key
|
||||||
PublicKey = c_class.generate(self.CAPDU_SE.dst.keylength,rnd.get_bytes)
|
PublicKey = c_class.generate(self.CAPDU_SE.dst.keylength,rnd.get_bytes)
|
||||||
self.CAPDU_SE.dst.key = PublicKey
|
self.CAPDU_SE.dst.key = PublicKey
|
||||||
else:
|
else:
|
||||||
pass #Read key
|
pass #Read key
|
||||||
|
|
||||||
#Encode keys
|
#Encode keys
|
||||||
if cipher == "RSA":
|
if cipher == "RSA":
|
||||||
#Public key
|
#Public key
|
||||||
@@ -1123,38 +1121,38 @@ class Secure_Messaging(object):
|
|||||||
#Private key
|
#Private key
|
||||||
x = str(PublicKey.__getstate__()['x'])
|
x = str(PublicKey.__getstate__()['x'])
|
||||||
#Add more algorithms here
|
#Add more algorithms here
|
||||||
|
|
||||||
if p1 & 0x02 == 0x02:
|
if p1 & 0x02 == 0x02:
|
||||||
return SW["NORMAL"], result
|
return SW["NORMAL"], result
|
||||||
else:
|
else:
|
||||||
#FIXME: Where to put the keys?
|
#FIXME: Where to put the keys?
|
||||||
return SW["NORMAL"], ""
|
return SW["NORMAL"], ""
|
||||||
|
|
||||||
#}}}
|
#}}}
|
||||||
class CryptoflexSM(Secure_Messaging):
|
class CryptoflexSM(Secure_Messaging):
|
||||||
def __init__(self,mf):
|
def __init__(self,mf):
|
||||||
Secure_Messaging.__init__(self,mf) #Does Cryptoflex need its own SE?
|
Secure_Messaging.__init__(self,mf) #Does Cryptoflex need its own SE?
|
||||||
|
|
||||||
def generate_public_key_pair(self,p1,p2,data):
|
def generate_public_key_pair(self,p1,p2,data):
|
||||||
"""
|
"""
|
||||||
In the Cryptoflex card this command only supports RSA keys.
|
In the Cryptoflex card this command only supports RSA keys.
|
||||||
|
|
||||||
@param data: Contains the public exponent used for key generation
|
@param data: Contains the public exponent used for key generation
|
||||||
@param p1: The keynumber. Can be used later to refer to the generated key
|
@param p1: The keynumber. Can be used later to refer to the generated key
|
||||||
@param p2: Used to specifiy the keylength. The mapping is: 0x40 => 256 Bit, 0x60 => 512 Bit, 0x80 => 1024
|
@param p2: Used to specifiy the keylength. The mapping is: 0x40 => 256 Bit, 0x60 => 512 Bit, 0x80 => 1024
|
||||||
"""
|
"""
|
||||||
from Crypto.PublicKey import RSA
|
from Crypto.PublicKey import RSA
|
||||||
from Crypto.Util.randpool import RandomPool
|
from Crypto.Util.randpool import RandomPool
|
||||||
|
|
||||||
keynumber = p1 #TODO: Check if key exists
|
keynumber = p1 #TODO: Check if key exists
|
||||||
|
|
||||||
keylength_dict = {0x40: 256, 0x60: 512, 0x80: 1024}
|
keylength_dict = {0x40: 256, 0x60: 512, 0x80: 1024}
|
||||||
|
|
||||||
if not keylength_dict.has_key(p2):
|
if not keylength_dict.has_key(p2):
|
||||||
raise SwError(SW["ERR_INCORRECTP1P2"])
|
raise SwError(SW["ERR_INCORRECTP1P2"])
|
||||||
else:
|
else:
|
||||||
keylength = keylength_dict[p2]
|
keylength = keylength_dict[p2]
|
||||||
|
|
||||||
rnd = RandomPool()
|
rnd = RandomPool()
|
||||||
PublicKey = RSA.generate(keylength,rnd.get_bytes)
|
PublicKey = RSA.generate(keylength,rnd.get_bytes)
|
||||||
self.CAPDU_SE.dst.key = PublicKey
|
self.CAPDU_SE.dst.key = PublicKey
|
||||||
@@ -1162,7 +1160,7 @@ class CryptoflexSM(Secure_Messaging):
|
|||||||
e_in = struct.unpack("<i",data)
|
e_in = struct.unpack("<i",data)
|
||||||
if e_in[0] != 65537:
|
if e_in[0] != 65537:
|
||||||
print "Warning: Exponents different from 65537 are ignored! The Exponent given is %i" % e_in[0]
|
print "Warning: Exponents different from 65537 are ignored! The Exponent given is %i" % e_in[0]
|
||||||
|
|
||||||
#Encode Public key
|
#Encode Public key
|
||||||
n = PublicKey.__getstate__()['n']
|
n = PublicKey.__getstate__()['n']
|
||||||
n_str = inttostring(n)
|
n_str = inttostring(n)
|
||||||
@@ -1173,8 +1171,8 @@ class CryptoflexSM(Secure_Messaging):
|
|||||||
padd = 187 * '\x30' #We don't have chinese remainder theorem components, so we need to inject padding
|
padd = 187 * '\x30' #We don't have chinese remainder theorem components, so we need to inject padding
|
||||||
pk_n = TLVutils.bertlv_pack(((0x81,len(n_str),n_str),(0x01,len(padd),padd),(0x82,len(e_str),e_str)))
|
pk_n = TLVutils.bertlv_pack(((0x81,len(n_str),n_str),(0x01,len(padd),padd),(0x82,len(e_str),e_str)))
|
||||||
#Private key
|
#Private key
|
||||||
d = PublicKey.__getstate__()['d']
|
d = PublicKey.__getstate__()['d']
|
||||||
|
|
||||||
#Write result to FID 10 12 EF-PUB-KEY
|
#Write result to FID 10 12 EF-PUB-KEY
|
||||||
df = self.mf.currentDF()
|
df = self.mf.currentDF()
|
||||||
file = df.select("fid", 0x1012)
|
file = df.select("fid", 0x1012)
|
||||||
@@ -1205,28 +1203,28 @@ 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.algo,
|
||||||
self.CAPDU_SE.cct.key,
|
self.CAPDU_SE.cct.key,
|
||||||
data,
|
data,
|
||||||
self.CAPDU_SE.cct.iv,
|
self.CAPDU_SE.cct.iv,
|
||||||
self.ssc)
|
self.ssc)
|
||||||
|
|
||||||
return SW["NORMAL"], checksum
|
return SW["NORMAL"], checksum
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
"""
|
"""
|
||||||
Unit test:
|
Unit test:
|
||||||
"""
|
"""
|
||||||
|
|
||||||
password = "DUMMYKEYDUMMYKEY"
|
password = "DUMMYKEYDUMMYKEY"
|
||||||
#generate_SAM_config("1234567890", "1234", "keykeykeykeykeyk", path, password)
|
#generate_SAM_config("1234567890", "1234", "keykeykeykeykeyk", path, password)
|
||||||
|
|
||||||
MyCard = SAM("1234", "1234567890")
|
MyCard = SAM("1234", "1234567890")
|
||||||
try:
|
try:
|
||||||
print MyCard.verify(0x00, 0x00, "5678")
|
print MyCard.verify(0x00, 0x00, "5678")
|
||||||
except SwError, e:
|
except SwError, e:
|
||||||
print e.message
|
print e.message
|
||||||
|
|
||||||
print "Counter = " + str(MyCard.counter)
|
print "Counter = " + str(MyCard.counter)
|
||||||
print MyCard.verify(0x00, 0x00, "1234")
|
print MyCard.verify(0x00, 0x00, "1234")
|
||||||
print "Counter = " + str(MyCard.counter)
|
print "Counter = " + str(MyCard.counter)
|
||||||
@@ -1235,7 +1233,7 @@ if __name__ == "__main__":
|
|||||||
padded = CryptoUtils.append_padding("DES3-ECB", challenge)
|
padded = CryptoUtils.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
|
||||||
|
|
||||||
try:
|
try:
|
||||||
sw, res = MyCard.external_authenticate(0x00, 0x00, result)
|
sw, res = MyCard.external_authenticate(0x00, 0x00, result)
|
||||||
except SwError, e:
|
except SwError, e:
|
||||||
|
|||||||
Reference in New Issue
Block a user