2 * Encapsulating Security Payload for IPsec for IPv4, rfc1827.
4 * rfc2104 defines hmac computation.
5 * currently only implements tunnel mode.
6 * TODO: verify aes algorithms;
7 * transport mode (host-to-host)
10 #include "../port/lib.h"
14 #include "../port/error.h"
20 #define BITS2BYTES(bi) (((bi) + BI2BY - 1) / BI2BY)
21 #define BYTES2BITS(by) ((by) * BI2BY)
23 typedef struct Algorithm Algorithm;
24 typedef struct Esp4hdr Esp4hdr;
25 typedef struct Esp6hdr Esp6hdr;
26 typedef struct Espcb Espcb;
27 typedef struct Esphdr Esphdr;
28 typedef struct Esppriv Esppriv;
29 typedef struct Esptail Esptail;
30 typedef struct Userhdr Userhdr;
36 IP_ESPPROTO = 50, /* IP v4 and v6 protocol number */
37 Esp4hdrlen = IP4HDR + 8,
38 Esp6hdrlen = IP6HDR + 8,
40 Esptaillen = 2, /* does not include pad or auth data */
41 Userhdrlen = 4, /* user-visible header size - if enabled */
43 Desblk = BITS2BYTES(64),
44 Des3keysz = BITS2BYTES(192),
46 Aesblk = BITS2BYTES(128),
47 Aeskeysz = BITS2BYTES(128),
52 uchar espspi[4]; /* Security parameter index */
53 uchar espseq[4]; /* Sequence number */
58 * tunnel-mode (network-to-network, etc.) layout is:
59 * new IP hdrs | ESP hdr |
60 * enc { orig IP hdrs | TCP/UDP hdr | user data | ESP trailer } | ESP ICV
62 * transport-mode (host-to-host) layout would be:
63 * orig IP hdrs | ESP hdr |
64 * enc { TCP/UDP hdr | user data | ESP trailer } | ESP ICV
69 uchar vihl; /* Version and header length */
70 uchar tos; /* Type of service */
71 uchar length[2]; /* packet length */
72 uchar id[2]; /* Identification */
73 uchar frag[2]; /* Fragment information */
75 uchar espproto; /* Protocol */
76 uchar espplen[2]; /* Header plus data length */
77 uchar espsrc[4]; /* Ip source */
78 uchar espdst[4]; /* Ip destination */
83 /* tunnel-mode layout */
96 /* IP-version-dependent data */
97 typedef struct Versdep Versdep;
102 ulong hdrlen; /* iphdrlen + esp hdr len */
104 uchar laddr[IPaddrlen];
105 uchar raddr[IPaddrlen];
108 /* header as seen by the user */
111 uchar nexthdr; /* next protocol */
122 * protocol specific part of Conv
127 int header; /* user-level header */
129 ulong seq; /* last seq sent */
130 ulong window; /* for replay attacks */
133 void *espstate; /* other state for esp */
134 int espivlen; /* in bytes */
136 int (*cipher)(Espcb*, uchar *buf, int len);
139 void *ahstate; /* other state for esp */
140 int ahlen; /* auth data length in bytes */
142 int (*auth)(Espcb*, uchar *buf, int len, uchar *hash);
149 int keylen; /* in bits */
150 void (*init)(Espcb*, char* name, uchar *key, unsigned keylen);
153 static Conv* convlookup(Proto *esp, ulong spi);
154 static char *setalg(Espcb *ecb, char **f, int n, Algorithm *alg);
155 static void espkick(void *x);
157 static void nullespinit(Espcb*, char*, uchar *key, unsigned keylen);
158 static void des3espinit(Espcb*, char*, uchar *key, unsigned keylen);
159 static void aescbcespinit(Espcb*, char*, uchar *key, unsigned keylen);
160 static void aesctrespinit(Espcb*, char*, uchar *key, unsigned keylen);
161 static void desespinit(Espcb *ecb, char *name, uchar *k, unsigned n);
163 static void nullahinit(Espcb*, char*, uchar *key, unsigned keylen);
164 static void shaahinit(Espcb*, char*, uchar *key, unsigned keylen);
165 static void aesahinit(Espcb*, char*, uchar *key, unsigned keylen);
166 static void md5ahinit(Espcb*, char*, uchar *key, unsigned keylen);
168 static Algorithm espalg[] =
170 "null", 0, nullespinit,
171 "des3_cbc", 192, des3espinit, /* new rfc2451, des-ede3 */
172 "aes_128_cbc", 128, aescbcespinit, /* new rfc3602 */
173 "aes_ctr", 128, aesctrespinit, /* new rfc3686 */
174 "des_56_cbc", 64, desespinit, /* rfc2405, deprecated */
175 /* rc4 was never required, was used in original bandt */
176 // "rc4_128", 128, rc4espinit,
180 static Algorithm ahalg[] =
182 "null", 0, nullahinit,
183 "hmac_sha1_96", 128, shaahinit, /* rfc2404 */
184 "aes_xcbc_mac_96", 128, aesahinit, /* new rfc3566 */
185 "hmac_md5_96", 128, md5ahinit, /* rfc2403 */
190 espconnect(Conv *c, char **argv, int argc)
192 char *p, *pp, *e = nil;
194 Espcb *ecb = (Espcb*)c->ptcl;
198 e = "bad args to connect";
201 p = strchr(argv[1], '!');
203 e = "malformed address";
207 if (parseip(c->raddr, argv[1]) == -1) {
211 findlocalip(c->p->f, c->laddr, c->raddr);
214 if(strcmp(p, "*") == 0) {
217 spi = nrand(1<<16) + 256;
218 if(convlookup(c->p, spi) == nil)
226 spi = strtoul(p, &pp, 10);
228 e = "malformed address";
234 nullespinit(ecb, "null", nil, 0);
235 nullahinit(ecb, "null", nil, 0);
244 espstate(Conv *c, char *state, int n)
246 return snprint(state, n, "%s", c->inuse?"Open\n":"Closed\n");
252 c->rq = qopen(64*1024, Qmsg, 0, 0);
253 c->wq = qopen(64*1024, Qkick, espkick, c);
264 ipmove(c->laddr, IPnoaddr);
265 ipmove(c->raddr, IPnoaddr);
267 ecb = (Espcb*)c->ptcl;
270 memset(ecb, 0, sizeof(Espcb));
276 if((memcmp(c->raddr, v4prefix, IPv4off) == 0 &&
277 memcmp(c->laddr, v4prefix, IPv4off) == 0) ||
278 ipcmp(c->raddr, IPnoaddr) == 0)
285 pktipvers(Fs *f, Block **bpp)
287 if (*bpp == nil || BLEN(*bpp) == 0) {
288 /* get enough to identify the IP version */
289 *bpp = pullupblock(*bpp, IP4HDR);
291 netlog(f, Logesp, "esp: short packet\n");
295 return (((Esp4hdr*)(*bpp)->rp)->vihl & 0xf0) == IP_VER4? V4: V6;
299 getverslens(int version, Versdep *vp)
301 vp->version = version;
302 switch(vp->version) {
304 vp->iphdrlen = IP4HDR;
305 vp->hdrlen = Esp4hdrlen;
308 vp->iphdrlen = IP6HDR;
309 vp->hdrlen = Esp6hdrlen;
312 panic("esp: getverslens version %d wrong", version);
317 getpktspiaddrs(uchar *pkt, Versdep *vp)
322 switch(vp->version) {
325 v4tov6(vp->raddr, eh4->espsrc);
326 v4tov6(vp->laddr, eh4->espdst);
327 vp->spi = nhgetl(eh4->espspi);
331 ipmove(vp->raddr, eh6->src);
332 ipmove(vp->laddr, eh6->dst);
333 vp->spi = nhgetl(eh6->espspi);
336 panic("esp: getpktspiaddrs vp->version %ld wrong", vp->version);
341 * encapsulate next IP packet on x's write queue in IP/ESP packet
342 * and initiate output of the result.
347 int nexthdr, payload, pad, align;
358 getverslens(convipvers(c), &vers);
367 /* make sure the message has a User header */
368 bp = pullupblock(bp, Userhdrlen);
373 uh = (Userhdr*)bp->rp;
374 nexthdr = uh->nexthdr;
375 bp->rp += Userhdrlen;
377 nexthdr = 0; /* what should this be? */
380 payload = BLEN(bp) + ecb->espivlen;
382 /* Make space to fit ip header */
383 bp = padblock(bp, vers.hdrlen + ecb->espivlen);
384 getpktspiaddrs(bp->rp, &vers);
387 if(ecb->espblklen > align)
388 align = ecb->espblklen;
389 if(align % ecb->ahblklen != 0)
390 panic("espkick: ahblklen is important after all");
391 pad = (align-1) - (payload + Esptaillen-1)%align;
394 * Make space for tail
395 * this is done by calling padblock with a negative size
396 * Padblock does not change bp->wp!
398 bp = padblock(bp, -(pad+Esptaillen+ecb->ahlen));
399 bp->wp += pad+Esptaillen+ecb->ahlen;
401 et = (Esptail*)(bp->rp + vers.hdrlen + payload + pad);
405 et->nexthdr = nexthdr;
407 /* encrypt the payload */
408 ecb->cipher(ecb, bp->rp + vers.hdrlen, payload + pad + Esptaillen);
409 auth = bp->rp + vers.hdrlen + payload + pad + Esptaillen;
411 /* fill in head; construct a new IP header and an ESP header */
412 if (vers.version == V4) {
413 eh4 = (Esp4hdr *)bp->rp;
415 v6tov4(eh4->espsrc, c->laddr);
416 v6tov4(eh4->espdst, c->raddr);
417 eh4->espproto = IP_ESPPROTO;
421 hnputl(eh4->espspi, ecb->spi);
422 hnputl(eh4->espseq, ++ecb->seq);
424 eh6 = (Esp6hdr *)bp->rp;
425 eh6->vcf[0] = IP_VER6;
426 ipmove(eh6->src, c->laddr);
427 ipmove(eh6->dst, c->raddr);
428 eh6->proto = IP_ESPPROTO;
430 hnputl(eh6->espspi, ecb->spi);
431 hnputl(eh6->espseq, ++ecb->seq);
434 /* compute secure hash */
435 ecb->auth(ecb, bp->rp + vers.iphdrlen, (vers.hdrlen - vers.iphdrlen) +
436 payload + pad + Esptaillen, auth);
439 /* print("esp: pass down: %uld\n", BLEN(bp)); */
440 if (vers.version == V4)
441 ipoput4(c->p->f, bp, 0, c->ttl, c->tos, c);
443 ipoput6(c->p->f, bp, 0, c->ttl, c->tos, c);
447 * decapsulate IP packet from IP/ESP packet in bp and
448 * pass the result up the spi's Conv's read queue.
451 espiput(Proto *esp, Ipifc*, Block *bp)
453 int payload, nexthdr;
454 uchar *auth, *espspi;
464 getverslens(pktipvers(f, &bp), &vers);
466 bp = pullupblock(bp, vers.hdrlen + Esptaillen);
468 netlog(f, Logesp, "esp: short packet\n");
471 getpktspiaddrs(bp->rp, &vers);
474 /* Look for a conversation structure for this port */
475 c = convlookup(esp, vers.spi);
478 netlog(f, Logesp, "esp: no conv %I -> %I!%lud\n", vers.raddr,
479 vers.laddr, vers.spi);
489 /* too hard to do decryption/authentication on block lists */
491 bp = concatblock(bp);
493 if(BLEN(bp) < vers.hdrlen + ecb->espivlen + Esptaillen + ecb->ahlen) {
495 netlog(f, Logesp, "esp: short block %I -> %I!%lud\n", vers.raddr,
496 vers.laddr, vers.spi);
501 auth = bp->wp - ecb->ahlen;
502 espspi = vers.version == V4? ((Esp4hdr*)bp->rp)->espspi:
503 ((Esp6hdr*)bp->rp)->espspi;
505 /* compute secure hash and authenticate */
506 if(!ecb->auth(ecb, espspi, auth - espspi, auth)) {
508 print("esp: bad auth %I -> %I!%ld\n", vers.raddr, vers.laddr, vers.spi);
509 netlog(f, Logesp, "esp: bad auth %I -> %I!%lud\n", vers.raddr,
510 vers.laddr, vers.spi);
515 payload = BLEN(bp) - vers.hdrlen - ecb->ahlen;
516 if(payload <= 0 || payload % 4 != 0 || payload % ecb->espblklen != 0) {
518 netlog(f, Logesp, "esp: bad length %I -> %I!%lud payload=%d BLEN=%lud\n",
519 vers.raddr, vers.laddr, vers.spi, payload, BLEN(bp));
524 /* decrypt payload */
525 if(!ecb->cipher(ecb, bp->rp + vers.hdrlen, payload)) {
527 print("esp: cipher failed %I -> %I!%ld: %s\n", vers.raddr, vers.laddr, vers.spi, up->errstr);
528 netlog(f, Logesp, "esp: cipher failed %I -> %I!%lud: %s\n",
529 vers.raddr, vers.laddr, vers.spi, up->errstr);
534 payload -= Esptaillen;
535 et = (Esptail*)(bp->rp + vers.hdrlen + payload);
536 payload -= et->pad + ecb->espivlen;
537 nexthdr = et->nexthdr;
540 netlog(f, Logesp, "esp: short packet after decrypt %I -> %I!%lud\n",
541 vers.raddr, vers.laddr, vers.spi);
547 bp->rp += vers.hdrlen + ecb->espivlen; /* toss original IP & ESP hdrs */
548 bp->wp = bp->rp + payload;
550 /* assume Userhdrlen < Esp4hdrlen < Esp6hdrlen */
551 bp->rp -= Userhdrlen;
552 uh = (Userhdr*)bp->rp;
553 memset(uh, 0, Userhdrlen);
554 uh->nexthdr = nexthdr;
557 /* ingress filtering here? */
560 netlog(f, Logesp, "esp: qfull %I -> %I.%uld\n", vers.raddr,
561 vers.laddr, vers.spi);
564 // print("esp: pass up: %uld\n", BLEN(bp));
565 qpass(c->rq, bp); /* pass packet up the read queue */
572 espctl(Conv *c, char **f, int n)
574 Espcb *ecb = c->ptcl;
577 if(strcmp(f[0], "esp") == 0)
578 e = setalg(ecb, f, n, espalg);
579 else if(strcmp(f[0], "ah") == 0)
580 e = setalg(ecb, f, n, ahalg);
581 else if(strcmp(f[0], "header") == 0)
583 else if(strcmp(f[0], "noheader") == 0)
586 e = "unknown control request";
590 /* called from icmp(v6) for unreachable hosts, time exceeded, etc. */
592 espadvise(Proto *esp, Block *bp, char *msg)
597 getverslens(pktipvers(esp->f, &bp), &vers);
598 getpktspiaddrs(bp->rp, &vers);
601 c = convlookup(esp, vers.spi);
611 espstats(Proto *esp, char *buf, int len)
616 return snprint(buf, len, "%llud %lud\n",
622 esplocal(Conv *c, char *buf, int len)
624 Espcb *ecb = c->ptcl;
629 n = snprint(buf, len, "%I!%uld\n", c->laddr, ecb->spi);
631 n = snprint(buf, len, "%I\n", c->laddr);
637 espremote(Conv *c, char *buf, int len)
639 Espcb *ecb = c->ptcl;
644 n = snprint(buf, len, "%I\n", c->raddr);
646 n = snprint(buf, len, "%I!%uld\n", c->raddr, ecb->spi);
652 convlookup(Proto *esp, ulong spi)
657 for(p=esp->conv; *p; p++){
660 if(ecb->incoming && ecb->spi == spi)
667 setalg(Espcb *ecb, char **f, int n, Algorithm *alg)
675 for(; alg->name; alg++)
676 if(strcmp(f[1], alg->name) == 0)
679 return "unknown algorithm";
681 nbyte = (alg->keylen + 7) >> 3;
685 nchar = strlen(f[2]);
686 if(nchar != 2 * nbyte) /* TODO: maybe < is ok */
687 return "key not required length";
688 /* convert hex digits from ascii, in place */
689 for(i=0; i<nchar; i++) {
691 if(c >= '0' && c <= '9')
693 else if(c >= 'a' && c <= 'f')
695 else if(c >= 'A' && c <= 'F')
698 return "non-hex character in key";
700 /* collapse hex digits into complete bytes in reverse order in key */
701 key = smalloc(nbyte);
702 for(i = 0; i < nchar && i/2 < nbyte; i++) {
709 alg->init(ecb, alg->name, key, alg->keylen);
720 nullcipher(Espcb*, uchar*, int)
726 nullespinit(Espcb *ecb, char *name, uchar*, unsigned)
731 ecb->cipher = nullcipher;
735 nullauth(Espcb*, uchar*, int, uchar*)
741 nullahinit(Espcb *ecb, char *name, uchar*, unsigned)
746 ecb->auth = nullauth;
755 seanq_hmac_sha1(uchar hash[SHA1dlen], uchar *t, long tlen, uchar *key, long klen)
758 uchar ipad[Hmacblksz+1], opad[Hmacblksz+1], innerhash[SHA1dlen];
761 memset(ipad, 0x36, Hmacblksz);
762 memset(opad, 0x5c, Hmacblksz);
763 ipad[Hmacblksz] = opad[Hmacblksz] = 0;
764 for(i = 0; i < klen; i++){
768 digest = sha1(ipad, Hmacblksz, nil, nil);
769 sha1(t, tlen, innerhash, digest);
770 digest = sha1(opad, Hmacblksz, nil, nil);
771 sha1(innerhash, SHA1dlen, hash, digest);
775 shaauth(Espcb *ecb, uchar *t, int tlen, uchar *auth)
778 uchar hash[SHA1dlen];
780 memset(hash, 0, SHA1dlen);
781 seanq_hmac_sha1(hash, t, tlen, (uchar*)ecb->ahstate, BITS2BYTES(128));
782 r = memcmp(auth, hash, ecb->ahlen) == 0;
783 memmove(auth, hash, ecb->ahlen);
788 shaahinit(Espcb *ecb, char *name, uchar *key, unsigned klen)
791 panic("shaahinit: bad keylen");
796 ecb->ahlen = BITS2BYTES(96);
798 ecb->ahstate = smalloc(klen);
799 memmove(ecb->ahstate, key, klen);
807 /* ah_aes_xcbc_mac_96, rfc3566 */
809 aesahauth(Espcb *ecb, uchar *t, int tlen, uchar *auth)
814 memset(hash, 0, AESdlen);
815 ecb->ds = hmac_aes(t, tlen, (uchar*)ecb->ahstate, BITS2BYTES(96), hash,
817 r = memcmp(auth, hash, ecb->ahlen) == 0;
818 memmove(auth, hash, ecb->ahlen);
823 aesahinit(Espcb *ecb, char *name, uchar *key, unsigned klen)
826 panic("aesahinit: keylen not 128");
831 ecb->ahlen = BITS2BYTES(96);
832 ecb->auth = aesahauth;
833 ecb->ahstate = smalloc(klen);
834 memmove(ecb->ahstate, key, klen);
838 aescbccipher(Espcb *ecb, uchar *p, int n) /* 128-bit blocks */
840 uchar tmp[AESbsize], q[AESbsize];
841 uchar *pp, *tp, *ip, *eip, *ep;
842 AESstate *ds = ecb->espstate;
846 memmove(ds->ivec, p, AESbsize);
849 memmove(tmp, p, AESbsize);
850 aes_decrypt(ds->dkey, ds->rounds, p, q);
851 memmove(p, q, AESbsize);
854 for(eip = ip + AESbsize; ip < eip; ){
860 memmove(p, ds->ivec, AESbsize);
861 for(p += AESbsize; p < ep; p += AESbsize){
864 for(eip = ip + AESbsize; ip < eip; )
866 aes_encrypt(ds->ekey, ds->rounds, p, q);
867 memmove(ds->ivec, q, AESbsize);
868 memmove(p, q, AESbsize);
875 aescbcespinit(Espcb *ecb, char *name, uchar *k, unsigned n)
877 uchar key[Aeskeysz], ivec[Aeskeysz];
883 memset(key, 0, sizeof(key));
885 for(i = 0; i < Aeskeysz; i++)
886 ivec[i] = nrand(256);
888 ecb->espblklen = Aesblk;
889 ecb->espivlen = Aesblk;
890 ecb->cipher = aescbccipher;
891 ecb->espstate = smalloc(sizeof(AESstate));
892 setupAESstate(ecb->espstate, key, n /* keybytes */, ivec);
896 aesctrcipher(Espcb *ecb, uchar *p, int n) /* 128-bit blocks */
898 uchar tmp[AESbsize], q[AESbsize];
899 uchar *pp, *tp, *ip, *eip, *ep;
900 AESstate *ds = ecb->espstate;
904 memmove(ds->ivec, p, AESbsize);
907 memmove(tmp, p, AESbsize);
908 aes_decrypt(ds->dkey, ds->rounds, p, q);
909 memmove(p, q, AESbsize);
912 for(eip = ip + AESbsize; ip < eip; ){
918 memmove(p, ds->ivec, AESbsize);
919 for(p += AESbsize; p < ep; p += AESbsize){
922 for(eip = ip + AESbsize; ip < eip; )
924 aes_encrypt(ds->ekey, ds->rounds, p, q);
925 memmove(ds->ivec, q, AESbsize);
926 memmove(p, q, AESbsize);
933 aesctrespinit(Espcb *ecb, char *name, uchar *k, unsigned n)
935 uchar key[Aesblk], ivec[Aesblk];
941 memset(key, 0, sizeof(key));
943 for(i = 0; i < Aesblk; i++)
944 ivec[i] = nrand(256);
946 ecb->espblklen = Aesblk;
947 ecb->espivlen = Aesblk;
948 ecb->cipher = aesctrcipher;
949 ecb->espstate = smalloc(sizeof(AESstate));
950 setupAESstate(ecb->espstate, key, n /* keybytes */, ivec);
959 seanq_hmac_md5(uchar hash[MD5dlen], uchar *t, long tlen, uchar *key, long klen)
962 uchar ipad[Hmacblksz+1], opad[Hmacblksz+1], innerhash[MD5dlen];
965 memset(ipad, 0x36, Hmacblksz);
966 memset(opad, 0x5c, Hmacblksz);
967 ipad[Hmacblksz] = opad[Hmacblksz] = 0;
968 for(i = 0; i < klen; i++){
972 digest = md5(ipad, Hmacblksz, nil, nil);
973 md5(t, tlen, innerhash, digest);
974 digest = md5(opad, Hmacblksz, nil, nil);
975 md5(innerhash, MD5dlen, hash, digest);
979 md5auth(Espcb *ecb, uchar *t, int tlen, uchar *auth)
984 memset(hash, 0, MD5dlen);
985 seanq_hmac_md5(hash, t, tlen, (uchar*)ecb->ahstate, BITS2BYTES(128));
986 r = memcmp(auth, hash, ecb->ahlen) == 0;
987 memmove(auth, hash, ecb->ahlen);
992 md5ahinit(Espcb *ecb, char *name, uchar *key, unsigned klen)
995 panic("md5ahinit: bad keylen");
996 klen = BITS2BYTES(klen);
999 ecb->ahlen = BITS2BYTES(96);
1000 ecb->auth = md5auth;
1001 ecb->ahstate = smalloc(klen);
1002 memmove(ecb->ahstate, key, klen);
1007 * des, single and triple
1011 descipher(Espcb *ecb, uchar *p, int n)
1013 DESstate *ds = ecb->espstate;
1016 memmove(ds->ivec, p, Desblk);
1017 desCBCdecrypt(p + Desblk, n - Desblk, ds);
1019 memmove(p, ds->ivec, Desblk);
1020 desCBCencrypt(p + Desblk, n - Desblk, ds);
1026 des3cipher(Espcb *ecb, uchar *p, int n)
1028 DES3state *ds = ecb->espstate;
1031 memmove(ds->ivec, p, Desblk);
1032 des3CBCdecrypt(p + Desblk, n - Desblk, ds);
1034 memmove(p, ds->ivec, Desblk);
1035 des3CBCencrypt(p + Desblk, n - Desblk, ds);
1041 desespinit(Espcb *ecb, char *name, uchar *k, unsigned n)
1043 uchar key[Desblk], ivec[Desblk];
1049 memset(key, 0, sizeof(key));
1051 for(i = 0; i < Desblk; i++)
1052 ivec[i] = nrand(256);
1054 ecb->espblklen = Desblk;
1055 ecb->espivlen = Desblk;
1057 ecb->cipher = descipher;
1058 ecb->espstate = smalloc(sizeof(DESstate));
1059 setupDESstate(ecb->espstate, key, ivec);
1063 des3espinit(Espcb *ecb, char *name, uchar *k, unsigned n)
1065 uchar key[3][Desblk], ivec[Desblk];
1071 memset(key, 0, sizeof(key));
1073 for(i = 0; i < Desblk; i++)
1074 ivec[i] = nrand(256);
1076 ecb->espblklen = Desblk;
1077 ecb->espivlen = Desblk;
1079 ecb->cipher = des3cipher;
1080 ecb->espstate = smalloc(sizeof(DES3state));
1081 setupDES3state(ecb->espstate, key, ivec);
1086 * interfacing to devip
1093 esp = smalloc(sizeof(Proto));
1094 esp->priv = smalloc(sizeof(Esppriv));
1096 esp->connect = espconnect;
1097 esp->announce = nil;
1099 esp->state = espstate;
1100 esp->create = espcreate;
1101 esp->close = espclose;
1103 esp->advise = espadvise;
1104 esp->stats = espstats;
1105 esp->local = esplocal;
1106 esp->remote = espremote;
1107 esp->ipproto = IP_ESPPROTO;
1109 esp->ptclsize = sizeof(Espcb);