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