]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - 6/sys/netinet6/ah_aesxcbcmac.c
merge fix for boot-time hang on centos' xen
[FreeBSD/FreeBSD.git] / 6 / sys / netinet6 / ah_aesxcbcmac.c
1 /*      $KAME: ah_aesxcbcmac.c,v 1.6 2003/07/22 02:30:54 itojun Exp $   */
2
3 /*-
4  * Copyright (C) 1995, 1996, 1997, 1998 and 2003 WIDE Project.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the project nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  * $FreeBSD$
32  */
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/socket.h>
37 #include <sys/queue.h>
38 #include <sys/malloc.h>
39 #include <sys/syslog.h>
40 #include <sys/mbuf.h>
41
42 #include <net/if.h>
43 #include <net/route.h>
44
45 #include <netinet/in.h>
46
47 #include <netinet6/ipsec.h>
48 #include <netinet6/ah.h>
49 #include <netinet6/ah_aesxcbcmac.h>
50
51 #include <netkey/key.h>
52
53 #include <crypto/rijndael/rijndael.h>
54
55 #include <net/net_osdep.h>
56
57 #define AES_BLOCKSIZE   16
58
59 typedef struct {
60         u_int8_t        e[AES_BLOCKSIZE];
61         u_int8_t        buf[AES_BLOCKSIZE];
62         size_t          buflen;
63         u_int32_t       r_k1s[(RIJNDAEL_MAXNR+1)*4];
64         u_int32_t       r_k2s[(RIJNDAEL_MAXNR+1)*4];
65         u_int32_t       r_k3s[(RIJNDAEL_MAXNR+1)*4];
66         int             r_nr; /* key-length-dependent number of rounds */
67         u_int8_t        k2[AES_BLOCKSIZE];
68         u_int8_t        k3[AES_BLOCKSIZE];
69 } aesxcbc_ctx;
70
71 int
72 ah_aes_xcbc_mac_init(state, sav)
73         struct ah_algorithm_state *state;
74         struct secasvar *sav;
75 {
76         u_int8_t k1seed[AES_BLOCKSIZE] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 };
77         u_int8_t k2seed[AES_BLOCKSIZE] = { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 };
78         u_int8_t k3seed[AES_BLOCKSIZE] = { 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 };
79         u_int32_t r_ks[(RIJNDAEL_MAXNR+1)*4];
80         aesxcbc_ctx *ctx;
81         u_int8_t k1[AES_BLOCKSIZE];
82
83         if (!state)
84                 panic("ah_aes_xcbc_mac_init: what?");
85
86         state->sav = sav;
87         state->foo = (void *)malloc(sizeof(aesxcbc_ctx), M_TEMP, M_NOWAIT);
88         if (!state->foo)
89                 return ENOBUFS;
90         bzero(state->foo, sizeof(aesxcbc_ctx));
91
92         ctx = (aesxcbc_ctx *)state->foo;
93
94         if ((ctx->r_nr = rijndaelKeySetupEnc(r_ks,
95             (char *)_KEYBUF(sav->key_auth), AES_BLOCKSIZE * 8)) == 0)
96                 return -1;
97         rijndaelEncrypt(r_ks, ctx->r_nr, k1seed, k1);
98         rijndaelEncrypt(r_ks, ctx->r_nr, k2seed, ctx->k2);
99         rijndaelEncrypt(r_ks, ctx->r_nr, k3seed, ctx->k3);
100         if (rijndaelKeySetupEnc(ctx->r_k1s, k1, AES_BLOCKSIZE * 8) == 0)
101                 return -1;
102         if (rijndaelKeySetupEnc(ctx->r_k2s, ctx->k2, AES_BLOCKSIZE * 8) == 0)
103                 return -1;
104         if (rijndaelKeySetupEnc(ctx->r_k3s, ctx->k3, AES_BLOCKSIZE * 8) == 0)
105                 return -1;
106
107         return 0;
108 }
109
110 void
111 ah_aes_xcbc_mac_loop(state, addr, len)
112         struct ah_algorithm_state *state;
113         u_int8_t *addr;
114         size_t len;
115 {
116         u_int8_t buf[AES_BLOCKSIZE];
117         aesxcbc_ctx *ctx;
118         u_int8_t *ep;
119         int i;
120
121         if (!state || !state->foo)
122                 panic("ah_aes_xcbc_mac_loop: what?");
123
124         ctx = (aesxcbc_ctx *)state->foo;
125         ep = addr + len;
126
127         if (ctx->buflen == sizeof(ctx->buf)) {
128                 for (i = 0; i < sizeof(ctx->e); i++)
129                         ctx->buf[i] ^= ctx->e[i];
130                 rijndaelEncrypt(ctx->r_k1s, ctx->r_nr, ctx->buf, ctx->e);
131                 ctx->buflen = 0;
132         }
133         if (ctx->buflen + len < sizeof(ctx->buf)) {
134                 bcopy(addr, ctx->buf + ctx->buflen, len);
135                 ctx->buflen += len;
136                 return;
137         }
138         if (ctx->buflen && ctx->buflen + len > sizeof(ctx->buf)) {
139                 bcopy(addr, ctx->buf + ctx->buflen,
140                     sizeof(ctx->buf) - ctx->buflen);
141                 for (i = 0; i < sizeof(ctx->e); i++)
142                         ctx->buf[i] ^= ctx->e[i];
143                 rijndaelEncrypt(ctx->r_k1s, ctx->r_nr, ctx->buf, ctx->e);
144                 addr += sizeof(ctx->buf) - ctx->buflen;
145                 ctx->buflen = 0;
146         }
147         /* due to the special processing for M[n], "=" case is not included */
148         while (addr + AES_BLOCKSIZE < ep) {
149                 bcopy(addr, buf, AES_BLOCKSIZE);
150                 for (i = 0; i < sizeof(buf); i++)
151                         buf[i] ^= ctx->e[i];
152                 rijndaelEncrypt(ctx->r_k1s, ctx->r_nr, buf, ctx->e);
153                 addr += AES_BLOCKSIZE;
154         }
155         if (addr < ep) {
156                 bcopy(addr, ctx->buf + ctx->buflen, ep - addr);
157                 ctx->buflen += ep - addr;
158         }
159 }
160
161 void
162 ah_aes_xcbc_mac_result(state, addr, l)
163         struct ah_algorithm_state *state;
164         u_int8_t *addr;
165         size_t l;
166 {
167         u_char digest[AES_BLOCKSIZE];
168         aesxcbc_ctx *ctx;
169         int i;
170
171         ctx = (aesxcbc_ctx *)state->foo;
172
173         if (ctx->buflen == sizeof(ctx->buf)) {
174                 for (i = 0; i < sizeof(ctx->buf); i++) {
175                         ctx->buf[i] ^= ctx->e[i];
176                         ctx->buf[i] ^= ctx->k2[i];
177                 }
178                 rijndaelEncrypt(ctx->r_k1s, ctx->r_nr, ctx->buf, digest);
179         } else {
180                 for (i = ctx->buflen; i < sizeof(ctx->buf); i++)
181                         ctx->buf[i] = (i == ctx->buflen) ? 0x80 : 0x00;
182                 for (i = 0; i < sizeof(ctx->buf); i++) {
183                         ctx->buf[i] ^= ctx->e[i];
184                         ctx->buf[i] ^= ctx->k3[i];
185                 }
186                 rijndaelEncrypt(ctx->r_k1s, ctx->r_nr, ctx->buf, digest);
187         }
188
189         bcopy(digest, addr, sizeof(digest) > l ? l : sizeof(digest));
190
191         free(state->foo, M_TEMP);
192 }