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