Subroutines to parse_SM_CAPDU, protect_response and perform_security_operation
only return the resulting string and no longer status bytes This prevents overwriting of the statusbytes when applying SM. Errors should be returned via `raise SwError` git-svn-id: https://vsmartcard.svn.sourceforge.net/svnroot/vsmartcard@703 96b47cad-a561-4643-ad3b-153ac7d7599c
This commit is contained in:
@@ -358,7 +358,7 @@ class Security_Environment(object):
|
|||||||
'80' to '8E' Proprietary
|
'80' to '8E' Proprietary
|
||||||
"""
|
"""
|
||||||
padding_indicator = stringtoint(value[0])
|
padding_indicator = stringtoint(value[0])
|
||||||
sw, plain = self.decipher(tag, 0x80, value[1:])
|
plain = self.decipher(tag, 0x80, value[1:])
|
||||||
plain = vsCrypto.strip_padding(self.ct.blocklength, plain,
|
plain = vsCrypto.strip_padding(self.ct.blocklength, plain,
|
||||||
padding_indicator)
|
padding_indicator)
|
||||||
return_data.append(plain)
|
return_data.append(plain)
|
||||||
@@ -366,18 +366,18 @@ class Security_Environment(object):
|
|||||||
#SM data objects for authentication
|
#SM data objects for authentication
|
||||||
if tag == SM_Class["CHECKSUM"]:
|
if tag == SM_Class["CHECKSUM"]:
|
||||||
auth = vsCrypto.append_padding(self.cct.blocklength, to_authenticate)
|
auth = vsCrypto.append_padding(self.cct.blocklength, to_authenticate)
|
||||||
sw, checksum = self.compute_cryptographic_checksum(0x8E,
|
checksum = self.compute_cryptographic_checksum(0x8E,
|
||||||
0x80,
|
0x80,
|
||||||
auth)
|
auth)
|
||||||
if checksum != value:
|
if checksum != value:
|
||||||
raise SwError(SW["ERR_SECMESSOBJECTSINCORRECT"])
|
raise SwError(SW["ERR_SECMESSOBJECTSINCORRECT"])
|
||||||
elif tag == SM_Class["DIGITAL_SIGNATURE"]:
|
elif tag == SM_Class["DIGITAL_SIGNATURE"]:
|
||||||
auth = to_authenticate #FIXME: Need padding?
|
auth = to_authenticate #FIXME: Need padding?
|
||||||
sw, signature = self.compute_digital_signature(0x9E, 0x9A, auth)
|
signature = self.compute_digital_signature(0x9E, 0x9A, auth)
|
||||||
if signature != value:
|
if signature != value:
|
||||||
raise SwError(SW["ERR_SECMESSOBJECTSINCORRECT"])
|
raise SwError(SW["ERR_SECMESSOBJECTSINCORRECT"])
|
||||||
elif tag in (SM_Class["HASH_CODE"], SM_Class["HASH_CODE_ODD"]):
|
elif tag in (SM_Class["HASH_CODE"], SM_Class["HASH_CODE_ODD"]):
|
||||||
sw, hash = self.hash(p1, p2, to_authenticate)
|
hash = self.hash(p1, p2, to_authenticate)
|
||||||
if hash != value:
|
if hash != value:
|
||||||
raise SwError(SW["ERR_SECMESSOBJECTSINCORRECT"])
|
raise SwError(SW["ERR_SECMESSOBJECTSINCORRECT"])
|
||||||
|
|
||||||
@@ -415,7 +415,7 @@ class Security_Environment(object):
|
|||||||
# return_data += tlv_sw
|
# return_data += tlv_sw
|
||||||
|
|
||||||
if result != "": # Encrypt the data included in the RAPDU
|
if result != "": # Encrypt the data included in the RAPDU
|
||||||
sw, encrypted = self.encipher(0x82, 0x80, result)
|
encrypted = self.encipher(0x82, 0x80, result)
|
||||||
encrypted = "\x01" + encrypted
|
encrypted = "\x01" + encrypted
|
||||||
encrypted_tlv = pack([(
|
encrypted_tlv = pack([(
|
||||||
SM_Class["CRYPTOGRAM_PADDING_INDICATOR_ODD"],
|
SM_Class["CRYPTOGRAM_PADDING_INDICATOR_ODD"],
|
||||||
@@ -429,17 +429,17 @@ class Security_Environment(object):
|
|||||||
elif self.cct.algorithm == "CC":
|
elif self.cct.algorithm == "CC":
|
||||||
tag = SM_Class["CHECKSUM"]
|
tag = SM_Class["CHECKSUM"]
|
||||||
padded = vsCrypto.append_padding(self.cct.blocklength, return_data)
|
padded = vsCrypto.append_padding(self.cct.blocklength, return_data)
|
||||||
sw, auth = self.compute_cryptographic_checksum(0x8E, 0x80, padded)
|
auth = self.compute_cryptographic_checksum(0x8E, 0x80, padded)
|
||||||
length = len(auth)
|
length = len(auth)
|
||||||
return_data += pack([(tag, length, auth)])
|
return_data += pack([(tag, length, auth)])
|
||||||
elif self.cct.algorithm == "SIGNATURE":
|
elif self.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)
|
auth = self.compute_digital_signature(0x9E, 0x9A, hash)
|
||||||
length = len(auth)
|
length = len(auth)
|
||||||
return_data += pack([(tag, length, auth)])
|
return_data += pack([(tag, length, auth)])
|
||||||
|
|
||||||
return SW["NORMAL"], return_data
|
return sw, return_data
|
||||||
|
|
||||||
#The following commands implement ISO 7816-8 {{{
|
#The following commands implement ISO 7816-8 {{{
|
||||||
def perform_security_operation(self, p1, p2, data):
|
def perform_security_operation(self, p1, p2, data):
|
||||||
@@ -458,24 +458,24 @@ class Security_Environment(object):
|
|||||||
raise SwError(SW["INCORRECTP1P2"])
|
raise SwError(SW["INCORRECTP1P2"])
|
||||||
|
|
||||||
if((p2 in (0x80, 0xA0)) and (p1 == 0x90)):
|
if((p2 in (0x80, 0xA0)) and (p1 == 0x90)):
|
||||||
sw, response_data = self.hash(p1, p2, data)
|
response_data = self.hash(p1, p2, data)
|
||||||
elif(p2 in (0x9A, 0xAC, 0xBC) and p1 == 0x9E):
|
elif(p2 in (0x9A, 0xAC, 0xBC) and p1 == 0x9E):
|
||||||
sw, response_data = self.compute_digital_signature(p1, p2, data)
|
response_data = self.compute_digital_signature(p1, p2, data)
|
||||||
elif(p2 == 0xA2 and p1 == 0x00):
|
elif(p2 == 0xA2 and p1 == 0x00):
|
||||||
sw, response_data = self.verify_cryptographic_checksum(p1, p2, data)
|
response_data = self.verify_cryptographic_checksum(p1, p2, data)
|
||||||
elif(p2 == 0xA8 and p1 == 0x00):
|
elif(p2 == 0xA8 and p1 == 0x00):
|
||||||
sw, response_data = self.verify_digital_signature(p1, p2, data)
|
response_data = self.verify_digital_signature(p1, p2, data)
|
||||||
elif(p2 in (0x92, 0xAE, 0xBE) and p1 == 0x00):
|
elif(p2 in (0x92, 0xAE, 0xBE) and p1 == 0x00):
|
||||||
sw, response_data = self.verify_certificate(p1, p2, data)
|
response_data = self.verify_certificate(p1, p2, data)
|
||||||
elif (p2 == 0x80 and p1 in (0x82, 0x84, 0x86)):
|
elif (p2 == 0x80 and p1 in (0x82, 0x84, 0x86)):
|
||||||
sw, response_data = self.encipher(p1, p2, data)
|
response_data = self.encipher(p1, p2, data)
|
||||||
elif (p2 in (0x82, 0x84, 0x86) and p1 == 0x80):
|
elif (p2 in (0x82, 0x84, 0x86) and p1 == 0x80):
|
||||||
sw, response_data = self.decipher(p1, p2, data)
|
response_data = self.decipher(p1, p2, data)
|
||||||
|
|
||||||
if p1 == 0x00:
|
if p1 == 0x00:
|
||||||
assert response_data == ""
|
assert response_data == ""
|
||||||
|
|
||||||
return sw, response_data
|
return SW["NORMAL"], response_data
|
||||||
|
|
||||||
|
|
||||||
def compute_cryptographic_checksum(self, p1, p2, data):
|
def compute_cryptographic_checksum(self, p1, p2, data):
|
||||||
@@ -490,7 +490,7 @@ class Security_Environment(object):
|
|||||||
|
|
||||||
checksum = vsCrypto.crypto_checksum(self.cct.algorithm, self.cct.key,
|
checksum = vsCrypto.crypto_checksum(self.cct.algorithm, self.cct.key,
|
||||||
data, self.cct.iv)
|
data, self.cct.iv)
|
||||||
return SW["NORMAL"], checksum
|
return checksum
|
||||||
|
|
||||||
def compute_digital_signature(self, p1, p2, data):
|
def compute_digital_signature(self, p1, p2, data):
|
||||||
"""
|
"""
|
||||||
@@ -520,7 +520,7 @@ class Security_Environment(object):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
signature = self.dst.key.sign(to_sign, "")
|
signature = self.dst.key.sign(to_sign, "")
|
||||||
return SW["NORMAL"], signature
|
return signature
|
||||||
|
|
||||||
def hash(self, p1, p2, data):
|
def hash(self, p1, p2, data):
|
||||||
"""
|
"""
|
||||||
@@ -539,7 +539,7 @@ class Security_Environment(object):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
raise SwError(SW["ERR_EXECUTION"])
|
raise SwError(SW["ERR_EXECUTION"])
|
||||||
|
|
||||||
return SW["NORMAL"], hash
|
return hash
|
||||||
|
|
||||||
def verify_cryptographic_checksum(self, p1, p2, data):
|
def verify_cryptographic_checksum(self, p1, p2, data):
|
||||||
"""
|
"""
|
||||||
@@ -567,7 +567,7 @@ class Security_Environment(object):
|
|||||||
else:
|
else:
|
||||||
my_cct = vsCrypto.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 ""
|
||||||
else:
|
else:
|
||||||
raise SwError["ERR_SECMESSOBJECTSINCORRECT"]
|
raise SwError["ERR_SECMESSOBJECTSINCORRECT"]
|
||||||
|
|
||||||
@@ -600,7 +600,7 @@ class Security_Environment(object):
|
|||||||
|
|
||||||
my_signature = key.sign(value)
|
my_signature = key.sign(value)
|
||||||
if my_signature == signature:
|
if my_signature == signature:
|
||||||
return SW["NORMAL"], ""
|
return ""
|
||||||
else:
|
else:
|
||||||
raise SwError(["ERR_SECMESSOBJECTSINCORRECT"])
|
raise SwError(["ERR_SECMESSOBJECTSINCORRECT"])
|
||||||
|
|
||||||
@@ -613,7 +613,7 @@ class Security_Environment(object):
|
|||||||
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"])
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError
|
raise SwError(SW["ERR_NOTSUPPORTED"])
|
||||||
|
|
||||||
def encipher(self, p1, p2, data):
|
def encipher(self, p1, p2, data):
|
||||||
"""
|
"""
|
||||||
@@ -625,11 +625,11 @@ class Security_Environment(object):
|
|||||||
algo = self.ct.algorithm
|
algo = self.ct.algorithm
|
||||||
key = self.ct.key
|
key = self.ct.key
|
||||||
if key == None or algo == None:
|
if key == None or algo == None:
|
||||||
return SW["ERR_CONDITIONNOTSATISFIED"], ""
|
raise SwError(SW["ERR_CONDITIONNOTSATISFIED"])
|
||||||
else:
|
else:
|
||||||
padded = vsCrypto.append_padding(vsCrypto.get_cipher_blocklen(algo), data)
|
padded = vsCrypto.append_padding(vsCrypto.get_cipher_blocklen(algo), data)
|
||||||
crypted = vsCrypto.encrypt(algo, key, padded, self.ct.iv)
|
crypted = vsCrypto.encrypt(algo, key, padded, self.ct.iv)
|
||||||
return SW["NORMAL"], crypted
|
return crypted
|
||||||
|
|
||||||
def decipher(self, p1, p2, data):
|
def decipher(self, p1, p2, data):
|
||||||
"""
|
"""
|
||||||
@@ -644,7 +644,7 @@ class Security_Environment(object):
|
|||||||
raise SwError(SW["ERR_CONDITIONNOTSATISFIED"])
|
raise SwError(SW["ERR_CONDITIONNOTSATISFIED"])
|
||||||
else:
|
else:
|
||||||
plain = vsCrypto.decrypt(algo, key, data, self.ct.iv)
|
plain = vsCrypto.decrypt(algo, key, data, self.ct.iv)
|
||||||
return SW["NORMAL"], plain
|
return plain
|
||||||
|
|
||||||
def generate_public_key_pair(self, p1, p2, data):
|
def generate_public_key_pair(self, p1, p2, data):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class ePass_SE(Security_Environment):
|
|||||||
checksum = vsCrypto.crypto_checksum(self.cct.algorithm, self.cct.key,
|
checksum = vsCrypto.crypto_checksum(self.cct.algorithm, self.cct.key,
|
||||||
data, self.cct.iv, self.ssc)
|
data, self.cct.iv, self.ssc)
|
||||||
|
|
||||||
return SW["NORMAL"], checksum
|
return checksum
|
||||||
|
|
||||||
class PassportSAM(SAM):
|
class PassportSAM(SAM):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -314,7 +314,7 @@ class nPA_SE(Security_Environment):
|
|||||||
|
|
||||||
print "Imported Certificate"
|
print "Imported Certificate"
|
||||||
|
|
||||||
return 0x9000, ""
|
return ""
|
||||||
|
|
||||||
def external_authenticate(self, p1, p2, data):
|
def external_authenticate(self, p1, p2, data):
|
||||||
"""
|
"""
|
||||||
@@ -350,7 +350,7 @@ class nPA_SE(Security_Environment):
|
|||||||
pace.print_ossl_err()
|
pace.print_ossl_err()
|
||||||
raise SwError(SW["ERR_NOINFO69"])
|
raise SwError(SW["ERR_NOINFO69"])
|
||||||
|
|
||||||
return 0x9000, checksum
|
return checksum
|
||||||
|
|
||||||
def encipher(self, p1, p2, data):
|
def encipher(self, p1, p2, data):
|
||||||
padded = vsCrypto.append_padding(self.cct.blocklength, data)
|
padded = vsCrypto.append_padding(self.cct.blocklength, data)
|
||||||
@@ -359,7 +359,7 @@ class nPA_SE(Security_Environment):
|
|||||||
pace.print_ossl_err()
|
pace.print_ossl_err()
|
||||||
raise SwError(SW["ERR_NOINFO69"])
|
raise SwError(SW["ERR_NOINFO69"])
|
||||||
|
|
||||||
return 0x9000, cipher
|
return cipher
|
||||||
|
|
||||||
def decipher(self, p1, p2, data):
|
def decipher(self, p1, p2, data):
|
||||||
plain = pace.EAC_decrypt(self.eac_ctx, self.ssc, data)
|
plain = pace.EAC_decrypt(self.eac_ctx, self.ssc, data)
|
||||||
@@ -367,7 +367,7 @@ class nPA_SE(Security_Environment):
|
|||||||
pace.print_ossl_err()
|
pace.print_ossl_err()
|
||||||
raise SwError(SW["ERR_NOINFO69"])
|
raise SwError(SW["ERR_NOINFO69"])
|
||||||
|
|
||||||
return 0x9000, plain
|
return plain
|
||||||
|
|
||||||
def protect_response(self, sw, result):
|
def protect_response(self, sw, result):
|
||||||
"""
|
"""
|
||||||
@@ -380,7 +380,7 @@ class nPA_SE(Security_Environment):
|
|||||||
|
|
||||||
if result != "":
|
if result != "":
|
||||||
# Encrypt the data included in the RAPDU
|
# Encrypt the data included in the RAPDU
|
||||||
sw, encrypted = self.encipher(0x82, 0x80, result)
|
encrypted = self.encipher(0x82, 0x80, result)
|
||||||
encrypted = "\x01" + encrypted
|
encrypted = "\x01" + encrypted
|
||||||
encrypted_tlv = bertlv_pack([(
|
encrypted_tlv = bertlv_pack([(
|
||||||
SM_Class["CRYPTOGRAM_PADDING_INDICATOR_ODD"],
|
SM_Class["CRYPTOGRAM_PADDING_INDICATOR_ODD"],
|
||||||
@@ -399,13 +399,13 @@ class nPA_SE(Security_Environment):
|
|||||||
elif self.cct.algorithm == "CC":
|
elif self.cct.algorithm == "CC":
|
||||||
tag = SM_Class["CHECKSUM"]
|
tag = SM_Class["CHECKSUM"]
|
||||||
padded = vsCrypto.append_padding(self.cct.blocklength, return_data)
|
padded = vsCrypto.append_padding(self.cct.blocklength, return_data)
|
||||||
sw, auth = self.compute_cryptographic_checksum(0x8E, 0x80, padded)
|
auth = self.compute_cryptographic_checksum(0x8E, 0x80, padded)
|
||||||
length = len(auth)
|
length = len(auth)
|
||||||
return_data += bertlv_pack([(tag, length, auth)])
|
return_data += bertlv_pack([(tag, length, auth)])
|
||||||
elif self.cct.algorithm == "SIGNATURE":
|
elif self.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)
|
auth = self.compute_digital_signature(0x9E, 0x9A, hash)
|
||||||
length = len(auth)
|
length = len(auth)
|
||||||
return_data += bertlv_pack([(tag, length, auth)])
|
return_data += bertlv_pack([(tag, length, auth)])
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user