Permalink
Browse files

Move YubiKeyEmu to test_common.

  • Loading branch information...
1 parent 0fea25b commit 91d752714c16337a9f1b87aff3d5d665a0c731a9 @fredrikt fredrikt committed Aug 21, 2011
Showing with 90 additions and 89 deletions.
  1. +87 −0 Tests/test_common.py
  2. +2 −89 Tests/test_yubikey_validate.py
  3. +1 −0 doc/wiki
View
87 Tests/test_common.py
@@ -1,9 +1,11 @@
# Copyright (c) 2011, Yubico AB
# All rights reserved.
+import os
import sys
import unittest
import pyhsm
+import struct
# configuration parameters
CfgPassphrase = ""
@@ -49,3 +51,88 @@ def who_can(self, what, expected = [], extra_khs = []):
if e.status != pyhsm.defines.YSM_FUNCTION_DISABLED:
self.fail("Expected YSM_FUNCTION_DISABLED for key handle 0x%0x, got %s" \
% (kh, e.status_str))
+def crc16(data):
+ """
+ Calculate an ISO13239 CRC checksum of the input buffer.
+ """
+ m_crc = 0xffff
+ for this in data:
+ m_crc ^= ord(this)
+ for _ in range(8):
+ j = m_crc & 1
+ m_crc >>= 1
+ if j:
+ m_crc ^= 0x8408
+ return m_crc
+
+class YubiKeyEmu():
+ """
+ Emulate the internal memory of a YubiKey.
+ """
+
+ def __init__(self, user_id, use_ctr, timestamp, session_ctr):
+ if len(user_id) != pyhsm.defines.UID_SIZE:
+ raise pyhsm.exception.YHSM_WrongInputSize(
+ 'user_id', pyhsm.defines.UID_SIZE, len(user_id))
+
+ self.user_id = user_id
+ self.use_ctr = use_ctr
+ self.timestamp = timestamp
+ self.session_ctr = session_ctr
+ self.rnd = struct.unpack('H', os.urandom(2))[0]
+
+ def pack(self):
+ """
+ Return contents packed. Only add AES ECB encryption and modhex to
+ get your own YubiKey OTP.
+ """
+
+ #define UID_SIZE 6
+ #typedef struct {
+ # uint8_t userId[UID_SIZE];
+ # uint16_t sessionCtr; # NOTE: this is use_ctr
+ # uint24_t timestamp;
+ # uint8_t sessionUse; # NOTE: this is session_ctr
+ # uint16_t rnd;
+ # uint16_t crc;
+ #} TICKET;
+ fmt = "< %is H HB B H" % (pyhsm.defines.UID_SIZE)
+
+ ts_high = (self.timestamp & 0x00ff0000) >> 16
+ ts_low = self.timestamp & 0x0000ffff
+
+ res = struct.pack(fmt, self.user_id, \
+ self.use_ctr, \
+ ts_low, ts_high, \
+ self.session_ctr, \
+ self.rnd)
+ crc = 0xffff - crc16(res)
+
+ return res + struct.pack('<H', crc)
+
+ def get_otp(self, key):
+ """
+ Return an modhex encoded OTP given our current state.
+ """
+ from Crypto.Cipher import AES
+ packed = self.pack()
+ obj = AES.new(key, AES.MODE_ECB)
+ ciphertext = obj.encrypt(packed)
+ return ciphertext
+
+ def from_key(self, public_id, key):
+ """
+ Return what the YubiKey would have returned when the button was pressed.
+ """
+ from pyhsm.yubikey import modhex_encode, modhex_decode
+
+ otp = self.get_otp(key)
+ from_key = modhex_encode(public_id.encode('hex')) + modhex_encode(otp.encode('hex'))
+ return from_key
+
+class YubiKeyRnd(YubiKeyEmu):
+ """ YubiKeyEmu with everything but user_id randomized. """
+
+ def __init__(self, user_id):
+ timestamp, session_counter, session_use = struct.unpack('IHB', os.urandom(7))
+ YubiKeyEmu.__init__(self, user_id, session_counter, timestamp, session_use)
View
91 Tests/test_yubikey_validate.py
@@ -1,100 +1,13 @@
# Copyright (c) 2011, Yubico AB
# All rights reserved.
-import os
import sys
import string
-import struct
import unittest
import pyhsm
-from Crypto.Cipher import AES
-from pyhsm.yubikey import modhex_encode, modhex_decode
import test_common
-
-class YubiKeyEmu():
- """
- Emulate the internal memory of a YubiKey.
- """
-
- def __init__(self, user_id, use_ctr, timestamp, session_ctr):
- if len(user_id) != pyhsm.defines.UID_SIZE:
- raise pyhsm.exception.YHSM_WrongInputSize(
- 'user_id', pyhsm.defines.UID_SIZE, len(user_id))
-
- self.user_id = user_id
- self.use_ctr = use_ctr
- self.timestamp = timestamp
- self.session_ctr = session_ctr
- self.rnd = struct.unpack('H', os.urandom(2))[0]
-
- def pack(self):
- """
- Return contents packed. Only add AES ECB encryption and modhex to
- get your own YubiKey OTP.
- """
-
- #define UID_SIZE 6
- #typedef struct {
- # uint8_t userId[UID_SIZE];
- # uint16_t sessionCtr; # NOTE: this is use_ctr
- # uint24_t timestamp;
- # uint8_t sessionUse; # NOTE: this is session_ctr
- # uint16_t rnd;
- # uint16_t crc;
- #} TICKET;
- fmt = "< %is H HB B H" % (pyhsm.defines.UID_SIZE)
-
- ts_high = (self.timestamp & 0x00ff0000) >> 16
- ts_low = self.timestamp & 0x0000ffff
-
- res = struct.pack(fmt, self.user_id, \
- self.use_ctr, \
- ts_low, ts_high, \
- self.session_ctr, \
- self.rnd)
- crc = 0xffff - crc16(res)
-
- return res + struct.pack('<H', crc)
-
- def get_otp(self, key):
- """
- Return an modhex encoded OTP given our current state.
- """
- packed = self.pack()
- obj = AES.new(key, AES.MODE_ECB)
- ciphertext = obj.encrypt(packed)
- return ciphertext
-
- def from_key(self, public_id, key):
- """
- Return what the YubiKey would have returned when the button was pressed.
- """
- otp = self.get_otp(key)
- from_key = modhex_encode(public_id.encode('hex')) + modhex_encode(otp.encode('hex'))
- return from_key
-
-class YubiKeyRnd(YubiKeyEmu):
- """ YubiKeyEmu with everything but user_id randomized. """
-
- def __init__(self, user_id):
- timestamp, session_counter, session_use = struct.unpack('IHB', os.urandom(7))
- YubiKeyEmu.__init__(self, user_id, session_counter, timestamp, session_use)
-
-
-def crc16(data):
- """
- Calculate an ISO13239 CRC checksum of the input buffer.
- """
- m_crc = 0xffff
- for this in data:
- m_crc ^= ord(this)
- for _ in range(8):
- j = m_crc & 1
- m_crc >>= 1
- if j:
- m_crc ^= 0x8408
- return m_crc
+from test_common import YubiKeyEmu, YubiKeyRnd
class TestYubikeyValidate(test_common.YHSM_TestCase):
@@ -146,7 +59,7 @@ def test_validate_yubikey(self):
def test_modhex_encode_decode(self):
""" Test modhex encoding/decoding. """
h = '4d014d024d4ddd5382b11195144da07d'
- self.assertEquals(h, modhex_decode( modhex_encode(h) ) )
+ self.assertEquals(h, pyhsm.yubikey.modhex_decode( pyhsm.yubikey.modhex_encode(h) ) )
def test_split_id_otp(self):
""" Test public_id + OTP split function. """
1 doc/wiki
@@ -0,0 +1 @@
+Subproject commit b077f27ad511d729a4bf10ac4efc09193dd96e40

0 comments on commit 91d7527

Please sign in to comment.