aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhenryk <henryk@f711b948-2313-0410-aaa9-d29f33439f0b>2005-09-29 03:39:27 +0000
committerhenryk <henryk@f711b948-2313-0410-aaa9-d29f33439f0b>2005-09-29 03:39:27 +0000
commit0fa0e7c41557224b03a0bc78f3a13101792a793f (patch)
tree5c7ae28158d269f649942668a8e59561d12d00d5
parent85c11acfcd6b699e8d960e62fb84ddb5b27f8173 (diff)
basic functions working
git-svn-id: svn+ssh://localhost/home/henryk/svn/cyberflex-shell/trunk@12 f711b948-2313-0410-aaa9-d29f33439f0b
-rw-r--r--crypto_utils.py71
-rw-r--r--cyberflex-shell.e3p24
-rwxr-xr-xcyberflex-shell.py73
3 files changed, 167 insertions, 1 deletions
diff --git a/crypto_utils.py b/crypto_utils.py
new file mode 100644
index 0000000..0004ee9
--- /dev/null
+++ b/crypto_utils.py
@@ -0,0 +1,71 @@
+import sys, binascii, utils, random
+from Crypto.Cipher import DES3
+
+iv = '\x00' * 8
+PADDING = '\x80' + '\x00' * 7
+
+def verify_card_cryptogram(session_key, host_challenge,
+ card_challenge, card_cryptogram):
+ message = host_challenge + card_challenge
+ expected = calculate_MAC(session_key, message, iv)
+
+ print >>sys.stderr, "Original: %s" % binascii.b2a_hex(card_cryptogram)
+ print >>sys.stderr, "Expected: %s" % binascii.b2a_hex(expected)
+
+ return card_cryptogram == expected
+
+def calculate_host_cryptogram(session_key, card_challenge,
+ host_challenge):
+ message = card_challenge + host_challenge
+ return calculate_MAC(session_key, message, iv)
+
+def calculate_MAC(session_key, message, iv):
+ print >>sys.stderr, "Doing MAC for: %s" % utils.hexdump(message, indent = 17)
+
+ cipher = DES3.new(session_key, DES3.MODE_CBC, iv)
+ block_count = len(message) / cipher.block_size
+ for i in range(block_count):
+ cipher.encrypt(message[i*cipher.block_size:(i+1)*cipher.block_size])
+
+ last_block_length = len(message) % cipher.block_size
+ last_block = (message[len(message)-last_block_length:]+PADDING)[:cipher.block_size]
+
+ return cipher.encrypt( last_block )
+
+def get_derivation_data(host_challenge, card_challenge):
+ return card_challenge[4:8] + host_challenge[:4] + \
+ card_challenge[:4] + host_challenge[4:8]
+
+def get_session_key(auth_key, host_challenge, card_challenge):
+ cipher = DES3.new(auth_key, DES3.MODE_ECB)
+ return cipher.encrypt(get_derivation_data(host_challenge, card_challenge))
+
+def generate_host_challenge():
+ random.seed()
+ return "".join([chr(random.randint(0,255)) for e in range(8)])
+
+def andstring(string1, string2):
+ if len(string1) != len(string2):
+ raise ValueError, "string1 and string2 must be of equal length"
+ result = []
+ for i in range(len(string1)):
+ result.append( chr(ord(string1[i]) & ord(string2[i])) )
+ return "".join(result)
+
+if __name__ == "__main__":
+ default_key = binascii.a2b_hex("404142434445464748494A4B4C4D4E4F")
+
+ host_chal = binascii.a2b_hex("".join("89 45 19 BF BC 1A 5B D8".split()))
+ card_chal = binascii.a2b_hex("".join("27 4D B7 EA CA 66 CE 44".split()))
+ card_crypto = binascii.a2b_hex("".join("8A D4 A9 2D 9B 6B 24 E0".split()))
+
+ session_key = get_session_key(default_key, host_chal, card_chal)
+ print "Session-Key: ", utils.hexdump(session_key)
+
+ print verify_card_cryptogram(session_key, host_chal, card_chal, card_crypto)
+
+ host_crypto = calculate_host_cryptogram(session_key, card_chal, host_chal)
+ print "Host-Crypto: ", utils.hexdump( host_crypto )
+
+ external_authenticate = binascii.a2b_hex("".join("84 82 01 00 10".split())) + host_crypto
+ print utils.hexdump(calculate_MAC(session_key, external_authenticate, iv))
diff --git a/cyberflex-shell.e3p b/cyberflex-shell.e3p
index 04469af..33da624 100644
--- a/cyberflex-shell.e3p
+++ b/cyberflex-shell.e3p
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Project SYSTEM "Project-3.5.dtd">
<!-- Project file for project cyberflex-shell -->
-<!-- Saved: 2005-09-27, 15:23:49 -->
+<!-- Saved: 2005-09-29, 05:37:58 -->
<!-- Copyright (C) 2005 Henryk Plötz, henryk@ploetzli.ch -->
<Project version="3.5">
<Description></Description>
@@ -12,6 +12,28 @@
<Source>
<Name>utils.py</Name>
</Source>
+ <Source>
+ <Name>crypto_utils.py</Name>
+ </Source>
+ <Source>
+ <Name>cyberflex-shell.py</Name>
+ </Source>
+ <Source>
+ <Dir>cards</Dir>
+ <Name>cyberflex_card.py</Name>
+ </Source>
+ <Source>
+ <Dir>cards</Dir>
+ <Name>generic_card.py</Name>
+ </Source>
+ <Source>
+ <Dir>cards</Dir>
+ <Name>java_card.py</Name>
+ </Source>
+ <Source>
+ <Dir>cards</Dir>
+ <Name>__init__.py</Name>
+ </Source>
</Sources>
<Forms>
</Forms>
diff --git a/cyberflex-shell.py b/cyberflex-shell.py
new file mode 100755
index 0000000..e5b7cd2
--- /dev/null
+++ b/cyberflex-shell.py
@@ -0,0 +1,73 @@
+#!/usr/bin/env python
+# -*- coding: iso-8859-1 -*-
+
+import pycsc, utils, cards, os, readline, re, binascii, sys
+
+histfile = os.path.join(os.environ["HOME"], ".cyberflex-shell.history")
+try:
+ readline.read_history_file(histfile)
+except IOError:
+ pass
+import atexit
+atexit.register(readline.write_history_file, histfile)
+del os, histfile
+
+readline.parse_and_bind("tab: complete")
+
+
+readerName = pycsc.listReader()[0]
+newState = pycsc.getStatusChange(ReaderStates=[{'Reader': readerName, 'CurrentState':pycsc.SCARD_STATE_UNAWARE}])
+
+print "Cyberflex shell"
+print "Using reader: %s" % readerName
+print "Card present: %s" % ((newState[0]['EventState'] & pycsc.SCARD_STATE_PRESENT) and "yes" or "no")
+
+if not newState[0]['EventState'] & pycsc.SCARD_STATE_PRESENT:
+ print "Please insert card ..."
+
+ while not newState[0]['EventState'] & pycsc.SCARD_STATE_PRESENT \
+ or newState[0]['EventState'] & pycsc.SCARD_STATE_MUTE:
+
+ newState = pycsc.getStatusChange(ReaderStates=[{'Reader': readerName, 'CurrentState':newState[0]['EventState']}])
+
+ if newState[0]['EventState'] & pycsc.SCARD_STATE_MUTE:
+ print "Card is mute, please retry ..."
+
+ print "Card present: %s" % ((newState[0]['EventState'] & pycsc.SCARD_STATE_PRESENT) and "yes" or "no")
+
+print "ATR: %s" % utils.hexdump(newState[0]['Atr'], short = True)
+card_class = cards.find_class(newState[0]['Atr'])
+
+card = card_class()
+
+line = ""
+apduregex = re.compile(r'^\s*([0-9a-f]{2}\s*){4,}$', re.I)
+while line != "exit":
+ try:
+ line = raw_input("%s > " % card.get_prompt())
+ except EOFError:
+ print
+ break
+
+ if line.strip() == "":
+ continue
+
+ parts = line.split()
+ cmd = parts[0]
+ if card.COMMANDS.has_key(cmd.lower()):
+ cmdspec = card.COMMANDS[cmd.lower()]
+ try:
+ cmdspec[0](card, *parts[1:])
+ except Exception:
+ exctype, value = sys.exc_info()[:2]
+ print "%s: %s" % (exctype, value)
+
+ elif apduregex.match(line):
+ ## Might be an APDU
+ apdu = binascii.a2b_hex("".join(line.split()))
+ try:
+ response = card.send_apdu(apdu)
+ print utils.hexdump(response)
+ except Exception:
+ exctype, value = sys.exc_info()[:2]
+ print "%s: %s" % (exctype, value)