This repository was archived by the owner on Dec 16, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdrbg_hmac.c
147 lines (116 loc) · 4.83 KB
/
drbg_hmac.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//
// Created by Ghost on 2019/9/12.
//
#include "include/drbg_hmac.h"
static bool DRBG_HMAC_Update(DRBG_HMAC *drbg,
const uint8_t *input1, uint32_t input1_len,
const uint8_t *input2, uint32_t input2_len,
const uint8_t *input3, uint32_t input3_len) {
// Key = hmac(Key, V || 0x00 || pdata)
uint8_t zero = 0x00;
if (!drbg->conf->hmac(drbg->V, drbg->conf->out_len, &zero, 1,
input1, input1_len, input2, input2_len, input3, input3_len,
drbg->Key, drbg->conf->out_len, drbg->Key))
return false;
// V = hmac(Key, V)
if (!drbg->conf->hmac(drbg->V, drbg->conf->out_len, NULL, 0, NULL, 0, NULL, 0, NULL, 0,
drbg->Key, drbg->conf->out_len, drbg->V))
return false;
// if provided data is null, return
if (input1 == NULL && input2 == NULL && input3 == NULL) return true;
// Key = hmac(Key, V || 0x01 || pdata)
uint8_t one = 0x01;
if (!drbg->conf->hmac(drbg->V, drbg->conf->out_len, &one, 1,
input1, input1_len, input2, input2_len, input3, input3_len,
drbg->Key, drbg->conf->out_len, drbg->Key))
return false;
// V = hmac(Key, V)
if (!drbg->conf->hmac(drbg->V, drbg->conf->out_len, NULL, 0, NULL, 0, NULL, 0, NULL, 0,
drbg->Key, drbg->conf->out_len, drbg->V))
return false;
return true;
}
bool DRBG_HMAC_new(DRBG_HMAC *drbg, DRBG_HMAC_CONF *conf) {
uint8_t *v, *key;
// validate config
if (conf == NULL || conf->hmac == NULL ||
conf->out_len == 0 ||
conf->reseed_interval == 0 ||
conf->security_strength == 0)
return false;
drbg->conf = conf;
/* initialize internal state */
v = malloc(conf->out_len);
memset(v, 0, conf->out_len);
drbg->V = v;
key = malloc(conf->out_len);
memset(key, 0, conf->out_len);
drbg->Key = key;
drbg->reseed_counter = 0;
drbg->prediction_resistance_flag = false;
return true;
}
bool DRBG_HMAC_instantiate(DRBG_HMAC *drbg,
const uint8_t *entropy, uint32_t entropy_length,
const uint8_t *nonce, uint32_t nonce_length,
const uint8_t *pstr, uint32_t pstr_length) {
// seed_material = entropy_input || nonce || personalization_string
// Key = 0x0000 with outlen
memset(drbg->Key, 0x00, drbg->conf->out_len);
// V = 0x0101 with outlen
memset(drbg->V, 0x01, drbg->conf->out_len);
DRBG_HMAC_Update(drbg, entropy, entropy_length, nonce, nonce_length, pstr, pstr_length);
drbg->reseed_counter = 1;
return true;
}
bool DRBG_HMAC_reseed(DRBG_HMAC *drbg,
uint8_t *entropy, uint32_t entropy_length,
uint8_t *add_input, uint32_t add_length) {
// seed_material = entropy_input || additional_input
uint32_t seed_mat_length = entropy_length + add_length;
uint8_t *seed_mat = malloc(seed_mat_length);
memcpy(seed_mat, entropy, entropy_length);
memcpy(&seed_mat[entropy_length], add_input, add_length);
DRBG_HMAC_Update(drbg, entropy, entropy_length, add_input, add_length, NULL, 0);
drbg->reseed_counter = 1;
free(seed_mat);
return true;
}
bool DRBG_HMAC_generate(DRBG_HMAC *drbg,
const uint8_t *add_input, uint32_t add_length,
uint8_t *output, uint32_t return_length) {
uint32_t remain;
if (add_input != NULL && add_length != 0) {
DRBG_HMAC_Update(drbg, add_input, add_length, NULL, 0, NULL, 0);
}
// since round is calculated to make output full of data returned
// we directly calculate remaining bytes to fill up output
for (remain = return_length;; remain -= drbg->conf->out_len) {
// V = hmac(Key, V)
if (!drbg->conf->hmac(drbg->V, drbg->conf->out_len, NULL, 0, NULL, 0, NULL, 0, NULL, 0,
drbg->Key, drbg->conf->out_len, drbg->V))
return false;
// temp = temp || V
// use the smaller one size, hash outputs up to hash_size length
if (remain > drbg->conf->out_len) memcpy(&output[return_length - remain], drbg->V, drbg->conf->out_len);
else {
// output remains less than out_len, which reaches final block
memcpy(&output[return_length - remain], drbg->V, remain);
break;
}
}
DRBG_HMAC_Update(drbg, add_input, add_length, NULL, 0, NULL, 0);
drbg->reseed_counter++;
return true;
}
bool DRBG_HMAC_uninstantiate(DRBG_HMAC *drbg) {
// clear V and Key state
memset(drbg->V, 0, drbg->conf->out_len);
free(drbg->V);
drbg->V = NULL;
memset(drbg->Key, 0, drbg->conf->out_len);
free(drbg->Key);
drbg->Key = NULL;
drbg->reseed_counter = 0;
return true;
}