chiark / gitweb /
symm/gcm.h, symm/gcm-def.h: Implement the GCM authenticated encryption mode.
[catacomb] / symm / gcm-def.h
1 /* -*-c-*-
2  *
3  * The GCM authenticated encryption mode
4  *
5  * (c) 2018 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of Catacomb.
11  *
12  * Catacomb is free software: you can redistribute it and/or modify it
13  * under the terms of the GNU Library General Public License as published
14  * by the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * Catacomb is distributed in the hope that it will be useful, but
18  * WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public
23  * License along with Catacomb.  If not, write to the Free Software
24  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
25  * USA.
26  */
27
28 #ifndef CATACOMB_GCM_DEF_H
29 #define CATACOMB_GCM_DEF_H
30
31 #ifdef __cplusplus
32   extern "C" {
33 #endif
34
35 /*----- Header files ------------------------------------------------------*/
36
37 #include <string.h>
38
39 #include <mLib/bits.h>
40 #include <mLib/sub.h>
41
42 #ifndef CATACOMB_ARENA_H
43 #  include "arena.h"
44 #endif
45
46 #ifndef CATACOMB_BLKC_H
47 #  include "blkc.h"
48 #endif
49
50 #ifndef CATACOMB_CT_H
51 #  include "ct.h"
52 #endif
53
54 #ifndef CATACOMB_KEYSZ_H
55 #  include "keysz.h"
56 #endif
57
58 #ifndef CATACOMB_PARANOIA_H
59 #  include "paranoia.h"
60 #endif
61
62 #ifndef CATACOMB_RSVR_H
63 #  include "rsvr.h"
64 #endif
65
66 /*----- Type definitions --------------------------------------------------*/
67
68 typedef struct gcm_params {
69   unsigned f;                           /* flags */
70 #define GCMF_SWAP 1u                    /*   swap byte order? */
71   unsigned n;                           /* number of words in block */
72   uint32 poly;                          /* selected polynomial mask */
73 } gcm_params;
74
75 /*----- Utilities ---------------------------------------------------------*/
76
77 /* Supported block sizes. */
78 #define GCM_WIDTHS(_) _(64) _(96) _(128) _(192) _(256)
79 #define GCM_NMAX 8
80
81 /* Polynomial tails for the supported block sizes. */
82 #define GCM_POLY_64  0xd8000000
83 #define GCM_POLY_96  0x82600000
84 #define GCM_POLY_128 0xe1000000
85 #define GCM_POLY_192 0xe1000000
86 #define GCM_POLY_256 0xa4200000
87
88 /* Determine whether to set the @GCMF_SWAP@ flag. */
89 #define GCM_SWAP_L GCMF_SWAP
90 #define GCM_SWAP_B 0
91
92 /* --- @gcm_mktable@ --- *
93  *
94  * Arguments:   @const gcm_params *p@ = pointer to the parameters
95  *              @uint32 *ktab@ = where to write the table; there must be
96  *                      space for %$32 n$% $%n$%-word entries, i.e.,
97  *                      %$32 n^2$% 32-bit words in total, where %$n$% is
98  *                      @p->n@, the block size in words
99  *              @const uint32 *k@ = input field element
100  *
101  * Returns:     ---
102  *
103  * Use:         Construct a table for use by @gcm_mulk_...@ below, to
104  *              multiply (vaguely) efficiently by @k@.
105  */
106
107 extern void gcm_mktable(const gcm_params */*p*/,
108                         uint32 */*ktab*/, const uint32 */*k*/);
109
110 /* --- @gcm_mulk_N@ --- *
111  *
112  * Arguments:   @uint32 *a@ = accumulator to multiply
113  *              @const uint32 *ktab@ = table constructed by @gcm_mktable@
114  *
115  * Returns:     ---
116  *
117  * Use:         Multiply @a@ by @k@ (implicitly represented in @ktab@),
118  *              updating @a@ in-place.  There are separate functions for each
119  *              supported block size because this is the function whose
120  *              performance actually matters.
121  */
122
123 #define GCM_DECL_MULK(nbits)                                            \
124   extern void gcm_mulk_##nbits(uint32 */*a*/, const uint32 */*ktab*/);
125 GCM_WIDTHS(GCM_DECL_MULK)
126 #undef GCM_DECL_MULK
127
128 /* Dispatch to the appropriate variant of @gcm_mulk@. */
129 #define GCM_MULK(PRE, a, ktab) BLKC_GLUE(gcm_mulk_, BLKC_BITS(PRE))(a, ktab)
130
131 /* --- @gcm_ghashdone@ --- *
132  *
133  * Arguments:   @const gcm_params *p@ = pointer to the parameters
134  *              @uint32 *a@ = GHASH accumulator
135  *              @const uint32 *ktab@ = multiplication table, built by
136  *                      @gcm_mktable@
137  *              @unsigned long xblocks, yblocks@ = number of whole blocks in
138  *                      the two inputs
139  *              @unsigned xbytes, ybytes@ = number of trailing bytes in the
140  *                      two inputs
141  *
142  * Returns:     ---
143  *
144  * Use:         Finishes a GHASH operation by appending the appropriately
145  *              encoded lengths of the two constituent messages.
146  */
147
148 extern void gcm_ghashdone(const gcm_params */*p*/,
149                           uint32 */*a*/, const uint32 */*ktab*/,
150                           unsigned long /*xblocks*/, unsigned /*xbytes*/,
151                           unsigned long /*yblocks*/, unsigned /*ybytes*/);
152
153 /* --- @gcm_concat@ --- *
154  *
155  * Arguments:   @const gcm_params *p@ = pointer to the parameters
156  *              @uint32 *z@ = GHASH accumulator for suffix, updated
157  *              @const uint32 *x@ = GHASH accumulator for prefix
158  *              @const uint32 *ktab@ = multiplication table, built by
159  *                      @gcm_mktable@
160  *              @unsigned long n@ = length of suffix in whole blocks
161  *
162  * Returns:     ---
163  *
164  * Use:         On entry, @x@ and @z@ are the results of hashing two strings
165  *              %$a$% and %$b$%, each a whole number of blocks long; in
166  *              particular, %$b$% is @n@ blocks long.  On exit, @z@ is
167  *              updated to be the hash of %$a \cat b$%.
168  */
169
170 extern void gcm_concat(const gcm_params */*p*/,
171                        uint32 */*z*/, const uint32 */*x*/,
172                        const uint32 */*ktab*/, unsigned long /*n*/);
173
174 /* Step the counter using GCM's strange only-the-last-32-bits convention. */
175 #define GCM_STEP(PRE, w) BLKC_GLUE(GCM_STEP_, BLKC_ENDIAN(PRE))(PRE, w)
176 #define GCM_STEP_B(PRE, w) GCM_STEP_X(PRE, BLKC_ID, w)
177 #define GCM_STEP_L(PRE, w) GCM_STEP_X(PRE, ENDSWAP32, w)
178 #define GCM_STEP_X(PRE, op, w) do {                                     \
179   BLKC_W(w);                                                            \
180   _w[PRE##_BLKSZ/4 - 1] = op(op(_w[PRE##_BLKSZ/4 - 1]) + 1);            \
181 } while (0)
182
183 /*----- Macros ------------------------------------------------------------*/
184
185 /* --- @GCM_DEF@ --- *
186  *
187  * Arguments:   @PRE@, @pre@ = prefixes for the underlying block cipher
188  *
189  * Use:         Creates an implementation for the GCM authenticated-
190  *              encryption mode.
191  */
192
193 #define GCM_DEF(PRE, pre) GCM_DEFX(PRE, pre, #pre, #pre)
194
195 #define GCM_DEFX(PRE, pre, name, fname)                                 \
196                                                                         \
197 static const gcm_params pre##_gcmparams = {                             \
198   BLKC_GLUE(GCM_SWAP_, BLKC_ENDIAN(PRE)),                               \
199   PRE##_BLKSZ/4,                                                        \
200   BLKC_GLUE(GCM_POLY_, BLKC_BITS(PRE))                                  \
201 };                                                                      \
202                                                                         \
203 const octet                                                             \
204   pre##_gcmnoncesz[] = { KSZ_ANY, PRE##_BLKSZ - 4 },                    \
205   pre##_gcmtagsz[] = { KSZ_RANGE, PRE##_BLKSZ, 0, PRE##_BLKSZ, 1 };     \
206                                                                         \
207 static const rsvr_policy pre##_gcmpolicy = { 0, PRE##_BLKSZ, PRE##_BLKSZ }; \
208                                                                         \
209 /* --- @pre_gcmsetkey@ --- *                                            \
210  *                                                                      \
211  * Arguments:   @pre_gcmkey *key@ = pointer to key block to fill in     \
212  *              @const void *k@ = pointer to key material               \
213  *              @size_t ksz@ = size of key material                     \
214  *                                                                      \
215  * Returns:     ---                                                     \
216  *                                                                      \
217  * Use:         Initializes an GCM key block.                           \
218  */                                                                     \
219                                                                         \
220 void pre##_gcmsetkey(pre##_gcmkey *key, const void *k, size_t ksz)      \
221 {                                                                       \
222   uint32 t[PRE##_BLKSZ/4];                                              \
223                                                                         \
224   /* Initialize the block cipher. */                                    \
225   pre##_init(&key->ctx, k, ksz);                                        \
226                                                                         \
227   /* Set up the GHASH multiplication table. */                          \
228   BLKC_ZERO(PRE, t); pre##_eblk(&key->ctx, t, t);                       \
229   gcm_mktable(&pre##_gcmparams, key->ktab, t);                          \
230 }                                                                       \
231                                                                         \
232 /* --- @pre_gcmaadinit@ --- *                                           \
233  *                                                                      \
234  * Arguments:   @pre_gcmaadctx *aad@ = pointer to AAD context           \
235  *              @const pre_gcmkey *key@ = pointer to key block          \
236  *                                                                      \
237  * Returns:     ---                                                     \
238  *                                                                      \
239  * Use:         Initializes an GCM AAD (`additional authenticated       \
240  *              data') context associated with a given key.  AAD        \
241  *              contexts can be copied and/or reused, saving time if    \
242  *              the AAD for a number of messages has a common prefix.   \
243  *                                                                      \
244  *              The @key@ doesn't need to be kept around, though        \
245  *              usually there'll at least be another copy in some GCM   \
246  *              operation context because the AAD on its own isn't much \
247  *              good.                                                   \
248  */                                                                     \
249                                                                         \
250 void pre##_gcmaadinit(pre##_gcmaadctx *aad, const pre##_gcmkey *key)    \
251   { aad->k = *key; aad->off = 0; aad->len = 0; BLKC_ZERO(PRE, aad->a); } \
252                                                                         \
253 /* --- @pre_gcmaadhash@ --- *                                           \
254  *                                                                      \
255  * Arguments:   @pre_gcmaadctx *aad@ = pointer to AAD context           \
256  *              @const void *p@ = pointer to AAD material               \
257  *              @size_t sz@ = length of AAD material                    \
258  *                                                                      \
259  * Returns:     ---                                                     \
260  *                                                                      \
261  * Use:         Feeds AAD into the context.                             \
262  */                                                                     \
263                                                                         \
264 void pre##_gcmaadhash(pre##_gcmaadctx *aad, const void *p, size_t sz)   \
265 {                                                                       \
266   rsvr_state st;                                                        \
267   const octet *q;                                                       \
268                                                                         \
269   rsvr_setup(&st, &pre##_gcmpolicy, aad->b, &aad->off, p, sz);          \
270   RSVR_DO(&st) while ((q = RSVR_NEXT(&st, PRE##_BLKSZ)) != 0) {         \
271     BLKC_XLOAD(PRE, aad->a, q); GCM_MULK(PRE, aad->a, aad->k.ktab);     \
272     aad->len++;                                                         \
273   }                                                                     \
274 }                                                                       \
275                                                                         \
276 /* --- @pre_gcminit@ --- *                                              \
277  *                                                                      \
278  * Arguments:   @pre_gcmctx *ctx@ = pointer to GCM context              \
279  *              @const pre_gcmkey *key@ = pointer to key block          \
280  *              @const void *n@ = pointer to nonce                      \
281  *              @size_t nsz@ = size of nonce                            \
282  *                                                                      \
283  * Returns:     ---                                                     \
284  *                                                                      \
285  * Use:         Initialize an GCM operation context with a given key.   \
286  *                                                                      \
287  *              The original key needn't be kept around any more.       \
288  */                                                                     \
289                                                                         \
290 void pre##_gcminit(pre##_gcmctx *ctx, const pre##_gcmkey *k,            \
291                    const void *n, size_t nsz)                           \
292   { ctx->k = *k; pre##_gcmreinit(ctx, n, nsz); }                        \
293                                                                         \
294 /* --- @pre_gcmreinit@ --- *                                            \
295  *                                                                      \
296  * Arguments:   @pre_gcmctx *ctx@ = pointer to GCM context              \
297  *              @const void *n@ = pointer to nonce                      \
298  *              @size_t nsz@ = size of nonce                            \
299  *                                                                      \
300  * Returns:     ---                                                     \
301  *                                                                      \
302  * Use:         Reinitialize an GCM operation context, changing the     \
303  *              nonce.                                                  \
304  */                                                                     \
305                                                                         \
306 void pre##_gcmreinit(pre##_gcmctx *ctx, const void *n, size_t nsz)      \
307 {                                                                       \
308   octet b[PRE##_BLKSZ];                                                 \
309   const octet *q = n;                                                   \
310   size_t nblocks;                                                       \
311   unsigned i;                                                           \
312                                                                         \
313   /* Zero the counters. */                                              \
314   ctx->off = 0; ctx->len = 0;                                           \
315   BLKC_ZERO(PRE, ctx->a);                                               \
316                                                                         \
317   /* Calculate the initial counter from the nonce. */                   \
318   if (nsz == PRE##_BLKSZ - 4) {                                         \
319     /* Easy version: initialize the final word to 1 and copy the        \
320      * remaining words from the nonce.  (The spec shows the nonce and   \
321      * counter the other way around for 64-bit block ciphers, but I'm   \
322      * sure this is just a mistake.)                                    \
323      */                                                                 \
324                                                                         \
325     for (i = 0; i < PRE##_BLKSZ/4 - 1; i++)                             \
326       { ctx->c0[i] = BLKC_LOAD_E(PRE)(q); q += 4; }                     \
327     ctx->c0[PRE##_BLKSZ/4 - 1] = BLKC_BWORD(PRE, 1);                    \
328   } else {                                                              \
329     /* Harder version: hash the nonce down with GHASH. */               \
330                                                                         \
331     BLKC_ZERO(PRE, ctx->c0); nblocks = 0;                               \
332     while (nsz >= PRE##_BLKSZ) {                                        \
333       BLKC_XLOAD(PRE, ctx->c0, q); q += PRE##_BLKSZ;                    \
334       GCM_MULK(PRE, ctx->c0, ctx->k.ktab);                              \
335       nsz -= PRE##_BLKSZ; nblocks++;                                    \
336     }                                                                   \
337     if (nsz) {                                                          \
338       memcpy(b, q, nsz); memset(b + nsz, 0, PRE##_BLKSZ - nsz);         \
339       BLKC_XLOAD(PRE, ctx->c0, b);                                      \
340       GCM_MULK(PRE, ctx->c0, ctx->k.ktab);                              \
341     }                                                                   \
342     gcm_ghashdone(&pre##_gcmparams, ctx->c0, ctx->k.ktab,               \
343                   0, 0, nblocks, nsz);                                  \
344   }                                                                     \
345                                                                         \
346   /* We must remember the initial counter for the final tag             \
347    * calculation.  (I conjecture that storing the final counter instead \
348    * would be just as secure, and require less state, but I've not      \
349    * proven this, and anyway it wouldn't interoperate.)  Copy it to     \
350    * make the working counter.                                          \
351    */                                                                   \
352   BLKC_MOVE(PRE, ctx->c, ctx->c0);                                      \
353 }                                                                       \
354                                                                         \
355 /* --- @pre_gcmencrypt@ --- *                                           \
356  *                                                                      \
357  * Arguments:   @pre_gcmctx *ctx@ = pointer to GCM operation context    \
358  *              @const void *src@ = pointer to plaintext message chunk  \
359  *              @size_t sz@ = size of the plaintext                     \
360  *              @buf *dst@ = a buffer to write the ciphertext to        \
361  *                                                                      \
362  * Returns:     Zero on success; @-1@ on failure.                       \
363  *                                                                      \
364  * Use:         Encrypts a chunk of a plaintext message, writing a      \
365  *              chunk of ciphertext to the output buffer and updating   \
366  *              the operation state.                                    \
367  *                                                                      \
368  *              For GCM, we always write a ciphertext chunk the same    \
369  *              size as the plaintext.  The messing about with @buf@    \
370  *              objects makes the interface consistent with other AEAD  \
371  *              schemes which can't do this.                            \
372  */                                                                     \
373                                                                         \
374 int pre##_gcmencrypt(pre##_gcmctx *ctx,                                 \
375                      const void *src, size_t sz, buf *dst)              \
376 {                                                                       \
377   rsvr_plan plan;                                                       \
378   uint32 t[PRE##_BLKSZ/4];                                              \
379   const octet *p = src;                                                 \
380   octet *q, *r, y;                                                      \
381                                                                         \
382   /* Allocate space for the ciphertext. */                              \
383   if (sz) { q = buf_get(dst, sz); if (!q) return (-1); }                \
384   else q = 0;                                                           \
385                                                                         \
386   /* Determine the buffering plan.  Our buffer is going to do double-   \
387    * duty here.  The end portion is going to contain mask from the      \
388    * encrypted counter which we mix into the plaintext to encrypt it;   \
389    * the start portion, which originally mask bytes we've already used, \
390    * will hold the output ciphertext, which will eventually be          \
391    * collected into the GHASH state.                                    \
392    */                                                                   \
393   rsvr_mkplan(&plan, &pre##_gcmpolicy, ctx->off, sz);                   \
394                                                                         \
395   /* Initial portion, fulfilled from the buffer.  If the buffer is      \
396    * empty, then that means that we haven't yet encrypted the current   \
397    * counter, so we should do that and advance it.                      \
398    */                                                                   \
399   if (plan.head) {                                                      \
400     if (!ctx->off) {                                                    \
401       GCM_STEP(PRE, ctx->c); pre##_eblk(&ctx->k.ctx, ctx->c, t);        \
402       BLKC_STORE(PRE, ctx->b, t);                                       \
403     }                                                                   \
404     r = ctx->b + ctx->off; ctx->off += plan.head;                       \
405     while (plan.head--) { y = *p++ ^ *r; *r++ = *q++ = y; }             \
406   }                                                                     \
407                                                                         \
408   /* If we've filled up the buffer then we need to cycle the MAC and    \
409    * reset the offset.                                                  \
410    */                                                                   \
411   if (plan.from_rsvr) {                                                 \
412     BLKC_XLOAD(PRE, ctx->a, ctx->b); GCM_MULK(PRE, ctx->a, ctx->k.ktab); \
413     ctx->len++; ctx->off = 0;                                           \
414   }                                                                     \
415                                                                         \
416   /* Now to process the main body of the input. */                      \
417   while (plan.from_input) {                                             \
418     GCM_STEP(PRE, ctx->c); pre##_eblk(&ctx->k.ctx, ctx->c, t);          \
419     BLKC_XLOAD(PRE, t, p); p += PRE##_BLKSZ;                            \
420     BLKC_STORE(PRE, q, t); q += PRE##_BLKSZ;                            \
421     BLKC_XMOVE(PRE, ctx->a, t); GCM_MULK(PRE, ctx->a, ctx->k.ktab);     \
422     plan.from_input -= PRE##_BLKSZ; ctx->len++;                         \
423   }                                                                     \
424                                                                         \
425   /* Finally, deal with any final portion.  If there is one, we know    \
426    * that the buffer is empty: we must have filled it above, or this    \
427    * would all count as `initial' data.                                 \
428    */                                                                   \
429   if (plan.tail) {                                                      \
430     GCM_STEP(PRE, ctx->c); pre##_eblk(&ctx->k.ctx, ctx->c, t);          \
431     BLKC_STORE(PRE, ctx->b, t);                                         \
432     r = ctx->b; ctx->off += plan.tail;                                  \
433     while (plan.tail--) { y = *p++ ^ *r; *r++ = *q++ = y; }             \
434   }                                                                     \
435                                                                         \
436   /* And we're done. */                                                 \
437   return (0);                                                           \
438 }                                                                       \
439                                                                         \
440 /* --- @pre_gcmdecrypt@ --- *                                           \
441  *                                                                      \
442  * Arguments:   @pre_gcmctx *ctx@ = pointer to GCM operation context    \
443  *              @const void *src@ = pointer to ciphertext message chunk \
444  *              @size_t sz@ = size of the ciphertext                    \
445  *              @buf *dst@ = a buffer to write the plaintext to         \
446  *                                                                      \
447  * Returns:     Zero on success; @-1@ on failure.                       \
448  *                                                                      \
449  * Use:         Decrypts a chunk of a ciphertext message, writing a     \
450  *              chunk of plaintext to the output buffer and updating    \
451  *              the operation state.                                    \
452  *                                                                      \
453  *              For GCM, we always write a plaintext chunk the same     \
454  *              size as the ciphertext.  The messing about with @buf@   \
455  *              objects makes the interface consistent with other AEAD  \
456  *              schemes which can't do this.                            \
457  */                                                                     \
458                                                                         \
459 int pre##_gcmdecrypt(pre##_gcmctx *ctx,                                 \
460                      const void *src, size_t sz, buf *dst)              \
461 {                                                                       \
462   rsvr_plan plan;                                                       \
463   uint32 t[PRE##_BLKSZ/4], u[PRE##_BLKSZ];                              \
464   const octet *p = src;                                                 \
465   octet *q, *r, y;                                                      \
466                                                                         \
467   /* Allocate space for the plaintext. */                               \
468   if (sz) { q = buf_get(dst, sz); if (!q) return (-1); }                \
469   else q = 0;                                                           \
470                                                                         \
471   /* Determine the buffering plan.  Our buffer is going to do double-   \
472    * duty here.  The end portion is going to contain mask from the      \
473    * encrypted counter which we mix into the plaintext to encrypt it;   \
474    * the start portion, which originally mask bytes we've already used, \
475    * will hold the input ciphertext, which will eventually be           \
476    * collected into the GHASH state.                                    \
477    */                                                                   \
478   rsvr_mkplan(&plan, &pre##_gcmpolicy, ctx->off, sz);                   \
479                                                                         \
480   /* Initial portion, fulfilled from the buffer.  If the buffer is      \
481    * empty, then that means that we haven't yet encrypted the current   \
482    * counter, so we should do that and advance it.                      \
483    */                                                                   \
484   if (plan.head) {                                                      \
485     if (!ctx->off) {                                                    \
486       GCM_STEP(PRE, ctx->c); pre##_eblk(&ctx->k.ctx, ctx->c, t);        \
487       BLKC_STORE(PRE, ctx->b, t);                                       \
488     }                                                                   \
489     r = ctx->b + ctx->off; ctx->off += plan.head;                       \
490     while (plan.head--) { y = *p++; *q++ = y ^ *r; *r++ = y; }          \
491   }                                                                     \
492                                                                         \
493   /* If we've filled up the buffer then we need to cycle the MAC and    \
494    * reset the offset.                                                  \
495    */                                                                   \
496   if (plan.from_rsvr) {                                                 \
497     BLKC_XLOAD(PRE, ctx->a, ctx->b); GCM_MULK(PRE, ctx->a, ctx->k.ktab); \
498     ctx->len++; ctx->off = 0;                                           \
499   }                                                                     \
500                                                                         \
501   /* Now to process the main body of the input. */                      \
502   while (plan.from_input) {                                             \
503     GCM_STEP(PRE, ctx->c); pre##_eblk(&ctx->k.ctx, ctx->c, t);          \
504     BLKC_LOAD(PRE, u, p); p += PRE##_BLKSZ;                             \
505     BLKC_XSTORE(PRE, q, t, u); q += PRE##_BLKSZ;                        \
506     BLKC_XMOVE(PRE, ctx->a, u); GCM_MULK(PRE, ctx->a, ctx->k.ktab);     \
507     plan.from_input -= PRE##_BLKSZ; ctx->len++;                         \
508   }                                                                     \
509                                                                         \
510   /* Finally, deal with any final portion.  If there is one, we know    \
511    * that the buffer is empty: we must have filled it above, or this    \
512    * would all count as `initial' data.                                 \
513    */                                                                   \
514   if (plan.tail) {                                                      \
515     GCM_STEP(PRE, ctx->c); pre##_eblk(&ctx->k.ctx, ctx->c, t);          \
516     BLKC_STORE(PRE, ctx->b, t);                                         \
517     r = ctx->b; ctx->off += plan.tail;                                  \
518     while (plan.tail--) { y = *p++; *q++ = y ^ *r; *r++ = y; }          \
519   }                                                                     \
520                                                                         \
521   /* And we're done. */                                                 \
522   return (0);                                                           \
523 }                                                                       \
524                                                                         \
525 /* --- @pre_gcmtag@ --- *                                               \
526  *                                                                      \
527  * Arguments:   @pre_gcmctx *ctx@ = pointer to an GCM context           \
528  *              @const pre_gcmaadctx *aad@ = pointer to AAD context, or \
529  *                      null                                            \
530  *              @octet *t@ = where to write a (full-length) tag         \
531  *                                                                      \
532  * Returns:     ---                                                     \
533  *                                                                      \
534  * Use:         Finishes an GCM operation, by calculating the tag.      \
535  */                                                                     \
536                                                                         \
537 static void pre##_gcmtag(pre##_gcmctx *ctx,                             \
538                          const pre##_gcmaadctx *aad, octet *t)          \
539 {                                                                       \
540   octet b[PRE##_BLKSZ];                                                 \
541   uint32 u[PRE##_BLKSZ/4];                                              \
542   unsigned long n;                                                      \
543                                                                         \
544   /* Finish tagging the ciphertext. */                                  \
545   if (ctx->off) {                                                       \
546     memcpy(b, ctx->b, ctx->off);                                        \
547     memset(b + ctx->off, 0, PRE##_BLKSZ - ctx->off);                    \
548     BLKC_XLOAD(PRE, ctx->a, b); GCM_MULK(PRE, ctx->a, ctx->k.ktab);     \
549   }                                                                     \
550                                                                         \
551   /* If there's no AAD, because the pointer is null or no data was      \
552    * supplied, then apply that to the GHASH state.  (Otherwise there's  \
553    * nothing to do here.)                                               \
554    */                                                                   \
555   if (aad && (aad->len || aad->off)) {                                  \
556     BLKC_MOVE(PRE, u, aad->a);                                          \
557     if (aad->off) {                                                     \
558       memcpy(b, aad->b, aad->off);                                      \
559       memset(b + aad->off, 0, PRE##_BLKSZ - aad->off);                  \
560       BLKC_XLOAD(PRE, u, b); GCM_MULK(PRE, u, ctx->k.ktab);             \
561     }                                                                   \
562     n = ctx->len; if (ctx->off) n++;                                    \
563     gcm_concat(&pre##_gcmparams, ctx->a, u, ctx->k.ktab, n);            \
564   }                                                                     \
565                                                                         \
566   /* Finish off the hash by appending the length. */                    \
567   gcm_ghashdone(&pre##_gcmparams, ctx->a, ctx->k.ktab,                  \
568                 aad ? aad->len : 0, aad ? aad->off : 0,                 \
569                 ctx->len, ctx->off);                                    \
570                                                                         \
571   /* Mask the hash and store. */                                        \
572   pre##_eblk(&ctx->k.ctx, ctx->c0, u);                                  \
573   BLKC_XSTORE(PRE, t, ctx->a, u);                                       \
574 }                                                                       \
575                                                                         \
576 /* --- @pre_gcmencryptdone@ --- *                                       \
577  *                                                                      \
578  * Arguments:   @pre_gcmctx *ctx@ = pointer to an GCM context           \
579  *              @const pre_gcmaadctx *aad@ = pointer to AAD context, or \
580  *                      null                                            \
581  *              @buf *dst@ = buffer for remaining ciphertext            \
582  *              @void *tag@ = where to write the tag                    \
583  *              @size_t tsz@ = length of tag to store                   \
584  *                                                                      \
585  * Returns:     Zero on success; @-1@ on failure.                       \
586  *                                                                      \
587  * Use:         Completes an GCM encryption operation.  The @aad@       \
588  *              pointer may be null if there is no additional           \
589  *              authenticated data.  GCM doesn't buffer ciphertext, but \
590  *              the output buffer is provided anyway for consistency    \
591  *              with other AEAD schemes which don't have this property; \
592  *              the function will fail if the output buffer is broken.  \
593  */                                                                     \
594                                                                         \
595 int pre##_gcmencryptdone(pre##_gcmctx *ctx,                             \
596                          const pre##_gcmaadctx *aad, buf *dst,          \
597                          void *tag, size_t tsz)                         \
598 {                                                                       \
599   octet t[PRE##_BLKSZ];                                                 \
600                                                                         \
601   if (tsz > PRE##_BLKSZ) return (-1);                                   \
602   if (!BOK(dst)) return (-1);                                           \
603   pre##_gcmtag(ctx, aad, t); memcpy(tag, t, tsz);                       \
604   return (0);                                                           \
605 }                                                                       \
606                                                                         \
607 /* --- @pre_gcmdecryptdone@ --- *                                       \
608  *                                                                      \
609  * Arguments:   @pre_gcmctx *ctx@ = pointer to an GCM context           \
610  *              @const pre_gcmaadctx *aad@ = pointer to AAD context, or \
611  *                      null                                            \
612  *              @buf *dst@ = buffer for remaining plaintext             \
613  *              @const void *tag@ = tag to verify                       \
614  *              @size_t tsz@ = length of tag                            \
615  *                                                                      \
616  * Returns:     @+1@ for complete success; @0@ if tag verification      \
617  *              failed; @-1@ for other kinds of errors.                 \
618  *                                                                      \
619  * Use:         Completes an GCM decryption operation.  The @aad@       \
620  *              pointer may be null if there is no additional           \
621  *              authenticated data.  GCM doesn't buffer plaintext, but  \
622  *              the output buffer is provided anyway for consistency    \
623  *              with other AEAD schemes which don't have this property; \
624  *              the function will fail if the output buffer is broken.  \
625  */                                                                     \
626                                                                         \
627 int pre##_gcmdecryptdone(pre##_gcmctx *ctx,                             \
628                          const pre##_gcmaadctx *aad, buf *dst,          \
629                          const void *tag, size_t tsz)                   \
630 {                                                                       \
631   octet t[PRE##_BLKSZ];                                                 \
632                                                                         \
633   if (tsz > PRE##_BLKSZ) return (-1);                                   \
634   if (!BOK(dst)) return (-1);                                           \
635   pre##_gcmtag(ctx, aad, t);                                            \
636   if (!ct_memeq(tag, t, tsz)) return (0);                               \
637   else return (+1);                                                     \
638 }                                                                       \
639                                                                         \
640 /* --- Generic AEAD interface --- */                                    \
641                                                                         \
642 typedef struct gactx {                                                  \
643   gaead_aad a;                                                          \
644   pre##_gcmaadctx aad;                                                  \
645 } gactx;                                                                \
646                                                                         \
647 static gaead_aad *gadup(const gaead_aad *a)                             \
648   { gactx *aad = S_CREATE(gactx); *aad = *(gactx *)a; return (&aad->a); } \
649                                                                         \
650 static void gahash(gaead_aad *a, const void *h, size_t hsz)             \
651   { gactx *aad = (gactx *)a; pre##_gcmaadhash(&aad->aad, h, hsz); }     \
652                                                                         \
653 static void gadestroy(gaead_aad *a)                                     \
654   { gactx *aad = (gactx *)a; BURN(*aad); S_DESTROY(aad); }              \
655                                                                         \
656 static const gaead_aadops gaops =                                       \
657   { &pre##_gcm, gadup, gahash, gadestroy };                             \
658                                                                         \
659 static gaead_aad *gaad(const pre##_gcmkey *k)                           \
660 {                                                                       \
661   gactx *aad = S_CREATE(gactx);                                         \
662   aad->a.ops = &gaops;                                                  \
663   pre##_gcmaadinit(&aad->aad, k);                                       \
664   return (&aad->a);                                                     \
665 }                                                                       \
666                                                                         \
667 typedef struct gectx {                                                  \
668   gaead_enc e;                                                          \
669   pre##_gcmctx ctx;                                                     \
670 } gectx;                                                                \
671                                                                         \
672 static gaead_aad *geaad(gaead_enc *e)                                   \
673   { gectx *enc = (gectx *)e; return (gaad(&enc->ctx.k)); }              \
674                                                                         \
675 static int gereinit(gaead_enc *e, const void *n, size_t nsz,            \
676                     size_t hsz, size_t msz, size_t tsz)                 \
677 {                                                                       \
678   gectx *enc = (gectx *)e;                                              \
679                                                                         \
680   if (tsz > PRE##_BLKSZ) return (-1);                                   \
681   pre##_gcmreinit(&enc->ctx, n, nsz);                                   \
682   return (0);                                                           \
683 }                                                                       \
684                                                                         \
685 static int geenc(gaead_enc *e, const void *m, size_t msz, buf *b)       \
686 {                                                                       \
687   gectx *enc = (gectx *)e;                                              \
688   return (pre##_gcmencrypt(&enc->ctx, m, msz, b));                      \
689 }                                                                       \
690                                                                         \
691 static int gedone(gaead_enc *e, const gaead_aad *a,                     \
692                   buf *b, void *t, size_t tsz)                          \
693 {                                                                       \
694   gectx *enc = (gectx *)e; gactx *aad = (gactx *)a;                     \
695   assert(!a || a->ops == &gaops);                                       \
696   return (pre##_gcmencryptdone(&enc->ctx, a ? &aad->aad : 0, b, t, tsz)); \
697 }                                                                       \
698                                                                         \
699 static void gedestroy(gaead_enc *e)                                     \
700   { gectx *enc = (gectx *)e; BURN(*enc); S_DESTROY(enc); }              \
701                                                                         \
702 static const gaead_encops geops =                                       \
703   { &pre##_gcm, geaad, gereinit, geenc, gedone, gedestroy };            \
704                                                                         \
705 typedef struct gdctx {                                                  \
706   gaead_dec d;                                                          \
707   pre##_gcmctx ctx;                                                     \
708 } gdctx;                                                                \
709                                                                         \
710 static gaead_aad *gdaad(gaead_dec *d)                                   \
711   { gdctx *dec = (gdctx *)d; return (gaad(&dec->ctx.k)); }              \
712                                                                         \
713 static int gdreinit(gaead_dec *d, const void *n, size_t nsz,            \
714                      size_t hsz, size_t csz, size_t tsz)                \
715 {                                                                       \
716   gdctx *dec = (gdctx *)d;                                              \
717                                                                         \
718   if (tsz > PRE##_BLKSZ) return (-1);                                   \
719   pre##_gcmreinit(&dec->ctx, n, nsz);                                   \
720   return (0);                                                           \
721 }                                                                       \
722                                                                         \
723 static int gddec(gaead_dec *d, const void *c, size_t csz, buf *b)       \
724 {                                                                       \
725   gdctx *dec = (gdctx *)d;                                              \
726   return (pre##_gcmdecrypt(&dec->ctx, c, csz, b));                      \
727 }                                                                       \
728                                                                         \
729 static int gddone(gaead_dec *d, const gaead_aad *a,                     \
730                   buf *b, const void *t, size_t tsz)                    \
731 {                                                                       \
732   gdctx *dec = (gdctx *)d; gactx *aad = (gactx *)a;                     \
733   assert(!a || a->ops == &gaops);                                       \
734   return (pre##_gcmdecryptdone(&dec->ctx, a ? &aad->aad : 0, b, t, tsz)); \
735 }                                                                       \
736                                                                         \
737 static void gddestroy(gaead_dec *d)                                     \
738   { gdctx *dec = (gdctx *)d; BURN(*dec); S_DESTROY(dec); }              \
739                                                                         \
740 static const gaead_decops gdops =                                       \
741   { &pre##_gcm, gdaad, gdreinit, gddec, gddone, gddestroy };            \
742                                                                         \
743 typedef struct gkctx {                                                  \
744   gaead_key k;                                                          \
745   pre##_gcmkey key;                                                     \
746 } gkctx;                                                                \
747                                                                         \
748 static gaead_aad *gkaad(const gaead_key *k)                             \
749   { gkctx *key = (gkctx *)k; return (gaad(&key->key)); }                \
750                                                                         \
751 static gaead_enc *gkenc(const gaead_key *k, const void *n, size_t nsz,  \
752                         size_t hsz, size_t msz, size_t tsz)             \
753 {                                                                       \
754   gkctx *key = (gkctx *)k;                                              \
755   gectx *enc = S_CREATE(gectx);                                         \
756                                                                         \
757   enc->e.ops = &geops;                                                  \
758   pre##_gcminit(&enc->ctx, &key->key, n, nsz);                          \
759   return (&enc->e);                                                     \
760 }                                                                       \
761                                                                         \
762 static gaead_dec *gkdec(const gaead_key *k, const void *n, size_t nsz,  \
763                         size_t hsz, size_t csz, size_t tsz)             \
764 {                                                                       \
765   gkctx *key = (gkctx *)k;                                              \
766   gdctx *dec = S_CREATE(gdctx);                                         \
767                                                                         \
768   dec->d.ops = &gdops;                                                  \
769   pre##_gcminit(&dec->ctx, &key->key, n, nsz);                          \
770   return (&dec->d);                                                     \
771 }                                                                       \
772                                                                         \
773 static void gkdestroy(gaead_key *k)                                     \
774   { gkctx *key = (gkctx *)k; BURN(*key); S_DESTROY(key); }              \
775                                                                         \
776 static const gaead_keyops gkops =                                       \
777   { &pre##_gcm, gkaad, gkenc, gkdec, gkdestroy };                       \
778                                                                         \
779 static gaead_key *gckey(const void *k, size_t ksz)                      \
780 {                                                                       \
781   gkctx *key = S_CREATE(gkctx);                                         \
782   key->k.ops = &gkops;                                                  \
783   pre##_gcmsetkey(&key->key, k, ksz);                                   \
784   return (&key->k);                                                     \
785 }                                                                       \
786                                                                         \
787 const gcaead pre##_gcm = {                                              \
788   name "-gcm",                                                          \
789   pre##_keysz, pre##_gcmnoncesz, pre##_gcmtagsz,                        \
790   PRE##_BLKSZ, 0, 0, 0,                                                 \
791   gckey                                                                 \
792 };                                                                      \
793                                                                         \
794 GCM_TESTX(PRE, pre, name, fname)
795
796 /*----- Test rig ----------------------------------------------------------*/
797
798 #define GCM_TEST(PRE, pre) GCM_TESTX(PRE, pre, #pre, #pre)
799
800 /* --- @GCM_TEST@ --- *
801  *
802  * Arguments:   @PRE, pre@ = prefixes for the underlying block cipher
803  *
804  * Use:         Standard test rig for GCM functions.
805  */
806
807 #ifdef TEST_RIG
808
809 #include <stdio.h>
810
811 #include <mLib/dstr.h>
812 #include <mLib/quis.h>
813 #include <mLib/testrig.h>
814
815 #define GCM_TESTX(PRE, pre, name, fname)                                \
816                                                                         \
817 static int gcmverify(dstr *v)                                           \
818 {                                                                       \
819   pre##_gcmkey key;                                                     \
820   pre##_gcmaadctx aad;                                                  \
821   pre##_gcmctx ctx;                                                     \
822   int ok = 1, win;                                                      \
823   int i;                                                                \
824   octet *p;                                                             \
825   int szs[] = { 1, 7, 192, -1, 0 }, *ip;                                \
826   size_t hsz, msz;                                                      \
827   dstr d = DSTR_INIT, t = DSTR_INIT;                                    \
828   buf b;                                                                \
829                                                                         \
830   dstr_ensure(&d, v[4].len > v[3].len ? v[4].len : v[3].len);           \
831   dstr_ensure(&t, v[5].len); t.len = v[5].len;                          \
832                                                                         \
833   pre##_gcmsetkey(&key, v[0].buf, v[0].len);                            \
834                                                                         \
835   for (ip = szs; *ip; ip++) {                                           \
836                                                                         \
837     pre##_gcminit(&ctx, &key, (octet *)v[1].buf, v[1].len);             \
838                                                                         \
839     i = *ip;                                                            \
840     hsz = v[2].len;                                                     \
841     if (i == -1) i = hsz;                                               \
842     if (i > hsz) continue;                                              \
843     p = (octet *)v[2].buf;                                              \
844     pre##_gcmaadinit(&aad, &key);                                       \
845     while (hsz) {                                                       \
846       if (i > hsz) i = hsz;                                             \
847       pre##_gcmaadhash(&aad, p, i);                                     \
848       p += i; hsz -= i;                                                 \
849     }                                                                   \
850                                                                         \
851     buf_init(&b, d.buf, d.sz);                                          \
852     i = *ip;                                                            \
853     msz = v[3].len;                                                     \
854     if (i == -1) i = msz;                                               \
855     if (i > msz) continue;                                              \
856     p = (octet *)v[3].buf;                                              \
857     while (msz) {                                                       \
858       if (i > msz) i = msz;                                             \
859       if (pre##_gcmencrypt(&ctx, p, i, &b)) {                           \
860         puts("!! gcmencrypt reports failure");                          \
861         goto fail_enc;                                                  \
862       }                                                                 \
863       p += i; msz -= i;                                                 \
864     }                                                                   \
865                                                                         \
866     if (pre##_gcmencryptdone(&ctx, &aad, &b, (octet *)t.buf, t.len)) {  \
867       puts("!! gcmencryptdone reports failure");                        \
868       goto fail_enc;                                                    \
869     }                                                                   \
870     d.len = BLEN(&b);                                                   \
871                                                                         \
872     if (d.len != v[4].len ||                                            \
873         memcmp(d.buf, v[4].buf, v[4].len) != 0 ||                       \
874         memcmp(t.buf, v[5].buf, v[5].len) != 0) {                       \
875     fail_enc:                                                           \
876       printf("\nfail encrypt:\n\tstep = %i", *ip);                      \
877       fputs("\n\tkey = ", stdout); type_hex.dump(&v[0], stdout);        \
878       fputs("\n\tnonce = ", stdout); type_hex.dump(&v[1], stdout);      \
879       fputs("\n\theader = ", stdout); type_hex.dump(&v[2], stdout);     \
880       fputs("\n\tmessage = ", stdout); type_hex.dump(&v[3], stdout);    \
881       fputs("\n\texp ct = ", stdout); type_hex.dump(&v[4], stdout);     \
882       fputs("\n\tcalc ct = ", stdout); type_hex.dump(&d, stdout);       \
883       fputs("\n\texp tag = ", stdout); type_hex.dump(&v[5], stdout);    \
884       fputs("\n\tcalc tag = ", stdout); type_hex.dump(&t, stdout);      \
885       putchar('\n');                                                    \
886       ok = 0;                                                           \
887     }                                                                   \
888                                                                         \
889     pre##_gcminit(&ctx, &key, (octet *)v[1].buf, v[1].len);             \
890                                                                         \
891     buf_init(&b, d.buf, d.sz);                                          \
892     i = *ip;                                                            \
893     msz = v[4].len;                                                     \
894     if (i == -1) i = msz;                                               \
895     if (i > msz) continue;                                              \
896     p = (octet *)v[4].buf;                                              \
897     while (msz) {                                                       \
898       if (i > msz) i = msz;                                             \
899       if (pre##_gcmdecrypt(&ctx, p, i, &b)) {                           \
900         puts("!! gcmdecrypt reports failure");                          \
901         win = 0; goto fail_dec;                                         \
902       }                                                                 \
903       p += i; msz -= i;                                                 \
904     }                                                                   \
905                                                                         \
906     win = pre##_gcmdecryptdone(&ctx, &aad, &b,                          \
907                                (octet *)v[5].buf, v[5].len);            \
908     if (win < 0) {                                                      \
909       puts("!! gcmdecryptdone reports failure");                        \
910       goto fail_dec;                                                    \
911     }                                                                   \
912     d.len = BLEN(&b);                                                   \
913                                                                         \
914     if (d.len != v[3].len || !win ||                                    \
915         memcmp(d.buf, v[3].buf, v[3].len) != 0) {                       \
916     fail_dec:                                                           \
917       printf("\nfail decrypt:\n\tstep = %i", *ip);                      \
918       fputs("\n\tkey = ", stdout); type_hex.dump(&v[0], stdout);        \
919       fputs("\n\tnonce = ", stdout); type_hex.dump(&v[1], stdout);      \
920       fputs("\n\theader = ", stdout); type_hex.dump(&v[2], stdout);     \
921       fputs("\n\tciphertext = ", stdout); type_hex.dump(&v[4], stdout); \
922       fputs("\n\texp pt = ", stdout); type_hex.dump(&v[3], stdout);     \
923       fputs("\n\tcalc pt = ", stdout); type_hex.dump(&d, stdout);       \
924       fputs("\n\ttag = ", stdout); type_hex.dump(&v[5], stdout);        \
925       printf("\n\tverify %s", win ? "ok" : "FAILED");                   \
926       putchar('\n');                                                    \
927       ok = 0;                                                           \
928     }                                                                   \
929   }                                                                     \
930                                                                         \
931   dstr_destroy(&d); dstr_destroy(&t);                                   \
932   return (ok);                                                          \
933 }                                                                       \
934                                                                         \
935 static test_chunk aeaddefs[] = {                                        \
936   { name "-gcm", gcmverify,                                             \
937     { &type_hex, &type_hex, &type_hex, &type_hex,                       \
938       &type_hex, &type_hex, 0 } },                                      \
939   { 0, 0, { 0 } }                                                       \
940 };                                                                      \
941                                                                         \
942 int main(int argc, char *argv[])                                        \
943 {                                                                       \
944   ego(argv[0]);                                                         \
945   test_run(argc, argv, aeaddefs, SRCDIR"/t/" fname);                    \
946   return (0);                                                           \
947 }
948
949 #else
950 #  define GCM_TESTX(PRE, pre, name, fname)
951 #endif
952
953 /*----- That's all, folks -------------------------------------------------*/
954
955 #ifdef __cplusplus
956   }
957 #endif
958
959 #endif