]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bearssl/src/rand/aesctr_drbg.c
Add libbearssl
[FreeBSD/FreeBSD.git] / contrib / bearssl / src / rand / aesctr_drbg.c
1 /*
2  * Copyright (c) 2018 Thomas Pornin <pornin@bolet.org>
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 };