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