Home | History | Annotate | Line # | Download | only in aes
      1  1.6  jmcneill /*	$NetBSD: aes_ccm.c,v 1.6 2021/10/17 14:45:45 jmcneill Exp $	*/
      2  1.1  riastrad 
      3  1.1  riastrad /*-
      4  1.1  riastrad  * Copyright (c) 2020 The NetBSD Foundation, Inc.
      5  1.1  riastrad  * All rights reserved.
      6  1.1  riastrad  *
      7  1.1  riastrad  * Redistribution and use in source and binary forms, with or without
      8  1.1  riastrad  * modification, are permitted provided that the following conditions
      9  1.1  riastrad  * are met:
     10  1.1  riastrad  * 1. Redistributions of source code must retain the above copyright
     11  1.1  riastrad  *    notice, this list of conditions and the following disclaimer.
     12  1.1  riastrad  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1  riastrad  *    notice, this list of conditions and the following disclaimer in the
     14  1.1  riastrad  *    documentation and/or other materials provided with the distribution.
     15  1.1  riastrad  *
     16  1.1  riastrad  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17  1.1  riastrad  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18  1.1  riastrad  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  1.1  riastrad  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20  1.1  riastrad  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  1.1  riastrad  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  1.1  riastrad  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23  1.1  riastrad  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24  1.1  riastrad  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25  1.1  riastrad  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26  1.1  riastrad  * POSSIBILITY OF SUCH DAMAGE.
     27  1.1  riastrad  */
     28  1.1  riastrad 
     29  1.1  riastrad /*
     30  1.1  riastrad  * AES-CCM, as defined in:
     31  1.1  riastrad  *
     32  1.1  riastrad  *	D. Whiting, R. Housley, and N. Ferguson, `Counter with CBC-MAC
     33  1.1  riastrad  *	(CCM)', IETF RFC 3610, September 2003.
     34  1.1  riastrad  *	https://tools.ietf.org/html/rfc3610
     35  1.1  riastrad  */
     36  1.1  riastrad 
     37  1.1  riastrad #include <sys/cdefs.h>
     38  1.6  jmcneill __KERNEL_RCSID(1, "$NetBSD: aes_ccm.c,v 1.6 2021/10/17 14:45:45 jmcneill Exp $");
     39  1.1  riastrad 
     40  1.1  riastrad #include <sys/types.h>
     41  1.1  riastrad #include <sys/param.h>
     42  1.1  riastrad #include <sys/systm.h>
     43  1.1  riastrad 
     44  1.1  riastrad #include <lib/libkern/libkern.h>
     45  1.1  riastrad 
     46  1.1  riastrad #include <crypto/aes/aes.h>
     47  1.1  riastrad #include <crypto/aes/aes_ccm.h>
     48  1.2  riastrad #include <crypto/aes/aes_impl.h>
     49  1.1  riastrad 
     50  1.1  riastrad static inline void
     51  1.1  riastrad xor(uint8_t *x, const uint8_t *a, const uint8_t *b, size_t n)
     52  1.1  riastrad {
     53  1.1  riastrad 
     54  1.1  riastrad 	while (n --> 0)
     55  1.1  riastrad 		*x++ = *a++ ^ *b++;
     56  1.1  riastrad }
     57  1.1  riastrad 
     58  1.1  riastrad /* RFC 3610, 2.2 Authentication */
     59  1.1  riastrad #define	CCM_AFLAGS_ADATA	__BIT(6)
     60  1.1  riastrad #define	CCM_AFLAGS_M		__BITS(5,3)
     61  1.1  riastrad #define	CCM_AFLAGS_L		__BITS(2,0)
     62  1.1  riastrad 
     63  1.1  riastrad /* RFC 3610, 2.3 Encryption */
     64  1.1  riastrad #define	CCM_EFLAGS_L		__BITS(2,0)
     65  1.1  riastrad 
     66  1.1  riastrad static void
     67  1.1  riastrad aes_ccm_inc(struct aes_ccm *C)
     68  1.1  riastrad {
     69  1.4  riastrad 	uint8_t *ctr = C->authctr + 16;
     70  1.1  riastrad 
     71  1.1  riastrad 	KASSERT(C->L == 2);
     72  1.4  riastrad 	if (++ctr[15] == 0 && ++ctr[14] == 0)
     73  1.1  riastrad 		panic("AES-CCM overflow");
     74  1.1  riastrad }
     75  1.1  riastrad 
     76  1.1  riastrad static void
     77  1.1  riastrad aes_ccm_zero_ctr(struct aes_ccm *C)
     78  1.1  riastrad {
     79  1.4  riastrad 	uint8_t *ctr = C->authctr + 16;
     80  1.1  riastrad 
     81  1.1  riastrad 	KASSERT(C->L == 2);
     82  1.4  riastrad 	ctr[14] = ctr[15] = 0;
     83  1.1  riastrad }
     84  1.1  riastrad 
     85  1.1  riastrad void
     86  1.1  riastrad aes_ccm_init(struct aes_ccm *C, unsigned nr, const struct aesenc *enc,
     87  1.1  riastrad     unsigned L, unsigned M,
     88  1.1  riastrad     const uint8_t *nonce, unsigned noncelen, const void *ad, size_t adlen,
     89  1.1  riastrad     size_t mlen)
     90  1.1  riastrad {
     91  1.1  riastrad 	const uint8_t *adp = ad;
     92  1.4  riastrad 	uint8_t *auth = C->authctr;
     93  1.4  riastrad 	uint8_t *ctr = C->authctr + 16;
     94  1.1  riastrad 	unsigned i;
     95  1.1  riastrad 
     96  1.1  riastrad 	KASSERT(L == 2);
     97  1.1  riastrad 	KASSERT(M % 2 == 0);
     98  1.1  riastrad 	KASSERT(M >= 4);
     99  1.1  riastrad 	KASSERT(M <= 16);
    100  1.1  riastrad 	KASSERT(noncelen == 15 - L);
    101  1.1  riastrad 
    102  1.1  riastrad 	C->enc = enc;
    103  1.1  riastrad 	C->nr = nr;
    104  1.1  riastrad 	C->L = L;
    105  1.1  riastrad 	C->M = M;
    106  1.1  riastrad 	C->mlen = C->mleft = mlen;
    107  1.1  riastrad 
    108  1.1  riastrad 	/* Encode B0, the initial authenticated data block.  */
    109  1.4  riastrad 	auth[0] = __SHIFTIN(adlen == 0 ? 0 : 1, CCM_AFLAGS_ADATA);
    110  1.4  riastrad 	auth[0] |= __SHIFTIN((M - 2)/2, CCM_AFLAGS_M);
    111  1.4  riastrad 	auth[0] |= __SHIFTIN(L - 1, CCM_AFLAGS_L);
    112  1.4  riastrad 	memcpy(auth + 1, nonce, noncelen);
    113  1.1  riastrad 	for (i = 0; i < L; i++, mlen >>= 8) {
    114  1.1  riastrad 		KASSERT(i < 16 - 1 - noncelen);
    115  1.4  riastrad 		auth[16 - i - 1] = mlen & 0xff;
    116  1.1  riastrad 	}
    117  1.4  riastrad 	aes_enc(enc, auth, auth, C->nr);
    118  1.1  riastrad 
    119  1.1  riastrad 	/* Process additional authenticated data, if any.  */
    120  1.1  riastrad 	if (adlen) {
    121  1.1  riastrad 		/* Encode the length according to the table on p. 4.  */
    122  1.1  riastrad 		if (adlen < 0xff00) {
    123  1.4  riastrad 			auth[0] ^= adlen >> 8;
    124  1.4  riastrad 			auth[1] ^= adlen;
    125  1.1  riastrad 			i = 2;
    126  1.1  riastrad 		} else if (adlen < 0xffffffff) {
    127  1.4  riastrad 			auth[0] ^= 0xff;
    128  1.4  riastrad 			auth[1] ^= 0xfe;
    129  1.4  riastrad 			auth[2] ^= adlen >> 24;
    130  1.4  riastrad 			auth[3] ^= adlen >> 16;
    131  1.4  riastrad 			auth[4] ^= adlen >> 8;
    132  1.4  riastrad 			auth[5] ^= adlen;
    133  1.1  riastrad 			i = 6;
    134  1.1  riastrad #if SIZE_MAX > 0xffffffffU
    135  1.1  riastrad 		} else {
    136  1.1  riastrad 			CTASSERT(SIZE_MAX <= 0xffffffffffffffff);
    137  1.4  riastrad 			auth[0] ^= 0xff;
    138  1.4  riastrad 			auth[1] ^= 0xff;
    139  1.4  riastrad 			auth[2] ^= adlen >> 56;
    140  1.4  riastrad 			auth[3] ^= adlen >> 48;
    141  1.4  riastrad 			auth[4] ^= adlen >> 40;
    142  1.4  riastrad 			auth[5] ^= adlen >> 32;
    143  1.4  riastrad 			auth[6] ^= adlen >> 24;
    144  1.4  riastrad 			auth[7] ^= adlen >> 16;
    145  1.4  riastrad 			auth[8] ^= adlen >> 8;
    146  1.4  riastrad 			auth[9] ^= adlen;
    147  1.1  riastrad 			i = 10;
    148  1.1  riastrad #endif
    149  1.1  riastrad 		}
    150  1.1  riastrad 
    151  1.1  riastrad 		/* Fill out the partial block if we can, and encrypt.  */
    152  1.4  riastrad 		xor(auth + i, auth + i, adp, MIN(adlen, 16 - i));
    153  1.1  riastrad 		adp += MIN(adlen, 16 - i);
    154  1.1  riastrad 		adlen -= MIN(adlen, 16 - i);
    155  1.4  riastrad 		aes_enc(enc, auth, auth, C->nr);
    156  1.1  riastrad 
    157  1.1  riastrad 		/* If there was anything more, process 16 bytes at a time.  */
    158  1.2  riastrad 		if (adlen - (adlen % 16)) {
    159  1.2  riastrad 			aes_cbcmac_update1(enc, adp, adlen - (adlen % 16),
    160  1.4  riastrad 			    auth, C->nr);
    161  1.2  riastrad 			adlen %= 16;
    162  1.1  riastrad 		}
    163  1.1  riastrad 
    164  1.1  riastrad 		/*
    165  1.1  riastrad 		 * If there's anything at the end, enter it in (padded
    166  1.1  riastrad 		 * with zeros, which is a no-op) and process it.
    167  1.1  riastrad 		 */
    168  1.1  riastrad 		if (adlen) {
    169  1.4  riastrad 			xor(auth, auth, adp, adlen);
    170  1.4  riastrad 			aes_enc(enc, auth, auth, C->nr);
    171  1.1  riastrad 		}
    172  1.1  riastrad 	}
    173  1.1  riastrad 
    174  1.1  riastrad 	/* Set up the AES input for AES-CTR encryption.  */
    175  1.4  riastrad 	ctr[0] = __SHIFTIN(L - 1, CCM_EFLAGS_L);
    176  1.4  riastrad 	memcpy(ctr + 1, nonce, noncelen);
    177  1.4  riastrad 	memset(ctr + 1 + noncelen, 0, 16 - 1 - noncelen);
    178  1.1  riastrad 
    179  1.1  riastrad 	/* Start on a block boundary.  */
    180  1.1  riastrad 	C->i = 0;
    181  1.1  riastrad }
    182  1.1  riastrad 
    183  1.1  riastrad void
    184  1.1  riastrad aes_ccm_enc(struct aes_ccm *C, const void *in, void *out, size_t nbytes)
    185  1.1  riastrad {
    186  1.4  riastrad 	uint8_t *auth = C->authctr;
    187  1.4  riastrad 	uint8_t *ctr = C->authctr + 16;
    188  1.1  riastrad 	const uint8_t *p = in;
    189  1.1  riastrad 	uint8_t *q = out;
    190  1.1  riastrad 
    191  1.1  riastrad 	KASSERTMSG(C->i != ~0u,
    192  1.1  riastrad 	    "%s not allowed after message complete", __func__);
    193  1.1  riastrad 	KASSERTMSG(nbytes <= C->mleft,
    194  1.1  riastrad 	    "message too long: promised %zu bytes, processing >=%zu",
    195  1.1  riastrad 	    C->mlen, C->mlen - C->mleft + nbytes);
    196  1.1  riastrad 	C->mleft -= nbytes;
    197  1.1  riastrad 
    198  1.1  riastrad 	/* Finish a partial block if it was already started.  */
    199  1.1  riastrad 	if (C->i) {
    200  1.1  riastrad 		unsigned m = MIN(16 - C->i, nbytes);
    201  1.1  riastrad 
    202  1.4  riastrad 		xor(auth + C->i, auth + C->i, p, m);
    203  1.1  riastrad 		xor(q, C->out + C->i, p, m);
    204  1.1  riastrad 		C->i += m;
    205  1.1  riastrad 		p += m;
    206  1.1  riastrad 		q += m;
    207  1.1  riastrad 		nbytes -= m;
    208  1.1  riastrad 
    209  1.1  riastrad 		if (C->i == 16) {
    210  1.1  riastrad 			/* Finished a block; authenticate it.  */
    211  1.4  riastrad 			aes_enc(C->enc, auth, auth, C->nr);
    212  1.1  riastrad 			C->i = 0;
    213  1.1  riastrad 		} else {
    214  1.1  riastrad 			/* Didn't finish block, must be done with input. */
    215  1.1  riastrad 			KASSERT(nbytes == 0);
    216  1.1  riastrad 			return;
    217  1.1  riastrad 		}
    218  1.1  riastrad 	}
    219  1.1  riastrad 
    220  1.1  riastrad 	/* Process 16 bytes at a time.  */
    221  1.2  riastrad 	if (nbytes - (nbytes % 16)) {
    222  1.4  riastrad 		aes_ccm_enc1(C->enc, p, q, nbytes - (nbytes % 16), auth,
    223  1.2  riastrad 		    C->nr);
    224  1.2  riastrad 		p += nbytes - (nbytes % 16);
    225  1.2  riastrad 		q += nbytes - (nbytes % 16);
    226  1.2  riastrad 		nbytes %= 16;
    227  1.1  riastrad 	}
    228  1.1  riastrad 
    229  1.1  riastrad 	/* Incorporate any <16-byte unit as a partial block.  */
    230  1.1  riastrad 	if (nbytes) {
    231  1.1  riastrad 		/* authenticate */
    232  1.4  riastrad 		xor(auth, auth, p, nbytes);
    233  1.1  riastrad 
    234  1.1  riastrad 		/* encrypt */
    235  1.1  riastrad 		aes_ccm_inc(C);
    236  1.4  riastrad 		aes_enc(C->enc, ctr, C->out, C->nr);
    237  1.1  riastrad 		xor(q, C->out, p, nbytes);
    238  1.1  riastrad 
    239  1.1  riastrad 		C->i = nbytes;
    240  1.1  riastrad 	}
    241  1.1  riastrad }
    242  1.1  riastrad 
    243  1.1  riastrad void
    244  1.1  riastrad aes_ccm_dec(struct aes_ccm *C, const void *in, void *out, size_t nbytes)
    245  1.1  riastrad {
    246  1.4  riastrad 	uint8_t *auth = C->authctr;
    247  1.4  riastrad 	uint8_t *ctr = C->authctr + 16;
    248  1.1  riastrad 	const uint8_t *p = in;
    249  1.1  riastrad 	uint8_t *q = out;
    250  1.1  riastrad 
    251  1.1  riastrad 	KASSERTMSG(C->i != ~0u,
    252  1.1  riastrad 	    "%s not allowed after message complete", __func__);
    253  1.1  riastrad 	KASSERTMSG(nbytes <= C->mleft,
    254  1.1  riastrad 	    "message too long: promised %zu bytes, processing >=%zu",
    255  1.1  riastrad 	    C->mlen, C->mlen - C->mleft + nbytes);
    256  1.1  riastrad 	C->mleft -= nbytes;
    257  1.1  riastrad 
    258  1.1  riastrad 	/* Finish a partial block if it was already started.  */
    259  1.1  riastrad 	if (C->i) {
    260  1.1  riastrad 		unsigned m = MIN(16 - C->i, nbytes);
    261  1.1  riastrad 
    262  1.1  riastrad 		xor(q, C->out + C->i, p, m);
    263  1.4  riastrad 		xor(auth + C->i, auth + C->i, q, m);
    264  1.1  riastrad 		C->i += m;
    265  1.1  riastrad 		p += m;
    266  1.1  riastrad 		q += m;
    267  1.1  riastrad 		nbytes -= m;
    268  1.1  riastrad 
    269  1.1  riastrad 		if (C->i == 16) {
    270  1.1  riastrad 			/* Finished a block; authenticate it.  */
    271  1.4  riastrad 			aes_enc(C->enc, auth, auth, C->nr);
    272  1.1  riastrad 			C->i = 0;
    273  1.1  riastrad 		} else {
    274  1.1  riastrad 			/* Didn't finish block, must be done with input. */
    275  1.1  riastrad 			KASSERT(nbytes == 0);
    276  1.1  riastrad 			return;
    277  1.1  riastrad 		}
    278  1.1  riastrad 	}
    279  1.1  riastrad 
    280  1.1  riastrad 	/* Process 16 bytes at a time.  */
    281  1.2  riastrad 	if (nbytes - (nbytes % 16)) {
    282  1.4  riastrad 		aes_ccm_dec1(C->enc, p, q, nbytes - (nbytes % 16), auth,
    283  1.2  riastrad 		    C->nr);
    284  1.2  riastrad 		p += nbytes - (nbytes % 16);
    285  1.2  riastrad 		q += nbytes - (nbytes % 16);
    286  1.2  riastrad 		nbytes %= 16;
    287  1.1  riastrad 	}
    288  1.1  riastrad 
    289  1.1  riastrad 	/* Incorporate any <16-byte unit as a partial block.  */
    290  1.1  riastrad 	if (nbytes) {
    291  1.1  riastrad 		/* decrypt */
    292  1.1  riastrad 		aes_ccm_inc(C);
    293  1.4  riastrad 		aes_enc(C->enc, ctr, C->out, C->nr);
    294  1.1  riastrad 		xor(q, C->out, p, nbytes);
    295  1.1  riastrad 
    296  1.1  riastrad 		/* authenticate */
    297  1.4  riastrad 		xor(auth, auth, q, nbytes);
    298  1.1  riastrad 
    299  1.1  riastrad 		C->i = nbytes;
    300  1.1  riastrad 	}
    301  1.1  riastrad }
    302  1.1  riastrad 
    303  1.1  riastrad void
    304  1.5       rin #if defined(__m68k__) && __GNUC_PREREQ__(8, 0)
    305  1.5       rin __attribute__((__optimize__("O0")))
    306  1.5       rin #endif
    307  1.1  riastrad aes_ccm_tag(struct aes_ccm *C, void *out)
    308  1.1  riastrad {
    309  1.4  riastrad 	uint8_t *auth = C->authctr;
    310  1.4  riastrad 	const uint8_t *ctr = C->authctr + 16;
    311  1.1  riastrad 
    312  1.1  riastrad 	KASSERTMSG(C->mleft == 0,
    313  1.1  riastrad 	    "message too short: promised %zu bytes, processed %zu",
    314  1.1  riastrad 	    C->mlen, C->mlen - C->mleft);
    315  1.1  riastrad 
    316  1.1  riastrad 	/* Zero-pad and munch up a partial block, if any.  */
    317  1.1  riastrad 	if (C->i)
    318  1.4  riastrad 		aes_enc(C->enc, auth, auth, C->nr);
    319  1.1  riastrad 
    320  1.1  riastrad 	/* Zero the counter and generate a pad for the tag.  */
    321  1.1  riastrad 	aes_ccm_zero_ctr(C);
    322  1.4  riastrad 	aes_enc(C->enc, ctr, C->out, C->nr);
    323  1.1  riastrad 
    324  1.1  riastrad 	/* Copy out as many bytes as requested.  */
    325  1.4  riastrad 	xor(out, C->out, auth, C->M);
    326  1.1  riastrad 
    327  1.1  riastrad 	C->i = ~0u;		/* paranoia: prevent future misuse */
    328  1.1  riastrad }
    329  1.1  riastrad 
    330  1.1  riastrad int
    331  1.1  riastrad aes_ccm_verify(struct aes_ccm *C, const void *tag)
    332  1.1  riastrad {
    333  1.1  riastrad 	uint8_t expected[16];
    334  1.1  riastrad 	int result;
    335  1.1  riastrad 
    336  1.1  riastrad 	aes_ccm_tag(C, expected);
    337  1.1  riastrad 	result = consttime_memequal(tag, expected, C->M);
    338  1.1  riastrad 	explicit_memset(expected, 0, sizeof expected);
    339  1.1  riastrad 
    340  1.1  riastrad 	return result;
    341  1.1  riastrad }
    342  1.1  riastrad 
    343  1.1  riastrad /* RFC 3610, 8 */
    344  1.1  riastrad 
    345  1.1  riastrad static const uint8_t keyC[16] = {
    346  1.1  riastrad 	0xc0,0xc1,0xc2,0xc3, 0xc4,0xc5,0xc6,0xc7,
    347  1.1  riastrad 	0xc8,0xc9,0xca,0xcb, 0xcc,0xcd,0xce,0xcf,
    348  1.1  riastrad };
    349  1.1  riastrad 
    350  1.1  riastrad static const uint8_t keyD[16] = {
    351  1.1  riastrad 	0xd7,0x82,0x8d,0x13, 0xb2,0xb0,0xbd,0xc3,
    352  1.1  riastrad 	0x25,0xa7,0x62,0x36, 0xdf,0x93,0xcc,0x6b,
    353  1.1  riastrad };
    354  1.1  riastrad 
    355  1.1  riastrad static const uint8_t ptxt_seq[] = {
    356  1.1  riastrad 	0x00,0x01,0x02,0x03, 0x04,0x05,0x06,0x07,
    357  1.1  riastrad 	0x08,0x09,0x0a,0x0b, 0x0c,0x0d,0x0e,0x0f,
    358  1.1  riastrad 	0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17,
    359  1.1  riastrad 	0x18,0x19,0x1a,0x1b, 0x1c,0x1d,0x1e,0x1f,
    360  1.1  riastrad 	0x20,
    361  1.1  riastrad };
    362  1.1  riastrad 
    363  1.1  riastrad static const uint8_t ptxt_rand[] = {
    364  1.1  riastrad 	0x6e,0x37,0xa6,0xef, 0x54,0x6d,0x95,0x5d,
    365  1.1  riastrad 	0x34,0xab,0x60,0x59, 0xab,0xf2,0x1c,0x0b,
    366  1.1  riastrad 	0x02,0xfe,0xb8,0x8f, 0x85,0x6d,0xf4,0xa3,
    367  1.1  riastrad 	0x73,0x81,0xbc,0xe3, 0xcc,0x12,0x85,0x17,
    368  1.1  riastrad 	0xd4,
    369  1.1  riastrad };
    370  1.1  riastrad 
    371  1.1  riastrad static const struct {
    372  1.1  riastrad 	const uint8_t *key;
    373  1.1  riastrad 	size_t noncelen;
    374  1.1  riastrad 	const uint8_t nonce[13];
    375  1.1  riastrad 	size_t adlen;
    376  1.1  riastrad 	const uint8_t *ad;
    377  1.1  riastrad 	size_t mlen;
    378  1.1  riastrad 	const uint8_t *ptxt;
    379  1.1  riastrad 	unsigned M;
    380  1.1  riastrad 	const uint8_t tag[16];
    381  1.1  riastrad 	const uint8_t *ctxt;
    382  1.1  riastrad } T[] = {
    383  1.1  riastrad 	[0] = {		/* Packet Vector #1, p. 11 */
    384  1.1  riastrad 		.key = keyC,
    385  1.1  riastrad 		.nonce = {
    386  1.1  riastrad 			0x00,0x00,0x00,0x03, 0x02,0x01,0x00,0xa0,
    387  1.1  riastrad 			0xa1,0xa2,0xa3,0xa4, 0xa5,
    388  1.1  riastrad 		},
    389  1.1  riastrad 		.adlen = 8,
    390  1.1  riastrad 		.ad = ptxt_seq,
    391  1.1  riastrad 		.mlen = 23,
    392  1.1  riastrad 		.ptxt = ptxt_seq + 8,
    393  1.1  riastrad 		.M = 8,
    394  1.1  riastrad 		.tag = {0x17,0xe8,0xd1,0x2c,0xfd, 0xf9,0x26,0xe0},
    395  1.1  riastrad 		.ctxt = (const uint8_t[23]) {
    396  1.1  riastrad 			0x58,0x8c,0x97,0x9a, 0x61,0xc6,0x63,0xd2,
    397  1.1  riastrad 			0xf0,0x66,0xd0,0xc2, 0xc0,0xf9,0x89,0x80,
    398  1.1  riastrad 			0x6d,0x5f,0x6b,0x61, 0xda,0xc3,0x84,
    399  1.1  riastrad 		},
    400  1.1  riastrad 	},
    401  1.1  riastrad 	[1] = {			/* Packet Vector #2, p. 11 */
    402  1.1  riastrad 		.key = keyC,
    403  1.1  riastrad 		.nonce = {
    404  1.1  riastrad 			0x00,0x00,0x00,0x04, 0x03,0x02,0x01,0xa0,
    405  1.1  riastrad 			0xa1,0xa2,0xa3,0xa4, 0xa5,
    406  1.1  riastrad 		},
    407  1.1  riastrad 		.adlen = 8,
    408  1.1  riastrad 		.ad = ptxt_seq,
    409  1.1  riastrad 		.mlen = 24,
    410  1.1  riastrad 		.ptxt = ptxt_seq + 8,
    411  1.1  riastrad 		.M = 8,
    412  1.1  riastrad 		.tag = {0xa0,0x91,0xd5,0x6e, 0x10,0x40,0x09,0x16},
    413  1.1  riastrad 		.ctxt = (const uint8_t[24]) {
    414  1.1  riastrad 			0x72,0xc9,0x1a,0x36, 0xe1,0x35,0xf8,0xcf,
    415  1.1  riastrad 			0x29,0x1c,0xa8,0x94, 0x08,0x5c,0x87,0xe3,
    416  1.1  riastrad 			0xcc,0x15,0xc4,0x39, 0xc9,0xe4,0x3a,0x3b,
    417  1.1  riastrad 		},
    418  1.1  riastrad 	},
    419  1.1  riastrad 	[2] = {			/* Packet Vector #3, p. 12 */
    420  1.1  riastrad 		.key = keyC,
    421  1.1  riastrad 		.nonce = {
    422  1.1  riastrad 			0x00,0x00,0x00,0x05, 0x04,0x03,0x02,0xa0,
    423  1.1  riastrad 			0xa1,0xa2,0xa3,0xa4, 0xa5,
    424  1.1  riastrad 		},
    425  1.1  riastrad 		.adlen = 8,
    426  1.1  riastrad 		.ad = ptxt_seq,
    427  1.1  riastrad 		.mlen = 25,
    428  1.1  riastrad 		.ptxt = ptxt_seq + 8,
    429  1.1  riastrad 		.M = 8,
    430  1.1  riastrad 		.tag = {0x4a,0xda,0xa7,0x6f, 0xbd,0x9f,0xb0,0xc5},
    431  1.1  riastrad 		.ctxt = (const uint8_t[25]) {
    432  1.1  riastrad 			0x51,0xb1,0xe5,0xf4, 0x4a,0x19,0x7d,0x1d,
    433  1.1  riastrad 			0xa4,0x6b,0x0f,0x8e, 0x2d,0x28,0x2a,0xe8,
    434  1.1  riastrad 			0x71,0xe8,0x38,0xbb, 0x64,0xda,0x85,0x96,
    435  1.1  riastrad 			0x57,
    436  1.1  riastrad 		},
    437  1.1  riastrad 	},
    438  1.1  riastrad 	[3] = {			/* Packet Vector #4, p. 13 */
    439  1.1  riastrad 		.key = keyC,
    440  1.1  riastrad 		.nonce = {
    441  1.1  riastrad 			0x00,0x00,0x00,0x06, 0x05,0x04,0x03,0xa0,
    442  1.1  riastrad 			0xa1,0xa2,0xa3,0xa4, 0xa5,
    443  1.1  riastrad 		},
    444  1.1  riastrad 		.adlen = 12,
    445  1.1  riastrad 		.ad = ptxt_seq,
    446  1.1  riastrad 		.mlen = 19,
    447  1.1  riastrad 		.ptxt = ptxt_seq + 12,
    448  1.1  riastrad 		.M = 8,
    449  1.1  riastrad 		.tag = {0x96,0xc8,0x61,0xb9, 0xc9,0xe6,0x1e,0xf1},
    450  1.1  riastrad 		.ctxt = (const uint8_t[19]) {
    451  1.1  riastrad 			0xa2,0x8c,0x68,0x65, 0x93,0x9a,0x9a,0x79,
    452  1.1  riastrad 			0xfa,0xaa,0x5c,0x4c, 0x2a,0x9d,0x4a,0x91,
    453  1.1  riastrad 			0xcd,0xac,0x8c,
    454  1.1  riastrad 		},
    455  1.1  riastrad 	},
    456  1.1  riastrad 	[4] = {			/* Packet Vector #5, p. 13 */
    457  1.1  riastrad 		.key = keyC,
    458  1.1  riastrad 		.nonce = {
    459  1.1  riastrad 			0x00,0x00,0x00,0x07, 0x06,0x05,0x04,0xa0,
    460  1.1  riastrad 			0xa1,0xa2,0xa3,0xa4, 0xa5,
    461  1.1  riastrad 		},
    462  1.1  riastrad 		.adlen = 12,
    463  1.1  riastrad 		.ad = ptxt_seq,
    464  1.1  riastrad 		.mlen = 20,
    465  1.1  riastrad 		.ptxt = ptxt_seq + 12,
    466  1.1  riastrad 		.M = 8,
    467  1.1  riastrad 		.tag = {0x51,0xe8,0x3f,0x07, 0x7d,0x9c,0x2d,0x93},
    468  1.1  riastrad 		.ctxt = (const uint8_t[20]) {
    469  1.1  riastrad 			0xdc,0xf1,0xfb,0x7b, 0x5d,0x9e,0x23,0xfb,
    470  1.1  riastrad 			0x9d,0x4e,0x13,0x12, 0x53,0x65,0x8a,0xd8,
    471  1.1  riastrad 			0x6e,0xbd,0xca,0x3e,
    472  1.1  riastrad 		},
    473  1.1  riastrad 	},
    474  1.1  riastrad 	[5] = {			/* Packet Vector #6, p. 13 */
    475  1.1  riastrad 		.key = keyC,
    476  1.1  riastrad 		.nonce = {
    477  1.1  riastrad 			0x00,0x00,0x00,0x08, 0x07,0x06,0x05,0xa0,
    478  1.1  riastrad 			0xa1,0xa2,0xa3,0xa4, 0xa5,
    479  1.1  riastrad 		},
    480  1.1  riastrad 		.adlen = 12,
    481  1.1  riastrad 		.ad = ptxt_seq,
    482  1.1  riastrad 		.mlen = 21,
    483  1.1  riastrad 		.ptxt = ptxt_seq + 12,
    484  1.1  riastrad 		.M = 8,
    485  1.1  riastrad 		.tag = {0x40,0x5a,0x04,0x43, 0xac,0x91,0xcb,0x94},
    486  1.1  riastrad 		.ctxt = (const uint8_t[21]) {
    487  1.1  riastrad 			0x6f,0xc1,0xb0,0x11, 0xf0,0x06,0x56,0x8b,
    488  1.1  riastrad 			0x51,0x71,0xa4,0x2d, 0x95,0x3d,0x46,0x9b,
    489  1.1  riastrad 			0x25,0x70,0xa4,0xbd, 0x87,
    490  1.1  riastrad 		},
    491  1.1  riastrad 	},
    492  1.1  riastrad 	[6] = {			/* Packet Vector #24 */
    493  1.1  riastrad 		.key = keyD,
    494  1.1  riastrad 		.nonce = {
    495  1.1  riastrad 			0x00,0x8d,0x49,0x3b, 0x30,0xae,0x8b,0x3c,
    496  1.1  riastrad 			0x96,0x96,0x76,0x6c, 0xfa,
    497  1.1  riastrad 		},
    498  1.1  riastrad 		.adlen = 12,
    499  1.1  riastrad 		.ad = ptxt_rand,
    500  1.1  riastrad 		.mlen = 21,
    501  1.1  riastrad 		.ptxt = ptxt_rand + 12,
    502  1.1  riastrad 		.M = 10,
    503  1.1  riastrad 		.tag = {0x6d,0xce,0x9e,0x82, 0xef,0xa1,0x6d,0xa6, 0x20,0x59},
    504  1.1  riastrad 		.ctxt = (const uint8_t[21]) {
    505  1.1  riastrad 			0xf3,0x29,0x05,0xb8, 0x8a,0x64,0x1b,0x04,
    506  1.1  riastrad 			0xb9,0xc9,0xff,0xb5, 0x8c,0xc3,0x90,0x90,
    507  1.1  riastrad 			0x0f,0x3d,0xa1,0x2a, 0xb1,
    508  1.1  riastrad 		},
    509  1.1  riastrad 	},
    510  1.1  riastrad };
    511  1.1  riastrad 
    512  1.1  riastrad int
    513  1.1  riastrad aes_ccm_selftest(void)
    514  1.1  riastrad {
    515  1.1  riastrad 	const unsigned L = 2;
    516  1.1  riastrad 	const unsigned noncelen = 13;
    517  1.1  riastrad 	struct aesenc enc, *AE = &enc;
    518  1.1  riastrad 	struct aes_ccm ccm, *C = &ccm;
    519  1.1  riastrad 	uint8_t buf[33 + 2], *bufp = buf + 1;
    520  1.1  riastrad 	uint8_t tag[16 + 2], *tagp = tag + 1;
    521  1.1  riastrad 	unsigned i;
    522  1.1  riastrad 	int result = 0;
    523  1.1  riastrad 
    524  1.1  riastrad 	bufp[-1] = bufp[33] = 0x1a;
    525  1.1  riastrad 	tagp[-1] = tagp[16] = 0x53;
    526  1.1  riastrad 
    527  1.1  riastrad 	for (i = 0; i < __arraycount(T); i++) {
    528  1.1  riastrad 		const unsigned nr = aes_setenckey128(AE, T[i].key);
    529  1.1  riastrad 
    530  1.1  riastrad 		/* encrypt and authenticate */
    531  1.1  riastrad 		aes_ccm_init(C, nr, AE, L, T[i].M, T[i].nonce, noncelen,
    532  1.1  riastrad 		    T[i].ad, T[i].adlen, T[i].mlen);
    533  1.1  riastrad 		aes_ccm_enc(C, T[i].ptxt, bufp, 1);
    534  1.1  riastrad 		aes_ccm_enc(C, T[i].ptxt + 1, bufp + 1, 2);
    535  1.1  riastrad 		aes_ccm_enc(C, T[i].ptxt + 3, bufp + 3, T[i].mlen - 4);
    536  1.1  riastrad 		aes_ccm_enc(C, T[i].ptxt + T[i].mlen - 1,
    537  1.1  riastrad 		    bufp + T[i].mlen - 1, 1);
    538  1.1  riastrad 		aes_ccm_tag(C, tagp);
    539  1.1  riastrad 		if (memcmp(bufp, T[i].ctxt, T[i].mlen)) {
    540  1.1  riastrad 			char name[32];
    541  1.1  riastrad 			snprintf(name, sizeof name, "%s: ctxt %u", __func__,
    542  1.1  riastrad 			    i);
    543  1.1  riastrad 			hexdump(printf, name, bufp, T[i].mlen);
    544  1.1  riastrad 			result = -1;
    545  1.1  riastrad 		}
    546  1.1  riastrad 		if (memcmp(tagp, T[i].tag, T[i].M)) {
    547  1.1  riastrad 			char name[32];
    548  1.1  riastrad 			snprintf(name, sizeof name, "%s: tag %u", __func__, i);
    549  1.1  riastrad 			hexdump(printf, name, tagp, T[i].M);
    550  1.1  riastrad 			result = -1;
    551  1.1  riastrad 		}
    552  1.1  riastrad 
    553  1.1  riastrad 		/* decrypt and verify */
    554  1.1  riastrad 		aes_ccm_init(C, nr, AE, L, T[i].M, T[i].nonce, noncelen,
    555  1.1  riastrad 		    T[i].ad, T[i].adlen, T[i].mlen);
    556  1.1  riastrad 		aes_ccm_dec(C, T[i].ctxt, bufp, 1);
    557  1.1  riastrad 		aes_ccm_dec(C, T[i].ctxt + 1, bufp + 1, 2);
    558  1.1  riastrad 		aes_ccm_dec(C, T[i].ctxt + 3, bufp + 3, T[i].mlen - 4);
    559  1.1  riastrad 		aes_ccm_dec(C, T[i].ctxt + T[i].mlen - 1,
    560  1.1  riastrad 		    bufp + T[i].mlen - 1, 1);
    561  1.1  riastrad 		if (!aes_ccm_verify(C, T[i].tag)) {
    562  1.1  riastrad 			printf("%s: verify %u failed\n", __func__, i);
    563  1.1  riastrad 			result = -1;
    564  1.1  riastrad 		}
    565  1.1  riastrad 		if (memcmp(bufp, T[i].ptxt, T[i].mlen)) {
    566  1.1  riastrad 			char name[32];
    567  1.1  riastrad 			snprintf(name, sizeof name, "%s: ptxt %u", __func__,
    568  1.1  riastrad 			    i);
    569  1.1  riastrad 			hexdump(printf, name, bufp, T[i].mlen);
    570  1.1  riastrad 			result = -1;
    571  1.1  riastrad 		}
    572  1.1  riastrad 
    573  1.1  riastrad 		/* decrypt and verify with a bit flipped */
    574  1.1  riastrad 		memcpy(tagp, T[i].tag, T[i].M);
    575  1.1  riastrad 		tagp[0] ^= 0x80;
    576  1.1  riastrad 		aes_ccm_init(C, nr, AE, L, T[i].M, T[i].nonce, noncelen,
    577  1.1  riastrad 		    T[i].ad, T[i].adlen, T[i].mlen);
    578  1.1  riastrad 		aes_ccm_dec(C, T[i].ctxt, bufp, 1);
    579  1.1  riastrad 		aes_ccm_dec(C, T[i].ctxt + 1, bufp + 1, 2);
    580  1.1  riastrad 		aes_ccm_dec(C, T[i].ctxt + 3, bufp + 3, T[i].mlen - 4);
    581  1.1  riastrad 		aes_ccm_dec(C, T[i].ctxt + T[i].mlen - 1,
    582  1.1  riastrad 		    bufp + T[i].mlen - 1, 1);
    583  1.1  riastrad 		if (aes_ccm_verify(C, tagp)) {
    584  1.1  riastrad 			printf("%s: forgery %u succeeded\n", __func__, i);
    585  1.1  riastrad 			result = -1;
    586  1.1  riastrad 		}
    587  1.1  riastrad 	}
    588  1.1  riastrad 
    589  1.1  riastrad 	if (bufp[-1] != 0x1a || bufp[33] != 0x1a) {
    590  1.1  riastrad 		printf("%s: buffer overrun\n", __func__);
    591  1.1  riastrad 		result = -1;
    592  1.1  riastrad 	}
    593  1.1  riastrad 	if (tagp[-1] != 0x53 || tagp[16] != 0x53) {
    594  1.1  riastrad 		printf("%s: tag overrun\n", __func__);
    595  1.1  riastrad 		result = -1;
    596  1.1  riastrad 	}
    597  1.1  riastrad 
    598  1.1  riastrad 	return result;
    599  1.1  riastrad }
    600  1.1  riastrad 
    601  1.1  riastrad /* XXX provisional hack */
    602  1.1  riastrad #include <sys/module.h>
    603  1.1  riastrad 
    604  1.3  riastrad MODULE(MODULE_CLASS_MISC, aes_ccm, "aes");
    605  1.1  riastrad 
    606  1.1  riastrad static int
    607  1.1  riastrad aes_ccm_modcmd(modcmd_t cmd, void *opaque)
    608  1.1  riastrad {
    609  1.1  riastrad 
    610  1.1  riastrad 	switch (cmd) {
    611  1.1  riastrad 	case MODULE_CMD_INIT:
    612  1.1  riastrad 		if (aes_ccm_selftest())
    613  1.1  riastrad 			return EIO;
    614  1.6  jmcneill 		aprint_debug("aes_ccm: self-test passed\n");
    615  1.1  riastrad 		return 0;
    616  1.1  riastrad 	case MODULE_CMD_FINI:
    617  1.1  riastrad 		return 0;
    618  1.1  riastrad 	default:
    619  1.1  riastrad 		return ENOTTY;
    620  1.1  riastrad 	}
    621  1.1  riastrad }
    622