diff --git a/ChaCha20_DRBG.c b/ChaCha20_DRBG.c index 50fb1b3..c1d6895 100755 --- a/ChaCha20_DRBG.c +++ b/ChaCha20_DRBG.c @@ -1,11 +1,12 @@ -#include -#include -#include -#include -#include -#include -#include #include +#include +#include +#include +#include +#include +#include +#include + // #include #define SUCCESS 0 @@ -27,7 +28,7 @@ #define MAX_STATES 100 #define INVALID_HANDLE -1 -// for Get_entropy_input +// for get_entropy_input #define reseed_interval_in_counter pow(2, 10) // (次) #define reseed_interval_in_time 60 //(秒) @@ -38,162 +39,149 @@ #define HASH_SIZE 32 /*----------------熵源的相关定义与函数----------------*/ -typedef struct -{ - uint8_t data[BLOCK_SIZE]; - uint32_t datalen; - uint64_t bitlen; - uint32_t state[8]; +typedef struct { + uint8_t data[BLOCK_SIZE]; + uint32_t datalen; + uint64_t bitlen; + uint32_t state[8]; } SHA256_CTX; -void sha256_transform(SHA256_CTX *ctx, const uint8_t data[]) -{ - uint32_t a, b, c, d, e, f, g, h, i, j, t1, t2, m[64]; +void sha256_transform(SHA256_CTX *ctx, const uint8_t data[]) { + uint32_t a, b, c, d, e, f, g, h, i, j, t1, t2, m[64]; - for (i = 0, j = 0; i < 16; ++i, j += 4) - { - m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]); - } + for (i = 0, j = 0; i < 16; ++i, j += 4) { + m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | + (data[j + 3]); + } - for (; i < 64; ++i) - { - m[i] = m[i - 16] + m[i - 7] + (m[i - 15] >> 7) + (m[i - 15] << 25) ^ (m[i - 15] >> 18) + (m[i - 15] << 14) ^ (m[i - 15] >> 3) + (m[i - 15] << 13); - } + for (; i < 64; ++i) { + m[i] = m[i - 16] + m[i - 7] + (m[i - 15] >> 7) + (m[i - 15] << 25) ^ + (m[i - 15] >> 18) + (m[i - 15] << 14) ^ + (m[i - 15] >> 3) + (m[i - 15] << 13); + } - a = ctx->state[0]; - b = ctx->state[1]; - c = ctx->state[2]; - d = ctx->state[3]; - e = ctx->state[4]; - f = ctx->state[5]; - g = ctx->state[6]; - h = ctx->state[7]; + a = ctx->state[0]; + b = ctx->state[1]; + c = ctx->state[2]; + d = ctx->state[3]; + e = ctx->state[4]; + f = ctx->state[5]; + g = ctx->state[6]; + h = ctx->state[7]; - for (i = 0; i < 64; ++i) - { - t1 = h + (e >> 6) + ((e & f) ^ (~e & g)) + 0x428a2f98 + m[i]; - t2 = (a >> 2) + ((a & b) ^ (a & c) ^ (b & c)) + 0x5a827999; + for (i = 0; i < 64; ++i) { + t1 = h + (e >> 6) + ((e & f) ^ (~e & g)) + 0x428a2f98 + m[i]; + t2 = (a >> 2) + ((a & b) ^ (a & c) ^ (b & c)) + 0x5a827999; - h = g; - g = f; - f = e; - e = d + t1; - d = c; - c = b; - b = a; - a = t1 + t2; - } + h = g; + g = f; + f = e; + e = d + t1; + d = c; + c = b; + b = a; + a = t1 + t2; + } - ctx->state[0] += a; - ctx->state[1] += b; - ctx->state[2] += c; - ctx->state[3] += d; - ctx->state[4] += e; - ctx->state[5] += f; - ctx->state[6] += g; - ctx->state[7] += h; + ctx->state[0] += a; + ctx->state[1] += b; + ctx->state[2] += c; + ctx->state[3] += d; + ctx->state[4] += e; + ctx->state[5] += f; + ctx->state[6] += g; + ctx->state[7] += h; } -void sha256_init(SHA256_CTX *ctx) -{ - ctx->datalen = 0; - ctx->bitlen = 0; - ctx->state[0] = 0x6a09e667; - ctx->state[1] = 0xbb67ae85; - ctx->state[2] = 0x3c6ef372; - ctx->state[3] = 0xa54ff53a; - ctx->state[4] = 0x510e527f; - ctx->state[5] = 0x9b05688c; - ctx->state[6] = 0x1f83d9ab; - ctx->state[7] = 0x5be0cd19; +void sha256_init(SHA256_CTX *ctx) { + ctx->datalen = 0; + ctx->bitlen = 0; + ctx->state[0] = 0x6a09e667; + ctx->state[1] = 0xbb67ae85; + ctx->state[2] = 0x3c6ef372; + ctx->state[3] = 0xa54ff53a; + ctx->state[4] = 0x510e527f; + ctx->state[5] = 0x9b05688c; + ctx->state[6] = 0x1f83d9ab; + ctx->state[7] = 0x5be0cd19; } -void sha256_update(SHA256_CTX *ctx, const uint8_t data[], size_t len) -{ - uint32_t i; +void sha256_update(SHA256_CTX *ctx, const uint8_t data[], size_t len) { + uint32_t i; - for (i = 0; i < len; ++i) - { - ctx->data[ctx->datalen] = data[i]; - ctx->datalen++; - if (ctx->datalen == BLOCK_SIZE) - { - sha256_transform(ctx, ctx->data); - ctx->bitlen += BLOCK_SIZE * 8; - ctx->datalen = 0; - } + for (i = 0; i < len; ++i) { + ctx->data[ctx->datalen] = data[i]; + ctx->datalen++; + if (ctx->datalen == BLOCK_SIZE) { + sha256_transform(ctx, ctx->data); + ctx->bitlen += BLOCK_SIZE * 8; + ctx->datalen = 0; } + } } -void sha256_final(SHA256_CTX *ctx, uint8_t hash[]) -{ - uint32_t i; +void sha256_final(SHA256_CTX *ctx, uint8_t hash[]) { + uint32_t i; - i = ctx->datalen; - - // Pad whatever data is left in the buffer - if (ctx->datalen < 56) - { - ctx->data[i++] = 0x80; - while (i < 56) - ctx->data[i++] = 0x00; - } - else - { - ctx->data[i++] = 0x80; - while (i < BLOCK_SIZE) - ctx->data[i++] = 0x00; - sha256_transform(ctx, ctx->data); - memset(ctx->data, 0, BLOCK_SIZE); - } - - // Append the total bit length of the input data - ctx->bitlen += ctx->datalen * 8; - ctx->data[BLOCK_SIZE - 1] = ctx->bitlen; - ctx->data[BLOCK_SIZE - 2] = ctx->bitlen >> 8; - ctx->data[BLOCK_SIZE - 3] = ctx->bitlen >> 16; - ctx->data[BLOCK_SIZE - 4] = ctx->bitlen >> 24; - ctx->data[BLOCK_SIZE - 5] = ctx->bitlen >> 32; - ctx->data[BLOCK_SIZE - 6] = ctx->bitlen >> 40; - ctx->data[BLOCK_SIZE - 7] = ctx->bitlen >> 48; - ctx->data[BLOCK_SIZE - 8] = ctx->bitlen >> 56; + i = ctx->datalen; + // Pad whatever data is left in the buffer + if (ctx->datalen < 56) { + ctx->data[i++] = 0x80; + while (i < 56) + ctx->data[i++] = 0x00; + } else { + ctx->data[i++] = 0x80; + while (i < BLOCK_SIZE) + ctx->data[i++] = 0x00; sha256_transform(ctx, ctx->data); + memset(ctx->data, 0, BLOCK_SIZE); + } - // Since this implementation uses little endian byte ordering and SHA uses big endian, - // reverse all the bytes when copying the final state to the output hash. - for (i = 0; i < 4; ++i) - { - hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff; - hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff; - hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff; - hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff; - hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff; - hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff; - hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff; - hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff; - } + // Append the total bit length of the input data + ctx->bitlen += ctx->datalen * 8; + ctx->data[BLOCK_SIZE - 1] = ctx->bitlen; + ctx->data[BLOCK_SIZE - 2] = ctx->bitlen >> 8; + ctx->data[BLOCK_SIZE - 3] = ctx->bitlen >> 16; + ctx->data[BLOCK_SIZE - 4] = ctx->bitlen >> 24; + ctx->data[BLOCK_SIZE - 5] = ctx->bitlen >> 32; + ctx->data[BLOCK_SIZE - 6] = ctx->bitlen >> 40; + ctx->data[BLOCK_SIZE - 7] = ctx->bitlen >> 48; + ctx->data[BLOCK_SIZE - 8] = ctx->bitlen >> 56; + + sha256_transform(ctx, ctx->data); + + // Since this implementation uses little endian byte ordering and SHA uses big + // endian, reverse all the bytes when copying the final state to the output + // hash. + for (i = 0; i < 4; ++i) { + hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff; + hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff; + hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff; + hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff; + hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff; + hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff; + hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff; + hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff; + } } -void get_entropy_source(uint8_t *entropy_source) -{ - // Simulate an entropy source by generating random data - for (int i = 0; i < min_entropy_input_length; i++) - { - entropy_source[i] = rand() % 256; - } +void get_entropy_source(uint8_t *entropy_source) { + // Simulate an entropy source by generating random data + for (int i = 0; i < min_entropy_input_length; i++) { + entropy_source[i] = rand() % 256; + } } -void Get_entropy_input(const uint8_t *data, size_t len, uint8_t *entropy) -{ - SHA256_CTX ctx; - uint8_t hash[HASH_SIZE]; +void get_entropy_input(const uint8_t *data, size_t len, uint8_t *entropy) { + SHA256_CTX ctx; + uint8_t hash[HASH_SIZE]; - sha256_init(&ctx); - sha256_update(&ctx, data, len); - sha256_final(&ctx, hash); + sha256_init(&ctx); + sha256_update(&ctx, data, len); + sha256_final(&ctx, hash); - memcpy(entropy, hash, HASH_SIZE); + memcpy(entropy, hash, HASH_SIZE); } /*----------------------------------------------*/ @@ -202,30 +190,25 @@ void Get_entropy_input(const uint8_t *data, size_t len, uint8_t *entropy) #define RANDOM_BITS_NUMBER 100 #define RANDOM_BITS_SIZE 128 -int test_randomness(const unsigned char *bits) -{ - // Test the randomness of the given bits using the chi-squared test - int ones = 0, zeros = 0; - for (int i = 0; i < RANDOM_BITS_SIZE / 8; i++) - { - unsigned char byte = bits[i]; - for (int j = 0; j < 8; j++) - { - if ((byte >> j) & 0x01) - { - ones++; - } - else - { - zeros++; - } - } +int test_randomness(const unsigned char *bits) { + // Test the randomness of the given bits using the chi-squared test + int ones = 0, zeros = 0; + for (int i = 0; i < RANDOM_BITS_SIZE / 8; i++) { + unsigned char byte = bits[i]; + for (int j = 0; j < 8; j++) { + if ((byte >> j) & 0x01) { + ones++; + } else { + zeros++; + } } - double expected_ones = RANDOM_BITS_SIZE / 2.0; - double expected_zeros = RANDOM_BITS_SIZE / 2.0; - double chi_squared = (ones - expected_ones) * (ones - expected_ones) / expected_ones + - (zeros - expected_zeros) * (zeros - expected_zeros) / expected_zeros; - return chi_squared > 3.84; + } + double expected_ones = RANDOM_BITS_SIZE / 2.0; + double expected_zeros = RANDOM_BITS_SIZE / 2.0; + double chi_squared = + (ones - expected_ones) * (ones - expected_ones) / expected_ones + + (zeros - expected_zeros) * (zeros - expected_zeros) / expected_zeros; + return chi_squared > 3.84; } /*-------------------------------------------------------*/ @@ -233,128 +216,120 @@ int test_randomness(const unsigned char *bits) /*----------------ChaCha20的相关定义与函数------------------*/ #define ROTL32(v, n) (((v) << (n)) | ((v) >> (32 - (n)))) -#define U32TO8_LITTLE(p, v) \ - { \ - (p)[0] = (uint8_t)((v)); \ - (p)[1] = (uint8_t)((v) >> 8); \ - (p)[2] = (uint8_t)((v) >> 16); \ - (p)[3] = (uint8_t)((v) >> 24); \ - } +#define U32TO8_LITTLE(p, v) \ + { \ + (p)[0] = (uint8_t)((v)); \ + (p)[1] = (uint8_t)((v) >> 8); \ + (p)[2] = (uint8_t)((v) >> 16); \ + (p)[3] = (uint8_t)((v) >> 24); \ + } -#define U8TO32_LITTLE(p) \ - (((uint32_t)((p)[0])) | ((uint32_t)((p)[1]) << 8) | \ - ((uint32_t)((p)[2]) << 16) | ((uint32_t)((p)[3]) << 24)) +#define U8TO32_LITTLE(p) \ + (((uint32_t)((p)[0])) | ((uint32_t)((p)[1]) << 8) | \ + ((uint32_t)((p)[2]) << 16) | ((uint32_t)((p)[3]) << 24)) // ChaCha的轮函数 -#define QUARTERROUND(x, a, b, c, d) \ - x[a] += x[b]; \ - x[d] = ROTL32(x[d] ^ x[a], 16); \ - x[c] += x[d]; \ - x[b] = ROTL32(x[b] ^ x[c], 12); \ - x[a] += x[b]; \ - x[d] = ROTL32(x[d] ^ x[a], 8); \ - x[c] += x[d]; \ - x[b] = ROTL32(x[b] ^ x[c], 7); +#define QUARTERROUND(x, a, b, c, d) \ + x[a] += x[b]; \ + x[d] = ROTL32(x[d] ^ x[a], 16); \ + x[c] += x[d]; \ + x[b] = ROTL32(x[b] ^ x[c], 12); \ + x[a] += x[b]; \ + x[d] = ROTL32(x[d] ^ x[a], 8); \ + x[c] += x[d]; \ + x[b] = ROTL32(x[b] ^ x[c], 7); static const char sigma[] = "expand 32-byte k"; static const char tau[] = "expand 16-byte k"; -void ChaCha20_block(uint32_t state[16], uint32_t output[16]) -{ - int i; - memcpy(output, state, sizeof(uint32_t) * 16); +void ChaCha20_block(uint32_t state[16], uint32_t output[16]) { + int i; + memcpy(output, state, sizeof(uint32_t) * 16); - // 20轮操作,每轮包括4个quarterrounds,所以共80个quarterrounds - for (i = 0; i < 10; ++i) - { - // 双轮 - QUARTERROUND(output, 0, 4, 8, 12) - QUARTERROUND(output, 1, 5, 9, 13) - QUARTERROUND(output, 2, 6, 10, 14) - QUARTERROUND(output, 3, 7, 11, 15) - QUARTERROUND(output, 0, 5, 10, 15) - QUARTERROUND(output, 1, 6, 11, 12) - QUARTERROUND(output, 2, 7, 8, 13) - QUARTERROUND(output, 3, 4, 9, 14) - } + // 20轮操作,每轮包括4个quarterrounds,所以共80个quarterrounds + for (i = 0; i < 10; ++i) { + // 双轮 + QUARTERROUND(output, 0, 4, 8, 12) + QUARTERROUND(output, 1, 5, 9, 13) + QUARTERROUND(output, 2, 6, 10, 14) + QUARTERROUND(output, 3, 7, 11, 15) + QUARTERROUND(output, 0, 5, 10, 15) + QUARTERROUND(output, 1, 6, 11, 12) + QUARTERROUND(output, 2, 7, 8, 13) + QUARTERROUND(output, 3, 4, 9, 14) + } - for (i = 0; i < 16; ++i) - { - output[i] += state[i]; - } + for (i = 0; i < 16; ++i) { + output[i] += state[i]; + } } -void ChaCha20_setup(uint32_t state[16], const uint8_t key[32], const uint8_t nonce[12], uint8_t counter[4]) -{ - const char *constants = (key[16] != 0 || key[24] != 0) ? sigma : tau; +void ChaCha20_setup(uint32_t state[16], const uint8_t key[32], + const uint8_t nonce[12], uint8_t counter[4]) { + const char *constants = (key[16] != 0 || key[24] != 0) ? sigma : tau; - state[4] = U8TO32_LITTLE(key + 0); - state[5] = U8TO32_LITTLE(key + 4); - state[6] = U8TO32_LITTLE(key + 8); - state[7] = U8TO32_LITTLE(key + 12); - state[8] = U8TO32_LITTLE(key + 16); - state[9] = U8TO32_LITTLE(key + 20); - state[10] = U8TO32_LITTLE(key + 24); - state[11] = U8TO32_LITTLE(key + 28); + state[4] = U8TO32_LITTLE(key + 0); + state[5] = U8TO32_LITTLE(key + 4); + state[6] = U8TO32_LITTLE(key + 8); + state[7] = U8TO32_LITTLE(key + 12); + state[8] = U8TO32_LITTLE(key + 16); + state[9] = U8TO32_LITTLE(key + 20); + state[10] = U8TO32_LITTLE(key + 24); + state[11] = U8TO32_LITTLE(key + 28); - // 前四个变量包含常量 - state[0] = U8TO32_LITTLE(constants + 0); - state[1] = U8TO32_LITTLE(constants + 4); - state[2] = U8TO32_LITTLE(constants + 8); - state[3] = U8TO32_LITTLE(constants + 12); + // 前四个变量包含常量 + state[0] = U8TO32_LITTLE(constants + 0); + state[1] = U8TO32_LITTLE(constants + 4); + state[2] = U8TO32_LITTLE(constants + 8); + state[3] = U8TO32_LITTLE(constants + 12); - // 加入计数器 - state[12] = U8TO32_LITTLE(counter); + // 加入计数器 + state[12] = U8TO32_LITTLE(counter); - // 后三个变量包含nonce - state[13] = U8TO32_LITTLE(nonce + 0); - state[14] = U8TO32_LITTLE(nonce + 4); - state[15] = U8TO32_LITTLE(nonce + 8); + // 后三个变量包含nonce + state[13] = U8TO32_LITTLE(nonce + 0); + state[14] = U8TO32_LITTLE(nonce + 4); + state[15] = U8TO32_LITTLE(nonce + 8); } -void ChaCha20_encrypt(uint32_t state[16], const uint8_t *in, uint8_t *out, size_t length, bool increment_flag) -{ - uint32_t keystream[16]; - uint8_t *keystream_bytes = (uint8_t *)keystream; // 为XOR操作重新解释keystream - size_t remaining = length; - size_t i; +void ChaCha20_encrypt(uint32_t state[16], const uint8_t *in, uint8_t *out, + size_t length, bool increment_flag) { + uint32_t keystream[16]; + uint8_t *keystream_bytes = (uint8_t *)keystream; // 为XOR操作重新解释keystream + size_t remaining = length; + size_t i; - while (remaining > 0) - { - size_t bytes_to_use = remaining < 64 ? remaining : 64; // 每个block 64 bytes + while (remaining > 0) { + size_t bytes_to_use = remaining < 64 ? remaining : 64; // 每个block 64 bytes - ChaCha20_block(state, keystream); + ChaCha20_block(state, keystream); - for (i = 0; i < bytes_to_use; ++i) - { - out[i] = in[i] ^ keystream_bytes[i]; - } - if (increment_flag) - { - state[12] += 1; // 增加计数器 - if (state[12] == 0) - { - state[13] += 1; // 处理计数器溢出 - } - } - - remaining -= bytes_to_use; - in += bytes_to_use; - out += bytes_to_use; + for (i = 0; i < bytes_to_use; ++i) { + out[i] = in[i] ^ keystream_bytes[i]; } + if (increment_flag) { + state[12] += 1; // 增加计数器 + if (state[12] == 0) { + state[13] += 1; // 处理计数器溢出 + } + } + + remaining -= bytes_to_use; + in += bytes_to_use; + out += bytes_to_use; + } } /*----------------------------------------------------*/ // 定义ChaCha20_DRBG的内部状态 -typedef struct -{ - uint8_t Key[KEYLEN]; // 用于ChaCha20的密钥 - uint8_t V[COUNTERLEN]; // 用于ChaCha20的计数器 - int reseed_counter; // 重播种计数值 - int reseed_time; // 上次重播种时间值(秒) +typedef struct { + uint8_t Key[KEYLEN]; // 用于ChaCha20的密钥 + uint8_t V[COUNTERLEN]; // 用于ChaCha20的计数器 + int reseed_counter; // 重播种计数值 + int reseed_time; // 上次重播种时间值(秒) - bool used; // 表示此状态是否已经被使用 + bool used; // 表示此状态是否已经被使用 } DRBG_State; // 全局变量 @@ -367,477 +342,482 @@ size_t array_length; size_t additional_input_length; // 主要函数 -int ChaCha20_DRBG_Instantiate_function(uint8_t *personalization_string, char *state); -char *ChaCha20_DRBG_Reseed_function(int state_handle, uint8_t *additional_input); -void ChaCha20_DRBG_Update(const uint8_t *provided_data, uint8_t *V, uint8_t *Key); -char *ChaCha20_DRBG_Generate_function(int state_handle, int requested_no_of_bits, uint8_t *additional_input, uint8_t **returned_bits); +int ChaCha20_DRBG_Instantiate_function(uint8_t *personalization_string, + char *state); +char *ChaCha20_DRBG_Reseed_function(int state_handle, + uint8_t *additional_input); +void ChaCha20_DRBG_Update(const uint8_t *provided_data, uint8_t *V, + uint8_t *Key); +char *ChaCha20_DRBG_Generate_function(int state_handle, + int requested_no_of_bits, + uint8_t *additional_input, + uint8_t **returned_bits); // 算法函数 -void ChaCha20_DRBG_Instantiate_algorithm(uint8_t *entropy_input, int nonce, uint8_t *personalization_string, uint8_t *V, uint8_t *Key, int *reseed_counter, int *reseed_time); -void ChaCha20_DRBG_Reseed_algorithm(uint8_t *V, uint8_t *Key, int *reseed_counter, int *reseed_time, uint8_t *entropy_input, uint8_t *additional_input); -char *ChaCha20_DRBG_Generate_algorithm(uint8_t *V, uint8_t *Key, int *reseed_counter, int requested_number_of_bits, uint8_t *additional_input, uint8_t **returned_bits); +void ChaCha20_DRBG_Instantiate_algorithm(uint8_t *entropy_input, int nonce, + uint8_t *personalization_string, + uint8_t *V, uint8_t *Key, + int *reseed_counter, int *reseed_time); +void ChaCha20_DRBG_Reseed_algorithm(uint8_t *V, uint8_t *Key, + int *reseed_counter, int *reseed_time, + uint8_t *entropy_input, + uint8_t *additional_input); +char *ChaCha20_DRBG_Generate_algorithm(uint8_t *V, uint8_t *Key, + int *reseed_counter, + int requested_number_of_bits, + uint8_t *additional_input, + uint8_t **returned_bits); // 派生函数 -uint8_t *ChaCha20_df(uint8_t *V, uint8_t *input_string, size_t no_of_bits_to_return); +uint8_t *ChaCha20_df(uint8_t *V, uint8_t *input_string, + size_t no_of_bits_to_return); // 初始化所有状态为空闲 -void initialize_states() -{ - for (int i = 0; i < MAX_STATES; i++) - { - drbg_states[i].used = false; - } +void initialize_states() { + for (int i = 0; i < MAX_STATES; i++) { + drbg_states[i].used = false; + } } // 查找并返回一个空闲的状态句柄。如果没有可用的空间,则返回INVALID_HANDLE -int Find_state_space() -{ - for (int i = 0; i < MAX_STATES; i++) - { - if (!drbg_states[i].used) - { - drbg_states[i].used = true; // 标记为已使用 - return i; // 返回句柄/索引 - } +int Find_state_space() { + for (int i = 0; i < MAX_STATES; i++) { + if (!drbg_states[i].used) { + drbg_states[i].used = true; // 标记为已使用 + return i; // 返回句柄/索引 } - return INVALID_HANDLE; // 所有的状态都在使用中 + } + return INVALID_HANDLE; // 所有的状态都在使用中 } -void increment_nonce(uint8_t *nonce) -{ - int i = 0; - for (i; i < NONCELEN; i++) - { - nonce[i]++; - if (nonce[i] != 0) - { // 检查是否有溢出 - break; // 如果没有溢出,则不需要进位 - } +void increment_nonce(uint8_t *nonce) { + int i = 0; + for (i; i < NONCELEN; i++) { + nonce[i]++; + if (nonce[i] != 0) { // 检查是否有溢出 + break; // 如果没有溢出,则不需要进位 } + } } -int ChaCha20_DRBG_Instantiate_function(uint8_t *personalization_string, char *status) -{ - if (strlen((char *)personalization_string) > MAX_PERSONALIZATION_STRING_LEN) - { - strcpy(status, "Personalization_string too long"); - return ERROR; - } +int ChaCha20_DRBG_Instantiate_function(uint8_t *personalization_string, + char *status) { + if (strlen((char *)personalization_string) > MAX_PERSONALIZATION_STRING_LEN) { + strcpy(status, "Personalization_string too long"); + return ERROR; + } - uint8_t entropy_input[min_entropy_input_length]; - get_entropy_source(entropy_source); - Get_entropy_input(entropy_source, min_entropy_input_length, entropy_input); + uint8_t entropy_input[min_entropy_input_length]; + get_entropy_source(entropy_source); + get_entropy_input(entropy_source, min_entropy_input_length, entropy_input); - instantiation_nonce += 1; - increment_nonce(chacha_nonce); + instantiation_nonce += 1; + increment_nonce(chacha_nonce); - uint8_t V[COUNTERLEN], Key[KEYLEN]; - int reseed_counter, reseed_time; - ChaCha20_DRBG_Instantiate_algorithm(entropy_input, instantiation_nonce, personalization_string, V, Key, &reseed_counter, &reseed_time); + uint8_t V[COUNTERLEN], Key[KEYLEN]; + int reseed_counter, reseed_time; + ChaCha20_DRBG_Instantiate_algorithm(entropy_input, instantiation_nonce, + personalization_string, V, Key, + &reseed_counter, &reseed_time); - int state_handle = Find_state_space(); - if (state_handle == ERROR) - { - strcpy(status, "Failed to find state space"); - return ERROR; - } + int state_handle = Find_state_space(); + if (state_handle == ERROR) { + strcpy(status, "Failed to find state space"); + return ERROR; + } - // Save the internal state - memcpy(drbg_states[state_handle].V, V, COUNTERLEN); - memcpy(drbg_states[state_handle].Key, Key, KEYLEN); - drbg_states[state_handle].reseed_counter = reseed_counter; - drbg_states[state_handle].reseed_time = reseed_time; + // Save the internal state + memcpy(drbg_states[state_handle].V, V, COUNTERLEN); + memcpy(drbg_states[state_handle].Key, Key, KEYLEN); + drbg_states[state_handle].reseed_counter = reseed_counter; + drbg_states[state_handle].reseed_time = reseed_time; - strcpy(status, "Success"); - return state_handle; + strcpy(status, "Success"); + return state_handle; } -char *ChaCha20_DRBG_Reseed_function(int state_handle, uint8_t *additional_input) -{ - // Check for the validity of state_handle. - if (!drbg_states[state_handle].used) - { - return "State not available for the indicated state_handle"; - } +char *ChaCha20_DRBG_Reseed_function(int state_handle, + uint8_t *additional_input) { + // Check for the validity of state_handle. + if (!drbg_states[state_handle].used) { + return "State not available for the indicated state_handle"; + } - // Get the internal state values. - uint8_t *V = drbg_states[state_handle].V; - uint8_t *Key = drbg_states[state_handle].Key; + // Get the internal state values. + uint8_t *V = drbg_states[state_handle].V; + uint8_t *Key = drbg_states[state_handle].Key; - // Check length of additional_input - if (additional_input_length > MAX_PERSONALIZATION_STRING_LEN) - { - return "additional_input too long"; - } + // Check length of additional_input + if (additional_input_length > MAX_PERSONALIZATION_STRING_LEN) { + return "additional_input too long"; + } - uint8_t entropy_input[min_entropy_input_length]; - get_entropy_source(entropy_source); - Get_entropy_input(entropy_source, min_entropy_input_length, entropy_input); + uint8_t entropy_input[min_entropy_input_length]; + get_entropy_source(entropy_source); + get_entropy_input(entropy_source, min_entropy_input_length, entropy_input); - // Invoke the reseed algorithm. - int reseed_counter, reseed_time; - ChaCha20_DRBG_Reseed_algorithm(V, Key, &reseed_counter, &reseed_time, entropy_input, additional_input); + // Invoke the reseed algorithm. + int reseed_counter, reseed_time; + ChaCha20_DRBG_Reseed_algorithm(V, Key, &reseed_counter, &reseed_time, + entropy_input, additional_input); - // Save the internal state. - memcpy(drbg_states[state_handle].V, V, OUTLEN); - memcpy(drbg_states[state_handle].Key, Key, KEYLEN); - drbg_states[state_handle].reseed_counter = reseed_counter; - drbg_states[state_handle].reseed_time = reseed_time; + // Save the internal state. + memcpy(drbg_states[state_handle].V, V, OUTLEN); + memcpy(drbg_states[state_handle].Key, Key, KEYLEN); + drbg_states[state_handle].reseed_counter = reseed_counter; + drbg_states[state_handle].reseed_time = reseed_time; - return "Success"; + return "Success"; } -void ChaCha20_DRBG_Update(const uint8_t *provided_data, uint8_t *Key, uint8_t *V) -{ - uint8_t temp[SEEDLEN] = {0}; - // uint32_t V_uint32; - int i; +void ChaCha20_DRBG_Update(const uint8_t *provided_data, uint8_t *Key, + uint8_t *V) { + uint8_t temp[SEEDLEN] = {0}; + // uint32_t V_uint32; + int i; - // memcpy(&V_uint32, V, sizeof(uint32_t)); - ChaCha20_setup(chacha_state, Key, chacha_nonce, V); - ChaCha20_encrypt(chacha_state, V, temp, SEEDLEN, true); + // memcpy(&V_uint32, V, sizeof(uint32_t)); + ChaCha20_setup(chacha_state, Key, chacha_nonce, V); + ChaCha20_encrypt(chacha_state, V, temp, SEEDLEN, true); - // XOR provided_data with the leftmost part of temp - for (i = 0; i < SEEDLEN; ++i) - { - temp[i] ^= provided_data[i]; - } + // XOR provided_data with the leftmost part of temp + for (i = 0; i < SEEDLEN; ++i) { + temp[i] ^= provided_data[i]; + } - // Update the key and V from temp - memcpy(Key, temp, KEYLEN); - memcpy(V, temp + KEYLEN, COUNTERLEN); + // Update the key and V from temp + memcpy(Key, temp, KEYLEN); + memcpy(V, temp + KEYLEN, COUNTERLEN); } -char *ChaCha20_DRBG_Generate_function(int state_handle, int requested_no_of_bits, uint8_t *additional_input, uint8_t **returned_bits) -{ - uint8_t *V; - uint8_t *Key; - int reseed_counter, reseed_time; - char *status; +char *ChaCha20_DRBG_Generate_function(int state_handle, + int requested_no_of_bits, + uint8_t *additional_input, + uint8_t **returned_bits) { + uint8_t *V; + uint8_t *Key; + int reseed_counter, reseed_time; + char *status; - // Check the validity of state_handle - if (!drbg_states[state_handle].V || !drbg_states[state_handle].Key) - { - return "State not available for the indicated state_handle"; + // Check the validity of state_handle + if (!drbg_states[state_handle].V || !drbg_states[state_handle].Key) { + return "State not available for the indicated state_handle"; + } + + // Get the internal state + V = drbg_states[state_handle].V; + Key = drbg_states[state_handle].Key; + reseed_counter = drbg_states[state_handle].reseed_counter; + reseed_time = drbg_states[state_handle].reseed_time; + + // Check the rest of the input parameters + if (requested_no_of_bits > 4000) { + return "Too many bits requested"; + } + + if ((additional_input_length) > MAX_PERSONALIZATION_STRING_LEN) { + return "additional_input too long"; + } + + time_t timep; + int now_time = time(&timep); + // Check for reseeding + if (reseed_counter > reseed_interval_in_counter || + (now_time - reseed_time) > reseed_interval_in_time) { + status = ChaCha20_DRBG_Reseed_function(state_handle, additional_input); + if (strcmp(status, "Success") == 0) { + V = drbg_states[state_handle].V; + Key = drbg_states[state_handle].Key; + reseed_counter = drbg_states[state_handle].reseed_counter; + reseed_time = drbg_states[state_handle].reseed_time; + additional_input = NULL; + additional_input_length = 0; + } else { + return status; } + } - // Get the internal state - V = drbg_states[state_handle].V; - Key = drbg_states[state_handle].Key; - reseed_counter = drbg_states[state_handle].reseed_counter; - reseed_time = drbg_states[state_handle].reseed_time; + // Execute the algorithm to generate pseudorandom bits + status = ChaCha20_DRBG_Generate_algorithm(V, Key, &reseed_counter, + requested_no_of_bits, + additional_input, returned_bits); + if (strcmp(status, "Success") != 0) { + return "Error in CTR_ChaCha20_DRBG_Generate_algorithm"; // Safety check + } - // Check the rest of the input parameters - if (requested_no_of_bits > 4000) - { - return "Too many bits requested"; - } + memcpy(drbg_states[state_handle].V, V, OUTLEN); + memcpy(drbg_states[state_handle].Key, Key, KEYLEN); + drbg_states[state_handle].reseed_counter = reseed_counter; + drbg_states[state_handle].reseed_time = reseed_time; - if ((additional_input_length) > MAX_PERSONALIZATION_STRING_LEN) - { - return "additional_input too long"; - } - - time_t timep; - int now_time = time(&timep); - // Check for reseeding - if (reseed_counter > reseed_interval_in_counter || (now_time - reseed_time) > reseed_interval_in_time) - { - status = ChaCha20_DRBG_Reseed_function(state_handle, additional_input); - if (strcmp(status, "Success") == 0) - { - V = drbg_states[state_handle].V; - Key = drbg_states[state_handle].Key; - reseed_counter = drbg_states[state_handle].reseed_counter; - reseed_time = drbg_states[state_handle].reseed_time; - additional_input = NULL; - additional_input_length = 0; - } - else - { - return status; - } - } - - // Execute the algorithm to generate pseudorandom bits - status = ChaCha20_DRBG_Generate_algorithm(V, Key, &reseed_counter, requested_no_of_bits, additional_input, returned_bits); - if (strcmp(status, "Success") != 0) - { - return "Error in CTR_ChaCha20_DRBG_Generate_algorithm"; // Safety check - } - - memcpy(drbg_states[state_handle].V, V, OUTLEN); - memcpy(drbg_states[state_handle].Key, Key, KEYLEN); - drbg_states[state_handle].reseed_counter = reseed_counter; - drbg_states[state_handle].reseed_time = reseed_time; - - return "Success"; + return "Success"; } -void ChaCha20_DRBG_Instantiate_algorithm(uint8_t *entropy_input, int nonce, uint8_t *personalization_string, uint8_t *V, uint8_t *Key, int *reseed_counter, int *reseed_time) -{ - size_t entropy_input_len = min_entropy_input_length; - size_t personalization_string_len = strlen((char *)personalization_string); - size_t seed_material_size = entropy_input_len + sizeof(nonce) + personalization_string_len; - uint8_t *seed_material = malloc(seed_material_size); - uint8_t *requested_bits; - time_t timep; - int i = 0; +void ChaCha20_DRBG_Instantiate_algorithm(uint8_t *entropy_input, int nonce, + uint8_t *personalization_string, + uint8_t *V, uint8_t *Key, + int *reseed_counter, + int *reseed_time) { + size_t entropy_input_len = min_entropy_input_length; + size_t personalization_string_len = strlen((char *)personalization_string); + size_t seed_material_size = + entropy_input_len + sizeof(nonce) + personalization_string_len; + uint8_t *seed_material = malloc(seed_material_size); + uint8_t *requested_bits; + time_t timep; + int i = 0; - memcpy(seed_material, entropy_input, entropy_input_len); - memcpy(seed_material + entropy_input_len, &nonce, sizeof(nonce)); - memcpy(seed_material + entropy_input_len + sizeof(nonce), personalization_string, personalization_string_len); + memcpy(seed_material, entropy_input, entropy_input_len); + memcpy(seed_material + entropy_input_len, &nonce, sizeof(nonce)); + memcpy(seed_material + entropy_input_len + sizeof(nonce), + personalization_string, personalization_string_len); - array_length = seed_material_size; - requested_bits = ChaCha20_df(V, seed_material, SEEDLEN * 8); - memcpy(seed_material, requested_bits, SEEDLEN); + array_length = seed_material_size; + requested_bits = ChaCha20_df(V, seed_material, SEEDLEN * 8); + memcpy(seed_material, requested_bits, SEEDLEN); - memset(Key, 0, KEYLEN); - memset(V, 0, COUNTERLEN); + memset(Key, 0, KEYLEN); + memset(V, 0, COUNTERLEN); - ChaCha20_DRBG_Update(seed_material, Key, V); + ChaCha20_DRBG_Update(seed_material, Key, V); - *reseed_counter = 1; - *reseed_time = time(&timep); + *reseed_counter = 1; + *reseed_time = time(&timep); } -void ChaCha20_DRBG_Reseed_algorithm(uint8_t *V, uint8_t *Key, int *reseed_counter, int *reseed_time, uint8_t *entropy_input, uint8_t *additional_input) -{ - // 1. seed_material = entropy_input || additional_input. - size_t seed_material_size = min_entropy_input_length + additional_input_length; - uint8_t *seed_material = malloc(seed_material_size); - memcpy(seed_material, entropy_input, min_entropy_input_length); - memcpy(seed_material + min_entropy_input_length, additional_input, additional_input_length); +void ChaCha20_DRBG_Reseed_algorithm(uint8_t *V, uint8_t *Key, + int *reseed_counter, int *reseed_time, + uint8_t *entropy_input, + uint8_t *additional_input) { + // 1. seed_material = entropy_input || additional_input. + size_t seed_material_size = + min_entropy_input_length + additional_input_length; + uint8_t *seed_material = malloc(seed_material_size); + memcpy(seed_material, entropy_input, min_entropy_input_length); + memcpy(seed_material + min_entropy_input_length, additional_input, + additional_input_length); - // 2. seed_material = Block_Cipher_df(seed_material, 256). - uint8_t *requested_bits; - array_length = seed_material_size; - requested_bits = ChaCha20_df(V, seed_material, SEEDLEN * 8); - memcpy(seed_material, requested_bits, SEEDLEN); + // 2. seed_material = Block_Cipher_df(seed_material, 256). + uint8_t *requested_bits; + array_length = seed_material_size; + requested_bits = ChaCha20_df(V, seed_material, SEEDLEN * 8); + memcpy(seed_material, requested_bits, SEEDLEN); - // 3. (Key, V) = CTR_ChaCha20_DRBG_Update(seed_material, Key, V). - ChaCha20_DRBG_Update(seed_material, Key, V); + // 3. (Key, V) = CTR_ChaCha20_DRBG_Update(seed_material, Key, V). + ChaCha20_DRBG_Update(seed_material, Key, V); - // 4. reseed_counter = 1. - time_t timep; - *reseed_counter = 1; - *reseed_time = time(&timep); + // 4. reseed_counter = 1. + time_t timep; + *reseed_counter = 1; + *reseed_time = time(&timep); } -char *ChaCha20_DRBG_Generate_algorithm(uint8_t *V, uint8_t *Key, int *reseed_counter, int requested_number_of_bits, uint8_t *additional_input, uint8_t **returned_bits) -{ - if (additional_input != NULL) - { - array_length = additional_input_length; - additional_input = ChaCha20_df(V, additional_input, SEEDLEN * 8); - ChaCha20_DRBG_Update(additional_input, Key, V); - } - else - { - // Assuming additional_input is a byte array, we set it to 0 - additional_input = (uint8_t *)malloc(SEEDLEN); - additional_input_length = SEEDLEN; - if (additional_input == NULL) - { - return "Memory allocation failed"; - } - memset(additional_input, 0, SEEDLEN); - } - - uint8_t temp[requested_number_of_bits / 8]; - - ChaCha20_encrypt(chacha_state, V, temp, requested_number_of_bits / 8, true); - - *returned_bits = (uint8_t *)malloc(requested_number_of_bits / 8); - memcpy(*returned_bits, temp, requested_number_of_bits / 8); - +char *ChaCha20_DRBG_Generate_algorithm(uint8_t *V, uint8_t *Key, + int *reseed_counter, + int requested_number_of_bits, + uint8_t *additional_input, + uint8_t **returned_bits) { + if (additional_input != NULL) { + array_length = additional_input_length; + additional_input = ChaCha20_df(V, additional_input, SEEDLEN * 8); ChaCha20_DRBG_Update(additional_input, Key, V); + } else { + // Assuming additional_input is a byte array, we set it to 0 + additional_input = (uint8_t *)malloc(SEEDLEN); + additional_input_length = SEEDLEN; + if (additional_input == NULL) { + return "Memory allocation failed"; + } + memset(additional_input, 0, SEEDLEN); + } - (*reseed_counter)++; + uint8_t temp[requested_number_of_bits / 8]; - return "Success"; + ChaCha20_encrypt(chacha_state, V, temp, requested_number_of_bits / 8, true); + + *returned_bits = (uint8_t *)malloc(requested_number_of_bits / 8); + memcpy(*returned_bits, temp, requested_number_of_bits / 8); + + ChaCha20_DRBG_Update(additional_input, Key, V); + + (*reseed_counter)++; + + return "Success"; } -uint8_t *ChaCha20_df(uint8_t *V, uint8_t *input_string, size_t no_of_bits_to_return) -{ - if (no_of_bits_to_return > MAX_NUMBER_OF_BITS) - { - return NULL; - } +uint8_t *ChaCha20_df(uint8_t *V, uint8_t *input_string, + size_t no_of_bits_to_return) { + if (no_of_bits_to_return > MAX_NUMBER_OF_BITS) { + return NULL; + } - uint32_t L = array_length / 8; - uint32_t N = no_of_bits_to_return / 8; - int S_init_size = 4 + 4 + array_length + 1; - uint8_t *S = (uint8_t *)malloc(S_init_size); + uint32_t L = array_length / 8; + uint32_t N = no_of_bits_to_return / 8; + int S_init_size = 4 + 4 + array_length + 1; + uint8_t *S = (uint8_t *)malloc(S_init_size); - // Prepend the string length and the requested length to the input_string - memcpy(S, &L, 4); - memcpy(S + 4, &N, 4); - memcpy(S + 8, input_string, array_length); - S[S_init_size - 1] = 0x80; // Padding + // Prepend the string length and the requested length to the input_string + memcpy(S, &L, 4); + memcpy(S + 4, &N, 4); + memcpy(S + 8, input_string, array_length); + S[S_init_size - 1] = 0x80; // Padding - // Pad S with zeros, if necessary. - int S_actual_size = S_init_size; // Taken the 0x80 into account - while (S_actual_size % OUTLEN != 0) - { - S = realloc(S, S_actual_size + 1); // Increase size by one byte - S[S_actual_size++] = 0x00; // Add a zero at current end, and increase actual size by one - } + // Pad S with zeros, if necessary. + int S_actual_size = S_init_size; // Taken the 0x80 into account + while (S_actual_size % OUTLEN != 0) { + S = realloc(S, S_actual_size + 1); // Increase size by one byte + S[S_actual_size++] = + 0x00; // Add a zero at current end, and increase actual size by one + } - int temp_len = 0; - uint8_t *temp = (uint8_t *)malloc(1); - uint32_t i = 0; + int temp_len = 0; + uint8_t *temp = (uint8_t *)malloc(1); + uint32_t i = 0; - uint8_t K[KEYLEN]; - uint8_t source[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F}; - memcpy(K, source, KEYLEN); + uint8_t K[KEYLEN]; + uint8_t source[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F}; + memcpy(K, source, KEYLEN); - ChaCha20_setup(chacha_state, K, chacha_nonce, V); - while (temp_len < KEYLEN + OUTLEN) - { - uint8_t IV[OUTLEN] = {0}; - IV[OUTLEN - 4] = i; // 32-bit integer representation of i padded with zeros to OUTLEN bits. + ChaCha20_setup(chacha_state, K, chacha_nonce, V); + while (temp_len < KEYLEN + OUTLEN) { + uint8_t IV[OUTLEN] = {0}; + IV[OUTLEN - 4] = i; // 32-bit integer representation of i padded with zeros + // to OUTLEN bits. - uint8_t data_to_be_encrypted[OUTLEN + S_actual_size]; - memcpy(data_to_be_encrypted, IV, OUTLEN); - memcpy(data_to_be_encrypted + OUTLEN, S, S_actual_size); + uint8_t data_to_be_encrypted[OUTLEN + S_actual_size]; + memcpy(data_to_be_encrypted, IV, OUTLEN); + memcpy(data_to_be_encrypted + OUTLEN, S, S_actual_size); - uint8_t data_encrypted_result[OUTLEN + S_actual_size]; + uint8_t data_encrypted_result[OUTLEN + S_actual_size]; - ChaCha20_encrypt(chacha_state, data_to_be_encrypted, data_encrypted_result, temp_len, true); + ChaCha20_encrypt(chacha_state, data_to_be_encrypted, data_encrypted_result, + temp_len, true); - temp_len = (i + 1) * (OUTLEN + S_actual_size); - temp = (uint8_t *)realloc(temp, temp_len); - memcpy(temp + i * (OUTLEN + S_actual_size), data_encrypted_result, temp_len); - i++; - } + temp_len = (i + 1) * (OUTLEN + S_actual_size); + temp = (uint8_t *)realloc(temp, temp_len); + memcpy(temp + i * (OUTLEN + S_actual_size), data_encrypted_result, + temp_len); + i++; + } - memcpy(K, temp, KEYLEN); - uint8_t X[OUTLEN] = {0}; - memcpy(X, temp + KEYLEN, OUTLEN); - uint8_t encrypted_data[OUTLEN] = {0}; - temp[0] = '\0'; // Clear temp - temp_len = 0; + memcpy(K, temp, KEYLEN); + uint8_t X[OUTLEN] = {0}; + memcpy(X, temp + KEYLEN, OUTLEN); + uint8_t encrypted_data[OUTLEN] = {0}; + temp[0] = '\0'; // Clear temp + temp_len = 0; - ChaCha20_setup(chacha_state, K, chacha_nonce, V); - while (temp_len < no_of_bits_to_return / 8) - { - ChaCha20_encrypt(chacha_state, X, encrypted_data, OUTLEN, true); - memcpy(X, encrypted_data, OUTLEN); - temp = (uint8_t *)realloc(temp, temp_len + OUTLEN); - memcpy(temp + temp_len, encrypted_data, OUTLEN); - temp_len += OUTLEN; - } + ChaCha20_setup(chacha_state, K, chacha_nonce, V); + while (temp_len < no_of_bits_to_return / 8) { + ChaCha20_encrypt(chacha_state, X, encrypted_data, OUTLEN, true); + memcpy(X, encrypted_data, OUTLEN); + temp = (uint8_t *)realloc(temp, temp_len + OUTLEN); + memcpy(temp + temp_len, encrypted_data, OUTLEN); + temp_len += OUTLEN; + } - uint8_t *requested_bits = (uint8_t *)malloc(no_of_bits_to_return / 8); - if (requested_bits == NULL) - { - return NULL; - } + uint8_t *requested_bits = (uint8_t *)malloc(no_of_bits_to_return / 8); + if (requested_bits == NULL) { + return NULL; + } - memcpy(requested_bits, temp, no_of_bits_to_return / 8); + memcpy(requested_bits, temp, no_of_bits_to_return / 8); - memset(temp, 0, sizeof(temp)); - memset(K, 0, sizeof(K)); - memset(X, 0, sizeof(X)); - memset(S, 0, sizeof(S)); + memset(temp, 0, sizeof(temp)); + memset(K, 0, sizeof(K)); + memset(X, 0, sizeof(X)); + memset(S, 0, sizeof(S)); - return requested_bits; + return requested_bits; } -int main() -{ - uint8_t personalization_string[] = "this is personalization_string"; - char status[MAX_STATES] = {'\0'}; - int state_handle; - uint8_t *returned_bits; - long int returned_bits_len, returned_bits_num; - bool pass; +int main() { + uint8_t personalization_string[] = "this is personalization_string"; + char status[MAX_STATES] = {'\0'}; + int state_handle; + uint8_t *returned_bits; + long int returned_bits_len, returned_bits_num; + bool pass; - srand(time(0)); + srand(time(0)); - // 初始化DRBG - state_handle = ChaCha20_DRBG_Instantiate_function(personalization_string, status); + // 初始化DRBG + state_handle = + ChaCha20_DRBG_Instantiate_function(personalization_string, status); - // 需要生成的比特串长度 - printf("Enter the length of the bit string to be generated(bit): "); - scanf("%d", &returned_bits_len); - // returned_bits_len = 128; + // 需要生成的比特串长度 + printf("Enter the length of the bit string to be generated(bit): "); + scanf("%d", &returned_bits_len); + // returned_bits_len = 128; - // 需要生成的比特串个数 - printf("Enter the number of the bit string to be generated: "); - scanf("%d", &returned_bits_num); - // returned_bits_num = 1000; + // 需要生成的比特串个数 + printf("Enter the number of the bit string to be generated: "); + scanf("%d", &returned_bits_num); + // returned_bits_num = 1000; - // char *filename; filename 未分配内存 - char filename[100]; // 假设文件名长度不超过 99 个字符 - printf("Enter the name of the saved file: "); - scanf("%s", filename); + // char *filename; filename 未分配内存 + char filename[100]; // 假设文件名长度不超过 99 个字符 + printf("Enter the name of the saved file: "); + scanf("%s", filename); - // 生成的比特串保存在文本文件中 - FILE *file = fopen(filename, "w"); - if (file == NULL) - { - printf("无法打开文件\n"); - return 1; - } + // 生成的比特串保存在文本文件中 + FILE *file = fopen(filename, "w"); + if (file == NULL) { + printf("无法打开文件\n"); + return 1; + } - clock_t start_time = clock(); + clock_t start_time = clock(); - for (int j = 1; j <= returned_bits_num; ++j) - { - do - { - int zero_count = 0; - int one_count = 0; + for (int j = 1; j <= returned_bits_num; ++j) { + do { + int zero_count = 0; + int one_count = 0; - additional_input_length = 0; - ChaCha20_DRBG_Generate_function(state_handle, returned_bits_len, NULL, &returned_bits); + additional_input_length = 0; + ChaCha20_DRBG_Generate_function(state_handle, returned_bits_len, NULL, + &returned_bits); - for (int i = 0; i < returned_bits_len / 8; i++) - { - int bits = returned_bits[i]; + for (int i = 0; i < returned_bits_len / 8; i++) { + int bits = returned_bits[i]; - for (int j = 0; j < 8; j++) - { - if (bits & 1) - one_count++; - else - zero_count++; + for (int j = 0; j < 8; j++) { + if (bits & 1) + one_count++; + else + zero_count++; - bits >>= 1; - } - } - - const float expected_count = returned_bits_len / 2; - float chisq = (pow(zero_count - expected_count, 2) / expected_count) + - (pow(one_count - expected_count, 2) / expected_count); - - if (chisq < 3.841) - pass = true; - else - pass = false; - } while (!pass); - - // 将二进制数据转为十六进制后写入文件 - char hex_str[returned_bits_len / 8 * 2 + 1]; - for (int i = 0; i < returned_bits_len / 8; ++i) - { - sprintf(&hex_str[i * 2], "%02x", returned_bits[i]); + bits >>= 1; } - hex_str[returned_bits_len / 8 * 2] = '\0'; - fprintf(file, "%s\n", hex_str); // 写入带有换行符的十六进制字符串 + } + + const float expected_count = returned_bits_len / 2; + float chisq = (pow(zero_count - expected_count, 2) / expected_count) + + (pow(one_count - expected_count, 2) / expected_count); + + if (chisq < 3.841) + pass = true; + else + pass = false; + } while (!pass); + + // 将二进制数据转为十六进制后写入文件 + char hex_str[returned_bits_len / 8 * 2 + 1]; + for (int i = 0; i < returned_bits_len / 8; ++i) { + sprintf(&hex_str[i * 2], "%02x", returned_bits[i]); } + hex_str[returned_bits_len / 8 * 2] = '\0'; + fprintf(file, "%s\n", hex_str); // 写入带有换行符的十六进制字符串 + } - clock_t end_time = clock(); - double execution_time = (double)(end_time - start_time) / CLOCKS_PER_SEC; - printf("running time: %f s\n", execution_time); + clock_t end_time = clock(); + double execution_time = (double)(end_time - start_time) / CLOCKS_PER_SEC; + printf("running time: %f s\n", execution_time); - fclose(file); + fclose(file); - return 0; + return 0; }