xref: /netbsd-src/sys/opencrypto/aesxcbcmac.c (revision 8835ffd08237019b1c2cfd70d4eab20f517cd01d)
1*8835ffd0Sriastradh /* $NetBSD: aesxcbcmac.c,v 1.3 2020/06/29 23:34:48 riastradh Exp $ */
2ebc232a5Sdrochner 
3ebc232a5Sdrochner /*
4ebc232a5Sdrochner  * Copyright (C) 1995, 1996, 1997, 1998 and 2003 WIDE Project.
5ebc232a5Sdrochner  * All rights reserved.
6ebc232a5Sdrochner  *
7ebc232a5Sdrochner  * Redistribution and use in source and binary forms, with or without
8ebc232a5Sdrochner  * modification, are permitted provided that the following conditions
9ebc232a5Sdrochner  * are met:
10ebc232a5Sdrochner  * 1. Redistributions of source code must retain the above copyright
11ebc232a5Sdrochner  *    notice, this list of conditions and the following disclaimer.
12ebc232a5Sdrochner  * 2. Redistributions in binary form must reproduce the above copyright
13ebc232a5Sdrochner  *    notice, this list of conditions and the following disclaimer in the
14ebc232a5Sdrochner  *    documentation and/or other materials provided with the distribution.
15ebc232a5Sdrochner  * 3. Neither the name of the project nor the names of its contributors
16ebc232a5Sdrochner  *    may be used to endorse or promote products derived from this software
17ebc232a5Sdrochner  *    without specific prior written permission.
18ebc232a5Sdrochner  *
19ebc232a5Sdrochner  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20ebc232a5Sdrochner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21ebc232a5Sdrochner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22ebc232a5Sdrochner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23ebc232a5Sdrochner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24ebc232a5Sdrochner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25ebc232a5Sdrochner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26ebc232a5Sdrochner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27ebc232a5Sdrochner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28ebc232a5Sdrochner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29ebc232a5Sdrochner  * SUCH DAMAGE.
30ebc232a5Sdrochner  */
31ebc232a5Sdrochner 
32ebc232a5Sdrochner #include <sys/cdefs.h>
33*8835ffd0Sriastradh __KERNEL_RCSID(0, "$NetBSD: aesxcbcmac.c,v 1.3 2020/06/29 23:34:48 riastradh Exp $");
34ebc232a5Sdrochner 
35ebc232a5Sdrochner #include <sys/param.h>
36ebc232a5Sdrochner #include <sys/systm.h>
37*8835ffd0Sriastradh 
38*8835ffd0Sriastradh #include <crypto/aes/aes.h>
39ebc232a5Sdrochner 
40ebc232a5Sdrochner #include <opencrypto/aesxcbcmac.h>
41ebc232a5Sdrochner 
42ebc232a5Sdrochner int
aes_xcbc_mac_init(void * vctx,const uint8_t * key,u_int16_t keylen)433ee5c00aSchristos aes_xcbc_mac_init(void *vctx, const uint8_t *key, u_int16_t keylen)
44ebc232a5Sdrochner {
453ee5c00aSchristos 	static const uint8_t k1seed[AES_BLOCKSIZE] =
463ee5c00aSchristos 	    { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 };
473ee5c00aSchristos 	static const uint8_t k2seed[AES_BLOCKSIZE] =
483ee5c00aSchristos 	    { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 };
493ee5c00aSchristos 	static const uint8_t k3seed[AES_BLOCKSIZE] =
503ee5c00aSchristos 	    { 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 };
51*8835ffd0Sriastradh 	struct aesenc r_ks;
52ebc232a5Sdrochner 	aesxcbc_ctx *ctx;
533ee5c00aSchristos 	uint8_t k1[AES_BLOCKSIZE];
54ebc232a5Sdrochner 
553ee5c00aSchristos 	ctx = vctx;
563ee5c00aSchristos 	memset(ctx, 0, sizeof(*ctx));
57ebc232a5Sdrochner 
58*8835ffd0Sriastradh 	switch (keylen) {
59*8835ffd0Sriastradh 	case 16:
60*8835ffd0Sriastradh 		ctx->r_nr = aes_setenckey128(&r_ks, key);
61*8835ffd0Sriastradh 		break;
62*8835ffd0Sriastradh 	case 24:
63*8835ffd0Sriastradh 		ctx->r_nr = aes_setenckey192(&r_ks, key);
64*8835ffd0Sriastradh 		break;
65*8835ffd0Sriastradh 	case 32:
66*8835ffd0Sriastradh 		ctx->r_nr = aes_setenckey256(&r_ks, key);
67*8835ffd0Sriastradh 		break;
68*8835ffd0Sriastradh 	}
69*8835ffd0Sriastradh 	aes_enc(&r_ks, k1seed, k1, ctx->r_nr);
70*8835ffd0Sriastradh 	aes_enc(&r_ks, k2seed, ctx->k2, ctx->r_nr);
71*8835ffd0Sriastradh 	aes_enc(&r_ks, k3seed, ctx->k3, ctx->r_nr);
72*8835ffd0Sriastradh 	aes_setenckey128(&ctx->r_k1s, k1);
73*8835ffd0Sriastradh 
74*8835ffd0Sriastradh 	explicit_memset(&r_ks, 0, sizeof(r_ks));
75*8835ffd0Sriastradh 	explicit_memset(k1, 0, sizeof(k1));
76ebc232a5Sdrochner 
77ebc232a5Sdrochner 	return 0;
78ebc232a5Sdrochner }
79ebc232a5Sdrochner 
80ebc232a5Sdrochner int
aes_xcbc_mac_loop(void * vctx,const uint8_t * addr,u_int16_t len)813ee5c00aSchristos aes_xcbc_mac_loop(void *vctx, const uint8_t *addr, u_int16_t len)
82ebc232a5Sdrochner {
833ee5c00aSchristos 	uint8_t buf[AES_BLOCKSIZE];
84ebc232a5Sdrochner 	aesxcbc_ctx *ctx;
853ee5c00aSchristos 	const uint8_t *ep;
86ebc232a5Sdrochner 	int i;
87ebc232a5Sdrochner 
883ee5c00aSchristos 	ctx = vctx;
89ebc232a5Sdrochner 	ep = addr + len;
90ebc232a5Sdrochner 
91ebc232a5Sdrochner 	if (ctx->buflen == sizeof(ctx->buf)) {
92ebc232a5Sdrochner 		for (i = 0; i < sizeof(ctx->e); i++)
93ebc232a5Sdrochner 			ctx->buf[i] ^= ctx->e[i];
94*8835ffd0Sriastradh 		aes_enc(&ctx->r_k1s, ctx->buf, ctx->e, ctx->r_nr);
95ebc232a5Sdrochner 		ctx->buflen = 0;
96ebc232a5Sdrochner 	}
97ebc232a5Sdrochner 	if (ctx->buflen + len < sizeof(ctx->buf)) {
98ebc232a5Sdrochner 		memcpy(ctx->buf + ctx->buflen, addr, len);
99ebc232a5Sdrochner 		ctx->buflen += len;
100ebc232a5Sdrochner 		return 0;
101ebc232a5Sdrochner 	}
102ebc232a5Sdrochner 	if (ctx->buflen && ctx->buflen + len > sizeof(ctx->buf)) {
103ebc232a5Sdrochner 		memcpy(ctx->buf + ctx->buflen, addr,
104ebc232a5Sdrochner 		    sizeof(ctx->buf) - ctx->buflen);
105ebc232a5Sdrochner 		for (i = 0; i < sizeof(ctx->e); i++)
106ebc232a5Sdrochner 			ctx->buf[i] ^= ctx->e[i];
107*8835ffd0Sriastradh 		aes_enc(&ctx->r_k1s, ctx->buf, ctx->e, ctx->r_nr);
108ebc232a5Sdrochner 		addr += sizeof(ctx->buf) - ctx->buflen;
109ebc232a5Sdrochner 		ctx->buflen = 0;
110ebc232a5Sdrochner 	}
111ebc232a5Sdrochner 	/* due to the special processing for M[n], "=" case is not included */
1123ee5c00aSchristos 	while (ep - addr > AES_BLOCKSIZE) {
113ebc232a5Sdrochner 		memcpy(buf, addr, AES_BLOCKSIZE);
114ebc232a5Sdrochner 		for (i = 0; i < sizeof(buf); i++)
115ebc232a5Sdrochner 			buf[i] ^= ctx->e[i];
116*8835ffd0Sriastradh 		aes_enc(&ctx->r_k1s, buf, ctx->e, ctx->r_nr);
117ebc232a5Sdrochner 		addr += AES_BLOCKSIZE;
118ebc232a5Sdrochner 	}
119ebc232a5Sdrochner 	if (addr < ep) {
120ebc232a5Sdrochner 		memcpy(ctx->buf + ctx->buflen, addr, ep - addr);
121ebc232a5Sdrochner 		ctx->buflen += ep - addr;
122ebc232a5Sdrochner 	}
123ebc232a5Sdrochner 	return 0;
124ebc232a5Sdrochner }
125ebc232a5Sdrochner 
126ebc232a5Sdrochner void
aes_xcbc_mac_result(uint8_t * addr,void * vctx)1273ee5c00aSchristos aes_xcbc_mac_result(uint8_t *addr, void *vctx)
128ebc232a5Sdrochner {
1293ee5c00aSchristos 	uint8_t digest[AES_BLOCKSIZE];
130ebc232a5Sdrochner 	aesxcbc_ctx *ctx;
131ebc232a5Sdrochner 	int i;
132ebc232a5Sdrochner 
1333ee5c00aSchristos 	ctx = vctx;
134ebc232a5Sdrochner 
135ebc232a5Sdrochner 	if (ctx->buflen == sizeof(ctx->buf)) {
136ebc232a5Sdrochner 		for (i = 0; i < sizeof(ctx->buf); i++) {
137ebc232a5Sdrochner 			ctx->buf[i] ^= ctx->e[i];
138ebc232a5Sdrochner 			ctx->buf[i] ^= ctx->k2[i];
139ebc232a5Sdrochner 		}
140*8835ffd0Sriastradh 		aes_enc(&ctx->r_k1s, ctx->buf, digest, ctx->r_nr);
141ebc232a5Sdrochner 	} else {
142ebc232a5Sdrochner 		for (i = ctx->buflen; i < sizeof(ctx->buf); i++)
143ebc232a5Sdrochner 			ctx->buf[i] = (i == ctx->buflen) ? 0x80 : 0x00;
144ebc232a5Sdrochner 		for (i = 0; i < sizeof(ctx->buf); i++) {
145ebc232a5Sdrochner 			ctx->buf[i] ^= ctx->e[i];
146ebc232a5Sdrochner 			ctx->buf[i] ^= ctx->k3[i];
147ebc232a5Sdrochner 		}
148*8835ffd0Sriastradh 		aes_enc(&ctx->r_k1s, ctx->buf, digest, ctx->r_nr);
149ebc232a5Sdrochner 	}
150ebc232a5Sdrochner 
151ebc232a5Sdrochner 	memcpy(addr, digest, sizeof(digest));
152ebc232a5Sdrochner }
153