chiark / gitweb /
Merge branch '2.4.x' into 2.5.x
[catacomb] / symm / pmac1-def.h
1 /* -*-c-*-
2  *
3  * The PMAC1 message authentication 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_PMAC1_DEF_H
29 #define CATACOMB_PMAC1_DEF_H
30
31 #ifdef __cplusplus
32   extern "C" {
33 #endif
34
35 /*----- Header files ------------------------------------------------------*/
36
37 #include <stddef.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_PARANOIA_H
51 #  include "paranoia.h"
52 #endif
53
54 #ifndef CATACOMB_RSVR_H
55 #  include "rsvr.h"
56 #endif
57
58 /*----- Macros ------------------------------------------------------------*/
59
60 /* --- @PMAC1_DEF@ --- *
61  *
62  * Arguments:   @PRE@, @pre@ = prefixes for the underlying block cipher
63  *
64  * Use:         Creates an implementation for the PMAC1 message-
65  *              authentication mode.
66  */
67
68 #define PMAC1_DEF(PRE, pre) PMAC1_DEFX(PRE, pre, #pre, #pre)
69
70 #define PMAC1_DEFX(PRE, pre, name, fname)                               \
71                                                                         \
72 OCB1_DECL(PRE, pre)                                                     \
73                                                                         \
74 const rsvr_policy pre##_ocb1policy =                                    \
75   { RSVRF_FULL, PRE##_BLKSZ, PRE##_BLKSZ };                             \
76                                                                         \
77 /* --- @pre_ocb1setkey@, @pre_pmac1setkey@ --- *                        \
78  *                                                                      \
79  * Arguments:   @pre_ocb1key *key@ = pointer to OCB1/PMAC1 key block    \
80  *              @ocnst void *k@ = pointer to key material               \
81  *              @size_t ksz@ = size of key material                     \
82  *                                                                      \
83  * Returns:     ---                                                     \
84  *                                                                      \
85  * Use:         Initializes a OCB1/PMAC1 key.  This can be used for     \
86  *              several encryption and/or MAC operations.               \
87  */                                                                     \
88                                                                         \
89 void pre##_ocb1setkey(pre##_ocb1key *key, const void *k, size_t ksz)    \
90 {                                                                       \
91   unsigned i;                                                           \
92                                                                         \
93   pre##_init(&key->ctx, k, ksz);                                        \
94   BLKC_ZERO(PRE, key->lmask[0]);                                        \
95   pre##_eblk(&key->ctx, key->lmask[0], key->lmask[0]);                  \
96   BLKC_BRSHIFT(PRE, IRRED, key->lxinv, key->lmask[0]);                  \
97   for (i = 1; i < OCB_NCALC; i++)                                       \
98     BLKC_BLSHIFT(PRE, IRRED, key->lmask[i], key->lmask[i - 1]);         \
99 }                                                                       \
100 void pre##_pmac1setkey(pre##_pmac1key *key, const void *k, size_t ksz)  \
101   { pre##_ocb1setkey((pre##_ocb1key *)key, k, ksz); }                   \
102                                                                         \
103 /* --- @pre_ocb1aadinit@, @pre_pmac1init --- *                          \
104  *                                                                      \
105  * Arguments:   @pre_ocb1aadctx *aad@ = pointer to context block        \
106  *              @pre_ocb1key *k@ = key block                            \
107  *                                                                      \
108  * Returns:     ---                                                     \
109  *                                                                      \
110  * Use:         Initializes an OCB1 AAD (`additional authenticated      \
111  *              data') or PMAC1 context associated witha a given key.   \
112  *              AAD contexts can be copied and/or reused, saving time   \
113  *              if the AAD for a number of messages has a common        \
114  *              prefix.                                                 \
115  *                                                                      \
116  *              The @key@ doesn't need to be kept around.               \
117  */                                                                     \
118                                                                         \
119 void pre##_ocb1aadinit(pre##_ocb1aadctx *aad, const pre##_ocb1key *k)   \
120 {                                                                       \
121   aad->k = *k;                                                          \
122   aad->off = 0; aad->i = 1;                                             \
123   BLKC_ZERO(PRE, aad->a);                                               \
124   BLKC_ZERO(PRE, aad->o);                                               \
125 }                                                                       \
126 void pre##_pmac1init(pre##_pmac1ctx *ctx, const pre##_pmac1key *k)      \
127   { pre##_ocb1aadinit((pre##_ocb1aadctx *)ctx, (pre##_ocb1key *)k); }   \
128                                                                         \
129 /* --- @pre_ocb1aadhash@, @pre_pmac1hash@ --- *                         \
130  *                                                                      \
131  * Arguments:   @pre_ocb1aadctx *aad@ = pointer to context block        \
132  *              @ocnst void *p@ = pointer to message buffer             \
133  *              @size_t sz@ = size of message buffer                    \
134  *                                                                      \
135  * Returns:     ---                                                     \
136  *                                                                      \
137  * Use:         Hashes some AAD input data.                             \
138  */                                                                     \
139                                                                         \
140 void pre##_ocb1aadhash(pre##_ocb1aadctx *aad, const void *p, size_t sz) \
141 {                                                                       \
142   rsvr_state st;                                                        \
143   uint32 t[PRE##_BLKSZ/4];                                              \
144   const octet *q;                                                       \
145                                                                         \
146   rsvr_setup(&st, &pre##_ocb1policy, aad->b, &aad->off, p, sz);         \
147   RSVR_DO(&st) while ((q = RSVR_NEXT(&st, PRE##_BLKSZ)) != 0) {         \
148     OCB_OFFSET(PRE, aad->o, aad->k.lmask, aad->i++);                    \
149     BLKC_LOAD(PRE, t, q); BLKC_XMOVE(PRE, t, aad->o);                   \
150     pre##_eblk(&aad->k.ctx, t, t);                                      \
151     BLKC_XMOVE(PRE, aad->a, t);                                         \
152   }                                                                     \
153 }                                                                       \
154 void pre##_pmac1hash(pre##_pmac1ctx *ctx, const void *p, size_t sz)     \
155   { pre##_ocb1aadhash((pre##_ocb1aadctx *)ctx, p, sz); }                \
156                                                                         \
157 /* --- @pre_ocb1aadtag@ --- *                                           \
158  *                                                                      \
159  * Arguments:   @const pre_ocb1aadctx *aad@ = pointer to context block  \
160  *              @uint32 *u@ = where to write the tag                    \
161  *                                                                      \
162  * Returns:     ---                                                     \
163  *                                                                      \
164  * Use:         Finishes processing AAD and produces a tag which can be \
165  *              mixed with an OCB1 checksum.  This function is exposed  \
166  *              for internal reasons and is not expected to be          \
167  *              generally useful.                                       \
168  */                                                                     \
169                                                                         \
170 void pre##_ocb1aadtag(const pre##_ocb1aadctx *aad, uint32 *t)           \
171 {                                                                       \
172   octet b[PRE##_BLKSZ];                                                 \
173                                                                         \
174   BLKC_MOVE(PRE, t, aad->a);                                            \
175   if (aad->off == PRE##_BLKSZ) {                                        \
176     BLKC_XLOAD(PRE, t, aad->b);                                         \
177     BLKC_XMOVE(PRE, t, aad->k.lxinv);                                   \
178   } else {                                                              \
179     memcpy(b, aad->b, aad->off); b[aad->off] = 0x80;                    \
180     memset(b + aad->off + 1, 0, PRE##_BLKSZ - aad->off - 1);            \
181     BLKC_XLOAD(PRE, t, b);                                              \
182   }                                                                     \
183   pre##_eblk(&aad->k.ctx, t, t);                                        \
184 }                                                                       \
185                                                                         \
186 /* --- @pre_pmac1done@ --- *                                            \
187  *                                                                      \
188  * Arguments:   @pre_pmac1ctx *ctx@ = pointer to context block          \
189  *              @void *t@ = where to write the tag                      \
190  *                                                                      \
191  * Returns:     ---                                                     \
192  *                                                                      \
193  * Use:         Finishes a MAC operation and produces the tag.  The     \
194  *              context is clobbered and can't be used for anything     \
195  *              useful any more.                                        \
196  */                                                                     \
197                                                                         \
198 void pre##_pmac1done(pre##_pmac1ctx *ctx, void *t)                      \
199 {                                                                       \
200   uint32 u[PRE##_BLKSZ];                                                \
201   pre##_ocb1aadtag((pre##_ocb1aadctx *)ctx, u); BLKC_STORE(PRE, t, u);  \
202 }                                                                       \
203                                                                         \
204 /* --- Generic MAC interface --- */                                     \
205                                                                         \
206 static const gmac_ops gkops;                                            \
207 static const ghash_ops gops;                                            \
208                                                                         \
209 typedef struct gkctx {                                                  \
210   gmac m;                                                               \
211   pre##_pmac1key k;                                                     \
212 } gkctx;                                                                \
213                                                                         \
214 typedef struct gctx {                                                   \
215   ghash h;                                                              \
216   pre##_pmac1ctx c;                                                     \
217   octet buf[PRE##_BLKSZ];                                               \
218 } gctx;                                                                 \
219                                                                         \
220 static ghash *gkinit(gmac *m)                                           \
221 {                                                                       \
222   gkctx *gk = (gkctx *)m;                                               \
223   gctx *g = S_CREATE(gctx);                                             \
224   g->h.ops = &gops;                                                     \
225   pre##_pmac1init(&g->c, &gk->k);                                       \
226   return (&g->h);                                                       \
227 }                                                                       \
228                                                                         \
229 static gmac *gkey(const void *k, size_t sz)                             \
230 {                                                                       \
231   gkctx *gk = S_CREATE(gkctx);                                          \
232   gk->m.ops = &gkops;                                                   \
233   pre##_pmac1setkey(&gk->k, k, sz);                                     \
234   return (&gk->m);                                                      \
235 }                                                                       \
236                                                                         \
237 static void ghhash(ghash *h, const void *p, size_t sz)                  \
238   { gctx *g = (gctx *)h; pre##_pmac1hash(&g->c, p, sz); }               \
239                                                                         \
240 static octet *ghdone(ghash *h, void *buf)                               \
241 {                                                                       \
242   gctx *g = (gctx *)h;                                                  \
243   if (!buf) buf = g->buf;                                               \
244   pre##_pmac1done(&g->c, buf);                                          \
245   return (buf);                                                         \
246 }                                                                       \
247                                                                         \
248 static ghash *ghcopy(ghash *h)                                          \
249 {                                                                       \
250   gctx *g = (gctx *)h;                                                  \
251   gctx *gg = S_CREATE(gctx);                                            \
252   memcpy(gg, g, sizeof(gctx));                                          \
253   return (&gg->h);                                                      \
254 }                                                                       \
255                                                                         \
256 static void ghdestroy(ghash *h)                                         \
257   { gctx *g = (gctx *)h; BURN(*g); S_DESTROY(g); }                      \
258                                                                         \
259 static void gkdestroy(gmac *m)                                          \
260   { gkctx *gk = (gkctx *)m; BURN(*gk); S_DESTROY(gk); }                 \
261                                                                         \
262 static ghash *ghinit(void)                                              \
263 {                                                                       \
264   assert(((void)"Attempt to instantiate an unkeyed MAC", 0));           \
265   return (0);                                                           \
266 }                                                                       \
267                                                                         \
268 const gcmac pre##_pmac1 =                                               \
269   { name "-pmac1", PRE##_BLKSZ, pre##_keysz, gkey };                    \
270 static const gmac_ops gkops = { &pre##_pmac1, gkinit, gkdestroy };      \
271 static const gchash gch = { name "-pmac1", PRE##_BLKSZ, ghinit };       \
272 static const ghash_ops gops =                                           \
273   { &gch, ghhash, ghdone, ghdestroy, ghcopy };                          \
274                                                                         \
275 PMAC1_TESTX(PRE, pre, name, fname)
276
277 #define PMAC1_TEST(PRE, pre) HMAC_TESTX(PRE, pre, #pre, #pre)
278
279 /* --- @PMAC1_TEST@ --- *
280  *
281  * Arguments:   @PRE@, @pre@ = prefixes for the underlying block cipher
282  *
283  * Use:         Standard test rig for PMAC1 functions.
284  */
285
286 #ifdef TEST_RIG
287
288 #include <stdio.h>
289
290 #include <mLib/dstr.h>
291 #include <mLib/quis.h>
292 #include <mLib/testrig.h>
293
294 #define PMAC1_TESTX(PRE, pre, name, fname)                              \
295                                                                         \
296 static int macverify(dstr *v)                                           \
297 {                                                                       \
298   pre##_pmac1ctx cctx;                                                  \
299   pre##_pmac1key ckey;                                                  \
300   int ok = 1;                                                           \
301   int i;                                                                \
302   octet *p;                                                             \
303   int szs[] = { 1, 7, 192, -1, 0 }, *ip;                                \
304   size_t csz;                                                           \
305   dstr d;                                                               \
306                                                                         \
307   dstr_create(&d);                                                      \
308   dstr_ensure(&d, PRE##_BLKSZ);                                         \
309   d.len = PRE##_BLKSZ;                                                  \
310                                                                         \
311   pre##_pmac1setkey(&ckey, v[0].buf, v[0].len);                         \
312                                                                         \
313   for (ip = szs; *ip; ip++) {                                           \
314     i = *ip;                                                            \
315     csz = v[1].len;                                                     \
316     if (i == -1)                                                        \
317       i = csz;                                                          \
318     if (i > csz)                                                        \
319       continue;                                                         \
320     p = (octet *)v[1].buf;                                              \
321     pre##_pmac1init(&cctx, &ckey);                                      \
322     while (csz) {                                                       \
323       if (i > csz)                                                      \
324         i = csz;                                                        \
325       pre##_pmac1hash(&cctx, p, i);                                     \
326       p += i;                                                           \
327       csz -= i;                                                         \
328     }                                                                   \
329     pre##_pmac1done(&cctx, d.buf);                                      \
330     if (memcmp(d.buf, v[2].buf, PRE##_BLKSZ) != 0) {                    \
331       printf("\nfail:\n\tstep = %i\n\tkey = ", *ip);                    \
332       type_hex.dump(&v[0], stdout);                                     \
333       fputs("\n\tinput = ", stdout);                                    \
334       type_hex.dump(&v[1], stdout);                                     \
335       fputs("\n\texpected = ", stdout);                                 \
336       type_hex.dump(&v[2], stdout);                                     \
337       fputs("\n\tcomputed = ", stdout);                                 \
338       type_hex.dump(&d, stdout);                                        \
339       putchar('\n');                                                    \
340       ok = 0;                                                           \
341     }                                                                   \
342   }                                                                     \
343                                                                         \
344   dstr_destroy(&d);                                                     \
345   return (ok);                                                          \
346 }                                                                       \
347                                                                         \
348 static test_chunk macdefs[] = {                                         \
349   { name "-pmac1", macverify,                                           \
350     { &type_hex, &type_hex, &type_hex, 0 } },                           \
351   { 0, 0, { 0 } }                                                       \
352 };                                                                      \
353                                                                         \
354 int main(int argc, char *argv[])                                        \
355 {                                                                       \
356   ego(argv[0]);                                                         \
357   test_run(argc, argv, macdefs, SRCDIR"/t/" fname);                     \
358   return (0);                                                           \
359 }
360
361 #else
362 #  define PMAC1_TESTX(PRE, pre, name, fname)
363 #endif
364
365 /*----- That's all, folks -------------------------------------------------*/
366
367 #ifdef __cplusplus
368   }
369 #endif
370
371 #endif