/usr/share/pyshared/pyhsm/hmac_cmd.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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | """
implementations of HMAC commands to execute on a YubiHSM
"""
# Copyright (c) 2011 Yubico AB
# See the file COPYING for licence statement.
import struct
__all__ = [
# constants
# functions
# classes
'YHSM_Cmd_HMAC_SHA1_Write',
'YHSM_GeneratedHMACSHA1',
]
import pyhsm.exception
import pyhsm.defines
from pyhsm.cmd import YHSM_Cmd
class YHSM_Cmd_HMAC_SHA1_Write(YHSM_Cmd):
"""
Calculate HMAC SHA1 using a key_handle in the YubiHSM.
Set final=False to not get a hash generated for the initial request.
Set to_buffer=True to get the SHA1 stored into the internal buffer, for
use in some other cryptographic operation.
"""
status = None
result = None
def __init__(self, stick, key_handle, data, flags = None, final = True, to_buffer = False):
data = pyhsm.util.input_validate_str(data, 'data', max_len = pyhsm.defines.YSM_MAX_PKT_SIZE - 6)
self.key_handle = pyhsm.util.input_validate_key_handle(key_handle)
if flags != None:
flags = pyhsm.util.input_validate_int(flags, 'flags', max_value=0xff)
else:
flags = pyhsm.defines.YSM_HMAC_SHA1_RESET
if final:
flags |= pyhsm.defines.YSM_HMAC_SHA1_FINAL
if to_buffer:
flags |= pyhsm.defines.YSM_HMAC_SHA1_TO_BUFFER
self.final = final
self.flags = flags
packed = _raw_pack(self.key_handle, self.flags, data)
YHSM_Cmd.__init__(self, stick, pyhsm.defines.YSM_HMAC_SHA1_GENERATE, packed)
def next(self, data, final = False, to_buffer = False):
"""
Add more input to the HMAC SHA1.
"""
if final:
self.flags = pyhsm.defines.YSM_HMAC_SHA1_FINAL
else:
self.flags = 0x0
if to_buffer:
self.flags |= pyhsm.defines.YSM_HMAC_SHA1_TO_BUFFER
self.payload = _raw_pack(self.key_handle, self.flags, data)
self.final = final
return self
def get_hash(self):
"""
Get the HMAC-SHA1 that has been calculated this far.
"""
if not self.executed:
raise pyhsm.exception.YHSM_Error("HMAC-SHA1 hash not available, before execute().")
return self.result.hash_result
def __repr__(self):
if self.executed:
return '<%s instance at %s: key_handle=0x%x, flags=0x%x, executed=%s>' % (
self.__class__.__name__,
hex(id(self)),
self.key_handle,
self.flags,
self.executed,
)
def parse_result(self, data):
# typedef struct {
# uint32_t keyHandle; // Key handle
# YHSM_STATUS status; // Status
# uint8_t numBytes; // Number of bytes in hash output
# uint8_t hash[YSM_SHA1_HASH_SIZE]; // Hash output (if applicable)
# } YHSM_HMAC_SHA1_GENERATE_RESP;
key_handle, \
self.status, \
num_bytes = struct.unpack_from('<IBB', data, 0)
pyhsm.util.validate_cmd_response_hex('key_handle', key_handle, self.key_handle)
if self.status == pyhsm.defines.YSM_STATUS_OK:
# struct.hash is not always of size YSM_SHA1_HASH_SIZE,
# it is really the size of numBytes
if num_bytes:
sha1 = data[6:6 + num_bytes]
else:
sha1 = '\x00' * pyhsm.defines.YSM_SHA1_HASH_SIZE
self.result = YHSM_GeneratedHMACSHA1(key_handle, sha1, self.final)
return self
else:
raise pyhsm.exception.YHSM_CommandFailed('YHSM_HMAC_SHA1_GENERATE', self.status)
def _raw_pack(key_handle, flags, data):
"""
Common code for packing payload to YHSM_HMAC_SHA1_GENERATE command.
"""
# #define YHSM_HMAC_RESET 0x01 // Flag to indicate reset at first packet
# #define YHSM_HMAC_FINAL 0x02 // Flag to indicate that the hash shall be calculated
# typedef struct {
# uint32_t keyHandle; // Key handle
# uint8_t flags; // Flags
# uint8_t numBytes; // Number of bytes in data packet
# uint8_t data[YHSM_MAX_PKT_SIZE - 6]; // Data to be written
# } YHSM_HMAC_SHA1_GENERATE_REQ;
return struct.pack('<IBB', key_handle, flags, len(data)) + data
class YHSM_GeneratedHMACSHA1():
""" Small class to represent a YHSM_HMAC_SHA1_GENERATE_RESP. """
def __init__(self, key_handle, sha1, final):
self.key_handle = key_handle
self.hash_result = sha1
self.final = final
def __repr__(self):
return '<%s instance at %s: key_handle=0x%x, trunc(hash_result)=%s, final=%s>' % (
self.__class__.__name__,
hex(id(self)),
self.key_handle,
self.hash_result[:4].encode('hex'),
self.final,
)
|