xref: /inferno-os/libinterp/keyring.c (revision 9bca6be9bfa93b52aeefad1e0ea9965d1fa5c53c)
1 #include "lib9.h"
2 #include "kernel.h"
3 #include <isa.h>
4 #include "interp.h"
5 #include "runt.h"
6 #include "keyring.h"
7 #include <mp.h>
8 #include <libsec.h>
9 #include "pool.h"
10 #include "raise.h"
11 #include "../libkeyring/keys.h"
12 
13 
14 Type	*TSigAlg;
15 Type	*TCertificate;
16 Type	*TSK;
17 Type	*TPK;
18 Type	*TDigestState;
19 Type	*TAuthinfo;
20 Type *TAESstate;
21 Type	*TDESstate;
22 Type *TIDEAstate;
23 Type *TBFstate;
24 Type	*TRC4state;
25 Type	*TIPint;
26 Type *TDSAsk;
27 Type *TDSApk;
28 Type *TDSAsig;
29 Type *TEGsk;
30 Type *TEGpk;
31 Type *TEGsig;
32 Type *TRSAsk;
33 Type *TRSApk;
34 Type *TRSAsig;
35 
36 enum {
37 	Maxmsg=	4096
38 };
39 
40 uchar IPintmap[] = Keyring_IPint_map;
41 uchar SigAlgmap[] = Keyring_SigAlg_map;
42 uchar SKmap[] = Keyring_SK_map;
43 uchar PKmap[] = Keyring_PK_map;
44 uchar Certificatemap[] = Keyring_Certificate_map;
45 uchar DigestStatemap[] = Keyring_DigestState_map;
46 uchar Authinfomap[] = Keyring_Authinfo_map;
47 uchar AESstatemap[] = Keyring_AESstate_map;
48 uchar DESstatemap[] = Keyring_DESstate_map;
49 uchar IDEAstatemap[] = Keyring_IDEAstate_map;
50 uchar BFstatemap[] = Keyring_BFstate_map;
51 uchar RC4statemap[] = Keyring_RC4state_map;
52 uchar DSAskmap[] = Keyring_DSAsk_map;
53 uchar DSApkmap[] = Keyring_DSApk_map;
54 uchar DSAsigmap[] = Keyring_DSAsig_map;
55 uchar EGskmap[] = Keyring_EGsk_map;
56 uchar EGpkmap[] = Keyring_EGpk_map;
57 uchar EGsigmap[] = Keyring_EGsig_map;
58 uchar RSAskmap[] = Keyring_RSAsk_map;
59 uchar RSApkmap[] = Keyring_RSApk_map;
60 uchar RSAsigmap[] = Keyring_RSAsig_map;
61 
62 PK*	checkPK(Keyring_PK *k);
63 
64 extern void		setid(char*, int);
65 extern vlong		osusectime(void);
66 extern Keyring_IPint*	newIPint(mpint*);
67 extern mpint*	checkIPint(Keyring_IPint*);
68 extern void		freeIPint(Heap*, int);
69 
70 static char exBadSA[]	= "bad signature algorithm";
71 static char exBadSK[]	= "bad secret key";
72 static char exBadPK[]	= "bad public key";
73 static char exBadCert[]	= "bad certificate";
74 static char exBadBsize[]	= "data not multiple of block size";
75 static char exBadKey[]	= "bad encryption key";
76 static char exBadDigest[]	= "bad digest value";
77 static char exBadIvec[]	= "bad ivec";
78 static char exBadState[] = "bad encryption state";
79 
80 typedef struct XBFstate XBFstate;
81 
82 /* BF state */
83 struct XBFstate
84 {
85 	Keyring_BFstate	x;
86 	BFstate	state;
87 };
88 
89 /*
90  *  Infinite (actually kind of big) precision integers
91  */
92 
93 /* convert a Big to base64 ascii */
94 int
95 bigtobase64(mpint* b, char *buf, int len)
96 {
97 	uchar *p;
98 	int n, rv, o;
99 
100 	n = (b->top+1)*Dbytes;
101 	p = malloc(n+1);
102 	if(p == nil)
103 		goto Err;
104 	n = mptobe(b, p+1, n, nil);
105 	if(n < 0)
106 		goto Err;
107 	p[0] = 0;
108 	if(n != 0 && (p[1]&0x80)){
109 		/* force leading 0 byte for compatibility with older representation */
110 		/* TO DO: if b->sign < 0, complement bits and add one */
111 		o = 0;
112 		n++;
113 	}else
114 		o = 1;
115 	rv = enc64(buf, len, p+o, n);
116 	free(p);
117 	return rv;
118 
119 Err:
120 	free(p);
121 	if(len > 0){
122 		*buf = '*';
123 		return 1;
124 	}
125 	return 0;
126 }
127 
128 /* convert a Big to base64 ascii for %U */
129 int
130 big64conv(Fmt *f)
131 {
132 	mpint *b;
133 	char *buf;
134 	int n;
135 
136 	b = va_arg(f->args, mpint*);
137 	n = (b->top+1)*Dbytes + 1;
138 	n = ((n+3)/3)*4 + 1;
139 	buf = malloc(n);
140 	bigtobase64(b, buf, n);
141 	n = fmtstrcpy(f, buf);
142 	free(buf);
143 	return  n;
144 }
145 
146 static void*
147 newthing(Type *t, int add)
148 {
149 	Heap *h;
150 
151 	h = heap(t);
152 	if(add)
153 		ptradd(h);
154 	return H2D(void*, h);
155 }
156 
157 static Keyring_IPint*
158 ipcopymp(mpint* b)
159 {
160 	if(b == nil)
161 		return H;
162 	return newIPint(mpcopy(b));
163 }
164 
165 /* convert a base64 string to a big */
166 mpint*
167 base64tobig(char *str, char **strp)
168 {
169 	int n;
170 	char *p;
171 	mpint *b;
172 	uchar hex[(MaxBigBytes*6 + 7)/8];
173 
174 	for(p = str; *p && *p != '\n'; p++)
175 		;
176 	if(p == str)
177 		return nil;
178 	n = dec64(hex, sizeof(hex), str, p - str);
179 	b = betomp(hex, n, nil);
180 	if(strp){
181 		if(*p)
182 			p++;
183 		*strp = p;
184 	}
185 	return b;
186 }
187 
188 /*
189  *  signature algorithms
190  */
191 enum
192 {
193 	Maxalg = 8
194 };
195 static SigAlgVec	*algs[Maxalg];
196 static int		nalg;
197 
198 static SigAlg*
199 newSigAlg(SigAlgVec *vec)
200 {
201 	Heap *h;
202 	SigAlg *sa;
203 
204 	h = heap(TSigAlg);
205 	sa = H2D(SigAlg*, h);
206 	retstr(vec->name, &sa->x.name);
207 	sa->vec = vec;
208 	return sa;
209 }
210 
211 static void
212 freeSigAlg(Heap *h, int swept)
213 {
214 	if(!swept)
215 		freeheap(h, 0);
216 }
217 
218 SigAlgVec*
219 findsigalg(char *name)
220 {
221 	SigAlgVec **sap;
222 
223 	for(sap = algs; sap < &algs[nalg]; sap++)
224 		if(strcmp(name, (*sap)->name) == 0)
225 			return *sap;
226 	return nil;
227 }
228 
229 SigAlg*
230 strtoalg(char *str, char **strp)
231 {
232 	int n;
233 	char *p, name[20];
234 	SigAlgVec *sa;
235 
236 
237 	p = strchr(str, '\n');
238 	if(p == 0){
239 		p = str + strlen(str);
240 		if(strp)
241 			*strp = p;
242 	} else {
243 		if(strp)
244 			*strp = p+1;
245 	}
246 
247 	n = p - str;
248 	if(n < sizeof(name)){
249 		strncpy(name, str, n);
250 		name[n] = 0;
251 		sa = findsigalg(name);
252 		if(sa != nil)
253 			return newSigAlg(sa);
254 	}
255 	return nil;
256 }
257 
258 static SigAlg*
259 checkSigAlg(Keyring_SigAlg *ksa)
260 {
261 	SigAlgVec **sap;
262 	SigAlg *sa;
263 
264 	sa = (SigAlg*)ksa;
265 
266 	for(sap = algs; sap < &algs[Maxalg]; sap++)
267 		if(sa->vec == *sap)
268 			return sa;
269 	errorf("%s: %s", exType, exBadSA);
270 	return nil;
271 }
272 
273 /*
274  *  parse next new line terminated string into a String
275  */
276 String*
277 strtostring(char *str, char **strp)
278 {
279 	char *p;
280 	String *s;
281 
282 	p = strchr(str, '\n');
283 	if(p == 0)
284 		p = str + strlen(str);
285 	s = H;
286 	retnstr(str, p - str, &s);
287 
288 	if(strp){
289 		if(*p)
290 			p++;
291 		*strp = p;
292 	}
293 
294 	return s;
295 }
296 
297 /*
298  *  private part of a key
299  */
300 static SK*
301 newSK(SigAlg *sa, String *owner, int increfsa)
302 {
303 	Heap *h;
304 	SK *k;
305 
306 	h = heap(TSK);
307 	k = H2D(SK*, h);
308 	k->x.sa = (Keyring_SigAlg*)sa;
309 	if(increfsa) {
310 		h = D2H(sa);
311 		h->ref++;
312 		Setmark(h);
313 	}
314 	k->x.owner = owner;
315 	k->key = 0;
316 	return k;
317 }
318 
319 static void
320 freeSK(Heap *h, int swept)
321 {
322 	SK *k;
323 	SigAlg *sa;
324 
325 	k = H2D(SK*, h);
326 	sa = checkSigAlg(k->x.sa);
327 	if(k->key)
328 		(*sa->vec->skfree)(k->key);
329 	freeheap(h, swept);
330 }
331 
332 static SK*
333 checkSK(Keyring_SK *k)
334 {
335 	SK *sk;
336 
337 	sk = (SK*)k;
338 	if(sk == H || sk == nil || sk->key == 0 || D2H(sk)->t != TSK){
339 		errorf("%s: %s", exType, exBadSK);
340 		return nil;
341 	}
342 	return sk;
343 }
344 
345 void
346 Keyring_genSK(void *fp)
347 {
348 	F_Keyring_genSK *f;
349 	SK *sk;
350 	SigAlg *sa;
351 	void *v;
352 
353 	f = fp;
354 	v = *f->ret;
355 	*f->ret = H;
356 	destroy(v);
357 
358 	sa = strtoalg(string2c(f->algname), 0);
359 	if(sa == nil)
360 		return;
361 
362 	sk = newSK(sa, stringdup(f->owner), 0);
363 	*f->ret = (Keyring_SK*)sk;
364 	release();
365 	sk->key = (*sa->vec->gensk)(f->length);
366 	acquire();
367 }
368 
369 void
370 Keyring_genSKfromPK(void *fp)
371 {
372 	F_Keyring_genSKfromPK *f;
373 	SigAlg *sa;
374 	PK *pk;
375 	SK *sk;
376 	void *v;
377 
378 	f = fp;
379 	v = *f->ret;
380 	*f->ret = H;
381 	destroy(v);
382 
383 	pk = checkPK(f->pk);
384 	sa = checkSigAlg(pk->x.sa);
385 	sk = newSK(sa, stringdup(f->owner), 1);
386 	*f->ret = (Keyring_SK*)sk;
387 	release();
388 	sk->key = (*sa->vec->genskfrompk)(pk->key);
389 	acquire();
390 }
391 
392 /* converts a sequence of newline-separated base64-encoded mpints to attr=hexval ... in f */
393 static char*
394 bigs2attr(Fmt *f, char *bigs, char **names)
395 {
396 	int i, n, nd;
397 	char *b16, *vals[20];
398 	uchar data[(MaxBigBytes*6 + 7)/8];
399 
400 	b16 = malloc(2*MaxBigBytes+1);
401 	if(b16 == nil)
402 		return nil;
403 	n = getfields(bigs, vals, nelem(vals), 0, "\n");
404 	for(i = 0; i < n-1; i++){
405 		if(names == nil || names[i] == nil)
406 			break;	/* shouldn't happen */
407 		nd = dec64(data, sizeof(data), vals[i], strlen(vals[i]));
408 		if(nd < 0)
409 			break;
410 		enc16(b16, 2*MaxBigBytes+1, data, nd);
411 		fmtprint(f, " %s=%s", names[i], b16);
412 	}
413 	free(b16);
414 	return fmtstrflush(f);
415 }
416 
417 void
418 Keyring_sktoattr(void *fp)
419 {
420 	F_Keyring_sktoattr *f;
421 	char *val, *buf, *owner;
422 	SigAlg *sa;
423 	Fmt o;
424 	SK *sk;
425 
426 	f = fp;
427 	sk = checkSK(f->sk);
428 	sa = checkSigAlg(sk->x.sa);
429 	buf = malloc(Maxbuf);
430 	if(buf == nil){
431 		retstr(nil, f->ret);
432 		return;
433 	}
434 	(*sa->vec->sk2str)(sk->key, buf, Maxbuf);
435 	fmtstrinit(&o);
436 	fmtprint(&o, "alg=%q", string2c(sa->x.name));
437 	owner = string2c(sk->x.owner);
438 	if(*owner)
439 		fmtprint(&o, " owner=%q", owner);
440 	val = bigs2attr(&o, buf, sa->vec->skattr);
441 	free(buf);
442 	retstr(val, f->ret);
443 	free(val);
444 }
445 
446 static int
447 sktostr(SK *sk, char *buf, int len)
448 {
449 	int n;
450 	SigAlg *sa;
451 
452 	sa = checkSigAlg(sk->x.sa);
453 	n = snprint(buf, len, "%s\n%s\n", string2c(sa->x.name),
454 			string2c(sk->x.owner));
455 	return n + (*sa->vec->sk2str)(sk->key, buf+n, len - n);
456 }
457 
458 void
459 Keyring_sktostr(void *fp)
460 {
461 	F_Keyring_sktostr *f;
462 	char *buf;
463 
464 	f = fp;
465 	buf = malloc(Maxbuf);
466 
467 	if(buf)
468 		sktostr(checkSK(f->sk), buf, Maxbuf);
469 	retstr(buf, f->ret);
470 
471 	free(buf);
472 }
473 
474 static SK*
475 strtosk(char *buf)
476 {
477 	SK *sk;
478 	char *p;
479 	SigAlg *sa;
480 	String *owner;
481 	void *key;
482 
483 	sa = strtoalg(buf, &p);
484 	if(sa == nil)
485 		return H;
486 	owner = strtostring(p, &p);
487 	if(owner == H){
488 		destroy(sa);
489 		return H;
490 	}
491 
492 	key = (*sa->vec->str2sk)(p, &p);
493 	if(key == nil){
494 		destroy(sa);
495 		destroy(owner);
496 		return H;
497 	}
498 	sk = newSK(sa, owner, 0);
499 	sk->key = key;
500 
501 	return sk;
502 }
503 
504 void
505 Keyring_strtosk(void *fp)
506 {
507 	F_Keyring_strtosk *f;
508 	void *v;
509 
510 	f = fp;
511 	v = *f->ret;
512 	*f->ret = H;
513 	destroy(v);
514 	*f->ret = (Keyring_SK*)strtosk(string2c(f->s));
515 }
516 
517 /*
518  *  public part of a key
519  */
520 PK*
521 newPK(SigAlg *sa, String *owner, int increfsa)
522 {
523 	Heap *h;
524 	PK *k;
525 
526 	h = heap(TPK);
527 	k = H2D(PK*, h);
528 	k->x.sa = (Keyring_SigAlg*)sa;
529 	if(increfsa) {
530 		h = D2H(sa);
531 		h->ref++;
532 		Setmark(h);
533 	}
534 	k->x.owner = owner;
535 	k->key = 0;
536 	return k;
537 }
538 
539 void
540 pkimmutable(PK *k)
541 {
542 	poolimmutable(D2H(k));
543 	poolimmutable(D2H(k->x.sa));
544 	poolimmutable(D2H(k->x.sa->name));
545 	poolimmutable(D2H(k->x.owner));
546 }
547 
548 void
549 pkmutable(PK *k)
550 {
551 	poolmutable(D2H(k));
552 	poolmutable(D2H(k->x.sa));
553 	poolmutable(D2H(k->x.sa->name));
554 	poolmutable(D2H(k->x.owner));
555 }
556 
557 void
558 freePK(Heap *h, int swept)
559 {
560 	PK *k;
561 	SigAlg *sa;
562 
563 	k = H2D(PK*, h);
564 	sa = checkSigAlg(k->x.sa);
565 	if(k->key)
566 		(*sa->vec->pkfree)(k->key);
567 	freeheap(h, swept);
568 }
569 
570 PK*
571 checkPK(Keyring_PK *k)
572 {
573 	PK *pk;
574 
575 	pk = (PK*)k;
576 	if(pk == H || pk == nil || pk->key == 0 || D2H(pk)->t != TPK){
577 		errorf("%s: %s", exType, exBadPK);
578 		return nil;
579 	}
580 	return pk;
581 }
582 
583 void
584 Keyring_sktopk(void *fp)
585 {
586 	F_Keyring_sktopk *f;
587 	PK *pk;
588 	SigAlg *sa;
589 	SK *sk;
590 	void *r;
591 
592 	f = fp;
593 	r = *f->ret;
594 	*f->ret = H;
595 	destroy(r);
596 
597 	sk = checkSK(f->sk);
598 	sa = checkSigAlg(sk->x.sa);
599 	pk = newPK(sa, stringdup(sk->x.owner), 1);
600 	pk->key = (*sa->vec->sk2pk)(sk->key);
601 	*f->ret = (Keyring_PK*)pk;
602 }
603 
604 static int
605 pktostr(PK *pk, char *buf, int len)
606 {
607 	int n;
608 	SigAlg *sa;
609 
610 	sa = checkSigAlg(pk->x.sa);
611 	n = snprint(buf, len, "%s\n%s\n", string2c(sa->x.name), string2c(pk->x.owner));
612 	return n + (*sa->vec->pk2str)(pk->key, buf+n, len - n);
613 }
614 
615 void
616 Keyring_pktostr(void *fp)
617 {
618 	F_Keyring_pktostr *f;
619 	char *buf;
620 
621 	f = fp;
622 	buf = malloc(Maxbuf);
623 
624 	if(buf)
625 		pktostr(checkPK(f->pk), buf, Maxbuf);
626 	retstr(buf, f->ret);
627 
628 	free(buf);
629 }
630 
631 void
632 Keyring_pktoattr(void *fp)
633 {
634 	F_Keyring_pktoattr *f;
635 	char *val, *buf, *owner;
636 	SigAlg *sa;
637 	Fmt o;
638 	PK *pk;
639 
640 	f = fp;
641 	pk = checkPK(f->pk);
642 	sa = checkSigAlg(pk->x.sa);
643 	buf = malloc(Maxbuf);
644 	if(buf == nil){
645 		retstr(nil, f->ret);
646 		return;
647 	}
648 	(*sa->vec->pk2str)(pk->key, buf, Maxbuf);
649 	fmtstrinit(&o);
650 	fmtprint(&o, "alg=%q", string2c(sa->x.name));
651 	owner = string2c(pk->x.owner);
652 	if(*owner)
653 		fmtprint(&o, " owner=%q", owner);
654 	val = bigs2attr(&o, buf, sa->vec->pkattr);
655 	free(buf);
656 	retstr(val, f->ret);
657 	free(val);
658 }
659 
660 static PK*
661 strtopk(char *buf)
662 {
663 	PK *pk;
664 	char *p;
665 	SigAlg *sa;
666 	String *owner;
667 	void *key;
668 
669 	sa = strtoalg(buf, &p);
670 	if(sa == nil)
671 		return H;
672 	owner = strtostring(p, &p);
673 	if(owner == H){
674 		destroy(sa);
675 		return H;
676 	}
677 
678 	key = (*sa->vec->str2pk)(p, &p);
679 	if(key == nil){
680 		destroy(sa);
681 		destroy(owner);
682 		return H;
683 	}
684 	pk = newPK(sa, owner, 0);
685 	pk->key = key;
686 
687 	return pk;
688 }
689 
690 void
691 Keyring_strtopk(void *fp)
692 {
693 	F_Keyring_strtopk *f;
694 	void *v;
695 
696 	f = fp;
697 	v = *f->ret;
698 	*f->ret = H;
699 	destroy(v);
700 	*f->ret = (Keyring_PK*)strtopk(string2c(f->s));
701 }
702 
703 /*
704  *  Certificates/signatures
705  */
706 
707 void
708 certimmutable(Certificate *c)
709 {
710 	poolimmutable(D2H(c));
711 	poolimmutable(D2H(c->x.signer));
712 	poolimmutable(D2H(c->x.ha));
713 	poolimmutable(D2H(c->x.sa));
714 	poolimmutable(D2H(c->x.sa->name));
715 }
716 
717 void
718 certmutable(Certificate *c)
719 {
720 	poolmutable(D2H(c));
721 	poolmutable(D2H(c->x.signer));
722 	poolmutable(D2H(c->x.ha));
723 	Setmark(D2H(c->x.sa));
724 	poolmutable(D2H(c->x.sa));
725 	Setmark(D2H(c->x.sa->name));
726 	poolmutable(D2H(c->x.sa->name));
727 }
728 
729 Certificate*
730 newCertificate(SigAlg *sa, String *ha, String *signer, long exp, int increfsa)
731 {
732 	Heap *h;
733 	Certificate *c;
734 
735 	h = heap(TCertificate);
736 	c = H2D(Certificate*, h);
737 	c->x.sa = (Keyring_SigAlg*)sa;
738 	if(increfsa) {
739 		h = D2H(sa);
740 		h->ref++;
741 		Setmark(h);
742 	}
743 	c->x.signer = signer;
744 	c->x.ha = ha;
745 	c->x.exp = exp;
746 	c->signa = 0;
747 
748 	return c;
749 }
750 
751 void
752 freeCertificate(Heap *h, int swept)
753 {
754 	Certificate *c;
755 	SigAlg *sa;
756 
757 	c = H2D(Certificate*, h);
758 	sa = checkSigAlg(c->x.sa);
759 	if(c->signa)
760 		(*sa->vec->sigfree)(c->signa);
761 	freeheap(h, swept);
762 }
763 
764 Certificate*
765 checkCertificate(Keyring_Certificate *c)
766 {
767 	Certificate *cert;
768 
769 	cert = (Certificate*)c;
770 	if(cert == H || cert == nil || cert->signa == 0 || D2H(cert)->t != TCertificate){
771 		errorf("%s: %s", exType, exBadCert);
772 		return nil;
773 	}
774 	return cert;
775 }
776 
777 static int
778 certtostr(Certificate *c, char *buf, int len)
779 {
780 	SigAlg *sa;
781 	int n;
782 
783 	sa = checkSigAlg(c->x.sa);
784 	n = snprint(buf, len, "%s\n%s\n%s\n%d\n", string2c(sa->x.name),
785 		string2c(c->x.ha), string2c(c->x.signer), c->x.exp);
786 	return n + (*sa->vec->sig2str)(c->signa, buf+n, len - n);
787 }
788 
789 void
790 Keyring_certtostr(void *fp)
791 {
792 	F_Keyring_certtostr *f;
793 	char *buf;
794 
795 	f = fp;
796 	buf = malloc(Maxbuf);
797 
798 	if(buf)
799 		certtostr(checkCertificate(f->c), buf, Maxbuf);
800 	retstr(buf, f->ret);
801 
802 	free(buf);
803 }
804 
805 void
806 Keyring_certtoattr(void *fp)
807 {
808 	F_Keyring_certtoattr *f;
809 	char *val, *buf, *ha;
810 	SigAlg *sa;
811 	Fmt o;
812 	Certificate *c;
813 
814 	f = fp;
815 	c = checkCertificate(f->c);
816 	sa = checkSigAlg(c->x.sa);
817 	buf = malloc(Maxbuf);
818 	if(buf == nil){
819 		retstr(nil, f->ret);
820 		return;
821 	}
822 	(*sa->vec->sig2str)(c->signa, buf, Maxbuf);
823 	ha = string2c(c->x.ha);
824 	if(strcmp(ha, "sha") == 0)
825 		ha = "sha1";	/* normalise */
826 	fmtstrinit(&o);
827 	fmtprint(&o, "sigalg=%q-%q signer=%q expires=%ud", string2c(sa->x.name), ha,
828 		string2c(c->x.signer), c->x.exp);
829 	val = bigs2attr(&o, buf, sa->vec->sigattr);
830 	free(buf);
831 	retstr(val, f->ret);
832 	free(val);
833 }
834 
835 static Certificate*
836 strtocert(char *buf)
837 {
838 	Certificate *c;
839 	char *p;
840 	SigAlg *sa;
841 	String *signer, *ha;
842 	long exp;
843 	void *signa;
844 
845 	sa = strtoalg(buf, &p);
846 	if(sa == 0)
847 		return H;
848 
849 	ha = strtostring(p, &p);
850 	if(ha == H){
851 		destroy(sa);
852 		return H;
853 	}
854 
855 	signer = strtostring(p, &p);
856 	if(signer == H){
857 		destroy(sa);
858 		destroy(ha);
859 		return H;
860 	}
861 
862 	exp = strtoul(p, &p, 10);
863 	if(*p)
864 		p++;
865 	signa = (*sa->vec->str2sig)(p, &p);
866 	if(signa == nil){
867 		destroy(sa);
868 		destroy(ha);
869 		destroy(signer);
870 		return H;
871 	}
872 
873 	c = newCertificate(sa, ha, signer, exp, 0);
874 	c->signa = signa;
875 
876 	return c;
877 }
878 
879 void
880 Keyring_strtocert(void *fp)
881 {
882 	F_Keyring_strtocert *f;
883 	void *r;
884 
885 	f = fp;
886 	r = *f->ret;
887 	*f->ret = H;
888 	destroy(r);
889 	*f->ret = (Keyring_Certificate*)strtocert(string2c(f->s));
890 }
891 
892 static Certificate*
893 sign(SK *sk, char *ha, ulong exp, uchar *a, int len)
894 {
895 	Certificate *c;
896 	mpint *b;
897 	int n;
898 	SigAlg *sa;
899 	DigestState *ds;
900 	uchar digest[SHA1dlen];
901 	char *buf;
902 	String *hastr;
903 
904 	hastr = H;
905 	sa = checkSigAlg(sk->x.sa);
906 	buf = malloc(Maxbuf);
907 	if(buf == nil)
908 		return nil;
909 
910 	/* add signer name and expiration time to hash */
911 	n = snprint(buf, Maxbuf, "%s %lud", string2c(sk->x.owner), exp);
912 	if(strcmp(ha, "sha") == 0 || strcmp(ha, "sha1") == 0){
913 		ds = sha1(a, len, 0, 0);
914 		sha1((uchar*)buf, n, digest, ds);
915 		n = Keyring_SHA1dlen;
916 	} else if(strcmp(ha, "md5") == 0){
917 		ds = md5(a, len, 0, 0);
918 		md5((uchar*)buf, n, digest, ds);
919 		n = Keyring_MD5dlen;
920 	} else if(strcmp(ha, "md4") == 0){
921 		ds = md4(a, len, 0, 0);
922 		md4((uchar*)buf, n, digest, ds);
923 		n = Keyring_MD5dlen;
924 	} else {
925 		free(buf);
926 		return nil;
927 	}
928 	free(buf);
929 
930 	/* turn message into a big integer */
931 	b = betomp(digest, n, nil);
932 	if(b == nil)
933 		return nil;
934 
935 	/* sign */
936 	retstr(ha, &hastr);
937 	c = newCertificate(sa, hastr, stringdup(sk->x.owner), exp, 1);
938 	certimmutable(c);		/* hide from the garbage collector */
939 	release();
940 	c->signa = (*sa->vec->sign)(b, sk->key);
941 	acquire();
942 	mpfree(b);
943 
944 	return c;
945 }
946 
947 void
948 Keyring_sign(void *fp)
949 {
950 	F_Keyring_sign *f;
951 	Certificate *c;
952 	mpint *b;
953 	int n;
954 	SigAlg *sa;
955 	SK *sk;
956 	XDigestState *ds;
957 	uchar digest[SHA1dlen];
958 	char *buf;
959 	void *v;
960 
961 	f = fp;
962 	v = *f->ret;
963 	*f->ret = H;
964 	destroy(v);
965 
966 	sk = checkSK(f->sk);
967 	sa = checkSigAlg(sk->x.sa);
968 
969 	/* add signer name and expiration time to hash */
970 	if(f->state == H)
971 		return;
972 	buf = malloc(Maxbuf);
973 	if(buf == nil)
974 		return;
975 	ds = (XDigestState*)f->state;
976 	n = snprint(buf, Maxbuf, "%s %d", string2c(sk->x.owner), f->exp);
977 	if(strcmp(string2c(f->ha), "sha") == 0 || strcmp(string2c(f->ha), "sha1") == 0){
978 		sha1((uchar*)buf, n, digest, &ds->state);
979 		n = Keyring_SHA1dlen;
980 	} else if(strcmp(string2c(f->ha), "md5") == 0){
981 		md5((uchar*)buf, n, digest, &ds->state);
982 		n = Keyring_MD5dlen;
983 	} else if(strcmp(string2c(f->ha), "md4") == 0){
984 		md4((uchar*)buf, n, digest, &ds->state);
985 		n = Keyring_MD5dlen;
986 	} else {
987 		free(buf);
988 		return;
989 	}
990 	free(buf);
991 
992 	/* turn message into a big integer */
993 	b = betomp(digest, n, nil);
994 	if(b == nil)
995 		return;
996 
997 	/* sign */
998 	c = newCertificate(sa, stringdup(f->ha), stringdup(sk->x.owner), f->exp, 1);
999 	*f->ret = (Keyring_Certificate*)c;
1000 	release();
1001 	c->signa = (*sa->vec->sign)(b, sk->key);
1002 	acquire();
1003 	mpfree(b);
1004 }
1005 
1006 void
1007 Keyring_signm(void *fp)
1008 {
1009 	F_Keyring_signm *f;
1010 	Certificate *c;
1011 	mpint *b;
1012 	SigAlg *sa;
1013 	SK *sk;
1014 	void *v;
1015 
1016 	f = fp;
1017 	v = *f->ret;
1018 	*f->ret = H;
1019 	destroy(v);
1020 
1021 	sk = checkSK(f->sk);
1022 	sa = checkSigAlg(sk->x.sa);
1023 
1024 	if(f->m == H)
1025 		return;
1026 	b = checkIPint(f->m);
1027 
1028 	/* sign */
1029 	c = newCertificate(sa, stringdup(f->ha), stringdup(sk->x.owner), 0, 1);
1030 	*f->ret = (Keyring_Certificate*)c;
1031 	release();
1032 	c->signa = (*sa->vec->sign)(b, sk->key);
1033 	acquire();
1034 }
1035 
1036 static int
1037 verify(PK *pk, Certificate *c, char *a, int len)
1038 {
1039 	mpint *b;
1040 	int n;
1041 	SigAlg *sa, *pksa;
1042 	DigestState *ds;
1043 	uchar digest[SHA1dlen];
1044 	char *buf;
1045 
1046 	sa = checkSigAlg(c->x.sa);
1047 	pksa = checkSigAlg(pk->x.sa);
1048 	if(sa->vec != pksa->vec)
1049 		return 0;
1050 
1051 	/* add signer name and expiration time to hash */
1052 	buf = malloc(Maxbuf);
1053 	if(buf == nil)
1054 		return 0;
1055 	n = snprint(buf, Maxbuf, "%s %d", string2c(c->x.signer), c->x.exp);
1056 	if(strcmp(string2c(c->x.ha), "sha") == 0 || strcmp(string2c(c->x.ha), "sha1") == 0){
1057 		ds = sha1((uchar*)a, len, 0, 0);
1058 		sha1((uchar*)buf, n, digest, ds);
1059 		n = Keyring_SHA1dlen;
1060 	} else if(strcmp(string2c(c->x.ha), "md5") == 0){
1061 		ds = md5((uchar*)a, len, 0, 0);
1062 		md5((uchar*)buf, n, digest, ds);
1063 		n = Keyring_MD5dlen;
1064 	} else if(strcmp(string2c(c->x.ha), "md4") == 0){
1065 		ds = md4((uchar*)a, len, 0, 0);
1066 		md4((uchar*)buf, n, digest, ds);
1067 		n = Keyring_MD5dlen;
1068 	} else {
1069 		free(buf);
1070 		return 0;
1071 	}
1072 	free(buf);
1073 
1074 	/* turn message into a big integer */
1075 	b = betomp(digest, n, nil);
1076 	if(b == nil)
1077 		return 0;
1078 	/* verify */
1079 	release();
1080 	n = (*sa->vec->verify)(b, c->signa, pk->key);
1081 	acquire();
1082 
1083 	mpfree(b);
1084 	return n;
1085 }
1086 
1087 void
1088 Keyring_verify(void *fp)
1089 {
1090 	F_Keyring_verify *f;
1091 	Certificate *c;
1092 	mpint *b;
1093 	int n;
1094 	SigAlg *sa, *pksa;
1095 	PK *pk;
1096 	XDigestState *ds;
1097 	uchar digest[SHA1dlen];
1098 	char *buf;
1099 
1100 	f = fp;
1101 	*f->ret = 0;
1102 
1103 	c = checkCertificate(f->cert);
1104 	sa = checkSigAlg(c->x.sa);
1105 	pk = checkPK(f->pk);
1106 	pksa = checkSigAlg(pk->x.sa);
1107 	if(sa->vec != pksa->vec)
1108 		return;
1109 
1110 	/* add signer name and expiration time to hash */
1111 	if(f->state == H)
1112 		return;
1113 	buf = malloc(Maxbuf);
1114 	if(buf == nil)
1115 		return;
1116 	n = snprint(buf, Maxbuf, "%s %d", string2c(c->x.signer), c->x.exp);
1117 	ds = (XDigestState*)f->state;
1118 
1119 	if(strcmp(string2c(c->x.ha), "sha") == 0 || strcmp(string2c(c->x.ha), "sha1") == 0){
1120 		sha1((uchar*)buf, n, digest, &ds->state);
1121 		n = Keyring_SHA1dlen;
1122 	} else if(strcmp(string2c(c->x.ha), "md5") == 0){
1123 		md5((uchar*)buf, n, digest, &ds->state);
1124 		n = Keyring_MD5dlen;
1125 	} else if(strcmp(string2c(c->x.ha), "md4") == 0){
1126 		md4((uchar*)buf, n, digest, &ds->state);
1127 		n = Keyring_MD5dlen;
1128 	} else {
1129 		free(buf);
1130 		return;
1131 	}
1132 	free(buf);
1133 
1134 	/* turn message into a big integer */
1135 	b = betomp(digest, n, nil);
1136 	if(b == nil)
1137 		return;
1138 
1139 	/* verify */
1140 	release();
1141 	*f->ret = (*sa->vec->verify)(b, c->signa, pk->key);
1142 	acquire();
1143 
1144 	mpfree(b);
1145 }
1146 
1147 void
1148 Keyring_verifym(void *fp)
1149 {
1150 	F_Keyring_verifym *f;
1151 	Certificate *c;
1152 	SigAlg *sa, *pksa;
1153 	PK *pk;
1154 
1155 	f = fp;
1156 	*f->ret = 0;
1157 
1158 	c = checkCertificate(f->cert);
1159 	sa = checkSigAlg(c->x.sa);
1160 	pk = checkPK(f->pk);
1161 	pksa = checkSigAlg(pk->x.sa);
1162 	if(sa->vec != pksa->vec)
1163 		return;
1164 
1165 	if(f->m == H)
1166 		return;
1167 
1168 	release();
1169 	*f->ret = (*sa->vec->verify)(checkIPint(f->m), c->signa, pk->key);
1170 	acquire();
1171 }
1172 
1173 static void*
1174 checktype(void *v, Type *t, char *name, int newref)
1175 {
1176 	Heap *h;
1177 
1178 	if(v == H || v == nil)
1179 		error(exNilref);
1180 	h = D2H(v);
1181 	if(h->t != t)
1182 		errorf("%s: %s", exType, name);
1183 	if(newref){
1184 		h->ref++;
1185 		Setmark(h);
1186 	}
1187 	return v;
1188 }
1189 
1190 /*
1191  *  digests
1192  */
1193 void
1194 DigestState_copy(void *fp)
1195 {
1196 	F_DigestState_copy *f;
1197 	Heap *h;
1198 	XDigestState *ds, *ods;
1199 	void *r;
1200 
1201 	f = fp;
1202 	r = *f->ret;
1203 	*f->ret = H;
1204 	destroy(r);
1205 
1206 	if(f->d != H){
1207 		ods = checktype(f->d, TDigestState, "DigestState", 0);
1208 		h = heap(TDigestState);
1209 		ds = H2D(XDigestState*, h);
1210 		memmove(&ds->state, &ods->state, sizeof(ds->state));
1211 		*f->ret = (Keyring_DigestState*)ds;
1212 	}
1213 }
1214 
1215 static Keyring_DigestState*
1216 keyring_digest_x(Array *buf, int n, Array *digest, int dlen, Keyring_DigestState *state, DigestState* (*fn)(uchar*, ulong, uchar*, DigestState*))
1217 {
1218 	Heap *h;
1219 	XDigestState *ds;
1220 	uchar *cbuf, *cdigest;
1221 
1222 	if(buf != H){
1223 		if(n > buf->len)
1224 			n = buf->len;
1225 		cbuf = buf->data;
1226 	}else{
1227 		if(n != 0)
1228 			error(exInval);
1229 		cbuf = nil;
1230 	}
1231 
1232 	if(digest != H){
1233 		if(digest->len < dlen)
1234 			error(exBadDigest);
1235 		cdigest = digest->data;
1236 	} else
1237 		cdigest = nil;
1238 
1239 	if(state == H){
1240 		h = heap(TDigestState);
1241 		ds = H2D(XDigestState*, h);
1242 		memset(&ds->state, 0, sizeof(ds->state));
1243 	} else
1244 		ds = checktype(state, TDigestState, "DigestState", 1);
1245 
1246 	(*fn)(cbuf, n, cdigest, &ds->state);
1247 
1248 	return (Keyring_DigestState*)ds;
1249 }
1250 
1251 void
1252 Keyring_sha1(void *fp)
1253 {
1254 	F_Keyring_sha1 *f;
1255 	void *r;
1256 
1257 	f = fp;
1258 	r = *f->ret;
1259 	*f->ret = H;
1260 	destroy(r);
1261 
1262 	*f->ret = keyring_digest_x(f->buf, f->n, f->digest, SHA1dlen, f->state, sha1);
1263 }
1264 
1265 void
1266 Keyring_md5(void *fp)
1267 {
1268 	F_Keyring_md5 *f;
1269 	void *r;
1270 
1271 	f = fp;
1272 	r = *f->ret;
1273 	*f->ret = H;
1274 	destroy(r);
1275 
1276 	*f->ret = keyring_digest_x(f->buf, f->n, f->digest, MD5dlen, f->state, md5);
1277 }
1278 
1279 void
1280 Keyring_md4(void *fp)
1281 {
1282 	F_Keyring_md4 *f;
1283 	void *r;
1284 
1285 	f = fp;
1286 	r = *f->ret;
1287 	*f->ret = H;
1288 	destroy(r);
1289 
1290 	*f->ret = keyring_digest_x(f->buf, f->n, f->digest, MD4dlen, f->state, md4);
1291 }
1292 
1293 static Keyring_DigestState*
1294 keyring_hmac_x(Array *data, int n, Array *key, Array *digest, int dlen, Keyring_DigestState *state, DigestState* (*fn)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*))
1295 {
1296 	Heap *h;
1297 	XDigestState *ds;
1298 	uchar *cdata, *cdigest;
1299 
1300 	if(data != H){
1301 		if(n > data->len)
1302 			n = data->len;
1303 		cdata = data->data;
1304 	}else{
1305 		if(n != 0)
1306 			error(exInval);
1307 		cdata = nil;
1308 	}
1309 
1310 	if(key == H || key->len > 64)
1311 		error(exBadKey);
1312 
1313 	if(digest != H){
1314 		if(digest->len < dlen)
1315 			error(exBadDigest);
1316 		cdigest = digest->data;
1317 	} else
1318 		cdigest = nil;
1319 
1320 	if(state == H){
1321 		h = heap(TDigestState);
1322 		ds = H2D(XDigestState*, h);
1323 		memset(&ds->state, 0, sizeof(ds->state));
1324 	} else
1325 		ds = checktype(state, TDigestState, "DigestState", 1);
1326 
1327 	(*fn)(cdata, n, key->data, key->len, cdigest, &ds->state);
1328 
1329 	return (Keyring_DigestState*)ds;
1330 }
1331 
1332 void
1333 Keyring_hmac_sha1(void *fp)
1334 {
1335 	F_Keyring_hmac_sha1 *f;
1336 	void *r;
1337 
1338 	f = fp;
1339 	r = *f->ret;
1340 	*f->ret = H;
1341 	destroy(r);
1342 	*f->ret = keyring_hmac_x(f->data, f->n, f->key, f->digest, SHA1dlen, f->state, hmac_sha1);
1343 }
1344 
1345 void
1346 Keyring_hmac_md5(void *fp)
1347 {
1348 	F_Keyring_hmac_md5 *f;
1349 	void *r;
1350 
1351 	f = fp;
1352 	r = *f->ret;
1353 	*f->ret = H;
1354 	destroy(r);
1355 	*f->ret = keyring_hmac_x(f->data, f->n, f->key, f->digest, MD5dlen, f->state, hmac_md5);
1356 }
1357 
1358 void
1359 Keyring_dhparams(void *fp)
1360 {
1361 	F_Keyring_dhparams *f;
1362 	mpint *p, *alpha;
1363 	void *v;
1364 
1365 	f = fp;
1366 	v = f->ret->t0;
1367 	f->ret->t0 = H;
1368 	destroy(v);
1369 	v = f->ret->t1;
1370 	f->ret->t1 = H;
1371 	destroy(v);
1372 
1373 	p = mpnew(0);
1374 	alpha = mpnew(0);
1375 	release();
1376 	if(f->nbits == 1024)
1377 		DSAprimes(alpha, p, nil);
1378 	else
1379 		gensafeprime(p, alpha, f->nbits, 0);
1380 	acquire();
1381 	f->ret->t0 = newIPint(alpha);
1382 	f->ret->t1 = newIPint(p);
1383 }
1384 
1385 static int
1386 sendmsg(int fd, void *buf, int n)
1387 {
1388 	char num[10];
1389 
1390 	release();
1391 	snprint(num, sizeof(num), "%4.4d\n", n);
1392 	if(kwrite(fd, num, 5) != 5){
1393 		acquire();
1394 		return -1;
1395 	}
1396 	n = kwrite(fd, buf, n);
1397 	acquire();
1398 	return n;
1399 }
1400 
1401 void
1402 Keyring_sendmsg(void *fp)
1403 {
1404 	F_Keyring_sendmsg *f;
1405 	int n;
1406 
1407 	f = fp;
1408 	*f->ret = -1;
1409 	if(f->fd == H || f->buf == H || f->n < 0)
1410 		return;
1411 	n = f->n;
1412 	if(n < 0 || n > f->buf->len)
1413 		error(exBounds);
1414 	*f->ret = sendmsg(f->fd->fd, f->buf->data, n);
1415 }
1416 
1417 static int
1418 senderr(int fd, char *err, int addrmt)
1419 {
1420 	char num[10];
1421 	int n, m;
1422 
1423 	release();
1424 	n = strlen(err);
1425 	m = 0;
1426 	if(addrmt)
1427 		m = strlen("remote: ");
1428 	snprint(num, sizeof(num), "!%3.3d\n", n+m);
1429 	if(kwrite(fd, num, 5) != 5){
1430 		acquire();
1431 		return -1;
1432 	}
1433 	if(addrmt)
1434 		kwrite(fd, "remote: ", m);
1435 	n = kwrite(fd, err, n);
1436 	acquire();
1437 	return n;
1438 }
1439 
1440 void
1441 Keyring_senderrmsg(void *fp)
1442 {
1443 	F_Keyring_senderrmsg *f;
1444 	char *s;
1445 
1446 	f = fp;
1447 	*f->ret = -1;
1448 	if(f->fd == H)
1449 		return;
1450 	s = string2c(f->s);
1451 	if(senderr(f->fd->fd, s, 0) > 0)
1452 		*f->ret = 0;
1453 }
1454 
1455 static int
1456 nreadn(int fd, void *av, int n)
1457 {
1458 
1459 	char *a;
1460 	long m, t;
1461 
1462 	a = av;
1463 	t = 0;
1464 	while(t < n){
1465 		m = kread(fd, a+t, n-t);
1466 		if(m <= 0){
1467 			if(t == 0)
1468 				return m;
1469 			break;
1470 		}
1471 		t += m;
1472 	}
1473 	return t;
1474 }
1475 
1476 #define MSG "input or format error"
1477 
1478 static void
1479 getmsgerr(char *buf, int n, int r)
1480 {
1481 	char *e;
1482 	int l;
1483 
1484 	e = r>0? MSG: "hungup";
1485 	l = strlen(e)+1;
1486 	if(n > l)
1487 		n = l;
1488 	memmove(buf, e, n-1);
1489 	buf[n-1] = 0;
1490 }
1491 
1492 static int
1493 getmsg(int fd, char *buf, int n)
1494 {
1495 	char num[6];
1496 	int len, r;
1497 
1498 	release();
1499 	if((r = nreadn(fd, num, 5)) != 5){
1500 		getmsgerr(buf, n, r);
1501 		acquire();
1502 		return -1;
1503 	}
1504 	num[5] = 0;
1505 
1506 	if(num[0] == '!')
1507 		len = strtoul(num+1, 0, 10);
1508 	else
1509 		len = strtoul(num, 0, 10);
1510 
1511 	r = -1;
1512 	if(len < 0 || len >= n || (r = nreadn(fd, buf, len)) != len){
1513 		getmsgerr(buf, n, r);
1514 		acquire();
1515 		return -1;
1516 	}
1517 
1518 	buf[len] = 0;
1519 	acquire();
1520 	if(num[0] == '!')
1521 		return -len;
1522 
1523 	return len;
1524 }
1525 
1526 void
1527 Keyring_getmsg(void *fp)
1528 {
1529 	F_Keyring_getmsg *f;
1530 	char *buf;
1531 	int n;
1532 	void *r;
1533 
1534 	f = fp;
1535 	r = *f->ret;
1536 	*f->ret = H;
1537 	destroy(r);
1538 	if(f->fd == H){
1539 		kwerrstr("nil fd");
1540 		return;
1541 	}
1542 
1543 	buf = malloc(Maxmsg);
1544 	if(buf == nil){
1545 		kwerrstr(exNomem);
1546 		return;
1547 	}
1548 
1549 	n = getmsg(f->fd->fd, buf, Maxmsg);
1550 	if(n < 0){
1551 		kwerrstr("%s", buf);
1552 		free(buf);
1553 		return;
1554 	}
1555 
1556 	*f->ret = mem2array(buf, n);
1557 	free(buf);
1558 }
1559 
1560 void
1561 Keyring_auth(void *fp)
1562 {
1563 	F_Keyring_auth *f;
1564 	mpint *r0, *r1, *p, *alpha, *alphar0, *alphar1, *alphar0r1;
1565 	SK *mysk;
1566 	PK *mypk, *spk, *hispk;
1567 	Certificate *cert, *hiscert, *alphacert;
1568 	char *buf, *err;
1569 	uchar *cvb;
1570 	int n, fd, version;
1571 	long now;
1572 
1573 	hispk = H;
1574 	hiscert = H;
1575 	alphacert = H;
1576 	err = nil;
1577 
1578 	/* null out the return values */
1579 	f = fp;
1580 	destroy(f->ret->t0);
1581 	f->ret->t0 = H;
1582 	destroy(f->ret->t1);
1583 	f->ret->t1 = H;
1584 	r0 = r1 = alphar0 = alphar1 = alphar0r1 = nil;
1585 
1586 	/* check args */
1587 	if(f->fd == H || f->fd->fd < 0){
1588 		retstr("bad fd", &f->ret->t0);
1589 		return;
1590 	}
1591 	fd = f->fd->fd;
1592 
1593 	buf = malloc(Maxbuf);
1594 	if(buf == nil){
1595 		retstr(exNomem, &f->ret->t0);
1596 		return;
1597 	}
1598 
1599 	/* send auth protocol version number */
1600 	if(sendmsg(fd, "1", 1) <= 0){
1601 		err = MSG;
1602 		goto out;
1603 	}
1604 
1605 	/* get auth protocol version number */
1606 	n = getmsg(fd, buf, Maxbuf-1);
1607 	if(n < 0){
1608 		err = buf;
1609 		goto out;
1610 	}
1611 	buf[n] = 0;
1612 	version = atoi(buf);
1613 	if(version != 1 || n > 4){
1614 		err = "incompatible authentication protocol";
1615 		goto out;
1616 	}
1617 
1618 	if(f->info == H){
1619 		err = "no authentication information";
1620 		goto out;
1621 	}
1622 	if(f->info->p == H){
1623 		err = "missing diffie hellman mod";
1624 		goto out;
1625 	}
1626 	if(f->info->alpha == H){
1627 		err = "missing diffie hellman base";
1628 		goto out;
1629 	}
1630 	mysk = checkSK(f->info->mysk);
1631 	if(mysk == H){
1632 		err = "bad sk arg";
1633 		goto out;
1634 	}
1635 	mypk = checkPK(f->info->mypk);
1636 	if(mypk == H){
1637 		err = "bad pk arg";
1638 		goto out;
1639 	}
1640 	cert = checkCertificate(f->info->cert);
1641 	if(cert == H){
1642 		err = "bad certificate arg";
1643 		goto out;
1644 	}
1645 	spk = checkPK(f->info->spk);
1646 	if(spk == H){
1647 		err = "bad signer key arg";
1648 		goto out;
1649 	}
1650 
1651 	/* get alpha and p */
1652 	p = checkIPint(f->info->p);
1653 	alpha = checkIPint(f->info->alpha);
1654 
1655 	if(p->sign == -1) {
1656 		err = "-ve modulus";
1657 		goto out;
1658 	}
1659 
1660 	r0 = mpnew(0);
1661 	r1 = mpnew(0);
1662 	alphar0 = mpnew(0);
1663 	alphar0r1 = mpnew(0);
1664 
1665 	/* generate alpha**r0 */
1666 if(0)print("X");
1667 	release();
1668 	mprand(mpsignif(p), genrandom, r0);
1669 	mpexp(alpha, r0, p, alphar0);
1670 	acquire();
1671 if(0)print("Y");
1672 
1673 	/* send alpha**r0 mod p, mycert, and mypk */
1674 	n = bigtobase64(alphar0, buf, Maxbuf);
1675 	if(sendmsg(fd, buf, n) <= 0){
1676 		err = MSG;
1677 		goto out;
1678 	}
1679 
1680 	n = certtostr(cert, buf, Maxbuf);
1681 	if(sendmsg(fd, buf, n) <= 0){
1682 		err = MSG;
1683 		goto out;
1684 	}
1685 
1686 	n = pktostr(mypk, buf, Maxbuf);
1687 	if(sendmsg(fd, buf, n) <= 0){
1688 		err = MSG;
1689 		goto out;
1690 	}
1691 
1692 	/* get alpha**r1 mod p, hiscert, hispk */
1693 	n = getmsg(fd, buf, Maxbuf-1);
1694 	if(n < 0){
1695 		err = buf;
1696 		goto out;
1697 	}
1698 	buf[n] = 0;
1699 	alphar1 = strtomp(buf, nil, 64, nil);
1700 
1701 	/* trying a fast one */
1702 	if(mpcmp(p, alphar1) <= 0){
1703 		err = "implausible parameter value";
1704 		goto out;
1705 	}
1706 
1707 	/* if alpha**r1 == alpha**r0, someone may be trying a replay */
1708 	if(mpcmp(alphar0, alphar1) == 0){
1709 		err = "possible replay attack";
1710 		goto out;
1711 	}
1712 
1713 	n = getmsg(fd, buf, Maxbuf-1);
1714 	if(n < 0){
1715 		err = buf;
1716 		goto out;
1717 	}
1718 	buf[n] = 0;
1719 	hiscert = strtocert(buf);
1720 	if(hiscert == H){
1721 		err = "bad certificate syntax";
1722 		goto out;
1723 	}
1724 	certimmutable(hiscert);		/* hide from the garbage collector */
1725 
1726 	n = getmsg(fd, buf, Maxbuf-1);
1727 	if(n < 0){
1728 		err = buf;
1729 		goto out;
1730 	}
1731 	buf[n] = 0;
1732 	hispk = strtopk(buf);
1733 	if(hispk == H){
1734 		err = "bad public key";
1735 		goto out;
1736 	}
1737 	pkimmutable(hispk);		/* hide from the garbage collector */
1738 
1739 	/* verify his public key */
1740 	if(verify(spk, hiscert, buf, n) == 0){
1741 		err = "pk doesn't match certificate";
1742 		goto out;
1743 	}
1744 
1745 	/* check expiration date - in seconds of epoch */
1746 
1747 	now = osusectime()/1000000;
1748 	if(hiscert->x.exp != 0 && hiscert->x.exp <= now){
1749 		err = "certificate expired";
1750 		goto out;
1751 	}
1752 
1753 	/* sign alpha**r0 and alpha**r1 and send */
1754 	n = bigtobase64(alphar0, buf, Maxbuf);
1755 	n += bigtobase64(alphar1, buf+n, Maxbuf-n);
1756 	alphacert = sign(mysk, "sha1", 0, (uchar*)buf, n);
1757 	n = certtostr(alphacert, buf, Maxbuf);
1758 	if(sendmsg(fd, buf, n) <= 0){
1759 		err = MSG;
1760 		goto out;
1761 	}
1762 	certmutable(alphacert);
1763 	destroy(alphacert);
1764 	alphacert = H;
1765 
1766 	/* get signature of alpha**r1 and alpha**r0 and verify */
1767 	n = getmsg(fd, buf, Maxbuf-1);
1768 	if(n < 0){
1769 		err = buf;
1770 		goto out;
1771 	}
1772 	buf[n] = 0;
1773 	alphacert = strtocert(buf);
1774 	if(alphacert == H){
1775 		err = "alpha**r1 doesn't match certificate";
1776 		goto out;
1777 	}
1778 	certimmutable(alphacert);		/* hide from the garbage collector */
1779 	n = bigtobase64(alphar1, buf, Maxbuf);
1780 	n += bigtobase64(alphar0, buf+n, Maxbuf-n);
1781 	if(verify(hispk, alphacert, buf, n) == 0){
1782 		err = "bad certificate";
1783 		goto out;
1784 	}
1785 
1786 	/* we are now authenticated and have a common secret, alpha**(r0*r1) */
1787 	f->ret->t0 = stringdup(hispk->x.owner);
1788 	mpexp(alphar1, r0, p, alphar0r1);
1789 	n = mptobe(alphar0r1, nil, Maxbuf, &cvb);
1790 	if(n < 0){
1791 		err = "bad conversion";
1792 		goto out;
1793 	}
1794 	f->ret->t1 = mem2array(cvb, n);
1795 	free(cvb);
1796 
1797 out:
1798 	/* return status */
1799 	if(f->ret->t0 == H){
1800 		if(err == buf)
1801 			senderr(fd, "missing your authentication data", 1);
1802 		else
1803 			senderr(fd, err, 1);
1804 	}else
1805 		sendmsg(fd, "OK", 2);
1806 
1807 	/* read responses */
1808 	if(err != buf){
1809 		for(;;){
1810 			n = getmsg(fd, buf, Maxbuf-1);
1811 			if(n < 0){
1812 				destroy(f->ret->t0);
1813 				f->ret->t0 = H;
1814 				destroy(f->ret->t1);
1815 				f->ret->t1 = H;
1816 				if(err == nil){
1817 					if(n < -1)
1818 						err = buf;
1819 					else
1820 						err = MSG;
1821 				}
1822 				break;
1823 			}
1824 			if(n == 2 && buf[0] == 'O' && buf[1] == 'K')
1825 				break;
1826 		}
1827 	}
1828 
1829 	/* set error and id to nobody */
1830 	if(f->ret->t0 == H){
1831 		if(err == nil)
1832 			err = MSG;
1833 		retstr(err, &f->ret->t0);
1834 		if(f->setid)
1835 			setid("nobody", 1);
1836 	} else {
1837 		/* change user id */
1838 		if(f->setid)
1839 			setid(string2c(f->ret->t0), 1);
1840 	}
1841 
1842 	/* free resources */
1843 	if(hispk != H){
1844 		pkmutable(hispk);
1845 		destroy(hispk);
1846 	}
1847 	if(hiscert != H){
1848 		certmutable(hiscert);
1849 		destroy(hiscert);
1850 	}
1851 	if(alphacert != H){
1852 		certmutable(alphacert);
1853 		destroy(alphacert);
1854 	}
1855 	free(buf);
1856 	if(r0 != nil){
1857 		mpfree(r0);
1858 		mpfree(r1);
1859 		mpfree(alphar0);
1860 		mpfree(alphar1);
1861 		mpfree(alphar0r1);
1862 	}
1863 }
1864 
1865 static Keyring_Authinfo*
1866 newAuthinfo(void)
1867 {
1868 	return H2D(Keyring_Authinfo*, heap(TAuthinfo));
1869 }
1870 
1871 void
1872 Keyring_writeauthinfo(void *fp)
1873 {
1874 	F_Keyring_writeauthinfo *f;
1875 	int n, fd;
1876 	char *buf;
1877 	PK *spk;
1878 	SK *mysk;
1879 	Certificate *c;
1880 
1881 	f = fp;
1882 	*f->ret = -1;
1883 
1884 	if(f->filename == H)
1885 		return;
1886 	if(f->info == H)
1887 		return;
1888 	if(f->info->alpha == H || f->info->p == H)
1889 		return;
1890 	if(((IPint*)f->info->alpha)->b == 0 || ((IPint*)f->info->p)->b == H)
1891 		return;
1892 	spk = checkPK(f->info->spk);
1893 	mysk = checkSK(f->info->mysk);
1894 	c = checkCertificate(f->info->cert);
1895 
1896 	buf = malloc(Maxbuf);
1897 	if(buf == nil)
1898 		return;
1899 
1900 	/*
1901 	 *  The file may already exist or be a file2chan file so first
1902 	 *  try opening with truncation since create will change the
1903 	 *  permissions of the file and create doesn't work with a
1904 	 *  file2chan.
1905 	 */
1906 	release();
1907 	fd = kopen(string2c(f->filename), OTRUNC|OWRITE);
1908 	if(fd < 0)
1909 		fd = kcreate(string2c(f->filename), OWRITE, 0600);
1910 	if(fd < 0)
1911 		fd = kopen(string2c(f->filename), OWRITE);
1912 	acquire();
1913 	if(fd < 0)
1914 		goto out;
1915 
1916 	/* signer's public key */
1917 	n = pktostr(spk, buf, Maxmsg);
1918 	if(sendmsg(fd, buf, n) <= 0)
1919 		goto out;
1920 
1921 	/* certificate for my public key */
1922 	n = certtostr(c, buf, Maxmsg);
1923 	if(sendmsg(fd, buf, n) <= 0)
1924 		goto out;
1925 
1926 	/* my secret/public key */
1927 	n = sktostr(mysk, buf, Maxmsg);
1928 	if(sendmsg(fd, buf, n) <= 0)
1929 		goto out;
1930 
1931 	/* diffie hellman base */
1932 	n = bigtobase64(((IPint*)f->info->alpha)->b, buf, Maxbuf);
1933 	if(sendmsg(fd, buf, n) <= 0)
1934 		goto out;
1935 
1936 	/* diffie hellman modulus */
1937 	n = bigtobase64(((IPint*)f->info->p)->b, buf, Maxbuf);
1938 	if(sendmsg(fd, buf, n) <= 0)
1939 		goto out;
1940 
1941 	*f->ret = 0;
1942 out:
1943 	free(buf);
1944 	if(fd >= 0){
1945 		release();
1946 		kclose(fd);
1947 		acquire();
1948 	}
1949 }
1950 
1951 void
1952 Keyring_readauthinfo(void *fp)
1953 {
1954 	F_Keyring_readauthinfo *f;
1955 	int fd;
1956 	char *buf;
1957 	int n, ok;
1958 	PK *mypk;
1959 	SK *mysk;
1960 	SigAlg *sa;
1961 	Keyring_Authinfo *ai;
1962 	mpint *b;
1963 	void *r;
1964 
1965 	f = fp;
1966 	r = *f->ret;
1967 	*f->ret = H;
1968 	destroy(r);
1969 
1970 	ok = 0;
1971 
1972 	if(f->filename == H)
1973 		return;
1974 
1975 	buf = malloc(Maxbuf);
1976 	if(buf == nil)
1977 		return;
1978 
1979 	ai = newAuthinfo();
1980 	*f->ret = ai;
1981 
1982 	release();
1983 	fd = kopen(string2c(f->filename), OREAD);
1984 	acquire();
1985 	if(fd < 0)
1986 		goto out;
1987 
1988 	/* signer's public key */
1989 	n = getmsg(fd, buf, Maxmsg);
1990 	if(n < 0)
1991 		goto out;
1992 
1993 	ai->spk = (Keyring_PK*)strtopk(buf);
1994 	if(ai->spk == H)
1995 		goto out;
1996 
1997 	/* certificate for my public key */
1998 	n = getmsg(fd, buf, Maxmsg);
1999 	if(n < 0)
2000 		goto out;
2001 	ai->cert = (Keyring_Certificate*)strtocert(buf);
2002 	if(ai->cert == H)
2003 		goto out;
2004 
2005 	/* my secret/public key */
2006 	n = getmsg(fd, buf, Maxmsg);
2007 	if(n < 0)
2008 		goto out;
2009 	mysk = strtosk(buf);
2010 	ai->mysk = (Keyring_SK*)mysk;
2011 	if(mysk == H)
2012 		goto out;
2013 	sa = checkSigAlg(mysk->x.sa);
2014 	mypk = newPK(sa, stringdup(mysk->x.owner), 1);
2015 	mypk->key = (*sa->vec->sk2pk)(mysk->key);
2016 	ai->mypk = (Keyring_PK*)mypk;
2017 
2018 	/* diffie hellman base */
2019 	n = getmsg(fd, buf, Maxmsg);
2020 	if(n < 0)
2021 		goto out;
2022 	b = strtomp(buf, nil, 64, nil);
2023 	ai->alpha = newIPint(b);
2024 
2025 	/* diffie hellman modulus */
2026 	n = getmsg(fd, buf, Maxmsg);
2027 	if(n < 0)
2028 		goto out;
2029 	b = strtomp(buf, nil, 64, nil);
2030 	ai->p = newIPint(b);
2031 	ok = 1;
2032 out:
2033 	if(!ok){
2034 		r = *f->ret;
2035 		*f->ret = H;
2036 		destroy(r);
2037 	}
2038 	free(buf);
2039 	if(fd >= 0){
2040 		release();
2041 		kclose(fd);
2042 		acquire();
2043 		kwerrstr("%q: %s", string2c(f->filename), MSG);
2044 	}
2045 }
2046 
2047 void
2048 keyringmodinit(void)
2049 {
2050 	SigAlgVec *sav;
2051 	extern SigAlgVec* elgamalinit(void);
2052 	extern SigAlgVec* rsainit(void);
2053 	extern SigAlgVec* dsainit(void);
2054 
2055 	TIPint = dtype(freeIPint, sizeof(IPint), IPintmap, sizeof(IPintmap));
2056 	TSigAlg = dtype(freeSigAlg, sizeof(SigAlg), SigAlgmap, sizeof(SigAlgmap));
2057 	TSK = dtype(freeSK, sizeof(SK), SKmap, sizeof(SKmap));
2058 	TPK = dtype(freePK, sizeof(PK), PKmap, sizeof(PKmap));
2059 	TCertificate = dtype(freeCertificate, sizeof(Certificate), Certificatemap,
2060 		sizeof(Certificatemap));
2061 	TDigestState = dtype(freeheap, sizeof(XDigestState), DigestStatemap,
2062 		sizeof(DigestStatemap));
2063 	TAESstate = dtype(freeheap, sizeof(XAESstate), AESstatemap,
2064 		sizeof(AESstatemap));
2065 	TDESstate = dtype(freeheap, sizeof(XDESstate), DESstatemap,
2066 		sizeof(DESstatemap));
2067 	TIDEAstate = dtype(freeheap, sizeof(XIDEAstate), IDEAstatemap,
2068 		sizeof(IDEAstatemap));
2069 	TBFstate = dtype(freeheap, sizeof(XBFstate), BFstatemap,
2070 		sizeof(BFstatemap));
2071 	TRC4state = dtype(freeheap, sizeof(XRC4state), RC4statemap,
2072 		sizeof(RC4statemap));
2073 	TAuthinfo = dtype(freeheap, sizeof(Keyring_Authinfo), Authinfomap, sizeof(Authinfomap));
2074 	TDSAsk = dtype(freeheap, sizeof(Keyring_DSAsk), DSAskmap, sizeof(DSAskmap));
2075 	TDSApk = dtype(freeheap, sizeof(Keyring_DSApk), DSApkmap, sizeof(DSApkmap));
2076 	TDSAsig = dtype(freeheap, sizeof(Keyring_DSAsig), DSAsigmap, sizeof(DSAsigmap));
2077 	TEGsk = dtype(freeheap, sizeof(Keyring_EGsk), EGskmap, sizeof(EGskmap));
2078 	TEGpk = dtype(freeheap, sizeof(Keyring_EGpk), EGpkmap, sizeof(EGpkmap));
2079 	TEGsig = dtype(freeheap, sizeof(Keyring_EGsig), EGsigmap, sizeof(EGsigmap));
2080 	TRSAsk = dtype(freeheap, sizeof(Keyring_RSAsk), RSAskmap, sizeof(RSAskmap));
2081 	TRSApk = dtype(freeheap, sizeof(Keyring_RSApk), RSApkmap, sizeof(RSApkmap));
2082 	TRSAsig = dtype(freeheap, sizeof(Keyring_RSAsig), RSAsigmap, sizeof(RSAsigmap));
2083 
2084 	if((sav = elgamalinit()) != nil)
2085 		algs[nalg++] = sav;
2086 	if((sav = rsainit()) != nil)
2087 		algs[nalg++] = sav;
2088 	if((sav = dsainit()) != nil)
2089 		algs[nalg++] = sav;
2090 
2091 	fmtinstall('U', big64conv);
2092 	builtinmod("$Keyring", Keyringmodtab, Keyringmodlen);
2093 }
2094 
2095 /*
2096  *  IO on a delimited channel.  A message starting with 0x00 is a normal
2097  *  message.  One starting with 0xff is an error string.
2098  *
2099  *  return negative number for error messages (including hangup)
2100  */
2101 static int
2102 getbuf(int fd, uchar *buf, int n, char *err, int nerr)
2103 {
2104 	int len;
2105 
2106 	release();
2107 	len = kread(fd, buf, n);
2108 	acquire();
2109 	if(len <= 0){
2110 		strncpy(err, "hungup", nerr);
2111 		buf[nerr-1] = 0;
2112 		return -1;
2113 	}
2114 	if(buf[0] == 0)
2115 		return len-1;
2116 	if(buf[0] != 0xff){
2117 		/*
2118 		 * this happens when the client's password is wrong: both sides use a digest of the
2119 		 * password as a crypt key for devssl. When they don't match decryption garbles
2120 		 * messages
2121 		 */
2122 		strncpy(err, "failure", nerr);
2123 		err[nerr-1] = 0;
2124 		return -1;
2125 	}
2126 
2127 	/* error string */
2128 	len--;
2129 	if(len < 1){
2130 		strncpy(err, "unknown", nerr);
2131 		err[nerr-1] = 0;
2132 	} else {
2133 		if(len >= nerr)
2134 			len = nerr-1;
2135 		memmove(err, buf+1, len);
2136 		err[len] = 0;
2137 	}
2138 	return -1;
2139 }
2140 
2141 void
2142 Keyring_getstring(void *fp)
2143 {
2144 	F_Keyring_getstring *f;
2145 	uchar *buf;
2146 	char err[64];
2147 	int n;
2148 
2149 	f = fp;
2150 	destroy(f->ret->t0);
2151 	f->ret->t0 = H;
2152 	destroy(f->ret->t1);
2153 	f->ret->t1 = H;
2154 
2155 	if(f->fd == H)
2156 		return;
2157 
2158 	buf = malloc(Maxmsg);
2159 	if(buf == nil)
2160 		return;
2161 
2162 	n = getbuf(f->fd->fd, buf, Maxmsg, err, sizeof(err));
2163 	if(n < 0)
2164 		retnstr(err, strlen(err), &f->ret->t1);
2165 	else
2166 		retnstr(((char*)buf)+1, n, &f->ret->t0);
2167 
2168 	free(buf);
2169 }
2170 
2171 void
2172 Keyring_getbytearray(void *fp)
2173 {
2174 	F_Keyring_getbytearray *f;
2175 	uchar *buf;
2176 	char err[64];
2177 	int n;
2178 
2179 	f = fp;
2180 	destroy(f->ret->t0);
2181 	f->ret->t0 = H;
2182 	destroy(f->ret->t1);
2183 	f->ret->t1 = H;
2184 
2185 	if(f->fd == H)
2186 		return;
2187 
2188 	buf = malloc(Maxmsg);
2189 	if(buf == nil)
2190 		return;
2191 
2192 	n = getbuf(f->fd->fd, buf, Maxmsg, err, sizeof(err));
2193 	if(n < 0)
2194 		retnstr(err, strlen(err), &f->ret->t1);
2195 	else
2196 		f->ret->t0 = mem2array(buf+1, n);
2197 
2198 	free(buf);
2199 }
2200 
2201 static int
2202 putbuf(int fd, void *p, int n)
2203 {
2204 	char *buf;
2205 
2206 	buf = malloc(Maxmsg);
2207 	if(buf == nil)
2208 		return -1;
2209 
2210 	release();
2211 	buf[0] = 0;
2212 	if(n < 0){
2213 		buf[0] = 0xff;
2214 		n = -n;
2215 	}
2216 	if(n >= Maxmsg)
2217 		n = Maxmsg - 1;
2218 	memmove(buf+1, p, n);
2219 	n = kwrite(fd, buf, n+1);
2220 	acquire();
2221 
2222 	free(buf);
2223 	return n;
2224 }
2225 
2226 void
2227 Keyring_putstring(void *fp)
2228 {
2229 	F_Keyring_putstring *f;
2230 
2231 	f = fp;
2232 	*f->ret = -1;
2233 	if(f->fd == H || f->s == H)
2234 		return;
2235 	*f->ret = putbuf(f->fd->fd, string2c(f->s), strlen(string2c(f->s)));
2236 }
2237 
2238 void
2239 Keyring_puterror(void *fp)
2240 {
2241 	F_Keyring_puterror *f;
2242 
2243 	f = fp;
2244 	*f->ret = -1;
2245 	if(f->fd == H || f->s == H)
2246 		return;
2247 	*f->ret = putbuf(f->fd->fd, string2c(f->s), -strlen(string2c(f->s)));
2248 }
2249 
2250 void
2251 Keyring_putbytearray(void *fp)
2252 {
2253 	F_Keyring_putbytearray *f;
2254 	int n;
2255 
2256 	f = fp;
2257 	*f->ret = -1;
2258 	if(f->fd == H || f->a == H)
2259 		return;
2260 	n = f->n;
2261 	if(n < 0 || n > f->a->len)
2262 		error(exBounds);
2263 	*f->ret = putbuf(f->fd->fd, f->a->data, n);
2264 }
2265 
2266 void
2267 Keyring_dessetup(void *fp)
2268 {
2269 	F_Keyring_dessetup *f;
2270 	Heap *h;
2271 	XDESstate *ds;
2272 	uchar *ivec;
2273 	void *r;
2274 
2275 	f = fp;
2276 	r = *f->ret;
2277 	*f->ret = H;
2278 	destroy(r);
2279 
2280 	if(f->key == H || f->key->len < 8)
2281 		error(exBadKey);
2282 	if(f->ivec != H){
2283 		if(f->ivec->len < 8)
2284 			error(exBadIvec);
2285 		ivec = f->ivec->data;
2286 	}else
2287 		ivec = nil;
2288 
2289 	h = heap(TDESstate);
2290 	ds = H2D(XDESstate*, h);
2291 	setupDESstate(&ds->state, f->key->data, ivec);
2292 
2293 	*f->ret = (Keyring_DESstate*)ds;
2294 }
2295 
2296 void
2297 Keyring_desecb(void *fp)
2298 {
2299 	F_Keyring_desecb *f;
2300 	XDESstate *ds;
2301 	int i;
2302 	uchar *p;
2303 
2304 	f = fp;
2305 
2306 	if(f->buf == H)
2307 		return;
2308 	if(f->n < 0 || f->n > f->buf->len)
2309 		error(exBounds);
2310 	if(f->n & 7)
2311 		error(exBadBsize);
2312 
2313 	ds = checktype(f->state, TDESstate, exBadState, 0);
2314 	p = f->buf->data;
2315 
2316 	for(i = 8; i <= f->n; i += 8, p += 8)
2317 		block_cipher(ds->state.expanded, p, f->direction);
2318 }
2319 
2320 void
2321 Keyring_descbc(void *fp)
2322 {
2323 	F_Keyring_descbc *f;
2324 	XDESstate *ds;
2325 	uchar *p, *ep, *ip, *p2, *eip;
2326 	uchar tmp[8];
2327 
2328 	f = fp;
2329 
2330 	if(f->buf == H)
2331 		return;
2332 	if(f->n < 0 || f->n > f->buf->len)
2333 		error(exBounds);
2334 	if(f->n & 7)
2335 		error(exBadBsize);
2336 
2337 	ds = checktype(f->state, TDESstate, exBadState, 0);
2338 	p = f->buf->data;
2339 
2340 	if(f->direction == 0){
2341 		for(ep = p + f->n; p < ep; p += 8){
2342 			p2 = p;
2343 			ip = ds->state.ivec;
2344 			for(eip = ip+8; ip < eip; )
2345 				*p2++ ^= *ip++;
2346 			block_cipher(ds->state.expanded, p, 0);
2347 			memmove(ds->state.ivec, p, 8);
2348 		}
2349 	} else {
2350 		for(ep = p + f->n; p < ep; ){
2351 			memmove(tmp, p, 8);
2352 			block_cipher(ds->state.expanded, p, 1);
2353 			p2 = tmp;
2354 			ip = ds->state.ivec;
2355 			for(eip = ip+8; ip < eip; ){
2356 				*p++ ^= *ip;
2357 				*ip++ = *p2++;
2358 			}
2359 		}
2360 	}
2361 }
2362 
2363 void
2364 Keyring_ideasetup(void *fp)
2365 {
2366 	F_Keyring_ideasetup *f;
2367 	Heap *h;
2368 	XIDEAstate *is;
2369 	uchar *ivec;
2370 	void *r;
2371 
2372 	f = fp;
2373 	r = *f->ret;
2374 	*f->ret = H;
2375 	destroy(r);
2376 
2377 	if(f->key == H || f->key->len < 16)
2378 		error(exBadKey);
2379 	if(f->ivec != H){
2380 		if(f->ivec->len < 8)
2381 			error(exBadIvec);
2382 		ivec = f->ivec->data;
2383 	}else
2384 		ivec = nil;
2385 
2386 	h = heap(TIDEAstate);
2387 	is = H2D(XIDEAstate*, h);
2388 
2389 	setupIDEAstate(&is->state, f->key->data, ivec);
2390 
2391 	*f->ret = (Keyring_IDEAstate*)is;
2392 }
2393 
2394 void
2395 Keyring_ideaecb(void *fp)
2396 {
2397 	F_Keyring_ideaecb *f;
2398 	XIDEAstate *is;
2399 	int i;
2400 	uchar *p;
2401 
2402 	f = fp;
2403 
2404 	if(f->buf == H)
2405 		return;
2406 	if(f->n < 0 || f->n > f->buf->len)
2407 		error(exBounds);
2408 	if(f->n & 7)
2409 		error(exBadBsize);
2410 
2411 	is = checktype(f->state, TIDEAstate, exBadState, 0);
2412 	p = f->buf->data;
2413 
2414 	for(i = 8; i <= f->n; i += 8, p += 8)
2415 		idea_cipher(is->state.edkey, p, f->direction);
2416 }
2417 
2418 void
2419 Keyring_ideacbc(void *fp)
2420 {
2421 	F_Keyring_ideacbc *f;
2422 	XIDEAstate *is;
2423 	uchar *p, *ep, *ip, *p2, *eip;
2424 	uchar tmp[8];
2425 
2426 	f = fp;
2427 
2428 	if(f->buf == H)
2429 		return;
2430 	if(f->n < 0 || f->n > f->buf->len)
2431 		error(exBounds);
2432 	if(f->n & 7)
2433 		error(exBadBsize);
2434 
2435 	is = checktype(f->state, TIDEAstate, exBadState, 0);
2436 	p = f->buf->data;
2437 
2438 	if(f->direction == 0){
2439 		for(ep = p + f->n; p < ep; p += 8){
2440 			p2 = p;
2441 			ip = is->state.ivec;
2442 			for(eip = ip+8; ip < eip; )
2443 				*p2++ ^= *ip++;
2444 			idea_cipher(is->state.edkey, p, 0);
2445 			memmove(is->state.ivec, p, 8);
2446 		}
2447 	} else {
2448 		for(ep = p + f->n; p < ep; ){
2449 			memmove(tmp, p, 8);
2450 			idea_cipher(is->state.edkey, p, 1);
2451 			p2 = tmp;
2452 			ip = is->state.ivec;
2453 			for(eip = ip+8; ip < eip; ){
2454 				*p++ ^= *ip;
2455 				*ip++ = *p2++;
2456 			}
2457 		}
2458 	}
2459 }
2460 
2461 void
2462 Keyring_aessetup(void *fp)
2463 {
2464 	F_Keyring_aessetup *f;
2465 	Heap *h;
2466 	XAESstate *is;
2467 	uchar *ivec;
2468 	void *r;
2469 
2470 	f = fp;
2471 	r = *f->ret;
2472 	*f->ret = H;
2473 	destroy(r);
2474 
2475 	if(f->key == H ||
2476 	   f->key->len != 16 && f->key->len != 24 && f->key->len != 32)
2477 		error(exBadKey);
2478 	if(f->ivec != H){
2479 		if(f->ivec->len < AESbsize)
2480 			error(exBadIvec);
2481 		ivec = f->ivec->data;
2482 	}else
2483 		ivec = nil;
2484 
2485 	h = heap(TAESstate);
2486 	is = H2D(XAESstate*, h);
2487 
2488 	setupAESstate(&is->state, f->key->data, f->key->len, ivec);
2489 
2490 	*f->ret = (Keyring_AESstate*)is;
2491 }
2492 
2493 void
2494 Keyring_aescbc(void *fp)
2495 {
2496 	F_Keyring_aescbc *f;
2497 	XAESstate *is;
2498 	uchar *p;
2499 
2500 	f = fp;
2501 
2502 	if(f->buf == H)
2503 		return;
2504 	if(f->n < 0 || f->n > f->buf->len)
2505 		error(exBounds);
2506 
2507 	is = checktype(f->state, TAESstate, exBadState, 0);
2508 	p = f->buf->data;
2509 
2510 	if(f->direction == 0)
2511 		aesCBCencrypt(p, f->n, &is->state);
2512 	else
2513 		aesCBCdecrypt(p, f->n, &is->state);
2514 }
2515 
2516 void
2517 Keyring_blowfishsetup(void *fp)
2518 {
2519 	F_Keyring_blowfishsetup *f;
2520 	Heap *h;
2521 	XBFstate *is;
2522 	uchar *ivec;
2523 	void *r;
2524 
2525 	f = fp;
2526 	r = *f->ret;
2527 	*f->ret = H;
2528 	destroy(r);
2529 
2530 	if(f->key == H || f->key->len <= 0)
2531 		error(exBadKey);
2532 	if(f->ivec != H){
2533 		if(f->ivec->len != BFbsize)
2534 			error(exBadIvec);
2535 		ivec = f->ivec->data;
2536 	}else
2537 		ivec = nil;
2538 
2539 	h = heap(TBFstate);
2540 	is = H2D(XBFstate*, h);
2541 
2542 	setupBFstate(&is->state, f->key->data, f->key->len, ivec);
2543 
2544 	*f->ret = (Keyring_BFstate*)is;
2545 }
2546 
2547 void
2548 Keyring_blowfishcbc(void *fp)
2549 {
2550 	F_Keyring_blowfishcbc *f;
2551 	XBFstate *is;
2552 	uchar *p;
2553 
2554 	f = fp;
2555 
2556 	if(f->buf == H)
2557 		return;
2558 	if(f->n < 0 || f->n > f->buf->len)
2559 		error(exBounds);
2560 	if(f->n & 7)
2561 		error(exBadBsize);
2562 
2563 	is = checktype(f->state, TBFstate, exBadState, 0);
2564 	p = f->buf->data;
2565 
2566 	if(f->direction == 0)
2567 		bfCBCencrypt(p, f->n, &is->state);
2568 	else
2569 		bfCBCdecrypt(p, f->n, &is->state);
2570 }
2571 
2572 void
2573 Keyring_rc4setup(void *fp)
2574 {
2575 	F_Keyring_rc4setup *f;
2576 	Heap *h;
2577 	XRC4state *is;
2578 	void *r;
2579 
2580 	f = fp;
2581 	r = *f->ret;
2582 	*f->ret = H;
2583 	destroy(r);
2584 
2585 	if(f->seed == H)
2586 		return;
2587 
2588 	h = heap(TRC4state);
2589 	is = H2D(XRC4state*, h);
2590 
2591 	setupRC4state(&is->state, f->seed->data, f->seed->len);
2592 
2593 	*f->ret = (Keyring_RC4state*)is;
2594 }
2595 
2596 void
2597 Keyring_rc4(void *fp)
2598 {
2599 	F_Keyring_rc4 *f;
2600 	XRC4state *is;
2601 	uchar *p;
2602 
2603 	f = fp;
2604 	if(f->buf == H)
2605 		return;
2606 	if(f->n < 0 || f->n > f->buf->len)
2607 		error(exBounds);
2608 	is = checktype(f->state, TRC4state, exBadState, 0);
2609 	p = f->buf->data;
2610 	rc4(&is->state, p, f->n);
2611 }
2612 
2613 void
2614 Keyring_rc4skip(void *fp)
2615 {
2616 	F_Keyring_rc4skip *f;
2617 	XRC4state *is;
2618 
2619 	f = fp;
2620 	is = checktype(f->state, TRC4state, exBadState, 0);
2621 	rc4skip(&is->state, f->n);
2622 }
2623 
2624 void
2625 Keyring_rc4back(void *fp)
2626 {
2627 	F_Keyring_rc4back *f;
2628 	XRC4state *is;
2629 
2630 	f = fp;
2631 	is = checktype(f->state, TRC4state, exBadState, 0);
2632 	rc4back(&is->state, f->n);
2633 }
2634 
2635 /*
2636  *  public/secret keys, signing and verifying
2637  */
2638 
2639 static void
2640 dsapk2pub(DSApub* p, Keyring_DSApk* pk)
2641 {
2642 	if(pk == H)
2643 		error(exNilref);
2644 	p->p = checkIPint(pk->p);
2645 	p->q = checkIPint(pk->q);
2646 	p->alpha = checkIPint(pk->alpha);
2647 	p->key = checkIPint(pk->key);
2648 }
2649 
2650 static void
2651 dsask2priv(DSApriv* p, Keyring_DSAsk* sk)
2652 {
2653 	if(sk == H || sk->pk == H)
2654 		error(exNilref);
2655 	dsapk2pub(&p->pub, sk->pk);
2656 	p->secret = checkIPint(sk->secret);
2657 }
2658 
2659 static void
2660 dsapriv2sk(Keyring_DSAsk* sk, DSApriv* p)
2661 {
2662 	Keyring_DSApk* pk;
2663 
2664 	pk = sk->pk;
2665 	pk->p = ipcopymp(p->pub.p);
2666 	pk->q = ipcopymp(p->pub.q);
2667 	pk->alpha = ipcopymp(p->pub.alpha);
2668 	pk->key = ipcopymp(p->pub.key);
2669 	sk->secret = ipcopymp(p->secret);
2670 }
2671 
2672 void
2673 DSAsk_gen(void *fp)
2674 {
2675 	F_DSAsk_gen *f;
2676 	Keyring_DSAsk *sk;
2677 	DSApriv *p;
2678 	DSApub pub, *oldpk;
2679 	void *v;
2680 
2681 	f = fp;
2682 	v = *f->ret;
2683 	sk = newthing(TDSAsk, 0);
2684 	sk->pk = newthing(TDSApk, 0);
2685 	*f->ret = sk;
2686 	destroy(v);
2687 	oldpk = nil;
2688 	if(f->oldpk != H){
2689 		dsapk2pub(&pub, f->oldpk);
2690 		oldpk = &pub;
2691 	}
2692 	release();
2693 	p = dsagen(oldpk);
2694 	acquire();
2695 	dsapriv2sk(sk, p);
2696 	dsaprivfree(p);
2697 }
2698 
2699 void
2700 DSAsk_sign(void *fp)
2701 {
2702 	F_DSAsk_sign *f;
2703 	Keyring_DSAsig *sig;
2704 	DSApriv p;
2705 	mpint *m;
2706 	DSAsig *s;
2707 	void *v;
2708 
2709 	f = fp;
2710 	v = *f->ret;
2711 	sig = newthing(TDSAsig, 0);
2712 	*f->ret = sig;
2713 	destroy(v);
2714 
2715 	dsask2priv(&p, f->k);
2716 	m = checkIPint(f->m);
2717 	release();
2718 	s = dsasign(&p, m);
2719 	acquire();
2720 	sig->r = ipcopymp(s->r);
2721 	sig->s = ipcopymp(s->s);
2722 	dsasigfree(s);
2723 }
2724 
2725 void
2726 DSApk_verify(void *fp)
2727 {
2728 	F_DSApk_verify *f;
2729 	DSApub p;
2730 	DSAsig sig;
2731 	mpint *m;
2732 
2733 	f = fp;
2734 	*f->ret = 0;
2735 	if(f->m == H || f->sig == H)
2736 		return;
2737 	dsapk2pub(&p, f->k);
2738 	sig.r = checkIPint(f->sig->r);
2739 	sig.s = checkIPint(f->sig->s);
2740 	m = checkIPint(f->m);
2741 	release();
2742 	*f->ret = dsaverify(&p, &sig, m) == 0;
2743 	acquire();
2744 }
2745 
2746 static void
2747 egpk2pub(EGpub* p, Keyring_EGpk* pk)
2748 {
2749 	if(pk == H)
2750 		error(exNilref);
2751 	p->p = checkIPint(pk->p);
2752 	p->alpha = checkIPint(pk->alpha);
2753 	p->key = checkIPint(pk->key);
2754 }
2755 
2756 static void
2757 egsk2priv(EGpriv* p, Keyring_EGsk* sk)
2758 {
2759 	if(sk == H || sk->pk == H)
2760 		error(exNilref);
2761 	egpk2pub(&p->pub, sk->pk);
2762 	p->secret = checkIPint(sk->secret);
2763 }
2764 
2765 static void
2766 egpriv2sk(Keyring_EGsk* sk, EGpriv* p)
2767 {
2768 	Keyring_EGpk* pk;
2769 
2770 	pk = sk->pk;
2771 	pk->p = ipcopymp(p->pub.p);
2772 	pk->alpha = ipcopymp(p->pub.alpha);
2773 	pk->key = ipcopymp(p->pub.key);
2774 	sk->secret = ipcopymp(p->secret);
2775 }
2776 
2777 void
2778 EGsk_gen(void *fp)
2779 {
2780 	F_EGsk_gen *f;
2781 	Keyring_EGsk *sk;
2782 	EGpriv *p;
2783 	void *v;
2784 
2785 	f = fp;
2786 	v = *f->ret;
2787 	sk = newthing(TEGsk, 0);
2788 	sk->pk = newthing(TEGpk, 0);
2789 	*f->ret = sk;
2790 	destroy(v);
2791 	release();
2792 	for(;;){
2793 		p = eggen(f->nlen, f->nrep);
2794 		if(mpsignif(p->pub.p) == f->nlen)
2795 			break;
2796 		egprivfree(p);
2797 	}
2798 	acquire();
2799 	egpriv2sk(sk, p);
2800 	egprivfree(p);
2801 }
2802 
2803 void
2804 EGsk_sign(void *fp)
2805 {
2806 	F_EGsk_sign *f;
2807 	Keyring_EGsig *sig;
2808 	EGpriv p;
2809 	mpint *m;
2810 	EGsig *s;
2811 	void *v;
2812 
2813 	f = fp;
2814 	v = *f->ret;
2815 	sig = newthing(TEGsig, 0);
2816 	*f->ret = sig;
2817 	destroy(v);
2818 
2819 	egsk2priv(&p, f->k);
2820 	m = checkIPint(f->m);
2821 	release();
2822 	s = egsign(&p, m);
2823 	acquire();
2824 	sig->r = ipcopymp(s->r);
2825 	sig->s = ipcopymp(s->s);
2826 	egsigfree(s);
2827 }
2828 
2829 void
2830 EGpk_verify(void *fp)
2831 {
2832 	F_EGpk_verify *f;
2833 	EGpub p;
2834 	EGsig sig;
2835 	mpint *m;
2836 
2837 	f = fp;
2838 	*f->ret = 0;
2839 	if(f->m == H || f->sig == H)
2840 		return;
2841 	egpk2pub(&p, f->k);
2842 	sig.r = checkIPint(f->sig->r);
2843 	sig.s = checkIPint(f->sig->s);
2844 	m = checkIPint(f->m);
2845 	release();
2846 	*f->ret = egverify(&p, &sig, m) == 0;
2847 	acquire();
2848 }
2849 
2850 static void
2851 rsapk2pub(RSApub* p, Keyring_RSApk* pk)
2852 {
2853 	if(pk == H)
2854 		error(exNilref);
2855 	memset(p, 0, sizeof(*p));
2856 	p->n = checkIPint(pk->n);
2857 	p->ek = checkIPint(pk->ek);
2858 }
2859 
2860 static void
2861 rsask2priv(RSApriv* p, Keyring_RSAsk* sk)
2862 {
2863 	if(sk == H || sk->pk == H)
2864 		error(exNilref);
2865 	rsapk2pub(&p->pub, sk->pk);
2866 	p->dk = checkIPint(sk->dk);
2867 	p->p = checkIPint(sk->p);
2868 	p->q = checkIPint(sk->q);
2869 	p->kp = checkIPint(sk->kp);
2870 	p->kq = checkIPint(sk->kq);
2871 	p->c2 = checkIPint(sk->c2);
2872 }
2873 
2874 static void
2875 rsapriv2sk(Keyring_RSAsk* sk, RSApriv* p)
2876 {
2877 	Keyring_RSApk* pk;
2878 
2879 	pk = sk->pk;
2880 	pk->n = ipcopymp(p->pub.n);
2881 	pk->ek = ipcopymp(p->pub.ek);
2882 	sk->dk = ipcopymp(p->dk);
2883 	sk->p = ipcopymp(p->p);
2884 	sk->q = ipcopymp(p->q);
2885 	sk->kp = ipcopymp(p->kp);
2886 	sk->kq = ipcopymp(p->kq);
2887 	sk->c2 = ipcopymp(p->c2);
2888 }
2889 
2890 void
2891 RSApk_encrypt(void *fp)
2892 {
2893 	F_RSApk_encrypt *f;
2894 	RSApub p;
2895 	mpint *m, *o;
2896 	void *v;
2897 
2898 	f = fp;
2899 	v = *f->ret;
2900 	*f->ret = H;
2901 	destroy(v);
2902 
2903 	rsapk2pub(&p, f->k);
2904 	m = checkIPint(f->m);
2905 	release();
2906 	o = rsaencrypt(&p, m, nil);
2907 	acquire();
2908 	*f->ret = newIPint(o);
2909 }
2910 
2911 void
2912 RSAsk_gen(void *fp)
2913 {
2914 	F_RSAsk_gen *f;
2915 	Keyring_RSAsk *sk;
2916 	RSApriv *p;
2917 	void *v;
2918 
2919 	f = fp;
2920 	v = *f->ret;
2921 	sk = newthing(TRSAsk, 0);
2922 	sk->pk = newthing(TRSApk, 0);
2923 	*f->ret = sk;
2924 	destroy(v);
2925 	release();
2926 	for(;;){
2927 		p = rsagen(f->nlen, f->elen, f->nrep);
2928 		if(mpsignif(p->pub.n) == f->nlen)
2929 			break;
2930 		rsaprivfree(p);
2931 	}
2932 	acquire();
2933 	rsapriv2sk(sk, p);
2934 	rsaprivfree(p);
2935 }
2936 
2937 void
2938 RSAsk_fill(void *fp)
2939 {
2940 	F_RSAsk_fill *f;
2941 	Keyring_RSAsk *sk;
2942 	RSApriv *p;
2943 	void *v;
2944 
2945 	f = fp;
2946 	v = *f->ret;
2947 	sk = newthing(TRSAsk, 0);
2948 	sk->pk = newthing(TRSApk, 0);
2949 	*f->ret = sk;
2950 	destroy(v);
2951 	release();
2952 	p = rsafill(checkIPint(f->n), checkIPint(f->e), checkIPint(f->d),
2953 			checkIPint(f->p), checkIPint(f->q));
2954 	acquire();
2955 	if(p == nil) {
2956 		*f->ret = H;
2957 		destroy(sk);
2958 	}else{
2959 		rsapriv2sk(sk, p);
2960 		rsaprivfree(p);
2961 	}
2962 }
2963 
2964 void
2965 RSAsk_decrypt(void *fp)
2966 {
2967 	F_RSAsk_decrypt *f;
2968 	RSApriv p;
2969 	mpint *m, *o;
2970 	void *v;
2971 
2972 	f = fp;
2973 	v = *f->ret;
2974 	*f->ret = H;
2975 	destroy(v);
2976 
2977 	rsask2priv(&p, f->k);
2978 	m = checkIPint(f->m);
2979 	release();
2980 	o = rsadecrypt(&p, m, nil);
2981 	acquire();
2982 	*f->ret = newIPint(o);
2983 }
2984 
2985 void
2986 RSAsk_sign(void *fp)
2987 {
2988 	F_RSAsk_sign *f;
2989 	Keyring_RSAsig *sig;
2990 	RSApriv p;
2991 	mpint *m, *s;
2992 	void *v;
2993 
2994 	f = fp;
2995 	v = *f->ret;
2996 	sig = newthing(TRSAsig, 0);
2997 	*f->ret = sig;
2998 	destroy(v);
2999 
3000 	rsask2priv(&p, f->k);
3001 	m = checkIPint(f->m);
3002 	release();
3003 	s = rsadecrypt(&p, m, nil);
3004 	acquire();
3005 	sig->n = newIPint(s);
3006 }
3007 
3008 void
3009 RSApk_verify(void *fp)
3010 {
3011 	F_RSApk_verify *f;
3012 	RSApub p;
3013 	mpint *sig, *m, *t;
3014 
3015 	f = fp;
3016 	*f->ret = 0;
3017 	if(f->m == H || f->sig == H)
3018 		return;
3019 	rsapk2pub(&p, f->k);
3020 	sig = checkIPint(f->sig->n);
3021 	m = checkIPint(f->m);
3022 	release();
3023 	t = rsaencrypt(&p, sig, nil);
3024 	*f->ret = mpcmp(t, m) == 0;
3025 	mpfree(t);
3026 	acquire();
3027 }
3028