esp.c (19612B)
1 /* 2 * Encapsulating Security Payload for IPsec for IPv4, rfc1827. 3 * currently only implements tunnel mode. 4 * TODO: update to match rfc4303. 5 */ 6 #include "u.h" 7 #include "lib.h" 8 #include "mem.h" 9 #include "dat.h" 10 #include "fns.h" 11 #include "error.h" 12 13 #include "ip.h" 14 #include "ipv6.h" 15 #include "libsec.h" 16 17 typedef struct Esphdr Esphdr; 18 typedef struct Esp4hdr Esp4hdr; 19 typedef struct Esp6hdr Esp6hdr; 20 typedef struct Esptail Esptail; 21 typedef struct Userhdr Userhdr; 22 typedef struct Esppriv Esppriv; 23 typedef struct Espcb Espcb; 24 typedef struct Algorithm Algorithm; 25 26 enum 27 { 28 IP_ESPPROTO = 50, /* IP v4 and v6 protocol number */ 29 Esp4hdrlen = IP4HDR + 8, 30 Esp6hdrlen = IP6HDR + 8, 31 32 Esptaillen = 2, /* does not include pad or auth data */ 33 Userhdrlen = 4, /* user-visible header size - if enabled */ 34 }; 35 36 struct Esphdr 37 { 38 uchar espspi[4]; /* Security parameter index */ 39 uchar espseq[4]; /* Sequence number */ 40 }; 41 42 /* 43 * tunnel-mode layout: IP | ESP | TCP/UDP | user data. 44 * transport-mode layout is: ESP | IP | TCP/UDP | user data. 45 */ 46 struct Esp4hdr 47 { 48 /* ipv4 header */ 49 uchar vihl; /* Version and header length */ 50 uchar tos; /* Type of service */ 51 uchar length[2]; /* packet length */ 52 uchar id[2]; /* Identification */ 53 uchar frag[2]; /* Fragment information */ 54 uchar Unused; 55 uchar espproto; /* Protocol */ 56 uchar espplen[2]; /* Header plus data length */ 57 uchar espsrc[4]; /* Ip source */ 58 uchar espdst[4]; /* Ip destination */ 59 60 /* Esphdr; */ 61 uchar espspi[4]; /* Security parameter index */ 62 uchar espseq[4]; /* Sequence number */ 63 }; 64 65 /* tunnel-mode layout */ 66 struct Esp6hdr 67 { 68 /* Ip6hdr; */ 69 uchar vcf[4]; /* version:4, traffic class:8, flow label:20 */ 70 uchar ploadlen[2]; /* payload length: packet length - 40 */ 71 uchar proto; /* next header type */ 72 uchar ttl; /* hop limit */ 73 uchar src[IPaddrlen]; 74 uchar dst[IPaddrlen]; 75 76 /* Esphdr; */ 77 uchar espspi[4]; /* Security parameter index */ 78 uchar espseq[4]; /* Sequence number */ 79 }; 80 81 struct Esptail 82 { 83 uchar pad; 84 uchar nexthdr; 85 }; 86 87 /* header as seen by the user */ 88 struct Userhdr 89 { 90 uchar nexthdr; /* next protocol */ 91 uchar unused[3]; 92 }; 93 94 struct Esppriv 95 { 96 ulong in; 97 ulong inerrors; 98 }; 99 100 /* 101 * protocol specific part of Conv 102 */ 103 struct Espcb 104 { 105 int incoming; 106 int header; /* user user level header */ 107 ulong spi; 108 ulong seq; /* last seq sent */ 109 ulong window; /* for replay attacks */ 110 char *espalg; 111 void *espstate; /* other state for esp */ 112 int espivlen; /* in bytes */ 113 int espblklen; 114 int (*cipher)(Espcb*, uchar *buf, int len); 115 char *ahalg; 116 void *ahstate; /* other state for esp */ 117 int ahlen; /* auth data length in bytes */ 118 int ahblklen; 119 int (*auth)(Espcb*, uchar *buf, int len, uchar *hash); 120 }; 121 122 struct Algorithm 123 { 124 char *name; 125 int keylen; /* in bits */ 126 void (*init)(Espcb*, char* name, uchar *key, int keylen); 127 }; 128 129 static Conv* convlookup(Proto *esp, ulong spi); 130 static char *setalg(Espcb *ecb, char **f, int n, Algorithm *alg); 131 static void espkick(void *x); 132 133 static void nullespinit(Espcb*, char*, uchar *key, int keylen); 134 static void desespinit(Espcb *ecb, char *name, uchar *k, int n); 135 136 static void nullahinit(Espcb*, char*, uchar *key, int keylen); 137 static void shaahinit(Espcb*, char*, uchar *key, int keylen); 138 static void md5ahinit(Espcb*, char*, uchar *key, int keylen); 139 140 static Algorithm espalg[] = 141 { 142 "null", 0, nullespinit, 143 // "des3_cbc", 192, des3espinit, /* rfc2451 */ 144 // "aes_128_cbc", 128, aescbcespinit, /* rfc3602 */ 145 // "aes_ctr", 128, aesctrespinit, /* rfc3686 */ 146 "des_56_cbc", 64, desespinit, /* rfc2405, deprecated */ 147 // "rc4_128", 128, rc4espinit, /* gone in rfc4305 */ 148 nil, 0, nil, 149 }; 150 151 static Algorithm ahalg[] = 152 { 153 "null", 0, nullahinit, 154 "hmac_sha1_96", 128, shaahinit, /* rfc2404 */ 155 // "aes_xcbc_mac_96", 128, aesahinit, /* rfc3566 */ 156 "hmac_md5_96", 128, md5ahinit, /* rfc2403 */ 157 nil, 0, nil, 158 }; 159 160 static char* 161 espconnect(Conv *c, char **argv, int argc) 162 { 163 char *p, *pp; 164 char *e = nil; 165 ulong spi; 166 Espcb *ecb = (Espcb*)c->ptcl; 167 168 switch(argc) { 169 default: 170 e = "bad args to connect"; 171 break; 172 case 2: 173 p = strchr(argv[1], '!'); 174 if(p == nil){ 175 e = "malformed address"; 176 break; 177 } 178 *p++ = 0; 179 parseip(c->raddr, argv[1]); 180 findlocalip(c->p->f, c->laddr, c->raddr); 181 ecb->incoming = 0; 182 ecb->seq = 0; 183 if(strcmp(p, "*") == 0) { 184 QLOCK(c->p); 185 for(;;) { 186 spi = nrand(1<<16) + 256; 187 if(convlookup(c->p, spi) == nil) 188 break; 189 } 190 QUNLOCK(c->p); 191 ecb->spi = spi; 192 ecb->incoming = 1; 193 qhangup(c->wq, nil); 194 } else { 195 spi = strtoul(p, &pp, 10); 196 if(pp == p) { 197 e = "malformed address"; 198 break; 199 } 200 ecb->spi = spi; 201 qhangup(c->rq, nil); 202 } 203 nullespinit(ecb, "null", nil, 0); 204 nullahinit(ecb, "null", nil, 0); 205 } 206 Fsconnected(c, e); 207 208 return e; 209 } 210 211 212 static int 213 espstate(Conv *c, char *state, int n) 214 { 215 return snprint(state, n, "%s", c->inuse?"Open\n":"Closed\n"); 216 } 217 218 static void 219 espcreate(Conv *c) 220 { 221 c->rq = qopen(64*1024, Qmsg, 0, 0); 222 c->wq = qopen(64*1024, Qkick, espkick, c); 223 } 224 225 static void 226 espclose(Conv *c) 227 { 228 Espcb *ecb; 229 230 qclose(c->rq); 231 qclose(c->wq); 232 qclose(c->eq); 233 ipmove(c->laddr, IPnoaddr); 234 ipmove(c->raddr, IPnoaddr); 235 236 ecb = (Espcb*)c->ptcl; 237 free(ecb->espstate); 238 free(ecb->ahstate); 239 memset(ecb, 0, sizeof(Espcb)); 240 } 241 242 static int 243 ipvers(Conv *c) 244 { 245 if((memcmp(c->raddr, v4prefix, IPv4off) == 0 && 246 memcmp(c->laddr, v4prefix, IPv4off) == 0) || 247 ipcmp(c->raddr, IPnoaddr) == 0) 248 return V4; 249 else 250 return V6; 251 } 252 253 static void 254 espkick(void *x) 255 { 256 Conv *c = x; 257 Esp4hdr *eh4; 258 Esp6hdr *eh6; 259 Esptail *et; 260 Userhdr *uh; 261 Espcb *ecb; 262 Block *bp; 263 int nexthdr, payload, pad, align, version, hdrlen, iphdrlen; 264 uchar *auth; 265 266 version = ipvers(c); 267 iphdrlen = version == V4? IP4HDR: IP6HDR; 268 hdrlen = version == V4? Esp4hdrlen: Esp6hdrlen; 269 270 bp = qget(c->wq); 271 if(bp == nil) 272 return; 273 274 QLOCK(c); 275 ecb = c->ptcl; 276 277 if(ecb->header) { 278 /* make sure the message has a User header */ 279 bp = pullupblock(bp, Userhdrlen); 280 if(bp == nil) { 281 QUNLOCK(c); 282 return; 283 } 284 uh = (Userhdr*)bp->rp; 285 nexthdr = uh->nexthdr; 286 bp->rp += Userhdrlen; 287 } else { 288 nexthdr = 0; /* what should this be? */ 289 } 290 291 payload = BLEN(bp) + ecb->espivlen; 292 293 /* Make space to fit ip header */ 294 bp = padblock(bp, hdrlen + ecb->espivlen); 295 296 align = 4; 297 if(ecb->espblklen > align) 298 align = ecb->espblklen; 299 if(align % ecb->ahblklen != 0) 300 panic("espkick: ahblklen is important after all"); 301 pad = (align-1) - (payload + Esptaillen-1)%align; 302 303 /* 304 * Make space for tail 305 * this is done by calling padblock with a negative size 306 * Padblock does not change bp->wp! 307 */ 308 bp = padblock(bp, -(pad+Esptaillen+ecb->ahlen)); 309 bp->wp += pad+Esptaillen+ecb->ahlen; 310 311 eh4 = (Esp4hdr *)bp->rp; 312 eh6 = (Esp6hdr *)bp->rp; 313 et = (Esptail*)(bp->rp + hdrlen + payload + pad); 314 315 /* fill in tail */ 316 et->pad = pad; 317 et->nexthdr = nexthdr; 318 319 ecb->cipher(ecb, bp->rp + hdrlen, payload + pad + Esptaillen); 320 auth = bp->rp + hdrlen + payload + pad + Esptaillen; 321 322 /* fill in head */ 323 if (version == V4) { 324 eh4->vihl = IP_VER4; 325 hnputl(eh4->espspi, ecb->spi); 326 hnputl(eh4->espseq, ++ecb->seq); 327 v6tov4(eh4->espsrc, c->laddr); 328 v6tov4(eh4->espdst, c->raddr); 329 eh4->espproto = IP_ESPPROTO; 330 eh4->frag[0] = 0; 331 eh4->frag[1] = 0; 332 } else { 333 eh6->vcf[0] = IP_VER6; 334 hnputl(eh6->espspi, ecb->spi); 335 hnputl(eh6->espseq, ++ecb->seq); 336 ipmove(eh6->src, c->laddr); 337 ipmove(eh6->dst, c->raddr); 338 eh6->proto = IP_ESPPROTO; 339 } 340 341 ecb->auth(ecb, bp->rp + iphdrlen, (hdrlen - iphdrlen) + 342 payload + pad + Esptaillen, auth); 343 344 QUNLOCK(c); 345 /* print("esp: pass down: %uld\n", BLEN(bp)); */ 346 if (version == V4) 347 ipoput4(c->p->f, bp, 0, c->ttl, c->tos, c); 348 else 349 ipoput6(c->p->f, bp, 0, c->ttl, c->tos, c); 350 } 351 352 void 353 espiput(Proto *esp, Ipifc* _, Block *bp) 354 { 355 Esp4hdr *eh4; 356 Esp6hdr *eh6; 357 Esptail *et; 358 Userhdr *uh; 359 Conv *c; 360 Espcb *ecb; 361 uchar raddr[IPaddrlen], laddr[IPaddrlen]; 362 Fs *f; 363 uchar *auth, *espspi; 364 ulong spi; 365 int payload, nexthdr, version, hdrlen; 366 367 f = esp->f; 368 if (bp == nil || BLEN(bp) == 0) { 369 /* get enough to identify the IP version */ 370 bp = pullupblock(bp, IP4HDR); 371 if(bp == nil) { 372 netlog(f, Logesp, "esp: short packet\n"); 373 return; 374 } 375 } 376 eh4 = (Esp4hdr*)bp->rp; 377 version = ((eh4->vihl & 0xf0) == IP_VER4? V4: V6); 378 hdrlen = version == V4? Esp4hdrlen: Esp6hdrlen; 379 380 bp = pullupblock(bp, hdrlen + Esptaillen); 381 if(bp == nil) { 382 netlog(f, Logesp, "esp: short packet\n"); 383 return; 384 } 385 386 if (version == V4) { 387 eh4 = (Esp4hdr*)bp->rp; 388 spi = nhgetl(eh4->espspi); 389 v4tov6(raddr, eh4->espsrc); 390 v4tov6(laddr, eh4->espdst); 391 } else { 392 eh6 = (Esp6hdr*)bp->rp; 393 spi = nhgetl(eh6->espspi); 394 ipmove(raddr, eh6->src); 395 ipmove(laddr, eh6->dst); 396 } 397 398 QLOCK(esp); 399 /* Look for a conversation structure for this port */ 400 c = convlookup(esp, spi); 401 if(c == nil) { 402 QUNLOCK(esp); 403 netlog(f, Logesp, "esp: no conv %I -> %I!%d\n", raddr, 404 laddr, spi); 405 icmpnoconv(f, bp); 406 freeblist(bp); 407 return; 408 } 409 410 QLOCK(c); 411 QUNLOCK(esp); 412 413 ecb = c->ptcl; 414 /* too hard to do decryption/authentication on block lists */ 415 if(bp->next) 416 bp = concatblock(bp); 417 418 if(BLEN(bp) < hdrlen + ecb->espivlen + Esptaillen + ecb->ahlen) { 419 QUNLOCK(c); 420 netlog(f, Logesp, "esp: short block %I -> %I!%d\n", raddr, 421 laddr, spi); 422 freeb(bp); 423 return; 424 } 425 426 auth = bp->wp - ecb->ahlen; 427 espspi = version == V4? ((Esp4hdr*)bp->rp)->espspi: 428 ((Esp6hdr*)bp->rp)->espspi; 429 if(!ecb->auth(ecb, espspi, auth - espspi, auth)) { 430 QUNLOCK(c); 431 print("esp: bad auth %I -> %I!%ld\n", raddr, laddr, spi); 432 netlog(f, Logesp, "esp: bad auth %I -> %I!%d\n", raddr, 433 laddr, spi); 434 freeb(bp); 435 return; 436 } 437 438 payload = BLEN(bp) - hdrlen - ecb->ahlen; 439 if(payload <= 0 || payload % 4 != 0 || payload % ecb->espblklen != 0) { 440 QUNLOCK(c); 441 netlog(f, Logesp, "esp: bad length %I -> %I!%d payload=%d BLEN=%d\n", 442 raddr, laddr, spi, payload, BLEN(bp)); 443 freeb(bp); 444 return; 445 } 446 if(!ecb->cipher(ecb, bp->rp + hdrlen, payload)) { 447 QUNLOCK(c); 448 print("esp: cipher failed %I -> %I!%ld: %s\n", raddr, laddr, spi, up->errstr); 449 netlog(f, Logesp, "esp: cipher failed %I -> %I!%d: %s\n", raddr, 450 laddr, spi, up->errstr); 451 freeb(bp); 452 return; 453 } 454 455 payload -= Esptaillen; 456 et = (Esptail*)(bp->rp + hdrlen + payload); 457 payload -= et->pad + ecb->espivlen; 458 nexthdr = et->nexthdr; 459 if(payload <= 0) { 460 QUNLOCK(c); 461 netlog(f, Logesp, "esp: short packet after decrypt %I -> %I!%d\n", 462 raddr, laddr, spi); 463 freeb(bp); 464 return; 465 } 466 467 /* trim packet */ 468 bp->rp += hdrlen + ecb->espivlen; 469 bp->wp = bp->rp + payload; 470 if(ecb->header) { 471 /* assume Userhdrlen < Esp4hdrlen < Esp6hdrlen */ 472 bp->rp -= Userhdrlen; 473 uh = (Userhdr*)bp->rp; 474 memset(uh, 0, Userhdrlen); 475 uh->nexthdr = nexthdr; 476 } 477 478 if(qfull(c->rq)){ 479 netlog(f, Logesp, "esp: qfull %I -> %I.%uld\n", raddr, 480 laddr, spi); 481 freeblist(bp); 482 }else { 483 // print("esp: pass up: %uld\n", BLEN(bp)); 484 qpass(c->rq, bp); 485 } 486 487 QUNLOCK(c); 488 } 489 490 char* 491 espctl(Conv *c, char **f, int n) 492 { 493 Espcb *ecb = c->ptcl; 494 char *e = nil; 495 496 if(strcmp(f[0], "esp") == 0) 497 e = setalg(ecb, f, n, espalg); 498 else if(strcmp(f[0], "ah") == 0) 499 e = setalg(ecb, f, n, ahalg); 500 else if(strcmp(f[0], "header") == 0) 501 ecb->header = 1; 502 else if(strcmp(f[0], "noheader") == 0) 503 ecb->header = 0; 504 else 505 e = "unknown control request"; 506 return e; 507 } 508 509 void 510 espadvise(Proto *esp, Block *bp, char *msg) 511 { 512 Esp4hdr *h; 513 Conv *c; 514 ulong spi; 515 516 h = (Esp4hdr*)(bp->rp); 517 518 spi = nhgets(h->espspi); 519 QLOCK(esp); 520 c = convlookup(esp, spi); 521 if(c != nil) { 522 qhangup(c->rq, msg); 523 qhangup(c->wq, msg); 524 } 525 QUNLOCK(esp); 526 freeblist(bp); 527 } 528 529 int 530 espstats(Proto *esp, char *buf, int len) 531 { 532 Esppriv *upriv; 533 534 upriv = esp->priv; 535 return snprint(buf, len, "%lud %lud\n", 536 upriv->in, 537 upriv->inerrors); 538 } 539 540 static int 541 esplocal(Conv *c, char *buf, int len) 542 { 543 Espcb *ecb = c->ptcl; 544 int n; 545 546 QLOCK(c); 547 if(ecb->incoming) 548 n = snprint(buf, len, "%I!%uld\n", c->laddr, ecb->spi); 549 else 550 n = snprint(buf, len, "%I\n", c->laddr); 551 QUNLOCK(c); 552 return n; 553 } 554 555 static int 556 espremote(Conv *c, char *buf, int len) 557 { 558 Espcb *ecb = c->ptcl; 559 int n; 560 561 QLOCK(c); 562 if(ecb->incoming) 563 n = snprint(buf, len, "%I\n", c->raddr); 564 else 565 n = snprint(buf, len, "%I!%uld\n", c->raddr, ecb->spi); 566 QUNLOCK(c); 567 return n; 568 } 569 570 static Conv* 571 convlookup(Proto *esp, ulong spi) 572 { 573 Conv *c, **p; 574 Espcb *ecb; 575 576 for(p=esp->conv; *p; p++){ 577 c = *p; 578 ecb = c->ptcl; 579 if(ecb->incoming && ecb->spi == spi) 580 return c; 581 } 582 return nil; 583 } 584 585 static char * 586 setalg(Espcb *ecb, char **f, int n, Algorithm *alg) 587 { 588 uchar *key; 589 int c, i, nbyte, nchar; 590 591 if(n < 2) 592 return "bad format"; 593 for(; alg->name; alg++) 594 if(strcmp(f[1], alg->name) == 0) 595 break; 596 if(alg->name == nil) 597 return "unknown algorithm"; 598 599 if(n != 3) 600 return "bad format"; 601 nbyte = (alg->keylen + 7) >> 3; 602 nchar = strlen(f[2]); 603 for(i=0; i<nchar; i++) { 604 c = f[2][i]; 605 if(c >= '0' && c <= '9') 606 f[2][i] -= '0'; 607 else if(c >= 'a' && c <= 'f') 608 f[2][i] -= 'a'-10; 609 else if(c >= 'A' && c <= 'F') 610 f[2][i] -= 'A'-10; 611 else 612 return "bad character in key"; 613 } 614 key = smalloc(nbyte); 615 for(i=0; i<nchar && i*2<nbyte; i++) { 616 c = f[2][nchar-i-1]; 617 if(i&1) 618 c <<= 4; 619 key[i>>1] |= c; 620 } 621 622 alg->init(ecb, alg->name, key, alg->keylen); 623 free(key); 624 return nil; 625 } 626 627 static int 628 nullcipher(Espcb* _, uchar* __, int ___) 629 { 630 return 1; 631 } 632 633 static void 634 nullespinit(Espcb *ecb, char *name, uchar* _, int __) 635 { 636 ecb->espalg = name; 637 ecb->espblklen = 1; 638 ecb->espivlen = 0; 639 ecb->cipher = nullcipher; 640 } 641 642 static int 643 nullauth(Espcb* _, uchar* __, int ___, uchar* ____) 644 { 645 return 1; 646 } 647 648 static void 649 nullahinit(Espcb *ecb, char *name, uchar* _, int __) 650 { 651 ecb->ahalg = name; 652 ecb->ahblklen = 1; 653 ecb->ahlen = 0; 654 ecb->auth = nullauth; 655 } 656 657 void 658 seanq_hmac_sha1(uchar hash[SHA1dlen], uchar *t, long tlen, uchar *key, long klen) 659 { 660 uchar ipad[65], opad[65]; 661 int i; 662 DigestState *digest; 663 uchar innerhash[SHA1dlen]; 664 665 for(i=0; i<64; i++){ 666 ipad[i] = 0x36; 667 opad[i] = 0x5c; 668 } 669 ipad[64] = opad[64] = 0; 670 for(i=0; i<klen; i++){ 671 ipad[i] ^= key[i]; 672 opad[i] ^= key[i]; 673 } 674 digest = sha1(ipad, 64, nil, nil); 675 sha1(t, tlen, innerhash, digest); 676 digest = sha1(opad, 64, nil, nil); 677 sha1(innerhash, SHA1dlen, hash, digest); 678 } 679 680 static int 681 shaauth(Espcb *ecb, uchar *t, int tlen, uchar *auth) 682 { 683 uchar hash[SHA1dlen]; 684 int r; 685 686 memset(hash, 0, SHA1dlen); 687 seanq_hmac_sha1(hash, t, tlen, (uchar*)ecb->ahstate, 16); 688 r = memcmp(auth, hash, ecb->ahlen) == 0; 689 memmove(auth, hash, ecb->ahlen); 690 return r; 691 } 692 693 static void 694 shaahinit(Espcb *ecb, char *name, uchar *key, int klen) 695 { 696 if(klen != 128) 697 panic("shaahinit: bad keylen"); 698 klen >>= 8; /* convert to bytes */ 699 700 ecb->ahalg = name; 701 ecb->ahblklen = 1; 702 ecb->ahlen = 12; 703 ecb->auth = shaauth; 704 ecb->ahstate = smalloc(klen); 705 memmove(ecb->ahstate, key, klen); 706 } 707 708 void 709 seanq_hmac_md5(uchar hash[MD5dlen], uchar *t, long tlen, uchar *key, long klen) 710 { 711 uchar ipad[65], opad[65]; 712 int i; 713 DigestState *digest; 714 uchar innerhash[MD5dlen]; 715 716 for(i=0; i<64; i++){ 717 ipad[i] = 0x36; 718 opad[i] = 0x5c; 719 } 720 ipad[64] = opad[64] = 0; 721 for(i=0; i<klen; i++){ 722 ipad[i] ^= key[i]; 723 opad[i] ^= key[i]; 724 } 725 digest = md5(ipad, 64, nil, nil); 726 md5(t, tlen, innerhash, digest); 727 digest = md5(opad, 64, nil, nil); 728 md5(innerhash, MD5dlen, hash, digest); 729 } 730 731 static int 732 md5auth(Espcb *ecb, uchar *t, int tlen, uchar *auth) 733 { 734 uchar hash[MD5dlen]; 735 int r; 736 737 memset(hash, 0, MD5dlen); 738 seanq_hmac_md5(hash, t, tlen, (uchar*)ecb->ahstate, 16); 739 r = memcmp(auth, hash, ecb->ahlen) == 0; 740 memmove(auth, hash, ecb->ahlen); 741 return r; 742 } 743 744 static void 745 md5ahinit(Espcb *ecb, char *name, uchar *key, int klen) 746 { 747 if(klen != 128) 748 panic("md5ahinit: bad keylen"); 749 klen >>= 3; /* convert to bytes */ 750 751 ecb->ahalg = name; 752 ecb->ahblklen = 1; 753 ecb->ahlen = 12; 754 ecb->auth = md5auth; 755 ecb->ahstate = smalloc(klen); 756 memmove(ecb->ahstate, key, klen); 757 } 758 759 static int 760 descipher(Espcb *ecb, uchar *p, int n) 761 { 762 uchar tmp[8]; 763 uchar *pp, *tp, *ip, *eip, *ep; 764 DESstate *ds = ecb->espstate; 765 766 ep = p + n; 767 if(ecb->incoming) { 768 memmove(ds->ivec, p, 8); 769 p += 8; 770 while(p < ep){ 771 memmove(tmp, p, 8); 772 block_cipher(ds->expanded, p, 1); 773 tp = tmp; 774 ip = ds->ivec; 775 for(eip = ip+8; ip < eip; ){ 776 *p++ ^= *ip; 777 *ip++ = *tp++; 778 } 779 } 780 } else { 781 memmove(p, ds->ivec, 8); 782 for(p += 8; p < ep; p += 8){ 783 pp = p; 784 ip = ds->ivec; 785 for(eip = ip+8; ip < eip; ) 786 *pp++ ^= *ip++; 787 block_cipher(ds->expanded, p, 0); 788 memmove(ds->ivec, p, 8); 789 } 790 } 791 return 1; 792 } 793 794 static void 795 desespinit(Espcb *ecb, char *name, uchar *k, int n) 796 { 797 uchar key[8], ivec[8]; 798 int i; 799 800 /* bits to bytes */ 801 n = (n+7)>>3; 802 if(n > 8) 803 n = 8; 804 memset(key, 0, sizeof(key)); 805 memmove(key, k, n); 806 for(i=0; i<8; i++) 807 ivec[i] = nrand(256); 808 ecb->espalg = name; 809 ecb->espblklen = 8; 810 ecb->espivlen = 8; 811 ecb->cipher = descipher; 812 ecb->espstate = smalloc(sizeof(DESstate)); 813 setupDESstate(ecb->espstate, key, ivec); 814 } 815 816 void 817 espinit(Fs *fs) 818 { 819 Proto *esp; 820 821 esp = smalloc(sizeof(Proto)); 822 esp->priv = smalloc(sizeof(Esppriv)); 823 esp->name = "esp"; 824 esp->connect = espconnect; 825 esp->announce = nil; 826 esp->ctl = espctl; 827 esp->state = espstate; 828 esp->create = espcreate; 829 esp->close = espclose; 830 esp->rcv = espiput; 831 esp->advise = espadvise; 832 esp->stats = espstats; 833 esp->local = esplocal; 834 esp->remote = espremote; 835 esp->ipproto = IP_ESPPROTO; 836 esp->nc = Nchans; 837 esp->ptclsize = sizeof(Espcb); 838 839 Fsproto(fs, esp); 840 } 841 842 843 #ifdef notdef 844 enum { 845 RC4forward= 10*1024*1024, /* maximum skip forward */ 846 RC4back = 100*1024, /* maximum look back */ 847 }; 848 849 typedef struct Esprc4 Esprc4; 850 struct Esprc4 851 { 852 ulong cseq; /* current byte sequence number */ 853 RC4state current; 854 855 int ovalid; /* old is valid */ 856 ulong lgseq; /* last good sequence */ 857 ulong oseq; /* old byte sequence number */ 858 RC4state old; 859 }; 860 861 static void rc4espinit(Espcb *ecb, char *name, uchar *k, int n); 862 863 static int 864 rc4cipher(Espcb *ecb, uchar *p, int n) 865 { 866 Esprc4 *esprc4; 867 RC4state tmpstate; 868 ulong seq; 869 long d, dd; 870 871 if(n < 4) 872 return 0; 873 874 esprc4 = ecb->espstate; 875 if(ecb->incoming) { 876 seq = nhgetl(p); 877 p += 4; 878 n -= 4; 879 d = seq-esprc4->cseq; 880 if(d == 0) { 881 rc4(&esprc4->current, p, n); 882 esprc4->cseq += n; 883 if(esprc4->ovalid) { 884 dd = esprc4->cseq - esprc4->lgseq; 885 if(dd > RC4back) 886 esprc4->ovalid = 0; 887 } 888 } else if(d > 0) { 889 print("esp rc4cipher: missing packet: %uld %ld\n", seq, d); /* this link is hosed */ 890 if(d > RC4forward) { 891 strcpy(up->errstr, "rc4cipher: skipped too much"); 892 return 0; 893 } 894 esprc4->lgseq = seq; 895 if(!esprc4->ovalid) { 896 esprc4->ovalid = 1; 897 esprc4->oseq = esprc4->cseq; 898 memmove(&esprc4->old, &esprc4->current, 899 sizeof(RC4state)); 900 } 901 rc4skip(&esprc4->current, d); 902 rc4(&esprc4->current, p, n); 903 esprc4->cseq = seq+n; 904 } else { 905 print("esp rc4cipher: reordered packet: %uld %ld\n", seq, d); 906 dd = seq - esprc4->oseq; 907 if(!esprc4->ovalid || -d > RC4back || dd < 0) { 908 strcpy(up->errstr, "rc4cipher: too far back"); 909 return 0; 910 } 911 memmove(&tmpstate, &esprc4->old, sizeof(RC4state)); 912 rc4skip(&tmpstate, dd); 913 rc4(&tmpstate, p, n); 914 return 1; 915 } 916 917 /* move old state up */ 918 if(esprc4->ovalid) { 919 dd = esprc4->cseq - RC4back - esprc4->oseq; 920 if(dd > 0) { 921 rc4skip(&esprc4->old, dd); 922 esprc4->oseq += dd; 923 } 924 } 925 } else { 926 hnputl(p, esprc4->cseq); 927 p += 4; 928 n -= 4; 929 rc4(&esprc4->current, p, n); 930 esprc4->cseq += n; 931 } 932 return 1; 933 } 934 935 static void 936 rc4espinit(Espcb *ecb, char *name, uchar *k, int n) 937 { 938 Esprc4 *esprc4; 939 940 /* bits to bytes */ 941 n = (n+7)>>3; 942 esprc4 = smalloc(sizeof(Esprc4)); 943 memset(esprc4, 0, sizeof(Esprc4)); 944 setupRC4state(&esprc4->current, k, n); 945 ecb->espalg = name; 946 ecb->espblklen = 4; 947 ecb->espivlen = 4; 948 ecb->cipher = rc4cipher; 949 ecb->espstate = esprc4; 950 } 951 #endif