]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet6/esp_core.c
xnu-1699.22.73.tar.gz
[apple/xnu.git] / bsd / netinet6 / esp_core.c
CommitLineData
b0d623f7
A
1/*
2 * Copyright (c) 2008 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
55e303ae 29/* $FreeBSD: src/sys/netinet6/esp_core.c,v 1.1.2.4 2002/03/26 10:12:29 ume Exp $ */
9bccf70c 30/* $KAME: esp_core.c,v 1.50 2000/11/02 12:27:38 itojun Exp $ */
1c79356b
A
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#define _IP_VHL
1c79356b
A
62
63#include <sys/param.h>
64#include <sys/systm.h>
65#include <sys/malloc.h>
66#include <sys/mbuf.h>
67#include <sys/domain.h>
68#include <sys/protosw.h>
69#include <sys/socket.h>
70#include <sys/errno.h>
71#include <sys/time.h>
72#include <sys/kernel.h>
73#include <sys/syslog.h>
74
91447636
A
75#include <kern/locks.h>
76
1c79356b
A
77#include <net/if.h>
78#include <net/route.h>
79
80#include <netinet/in.h>
81#include <netinet/in_var.h>
82#if INET6
83#include <netinet/ip6.h>
84#include <netinet6/ip6_var.h>
85#include <netinet/icmp6.h>
86#endif
87
88#include <netinet6/ipsec.h>
9bccf70c
A
89#if INET6
90#include <netinet6/ipsec6.h>
91#endif
1c79356b 92#include <netinet6/ah.h>
9bccf70c
A
93#if INET6
94#include <netinet6/ah6.h>
95#endif
1c79356b 96#include <netinet6/esp.h>
9bccf70c
A
97#if INET6
98#include <netinet6/esp6.h>
99#endif
100#include <netinet6/esp_rijndael.h>
1c79356b
A
101#include <net/pfkeyv2.h>
102#include <netkey/keydb.h>
9bccf70c 103#include <netkey/key.h>
1c79356b
A
104#include <crypto/des/des.h>
105#include <crypto/blowfish/blowfish.h>
106#include <crypto/cast128/cast128.h>
1c79356b
A
107
108#include <net/net_osdep.h>
109
55e303ae
A
110#include <sys/kdebug.h>
111#define DBG_LAYER_BEG NETDBG_CODE(DBG_NETIPSEC, 1)
112#define DBG_LAYER_END NETDBG_CODE(DBG_NETIPSEC, 3)
113#define DBG_FNC_ESPAUTH NETDBG_CODE(DBG_NETIPSEC, (8 << 8))
114
91447636
A
115extern lck_mtx_t *sadb_mutex;
116
117static int esp_null_mature(struct secasvar *);
118static int esp_null_decrypt(struct mbuf *, size_t,
119 struct secasvar *, const struct esp_algorithm *, int);
120static int esp_null_encrypt(struct mbuf *, size_t, size_t,
121 struct secasvar *, const struct esp_algorithm *, int);
122static int esp_descbc_mature(struct secasvar *);
123static int esp_descbc_ivlen(const struct esp_algorithm *,
124 struct secasvar *);
125static int esp_des_schedule(const struct esp_algorithm *,
126 struct secasvar *);
127static int esp_des_schedlen(const struct esp_algorithm *);
128static int esp_des_blockdecrypt(const struct esp_algorithm *,
129 struct secasvar *, u_int8_t *, u_int8_t *);
130static int esp_des_blockencrypt(const struct esp_algorithm *,
131 struct secasvar *, u_int8_t *, u_int8_t *);
132static int esp_cbc_mature(struct secasvar *);
2d21ac55 133#if ALLCRYPTO
91447636
A
134static int esp_blowfish_schedule(const struct esp_algorithm *,
135 struct secasvar *);
136static int esp_blowfish_schedlen(const struct esp_algorithm *);
137static int esp_blowfish_blockdecrypt(const struct esp_algorithm *,
138 struct secasvar *, u_int8_t *, u_int8_t *);
139static int esp_blowfish_blockencrypt(const struct esp_algorithm *,
140 struct secasvar *, u_int8_t *, u_int8_t *);
141static int esp_cast128_schedule(const struct esp_algorithm *,
142 struct secasvar *);
143static int esp_cast128_schedlen(const struct esp_algorithm *);
144static int esp_cast128_blockdecrypt(const struct esp_algorithm *,
145 struct secasvar *, u_int8_t *, u_int8_t *);
146static int esp_cast128_blockencrypt(const struct esp_algorithm *,
147 struct secasvar *, u_int8_t *, u_int8_t *);
2d21ac55 148#endif /* ALLCRYPTO */
91447636
A
149static int esp_3des_schedule(const struct esp_algorithm *,
150 struct secasvar *);
151static int esp_3des_schedlen(const struct esp_algorithm *);
152static int esp_3des_blockdecrypt(const struct esp_algorithm *,
153 struct secasvar *, u_int8_t *, u_int8_t *);
154static int esp_3des_blockencrypt(const struct esp_algorithm *,
155 struct secasvar *, u_int8_t *, u_int8_t *);
156static int esp_common_ivlen(const struct esp_algorithm *,
157 struct secasvar *);
158static int esp_cbc_decrypt(struct mbuf *, size_t,
159 struct secasvar *, const struct esp_algorithm *, int);
160static int esp_cbc_encrypt(struct mbuf *, size_t, size_t,
161 struct secasvar *, const struct esp_algorithm *, int);
9bccf70c
A
162
163#define MAXIVLEN 16
164
2d21ac55 165static const struct esp_algorithm des_cbc =
9bccf70c
A
166 { 8, -1, esp_descbc_mature, 64, 64, esp_des_schedlen,
167 "des-cbc",
168 esp_descbc_ivlen, esp_cbc_decrypt,
169 esp_cbc_encrypt, esp_des_schedule,
2d21ac55
A
170 esp_des_blockdecrypt, esp_des_blockencrypt, };
171static const struct esp_algorithm des3_cbc =
9bccf70c
A
172 { 8, 8, esp_cbc_mature, 192, 192, esp_3des_schedlen,
173 "3des-cbc",
174 esp_common_ivlen, esp_cbc_decrypt,
175 esp_cbc_encrypt, esp_3des_schedule,
2d21ac55
A
176 esp_3des_blockdecrypt, esp_3des_blockencrypt, };
177static const struct esp_algorithm null_esp =
9bccf70c
A
178 { 1, 0, esp_null_mature, 0, 2048, 0, "null",
179 esp_common_ivlen, esp_null_decrypt,
2d21ac55
A
180 esp_null_encrypt, NULL, NULL, NULL };
181#if ALLCRYPTO
182static const struct esp_algorithm blowfish_cbc =
9bccf70c
A
183 { 8, 8, esp_cbc_mature, 40, 448, esp_blowfish_schedlen, "blowfish-cbc",
184 esp_common_ivlen, esp_cbc_decrypt,
185 esp_cbc_encrypt, esp_blowfish_schedule,
2d21ac55
A
186 esp_blowfish_blockdecrypt, esp_blowfish_blockencrypt, };
187static const struct esp_algorithm cast128_cbc =
9bccf70c
A
188 { 8, 8, esp_cbc_mature, 40, 128, esp_cast128_schedlen,
189 "cast128-cbc",
190 esp_common_ivlen, esp_cbc_decrypt,
191 esp_cbc_encrypt, esp_cast128_schedule,
2d21ac55
A
192 esp_cast128_blockdecrypt, esp_cast128_blockencrypt, };
193#endif /* ALLCRYPTO */
194static const struct esp_algorithm aes_cbc =
91447636
A
195 { 16, 16, esp_cbc_mature, 128, 256, esp_aes_schedlen,
196 "aes-cbc",
197 esp_common_ivlen, esp_cbc_decrypt_aes,
198 esp_cbc_encrypt_aes, esp_aes_schedule,
2d21ac55
A
199 0, 0 };
200
201static const struct esp_algorithm *esp_algorithms[] = {
202 &des_cbc,
203 &des3_cbc,
204 &null_esp,
205#if ALLCRYPTO
206 &blowfish_cbc,
207 &cast128_cbc,
208#endif /* ALLCRYPTO */
209 &aes_cbc
1c79356b
A
210};
211
9bccf70c
A
212const struct esp_algorithm *
213esp_algorithm_lookup(idx)
214 int idx;
215{
1c79356b 216
9bccf70c
A
217 switch (idx) {
218 case SADB_EALG_DESCBC:
2d21ac55 219 return &des_cbc;
9bccf70c 220 case SADB_EALG_3DESCBC:
2d21ac55 221 return &des3_cbc;
9bccf70c 222 case SADB_EALG_NULL:
2d21ac55
A
223 return &null_esp;
224#if ALLCRYPTO
9bccf70c 225 case SADB_X_EALG_BLOWFISHCBC:
2d21ac55 226 return &blowfish_cbc;
9bccf70c 227 case SADB_X_EALG_CAST128CBC:
2d21ac55
A
228 return &cast128_cbc;
229#endif /* ALLCRYPTO */
9bccf70c 230 case SADB_X_EALG_RIJNDAELCBC:
2d21ac55 231 return &aes_cbc;
9bccf70c
A
232 default:
233 return NULL;
234 }
235}
236
237int
238esp_max_ivlen()
239{
240 int idx;
241 int ivlen;
242
243 ivlen = 0;
244 for (idx = 0; idx < sizeof(esp_algorithms)/sizeof(esp_algorithms[0]);
245 idx++) {
2d21ac55
A
246 if (esp_algorithms[idx]->ivlenval > ivlen)
247 ivlen = esp_algorithms[idx]->ivlenval;
9bccf70c
A
248 }
249
250 return ivlen;
251}
252
253int
254esp_schedule(algo, sav)
255 const struct esp_algorithm *algo;
1c79356b
A
256 struct secasvar *sav;
257{
9bccf70c
A
258 int error;
259
260 /* check for key length */
261 if (_KEYBITS(sav->key_enc) < algo->keymin ||
262 _KEYBITS(sav->key_enc) > algo->keymax) {
263 ipseclog((LOG_ERR,
264 "esp_schedule %s: unsupported key length %d: "
265 "needs %d to %d bits\n", algo->name, _KEYBITS(sav->key_enc),
266 algo->keymin, algo->keymax));
267 return EINVAL;
268 }
269
2d21ac55 270 lck_mtx_lock(sadb_mutex);
9bccf70c 271 /* already allocated */
2d21ac55
A
272 if (sav->sched && sav->schedlen != 0) {
273 lck_mtx_unlock(sadb_mutex);
9bccf70c 274 return 0;
2d21ac55 275 }
9bccf70c 276 /* no schedule necessary */
2d21ac55
A
277 if (!algo->schedule || !algo->schedlen) {
278 lck_mtx_unlock(sadb_mutex);
9bccf70c 279 return 0;
2d21ac55 280 }
b0d623f7 281
9bccf70c 282 sav->schedlen = (*algo->schedlen)(algo);
b0d623f7 283 if ((signed) sav->schedlen < 0) {
2d21ac55 284 lck_mtx_unlock(sadb_mutex);
9bccf70c 285 return EINVAL;
2d21ac55 286 }
55e303ae
A
287
288//#### that malloc should be replaced by a saved buffer...
9bccf70c
A
289 sav->sched = _MALLOC(sav->schedlen, M_SECA, M_DONTWAIT);
290 if (!sav->sched) {
291 sav->schedlen = 0;
2d21ac55 292 lck_mtx_unlock(sadb_mutex);
9bccf70c
A
293 return ENOBUFS;
294 }
295
296 error = (*algo->schedule)(algo, sav);
297 if (error) {
298 ipseclog((LOG_ERR, "esp_schedule %s: error %d\n",
299 algo->name, error));
55e303ae 300 bzero(sav->sched, sav->schedlen);
9bccf70c
A
301 FREE(sav->sched, M_SECA);
302 sav->sched = NULL;
303 sav->schedlen = 0;
304 }
2d21ac55 305 lck_mtx_unlock(sadb_mutex);
9bccf70c 306 return error;
1c79356b
A
307}
308
309static int
2d21ac55
A
310esp_null_mature(
311 __unused struct secasvar *sav)
1c79356b 312{
9bccf70c
A
313
314 /* anything is okay */
1c79356b
A
315 return 0;
316}
317
318static int
2d21ac55
A
319esp_null_decrypt(
320 __unused struct mbuf *m,
321 __unused size_t off, /* offset to ESP header */
322 __unused struct secasvar *sav,
323 __unused const struct esp_algorithm *algo,
324 __unused int ivlen)
1c79356b 325{
9bccf70c 326
1c79356b
A
327 return 0; /* do nothing */
328}
329
330static int
2d21ac55
A
331esp_null_encrypt(
332 __unused struct mbuf *m,
333 __unused size_t off, /* offset to ESP header */
334 __unused size_t plen, /* payload length (to be encrypted) */
335 __unused struct secasvar *sav,
336 __unused const struct esp_algorithm *algo,
337 __unused int ivlen)
1c79356b 338{
9bccf70c 339
1c79356b
A
340 return 0; /* do nothing */
341}
342
343static int
344esp_descbc_mature(sav)
345 struct secasvar *sav;
346{
9bccf70c 347 const struct esp_algorithm *algo;
1c79356b
A
348
349 if (!(sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_IV4B)) {
350 ipseclog((LOG_ERR, "esp_cbc_mature: "
351 "algorithm incompatible with 4 octets IV length\n"));
352 return 1;
353 }
354
355 if (!sav->key_enc) {
356 ipseclog((LOG_ERR, "esp_descbc_mature: no key is given.\n"));
357 return 1;
358 }
9bccf70c
A
359
360 algo = esp_algorithm_lookup(sav->alg_enc);
361 if (!algo) {
362 ipseclog((LOG_ERR,
363 "esp_descbc_mature: unsupported algorithm.\n"));
364 return 1;
365 }
366
367 if (_KEYBITS(sav->key_enc) < algo->keymin ||
368 _KEYBITS(sav->key_enc) > algo->keymax) {
1c79356b
A
369 ipseclog((LOG_ERR,
370 "esp_descbc_mature: invalid key length %d.\n",
371 _KEYBITS(sav->key_enc)));
372 return 1;
373 }
374
375 /* weak key check */
9bccf70c 376 if (des_is_weak_key((des_cblock *)_KEYBUF(sav->key_enc))) {
1c79356b
A
377 ipseclog((LOG_ERR,
378 "esp_descbc_mature: weak key was passed.\n"));
379 return 1;
380 }
381
382 return 0;
383}
384
385static int
2d21ac55
A
386esp_descbc_ivlen(
387 __unused const struct esp_algorithm *algo,
388 struct secasvar *sav)
1c79356b 389{
1c79356b 390
9bccf70c 391 if (!sav)
1c79356b 392 return 8;
9bccf70c
A
393 if ((sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_IV4B))
394 return 4;
395 if (!(sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_DERIV))
396 return 4;
397 return 8;
1c79356b
A
398}
399
400static int
2d21ac55
A
401esp_des_schedlen(
402 __unused const struct esp_algorithm *algo)
1c79356b 403{
1c79356b 404
9bccf70c
A
405 return sizeof(des_key_schedule);
406}
1c79356b 407
9bccf70c 408static int
2d21ac55
A
409esp_des_schedule(
410 __unused const struct esp_algorithm *algo,
411 struct secasvar *sav)
9bccf70c 412{
1c79356b 413
2d21ac55 414 lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
9bccf70c
A
415 if (des_key_sched((des_cblock *)_KEYBUF(sav->key_enc),
416 *(des_key_schedule *)sav->sched))
1c79356b 417 return EINVAL;
9bccf70c
A
418 else
419 return 0;
420}
1c79356b 421
9bccf70c 422static int
2d21ac55
A
423esp_des_blockdecrypt(
424 __unused const struct esp_algorithm *algo,
425 struct secasvar *sav,
426 u_int8_t *s,
427 u_int8_t *d)
9bccf70c 428{
1c79356b 429
9bccf70c
A
430 /* assumption: d has a good alignment */
431 bcopy(s, d, sizeof(DES_LONG) * 2);
432 des_ecb_encrypt((des_cblock *)d, (des_cblock *)d,
433 *(des_key_schedule *)sav->sched, DES_DECRYPT);
1c79356b
A
434 return 0;
435}
436
437static int
2d21ac55
A
438esp_des_blockencrypt(
439 __unused const struct esp_algorithm *algo,
440 struct secasvar *sav,
441 u_int8_t *s,
442 u_int8_t *d)
1c79356b 443{
1c79356b 444
9bccf70c
A
445 /* assumption: d has a good alignment */
446 bcopy(s, d, sizeof(DES_LONG) * 2);
447 des_ecb_encrypt((des_cblock *)d, (des_cblock *)d,
448 *(des_key_schedule *)sav->sched, DES_ENCRYPT);
1c79356b
A
449 return 0;
450}
451
452static int
453esp_cbc_mature(sav)
454 struct secasvar *sav;
455{
456 int keylen;
9bccf70c 457 const struct esp_algorithm *algo;
1c79356b
A
458
459 if (sav->flags & SADB_X_EXT_OLD) {
460 ipseclog((LOG_ERR,
461 "esp_cbc_mature: algorithm incompatible with esp-old\n"));
462 return 1;
463 }
464 if (sav->flags & SADB_X_EXT_DERIV) {
465 ipseclog((LOG_ERR,
466 "esp_cbc_mature: algorithm incompatible with derived\n"));
467 return 1;
468 }
469
470 if (!sav->key_enc) {
9bccf70c
A
471 ipseclog((LOG_ERR, "esp_cbc_mature: no key is given.\n"));
472 return 1;
473 }
474
475 algo = esp_algorithm_lookup(sav->alg_enc);
476 if (!algo) {
1c79356b 477 ipseclog((LOG_ERR,
9bccf70c 478 "esp_cbc_mature %s: unsupported algorithm.\n", algo->name));
1c79356b
A
479 return 1;
480 }
9bccf70c 481
1c79356b
A
482 keylen = sav->key_enc->sadb_key_bits;
483 if (keylen < algo->keymin || algo->keymax < keylen) {
9bccf70c
A
484 ipseclog((LOG_ERR,
485 "esp_cbc_mature %s: invalid key length %d.\n",
486 algo->name, sav->key_enc->sadb_key_bits));
1c79356b
A
487 return 1;
488 }
489 switch (sav->alg_enc) {
490 case SADB_EALG_3DESCBC:
491 /* weak key check */
9bccf70c
A
492 if (des_is_weak_key((des_cblock *)_KEYBUF(sav->key_enc)) ||
493 des_is_weak_key((des_cblock *)(_KEYBUF(sav->key_enc) + 8)) ||
494 des_is_weak_key((des_cblock *)(_KEYBUF(sav->key_enc) + 16))) {
1c79356b 495 ipseclog((LOG_ERR,
9bccf70c
A
496 "esp_cbc_mature %s: weak key was passed.\n",
497 algo->name));
1c79356b
A
498 return 1;
499 }
500 break;
9bccf70c
A
501 case SADB_X_EALG_BLOWFISHCBC:
502 case SADB_X_EALG_CAST128CBC:
503 break;
504 case SADB_X_EALG_RIJNDAELCBC:
505 /* allows specific key sizes only */
506 if (!(keylen == 128 || keylen == 192 || keylen == 256)) {
507 ipseclog((LOG_ERR,
508 "esp_cbc_mature %s: invalid key length %d.\n",
509 algo->name, keylen));
510 return 1;
511 }
1c79356b
A
512 break;
513 }
514
515 return 0;
516}
517
2d21ac55 518#if ALLCRYPTO
1c79356b 519static int
2d21ac55
A
520esp_blowfish_schedlen(
521 __unused const struct esp_algorithm *algo)
1c79356b 522{
1c79356b 523
9bccf70c 524 return sizeof(BF_KEY);
1c79356b
A
525}
526
527static int
2d21ac55
A
528esp_blowfish_schedule(
529 __unused const struct esp_algorithm *algo,
530 struct secasvar *sav)
1c79356b 531{
1c79356b 532
2d21ac55 533 lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
9bccf70c 534 BF_set_key((BF_KEY *)sav->sched, _KEYLEN(sav->key_enc),
b0d623f7 535 (u_int8_t *) _KEYBUF(sav->key_enc));
1c79356b
A
536 return 0;
537}
538
539static int
2d21ac55
A
540esp_blowfish_blockdecrypt(
541 __unused const struct esp_algorithm *algo,
542 struct secasvar *sav,
543 u_int8_t *s,
544 u_int8_t *d)
1c79356b 545{
55e303ae 546 /* HOLY COW! BF_decrypt() takes values in host byteorder */
9bccf70c
A
547 BF_LONG t[2];
548
549 bcopy(s, t, sizeof(t));
550 t[0] = ntohl(t[0]);
551 t[1] = ntohl(t[1]);
55e303ae 552 BF_decrypt(t, (BF_KEY *)sav->sched);
9bccf70c
A
553 t[0] = htonl(t[0]);
554 t[1] = htonl(t[1]);
555 bcopy(t, d, sizeof(t));
556 return 0;
1c79356b
A
557}
558
559static int
2d21ac55
A
560esp_blowfish_blockencrypt(
561 __unused const struct esp_algorithm *algo,
562 struct secasvar *sav,
563 u_int8_t *s,
564 u_int8_t *d)
1c79356b 565{
9bccf70c
A
566 /* HOLY COW! BF_encrypt() takes values in host byteorder */
567 BF_LONG t[2];
568
569 bcopy(s, t, sizeof(t));
570 t[0] = ntohl(t[0]);
571 t[1] = ntohl(t[1]);
55e303ae 572 BF_encrypt(t, (BF_KEY *)sav->sched);
9bccf70c
A
573 t[0] = htonl(t[0]);
574 t[1] = htonl(t[1]);
575 bcopy(t, d, sizeof(t));
576 return 0;
1c79356b
A
577}
578
579static int
2d21ac55
A
580esp_cast128_schedlen(
581 __unused const struct esp_algorithm *algo)
1c79356b 582{
1c79356b 583
9bccf70c
A
584 return sizeof(u_int32_t) * 32;
585}
1c79356b 586
9bccf70c 587static int
2d21ac55
A
588esp_cast128_schedule(
589 __unused const struct esp_algorithm *algo,
590 struct secasvar *sav)
9bccf70c 591{
2d21ac55 592 lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
b0d623f7 593 set_cast128_subkey((u_int32_t *)sav->sched, (u_int8_t *) _KEYBUF(sav->key_enc),
9bccf70c 594 _KEYLEN(sav->key_enc));
1c79356b
A
595 return 0;
596}
597
598static int
2d21ac55
A
599esp_cast128_blockdecrypt(
600 __unused const struct esp_algorithm *algo,
601 struct secasvar *sav,
602 u_int8_t *s,
603 u_int8_t *d)
1c79356b 604{
1c79356b 605
9bccf70c
A
606 if (_KEYLEN(sav->key_enc) <= 80 / 8)
607 cast128_decrypt_round12(d, s, (u_int32_t *)sav->sched);
608 else
609 cast128_decrypt_round16(d, s, (u_int32_t *)sav->sched);
610 return 0;
611}
1c79356b 612
9bccf70c 613static int
2d21ac55
A
614esp_cast128_blockencrypt(
615 __unused const struct esp_algorithm *algo,
616 struct secasvar *sav,
617 u_int8_t *s,
618 u_int8_t *d)
9bccf70c 619{
1c79356b 620
9bccf70c
A
621 if (_KEYLEN(sav->key_enc) <= 80 / 8)
622 cast128_encrypt_round12(d, s, (u_int32_t *)sav->sched);
623 else
624 cast128_encrypt_round16(d, s, (u_int32_t *)sav->sched);
625 return 0;
626}
2d21ac55 627#endif /* ALLCRYPTO */
1c79356b 628
9bccf70c 629static int
2d21ac55
A
630esp_3des_schedlen(
631 __unused const struct esp_algorithm *algo)
9bccf70c 632{
1c79356b 633
9bccf70c
A
634 return sizeof(des_key_schedule) * 3;
635}
1c79356b 636
9bccf70c 637static int
2d21ac55
A
638esp_3des_schedule(
639 __unused const struct esp_algorithm *algo,
640 struct secasvar *sav)
9bccf70c
A
641{
642 int error;
643 des_key_schedule *p;
644 int i;
645 char *k;
1c79356b 646
2d21ac55 647 lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
9bccf70c
A
648 p = (des_key_schedule *)sav->sched;
649 k = _KEYBUF(sav->key_enc);
650 for (i = 0; i < 3; i++) {
651 error = des_key_sched((des_cblock *)(k + 8 * i), p[i]);
652 if (error)
653 return EINVAL;
654 }
655 return 0;
656}
1c79356b 657
9bccf70c 658static int
2d21ac55
A
659esp_3des_blockdecrypt(
660 __unused const struct esp_algorithm *algo,
661 struct secasvar *sav,
662 u_int8_t *s,
663 u_int8_t *d)
9bccf70c
A
664{
665 des_key_schedule *p;
666
667 /* assumption: d has a good alignment */
668 p = (des_key_schedule *)sav->sched;
669 bcopy(s, d, sizeof(DES_LONG) * 2);
55e303ae
A
670 des_ecb3_encrypt((des_cblock *)d, (des_cblock *)d,
671 p[0], p[1], p[2], DES_DECRYPT);
9bccf70c
A
672 return 0;
673}
1c79356b 674
9bccf70c 675static int
2d21ac55
A
676esp_3des_blockencrypt(
677 __unused const struct esp_algorithm *algo,
678 struct secasvar *sav,
679 u_int8_t *s,
680 u_int8_t *d)
9bccf70c
A
681{
682 des_key_schedule *p;
683
684 /* assumption: d has a good alignment */
685 p = (des_key_schedule *)sav->sched;
686 bcopy(s, d, sizeof(DES_LONG) * 2);
55e303ae
A
687 des_ecb3_encrypt((des_cblock *)d, (des_cblock *)d,
688 p[0], p[1], p[2], DES_ENCRYPT);
1c79356b
A
689 return 0;
690}
691
692static int
2d21ac55
A
693esp_common_ivlen(
694 const struct esp_algorithm *algo,
695 __unused struct secasvar *sav)
1c79356b 696{
9bccf70c
A
697
698 if (!algo)
699 panic("esp_common_ivlen: unknown algorithm");
700 return algo->ivlenval;
1c79356b
A
701}
702
703static int
9bccf70c 704esp_cbc_decrypt(m, off, sav, algo, ivlen)
1c79356b
A
705 struct mbuf *m;
706 size_t off;
707 struct secasvar *sav;
9bccf70c 708 const struct esp_algorithm *algo;
1c79356b
A
709 int ivlen;
710{
9bccf70c
A
711 struct mbuf *s;
712 struct mbuf *d, *d0, *dp;
55e303ae
A
713 int soff, doff; /* offset from the head of chain, to head of this mbuf */
714 int sn, dn; /* offset from the head of the mbuf, to meat */
9bccf70c
A
715 size_t ivoff, bodyoff;
716 u_int8_t iv[MAXIVLEN], *ivp;
717 u_int8_t sbuf[MAXIVLEN], *sp;
718 u_int8_t *p, *q;
719 struct mbuf *scut;
720 int scutoff;
721 int i;
722 int blocklen;
723 int derived;
1c79356b 724
9bccf70c
A
725 if (ivlen != sav->ivlen || ivlen > sizeof(iv)) {
726 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
727 "unsupported ivlen %d\n", algo->name, ivlen));
728 m_freem(m);
1c79356b
A
729 return EINVAL;
730 }
731
9bccf70c
A
732 /* assumes blocklen == padbound */
733 blocklen = algo->padbound;
1c79356b 734
9bccf70c
A
735#if DIAGNOSTIC
736 if (blocklen > sizeof(iv)) {
737 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
738 "unsupported blocklen %d\n", algo->name, blocklen));
739 m_freem(m);
1c79356b
A
740 return EINVAL;
741 }
9bccf70c 742#endif
1c79356b 743
9bccf70c
A
744 if (sav->flags & SADB_X_EXT_OLD) {
745 /* RFC 1827 */
746 ivoff = off + sizeof(struct esp);
747 bodyoff = off + sizeof(struct esp) + ivlen;
748 derived = 0;
749 } else {
750 /* RFC 2406 */
751 if (sav->flags & SADB_X_EXT_DERIV) {
752 /*
753 * draft-ietf-ipsec-ciph-des-derived-00.txt
754 * uses sequence number field as IV field.
755 */
756 ivoff = off + sizeof(struct esp);
757 bodyoff = off + sizeof(struct esp) + sizeof(u_int32_t);
758 ivlen = sizeof(u_int32_t);
759 derived = 1;
760 } else {
761 ivoff = off + sizeof(struct newesp);
762 bodyoff = off + sizeof(struct newesp) + ivlen;
763 derived = 0;
764 }
1c79356b
A
765 }
766
9bccf70c 767 /* grab iv */
b0d623f7 768 m_copydata(m, ivoff, ivlen, (caddr_t) iv);
1c79356b 769
9bccf70c
A
770 /* extend iv */
771 if (ivlen == blocklen)
772 ;
773 else if (ivlen == 4 && blocklen == 8) {
774 bcopy(&iv[0], &iv[4], 4);
775 iv[4] ^= 0xff;
776 iv[5] ^= 0xff;
777 iv[6] ^= 0xff;
778 iv[7] ^= 0xff;
779 } else {
780 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
781 "unsupported ivlen/blocklen: %d %d\n",
782 algo->name, ivlen, blocklen));
783 m_freem(m);
1c79356b
A
784 return EINVAL;
785 }
9bccf70c
A
786
787 if (m->m_pkthdr.len < bodyoff) {
788 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: bad len %d/%lu\n",
b0d623f7 789 algo->name, m->m_pkthdr.len, (u_int32_t)bodyoff));
9bccf70c 790 m_freem(m);
1c79356b
A
791 return EINVAL;
792 }
9bccf70c
A
793 if ((m->m_pkthdr.len - bodyoff) % blocklen) {
794 ipseclog((LOG_ERR, "esp_cbc_decrypt %s: "
795 "payload length must be multiple of %d\n",
796 algo->name, blocklen));
797 m_freem(m);
1c79356b
A
798 return EINVAL;
799 }
800
9bccf70c
A
801 s = m;
802 d = d0 = dp = NULL;
803 soff = doff = sn = dn = 0;
804 ivp = sp = NULL;
1c79356b 805
9bccf70c
A
806 /* skip bodyoff */
807 while (soff < bodyoff) {
808 if (soff + s->m_len > bodyoff) {
809 sn = bodyoff - soff;
810 break;
811 }
1c79356b 812
9bccf70c
A
813 soff += s->m_len;
814 s = s->m_next;
1c79356b 815 }
9bccf70c
A
816 scut = s;
817 scutoff = sn;
1c79356b 818
9bccf70c
A
819 /* skip over empty mbuf */
820 while (s && s->m_len == 0)
821 s = s->m_next;
1c79356b 822
9bccf70c
A
823 while (soff < m->m_pkthdr.len) {
824 /* source */
825 if (sn + blocklen <= s->m_len) {
826 /* body is continuous */
827 sp = mtod(s, u_int8_t *) + sn;
828 } else {
829 /* body is non-continuous */
b0d623f7 830 m_copydata(s, sn, blocklen, (caddr_t) sbuf);
9bccf70c
A
831 sp = sbuf;
832 }
1c79356b 833
9bccf70c
A
834 /* destination */
835 if (!d || dn + blocklen > d->m_len) {
836 if (d)
837 dp = d;
838 MGET(d, M_DONTWAIT, MT_DATA);
839 i = m->m_pkthdr.len - (soff + sn);
840 if (d && i > MLEN) {
841 MCLGET(d, M_DONTWAIT);
842 if ((d->m_flags & M_EXT) == 0) {
843 m_free(d);
844 d = NULL;
845 }
846 }
847 if (!d) {
848 m_freem(m);
849 if (d0)
850 m_freem(d0);
851 return ENOBUFS;
852 }
853 if (!d0)
854 d0 = d;
855 if (dp)
856 dp->m_next = d;
857 d->m_len = 0;
858 d->m_len = (M_TRAILINGSPACE(d) / blocklen) * blocklen;
859 if (d->m_len > i)
860 d->m_len = i;
861 dn = 0;
862 }
1c79356b 863
9bccf70c
A
864 /* decrypt */
865 (*algo->blockdecrypt)(algo, sav, sp, mtod(d, u_int8_t *) + dn);
1c79356b 866
9bccf70c
A
867 /* xor */
868 p = ivp ? ivp : iv;
869 q = mtod(d, u_int8_t *) + dn;
870 for (i = 0; i < blocklen; i++)
871 q[i] ^= p[i];
1c79356b 872
9bccf70c
A
873 /* next iv */
874 if (sp == sbuf) {
875 bcopy(sbuf, iv, blocklen);
876 ivp = NULL;
877 } else
878 ivp = sp;
1c79356b 879
9bccf70c
A
880 sn += blocklen;
881 dn += blocklen;
1c79356b 882
9bccf70c
A
883 /* find the next source block */
884 while (s && sn >= s->m_len) {
885 sn -= s->m_len;
886 soff += s->m_len;
887 s = s->m_next;
888 }
1c79356b
A
889 }
890
9bccf70c
A
891 m_freem(scut->m_next);
892 scut->m_len = scutoff;
893 scut->m_next = d0;
1c79356b 894
9bccf70c
A
895 /* just in case */
896 bzero(iv, sizeof(iv));
897 bzero(sbuf, sizeof(sbuf));
1c79356b
A
898
899 return 0;
900}
901
902static int
2d21ac55
A
903esp_cbc_encrypt(
904 struct mbuf *m,
905 size_t off,
906 __unused size_t plen,
907 struct secasvar *sav,
908 const struct esp_algorithm *algo,
909 int ivlen)
1c79356b 910{
9bccf70c
A
911 struct mbuf *s;
912 struct mbuf *d, *d0, *dp;
55e303ae
A
913 int soff, doff; /* offset from the head of chain, to head of this mbuf */
914 int sn, dn; /* offset from the head of the mbuf, to meat */
9bccf70c
A
915 size_t ivoff, bodyoff;
916 u_int8_t iv[MAXIVLEN], *ivp;
917 u_int8_t sbuf[MAXIVLEN], *sp;
918 u_int8_t *p, *q;
919 struct mbuf *scut;
920 int scutoff;
921 int i;
922 int blocklen;
923 int derived;
924
925 if (ivlen != sav->ivlen || ivlen > sizeof(iv)) {
926 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
927 "unsupported ivlen %d\n", algo->name, ivlen));
928 m_freem(m);
1c79356b
A
929 return EINVAL;
930 }
9bccf70c
A
931
932 /* assumes blocklen == padbound */
933 blocklen = algo->padbound;
934
935#if DIAGNOSTIC
936 if (blocklen > sizeof(iv)) {
937 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
938 "unsupported blocklen %d\n", algo->name, blocklen));
939 m_freem(m);
1c79356b
A
940 return EINVAL;
941 }
9bccf70c
A
942#endif
943
944 if (sav->flags & SADB_X_EXT_OLD) {
945 /* RFC 1827 */
946 ivoff = off + sizeof(struct esp);
947 bodyoff = off + sizeof(struct esp) + ivlen;
948 derived = 0;
949 } else {
950 /* RFC 2406 */
951 if (sav->flags & SADB_X_EXT_DERIV) {
952 /*
953 * draft-ietf-ipsec-ciph-des-derived-00.txt
954 * uses sequence number field as IV field.
955 */
956 ivoff = off + sizeof(struct esp);
957 bodyoff = off + sizeof(struct esp) + sizeof(u_int32_t);
958 ivlen = sizeof(u_int32_t);
959 derived = 1;
960 } else {
961 ivoff = off + sizeof(struct newesp);
962 bodyoff = off + sizeof(struct newesp) + ivlen;
963 derived = 0;
964 }
965 }
966
967 /* put iv into the packet. if we are in derived mode, use seqno. */
968 if (derived)
b0d623f7 969 m_copydata(m, ivoff, ivlen, (caddr_t) iv);
9bccf70c
A
970 else {
971 bcopy(sav->iv, iv, ivlen);
972 /* maybe it is better to overwrite dest, not source */
b0d623f7 973 m_copyback(m, ivoff, ivlen, (caddr_t) iv);
9bccf70c
A
974 }
975
976 /* extend iv */
977 if (ivlen == blocklen)
978 ;
979 else if (ivlen == 4 && blocklen == 8) {
980 bcopy(&iv[0], &iv[4], 4);
981 iv[4] ^= 0xff;
982 iv[5] ^= 0xff;
983 iv[6] ^= 0xff;
984 iv[7] ^= 0xff;
985 } else {
986 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
987 "unsupported ivlen/blocklen: %d %d\n",
988 algo->name, ivlen, blocklen));
989 m_freem(m);
1c79356b
A
990 return EINVAL;
991 }
9bccf70c
A
992
993 if (m->m_pkthdr.len < bodyoff) {
994 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: bad len %d/%lu\n",
b0d623f7 995 algo->name, m->m_pkthdr.len, (u_int32_t)bodyoff));
9bccf70c 996 m_freem(m);
1c79356b
A
997 return EINVAL;
998 }
9bccf70c
A
999 if ((m->m_pkthdr.len - bodyoff) % blocklen) {
1000 ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
1001 "payload length must be multiple of %lu\n",
b0d623f7 1002 algo->name, (u_int32_t)algo->padbound));
9bccf70c 1003 m_freem(m);
1c79356b
A
1004 return EINVAL;
1005 }
1006
9bccf70c
A
1007 s = m;
1008 d = d0 = dp = NULL;
1009 soff = doff = sn = dn = 0;
1010 ivp = sp = NULL;
1c79356b 1011
9bccf70c
A
1012 /* skip bodyoff */
1013 while (soff < bodyoff) {
1014 if (soff + s->m_len > bodyoff) {
1015 sn = bodyoff - soff;
1016 break;
1017 }
1c79356b 1018
9bccf70c
A
1019 soff += s->m_len;
1020 s = s->m_next;
1021 }
1022 scut = s;
1023 scutoff = sn;
1c79356b 1024
9bccf70c
A
1025 /* skip over empty mbuf */
1026 while (s && s->m_len == 0)
1027 s = s->m_next;
1c79356b 1028
9bccf70c
A
1029 while (soff < m->m_pkthdr.len) {
1030 /* source */
1031 if (sn + blocklen <= s->m_len) {
1032 /* body is continuous */
1033 sp = mtod(s, u_int8_t *) + sn;
1034 } else {
1035 /* body is non-continuous */
b0d623f7 1036 m_copydata(s, sn, blocklen, (caddr_t) sbuf);
9bccf70c
A
1037 sp = sbuf;
1038 }
1c79356b 1039
9bccf70c
A
1040 /* destination */
1041 if (!d || dn + blocklen > d->m_len) {
1042 if (d)
1043 dp = d;
1044 MGET(d, M_DONTWAIT, MT_DATA);
1045 i = m->m_pkthdr.len - (soff + sn);
1046 if (d && i > MLEN) {
1047 MCLGET(d, M_DONTWAIT);
1048 if ((d->m_flags & M_EXT) == 0) {
1049 m_free(d);
1050 d = NULL;
1051 }
1052 }
1053 if (!d) {
1054 m_freem(m);
1055 if (d0)
1056 m_freem(d0);
1057 return ENOBUFS;
1058 }
1059 if (!d0)
1060 d0 = d;
1061 if (dp)
1062 dp->m_next = d;
1063 d->m_len = 0;
1064 d->m_len = (M_TRAILINGSPACE(d) / blocklen) * blocklen;
1065 if (d->m_len > i)
1066 d->m_len = i;
1067 dn = 0;
1068 }
1c79356b 1069
9bccf70c
A
1070 /* xor */
1071 p = ivp ? ivp : iv;
1072 q = sp;
1073 for (i = 0; i < blocklen; i++)
1074 q[i] ^= p[i];
1c79356b 1075
9bccf70c
A
1076 /* encrypt */
1077 (*algo->blockencrypt)(algo, sav, sp, mtod(d, u_int8_t *) + dn);
1c79356b 1078
9bccf70c
A
1079 /* next iv */
1080 ivp = mtod(d, u_int8_t *) + dn;
1c79356b 1081
9bccf70c
A
1082 sn += blocklen;
1083 dn += blocklen;
1c79356b 1084
9bccf70c
A
1085 /* find the next source block */
1086 while (s && sn >= s->m_len) {
1087 sn -= s->m_len;
1088 soff += s->m_len;
1089 s = s->m_next;
1c79356b 1090 }
1c79356b 1091 }
9bccf70c
A
1092
1093 m_freem(scut->m_next);
1094 scut->m_len = scutoff;
1095 scut->m_next = d0;
1096
1097 /* just in case */
1098 bzero(iv, sizeof(iv));
1099 bzero(sbuf, sizeof(sbuf));
1100
1101 key_sa_stir_iv(sav);
1102
1103 return 0;
1c79356b
A
1104}
1105
1106/*------------------------------------------------------------*/
1107
9bccf70c 1108/* does not free m0 on error */
1c79356b
A
1109int
1110esp_auth(m0, skip, length, sav, sum)
1111 struct mbuf *m0;
1112 size_t skip; /* offset to ESP header */
1113 size_t length; /* payload length */
1114 struct secasvar *sav;
1115 u_char *sum;
1116{
1117 struct mbuf *m;
1118 size_t off;
1119 struct ah_algorithm_state s;
1120 u_char sumbuf[AH_MAXSUMSIZE];
9bccf70c 1121 const struct ah_algorithm *algo;
1c79356b 1122 size_t siz;
9bccf70c 1123 int error;
1c79356b
A
1124
1125 /* sanity checks */
1126 if (m0->m_pkthdr.len < skip) {
1127 ipseclog((LOG_DEBUG, "esp_auth: mbuf length < skip\n"));
1128 return EINVAL;
1129 }
1130 if (m0->m_pkthdr.len < skip + length) {
1131 ipseclog((LOG_DEBUG,
1132 "esp_auth: mbuf length < skip + length\n"));
1133 return EINVAL;
1134 }
55e303ae
A
1135
1136 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_START, skip,length,0,0,0);
1c79356b
A
1137 /*
1138 * length of esp part (excluding authentication data) must be 4n,
1139 * since nexthdr must be at offset 4n+3.
1140 */
1141 if (length % 4) {
1142 ipseclog((LOG_ERR, "esp_auth: length is not multiple of 4\n"));
55e303ae 1143 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 1,0,0,0,0);
1c79356b
A
1144 return EINVAL;
1145 }
1146 if (!sav) {
1147 ipseclog((LOG_DEBUG, "esp_auth: NULL SA passed\n"));
55e303ae 1148 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 2,0,0,0,0);
1c79356b
A
1149 return EINVAL;
1150 }
9bccf70c
A
1151 algo = ah_algorithm_lookup(sav->alg_auth);
1152 if (!algo) {
1c79356b
A
1153 ipseclog((LOG_ERR,
1154 "esp_auth: bad ESP auth algorithm passed: %d\n",
1155 sav->alg_auth));
55e303ae 1156 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 3,0,0,0,0);
1c79356b
A
1157 return EINVAL;
1158 }
1159
1160 m = m0;
1161 off = 0;
1162
1c79356b
A
1163 siz = (((*algo->sumsiz)(sav) + 3) & ~(4 - 1));
1164 if (sizeof(sumbuf) < siz) {
1165 ipseclog((LOG_DEBUG,
1166 "esp_auth: AH_MAXSUMSIZE is too small: siz=%lu\n",
b0d623f7 1167 (u_int32_t)siz));
55e303ae 1168 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 4,0,0,0,0);
1c79356b
A
1169 return EINVAL;
1170 }
1171
1172 /* skip the header */
1173 while (skip) {
1174 if (!m)
1175 panic("mbuf chain?");
1176 if (m->m_len <= skip) {
1177 skip -= m->m_len;
1178 m = m->m_next;
1179 off = 0;
1180 } else {
1181 off = skip;
1182 skip = 0;
1183 }
1184 }
1185
9bccf70c 1186 error = (*algo->init)(&s, sav);
55e303ae
A
1187 if (error) {
1188 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 5,0,0,0,0);
9bccf70c 1189 return error;
55e303ae 1190 }
1c79356b
A
1191 while (0 < length) {
1192 if (!m)
1193 panic("mbuf chain?");
1194
1195 if (m->m_len - off < length) {
b0d623f7 1196 (*algo->update)(&s, (caddr_t)(mtod(m, u_char *) + off),
1c79356b
A
1197 m->m_len - off);
1198 length -= m->m_len - off;
1199 m = m->m_next;
1200 off = 0;
1201 } else {
b0d623f7 1202 (*algo->update)(&s, (caddr_t)(mtod(m, u_char *) + off), length);
1c79356b
A
1203 break;
1204 }
1205 }
6d2010ae 1206 (*algo->result)(&s, (caddr_t) sumbuf, sizeof(sumbuf));
1c79356b 1207 bcopy(sumbuf, sum, siz); /*XXX*/
55e303ae 1208 KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 6,0,0,0,0);
1c79356b
A
1209 return 0;
1210}