Add SHA256 HMAC

SPHINCS+ need HMAC
This commit is contained in:
Zhi Guan
2026-01-11 15:19:42 +08:00
parent 4df06e7196
commit 58a51a8474
2 changed files with 87 additions and 1 deletions

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2014-2024 The GmSSL Project. All Rights Reserved. * Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
* *
* Licensed under the Apache License, Version 2.0 (the License); you may * Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License. * 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);
void sha512_finish(SHA512_CTX *ctx, uint8_t dgst[SHA512_DIGEST_SIZE]); void sha512_finish(SHA512_CTX *ctx, uint8_t dgst[SHA512_DIGEST_SIZE]);
#define SHA256_HMAC_SIZE (SHA256_DIGEST_SIZE)
typedef struct {
SHA256_CTX sha256_ctx;
uint8_t key[SHA256_BLOCK_SIZE];
} SHA256_HMAC_CTX;
void sha256_hmac_init(SHA256_HMAC_CTX *ctx, const uint8_t *key, size_t keylen);
void sha256_hmac_update(SHA256_HMAC_CTX *ctx, const uint8_t *data, size_t datalen);
void sha256_hmac_finish(SHA256_HMAC_CTX *ctx, uint8_t mac[SHA256_HMAC_SIZE]);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

74
src/sha256_hmac.c Normal file
View File

@@ -0,0 +1,74 @@
/*
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
#include <string.h>
#include <gmssl/sha2.h>
#include <gmssl/error.h>
/**
* HMAC_k(m) = H((k ^ opad) || H((k ^ ipad) || m))
* pseudo-code:
* function hmac(key, message)
* opad = [0x5c * blocksize]
* ipad = [0x36 * blocksize]
* if (length(key) > blocksize) then
* key = hash(key)
* end if
* for i from 0 to length(key) - 1 step 1
* ipad[i] = ipad[i] XOR key[i]
* opad[i] = opad[i] XOR key[i]
* end for
* return hash(opad || hash(ipad || message))
* end function
*/
#define IPAD 0x36
#define OPAD 0x5C
void sha256_hmac_init(SHA256_HMAC_CTX *ctx, const uint8_t *key, size_t key_len)
{
int i;
if (key_len <= SHA256_BLOCK_SIZE) {
memcpy(ctx->key, key, key_len);
memset(ctx->key + key_len, 0, SHA256_BLOCK_SIZE - key_len);
} else {
sha256_init(&ctx->sha256_ctx);
sha256_update(&ctx->sha256_ctx, key, key_len);
sha256_finish(&ctx->sha256_ctx, ctx->key);
memset(ctx->key + SHA256_DIGEST_SIZE, 0,
SHA256_BLOCK_SIZE - SHA256_DIGEST_SIZE);
}
for (i = 0; i < SHA256_BLOCK_SIZE; i++) {
ctx->key[i] ^= IPAD;
}
sha256_init(&ctx->sha256_ctx);
sha256_update(&ctx->sha256_ctx, ctx->key, SHA256_BLOCK_SIZE);
}
void sha256_hmac_update(SHA256_HMAC_CTX *ctx, const uint8_t *data, size_t data_len)
{
sha256_update(&ctx->sha256_ctx, data, data_len);
}
void sha256_hmac_finish(SHA256_HMAC_CTX *ctx, uint8_t mac[SHA256_HMAC_SIZE])
{
int i;
for (i = 0; i < SHA256_BLOCK_SIZE; i++) {
ctx->key[i] ^= (IPAD ^ OPAD);
}
sha256_finish(&ctx->sha256_ctx, mac);
sha256_init(&ctx->sha256_ctx);
sha256_update(&ctx->sha256_ctx, ctx->key, SHA256_BLOCK_SIZE);
sha256_update(&ctx->sha256_ctx, mac, SHA256_DIGEST_SIZE);
sha256_finish(&ctx->sha256_ctx, mac);
}