]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bearssl/src/rand/hmac_drbg.c
MFC r366760: lua: update to 5.3.6
[FreeBSD/FreeBSD.git] / contrib / bearssl / src / rand / hmac_drbg.c
1 /*
2  * Copyright (c) 2016 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.h */
28 void
29 br_hmac_drbg_init(br_hmac_drbg_context *ctx,
30         const br_hash_class *digest_class, const void *seed, size_t len)
31 {
32         size_t hlen;
33
34         ctx->vtable = &br_hmac_drbg_vtable;
35         hlen = br_digest_size(digest_class);
36         memset(ctx->K, 0x00, hlen);
37         memset(ctx->V, 0x01, hlen);
38         ctx->digest_class = digest_class;
39         br_hmac_drbg_update(ctx, seed, len);
40 }
41
42 /* see bearssl.h */
43 void
44 br_hmac_drbg_generate(br_hmac_drbg_context *ctx, void *out, size_t len)
45 {
46         const br_hash_class *dig;
47         br_hmac_key_context kc;
48         br_hmac_context hc;
49         size_t hlen;
50         unsigned char *buf;
51         unsigned char x;
52
53         dig = ctx->digest_class;
54         hlen = br_digest_size(dig);
55         br_hmac_key_init(&kc, dig, ctx->K, hlen);
56         buf = out;
57         while (len > 0) {
58                 size_t clen;
59
60                 br_hmac_init(&hc, &kc, 0);
61                 br_hmac_update(&hc, ctx->V, hlen);
62                 br_hmac_out(&hc, ctx->V);
63                 clen = hlen;
64                 if (clen > len) {
65                         clen = len;
66                 }
67                 memcpy(buf, ctx->V, clen);
68                 buf += clen;
69                 len -= clen;
70         }
71
72         /*
73          * To prepare the state for the next request, we should call
74          * br_hmac_drbg_update() with an empty additional seed. However,
75          * we already have an initialized HMAC context with the right
76          * initial key, and we don't want to push another one on the
77          * stack, so we inline that update() call here.
78          */
79         br_hmac_init(&hc, &kc, 0);
80         br_hmac_update(&hc, ctx->V, hlen);
81         x = 0x00;
82         br_hmac_update(&hc, &x, 1);
83         br_hmac_out(&hc, ctx->K);
84         br_hmac_key_init(&kc, dig, ctx->K, hlen);
85         br_hmac_init(&hc, &kc, 0);
86         br_hmac_update(&hc, ctx->V, hlen);
87         br_hmac_out(&hc, ctx->V);
88 }
89
90 /* see bearssl.h */
91 void
92 br_hmac_drbg_update(br_hmac_drbg_context *ctx, const void *seed, size_t len)
93 {
94         const br_hash_class *dig;
95         br_hmac_key_context kc;
96         br_hmac_context hc;
97         size_t hlen;
98         unsigned char x;
99
100         dig = ctx->digest_class;
101         hlen = br_digest_size(dig);
102
103         /*
104          * 1. K = HMAC(K, V || 0x00 || seed)
105          */
106         br_hmac_key_init(&kc, dig, ctx->K, hlen);
107         br_hmac_init(&hc, &kc, 0);
108         br_hmac_update(&hc, ctx->V, hlen);
109         x = 0x00;
110         br_hmac_update(&hc, &x, 1);
111         br_hmac_update(&hc, seed, len);
112         br_hmac_out(&hc, ctx->K);
113         br_hmac_key_init(&kc, dig, ctx->K, hlen);
114
115         /*
116          * 2. V = HMAC(K, V)
117          */
118         br_hmac_init(&hc, &kc, 0);
119         br_hmac_update(&hc, ctx->V, hlen);
120         br_hmac_out(&hc, ctx->V);
121
122         /*
123          * 3. If the additional seed is empty, then stop here.
124          */
125         if (len == 0) {
126                 return;
127         }
128
129         /*
130          * 4. K = HMAC(K, V || 0x01 || seed)
131          */
132         br_hmac_init(&hc, &kc, 0);
133         br_hmac_update(&hc, ctx->V, hlen);
134         x = 0x01;
135         br_hmac_update(&hc, &x, 1);
136         br_hmac_update(&hc, seed, len);
137         br_hmac_out(&hc, ctx->K);
138         br_hmac_key_init(&kc, dig, ctx->K, hlen);
139
140         /*
141          * 5. V = HMAC(K, V)
142          */
143         br_hmac_init(&hc, &kc, 0);
144         br_hmac_update(&hc, ctx->V, hlen);
145         br_hmac_out(&hc, ctx->V);
146 }
147
148 /* see bearssl.h */
149 const br_prng_class br_hmac_drbg_vtable = {
150         sizeof(br_hmac_drbg_context),
151         (void (*)(const br_prng_class **, const void *, const void *, size_t))
152                 &br_hmac_drbg_init,
153         (void (*)(const br_prng_class **, void *, size_t))
154                 &br_hmac_drbg_generate,
155         (void (*)(const br_prng_class **, const void *, size_t))
156                 &br_hmac_drbg_update
157 };