Implement (modified) HMAC
This commit is contained in:
parent
08c8d33b20
commit
9a0b35609b
43
puer.c
43
puer.c
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue