]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/hmac.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
9 #define HMAC_BLOCK_SIZE 64
10 #define INNER_PADDING_BYTE 0x36
11 #define OUTER_PADDING_BYTE 0x5c
13 void hmac_sha256(const void *key
,
17 uint8_t res
[static SHA256_DIGEST_SIZE
]) {
19 uint8_t inner_padding
[HMAC_BLOCK_SIZE
] = { };
20 uint8_t outer_padding
[HMAC_BLOCK_SIZE
] = { };
21 uint8_t replacement_key
[SHA256_DIGEST_SIZE
];
22 struct sha256_ctx hash
;
28 /* Implement algorithm as described by FIPS 198. */
30 /* The key needs to be block size length or less, hash it if it's longer. */
31 if (key_size
> HMAC_BLOCK_SIZE
) {
32 sha256_init_ctx(&hash
);
33 sha256_process_bytes(key
, key_size
, &hash
);
34 sha256_finish_ctx(&hash
, replacement_key
);
35 key
= replacement_key
;
36 key_size
= SHA256_DIGEST_SIZE
;
39 /* First, copy the key into the padding arrays. If it's shorter than
40 * the block size, the arrays are already initialized to 0. */
41 memcpy(inner_padding
, key
, key_size
);
42 memcpy(outer_padding
, key
, key_size
);
44 /* Then, XOR the provided key and any padding leftovers with the fixed
45 * padding bytes as defined in FIPS 198. */
46 for (size_t i
= 0; i
< HMAC_BLOCK_SIZE
; i
++) {
47 inner_padding
[i
] ^= INNER_PADDING_BYTE
;
48 outer_padding
[i
] ^= OUTER_PADDING_BYTE
;
51 /* First pass: hash the inner padding array and the input. */
52 sha256_init_ctx(&hash
);
53 sha256_process_bytes(inner_padding
, HMAC_BLOCK_SIZE
, &hash
);
54 sha256_process_bytes(input
, input_size
, &hash
);
55 sha256_finish_ctx(&hash
, res
);
57 /* Second pass: hash the outer padding array and the result of the first pass. */
58 sha256_init_ctx(&hash
);
59 sha256_process_bytes(outer_padding
, HMAC_BLOCK_SIZE
, &hash
);
60 sha256_process_bytes(res
, SHA256_DIGEST_SIZE
, &hash
);
61 sha256_finish_ctx(&hash
, res
);