mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-05-07 00:46:17 +08:00
Remove HASH_DRBG
This commit is contained in:
@@ -98,7 +98,6 @@ set(src
|
||||
src/sm9_exch.c
|
||||
src/zuc.c
|
||||
src/zuc_modes.c
|
||||
src/hash_drbg.c
|
||||
src/block_cipher.c
|
||||
src/digest.c
|
||||
src/hmac.c
|
||||
@@ -196,7 +195,6 @@ set(tests
|
||||
sm2_enc
|
||||
sm9
|
||||
zuc
|
||||
hash_drbg
|
||||
block_cipher
|
||||
digest
|
||||
hmac
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2022 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
|
||||
*/
|
||||
|
||||
|
||||
/* NIST SP800-90A Rev.1 "Recommendation for Random Number Generation
|
||||
* Using Deterministic Random Bit Generators", 10.1.1 Hash_DRBG */
|
||||
|
||||
#ifndef GMSSL_HASH_DRBG_H
|
||||
#define GMSSL_HASH_DRBG_H
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <gmssl/digest.h>
|
||||
|
||||
|
||||
/* seedlen for hash_drgb, table 2 of nist sp 800-90a rev.1 */
|
||||
#define HASH_DRBG_SM3_SEED_BITS 440 /* 55 bytes */
|
||||
#define HASH_DRBG_SHA1_SEED_BITS 440
|
||||
#define HASH_DRBG_SHA224_SEED_BITS 440
|
||||
#define HASH_DRBG_SHA512_224_SEED_BITS 440
|
||||
#define HASH_DRBG_SHA256_SEED_BITS 440
|
||||
#define HASH_DRBG_SHA512_256_SEED_BITS 440
|
||||
#define HASH_DRBG_SHA384_SEED_BITS 888 /* 110 bytes */
|
||||
#define HASH_DRBG_SHA512_SEED_BITS 888
|
||||
#define HASH_DRBG_MAX_SEED_BITS 888
|
||||
|
||||
#define HASH_DRBG_SM3_SEED_SIZE (HASH_DRBG_SM3_SEED_BITS/8)
|
||||
#define HASH_DRBG_SHA1_SEED_SIZE (HASH_DRBG_SHA1_SEED_BITS/8)
|
||||
#define HASH_DRBG_SHA224_SEED_SIZE (HASH_DRBG_SHA224_SEED_BITS/8)
|
||||
#define HASH_DRBG_SHA512_224_SEED_SIZE (HASH_DRBG_SHA512_224_SEED_BITS/8)
|
||||
#define HASH_DRBG_SHA256_SEED_SIZE (HASH_DRBG_SHA256_SEED_BITS/8)
|
||||
#define HASH_DRBG_SHA512_256_SEED_SIZE (HASH_DRBG_SHA512_256_SEED_BITS/8)
|
||||
#define HASH_DRBG_SHA384_SEED_SIZE (HASH_DRBG_SHA384_SEED_BITS/8)
|
||||
#define HASH_DRBG_SHA512_SEED_SIZE (HASH_DRBG_SHA512_SEED_BITS/8)
|
||||
#define HASH_DRBG_MAX_SEED_SIZE (HASH_DRBG_MAX_SEED_BITS/8)
|
||||
|
||||
#define HASH_DRBG_RESEED_INTERVAL ((uint64_t)1 << 48)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
const DIGEST *digest;
|
||||
uint8_t V[HASH_DRBG_MAX_SEED_SIZE];
|
||||
uint8_t C[HASH_DRBG_MAX_SEED_SIZE];
|
||||
size_t seedlen;
|
||||
uint64_t reseed_counter;
|
||||
} HASH_DRBG;
|
||||
|
||||
|
||||
int hash_drbg_init(HASH_DRBG *drbg,
|
||||
const DIGEST *digest,
|
||||
const uint8_t *entropy, size_t entropy_len,
|
||||
const uint8_t *nonce, size_t nonce_len,
|
||||
const uint8_t *personalstr, size_t personalstr_len);
|
||||
|
||||
int hash_drbg_reseed(HASH_DRBG *drbg,
|
||||
const uint8_t *entropy, size_t entropy_len,
|
||||
const uint8_t *additional, size_t additional_len);
|
||||
|
||||
int hash_drbg_generate(HASH_DRBG *drbg,
|
||||
const uint8_t *additional, size_t additional_len,
|
||||
size_t outlen, uint8_t *out);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
299
src/hash_drbg.c
299
src/hash_drbg.c
@@ -1,299 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2022 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <gmssl/hash_drbg.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/endian.h>
|
||||
|
||||
|
||||
static int hash_df(const DIGEST *digest, const uint8_t *in, size_t inlen,
|
||||
size_t outlen, uint8_t *out)
|
||||
{
|
||||
int ret = 0;
|
||||
DIGEST_CTX ctx;
|
||||
uint8_t counter;
|
||||
uint8_t outbits[4];
|
||||
unsigned char dgst[64];
|
||||
size_t len;
|
||||
|
||||
counter = 0x01;
|
||||
PUTU32(outbits, (uint32_t)outlen << 3);
|
||||
|
||||
while (outlen > 0) {
|
||||
if (digest_init(&ctx, digest) != 1
|
||||
|| digest_update(&ctx, &counter, sizeof(counter)) != 1
|
||||
|| digest_update(&ctx, outbits, sizeof(outbits)) != 1
|
||||
|| digest_update(&ctx, in, inlen) != 1
|
||||
|| digest_finish(&ctx, dgst, &len) != 1) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (outlen < len) {
|
||||
len = outlen;
|
||||
}
|
||||
memcpy(out, dgst, len);
|
||||
out += len;
|
||||
outlen -= len;
|
||||
|
||||
counter++;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
end:
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
memset(dgst, 0, sizeof(dgst));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hash_drbg_init(HASH_DRBG *drbg, const DIGEST *digest,
|
||||
const uint8_t *entropy, size_t entropy_len,
|
||||
const uint8_t *nonce, size_t nonce_len,
|
||||
const uint8_t *personalstr, size_t personalstr_len)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned char *seed_material = NULL;
|
||||
size_t seed_material_len;
|
||||
uint8_t buf[1 + HASH_DRBG_MAX_SEED_SIZE];
|
||||
uint8_t *p;
|
||||
|
||||
memset(drbg, 0, sizeof(HASH_DRBG));
|
||||
|
||||
/* set digest */
|
||||
drbg->digest = digest;
|
||||
|
||||
/* set seedlen */
|
||||
if (digest->digest_size <= 32) {
|
||||
drbg->seedlen = HASH_DRBG_SM3_SEED_SIZE;
|
||||
} else {
|
||||
drbg->seedlen = HASH_DRBG_SHA512_SEED_SIZE;
|
||||
}
|
||||
|
||||
/* seed_material = entropy_input || nonce || personalization_string */
|
||||
seed_material_len = entropy_len + nonce_len + personalstr_len;
|
||||
if (!(seed_material = malloc(seed_material_len))) {
|
||||
return 0;
|
||||
}
|
||||
p = seed_material;
|
||||
memcpy(p, entropy, entropy_len);
|
||||
p += entropy_len;
|
||||
memcpy(p, nonce, nonce_len);
|
||||
p += nonce_len;
|
||||
memcpy(p, personalstr, personalstr_len);
|
||||
|
||||
/* V = Hash_df (seed_material, seedlen) */
|
||||
if (!hash_df(drbg->digest, seed_material, seed_material_len, drbg->seedlen,
|
||||
drbg->V)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* C = Hash_df ((0x00 || V), seedlen) */
|
||||
buf[0] = 0x00;
|
||||
memcpy(buf + 1, drbg->V, drbg->seedlen);
|
||||
if (!hash_df(drbg->digest, buf, 1 + drbg->seedlen, drbg->seedlen,
|
||||
drbg->C)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* reseed_counter = 1 */
|
||||
drbg->reseed_counter = 1;
|
||||
|
||||
ret = 1;
|
||||
end:
|
||||
if (seed_material) {
|
||||
memset(seed_material, 0, seed_material_len);
|
||||
free(seed_material);
|
||||
}
|
||||
memset(buf, 0, sizeof(buf));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hash_drbg_reseed(HASH_DRBG *drbg,
|
||||
const uint8_t *entropy, size_t entropy_len,
|
||||
const uint8_t *additional, size_t additional_len)
|
||||
{
|
||||
int ret = 0;
|
||||
uint8_t *seed_material = NULL;
|
||||
size_t seed_material_len;
|
||||
uint8_t *p;
|
||||
uint8_t buf[1 + HASH_DRBG_MAX_SEED_SIZE];
|
||||
|
||||
/* seed_material = 0x01 || V || entropy_input || additional_input */
|
||||
seed_material_len = 1 + drbg->seedlen + entropy_len + additional_len;
|
||||
if (!(seed_material = malloc(seed_material_len))) {
|
||||
return 0;
|
||||
}
|
||||
seed_material[0] = 0x01;
|
||||
p = seed_material + 1;
|
||||
memcpy(p, drbg->V, drbg->seedlen);
|
||||
p += drbg->seedlen;
|
||||
memcpy(p, entropy, entropy_len);
|
||||
p += entropy_len;
|
||||
memcpy(p, additional, additional_len);
|
||||
|
||||
/* V = Hash_df(seed_material, seedlen) */
|
||||
if (!hash_df(drbg->digest, seed_material, seed_material_len, drbg->seedlen,
|
||||
drbg->V)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* C = Hash_df((0x00 || V), seedlen) */
|
||||
buf[0] = 0x00;
|
||||
memcpy(buf + 1, drbg->V, drbg->seedlen);
|
||||
if (!hash_df(drbg->digest, buf, 1 + drbg->seedlen, drbg->seedlen,
|
||||
drbg->C)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* reseed_counter = 1 */
|
||||
drbg->reseed_counter = 1;
|
||||
|
||||
ret = 1;
|
||||
end:
|
||||
if (seed_material) {
|
||||
memset(seed_material, 0, seed_material_len);
|
||||
free(seed_material);
|
||||
}
|
||||
memset(buf, 0, sizeof(buf));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* seedlen is always >= dgstlen
|
||||
* R0 ... Ru-v .. .. .. Ru-1
|
||||
* + A0 A1 A2 .. Av-1
|
||||
*/
|
||||
static void drbg_add(uint8_t *R, const uint8_t *A, size_t seedlen)
|
||||
{
|
||||
int temp = 0;
|
||||
while (seedlen--) {
|
||||
temp += R[seedlen] + A[seedlen];
|
||||
R[seedlen] = temp & 0xff;
|
||||
temp >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
static void drbg_add1(uint8_t *R, size_t seedlen)
|
||||
{
|
||||
int temp = 1;
|
||||
while (seedlen--) {
|
||||
temp += R[seedlen];
|
||||
R[seedlen] = temp & 0xff;
|
||||
temp >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
static int drbg_hashgen(HASH_DRBG *drbg, size_t outlen, uint8_t *out)
|
||||
{
|
||||
int ret = 0;
|
||||
DIGEST_CTX ctx;
|
||||
uint8_t data[HASH_DRBG_MAX_SEED_SIZE];
|
||||
uint8_t dgst[DIGEST_MAX_SIZE];
|
||||
size_t len;
|
||||
|
||||
/* data = V */
|
||||
memcpy(data, drbg->V, drbg->seedlen);
|
||||
|
||||
while (outlen > 0) {
|
||||
|
||||
/* output Hash(data) */
|
||||
if (digest_init(&ctx, drbg->digest) != 1
|
||||
|| digest_update(&ctx, data, drbg->seedlen) != 1
|
||||
|| digest_finish(&ctx, dgst, &len) != 1) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (outlen < len) {
|
||||
len = outlen;
|
||||
}
|
||||
memcpy(out, dgst, len);
|
||||
out += len;
|
||||
outlen -= len;
|
||||
|
||||
/* data = (data + 1) mod 2^seedlen */
|
||||
drbg_add1(data, drbg->seedlen);
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
end:
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
memset(data, 0, sizeof(data));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hash_drbg_generate(HASH_DRBG *drbg,
|
||||
const uint8_t *additional, size_t additional_len,
|
||||
size_t outlen, uint8_t *out)
|
||||
{
|
||||
int ret = 0;
|
||||
DIGEST_CTX ctx;
|
||||
uint8_t prefix;
|
||||
uint8_t T[HASH_DRBG_MAX_SEED_SIZE];
|
||||
uint8_t dgst[DIGEST_MAX_SIZE];
|
||||
size_t dgstlen;
|
||||
|
||||
// FIXME: check outlen max value
|
||||
|
||||
if (drbg->reseed_counter > HASH_DRBG_RESEED_INTERVAL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (additional) {
|
||||
/* w = Hash (0x02 || V || additional_input) */
|
||||
prefix = 0x02;
|
||||
if (digest_init(&ctx, drbg->digest) != 1
|
||||
|| digest_update(&ctx, &prefix, 1) != 1
|
||||
|| digest_update(&ctx, drbg->V, drbg->seedlen) != 1
|
||||
|| digest_update(&ctx, additional, additional_len) != 1
|
||||
|| digest_finish(&ctx, dgst, &dgstlen) != 1) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* V = (V + w) mod 2^seedlen */
|
||||
memset(T, 0, drbg->seedlen - dgstlen);
|
||||
memcpy(T + drbg->seedlen - dgstlen, dgst, dgstlen);
|
||||
drbg_add(drbg->V, T, drbg->seedlen);
|
||||
}
|
||||
|
||||
/* (returned_bits) = Hashgen (requested_number_of_bits, V). */
|
||||
drbg_hashgen(drbg, outlen, out);
|
||||
|
||||
/* H = Hash (0x03 || V). */
|
||||
prefix = 0x03;
|
||||
if (digest_init(&ctx, drbg->digest) != 1
|
||||
|| digest_update(&ctx, &prefix, 1) != 1
|
||||
|| digest_update(&ctx, drbg->V, drbg->seedlen) != 1
|
||||
|| digest_finish(&ctx, dgst, &dgstlen) != 1) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* V = (V + H + C + reseed_counter) mod 2^seedlen */
|
||||
memset(T, 0, drbg->seedlen - dgstlen);
|
||||
memcpy(T + drbg->seedlen - dgstlen, dgst, dgstlen);
|
||||
drbg_add(drbg->V, T, drbg->seedlen);
|
||||
|
||||
drbg_add(drbg->V, drbg->C, drbg->seedlen);
|
||||
|
||||
memset(T, 0, drbg->seedlen - sizeof(uint64_t));
|
||||
PUTU64(T + drbg->seedlen - sizeof(uint64_t), drbg->reseed_counter);
|
||||
drbg_add(drbg->V, T, drbg->seedlen);
|
||||
|
||||
/* reseed_counter = reseed_counter + 1 */
|
||||
drbg->reseed_counter++;
|
||||
|
||||
ret = 1;
|
||||
end:
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
memset(T, 0, sizeof(T));
|
||||
memset(dgst, 0, sizeof(dgst));
|
||||
return ret;
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014-2022 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <gmssl/hex.h>
|
||||
#include <gmssl/digest.h>
|
||||
#include <gmssl/hash_drbg.h>
|
||||
#include <gmssl/error.h>
|
||||
|
||||
|
||||
#define EntropyInput "212956390783381dbfc6362dd0da9a09"
|
||||
#define Nonce "5280987fc5e27a49"
|
||||
#define PersonalizationString ""
|
||||
#define AdditionalInput ""
|
||||
#define V0 "02b84eba8121ca090b6b66d3371609eaf76405a5c2807d80035c1a13dfed5aa18e536af599a7b3c68b2c56240ed11997f4048910d84604"
|
||||
#define C0 "a677e4921587563eebe55d1b25e59c3f3d200bc61aaee665e7a6858c2857c45dba4bce8182252962ae86de491046a5e3450eec44938a0a"
|
||||
|
||||
#define AdditionalInput1 ""
|
||||
#define EntropyInputPR1 "2edb396eeb8960f77943c2a59075a786"
|
||||
#define V1 "f9afadfbbf2c3d1004f9baca38be247342e5fbb83281915d5de18beb963712a344e89bb0e6b925a7bbc32eadb8b441efc1fa0c649df42a"
|
||||
#define C1 "1d41cbbd634909e4761c232fcfd6a6c2edf0a7f4d3d3c164f74a88955f355efce2d86c1e9fa897b7005ef9d4d3a51bf4fc0b805ab896c9"
|
||||
|
||||
#define PR1 "2edb396eeb8960f77943c2a59075a786"
|
||||
#define PR2 "30b565b63a5012676940d3ef17d9e996"
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// currently we only has SHA-1 test suites
|
||||
#ifdef ENABLE_SHA1
|
||||
HASH_DRBG drbg;
|
||||
|
||||
uint8_t entropy[sizeof(EntropyInput)/2];
|
||||
uint8_t nonce[sizeof(Nonce)/2];
|
||||
uint8_t personalstr[1 + sizeof(PersonalizationString)/2];
|
||||
uint8_t v[sizeof(V0)/2];
|
||||
uint8_t c[sizeof(C0)/2];
|
||||
uint8_t entropy_pr1[sizeof(EntropyInputPR1)/2];
|
||||
uint8_t pr1[sizeof(PR1)/2];
|
||||
uint8_t pr2[sizeof(PR2)/2];
|
||||
size_t entropy_len, nonce_len, personalstr_len, vlen, clen;
|
||||
size_t entropy_pr1len;
|
||||
size_t pr1_len, pr2_len;
|
||||
unsigned char out[640/8];
|
||||
int i;
|
||||
|
||||
hex_to_bytes(EntropyInput, strlen(EntropyInput), entropy, &entropy_len);
|
||||
hex_to_bytes(Nonce, strlen(Nonce), nonce, &nonce_len);
|
||||
hex_to_bytes(PersonalizationString, strlen(PersonalizationString), personalstr, &personalstr_len);
|
||||
hex_to_bytes(V0, strlen(V0), v, &vlen);
|
||||
hex_to_bytes(C0, strlen(C0), c, &clen);
|
||||
hex_to_bytes(EntropyInputPR1, strlen(EntropyInputPR1), entropy_pr1, &entropy_pr1len);
|
||||
hex_to_bytes(PR1, strlen(PR1), pr1, &pr1_len);
|
||||
hex_to_bytes(PR2, strlen(PR2), pr2, &pr2_len);
|
||||
|
||||
hash_drbg_init(&drbg, DIGEST_sha1(),
|
||||
entropy, entropy_len,
|
||||
nonce, nonce_len,
|
||||
personalstr, personalstr_len);
|
||||
|
||||
printf("sha1_drbg test 1 ");
|
||||
if (drbg.seedlen != vlen
|
||||
|| memcmp(drbg.V, v, vlen) != 0
|
||||
|| memcmp(drbg.C, c, clen) != 0
|
||||
|| drbg.reseed_counter != 1) {
|
||||
printf("failed\n");
|
||||
return 1;
|
||||
} else {
|
||||
printf("ok\n");
|
||||
}
|
||||
|
||||
hash_drbg_reseed(&drbg, pr1, pr1_len, NULL, 0);
|
||||
hash_drbg_generate(&drbg, NULL, 0, 640/8, out);
|
||||
|
||||
hash_drbg_reseed(&drbg, pr2, pr2_len, NULL, 0);
|
||||
hash_drbg_generate(&drbg, NULL, 0, 640/8, out);
|
||||
|
||||
for (i = 0; i < sizeof(out); i++) {
|
||||
printf("%02x", out[i]);
|
||||
}
|
||||
printf("\n");
|
||||
#endif // ENABLE_SHA1
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user