style: format code

This commit is contained in:
2024-01-08 05:11:53 +08:00
parent f8db961166
commit 8d7133eb5a

View File

@@ -1,11 +1,12 @@
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <math.h>
#include <time.h>
#include <stdbool.h>
#include <stdlib.h>
#include <ctype.h> #include <ctype.h>
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
// #include <openssl/evp.h> // #include <openssl/evp.h>
#define SUCCESS 0 #define SUCCESS 0
@@ -27,7 +28,7 @@
#define MAX_STATES 100 #define MAX_STATES 100
#define INVALID_HANDLE -1 #define INVALID_HANDLE -1
// for Get_entropy_input // for get_entropy_input
#define reseed_interval_in_counter pow(2, 10) // (次) #define reseed_interval_in_counter pow(2, 10) // (次)
#define reseed_interval_in_time 60 //(秒) #define reseed_interval_in_time 60 //(秒)
@@ -38,26 +39,25 @@
#define HASH_SIZE 32 #define HASH_SIZE 32
/*----------------熵源的相关定义与函数----------------*/ /*----------------熵源的相关定义与函数----------------*/
typedef struct typedef struct {
{
uint8_t data[BLOCK_SIZE]; uint8_t data[BLOCK_SIZE];
uint32_t datalen; uint32_t datalen;
uint64_t bitlen; uint64_t bitlen;
uint32_t state[8]; uint32_t state[8];
} SHA256_CTX; } SHA256_CTX;
void sha256_transform(SHA256_CTX *ctx, const uint8_t data[]) 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]; 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) for (i = 0, j = 0; i < 16; ++i, j += 4) {
{ m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) |
m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]); (data[j + 3]);
} }
for (; i < 64; ++i) for (; i < 64; ++i) {
{ m[i] = m[i - 16] + m[i - 7] + (m[i - 15] >> 7) + (m[i - 15] << 25) ^
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); (m[i - 15] >> 18) + (m[i - 15] << 14) ^
(m[i - 15] >> 3) + (m[i - 15] << 13);
} }
a = ctx->state[0]; a = ctx->state[0];
@@ -69,8 +69,7 @@ void sha256_transform(SHA256_CTX *ctx, const uint8_t data[])
g = ctx->state[6]; g = ctx->state[6];
h = ctx->state[7]; h = ctx->state[7];
for (i = 0; i < 64; ++i) for (i = 0; i < 64; ++i) {
{
t1 = h + (e >> 6) + ((e & f) ^ (~e & g)) + 0x428a2f98 + m[i]; t1 = h + (e >> 6) + ((e & f) ^ (~e & g)) + 0x428a2f98 + m[i];
t2 = (a >> 2) + ((a & b) ^ (a & c) ^ (b & c)) + 0x5a827999; t2 = (a >> 2) + ((a & b) ^ (a & c) ^ (b & c)) + 0x5a827999;
@@ -94,8 +93,7 @@ void sha256_transform(SHA256_CTX *ctx, const uint8_t data[])
ctx->state[7] += h; ctx->state[7] += h;
} }
void sha256_init(SHA256_CTX *ctx) void sha256_init(SHA256_CTX *ctx) {
{
ctx->datalen = 0; ctx->datalen = 0;
ctx->bitlen = 0; ctx->bitlen = 0;
ctx->state[0] = 0x6a09e667; ctx->state[0] = 0x6a09e667;
@@ -108,16 +106,13 @@ void sha256_init(SHA256_CTX *ctx)
ctx->state[7] = 0x5be0cd19; ctx->state[7] = 0x5be0cd19;
} }
void sha256_update(SHA256_CTX *ctx, const uint8_t data[], size_t len) void sha256_update(SHA256_CTX *ctx, const uint8_t data[], size_t len) {
{
uint32_t i; uint32_t i;
for (i = 0; i < len; ++i) for (i = 0; i < len; ++i) {
{
ctx->data[ctx->datalen] = data[i]; ctx->data[ctx->datalen] = data[i];
ctx->datalen++; ctx->datalen++;
if (ctx->datalen == BLOCK_SIZE) if (ctx->datalen == BLOCK_SIZE) {
{
sha256_transform(ctx, ctx->data); sha256_transform(ctx, ctx->data);
ctx->bitlen += BLOCK_SIZE * 8; ctx->bitlen += BLOCK_SIZE * 8;
ctx->datalen = 0; ctx->datalen = 0;
@@ -125,21 +120,17 @@ void sha256_update(SHA256_CTX *ctx, const uint8_t data[], size_t len)
} }
} }
void sha256_final(SHA256_CTX *ctx, uint8_t hash[]) void sha256_final(SHA256_CTX *ctx, uint8_t hash[]) {
{
uint32_t i; uint32_t i;
i = ctx->datalen; i = ctx->datalen;
// Pad whatever data is left in the buffer // Pad whatever data is left in the buffer
if (ctx->datalen < 56) if (ctx->datalen < 56) {
{
ctx->data[i++] = 0x80; ctx->data[i++] = 0x80;
while (i < 56) while (i < 56)
ctx->data[i++] = 0x00; ctx->data[i++] = 0x00;
} } else {
else
{
ctx->data[i++] = 0x80; ctx->data[i++] = 0x80;
while (i < BLOCK_SIZE) while (i < BLOCK_SIZE)
ctx->data[i++] = 0x00; ctx->data[i++] = 0x00;
@@ -160,10 +151,10 @@ void sha256_final(SHA256_CTX *ctx, uint8_t hash[])
sha256_transform(ctx, ctx->data); sha256_transform(ctx, ctx->data);
// Since this implementation uses little endian byte ordering and SHA uses big endian, // Since this implementation uses little endian byte ordering and SHA uses big
// reverse all the bytes when copying the final state to the output hash. // endian, reverse all the bytes when copying the final state to the output
for (i = 0; i < 4; ++i) // hash.
{ for (i = 0; i < 4; ++i) {
hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff; hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff;
hash[i + 4] = (ctx->state[1] >> (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 + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff;
@@ -175,17 +166,14 @@ void sha256_final(SHA256_CTX *ctx, uint8_t hash[])
} }
} }
void get_entropy_source(uint8_t *entropy_source) void get_entropy_source(uint8_t *entropy_source) {
{
// Simulate an entropy source by generating random data // Simulate an entropy source by generating random data
for (int i = 0; i < min_entropy_input_length; i++) for (int i = 0; i < min_entropy_input_length; i++) {
{
entropy_source[i] = rand() % 256; entropy_source[i] = rand() % 256;
} }
} }
void Get_entropy_input(const uint8_t *data, size_t len, uint8_t *entropy) void get_entropy_input(const uint8_t *data, size_t len, uint8_t *entropy) {
{
SHA256_CTX ctx; SHA256_CTX ctx;
uint8_t hash[HASH_SIZE]; uint8_t hash[HASH_SIZE];
@@ -202,28 +190,23 @@ void Get_entropy_input(const uint8_t *data, size_t len, uint8_t *entropy)
#define RANDOM_BITS_NUMBER 100 #define RANDOM_BITS_NUMBER 100
#define RANDOM_BITS_SIZE 128 #define RANDOM_BITS_SIZE 128
int test_randomness(const unsigned char *bits) int test_randomness(const unsigned char *bits) {
{
// Test the randomness of the given bits using the chi-squared test // Test the randomness of the given bits using the chi-squared test
int ones = 0, zeros = 0; int ones = 0, zeros = 0;
for (int i = 0; i < RANDOM_BITS_SIZE / 8; i++) for (int i = 0; i < RANDOM_BITS_SIZE / 8; i++) {
{
unsigned char byte = bits[i]; unsigned char byte = bits[i];
for (int j = 0; j < 8; j++) for (int j = 0; j < 8; j++) {
{ if ((byte >> j) & 0x01) {
if ((byte >> j) & 0x01)
{
ones++; ones++;
} } else {
else
{
zeros++; zeros++;
} }
} }
} }
double expected_ones = RANDOM_BITS_SIZE / 2.0; double expected_ones = RANDOM_BITS_SIZE / 2.0;
double expected_zeros = RANDOM_BITS_SIZE / 2.0; double expected_zeros = RANDOM_BITS_SIZE / 2.0;
double chi_squared = (ones - expected_ones) * (ones - expected_ones) / expected_ones + double chi_squared =
(ones - expected_ones) * (ones - expected_ones) / expected_ones +
(zeros - expected_zeros) * (zeros - expected_zeros) / expected_zeros; (zeros - expected_zeros) * (zeros - expected_zeros) / expected_zeros;
return chi_squared > 3.84; return chi_squared > 3.84;
} }
@@ -259,14 +242,12 @@ int test_randomness(const unsigned char *bits)
static const char sigma[] = "expand 32-byte k"; static const char sigma[] = "expand 32-byte k";
static const char tau[] = "expand 16-byte k"; static const char tau[] = "expand 16-byte k";
void ChaCha20_block(uint32_t state[16], uint32_t output[16]) void ChaCha20_block(uint32_t state[16], uint32_t output[16]) {
{
int i; int i;
memcpy(output, state, sizeof(uint32_t) * 16); memcpy(output, state, sizeof(uint32_t) * 16);
// 20轮操作每轮包括4个quarterrounds所以共80个quarterrounds // 20轮操作每轮包括4个quarterrounds所以共80个quarterrounds
for (i = 0; i < 10; ++i) for (i = 0; i < 10; ++i) {
{
// 双轮 // 双轮
QUARTERROUND(output, 0, 4, 8, 12) QUARTERROUND(output, 0, 4, 8, 12)
QUARTERROUND(output, 1, 5, 9, 13) QUARTERROUND(output, 1, 5, 9, 13)
@@ -278,14 +259,13 @@ void ChaCha20_block(uint32_t state[16], uint32_t output[16])
QUARTERROUND(output, 3, 4, 9, 14) QUARTERROUND(output, 3, 4, 9, 14)
} }
for (i = 0; i < 16; ++i) for (i = 0; i < 16; ++i) {
{
output[i] += state[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]) 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; const char *constants = (key[16] != 0 || key[24] != 0) ? sigma : tau;
state[4] = U8TO32_LITTLE(key + 0); state[4] = U8TO32_LITTLE(key + 0);
@@ -312,28 +292,24 @@ void ChaCha20_setup(uint32_t state[16], const uint8_t key[32], const uint8_t non
state[15] = U8TO32_LITTLE(nonce + 8); 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) void ChaCha20_encrypt(uint32_t state[16], const uint8_t *in, uint8_t *out,
{ size_t length, bool increment_flag) {
uint32_t keystream[16]; uint32_t keystream[16];
uint8_t *keystream_bytes = (uint8_t *)keystream; // 为XOR操作重新解释keystream uint8_t *keystream_bytes = (uint8_t *)keystream; // 为XOR操作重新解释keystream
size_t remaining = length; size_t remaining = length;
size_t i; size_t i;
while (remaining > 0) while (remaining > 0) {
{
size_t bytes_to_use = remaining < 64 ? remaining : 64; // 每个block 64 bytes 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) for (i = 0; i < bytes_to_use; ++i) {
{
out[i] = in[i] ^ keystream_bytes[i]; out[i] = in[i] ^ keystream_bytes[i];
} }
if (increment_flag) if (increment_flag) {
{
state[12] += 1; // 增加计数器 state[12] += 1; // 增加计数器
if (state[12] == 0) if (state[12] == 0) {
{
state[13] += 1; // 处理计数器溢出 state[13] += 1; // 处理计数器溢出
} }
} }
@@ -347,8 +323,7 @@ void ChaCha20_encrypt(uint32_t state[16], const uint8_t *in, uint8_t *out, size_
/*----------------------------------------------------*/ /*----------------------------------------------------*/
// 定义ChaCha20_DRBG的内部状态 // 定义ChaCha20_DRBG的内部状态
typedef struct typedef struct {
{
uint8_t Key[KEYLEN]; // 用于ChaCha20的密钥 uint8_t Key[KEYLEN]; // 用于ChaCha20的密钥
uint8_t V[COUNTERLEN]; // 用于ChaCha20的计数器 uint8_t V[COUNTERLEN]; // 用于ChaCha20的计数器
int reseed_counter; // 重播种计数值 int reseed_counter; // 重播种计数值
@@ -367,35 +342,47 @@ size_t array_length;
size_t additional_input_length; size_t additional_input_length;
// 主要函数 // 主要函数
int ChaCha20_DRBG_Instantiate_function(uint8_t *personalization_string, char *state); int ChaCha20_DRBG_Instantiate_function(uint8_t *personalization_string,
char *ChaCha20_DRBG_Reseed_function(int state_handle, uint8_t *additional_input); char *state);
void ChaCha20_DRBG_Update(const uint8_t *provided_data, uint8_t *V, uint8_t *Key); char *ChaCha20_DRBG_Reseed_function(int state_handle,
char *ChaCha20_DRBG_Generate_function(int state_handle, int requested_no_of_bits, uint8_t *additional_input, uint8_t **returned_bits); 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_Instantiate_algorithm(uint8_t *entropy_input, int nonce,
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); uint8_t *personalization_string,
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 *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() void initialize_states() {
{ for (int i = 0; i < MAX_STATES; i++) {
for (int i = 0; i < MAX_STATES; i++)
{
drbg_states[i].used = false; drbg_states[i].used = false;
} }
} }
// 查找并返回一个空闲的状态句柄。如果没有可用的空间则返回INVALID_HANDLE // 查找并返回一个空闲的状态句柄。如果没有可用的空间则返回INVALID_HANDLE
int Find_state_space() int Find_state_space() {
{ for (int i = 0; i < MAX_STATES; i++) {
for (int i = 0; i < MAX_STATES; i++) if (!drbg_states[i].used) {
{
if (!drbg_states[i].used)
{
drbg_states[i].used = true; // 标记为已使用 drbg_states[i].used = true; // 标记为已使用
return i; // 返回句柄/索引 return i; // 返回句柄/索引
} }
@@ -403,41 +390,38 @@ int Find_state_space()
return INVALID_HANDLE; // 所有的状态都在使用中 return INVALID_HANDLE; // 所有的状态都在使用中
} }
void increment_nonce(uint8_t *nonce) void increment_nonce(uint8_t *nonce) {
{
int i = 0; int i = 0;
for (i; i < NONCELEN; i++) for (i; i < NONCELEN; i++) {
{
nonce[i]++; nonce[i]++;
if (nonce[i] != 0) if (nonce[i] != 0) { // 检查是否有溢出
{ // 检查是否有溢出
break; // 如果没有溢出,则不需要进位 break; // 如果没有溢出,则不需要进位
} }
} }
} }
int ChaCha20_DRBG_Instantiate_function(uint8_t *personalization_string, char *status) int ChaCha20_DRBG_Instantiate_function(uint8_t *personalization_string,
{ char *status) {
if (strlen((char *)personalization_string) > MAX_PERSONALIZATION_STRING_LEN) if (strlen((char *)personalization_string) > MAX_PERSONALIZATION_STRING_LEN) {
{
strcpy(status, "Personalization_string too long"); strcpy(status, "Personalization_string too long");
return ERROR; return ERROR;
} }
uint8_t entropy_input[min_entropy_input_length]; uint8_t entropy_input[min_entropy_input_length];
get_entropy_source(entropy_source); get_entropy_source(entropy_source);
Get_entropy_input(entropy_source, min_entropy_input_length, entropy_input); get_entropy_input(entropy_source, min_entropy_input_length, entropy_input);
instantiation_nonce += 1; instantiation_nonce += 1;
increment_nonce(chacha_nonce); increment_nonce(chacha_nonce);
uint8_t V[COUNTERLEN], Key[KEYLEN]; uint8_t V[COUNTERLEN], Key[KEYLEN];
int reseed_counter, reseed_time; int reseed_counter, reseed_time;
ChaCha20_DRBG_Instantiate_algorithm(entropy_input, instantiation_nonce, personalization_string, V, Key, &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(); int state_handle = Find_state_space();
if (state_handle == ERROR) if (state_handle == ERROR) {
{
strcpy(status, "Failed to find state space"); strcpy(status, "Failed to find state space");
return ERROR; return ERROR;
} }
@@ -452,11 +436,10 @@ int ChaCha20_DRBG_Instantiate_function(uint8_t *personalization_string, char *st
return state_handle; return state_handle;
} }
char *ChaCha20_DRBG_Reseed_function(int state_handle, uint8_t *additional_input) char *ChaCha20_DRBG_Reseed_function(int state_handle,
{ uint8_t *additional_input) {
// Check for the validity of state_handle. // Check for the validity of state_handle.
if (!drbg_states[state_handle].used) if (!drbg_states[state_handle].used) {
{
return "State not available for the indicated state_handle"; return "State not available for the indicated state_handle";
} }
@@ -465,18 +448,18 @@ char *ChaCha20_DRBG_Reseed_function(int state_handle, uint8_t *additional_input)
uint8_t *Key = drbg_states[state_handle].Key; uint8_t *Key = drbg_states[state_handle].Key;
// Check length of additional_input // Check length of additional_input
if (additional_input_length > MAX_PERSONALIZATION_STRING_LEN) if (additional_input_length > MAX_PERSONALIZATION_STRING_LEN) {
{
return "additional_input too long"; return "additional_input too long";
} }
uint8_t entropy_input[min_entropy_input_length]; uint8_t entropy_input[min_entropy_input_length];
get_entropy_source(entropy_source); get_entropy_source(entropy_source);
Get_entropy_input(entropy_source, min_entropy_input_length, entropy_input); get_entropy_input(entropy_source, min_entropy_input_length, entropy_input);
// Invoke the reseed algorithm. // Invoke the reseed algorithm.
int reseed_counter, reseed_time; int reseed_counter, reseed_time;
ChaCha20_DRBG_Reseed_algorithm(V, Key, &reseed_counter, &reseed_time, entropy_input, additional_input); ChaCha20_DRBG_Reseed_algorithm(V, Key, &reseed_counter, &reseed_time,
entropy_input, additional_input);
// Save the internal state. // Save the internal state.
memcpy(drbg_states[state_handle].V, V, OUTLEN); memcpy(drbg_states[state_handle].V, V, OUTLEN);
@@ -487,8 +470,8 @@ char *ChaCha20_DRBG_Reseed_function(int state_handle, uint8_t *additional_input)
return "Success"; return "Success";
} }
void ChaCha20_DRBG_Update(const uint8_t *provided_data, uint8_t *Key, uint8_t *V) void ChaCha20_DRBG_Update(const uint8_t *provided_data, uint8_t *Key,
{ uint8_t *V) {
uint8_t temp[SEEDLEN] = {0}; uint8_t temp[SEEDLEN] = {0};
// uint32_t V_uint32; // uint32_t V_uint32;
int i; int i;
@@ -498,8 +481,7 @@ void ChaCha20_DRBG_Update(const uint8_t *provided_data, uint8_t *Key, uint8_t *V
ChaCha20_encrypt(chacha_state, V, temp, SEEDLEN, true); ChaCha20_encrypt(chacha_state, V, temp, SEEDLEN, true);
// XOR provided_data with the leftmost part of temp // XOR provided_data with the leftmost part of temp
for (i = 0; i < SEEDLEN; ++i) for (i = 0; i < SEEDLEN; ++i) {
{
temp[i] ^= provided_data[i]; temp[i] ^= provided_data[i];
} }
@@ -508,16 +490,17 @@ void ChaCha20_DRBG_Update(const uint8_t *provided_data, uint8_t *Key, uint8_t *V
memcpy(V, temp + KEYLEN, COUNTERLEN); 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) 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 *V;
uint8_t *Key; uint8_t *Key;
int reseed_counter, reseed_time; int reseed_counter, reseed_time;
char *status; char *status;
// Check the validity of state_handle // Check the validity of state_handle
if (!drbg_states[state_handle].V || !drbg_states[state_handle].Key) if (!drbg_states[state_handle].V || !drbg_states[state_handle].Key) {
{
return "State not available for the indicated state_handle"; return "State not available for the indicated state_handle";
} }
@@ -528,41 +511,37 @@ char *ChaCha20_DRBG_Generate_function(int state_handle, int requested_no_of_bits
reseed_time = drbg_states[state_handle].reseed_time; reseed_time = drbg_states[state_handle].reseed_time;
// Check the rest of the input parameters // Check the rest of the input parameters
if (requested_no_of_bits > 4000) if (requested_no_of_bits > 4000) {
{
return "Too many bits requested"; return "Too many bits requested";
} }
if ((additional_input_length) > MAX_PERSONALIZATION_STRING_LEN) if ((additional_input_length) > MAX_PERSONALIZATION_STRING_LEN) {
{
return "additional_input too long"; return "additional_input too long";
} }
time_t timep; time_t timep;
int now_time = time(&timep); int now_time = time(&timep);
// Check for reseeding // Check for reseeding
if (reseed_counter > reseed_interval_in_counter || (now_time - reseed_time) > reseed_interval_in_time) if (reseed_counter > reseed_interval_in_counter ||
{ (now_time - reseed_time) > reseed_interval_in_time) {
status = ChaCha20_DRBG_Reseed_function(state_handle, additional_input); status = ChaCha20_DRBG_Reseed_function(state_handle, additional_input);
if (strcmp(status, "Success") == 0) if (strcmp(status, "Success") == 0) {
{
V = drbg_states[state_handle].V; V = drbg_states[state_handle].V;
Key = drbg_states[state_handle].Key; Key = drbg_states[state_handle].Key;
reseed_counter = drbg_states[state_handle].reseed_counter; reseed_counter = drbg_states[state_handle].reseed_counter;
reseed_time = drbg_states[state_handle].reseed_time; reseed_time = drbg_states[state_handle].reseed_time;
additional_input = NULL; additional_input = NULL;
additional_input_length = 0; additional_input_length = 0;
} } else {
else
{
return status; return status;
} }
} }
// Execute the algorithm to generate pseudorandom bits // Execute the algorithm to generate pseudorandom bits
status = ChaCha20_DRBG_Generate_algorithm(V, Key, &reseed_counter, requested_no_of_bits, additional_input, returned_bits); status = ChaCha20_DRBG_Generate_algorithm(V, Key, &reseed_counter,
if (strcmp(status, "Success") != 0) requested_no_of_bits,
{ additional_input, returned_bits);
if (strcmp(status, "Success") != 0) {
return "Error in CTR_ChaCha20_DRBG_Generate_algorithm"; // Safety check return "Error in CTR_ChaCha20_DRBG_Generate_algorithm"; // Safety check
} }
@@ -574,11 +553,15 @@ char *ChaCha20_DRBG_Generate_function(int state_handle, int requested_no_of_bits
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) 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 entropy_input_len = min_entropy_input_length;
size_t personalization_string_len = strlen((char *)personalization_string); size_t personalization_string_len = strlen((char *)personalization_string);
size_t seed_material_size = entropy_input_len + sizeof(nonce) + personalization_string_len; size_t seed_material_size =
entropy_input_len + sizeof(nonce) + personalization_string_len;
uint8_t *seed_material = malloc(seed_material_size); uint8_t *seed_material = malloc(seed_material_size);
uint8_t *requested_bits; uint8_t *requested_bits;
time_t timep; time_t timep;
@@ -586,7 +569,8 @@ void ChaCha20_DRBG_Instantiate_algorithm(uint8_t *entropy_input, int nonce, uint
memcpy(seed_material, entropy_input, entropy_input_len); memcpy(seed_material, entropy_input, entropy_input_len);
memcpy(seed_material + entropy_input_len, &nonce, sizeof(nonce)); 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_len + sizeof(nonce),
personalization_string, personalization_string_len);
array_length = seed_material_size; array_length = seed_material_size;
requested_bits = ChaCha20_df(V, seed_material, SEEDLEN * 8); requested_bits = ChaCha20_df(V, seed_material, SEEDLEN * 8);
@@ -601,13 +585,17 @@ void ChaCha20_DRBG_Instantiate_algorithm(uint8_t *entropy_input, int nonce, uint
*reseed_time = time(&timep); *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) 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. // 1. seed_material = entropy_input || additional_input.
size_t seed_material_size = min_entropy_input_length + additional_input_length; size_t seed_material_size =
min_entropy_input_length + additional_input_length;
uint8_t *seed_material = malloc(seed_material_size); uint8_t *seed_material = malloc(seed_material_size);
memcpy(seed_material, entropy_input, min_entropy_input_length); memcpy(seed_material, entropy_input, min_entropy_input_length);
memcpy(seed_material + min_entropy_input_length, additional_input, additional_input_length); memcpy(seed_material + min_entropy_input_length, additional_input,
additional_input_length);
// 2. seed_material = Block_Cipher_df(seed_material, 256). // 2. seed_material = Block_Cipher_df(seed_material, 256).
uint8_t *requested_bits; uint8_t *requested_bits;
@@ -624,21 +612,20 @@ void ChaCha20_DRBG_Reseed_algorithm(uint8_t *V, uint8_t *Key, int *reseed_counte
*reseed_time = time(&timep); *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) char *ChaCha20_DRBG_Generate_algorithm(uint8_t *V, uint8_t *Key,
{ int *reseed_counter,
if (additional_input != NULL) int requested_number_of_bits,
{ uint8_t *additional_input,
uint8_t **returned_bits) {
if (additional_input != NULL) {
array_length = additional_input_length; array_length = additional_input_length;
additional_input = ChaCha20_df(V, additional_input, SEEDLEN * 8); additional_input = ChaCha20_df(V, additional_input, SEEDLEN * 8);
ChaCha20_DRBG_Update(additional_input, Key, V); ChaCha20_DRBG_Update(additional_input, Key, V);
} } else {
else
{
// Assuming additional_input is a byte array, we set it to 0 // Assuming additional_input is a byte array, we set it to 0
additional_input = (uint8_t *)malloc(SEEDLEN); additional_input = (uint8_t *)malloc(SEEDLEN);
additional_input_length = SEEDLEN; additional_input_length = SEEDLEN;
if (additional_input == NULL) if (additional_input == NULL) {
{
return "Memory allocation failed"; return "Memory allocation failed";
} }
memset(additional_input, 0, SEEDLEN); memset(additional_input, 0, SEEDLEN);
@@ -658,10 +645,9 @@ char *ChaCha20_DRBG_Generate_algorithm(uint8_t *V, uint8_t *Key, int *reseed_cou
return "Success"; return "Success";
} }
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) {
if (no_of_bits_to_return > MAX_NUMBER_OF_BITS) if (no_of_bits_to_return > MAX_NUMBER_OF_BITS) {
{
return NULL; return NULL;
} }
@@ -678,10 +664,10 @@ uint8_t *ChaCha20_df(uint8_t *V, uint8_t *input_string, size_t no_of_bits_to_ret
// Pad S with zeros, if necessary. // Pad S with zeros, if necessary.
int S_actual_size = S_init_size; // Taken the 0x80 into account int S_actual_size = S_init_size; // Taken the 0x80 into account
while (S_actual_size % OUTLEN != 0) while (S_actual_size % OUTLEN != 0) {
{
S = realloc(S, S_actual_size + 1); // Increase size by one byte 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 S[S_actual_size++] =
0x00; // Add a zero at current end, and increase actual size by one
} }
int temp_len = 0; int temp_len = 0;
@@ -689,18 +675,17 @@ uint8_t *ChaCha20_df(uint8_t *V, uint8_t *input_string, size_t no_of_bits_to_ret
uint32_t i = 0; uint32_t i = 0;
uint8_t K[KEYLEN]; uint8_t K[KEYLEN];
uint8_t source[] = { uint8_t source[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F}; 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F};
memcpy(K, source, KEYLEN); memcpy(K, source, KEYLEN);
ChaCha20_setup(chacha_state, K, chacha_nonce, V); ChaCha20_setup(chacha_state, K, chacha_nonce, V);
while (temp_len < KEYLEN + OUTLEN) while (temp_len < KEYLEN + OUTLEN) {
{
uint8_t IV[OUTLEN] = {0}; uint8_t IV[OUTLEN] = {0};
IV[OUTLEN - 4] = i; // 32-bit integer representation of i padded with zeros to OUTLEN bits. 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]; uint8_t data_to_be_encrypted[OUTLEN + S_actual_size];
memcpy(data_to_be_encrypted, IV, OUTLEN); memcpy(data_to_be_encrypted, IV, OUTLEN);
@@ -708,11 +693,13 @@ uint8_t *ChaCha20_df(uint8_t *V, uint8_t *input_string, size_t no_of_bits_to_ret
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_len = (i + 1) * (OUTLEN + S_actual_size);
temp = (uint8_t *)realloc(temp, temp_len); temp = (uint8_t *)realloc(temp, temp_len);
memcpy(temp + i * (OUTLEN + S_actual_size), data_encrypted_result, temp_len); memcpy(temp + i * (OUTLEN + S_actual_size), data_encrypted_result,
temp_len);
i++; i++;
} }
@@ -724,8 +711,7 @@ uint8_t *ChaCha20_df(uint8_t *V, uint8_t *input_string, size_t no_of_bits_to_ret
temp_len = 0; temp_len = 0;
ChaCha20_setup(chacha_state, K, chacha_nonce, V); ChaCha20_setup(chacha_state, K, chacha_nonce, V);
while (temp_len < no_of_bits_to_return / 8) while (temp_len < no_of_bits_to_return / 8) {
{
ChaCha20_encrypt(chacha_state, X, encrypted_data, OUTLEN, true); ChaCha20_encrypt(chacha_state, X, encrypted_data, OUTLEN, true);
memcpy(X, encrypted_data, OUTLEN); memcpy(X, encrypted_data, OUTLEN);
temp = (uint8_t *)realloc(temp, temp_len + OUTLEN); temp = (uint8_t *)realloc(temp, temp_len + OUTLEN);
@@ -734,8 +720,7 @@ uint8_t *ChaCha20_df(uint8_t *V, uint8_t *input_string, size_t no_of_bits_to_ret
} }
uint8_t *requested_bits = (uint8_t *)malloc(no_of_bits_to_return / 8); uint8_t *requested_bits = (uint8_t *)malloc(no_of_bits_to_return / 8);
if (requested_bits == NULL) if (requested_bits == NULL) {
{
return NULL; return NULL;
} }
@@ -749,8 +734,7 @@ uint8_t *ChaCha20_df(uint8_t *V, uint8_t *input_string, size_t no_of_bits_to_ret
return requested_bits; return requested_bits;
} }
int main() int main() {
{
uint8_t personalization_string[] = "this is personalization_string"; uint8_t personalization_string[] = "this is personalization_string";
char status[MAX_STATES] = {'\0'}; char status[MAX_STATES] = {'\0'};
int state_handle; int state_handle;
@@ -761,7 +745,8 @@ int main()
srand(time(0)); srand(time(0));
// 初始化DRBG // 初始化DRBG
state_handle = ChaCha20_DRBG_Instantiate_function(personalization_string, status); state_handle =
ChaCha20_DRBG_Instantiate_function(personalization_string, status);
// 需要生成的比特串长度 // 需要生成的比特串长度
printf("Enter the length of the bit string to be generated(bit): "); printf("Enter the length of the bit string to be generated(bit): ");
@@ -780,30 +765,26 @@ int main()
// 生成的比特串保存在文本文件中 // 生成的比特串保存在文本文件中
FILE *file = fopen(filename, "w"); FILE *file = fopen(filename, "w");
if (file == NULL) if (file == NULL) {
{
printf("无法打开文件\n"); printf("无法打开文件\n");
return 1; return 1;
} }
clock_t start_time = clock(); clock_t start_time = clock();
for (int j = 1; j <= returned_bits_num; ++j) for (int j = 1; j <= returned_bits_num; ++j) {
{ do {
do
{
int zero_count = 0; int zero_count = 0;
int one_count = 0; int one_count = 0;
additional_input_length = 0; additional_input_length = 0;
ChaCha20_DRBG_Generate_function(state_handle, returned_bits_len, NULL, &returned_bits); ChaCha20_DRBG_Generate_function(state_handle, returned_bits_len, NULL,
&returned_bits);
for (int i = 0; i < returned_bits_len / 8; i++) for (int i = 0; i < returned_bits_len / 8; i++) {
{
int bits = returned_bits[i]; int bits = returned_bits[i];
for (int j = 0; j < 8; j++) for (int j = 0; j < 8; j++) {
{
if (bits & 1) if (bits & 1)
one_count++; one_count++;
else else
@@ -825,8 +806,7 @@ int main()
// 将二进制数据转为十六进制后写入文件 // 将二进制数据转为十六进制后写入文件
char hex_str[returned_bits_len / 8 * 2 + 1]; char hex_str[returned_bits_len / 8 * 2 + 1];
for (int i = 0; i < returned_bits_len / 8; ++i) for (int i = 0; i < returned_bits_len / 8; ++i) {
{
sprintf(&hex_str[i * 2], "%02x", returned_bits[i]); sprintf(&hex_str[i * 2], "%02x", returned_bits[i]);
} }
hex_str[returned_bits_len / 8 * 2] = '\0'; hex_str[returned_bits_len / 8 * 2] = '\0';