Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/bearssl/src/rand/aesctr_drbg.c
39507 views
1
/*
2
* Copyright (c) 2018 Thomas Pornin <[email protected]>
3
*
4
* Permission is hereby granted, free of charge, to any person obtaining
5
* a copy of this software and associated documentation files (the
6
* "Software"), to deal in the Software without restriction, including
7
* without limitation the rights to use, copy, modify, merge, publish,
8
* distribute, sublicense, and/or sell copies of the Software, and to
9
* permit persons to whom the Software is furnished to do so, subject to
10
* the following conditions:
11
*
12
* The above copyright notice and this permission notice shall be
13
* included in all copies or substantial portions of the Software.
14
*
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
* SOFTWARE.
23
*/
24
25
#include "inner.h"
26
27
/* see bearssl_rand.h */
28
void
29
br_aesctr_drbg_init(br_aesctr_drbg_context *ctx,
30
const br_block_ctr_class *aesctr,
31
const void *seed, size_t len)
32
{
33
unsigned char tmp[16];
34
35
ctx->vtable = &br_aesctr_drbg_vtable;
36
memset(tmp, 0, sizeof tmp);
37
aesctr->init(&ctx->sk.vtable, tmp, 16);
38
ctx->cc = 0;
39
br_aesctr_drbg_update(ctx, seed, len);
40
}
41
42
/* see bearssl_rand.h */
43
void
44
br_aesctr_drbg_generate(br_aesctr_drbg_context *ctx, void *out, size_t len)
45
{
46
unsigned char *buf;
47
unsigned char iv[12];
48
49
buf = out;
50
memset(iv, 0, sizeof iv);
51
while (len > 0) {
52
size_t clen;
53
54
/*
55
* We generate data by blocks of at most 65280 bytes. This
56
* allows for unambiguously testing the counter overflow
57
* condition; also, it should work on 16-bit architectures
58
* (where 'size_t' is 16 bits only).
59
*/
60
clen = len;
61
if (clen > 65280) {
62
clen = 65280;
63
}
64
65
/*
66
* We make sure that the counter won't exceed the configured
67
* limit.
68
*/
69
if ((uint32_t)(ctx->cc + ((clen + 15) >> 4)) > 32768) {
70
clen = (32768 - ctx->cc) << 4;
71
if (clen > len) {
72
clen = len;
73
}
74
}
75
76
/*
77
* Run CTR.
78
*/
79
memset(buf, 0, clen);
80
ctx->cc = ctx->sk.vtable->run(&ctx->sk.vtable,
81
iv, ctx->cc, buf, clen);
82
buf += clen;
83
len -= clen;
84
85
/*
86
* Every 32768 blocks, we force a state update.
87
*/
88
if (ctx->cc >= 32768) {
89
br_aesctr_drbg_update(ctx, NULL, 0);
90
}
91
}
92
}
93
94
/* see bearssl_rand.h */
95
void
96
br_aesctr_drbg_update(br_aesctr_drbg_context *ctx, const void *seed, size_t len)
97
{
98
/*
99
* We use a Hirose construction on AES-256 to make a hash function.
100
* Function definition:
101
* - running state consists in two 16-byte blocks G and H
102
* - initial values of G and H are conventional
103
* - there is a fixed block-sized constant C
104
* - for next data block m:
105
* set AES key to H||m
106
* G' = E(G) xor G
107
* H' = E(G xor C) xor G xor C
108
* G <- G', H <- H'
109
* - once all blocks have been processed, output is H||G
110
*
111
* Constants:
112
* G_init = B6 B6 ... B6
113
* H_init = A5 A5 ... A5
114
* C = 01 00 ... 00
115
*
116
* With this hash function h(), we compute the new state as
117
* follows:
118
* - produce a state-dependent value s as encryption of an
119
* all-one block with AES and the current key
120
* - compute the new key as the first 128 bits of h(s||seed)
121
*
122
* Original Hirose article:
123
* https://www.iacr.org/archive/fse2006/40470213/40470213.pdf
124
*/
125
126
unsigned char s[16], iv[12];
127
unsigned char G[16], H[16];
128
int first;
129
130
/*
131
* Use an all-one IV to get a fresh output block that depends on the
132
* current seed.
133
*/
134
memset(iv, 0xFF, sizeof iv);
135
memset(s, 0, 16);
136
ctx->sk.vtable->run(&ctx->sk.vtable, iv, 0xFFFFFFFF, s, 16);
137
138
/*
139
* Set G[] and H[] to conventional start values.
140
*/
141
memset(G, 0xB6, sizeof G);
142
memset(H, 0x5A, sizeof H);
143
144
/*
145
* Process the concatenation of the current state and the seed
146
* with the custom hash function.
147
*/
148
first = 1;
149
for (;;) {
150
unsigned char tmp[32];
151
unsigned char newG[16];
152
153
/*
154
* Assemble new key H||m into tmp[].
155
*/
156
memcpy(tmp, H, 16);
157
if (first) {
158
memcpy(tmp + 16, s, 16);
159
first = 0;
160
} else {
161
size_t clen;
162
163
if (len == 0) {
164
break;
165
}
166
clen = len < 16 ? len : 16;
167
memcpy(tmp + 16, seed, clen);
168
memset(tmp + 16 + clen, 0, 16 - clen);
169
seed = (const unsigned char *)seed + clen;
170
len -= clen;
171
}
172
ctx->sk.vtable->init(&ctx->sk.vtable, tmp, 32);
173
174
/*
175
* Compute new G and H values.
176
*/
177
memcpy(iv, G, 12);
178
memcpy(newG, G, 16);
179
ctx->sk.vtable->run(&ctx->sk.vtable, iv,
180
br_dec32be(G + 12), newG, 16);
181
iv[0] ^= 0x01;
182
memcpy(H, G, 16);
183
H[0] ^= 0x01;
184
ctx->sk.vtable->run(&ctx->sk.vtable, iv,
185
br_dec32be(G + 12), H, 16);
186
memcpy(G, newG, 16);
187
}
188
189
/*
190
* Output hash value is H||G. We truncate it to its first 128 bits,
191
* i.e. H; that's our new AES key.
192
*/
193
ctx->sk.vtable->init(&ctx->sk.vtable, H, 16);
194
ctx->cc = 0;
195
}
196
197
/* see bearssl_rand.h */
198
const br_prng_class br_aesctr_drbg_vtable = {
199
sizeof(br_aesctr_drbg_context),
200
(void (*)(const br_prng_class **, const void *, const void *, size_t))
201
&br_aesctr_drbg_init,
202
(void (*)(const br_prng_class **, void *, size_t))
203
&br_aesctr_drbg_generate,
204
(void (*)(const br_prng_class **, const void *, size_t))
205
&br_aesctr_drbg_update
206
};
207
208