udev: String substitutions can be done in ENV, too
[systemd_ALT.git] / src / basic / hmac.c
bloba5f66d560566b93c53152649613b282ae69adbcb
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 #include <assert.h>
4 #include <string.h>
6 #include "hmac.h"
7 #include "sha256.h"
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,
14 size_t key_size,
15 const void *input,
16 size_t input_size,
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;
24 assert(key);
25 assert(key_size > 0);
26 assert(res);
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_direct(key, key_size, replacement_key);
33 key = replacement_key;
34 key_size = SHA256_DIGEST_SIZE;
37 /* First, copy the key into the padding arrays. If it's shorter than
38 * the block size, the arrays are already initialized to 0. */
39 memcpy(inner_padding, key, key_size);
40 memcpy(outer_padding, key, key_size);
42 /* Then, XOR the provided key and any padding leftovers with the fixed
43 * padding bytes as defined in FIPS 198. */
44 for (size_t i = 0; i < HMAC_BLOCK_SIZE; i++) {
45 inner_padding[i] ^= INNER_PADDING_BYTE;
46 outer_padding[i] ^= OUTER_PADDING_BYTE;
49 /* First pass: hash the inner padding array and the input. */
50 sha256_init_ctx(&hash);
51 sha256_process_bytes(inner_padding, HMAC_BLOCK_SIZE, &hash);
52 sha256_process_bytes(input, input_size, &hash);
53 sha256_finish_ctx(&hash, res);
55 /* Second pass: hash the outer padding array and the result of the first pass. */
56 sha256_init_ctx(&hash);
57 sha256_process_bytes(outer_padding, HMAC_BLOCK_SIZE, &hash);
58 sha256_process_bytes(res, SHA256_DIGEST_SIZE, &hash);
59 sha256_finish_ctx(&hash, res);