File Coverage

src/rand/aesctr_drbg.c
Criterion Covered Total %
statement 51 56 91.0
branch 9 14 64.2
condition n/a
subroutine n/a
pod n/a
total 60 70 85.7


line stmt bran cond sub pod time code
1             /*
2             * Copyright (c) 2018 Thomas Pornin
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 1           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 1           ctx->vtable = &br_aesctr_drbg_vtable;
36 1           memset(tmp, 0, sizeof tmp);
37 1           aesctr->init(&ctx->sk.vtable, tmp, 16);
38 1           ctx->cc = 0;
39 1           br_aesctr_drbg_update(ctx, seed, len);
40 1           }
41              
42             /* see bearssl_rand.h */
43             void
44 2           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 2           buf = out;
50 2           memset(iv, 0, sizeof iv);
51 4 100         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 2           clen = len;
61 2 50         if (clen > 65280) {
62 0           clen = 65280;
63             }
64              
65             /*
66             * We make sure that the counter won't exceed the configured
67             * limit.
68             */
69 2 50         if ((uint32_t)(ctx->cc + ((clen + 15) >> 4)) > 32768) {
70 0           clen = (32768 - ctx->cc) << 4;
71 0 0         if (clen > len) {
72 0           clen = len;
73             }
74             }
75              
76             /*
77             * Run CTR.
78             */
79 2           memset(buf, 0, clen);
80 2           ctx->cc = ctx->sk.vtable->run(&ctx->sk.vtable,
81             iv, ctx->cc, buf, clen);
82 2           buf += clen;
83 2           len -= clen;
84              
85             /*
86             * Every 32768 blocks, we force a state update.
87             */
88 2 50         if (ctx->cc >= 32768) {
89 0           br_aesctr_drbg_update(ctx, NULL, 0);
90             }
91             }
92 2           }
93              
94             /* see bearssl_rand.h */
95             void
96 2           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 2           memset(iv, 0xFF, sizeof iv);
135 2           memset(s, 0, 16);
136 2           ctx->sk.vtable->run(&ctx->sk.vtable, iv, 0xFFFFFFFF, s, 16);
137              
138             /*
139             * Set G[] and H[] to conventional start values.
140             */
141 2           memset(G, 0xB6, sizeof G);
142 2           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 2           first = 1;
149 4           for (;;) {
150             unsigned char tmp[32];
151             unsigned char newG[16];
152              
153             /*
154             * Assemble new key H||m into tmp[].
155             */
156 6           memcpy(tmp, H, 16);
157 6 100         if (first) {
158 2           memcpy(tmp + 16, s, 16);
159 2           first = 0;
160             } else {
161             size_t clen;
162              
163 4 100         if (len == 0) {
164 2           break;
165             }
166 2           clen = len < 16 ? len : 16;
167 2           memcpy(tmp + 16, seed, clen);
168 2           memset(tmp + 16 + clen, 0, 16 - clen);
169 2           seed = (const unsigned char *)seed + clen;
170 2           len -= clen;
171             }
172 4           ctx->sk.vtable->init(&ctx->sk.vtable, tmp, 32);
173              
174             /*
175             * Compute new G and H values.
176             */
177 4           memcpy(iv, G, 12);
178 4           memcpy(newG, G, 16);
179 4           ctx->sk.vtable->run(&ctx->sk.vtable, iv,
180             br_dec32be(G + 12), newG, 16);
181 4           iv[0] ^= 0x01;
182 4           memcpy(H, G, 16);
183 4           H[0] ^= 0x01;
184 4           ctx->sk.vtable->run(&ctx->sk.vtable, iv,
185             br_dec32be(G + 12), H, 16);
186 4           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 2           ctx->sk.vtable->init(&ctx->sk.vtable, H, 16);
194 2           ctx->cc = 0;
195 2           }
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             };