]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/bearssl/src/aead/gcm.c
MFV r354378,r354379,r354386: 10499 Multi-modifier protection (MMP)
[FreeBSD/FreeBSD.git] / contrib / bearssl / src / aead / gcm.c
1 /*
2  * Copyright (c) 2017 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 /*
28  * Implementation Notes
29  * ====================
30  *
31  * Since CTR and GHASH implementations can handle only full blocks, a
32  * 16-byte buffer (buf[]) is maintained in the context:
33  *
34  *  - When processing AAD, buf[] contains the 0-15 unprocessed bytes.
35  *
36  *  - When doing CTR encryption / decryption, buf[] contains the AES output
37  *    for the last partial block, to be used with the next few bytes of
38  *    data, as well as the already encrypted bytes. For instance, if the
39  *    processed data length so far is 21 bytes, then buf[0..4] contains
40  *    the five last encrypted bytes, and buf[5..15] contains the next 11
41  *    AES output bytes to be XORed with the next 11 bytes of input.
42  *
43  *    The recorded AES output bytes are used to complete the block when
44  *    the corresponding bytes are obtained. Note that buf[] always
45  *    contains the _encrypted_ bytes, whether we apply encryption or
46  *    decryption: these bytes are used as input to GHASH when the block
47  *    is complete.
48  *
49  * In both cases, the low bits of the data length counters (count_aad,
50  * count_ctr) are used to work out the current situation.
51  */
52
53 /* see bearssl_aead.h */
54 void
55 br_gcm_init(br_gcm_context *ctx, const br_block_ctr_class **bctx, br_ghash gh)
56 {
57         unsigned char iv[12];
58
59         ctx->vtable = &br_gcm_vtable;
60         ctx->bctx = bctx;
61         ctx->gh = gh;
62
63         /*
64          * The GHASH key h[] is the raw encryption of the all-zero
65          * block. Since we only have a CTR implementation, we use it
66          * with an all-zero IV and a zero counter, to CTR-encrypt an
67          * all-zero block.
68          */
69         memset(ctx->h, 0, sizeof ctx->h);
70         memset(iv, 0, sizeof iv);
71         (*bctx)->run(bctx, iv, 0, ctx->h, sizeof ctx->h);
72 }
73
74 /* see bearssl_aead.h */
75 void
76 br_gcm_reset(br_gcm_context *ctx, const void *iv, size_t len)
77 {
78         /*
79          * If the provided nonce is 12 bytes, then this is the initial
80          * IV for CTR mode; it will be used with a counter that starts
81          * at 2 (value 1 is for encrypting the GHASH output into the tag).
82          *
83          * If the provided nonce has any other length, then it is hashed
84          * (with GHASH) into a 16-byte value that will be the IV for CTR
85          * (both 12-byte IV and 32-bit counter).
86          */
87         if (len == 12) {
88                 memcpy(ctx->j0_1, iv, 12);
89                 ctx->j0_2 = 1;
90         } else {
91                 unsigned char ty[16], tmp[16];
92
93                 memset(ty, 0, sizeof ty);
94                 ctx->gh(ty, ctx->h, iv, len);
95                 memset(tmp, 0, 8);
96                 br_enc64be(tmp + 8, (uint64_t)len << 3);
97                 ctx->gh(ty, ctx->h, tmp, 16);
98                 memcpy(ctx->j0_1, ty, 12);
99                 ctx->j0_2 = br_dec32be(ty + 12);
100         }
101         ctx->jc = ctx->j0_2 + 1;
102         memset(ctx->y, 0, sizeof ctx->y);
103         ctx->count_aad = 0;
104         ctx->count_ctr = 0;
105 }
106
107 /* see bearssl_aead.h */
108 void
109 br_gcm_aad_inject(br_gcm_context *ctx, const void *data, size_t len)
110 {
111         size_t ptr, dlen;
112
113         ptr = (size_t)ctx->count_aad & (size_t)15;
114         if (ptr != 0) {
115                 /*
116                  * If there is a partial block, then we first try to
117                  * complete it.
118                  */
119                 size_t clen;
120
121                 clen = 16 - ptr;
122                 if (len < clen) {
123                         memcpy(ctx->buf + ptr, data, len);
124                         ctx->count_aad += (uint64_t)len;
125                         return;
126                 }
127                 memcpy(ctx->buf + ptr, data, clen);
128                 ctx->gh(ctx->y, ctx->h, ctx->buf, 16);
129                 data = (const unsigned char *)data + clen;
130                 len -= clen;
131                 ctx->count_aad += (uint64_t)clen;
132         }
133
134         /*
135          * Now AAD is aligned on a 16-byte block (with regards to GHASH).
136          * We process all complete blocks, and save the last partial
137          * block.
138          */
139         dlen = len & ~(size_t)15;
140         ctx->gh(ctx->y, ctx->h, data, dlen);
141         memcpy(ctx->buf, (const unsigned char *)data + dlen, len - dlen);
142         ctx->count_aad += (uint64_t)len;
143 }
144
145 /* see bearssl_aead.h */
146 void
147 br_gcm_flip(br_gcm_context *ctx)
148 {
149         /*
150          * We complete the GHASH computation if there is a partial block.
151          * The GHASH implementation automatically applies padding with
152          * zeros.
153          */
154         size_t ptr;
155
156         ptr = (size_t)ctx->count_aad & (size_t)15;
157         if (ptr != 0) {
158                 ctx->gh(ctx->y, ctx->h, ctx->buf, ptr);
159         }
160 }
161
162 /* see bearssl_aead.h */
163 void
164 br_gcm_run(br_gcm_context *ctx, int encrypt, void *data, size_t len)
165 {
166         unsigned char *buf;
167         size_t ptr, dlen;
168
169         buf = data;
170         ptr = (size_t)ctx->count_ctr & (size_t)15;
171         if (ptr != 0) {
172                 /*
173                  * If we have a partial block, then we try to complete it.
174                  */
175                 size_t u, clen;
176
177                 clen = 16 - ptr;
178                 if (len < clen) {
179                         clen = len;
180                 }
181                 for (u = 0; u < clen; u ++) {
182                         unsigned x, y;
183
184                         x = buf[u];
185                         y = x ^ ctx->buf[ptr + u];
186                         ctx->buf[ptr + u] = encrypt ? y : x;
187                         buf[u] = y;
188                 }
189                 ctx->count_ctr += (uint64_t)clen;
190                 buf += clen;
191                 len -= clen;
192                 if (ptr + clen < 16) {
193                         return;
194                 }
195                 ctx->gh(ctx->y, ctx->h, ctx->buf, 16);
196         }
197
198         /*
199          * Process full blocks.
200          */
201         dlen = len & ~(size_t)15;
202         if (!encrypt) {
203                 ctx->gh(ctx->y, ctx->h, buf, dlen);
204         }
205         ctx->jc = (*ctx->bctx)->run(ctx->bctx, ctx->j0_1, ctx->jc, buf, dlen);
206         if (encrypt) {
207                 ctx->gh(ctx->y, ctx->h, buf, dlen);
208         }
209         buf += dlen;
210         len -= dlen;
211         ctx->count_ctr += (uint64_t)dlen;
212
213         if (len > 0) {
214                 /*
215                  * There is a partial block.
216                  */
217                 size_t u;
218
219                 memset(ctx->buf, 0, sizeof ctx->buf);
220                 ctx->jc = (*ctx->bctx)->run(ctx->bctx, ctx->j0_1,
221                         ctx->jc, ctx->buf, 16);
222                 for (u = 0; u < len; u ++) {
223                         unsigned x, y;
224
225                         x = buf[u];
226                         y = x ^ ctx->buf[u];
227                         ctx->buf[u] = encrypt ? y : x;
228                         buf[u] = y;
229                 }
230                 ctx->count_ctr += (uint64_t)len;
231         }
232 }
233
234 /* see bearssl_aead.h */
235 void
236 br_gcm_get_tag(br_gcm_context *ctx, void *tag)
237 {
238         size_t ptr;
239         unsigned char tmp[16];
240
241         ptr = (size_t)ctx->count_ctr & (size_t)15;
242         if (ptr > 0) {
243                 /*
244                  * There is a partial block: encrypted/decrypted data has
245                  * been produced, but the encrypted bytes must still be
246                  * processed by GHASH.
247                  */
248                 ctx->gh(ctx->y, ctx->h, ctx->buf, ptr);
249         }
250
251         /*
252          * Final block for GHASH: the AAD and plaintext lengths (in bits).
253          */
254         br_enc64be(tmp, ctx->count_aad << 3);
255         br_enc64be(tmp + 8, ctx->count_ctr << 3);
256         ctx->gh(ctx->y, ctx->h, tmp, 16);
257
258         /*
259          * Tag is the GHASH output XORed with the encryption of the
260          * nonce with the initial counter value.
261          */
262         memcpy(tag, ctx->y, 16);
263         (*ctx->bctx)->run(ctx->bctx, ctx->j0_1, ctx->j0_2, tag, 16);
264 }
265
266 /* see bearssl_aead.h */
267 void
268 br_gcm_get_tag_trunc(br_gcm_context *ctx, void *tag, size_t len)
269 {
270         unsigned char tmp[16];
271
272         br_gcm_get_tag(ctx, tmp);
273         memcpy(tag, tmp, len);
274 }
275
276 /* see bearssl_aead.h */
277 uint32_t
278 br_gcm_check_tag_trunc(br_gcm_context *ctx, const void *tag, size_t len)
279 {
280         unsigned char tmp[16];
281         size_t u;
282         int x;
283
284         br_gcm_get_tag(ctx, tmp);
285         x = 0;
286         for (u = 0; u < len; u ++) {
287                 x |= tmp[u] ^ ((const unsigned char *)tag)[u];
288         }
289         return EQ0(x);
290 }
291
292 /* see bearssl_aead.h */
293 uint32_t
294 br_gcm_check_tag(br_gcm_context *ctx, const void *tag)
295 {
296         return br_gcm_check_tag_trunc(ctx, tag, 16);
297 }
298
299 /* see bearssl_aead.h */
300 const br_aead_class br_gcm_vtable = {
301         16,
302         (void (*)(const br_aead_class **, const void *, size_t))
303                 &br_gcm_reset,
304         (void (*)(const br_aead_class **, const void *, size_t))
305                 &br_gcm_aad_inject,
306         (void (*)(const br_aead_class **))
307                 &br_gcm_flip,
308         (void (*)(const br_aead_class **, int, void *, size_t))
309                 &br_gcm_run,
310         (void (*)(const br_aead_class **, void *))
311                 &br_gcm_get_tag,
312         (uint32_t (*)(const br_aead_class **, const void *))
313                 &br_gcm_check_tag,
314         (void (*)(const br_aead_class **, void *, size_t))
315                 &br_gcm_get_tag_trunc,
316         (uint32_t (*)(const br_aead_class **, const void *, size_t))
317                 &br_gcm_check_tag_trunc
318 };