xref: /freebsd/contrib/bearssl/src/aead/gcm.c (revision 2aaf9152a852aba9eb2036b95f4948ee77988826)
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
br_gcm_init(br_gcm_context * ctx,const br_block_ctr_class ** bctx,br_ghash gh)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
br_gcm_reset(br_gcm_context * ctx,const void * iv,size_t len)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
br_gcm_aad_inject(br_gcm_context * ctx,const void * data,size_t len)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
br_gcm_flip(br_gcm_context * ctx)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
br_gcm_run(br_gcm_context * ctx,int encrypt,void * data,size_t len)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
br_gcm_get_tag(br_gcm_context * ctx,void * tag)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
br_gcm_get_tag_trunc(br_gcm_context * ctx,void * tag,size_t len)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
br_gcm_check_tag_trunc(br_gcm_context * ctx,const void * tag,size_t len)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
br_gcm_check_tag(br_gcm_context * ctx,const void * tag)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 };
319