Skip to content

Commit

Permalink
Add hashing of HMAC keys.
Browse files Browse the repository at this point in the history
  • Loading branch information
elibon99 committed Aug 21, 2023
1 parent c39c035 commit a079b74
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 16 deletions.
58 changes: 46 additions & 12 deletions tests/device/test_hmac.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,18 +152,52 @@ def test_hmac_vectors(session, vector):
key4.delete()


def test_import_invalid_key_size(session):
# Key length must match algorithm
with pytest.raises(ValueError):
HmacKey.put(
session,
0,
"Test PUT invalid algorithm",
0xFFFF,
CAPABILITY.SIGN_HMAC,
os.urandom(65),
ALGORITHM.HMAC_SHA256,
)
@pytest.mark.parametrize(
"vector",
[
{
"key": b"\x0b" * 65, # Larger than SHA1 block size (64)
"chal": b"\xdd" * 50,
"algorithm": ALGORITHM.HMAC_SHA1,
"exp_sha": b"<D\x87\x828\x8eW&\x03\xa1\xa8\x9a\x0bmy\x81\xfa\xffD\xed", # noqa: E501
},
{
"key": b"\xcd" * 65, # Larger than SHA256 block size (64),
"chal": b"\xab" * 50,
"algorithm": ALGORITHM.HMAC_SHA256,
"exp_sha": b"T\x15\xaf\xc0\xb8\xda\x95\x97pb_\xe6$\xea\xe1rR\xfe\\\r\x11(\xbe\x02\x06\x1a&l\xc9\x94\x95\x13", # noqa: E501
},
{
"key": b"\xde" * 129, # Larger than SHA384 block size (128)
"chal": b"\xbb" * 50,
"algorithm": ALGORITHM.HMAC_SHA384,
"exp_sha": b'`H\x9f\xfd\x99"\x86\x15\x1e\x80O\x0c\x19\xe9gH\xbck\xb57\x82\x16G42%6\xdcs\x82\xc8I\xcb|1\x1ftU\xfbb\x1c\x8b\xfb;"\xb6A\xb4', # noqa: E501
},
{
"key": b"\xcc" * 129, # Larger than SHA512 block size (128)
"chal": b"\xac" * 50,
"algorithm": ALGORITHM.HMAC_SHA512,
"exp_sha": b"1\xe2\x94\x08\xa0\xefF\x01Y\xeb\x9e\xc7\xe5\x807\xc9\xd7~Y\xd9\x83pM\xe5\x0eU\x94\xe4\xf1/\xa9J\xb97r\xf5\x16\x0f\xe62\x88\xcd\x14\xee\xd7\x1b|I\xe7\xbd\x8a\x12*H\x9b\xeb\x00\xa0-V\x05dn\x16", # noqa: E501
},
],
)
def test_import_large_keys(session, vector):
key_id = random.randint(1, 0xFFFE)

caps = CAPABILITY.SIGN_HMAC | CAPABILITY.VERIFY_HMAC

key = HmacKey.put(
session,
key_id,
"Test import large key 0x%04x" % key_id,
1,
caps,
vector["key"],
vector["algorithm"],
)

assert key.sign_hmac(vector["chal"]) == vector["exp_sha"]
assert key.verify_hmac(vector["exp_sha"], vector["chal"])


def test_import_invalid_algorithm(session):
Expand Down
21 changes: 21 additions & 0 deletions yubihsm/defs.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"""Named constants used in YubiHSM commands."""

from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import hashes
from enum import IntEnum, IntFlag, unique


Expand Down Expand Up @@ -216,6 +217,19 @@ def to_key_size(self) -> int:

return _key_size_table[self]

def to_hash_algorithm(self) -> hashes.HashAlgorithm:
"""Return the cryptography hash algorithm object corresponding to the algorithm.
:return The corresponding cryptography hash algorithm object.
:Example:
>>> ALGORITHM.HMAC_SHA1.to_hash_algorithm()
hashes.SHA1
"""

return _hash_table[self]()


_curve_table = {
ALGORITHM.EC_P224: ec.SECP224R1,
Expand Down Expand Up @@ -244,6 +258,13 @@ def to_key_size(self) -> int:
ALGORITHM.AES256: 32,
}

_hash_table = {
ALGORITHM.HMAC_SHA1: hashes.SHA1,
ALGORITHM.HMAC_SHA256: hashes.SHA256,
ALGORITHM.HMAC_SHA384: hashes.SHA384,
ALGORITHM.HMAC_SHA512: hashes.SHA512,
}


@unique
class LIST_FILTER(IntEnum):
Expand Down
6 changes: 2 additions & 4 deletions yubihsm/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -1037,10 +1037,8 @@ def put(
raise ValueError("Invalid algorithm")

if len(key) > algorithm.to_key_size():
raise ValueError(
"Key length (%d) not matching algorithm (%s)"
% (len(key), algorithm.name)
)
# Hash key using corresponding hash algorithm
key = _calc_hash(key, algorithm.to_hash_algorithm())

msg = (
struct.pack(
Expand Down

0 comments on commit a079b74

Please sign in to comment.