1 | /* |
2 | * Copyright (c) 2008-2016 Apple Inc. All rights reserved. |
3 | * |
4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
5 | * |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License |
8 | * Version 2.0 (the 'License'). You may not use this file except in |
9 | * compliance with the License. The rights granted to you under the License |
10 | * may not be used to create, or enable the creation or redistribution of, |
11 | * unlawful or unlicensed copies of an Apple operating system, or to |
12 | * circumvent, violate, or enable the circumvention or violation of, any |
13 | * terms of an Apple operating system software license agreement. |
14 | * |
15 | * Please obtain a copy of the License at |
16 | * http://www.opensource.apple.com/apsl/ and read it before using this file. |
17 | * |
18 | * The Original Code and all software distributed under the License are |
19 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, |
22 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
23 | * Please see the License for the specific language governing rights and |
24 | * limitations under the License. |
25 | * |
26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
27 | */ |
28 | |
29 | /* $FreeBSD: src/sys/netinet6/ah_core.c,v 1.2.2.4 2001/07/03 11:01:49 ume Exp $ */ |
30 | /* $KAME: ah_core.c,v 1.44 2001/03/12 11:24:39 itojun Exp $ */ |
31 | |
32 | /* |
33 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. |
34 | * All rights reserved. |
35 | * |
36 | * Redistribution and use in source and binary forms, with or without |
37 | * modification, are permitted provided that the following conditions |
38 | * are met: |
39 | * 1. Redistributions of source code must retain the above copyright |
40 | * notice, this list of conditions and the following disclaimer. |
41 | * 2. Redistributions in binary form must reproduce the above copyright |
42 | * notice, this list of conditions and the following disclaimer in the |
43 | * documentation and/or other materials provided with the distribution. |
44 | * 3. Neither the name of the project nor the names of its contributors |
45 | * may be used to endorse or promote products derived from this software |
46 | * without specific prior written permission. |
47 | * |
48 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND |
49 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
50 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
51 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE |
52 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
53 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
54 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
55 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
56 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
57 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
58 | * SUCH DAMAGE. |
59 | */ |
60 | |
61 | /* |
62 | * RFC1826/2402 authentication header. |
63 | */ |
64 | |
65 | /* TODO: have shared routines for hmac-* algorithms */ |
66 | |
67 | #include <sys/param.h> |
68 | #include <sys/systm.h> |
69 | #include <sys/malloc.h> |
70 | #include <sys/mbuf.h> |
71 | #include <sys/domain.h> |
72 | #include <sys/protosw.h> |
73 | #include <sys/socket.h> |
74 | #include <sys/socketvar.h> |
75 | #include <sys/errno.h> |
76 | #include <sys/time.h> |
77 | #include <sys/syslog.h> |
78 | |
79 | #include <net/if.h> |
80 | #include <net/route.h> |
81 | |
82 | #include <netinet/in.h> |
83 | #include <netinet/in_systm.h> |
84 | #include <netinet/ip.h> |
85 | #include <netinet/in_var.h> |
86 | |
87 | #if INET6 |
88 | #include <netinet/ip6.h> |
89 | #include <netinet6/ip6_var.h> |
90 | #include <netinet/icmp6.h> |
91 | #endif |
92 | |
93 | #include <netinet6/ipsec.h> |
94 | #if INET6 |
95 | #include <netinet6/ipsec6.h> |
96 | #endif |
97 | #include <netinet6/ah.h> |
98 | #if INET6 |
99 | #include <netinet6/ah6.h> |
100 | #endif |
101 | #if IPSEC_ESP |
102 | #include <netinet6/esp.h> |
103 | #if INET6 |
104 | #include <netinet6/esp6.h> |
105 | #endif |
106 | #endif |
107 | #include <net/pfkeyv2.h> |
108 | #include <netkey/keydb.h> |
109 | #include <libkern/crypto/md5.h> |
110 | #include <libkern/crypto/sha1.h> |
111 | #include <libkern/crypto/sha2.h> |
112 | |
113 | #include <net/net_osdep.h> |
114 | |
115 | #define HMACSIZE 16 |
116 | |
117 | static int ah_sumsiz_1216(struct secasvar *); |
118 | static int ah_sumsiz_zero(struct secasvar *); |
119 | static int ah_none_mature(struct secasvar *); |
120 | static int ah_none_init(struct ah_algorithm_state *, struct secasvar *); |
121 | static void ah_none_loop(struct ah_algorithm_state *, caddr_t, size_t); |
122 | static void ah_none_result(struct ah_algorithm_state *, caddr_t, size_t); |
123 | static int ah_keyed_md5_mature(struct secasvar *); |
124 | static int ah_keyed_md5_init(struct ah_algorithm_state *, struct secasvar *); |
125 | static void ah_keyed_md5_loop(struct ah_algorithm_state *, caddr_t, size_t); |
126 | static void ah_keyed_md5_result(struct ah_algorithm_state *, caddr_t, size_t); |
127 | static int ah_keyed_sha1_mature(struct secasvar *); |
128 | static int ah_keyed_sha1_init(struct ah_algorithm_state *, struct secasvar *); |
129 | static void ah_keyed_sha1_loop(struct ah_algorithm_state *, caddr_t, size_t); |
130 | static void ah_keyed_sha1_result(struct ah_algorithm_state *, caddr_t, size_t); |
131 | static int ah_hmac_md5_mature(struct secasvar *); |
132 | static int ah_hmac_md5_init(struct ah_algorithm_state *, struct secasvar *); |
133 | static void ah_hmac_md5_loop(struct ah_algorithm_state *, caddr_t, size_t); |
134 | static void ah_hmac_md5_result(struct ah_algorithm_state *, caddr_t, size_t); |
135 | static int ah_hmac_sha1_mature(struct secasvar *); |
136 | static int ah_hmac_sha1_init(struct ah_algorithm_state *, struct secasvar *); |
137 | static void ah_hmac_sha1_loop(struct ah_algorithm_state *, caddr_t, size_t); |
138 | static void ah_hmac_sha1_result(struct ah_algorithm_state *, caddr_t, size_t); |
139 | #if AH_ALL_CRYPTO |
140 | static int ah_sumsiz_sha2_256(struct secasvar *); |
141 | static int ah_hmac_sha2_256_mature(struct secasvar *); |
142 | static int ah_hmac_sha2_256_init(struct ah_algorithm_state *, |
143 | struct secasvar *); |
144 | static void ah_hmac_sha2_256_loop(struct ah_algorithm_state *, caddr_t, size_t); |
145 | static void ah_hmac_sha2_256_result(struct ah_algorithm_state *, caddr_t, size_t); |
146 | static int ah_sumsiz_sha2_384(struct secasvar *); |
147 | static int ah_hmac_sha2_384_mature(struct secasvar *); |
148 | static int ah_hmac_sha2_384_init(struct ah_algorithm_state *, |
149 | struct secasvar *); |
150 | static void ah_hmac_sha2_384_loop(struct ah_algorithm_state *, caddr_t, size_t); |
151 | static void ah_hmac_sha2_384_result(struct ah_algorithm_state *, caddr_t, size_t); |
152 | static int ah_sumsiz_sha2_512(struct secasvar *); |
153 | static int ah_hmac_sha2_512_mature(struct secasvar *); |
154 | static int ah_hmac_sha2_512_init(struct ah_algorithm_state *, |
155 | struct secasvar *); |
156 | static void ah_hmac_sha2_512_loop(struct ah_algorithm_state *, caddr_t, size_t); |
157 | static void ah_hmac_sha2_512_result(struct ah_algorithm_state *, caddr_t, size_t); |
158 | #endif /* AH_ALL_CRYPTO */ |
159 | |
160 | static void ah_update_mbuf(struct mbuf *, int, int, |
161 | const struct ah_algorithm *, struct ah_algorithm_state *); |
162 | |
163 | const struct ah_algorithm * |
164 | ah_algorithm_lookup(int idx) |
165 | { |
166 | /* checksum algorithms */ |
167 | static struct ah_algorithm hmac_md5 = |
168 | { ah_sumsiz_1216, ah_hmac_md5_mature, 128, 128, "hmac-md5" , |
169 | ah_hmac_md5_init, ah_hmac_md5_loop, |
170 | ah_hmac_md5_result, }; |
171 | static struct ah_algorithm keyed_md5 = |
172 | { ah_sumsiz_1216, ah_keyed_md5_mature, 128, 128, "keyed-md5" , |
173 | ah_keyed_md5_init, ah_keyed_md5_loop, |
174 | ah_keyed_md5_result, }; |
175 | static struct ah_algorithm hmac_sha1 = |
176 | { ah_sumsiz_1216, ah_hmac_sha1_mature, 160, 160, "hmac-sha1" , |
177 | ah_hmac_sha1_init, ah_hmac_sha1_loop, |
178 | ah_hmac_sha1_result, }; |
179 | static struct ah_algorithm keyed_sha1 = |
180 | { ah_sumsiz_1216, ah_keyed_sha1_mature, 160, 160, "keyed-sha1" , |
181 | ah_keyed_sha1_init, ah_keyed_sha1_loop, |
182 | ah_keyed_sha1_result, }; |
183 | static struct ah_algorithm ah_none = |
184 | { ah_sumsiz_zero, ah_none_mature, 0, 2048, "none" , |
185 | ah_none_init, ah_none_loop, ah_none_result, }; |
186 | #if AH_ALL_CRYPTO |
187 | static struct ah_algorithm hmac_sha2_256 = |
188 | { ah_sumsiz_sha2_256, ah_hmac_sha2_256_mature, 256, 256, |
189 | "hmac-sha2-256" , |
190 | ah_hmac_sha2_256_init, ah_hmac_sha2_256_loop, |
191 | ah_hmac_sha2_256_result, }; |
192 | static struct ah_algorithm hmac_sha2_384 = |
193 | { ah_sumsiz_sha2_384, ah_hmac_sha2_384_mature, 384, 384, |
194 | "hmac-sha2-384" , |
195 | ah_hmac_sha2_384_init, ah_hmac_sha2_384_loop, |
196 | ah_hmac_sha2_384_result, }; |
197 | static struct ah_algorithm hmac_sha2_512 = |
198 | { ah_sumsiz_sha2_512, ah_hmac_sha2_512_mature, 512, 512, |
199 | "hmac-sha2-512" , |
200 | ah_hmac_sha2_512_init, ah_hmac_sha2_512_loop, |
201 | ah_hmac_sha2_512_result, }; |
202 | #endif /* AH_ALL_CRYPTO */ |
203 | |
204 | switch (idx) { |
205 | case SADB_AALG_MD5HMAC: |
206 | return &hmac_md5; |
207 | case SADB_AALG_SHA1HMAC: |
208 | return &hmac_sha1; |
209 | case SADB_X_AALG_MD5: |
210 | return &keyed_md5; |
211 | case SADB_X_AALG_SHA: |
212 | return &keyed_sha1; |
213 | case SADB_X_AALG_NULL: |
214 | return &ah_none; |
215 | #if AH_ALL_CRYPTO |
216 | case SADB_X_AALG_SHA2_256: |
217 | return &hmac_sha2_256; |
218 | case SADB_X_AALG_SHA2_384: |
219 | return &hmac_sha2_384; |
220 | case SADB_X_AALG_SHA2_512: |
221 | return &hmac_sha2_512; |
222 | #endif /* AH_ALL_CRYPTO */ |
223 | default: |
224 | return NULL; |
225 | } |
226 | } |
227 | |
228 | |
229 | static int |
230 | ah_sumsiz_1216(struct secasvar *sav) |
231 | { |
232 | if (!sav) |
233 | return -1; |
234 | if (sav->flags & SADB_X_EXT_OLD) |
235 | return 16; |
236 | else |
237 | return 12; |
238 | } |
239 | |
240 | static int |
241 | ah_sumsiz_zero(struct secasvar *sav) |
242 | { |
243 | if (!sav) |
244 | return -1; |
245 | return 0; |
246 | } |
247 | |
248 | static int |
249 | ah_none_mature(struct secasvar *sav) |
250 | { |
251 | if (sav->sah->saidx.proto == IPPROTO_AH) { |
252 | ipseclog((LOG_ERR, |
253 | "ah_none_mature: protocol and algorithm mismatch.\n" )); |
254 | return 1; |
255 | } |
256 | return 0; |
257 | } |
258 | |
259 | static int |
260 | ah_none_init( |
261 | struct ah_algorithm_state *state, |
262 | __unused struct secasvar *sav) |
263 | { |
264 | state->foo = NULL; |
265 | return 0; |
266 | } |
267 | |
268 | static void |
269 | ah_none_loop( |
270 | __unused struct ah_algorithm_state *state, |
271 | __unused caddr_t addr, |
272 | __unused size_t len) |
273 | { |
274 | } |
275 | |
276 | static void |
277 | ah_none_result( |
278 | __unused struct ah_algorithm_state *state, |
279 | __unused caddr_t addr, |
280 | __unused size_t l) |
281 | { |
282 | } |
283 | |
284 | static int |
285 | ah_keyed_md5_mature( |
286 | __unused struct secasvar *sav) |
287 | { |
288 | /* anything is okay */ |
289 | return 0; |
290 | } |
291 | |
292 | static int |
293 | ah_keyed_md5_init(struct ah_algorithm_state *state, struct secasvar *sav) |
294 | { |
295 | size_t padlen; |
296 | size_t keybitlen; |
297 | u_int8_t buf[32] __attribute__((aligned(4))); |
298 | |
299 | if (!state) |
300 | panic("ah_keyed_md5_init: what?" ); |
301 | |
302 | state->sav = sav; |
303 | state->foo = (void *)_MALLOC(sizeof(MD5_CTX), M_TEMP, M_NOWAIT); |
304 | if (state->foo == NULL) |
305 | return ENOBUFS; |
306 | |
307 | MD5Init((MD5_CTX *)state->foo); |
308 | if (state->sav) { |
309 | MD5Update((MD5_CTX *)state->foo, |
310 | (u_int8_t *)_KEYBUF(state->sav->key_auth), |
311 | (u_int)_KEYLEN(state->sav->key_auth)); |
312 | |
313 | /* |
314 | * Pad after the key. |
315 | * We cannot simply use md5_pad() since the function |
316 | * won't update the total length. |
317 | */ |
318 | if (_KEYLEN(state->sav->key_auth) < 56) |
319 | padlen = 64 - 8 - _KEYLEN(state->sav->key_auth); |
320 | else |
321 | padlen = 64 + 64 - 8 - _KEYLEN(state->sav->key_auth); |
322 | keybitlen = _KEYLEN(state->sav->key_auth); |
323 | keybitlen *= 8; |
324 | |
325 | buf[0] = 0x80; |
326 | MD5Update((MD5_CTX *)state->foo, &buf[0], 1); |
327 | padlen--; |
328 | |
329 | bzero(buf, sizeof(buf)); |
330 | while (sizeof(buf) < padlen) { |
331 | MD5Update((MD5_CTX *)state->foo, &buf[0], sizeof(buf)); |
332 | padlen -= sizeof(buf); |
333 | } |
334 | if (padlen) { |
335 | MD5Update((MD5_CTX *)state->foo, &buf[0], padlen); |
336 | } |
337 | |
338 | buf[0] = (keybitlen >> 0) & 0xff; |
339 | buf[1] = (keybitlen >> 8) & 0xff; |
340 | buf[2] = (keybitlen >> 16) & 0xff; |
341 | buf[3] = (keybitlen >> 24) & 0xff; |
342 | MD5Update((MD5_CTX *)state->foo, buf, 8); |
343 | } |
344 | |
345 | return 0; |
346 | } |
347 | |
348 | static void |
349 | ah_keyed_md5_loop(struct ah_algorithm_state *state, caddr_t addr, size_t len) |
350 | { |
351 | if (!state) |
352 | panic("ah_keyed_md5_loop: what?" ); |
353 | |
354 | MD5Update((MD5_CTX *)state->foo, addr, len); |
355 | } |
356 | |
357 | static void |
358 | ah_keyed_md5_result(struct ah_algorithm_state *state, caddr_t addr, size_t l) |
359 | { |
360 | u_char digest[16] __attribute__((aligned(4))); |
361 | |
362 | if (!state) |
363 | panic("ah_keyed_md5_result: what?" ); |
364 | |
365 | if (state->sav) { |
366 | MD5Update((MD5_CTX *)state->foo, |
367 | (u_int8_t *)_KEYBUF(state->sav->key_auth), |
368 | (u_int)_KEYLEN(state->sav->key_auth)); |
369 | } |
370 | MD5Final(&digest[0], (MD5_CTX *)state->foo); |
371 | FREE(state->foo, M_TEMP); |
372 | bcopy(&digest[0], (void *)addr, sizeof(digest) > l ? l : sizeof(digest)); |
373 | } |
374 | |
375 | static int |
376 | ah_keyed_sha1_mature(struct secasvar *sav) |
377 | { |
378 | const struct ah_algorithm *algo; |
379 | |
380 | if (!sav->key_auth) { |
381 | ipseclog((LOG_ERR, "ah_keyed_sha1_mature: no key is given.\n" )); |
382 | return 1; |
383 | } |
384 | |
385 | algo = ah_algorithm_lookup(sav->alg_auth); |
386 | if (!algo) { |
387 | ipseclog((LOG_ERR, "ah_keyed_sha1_mature: unsupported algorithm.\n" )); |
388 | return 1; |
389 | } |
390 | |
391 | if (sav->key_auth->sadb_key_bits < algo->keymin |
392 | || algo->keymax < sav->key_auth->sadb_key_bits) { |
393 | ipseclog((LOG_ERR, |
394 | "ah_keyed_sha1_mature: invalid key length %d.\n" , |
395 | sav->key_auth->sadb_key_bits)); |
396 | return 1; |
397 | } |
398 | |
399 | return 0; |
400 | } |
401 | |
402 | static int |
403 | ah_keyed_sha1_init(struct ah_algorithm_state *state, struct secasvar *sav) |
404 | { |
405 | SHA1_CTX *ctxt; |
406 | size_t padlen; |
407 | size_t keybitlen; |
408 | u_int8_t buf[32] __attribute__((aligned(4))); |
409 | |
410 | if (!state) |
411 | panic("ah_keyed_sha1_init: what?" ); |
412 | |
413 | state->sav = sav; |
414 | state->foo = (void *)_MALLOC(sizeof(SHA1_CTX), M_TEMP, M_NOWAIT); |
415 | if (!state->foo) |
416 | return ENOBUFS; |
417 | |
418 | ctxt = (SHA1_CTX *)state->foo; |
419 | SHA1Init(ctxt); |
420 | |
421 | if (state->sav) { |
422 | SHA1Update(ctxt, (u_int8_t *)_KEYBUF(state->sav->key_auth), |
423 | (u_int)_KEYLEN(state->sav->key_auth)); |
424 | |
425 | /* |
426 | * Pad after the key. |
427 | */ |
428 | if (_KEYLEN(state->sav->key_auth) < 56) |
429 | padlen = 64 - 8 - _KEYLEN(state->sav->key_auth); |
430 | else |
431 | padlen = 64 + 64 - 8 - _KEYLEN(state->sav->key_auth); |
432 | keybitlen = _KEYLEN(state->sav->key_auth); |
433 | keybitlen *= 8; |
434 | |
435 | buf[0] = 0x80; |
436 | SHA1Update(ctxt, &buf[0], 1); |
437 | padlen--; |
438 | |
439 | bzero(buf, sizeof(buf)); |
440 | while (sizeof(buf) < padlen) { |
441 | SHA1Update(ctxt, &buf[0], sizeof(buf)); |
442 | padlen -= sizeof(buf); |
443 | } |
444 | if (padlen) { |
445 | SHA1Update(ctxt, &buf[0], padlen); |
446 | } |
447 | |
448 | buf[0] = (keybitlen >> 0) & 0xff; |
449 | buf[1] = (keybitlen >> 8) & 0xff; |
450 | buf[2] = (keybitlen >> 16) & 0xff; |
451 | buf[3] = (keybitlen >> 24) & 0xff; |
452 | SHA1Update(ctxt, buf, 8); |
453 | } |
454 | |
455 | return 0; |
456 | } |
457 | |
458 | static void |
459 | ah_keyed_sha1_loop(struct ah_algorithm_state *state, caddr_t addr, size_t len) |
460 | { |
461 | SHA1_CTX *ctxt; |
462 | |
463 | if (!state || !state->foo) |
464 | panic("ah_keyed_sha1_loop: what?" ); |
465 | ctxt = (SHA1_CTX *)state->foo; |
466 | |
467 | SHA1Update(ctxt, (caddr_t)addr, (size_t)len); |
468 | } |
469 | |
470 | static void |
471 | ah_keyed_sha1_result(struct ah_algorithm_state *state, caddr_t addr, size_t l) |
472 | { |
473 | u_char digest[SHA1_RESULTLEN] __attribute__((aligned(4))); /* SHA-1 generates 160 bits */ |
474 | SHA1_CTX *ctxt; |
475 | |
476 | if (!state || !state->foo) |
477 | panic("ah_keyed_sha1_result: what?" ); |
478 | ctxt = (SHA1_CTX *)state->foo; |
479 | |
480 | if (state->sav) { |
481 | SHA1Update(ctxt, (u_int8_t *)_KEYBUF(state->sav->key_auth), |
482 | (u_int)_KEYLEN(state->sav->key_auth)); |
483 | } |
484 | SHA1Final((caddr_t)&digest[0], ctxt); |
485 | bcopy(&digest[0], (void *)addr, sizeof(digest) > l ? l : sizeof(digest)); |
486 | |
487 | FREE(state->foo, M_TEMP); |
488 | } |
489 | |
490 | static int |
491 | ah_hmac_md5_mature(struct secasvar *sav) |
492 | { |
493 | const struct ah_algorithm *algo; |
494 | |
495 | if (!sav->key_auth) { |
496 | ipseclog((LOG_ERR, "ah_hmac_md5_mature: no key is given.\n" )); |
497 | return 1; |
498 | } |
499 | |
500 | algo = ah_algorithm_lookup(sav->alg_auth); |
501 | if (!algo) { |
502 | ipseclog((LOG_ERR, "ah_hmac_md5_mature: unsupported algorithm.\n" )); |
503 | return 1; |
504 | } |
505 | |
506 | if (sav->key_auth->sadb_key_bits < algo->keymin |
507 | || algo->keymax < sav->key_auth->sadb_key_bits) { |
508 | ipseclog((LOG_ERR, |
509 | "ah_hmac_md5_mature: invalid key length %d.\n" , |
510 | sav->key_auth->sadb_key_bits)); |
511 | return 1; |
512 | } |
513 | |
514 | return 0; |
515 | } |
516 | |
517 | static int |
518 | ah_hmac_md5_init(struct ah_algorithm_state *state, struct secasvar *sav) |
519 | { |
520 | u_char *ipad; |
521 | u_char *opad; |
522 | u_char tk[16] __attribute__((aligned(4))); |
523 | u_char *key; |
524 | size_t keylen; |
525 | size_t i; |
526 | MD5_CTX *ctxt; |
527 | |
528 | if (!state) |
529 | panic("ah_hmac_md5_init: what?" ); |
530 | |
531 | state->sav = sav; |
532 | state->foo = (void *)_MALLOC(64 + 64 + sizeof(MD5_CTX), M_TEMP, M_NOWAIT); |
533 | if (!state->foo) |
534 | return ENOBUFS; |
535 | |
536 | ipad = (u_char *)state->foo; |
537 | opad = (u_char *)(ipad + 64); |
538 | ctxt = (MD5_CTX *)(void *)(opad + 64); |
539 | |
540 | /* compress the key if necessery */ |
541 | if (64 < _KEYLEN(state->sav->key_auth)) { |
542 | MD5Init(ctxt); |
543 | MD5Update(ctxt, _KEYBUF(state->sav->key_auth), |
544 | _KEYLEN(state->sav->key_auth)); |
545 | MD5Final(&tk[0], ctxt); |
546 | key = &tk[0]; |
547 | keylen = 16; |
548 | } else { |
549 | key = (u_char *) _KEYBUF(state->sav->key_auth); |
550 | keylen = _KEYLEN(state->sav->key_auth); |
551 | } |
552 | |
553 | bzero(ipad, 64); |
554 | bzero(opad, 64); |
555 | bcopy(key, ipad, keylen); |
556 | bcopy(key, opad, keylen); |
557 | for (i = 0; i < 64; i++) { |
558 | ipad[i] ^= 0x36; |
559 | opad[i] ^= 0x5c; |
560 | } |
561 | |
562 | MD5Init(ctxt); |
563 | MD5Update(ctxt, ipad, 64); |
564 | |
565 | return 0; |
566 | } |
567 | |
568 | static void |
569 | ah_hmac_md5_loop(struct ah_algorithm_state *state, caddr_t addr, size_t len) |
570 | { |
571 | MD5_CTX *ctxt; |
572 | |
573 | if (!state || !state->foo) |
574 | panic("ah_hmac_md5_loop: what?" ); |
575 | ctxt = (MD5_CTX *)(void *)(((caddr_t)state->foo) + 128); |
576 | MD5Update(ctxt, addr, len); |
577 | } |
578 | |
579 | static void |
580 | ah_hmac_md5_result(struct ah_algorithm_state *state, caddr_t addr, size_t l) |
581 | { |
582 | u_char digest[16] __attribute__((aligned(4))); |
583 | u_char *ipad; |
584 | u_char *opad; |
585 | MD5_CTX *ctxt; |
586 | |
587 | if (!state || !state->foo) |
588 | panic("ah_hmac_md5_result: what?" ); |
589 | |
590 | ipad = (u_char *)state->foo; |
591 | opad = (u_char *)(ipad + 64); |
592 | ctxt = (MD5_CTX *)(void *)(opad + 64); |
593 | |
594 | MD5Final(&digest[0], ctxt); |
595 | |
596 | MD5Init(ctxt); |
597 | MD5Update(ctxt, opad, 64); |
598 | MD5Update(ctxt, &digest[0], sizeof(digest)); |
599 | MD5Final(&digest[0], ctxt); |
600 | |
601 | bcopy(&digest[0], (void *)addr, sizeof(digest) > l ? l : sizeof(digest)); |
602 | |
603 | FREE(state->foo, M_TEMP); |
604 | } |
605 | |
606 | static int |
607 | ah_hmac_sha1_mature(struct secasvar *sav) |
608 | { |
609 | const struct ah_algorithm *algo; |
610 | |
611 | if (!sav->key_auth) { |
612 | ipseclog((LOG_ERR, "ah_hmac_sha1_mature: no key is given.\n" )); |
613 | return 1; |
614 | } |
615 | |
616 | algo = ah_algorithm_lookup(sav->alg_auth); |
617 | if (!algo) { |
618 | ipseclog((LOG_ERR, "ah_hmac_sha1_mature: unsupported algorithm.\n" )); |
619 | return 1; |
620 | } |
621 | |
622 | if (sav->key_auth->sadb_key_bits < algo->keymin |
623 | || algo->keymax < sav->key_auth->sadb_key_bits) { |
624 | ipseclog((LOG_ERR, |
625 | "ah_hmac_sha1_mature: invalid key length %d.\n" , |
626 | sav->key_auth->sadb_key_bits)); |
627 | return 1; |
628 | } |
629 | |
630 | return 0; |
631 | } |
632 | |
633 | static int |
634 | ah_hmac_sha1_init(struct ah_algorithm_state *state, struct secasvar *sav) |
635 | { |
636 | u_char *ipad; |
637 | u_char *opad; |
638 | SHA1_CTX *ctxt; |
639 | u_char tk[SHA1_RESULTLEN] __attribute__((aligned(4))); /* SHA-1 generates 160 bits */ |
640 | u_char *key; |
641 | size_t keylen; |
642 | size_t i; |
643 | |
644 | if (!state) |
645 | panic("ah_hmac_sha1_init: what?" ); |
646 | |
647 | state->sav = sav; |
648 | state->foo = (void *)_MALLOC(64 + 64 + sizeof(SHA1_CTX), |
649 | M_TEMP, M_NOWAIT); |
650 | if (!state->foo) |
651 | return ENOBUFS; |
652 | |
653 | ipad = (u_char *)state->foo; |
654 | opad = (u_char *)(ipad + 64); |
655 | ctxt = (SHA1_CTX *)(void *)(opad + 64); |
656 | |
657 | /* compress the key if necessery */ |
658 | if (64 < _KEYLEN(state->sav->key_auth)) { |
659 | SHA1Init(ctxt); |
660 | SHA1Update(ctxt, _KEYBUF(state->sav->key_auth), |
661 | _KEYLEN(state->sav->key_auth)); |
662 | SHA1Final(&tk[0], ctxt); |
663 | key = &tk[0]; |
664 | keylen = SHA1_RESULTLEN; |
665 | } else { |
666 | key = (u_char *) _KEYBUF(state->sav->key_auth); |
667 | keylen = _KEYLEN(state->sav->key_auth); |
668 | } |
669 | |
670 | bzero(ipad, 64); |
671 | bzero(opad, 64); |
672 | bcopy(key, ipad, keylen); |
673 | bcopy(key, opad, keylen); |
674 | for (i = 0; i < 64; i++) { |
675 | ipad[i] ^= 0x36; |
676 | opad[i] ^= 0x5c; |
677 | } |
678 | |
679 | SHA1Init(ctxt); |
680 | SHA1Update(ctxt, ipad, 64); |
681 | |
682 | return 0; |
683 | } |
684 | |
685 | static void |
686 | ah_hmac_sha1_loop(struct ah_algorithm_state *state, caddr_t addr, size_t len) |
687 | { |
688 | SHA1_CTX *ctxt; |
689 | |
690 | if (!state || !state->foo) |
691 | panic("ah_hmac_sha1_loop: what?" ); |
692 | |
693 | ctxt = (SHA1_CTX *)(void *)(((u_char *)state->foo) + 128); |
694 | SHA1Update(ctxt, (caddr_t)addr, (size_t)len); |
695 | } |
696 | |
697 | static void |
698 | ah_hmac_sha1_result(struct ah_algorithm_state *state, caddr_t addr, size_t l) |
699 | { |
700 | u_char digest[SHA1_RESULTLEN] __attribute__((aligned(4))); /* SHA-1 generates 160 bits */ |
701 | u_char *ipad; |
702 | u_char *opad; |
703 | SHA1_CTX *ctxt; |
704 | |
705 | if (!state || !state->foo) |
706 | panic("ah_hmac_sha1_result: what?" ); |
707 | |
708 | ipad = (u_char *)state->foo; |
709 | opad = (u_char *)(ipad + 64); |
710 | ctxt = (SHA1_CTX *)(void *)(opad + 64); |
711 | |
712 | SHA1Final((caddr_t)&digest[0], ctxt); |
713 | |
714 | SHA1Init(ctxt); |
715 | SHA1Update(ctxt, opad, 64); |
716 | SHA1Update(ctxt, (caddr_t)&digest[0], sizeof(digest)); |
717 | SHA1Final((caddr_t)&digest[0], ctxt); |
718 | |
719 | bcopy(&digest[0], (void *)addr, sizeof(digest) > l ? l : sizeof(digest)); |
720 | |
721 | FREE(state->foo, M_TEMP); |
722 | } |
723 | |
724 | #if AH_ALL_CRYPTO |
725 | static int |
726 | ah_sumsiz_sha2_256(struct secasvar *sav) |
727 | { |
728 | if (!sav) |
729 | return -1; |
730 | // return half the output size (in bytes), as per rfc 4868 |
731 | return 16; // 256/(8*2) |
732 | } |
733 | |
734 | static int |
735 | ah_hmac_sha2_256_mature(struct secasvar *sav) |
736 | { |
737 | const struct ah_algorithm *algo; |
738 | |
739 | if (!sav->key_auth) { |
740 | ipseclog((LOG_ERR, |
741 | "ah_hmac_sha2_256_mature: no key is given.\n" )); |
742 | return 1; |
743 | } |
744 | |
745 | algo = ah_algorithm_lookup(sav->alg_auth); |
746 | if (!algo) { |
747 | ipseclog((LOG_ERR, |
748 | "ah_hmac_sha2_256_mature: unsupported algorithm.\n" )); |
749 | return 1; |
750 | } |
751 | |
752 | if (sav->key_auth->sadb_key_bits < algo->keymin || |
753 | algo->keymax < sav->key_auth->sadb_key_bits) { |
754 | ipseclog((LOG_ERR, |
755 | "ah_hmac_sha2_256_mature: invalid key length %d.\n" , |
756 | sav->key_auth->sadb_key_bits)); |
757 | return 1; |
758 | } |
759 | |
760 | return 0; |
761 | } |
762 | |
763 | static int |
764 | ah_hmac_sha2_256_init(struct ah_algorithm_state *state, struct secasvar *sav) |
765 | { |
766 | u_char *ipad; |
767 | u_char *opad; |
768 | SHA256_CTX *ctxt; |
769 | u_char tk[SHA256_DIGEST_LENGTH] __attribute__((aligned(4))); |
770 | u_char *key; |
771 | size_t keylen; |
772 | size_t i; |
773 | |
774 | if (!state) |
775 | panic("ah_hmac_sha2_256_init: what?" ); |
776 | |
777 | state->sav = sav; |
778 | state->foo = (void *)_MALLOC(64 + 64 + sizeof(SHA256_CTX), |
779 | M_TEMP, M_NOWAIT); |
780 | if (!state->foo) |
781 | return ENOBUFS; |
782 | |
783 | ipad = (u_char *)state->foo; |
784 | opad = (u_char *)(ipad + 64); |
785 | ctxt = (SHA256_CTX *)(void *)(opad + 64); |
786 | |
787 | /* compress the key if necessery */ |
788 | if (64 < _KEYLEN(state->sav->key_auth)) { |
789 | bzero(tk, sizeof(tk)); |
790 | bzero(ctxt, sizeof(*ctxt)); |
791 | SHA256_Init(ctxt); |
792 | SHA256_Update(ctxt, (const u_int8_t *) _KEYBUF(state->sav->key_auth), |
793 | _KEYLEN(state->sav->key_auth)); |
794 | SHA256_Final(&tk[0], ctxt); |
795 | key = &tk[0]; |
796 | keylen = sizeof(tk) < 64 ? sizeof(tk) : 64; |
797 | } else { |
798 | key = (u_char *) _KEYBUF(state->sav->key_auth); |
799 | keylen = _KEYLEN(state->sav->key_auth); |
800 | } |
801 | |
802 | bzero(ipad, 64); |
803 | bzero(opad, 64); |
804 | bcopy(key, ipad, keylen); |
805 | bcopy(key, opad, keylen); |
806 | for (i = 0; i < 64; i++) { |
807 | ipad[i] ^= 0x36; |
808 | opad[i] ^= 0x5c; |
809 | } |
810 | |
811 | bzero(ctxt, sizeof(*ctxt)); |
812 | SHA256_Init(ctxt); |
813 | SHA256_Update(ctxt, ipad, 64); |
814 | |
815 | return 0; |
816 | } |
817 | |
818 | static void |
819 | ah_hmac_sha2_256_loop(struct ah_algorithm_state *state, |
820 | caddr_t addr, |
821 | size_t len) |
822 | { |
823 | SHA256_CTX *ctxt; |
824 | |
825 | if (!state || !state->foo) |
826 | panic("ah_hmac_sha2_256_loop: what?" ); |
827 | |
828 | ctxt = (SHA256_CTX *)(void *)(((u_char *)state->foo) + 128); |
829 | SHA256_Update(ctxt, (const u_int8_t *)addr, (size_t)len); |
830 | } |
831 | |
832 | static void |
833 | ah_hmac_sha2_256_result(struct ah_algorithm_state *state, |
834 | caddr_t addr, |
835 | size_t l) |
836 | { |
837 | u_char digest[SHA256_DIGEST_LENGTH] __attribute__((aligned(4))); |
838 | u_char *ipad; |
839 | u_char *opad; |
840 | SHA256_CTX *ctxt; |
841 | |
842 | if (!state || !state->foo) |
843 | panic("ah_hmac_sha2_256_result: what?" ); |
844 | |
845 | ipad = (u_char *)state->foo; |
846 | opad = (u_char *)(ipad + 64); |
847 | ctxt = (SHA256_CTX *)(void *)(opad + 64); |
848 | |
849 | SHA256_Final((u_int8_t *)digest, ctxt); |
850 | |
851 | SHA256_Init(ctxt); |
852 | SHA256_Update(ctxt, opad, 64); |
853 | SHA256_Update(ctxt, (const u_int8_t *)digest, sizeof(digest)); |
854 | SHA256_Final((u_int8_t *)digest, ctxt); |
855 | |
856 | bcopy(&digest[0], (void *)addr, sizeof(digest) > l ? l : sizeof(digest)); |
857 | |
858 | FREE(state->foo, M_TEMP); |
859 | } |
860 | |
861 | static int |
862 | ah_sumsiz_sha2_384(struct secasvar *sav) |
863 | { |
864 | if (!sav) |
865 | return -1; |
866 | // return half the output size (in bytes), as per rfc 4868 |
867 | return 24; // 384/(8*2) |
868 | } |
869 | |
870 | static int |
871 | ah_hmac_sha2_384_mature(struct secasvar *sav) |
872 | { |
873 | const struct ah_algorithm *algo; |
874 | |
875 | if (!sav->key_auth) { |
876 | ipseclog((LOG_ERR, |
877 | "ah_hmac_sha2_384_mature: no key is given.\n" )); |
878 | return 1; |
879 | } |
880 | |
881 | algo = ah_algorithm_lookup(sav->alg_auth); |
882 | if (!algo) { |
883 | ipseclog((LOG_ERR, |
884 | "ah_hmac_sha2_384_mature: unsupported algorithm.\n" )); |
885 | return 1; |
886 | } |
887 | |
888 | if (sav->key_auth->sadb_key_bits < algo->keymin || |
889 | algo->keymax < sav->key_auth->sadb_key_bits) { |
890 | ipseclog((LOG_ERR, |
891 | "ah_hmac_sha2_384_mature: invalid key length %d.\n" , |
892 | sav->key_auth->sadb_key_bits)); |
893 | return 1; |
894 | } |
895 | |
896 | return 0; |
897 | } |
898 | |
899 | static int |
900 | ah_hmac_sha2_384_init(struct ah_algorithm_state *state, struct secasvar *sav) |
901 | { |
902 | u_char *ipad; |
903 | u_char *opad; |
904 | SHA384_CTX *ctxt; |
905 | u_char tk[SHA384_DIGEST_LENGTH] __attribute__((aligned(4))); |
906 | u_char *key; |
907 | size_t keylen; |
908 | size_t i; |
909 | |
910 | if (!state) |
911 | panic("ah_hmac_sha2_384_init: what?" ); |
912 | |
913 | state->sav = sav; |
914 | state->foo = (void *)_MALLOC(128 + 128 + sizeof(SHA384_CTX), |
915 | M_TEMP, M_NOWAIT | M_ZERO); |
916 | if (!state->foo) |
917 | return ENOBUFS; |
918 | |
919 | ipad = (u_char *)state->foo; |
920 | opad = (u_char *)(ipad + 128); |
921 | ctxt = (SHA384_CTX *)(void *)(opad + 128); |
922 | |
923 | /* compress the key if necessery */ |
924 | if (128 < _KEYLEN(state->sav->key_auth)) { |
925 | bzero(tk, sizeof(tk)); |
926 | bzero(ctxt, sizeof(*ctxt)); |
927 | SHA384_Init(ctxt); |
928 | SHA384_Update(ctxt, (const u_int8_t *) _KEYBUF(state->sav->key_auth), |
929 | _KEYLEN(state->sav->key_auth)); |
930 | SHA384_Final(&tk[0], ctxt); |
931 | key = &tk[0]; |
932 | keylen = sizeof(tk) < 128 ? sizeof(tk) : 128; |
933 | } else { |
934 | key = (u_char *) _KEYBUF(state->sav->key_auth); |
935 | keylen = _KEYLEN(state->sav->key_auth); |
936 | } |
937 | |
938 | bzero(ipad, 128); |
939 | bzero(opad, 128); |
940 | bcopy(key, ipad, keylen); |
941 | bcopy(key, opad, keylen); |
942 | for (i = 0; i < 128; i++) { |
943 | ipad[i] ^= 0x36; |
944 | opad[i] ^= 0x5c; |
945 | } |
946 | |
947 | bzero(ctxt, sizeof(*ctxt)); |
948 | SHA384_Init(ctxt); |
949 | SHA384_Update(ctxt, ipad, 128); |
950 | |
951 | return 0; |
952 | } |
953 | |
954 | static void |
955 | ah_hmac_sha2_384_loop(struct ah_algorithm_state *state, |
956 | caddr_t addr, |
957 | size_t len) |
958 | { |
959 | SHA384_CTX *ctxt; |
960 | |
961 | if (!state || !state->foo) |
962 | panic("ah_hmac_sha2_384_loop: what?" ); |
963 | |
964 | ctxt = (SHA384_CTX *)(void *)(((u_char *)state->foo) + 256); |
965 | SHA384_Update(ctxt, (const u_int8_t *)addr, (size_t)len); |
966 | } |
967 | |
968 | static void |
969 | ah_hmac_sha2_384_result(struct ah_algorithm_state *state, |
970 | caddr_t addr, |
971 | size_t l) |
972 | { |
973 | u_char digest[SHA384_DIGEST_LENGTH]; |
974 | u_char *ipad; |
975 | u_char *opad; |
976 | SHA384_CTX *ctxt; |
977 | |
978 | if (!state || !state->foo) |
979 | panic("ah_hmac_sha2_384_result: what?" ); |
980 | |
981 | ipad = (u_char *)state->foo; |
982 | opad = (u_char *)(ipad + 128); |
983 | ctxt = (SHA384_CTX *)(void *)(opad + 128); |
984 | |
985 | SHA384_Final((u_int8_t *)digest, ctxt); |
986 | |
987 | SHA384_Init(ctxt); |
988 | SHA384_Update(ctxt, opad, 128); |
989 | SHA384_Update(ctxt, (const u_int8_t *)digest, sizeof(digest)); |
990 | SHA384_Final((u_int8_t *)digest, ctxt); |
991 | |
992 | bcopy(&digest[0], (void *)addr, sizeof(digest) > l ? l : sizeof(digest)); |
993 | |
994 | FREE(state->foo, M_TEMP); |
995 | } |
996 | |
997 | static int |
998 | ah_sumsiz_sha2_512(struct secasvar *sav) |
999 | { |
1000 | if (!sav) |
1001 | return -1; |
1002 | // return half the output size (in bytes), as per rfc 4868 |
1003 | return 32; // 512/(8*2) |
1004 | } |
1005 | |
1006 | static int |
1007 | ah_hmac_sha2_512_mature(struct secasvar *sav) |
1008 | { |
1009 | const struct ah_algorithm *algo; |
1010 | |
1011 | if (!sav->key_auth) { |
1012 | ipseclog((LOG_ERR, |
1013 | "ah_hmac_sha2_512_mature: no key is given.\n" )); |
1014 | return 1; |
1015 | } |
1016 | |
1017 | algo = ah_algorithm_lookup(sav->alg_auth); |
1018 | if (!algo) { |
1019 | ipseclog((LOG_ERR, |
1020 | "ah_hmac_sha2_512_mature: unsupported algorithm.\n" )); |
1021 | return 1; |
1022 | } |
1023 | |
1024 | if (sav->key_auth->sadb_key_bits < algo->keymin || |
1025 | algo->keymax < sav->key_auth->sadb_key_bits) { |
1026 | ipseclog((LOG_ERR, |
1027 | "ah_hmac_sha2_512_mature: invalid key length %d.\n" , |
1028 | sav->key_auth->sadb_key_bits)); |
1029 | return 1; |
1030 | } |
1031 | |
1032 | return 0; |
1033 | } |
1034 | |
1035 | static int |
1036 | ah_hmac_sha2_512_init(struct ah_algorithm_state *state, struct secasvar *sav) |
1037 | { |
1038 | u_char *ipad; |
1039 | u_char *opad; |
1040 | SHA512_CTX *ctxt; |
1041 | u_char tk[SHA512_DIGEST_LENGTH] __attribute__((aligned(4))); |
1042 | u_char *key; |
1043 | size_t keylen; |
1044 | size_t i; |
1045 | |
1046 | if (!state) |
1047 | panic("ah_hmac_sha2_512_init: what?" ); |
1048 | |
1049 | state->sav = sav; |
1050 | state->foo = (void *)_MALLOC(128 + 128 + sizeof(SHA512_CTX), |
1051 | M_TEMP, M_NOWAIT | M_ZERO); |
1052 | if (!state->foo) |
1053 | return ENOBUFS; |
1054 | |
1055 | ipad = (u_char *)state->foo; |
1056 | opad = (u_char *)(ipad + 128); |
1057 | ctxt = (SHA512_CTX *)(void *)(opad + 128); |
1058 | |
1059 | /* compress the key if necessery */ |
1060 | if (128 < _KEYLEN(state->sav->key_auth)) { |
1061 | bzero(tk, sizeof(tk)); |
1062 | bzero(ctxt, sizeof(*ctxt)); |
1063 | SHA512_Init(ctxt); |
1064 | SHA512_Update(ctxt, (const u_int8_t *) _KEYBUF(state->sav->key_auth), |
1065 | _KEYLEN(state->sav->key_auth)); |
1066 | SHA512_Final(&tk[0], ctxt); |
1067 | key = &tk[0]; |
1068 | keylen = sizeof(tk) < 128 ? sizeof(tk) : 128; |
1069 | } else { |
1070 | key = (u_char *) _KEYBUF(state->sav->key_auth); |
1071 | keylen = _KEYLEN(state->sav->key_auth); |
1072 | } |
1073 | |
1074 | bzero(ipad, 128); |
1075 | bzero(opad, 128); |
1076 | bcopy(key, ipad, keylen); |
1077 | bcopy(key, opad, keylen); |
1078 | for (i = 0; i < 128; i++) { |
1079 | ipad[i] ^= 0x36; |
1080 | opad[i] ^= 0x5c; |
1081 | } |
1082 | |
1083 | bzero(ctxt, sizeof(*ctxt)); |
1084 | SHA512_Init(ctxt); |
1085 | SHA512_Update(ctxt, ipad, 128); |
1086 | |
1087 | return 0; |
1088 | } |
1089 | |
1090 | static void |
1091 | ah_hmac_sha2_512_loop(struct ah_algorithm_state *state, |
1092 | caddr_t addr, |
1093 | size_t len) |
1094 | { |
1095 | SHA512_CTX *ctxt; |
1096 | |
1097 | if (!state || !state->foo) |
1098 | panic("ah_hmac_sha2_512_loop: what?" ); |
1099 | |
1100 | ctxt = (SHA512_CTX *)(void *)(((u_char *)state->foo) + 256); |
1101 | SHA512_Update(ctxt, (const u_int8_t *) addr, (size_t)len); |
1102 | } |
1103 | |
1104 | static void |
1105 | ah_hmac_sha2_512_result(struct ah_algorithm_state *state, |
1106 | caddr_t addr, |
1107 | size_t l) |
1108 | { |
1109 | u_char digest[SHA512_DIGEST_LENGTH] __attribute__((aligned(4))); |
1110 | u_char *ipad; |
1111 | u_char *opad; |
1112 | SHA512_CTX *ctxt; |
1113 | |
1114 | if (!state || !state->foo) |
1115 | panic("ah_hmac_sha2_512_result: what?" ); |
1116 | |
1117 | ipad = (u_char *)state->foo; |
1118 | opad = (u_char *)(ipad + 128); |
1119 | ctxt = (SHA512_CTX *)(void *)(opad + 128); |
1120 | |
1121 | SHA512_Final((u_int8_t *)digest, ctxt); |
1122 | |
1123 | SHA512_Init(ctxt); |
1124 | SHA512_Update(ctxt, opad, 128); |
1125 | SHA512_Update(ctxt, (const u_int8_t *)digest, sizeof(digest)); |
1126 | SHA512_Final((u_int8_t *)digest, ctxt); |
1127 | |
1128 | bcopy(&digest[0], (void *)addr, sizeof(digest) > l ? l : sizeof(digest)); |
1129 | |
1130 | FREE(state->foo, M_TEMP); |
1131 | } |
1132 | #endif /* AH_ALL_CRYPTO */ |
1133 | |
1134 | /*------------------------------------------------------------*/ |
1135 | |
1136 | /* |
1137 | * go generate the checksum. |
1138 | */ |
1139 | static void |
1140 | ah_update_mbuf(struct mbuf *m,int off, int len, |
1141 | const struct ah_algorithm *algo, |
1142 | struct ah_algorithm_state *algos) |
1143 | { |
1144 | struct mbuf *n; |
1145 | int tlen; |
1146 | |
1147 | /* easy case first */ |
1148 | if (off + len <= m->m_len) { |
1149 | (algo->update)(algos, mtod(m, caddr_t) + off, len); |
1150 | return; |
1151 | } |
1152 | |
1153 | for (n = m; n; n = n->m_next) { |
1154 | if (off < n->m_len) |
1155 | break; |
1156 | |
1157 | off -= n->m_len; |
1158 | } |
1159 | |
1160 | if (!n) |
1161 | panic("ah_update_mbuf: wrong offset specified" ); |
1162 | |
1163 | for (/*nothing*/; n && len > 0; n = n->m_next) { |
1164 | if (n->m_len == 0) |
1165 | continue; |
1166 | if (n->m_len - off < len) |
1167 | tlen = n->m_len - off; |
1168 | else |
1169 | tlen = len; |
1170 | |
1171 | (algo->update)(algos, mtod(n, caddr_t) + off, tlen); |
1172 | |
1173 | len -= tlen; |
1174 | off = 0; |
1175 | } |
1176 | } |
1177 | |
1178 | #if INET |
1179 | /* |
1180 | * Go generate the checksum. This function won't modify the mbuf chain |
1181 | * except AH itself. |
1182 | * |
1183 | * NOTE: the function does not free mbuf on failure. |
1184 | * Don't use m_copy(), it will try to share cluster mbuf by using refcnt. |
1185 | */ |
1186 | int |
1187 | ah4_calccksum(struct mbuf *m, caddr_t ahdat, size_t len, |
1188 | const struct ah_algorithm *algo, struct secasvar *sav) |
1189 | { |
1190 | int off; |
1191 | int hdrtype; |
1192 | size_t advancewidth; |
1193 | struct ah_algorithm_state algos; |
1194 | u_char sumbuf[AH_MAXSUMSIZE] __attribute__((aligned(4))); |
1195 | int error = 0; |
1196 | int ahseen; |
1197 | struct mbuf *n = NULL; |
1198 | |
1199 | if ((m->m_flags & M_PKTHDR) == 0) |
1200 | return EINVAL; |
1201 | |
1202 | ahseen = 0; |
1203 | hdrtype = -1; /*dummy, it is called IPPROTO_IP*/ |
1204 | |
1205 | off = 0; |
1206 | |
1207 | error = (algo->init)(&algos, sav); |
1208 | if (error) |
1209 | return error; |
1210 | |
1211 | advancewidth = 0; /*safety*/ |
1212 | |
1213 | again: |
1214 | /* gory. */ |
1215 | switch (hdrtype) { |
1216 | case -1: /*first one only*/ |
1217 | { |
1218 | /* |
1219 | * copy ip hdr, modify to fit the AH checksum rule, |
1220 | * then take a checksum. |
1221 | */ |
1222 | struct ip iphdr; |
1223 | size_t hlen; |
1224 | |
1225 | m_copydata(m, off, sizeof(iphdr), (caddr_t)&iphdr); |
1226 | #if _IP_VHL |
1227 | hlen = IP_VHL_HL(iphdr.ip_vhl) << 2; |
1228 | #else |
1229 | hlen = iphdr.ip_hl << 2; |
1230 | #endif |
1231 | iphdr.ip_ttl = 0; |
1232 | iphdr.ip_sum = htons(0); |
1233 | if (ip4_ah_cleartos) |
1234 | iphdr.ip_tos = 0; |
1235 | iphdr.ip_off = htons(ntohs(iphdr.ip_off) & ip4_ah_offsetmask); |
1236 | (algo->update)(&algos, (caddr_t)&iphdr, sizeof(struct ip)); |
1237 | |
1238 | if (hlen != sizeof(struct ip)) { |
1239 | u_char *p; |
1240 | int i, l, skip; |
1241 | |
1242 | if (hlen > MCLBYTES) { |
1243 | error = EMSGSIZE; |
1244 | goto fail; |
1245 | } |
1246 | MGET(n, M_DONTWAIT, MT_DATA); |
1247 | if (n && hlen > MLEN) { |
1248 | MCLGET(n, M_DONTWAIT); |
1249 | if ((n->m_flags & M_EXT) == 0) { |
1250 | m_free(n); |
1251 | n = NULL; |
1252 | } |
1253 | } |
1254 | if (n == NULL) { |
1255 | error = ENOBUFS; |
1256 | goto fail; |
1257 | } |
1258 | m_copydata(m, off, hlen, mtod(n, caddr_t)); |
1259 | |
1260 | /* |
1261 | * IP options processing. |
1262 | * See RFC2402 appendix A. |
1263 | */ |
1264 | p = mtod(n, u_char *); |
1265 | i = sizeof(struct ip); |
1266 | while (i < hlen) { |
1267 | if (i + IPOPT_OPTVAL >= hlen) { |
1268 | ipseclog((LOG_ERR, "ah4_calccksum: " |
1269 | "invalid IP option\n" )); |
1270 | error = EINVAL; |
1271 | goto fail; |
1272 | } |
1273 | if (p[i + IPOPT_OPTVAL] == IPOPT_EOL || |
1274 | p[i + IPOPT_OPTVAL] == IPOPT_NOP || |
1275 | i + IPOPT_OLEN < hlen) |
1276 | ; |
1277 | else { |
1278 | ipseclog((LOG_ERR, |
1279 | "ah4_calccksum: invalid IP option " |
1280 | "(type=%02x)\n" , |
1281 | p[i + IPOPT_OPTVAL])); |
1282 | error = EINVAL; |
1283 | goto fail; |
1284 | } |
1285 | |
1286 | skip = 1; |
1287 | switch (p[i + IPOPT_OPTVAL]) { |
1288 | case IPOPT_EOL: |
1289 | case IPOPT_NOP: |
1290 | l = 1; |
1291 | skip = 0; |
1292 | break; |
1293 | case IPOPT_SECURITY: /* 0x82 */ |
1294 | case 0x85: /* Extended security */ |
1295 | case 0x86: /* Commercial security */ |
1296 | case 0x94: /* Router alert */ |
1297 | case 0x95: /* RFC1770 */ |
1298 | l = p[i + IPOPT_OLEN]; |
1299 | if (l < 2) |
1300 | goto invalopt; |
1301 | skip = 0; |
1302 | break; |
1303 | default: |
1304 | l = p[i + IPOPT_OLEN]; |
1305 | if (l < 2) |
1306 | goto invalopt; |
1307 | skip = 1; |
1308 | break; |
1309 | } |
1310 | if (l < 1 || hlen - i < l) { |
1311 | invalopt: |
1312 | ipseclog((LOG_ERR, |
1313 | "ah4_calccksum: invalid IP option " |
1314 | "(type=%02x len=%02x)\n" , |
1315 | p[i + IPOPT_OPTVAL], |
1316 | p[i + IPOPT_OLEN])); |
1317 | error = EINVAL; |
1318 | goto fail; |
1319 | } |
1320 | if (skip) |
1321 | bzero(p + i, l); |
1322 | if (p[i + IPOPT_OPTVAL] == IPOPT_EOL) |
1323 | break; |
1324 | i += l; |
1325 | } |
1326 | |
1327 | p = mtod(n, u_char *) + sizeof(struct ip); |
1328 | (algo->update)(&algos, (caddr_t)p, hlen - sizeof(struct ip)); |
1329 | |
1330 | m_free(n); |
1331 | n = NULL; |
1332 | } |
1333 | |
1334 | hdrtype = (iphdr.ip_p) & 0xff; |
1335 | advancewidth = hlen; |
1336 | break; |
1337 | } |
1338 | |
1339 | case IPPROTO_AH: |
1340 | { |
1341 | struct ah ah; |
1342 | int siz; |
1343 | int hdrsiz; |
1344 | int totlen; |
1345 | |
1346 | m_copydata(m, off, sizeof(ah), (caddr_t)&ah); |
1347 | hdrsiz = (sav->flags & SADB_X_EXT_OLD) |
1348 | ? sizeof(struct ah) |
1349 | : sizeof(struct newah); |
1350 | siz = (*algo->sumsiz)(sav); |
1351 | totlen = (ah.ah_len + 2) << 2; |
1352 | |
1353 | /* |
1354 | * special treatment is necessary for the first one, not others |
1355 | */ |
1356 | if (!ahseen) { |
1357 | if (totlen > m->m_pkthdr.len - off || |
1358 | totlen > MCLBYTES) { |
1359 | error = EMSGSIZE; |
1360 | goto fail; |
1361 | } |
1362 | MGET(n, M_DONTWAIT, MT_DATA); |
1363 | if (n && totlen > MLEN) { |
1364 | MCLGET(n, M_DONTWAIT); |
1365 | if ((n->m_flags & M_EXT) == 0) { |
1366 | m_free(n); |
1367 | n = NULL; |
1368 | } |
1369 | } |
1370 | if (n == NULL) { |
1371 | error = ENOBUFS; |
1372 | goto fail; |
1373 | } |
1374 | m_copydata(m, off, totlen, mtod(n, caddr_t)); |
1375 | n->m_len = totlen; |
1376 | bzero(mtod(n, caddr_t) + hdrsiz, siz); |
1377 | (algo->update)(&algos, mtod(n, caddr_t), n->m_len); |
1378 | m_free(n); |
1379 | n = NULL; |
1380 | } else |
1381 | ah_update_mbuf(m, off, totlen, algo, &algos); |
1382 | ahseen++; |
1383 | |
1384 | hdrtype = ah.ah_nxt; |
1385 | advancewidth = totlen; |
1386 | break; |
1387 | } |
1388 | |
1389 | default: |
1390 | ah_update_mbuf(m, off, m->m_pkthdr.len - off, algo, &algos); |
1391 | advancewidth = m->m_pkthdr.len - off; |
1392 | break; |
1393 | } |
1394 | |
1395 | off += advancewidth; |
1396 | if (off < m->m_pkthdr.len) |
1397 | goto again; |
1398 | |
1399 | if (len < (*algo->sumsiz)(sav)) { |
1400 | error = EINVAL; |
1401 | goto fail; |
1402 | } |
1403 | |
1404 | (algo->result)(&algos, (caddr_t) &sumbuf[0], sizeof(sumbuf)); |
1405 | bcopy(&sumbuf[0], ahdat, (*algo->sumsiz)(sav)); |
1406 | |
1407 | if (n) |
1408 | m_free(n); |
1409 | return error; |
1410 | |
1411 | fail: |
1412 | if (n) |
1413 | m_free(n); |
1414 | return error; |
1415 | } |
1416 | #endif |
1417 | |
1418 | #if INET6 |
1419 | /* |
1420 | * Go generate the checksum. This function won't modify the mbuf chain |
1421 | * except AH itself. |
1422 | * |
1423 | * NOTE: the function does not free mbuf on failure. |
1424 | * Don't use m_copy(), it will try to share cluster mbuf by using refcnt. |
1425 | */ |
1426 | int |
1427 | ah6_calccksum(struct mbuf *m, caddr_t ahdat, size_t len, |
1428 | const struct ah_algorithm *algo, struct secasvar *sav) |
1429 | { |
1430 | int newoff, off; |
1431 | int proto, nxt; |
1432 | struct mbuf *n = NULL; |
1433 | int error; |
1434 | int ahseen; |
1435 | struct ah_algorithm_state algos; |
1436 | u_char sumbuf[AH_MAXSUMSIZE] __attribute__((aligned(4))); |
1437 | |
1438 | if ((m->m_flags & M_PKTHDR) == 0) |
1439 | return EINVAL; |
1440 | |
1441 | error = (algo->init)(&algos, sav); |
1442 | if (error) |
1443 | return error; |
1444 | |
1445 | off = 0; |
1446 | proto = IPPROTO_IPV6; |
1447 | nxt = -1; |
1448 | ahseen = 0; |
1449 | |
1450 | again: |
1451 | newoff = ip6_nexthdr(m, off, proto, &nxt); |
1452 | if (newoff < 0) |
1453 | newoff = m->m_pkthdr.len; |
1454 | else if (newoff <= off) { |
1455 | error = EINVAL; |
1456 | goto fail; |
1457 | } |
1458 | |
1459 | switch (proto) { |
1460 | case IPPROTO_IPV6: |
1461 | /* |
1462 | * special treatment is necessary for the first one, not others |
1463 | */ |
1464 | if (off == 0) { |
1465 | struct ip6_hdr ip6copy; |
1466 | |
1467 | if (newoff - off != sizeof(struct ip6_hdr)) { |
1468 | error = EINVAL; |
1469 | goto fail; |
1470 | } |
1471 | |
1472 | m_copydata(m, off, newoff - off, (caddr_t)&ip6copy); |
1473 | /* RFC2402 */ |
1474 | ip6copy.ip6_flow = 0; |
1475 | ip6copy.ip6_vfc &= ~IPV6_VERSION_MASK; |
1476 | ip6copy.ip6_vfc |= IPV6_VERSION; |
1477 | ip6copy.ip6_hlim = 0; |
1478 | if (IN6_IS_ADDR_LINKLOCAL(&ip6copy.ip6_src)) |
1479 | ip6copy.ip6_src.s6_addr16[1] = 0x0000; |
1480 | if (IN6_IS_ADDR_LINKLOCAL(&ip6copy.ip6_dst)) |
1481 | ip6copy.ip6_dst.s6_addr16[1] = 0x0000; |
1482 | (algo->update)(&algos, (caddr_t)&ip6copy, |
1483 | sizeof(struct ip6_hdr)); |
1484 | } else { |
1485 | newoff = m->m_pkthdr.len; |
1486 | ah_update_mbuf(m, off, m->m_pkthdr.len - off, algo, |
1487 | &algos); |
1488 | } |
1489 | break; |
1490 | |
1491 | case IPPROTO_AH: |
1492 | { |
1493 | int siz; |
1494 | int hdrsiz; |
1495 | |
1496 | hdrsiz = (sav->flags & SADB_X_EXT_OLD) |
1497 | ? sizeof(struct ah) |
1498 | : sizeof(struct newah); |
1499 | siz = (*algo->sumsiz)(sav); |
1500 | |
1501 | /* |
1502 | * special treatment is necessary for the first one, not others |
1503 | */ |
1504 | if (!ahseen) { |
1505 | if (newoff - off > MCLBYTES) { |
1506 | error = EMSGSIZE; |
1507 | goto fail; |
1508 | } |
1509 | MGET(n, M_DONTWAIT, MT_DATA); |
1510 | if (n && newoff - off > MLEN) { |
1511 | MCLGET(n, M_DONTWAIT); |
1512 | if ((n->m_flags & M_EXT) == 0) { |
1513 | m_free(n); |
1514 | n = NULL; |
1515 | } |
1516 | } |
1517 | if (n == NULL) { |
1518 | error = ENOBUFS; |
1519 | goto fail; |
1520 | } |
1521 | m_copydata(m, off, newoff - off, mtod(n, caddr_t)); |
1522 | n->m_len = newoff - off; |
1523 | bzero(mtod(n, caddr_t) + hdrsiz, siz); |
1524 | (algo->update)(&algos, mtod(n, caddr_t), n->m_len); |
1525 | m_free(n); |
1526 | n = NULL; |
1527 | } else |
1528 | ah_update_mbuf(m, off, newoff - off, algo, &algos); |
1529 | ahseen++; |
1530 | break; |
1531 | } |
1532 | |
1533 | case IPPROTO_HOPOPTS: |
1534 | case IPPROTO_DSTOPTS: |
1535 | { |
1536 | struct ip6_ext *ip6e; |
1537 | int hdrlen, optlen; |
1538 | u_int8_t *p, *optend, *optp; |
1539 | |
1540 | if (newoff - off > MCLBYTES) { |
1541 | error = EMSGSIZE; |
1542 | goto fail; |
1543 | } |
1544 | MGET(n, M_DONTWAIT, MT_DATA); |
1545 | if (n && newoff - off > MLEN) { |
1546 | MCLGET(n, M_DONTWAIT); |
1547 | if ((n->m_flags & M_EXT) == 0) { |
1548 | m_free(n); |
1549 | n = NULL; |
1550 | } |
1551 | } |
1552 | if (n == NULL) { |
1553 | error = ENOBUFS; |
1554 | goto fail; |
1555 | } |
1556 | m_copydata(m, off, newoff - off, mtod(n, caddr_t)); |
1557 | n->m_len = newoff - off; |
1558 | |
1559 | ip6e = mtod(n, struct ip6_ext *); |
1560 | hdrlen = (ip6e->ip6e_len + 1) << 3; |
1561 | if (newoff - off < hdrlen) { |
1562 | error = EINVAL; |
1563 | m_free(n); |
1564 | n = NULL; |
1565 | goto fail; |
1566 | } |
1567 | p = mtod(n, u_int8_t *); |
1568 | optend = p + hdrlen; |
1569 | |
1570 | /* |
1571 | * ICV calculation for the options header including all |
1572 | * options. This part is a little tricky since there are |
1573 | * two type of options; mutable and immutable. We try to |
1574 | * null-out mutable ones here. |
1575 | */ |
1576 | optp = p + 2; |
1577 | while (optp < optend) { |
1578 | if (optp[0] == IP6OPT_PAD1) |
1579 | optlen = 1; |
1580 | else { |
1581 | if (optp + 2 > optend) { |
1582 | error = EINVAL; |
1583 | m_free(n); |
1584 | n = NULL; |
1585 | goto fail; |
1586 | } |
1587 | optlen = optp[1] + 2; |
1588 | |
1589 | if (optp[0] & IP6OPT_MUTABLE) |
1590 | bzero(optp + 2, optlen - 2); |
1591 | } |
1592 | |
1593 | optp += optlen; |
1594 | } |
1595 | |
1596 | (algo->update)(&algos, mtod(n, caddr_t), n->m_len); |
1597 | m_free(n); |
1598 | n = NULL; |
1599 | break; |
1600 | } |
1601 | |
1602 | case IPPROTO_ROUTING: |
1603 | /* |
1604 | * For an input packet, we can just calculate `as is'. |
1605 | * For an output packet, we assume ip6_output have already |
1606 | * made packet how it will be received at the final |
1607 | * destination. |
1608 | */ |
1609 | /* FALLTHROUGH */ |
1610 | |
1611 | default: |
1612 | ah_update_mbuf(m, off, newoff - off, algo, &algos); |
1613 | break; |
1614 | } |
1615 | |
1616 | if (newoff < m->m_pkthdr.len) { |
1617 | proto = nxt; |
1618 | off = newoff; |
1619 | goto again; |
1620 | } |
1621 | |
1622 | if (len < (*algo->sumsiz)(sav)) { |
1623 | error = EINVAL; |
1624 | goto fail; |
1625 | } |
1626 | |
1627 | (algo->result)(&algos, (caddr_t) &sumbuf[0], sizeof(sumbuf)); |
1628 | bcopy(&sumbuf[0], ahdat, (*algo->sumsiz)(sav)); |
1629 | |
1630 | /* just in case */ |
1631 | if (n) |
1632 | m_free(n); |
1633 | return 0; |
1634 | fail: |
1635 | /* just in case */ |
1636 | if (n) |
1637 | m_free(n); |
1638 | return error; |
1639 | } |
1640 | #endif |
1641 | |