Implement (modified) HMAC

This commit is contained in:
Juhani Krekelä 2021-04-08 21:23:53 +03:00
parent 08c8d33b20
commit 9a0b35609b
1 changed files with 43 additions and 0 deletions

43
puer.c
View File

@ -205,3 +205,46 @@ void finalize_hash(struct hashstate *state, unsigned char hash[32]) {
// there
explicit_bzero(state, sizeof(struct hashstate));
}
void hmac(unsigned char output[32], unsigned char key[], size_t keylen, unsigned char message[], size_t messagelen) {
// The blocksize of the underlying has function is 128 bits (16B)
// but HMAC is specified assuming that the hash function output (in
// our case 256 bits or 32B) fits in one block. As far as I can
// tell extending the key to be two blocks long is not a problem.
unsigned char padded_key[32];
if (keylen > 16) {
// We hash it even if it is shorter than our extended key
// length to avoid giving attacker any funny surfaces to
// play with at the interface of two blocks
struct hashstate state;
initialize_hash(&state);
feed_hash(&state, key, keylen);
finalize_hash(&state, padded_key);
} else {
// Copy the key and zero-pad if necessary
memset(padded_key, 0, 32);
memcpy(padded_key, key, keylen);
}
// Outer and inner key derivation
unsigned char outer_key[32], inner_key[32];
for (size_t i = 0; i < 32; i++) {
outer_key[i] = padded_key[i] ^ 0x5c;
inner_key[i] = padded_key[i] ^ 0x36;
}
// Inner hash
unsigned char inner_hash[32];
struct hashstate state;
initialize_hash(&state);
feed_hash(&state, inner_key, 32);
feed_hash(&state, message, messagelen);
finalize_hash(&state, inner_hash);
// Outer hash
initialize_hash(&state);
feed_hash(&state, outer_key, 32);
feed_hash(&state, inner_hash, 32);
finalize_hash(&state, output);
}