/usr/share/pyshared/pyhsm/oath_hotp.py is in python-pyhsm 1.0.4f-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | """
helper functions to work with OATH HOTP (RFC4226) OTP's and YubiHSM
"""
# Copyright (c) 2011 Yubico AB
# See the file COPYING for licence statement.
import string
import struct
__all__ = [
# constants
# functions
'validate_oath_hotp_with_aead',
# classes
]
import pyhsm.exception
import pyhsm.aead_cmd
def search_for_oath_code(hsm, key_handle, nonce, aead, counter, user_code, look_ahead=1):
"""
Try to validate an OATH HOTP OTP generated by a token whose secret key is
available to the YubiHSM through the AEAD.
The parameter `aead' is either a string, or an instance of YHSM_GeneratedAEAD.
Returns next counter value on successful auth, and None otherwise.
"""
key_handle = pyhsm.util.input_validate_key_handle(key_handle)
nonce = pyhsm.util.input_validate_nonce(nonce, pad = False)
aead = pyhsm.util.input_validate_aead(aead)
counter = pyhsm.util.input_validate_int(counter, 'counter')
user_code = pyhsm.util.input_validate_int(user_code, 'user_code')
hsm.load_temp_key(nonce, key_handle, aead)
# User might have produced codes never sent to us, so we support trying look_ahead
# codes to see if we find the user's current code.
for j in xrange(look_ahead):
this_counter = counter + j
secret = struct.pack("> Q", this_counter)
hmac_result = hsm.hmac_sha1(pyhsm.defines.YSM_TEMP_KEY_HANDLE, secret).get_hash()
this_code = truncate(hmac_result)
if this_code == user_code:
return this_counter + 1
return None
def truncate(hmac_result, length=6):
""" Perform the truncating. """
assert(len(hmac_result) == 20)
offset = ord(hmac_result[19]) & 0xf
bin_code = (ord(hmac_result[offset]) & 0x7f) << 24 \
| (ord(hmac_result[offset+1]) & 0xff) << 16 \
| (ord(hmac_result[offset+2]) & 0xff) << 8 \
| (ord(hmac_result[offset+3]) & 0xff)
return bin_code % (10 ** length)
|