Skip to content

Commit 58a51a8

Browse files
committed
Add SHA256 HMAC
SPHINCS+ need HMAC
1 parent 4df06e7 commit 58a51a8

File tree

2 files changed

+87
-1
lines changed

2 files changed

+87
-1
lines changed

include/gmssl/sha2.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2024 The GmSSL Project. All Rights Reserved.
2+
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the License); you may
55
* not use this file except in compliance with the License.
@@ -88,6 +88,18 @@ void sha512_update(SHA512_CTX *ctx, const uint8_t* data, size_t datalen);
8888
void sha512_finish(SHA512_CTX *ctx, uint8_t dgst[SHA512_DIGEST_SIZE]);
8989

9090

91+
#define SHA256_HMAC_SIZE (SHA256_DIGEST_SIZE)
92+
93+
typedef struct {
94+
SHA256_CTX sha256_ctx;
95+
uint8_t key[SHA256_BLOCK_SIZE];
96+
} SHA256_HMAC_CTX;
97+
98+
void sha256_hmac_init(SHA256_HMAC_CTX *ctx, const uint8_t *key, size_t keylen);
99+
void sha256_hmac_update(SHA256_HMAC_CTX *ctx, const uint8_t *data, size_t datalen);
100+
void sha256_hmac_finish(SHA256_HMAC_CTX *ctx, uint8_t mac[SHA256_HMAC_SIZE]);
101+
102+
91103
#ifdef __cplusplus
92104
}
93105
#endif

src/sha256_hmac.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the License); you may
5+
* not use this file except in compliance with the License.
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*/
9+
10+
11+
#include <string.h>
12+
#include <gmssl/sha2.h>
13+
#include <gmssl/error.h>
14+
15+
/**
16+
* HMAC_k(m) = H((k ^ opad) || H((k ^ ipad) || m))
17+
* pseudo-code:
18+
* function hmac(key, message)
19+
* opad = [0x5c * blocksize]
20+
* ipad = [0x36 * blocksize]
21+
* if (length(key) > blocksize) then
22+
* key = hash(key)
23+
* end if
24+
* for i from 0 to length(key) - 1 step 1
25+
* ipad[i] = ipad[i] XOR key[i]
26+
* opad[i] = opad[i] XOR key[i]
27+
* end for
28+
* return hash(opad || hash(ipad || message))
29+
* end function
30+
*/
31+
32+
33+
#define IPAD 0x36
34+
#define OPAD 0x5C
35+
36+
void sha256_hmac_init(SHA256_HMAC_CTX *ctx, const uint8_t *key, size_t key_len)
37+
{
38+
int i;
39+
40+
if (key_len <= SHA256_BLOCK_SIZE) {
41+
memcpy(ctx->key, key, key_len);
42+
memset(ctx->key + key_len, 0, SHA256_BLOCK_SIZE - key_len);
43+
} else {
44+
sha256_init(&ctx->sha256_ctx);
45+
sha256_update(&ctx->sha256_ctx, key, key_len);
46+
sha256_finish(&ctx->sha256_ctx, ctx->key);
47+
memset(ctx->key + SHA256_DIGEST_SIZE, 0,
48+
SHA256_BLOCK_SIZE - SHA256_DIGEST_SIZE);
49+
}
50+
for (i = 0; i < SHA256_BLOCK_SIZE; i++) {
51+
ctx->key[i] ^= IPAD;
52+
}
53+
54+
sha256_init(&ctx->sha256_ctx);
55+
sha256_update(&ctx->sha256_ctx, ctx->key, SHA256_BLOCK_SIZE);
56+
}
57+
58+
void sha256_hmac_update(SHA256_HMAC_CTX *ctx, const uint8_t *data, size_t data_len)
59+
{
60+
sha256_update(&ctx->sha256_ctx, data, data_len);
61+
}
62+
63+
void sha256_hmac_finish(SHA256_HMAC_CTX *ctx, uint8_t mac[SHA256_HMAC_SIZE])
64+
{
65+
int i;
66+
for (i = 0; i < SHA256_BLOCK_SIZE; i++) {
67+
ctx->key[i] ^= (IPAD ^ OPAD);
68+
}
69+
sha256_finish(&ctx->sha256_ctx, mac);
70+
sha256_init(&ctx->sha256_ctx);
71+
sha256_update(&ctx->sha256_ctx, ctx->key, SHA256_BLOCK_SIZE);
72+
sha256_update(&ctx->sha256_ctx, mac, SHA256_DIGEST_SIZE);
73+
sha256_finish(&ctx->sha256_ctx, mac);
74+
}

0 commit comments

Comments
 (0)