Status word decoding
git-svn-id: svn+ssh://localhost/home/henryk/svn/cyberflex-shell/trunk@18 f711b948-2313-0410-aaa9-d29f33439f0b
This commit is contained in:
parent
2e29202aae
commit
3f36321e51
|
@ -270,6 +270,49 @@ class Cyberflex_Card(Java_Card):
|
|||
"reset_keyset": (cmd_resetkeyset, "reset_keyset",
|
||||
"""Reset the keyset to the default keyset for this card.""")
|
||||
} )
|
||||
STATUS_WORDS = dict(Java_Card.STATUS_WORDS)
|
||||
STATUS_WORDS.update( {
|
||||
"\x62\x83": "The Card Manager is locked (SelectApplication).",
|
||||
"\x63\x00": "Authentication of the host cryptogram failed.",
|
||||
"\x63\x10": "More data is available for return than is specified in the Le value.",
|
||||
"\x64\x00": "Technical problem that has no specified diagnosis.",
|
||||
"\x65\x81": "Memory failure.",
|
||||
"\x67\x00": "The specified length of the input data (Lc) is incorrect.",
|
||||
"\x69\x81": "No key is specified (GetResponse, called internally).",
|
||||
"\x69\x82": "Security status not satisfied. For example, MAC verification failed, the authentication key is locked, or the current security domain requires DAP verification and no verification data was included with the command.",
|
||||
"\x69\x83": "The key is blocked (GetResponse, called internally).",
|
||||
"\x69\x85": """A requirement for using the command is not satisfied. For example:
|
||||
+ Command issued outside of a secure channel.
|
||||
+ Current application does not have the required application privilege
|
||||
or life cycle state.
|
||||
+ The required preceding command was not present.
|
||||
+ The object to delete is referenced by another object on the card.""",
|
||||
"\x69\x87": "The MAC or other verification data is missing (Install).",
|
||||
"\x69\x99": "Application selection failed (SelectApplication).",
|
||||
"\x6A\x80": """Invalid or inconsistent input data, including input data that is inconsistent with a command header parameter, and LV/TLV-format elements in the input data that are not self-consistent. For example:
|
||||
+ Incorrect number of padding bytes, incorrect key used for
|
||||
encryption, or the specified key set or key index value is invalid.
|
||||
+ Referenced AID is not found in the card registry or package, or the
|
||||
newly specified AID already exists in the registry.
|
||||
+ Inappropriate application privilege byte value (installing security
|
||||
domain), or card already has a default selected application
|
||||
(specifying default selected application).
|
||||
+ First block of input data for a load file is not preceded by the
|
||||
correct tag and/or valid length, or the load file refers to a
|
||||
nonexistent package.""",
|
||||
"\x6A\x81": "Target is locked (SelectApplication).",
|
||||
"\x6A\x82": "Registry contains no valid application (or no additional valid application) with the specified AID (SelectApplication).",
|
||||
"\x6A\x84": "Insufficient EEPROM memory available to add the object to the card.",
|
||||
"\x6A\x86": "Incorrect or unsupported value is specified for P1, P2, or both.",
|
||||
"\x6A\x88": "Data referred to in P1, P2, or both is not found.",
|
||||
"\x6D\x00": "Unsupported value entered for the INS byte.",
|
||||
"\x6E\x00": "Unsupported value entered for the CLA byte.",
|
||||
"\x6F\x00": "JVM error that has no specified diagnosis.",
|
||||
"\x90\x00": "Command succeeded.",
|
||||
"\x94\x81": "Target has an invalid life cycle state.",
|
||||
"\x94\x84": "Unsupported algorithm ID in input data (PutKey).",
|
||||
"\x94\x85": "Invalid key check value in input data (PutKey).",
|
||||
} )
|
||||
|
||||
if __name__ == "__main__":
|
||||
c = Cyberflex_Card()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import crypto_utils, utils, pycsc
|
||||
import crypto_utils, utils, pycsc, binascii
|
||||
|
||||
DEBUG = True
|
||||
|
||||
|
@ -8,6 +8,9 @@ class Card:
|
|||
ATRS = []
|
||||
DRIVER_NAME = "Generic"
|
||||
COMMANDS = {}
|
||||
STATUS_WORDS = {
|
||||
SW_OK: "Normal execution"
|
||||
}
|
||||
|
||||
def __init__(self, card = None):
|
||||
if card is None:
|
||||
|
@ -16,6 +19,9 @@ class Card:
|
|||
self.card = card
|
||||
|
||||
self._i = 0
|
||||
self.last_apdu = None
|
||||
self.last_sw = None
|
||||
self.sw_changed = False
|
||||
|
||||
def _check_apdu(apdu):
|
||||
if len(apdu) < 4 or ((len(apdu) > 5) and len(apdu) != (ord(apdu[4])+5)):
|
||||
|
@ -24,6 +30,19 @@ class Card:
|
|||
return True
|
||||
_check_apdu = staticmethod(_check_apdu)
|
||||
|
||||
def _real_send(self, apdu):
|
||||
if not Card._check_apdu(apdu):
|
||||
raise Exception, "Invalid APDU"
|
||||
if DEBUG:
|
||||
print ">> " + utils.hexdump(apdu, indent = 3)
|
||||
result = self.card.transmit(apdu)
|
||||
self.last_apdu = apdu
|
||||
self.last_sw = result[-2:]
|
||||
self.sw_changed = True
|
||||
if DEBUG:
|
||||
print "<< " + utils.hexdump(result, indent = 3)
|
||||
return result
|
||||
|
||||
def send_apdu(self, apdu):
|
||||
if not Card._check_apdu(apdu):
|
||||
raise Exception, "Invalid APDU"
|
||||
|
@ -32,29 +51,18 @@ class Card:
|
|||
|
||||
if hasattr(self, "before_send"):
|
||||
apdu = self.before_send(apdu)
|
||||
if not Card._check_apdu(apdu):
|
||||
raise Exception, "Invalid APDU"
|
||||
|
||||
if DEBUG:
|
||||
print ">> " + utils.hexdump(apdu, indent = 3)
|
||||
result = self.card.transmit(apdu)
|
||||
if DEBUG:
|
||||
print "<< " + utils.hexdump(result, indent = 3)
|
||||
result = self._real_send(apdu)
|
||||
|
||||
if result[0] == '\x61':
|
||||
## Need to call GetResponse
|
||||
gr_apdu = self.APDU_GET_RESPONSE + result[1]
|
||||
if not Card._check_apdu(gr_apdu):
|
||||
raise Exception, "Invalid APDU"
|
||||
if DEBUG:
|
||||
print ">> " + utils.hexdump(gr_apdu, indent = 3)
|
||||
result = self.card.transmit(gr_apdu)
|
||||
if DEBUG:
|
||||
print "<< " + utils.hexdump(result, indent = 3)
|
||||
result = self._real_send(gr_apdu)
|
||||
|
||||
if DEBUG:
|
||||
print "Ending transaction %i\n%s\n" % (self._i, '-'*80)
|
||||
self._i = self._i + 1
|
||||
|
||||
return result
|
||||
|
||||
def can_handle(cls, ATR):
|
||||
|
@ -69,3 +77,11 @@ class Card:
|
|||
|
||||
def get_prompt(self):
|
||||
return "(%s)" % self.DRIVER_NAME
|
||||
|
||||
def decode_statusword(self):
|
||||
if self.last_sw is None:
|
||||
return "No command executed so far"
|
||||
elif self.last_sw[0] == "\x61":
|
||||
return "%i (0x%02x) bytes of response data can be retrieved with GetResponse." % ( (ord(self.last_sw[1])) * 2 )
|
||||
else:
|
||||
return self.STATUS_WORDS.get(self.last_sw, "Unknown SW: %s" % binascii.b2a_hex(self.last_sw))
|
||||
|
|
|
@ -117,6 +117,8 @@ if __name__ == "__main__":
|
|||
if line == "":
|
||||
continue
|
||||
|
||||
card.sw_changed = False
|
||||
|
||||
parts = line.split()
|
||||
cmd = parts[0]
|
||||
if card.COMMANDS.has_key(cmd.lower()):
|
||||
|
@ -151,3 +153,6 @@ if __name__ == "__main__":
|
|||
|
||||
else:
|
||||
print "Unknown command"
|
||||
|
||||
if card.sw_changed:
|
||||
print card.decode_statusword()
|
||||
|
|
Loading…
Reference in New Issue