xref: /inferno-os/libinterp/keyring.c (revision aee7f58dfcd519d45482e45ab1ce6026c846dc21)
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_sha224(void *fp)
1267 {
1268 	F_Keyring_sha224 *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, SHA224dlen, f->state, sha224);
1277 }
1278 
1279 void
1280 Keyring_sha256(void *fp)
1281 {
1282 	F_Keyring_sha256 *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, SHA256dlen, f->state, sha256);
1291 }
1292 
1293 void
1294 Keyring_sha384(void *fp)
1295 {
1296 	F_Keyring_sha384 *f;
1297 	void *r;
1298 
1299 	f = fp;
1300 	r = *f->ret;
1301 	*f->ret = H;
1302 	destroy(r);
1303 
1304 	*f->ret = keyring_digest_x(f->buf, f->n, f->digest, SHA384dlen, f->state, sha384);
1305 }
1306 
1307 void
1308 Keyring_sha512(void *fp)
1309 {
1310 	F_Keyring_sha512 *f;
1311 	void *r;
1312 
1313 	f = fp;
1314 	r = *f->ret;
1315 	*f->ret = H;
1316 	destroy(r);
1317 
1318 	*f->ret = keyring_digest_x(f->buf, f->n, f->digest, SHA512dlen, f->state, sha512);
1319 }
1320 
1321 void
1322 Keyring_md5(void *fp)
1323 {
1324 	F_Keyring_md5 *f;
1325 	void *r;
1326 
1327 	f = fp;
1328 	r = *f->ret;
1329 	*f->ret = H;
1330 	destroy(r);
1331 
1332 	*f->ret = keyring_digest_x(f->buf, f->n, f->digest, MD5dlen, f->state, md5);
1333 }
1334 
1335 void
1336 Keyring_md4(void *fp)
1337 {
1338 	F_Keyring_md4 *f;
1339 	void *r;
1340 
1341 	f = fp;
1342 	r = *f->ret;
1343 	*f->ret = H;
1344 	destroy(r);
1345 
1346 	*f->ret = keyring_digest_x(f->buf, f->n, f->digest, MD4dlen, f->state, md4);
1347 }
1348 
1349 static Keyring_DigestState*
1350 keyring_hmac_x(Array *data, int n, Array *key, Array *digest, int dlen, Keyring_DigestState *state, DigestState* (*fn)(uchar*, ulong, uchar*, ulong, uchar*, DigestState*))
1351 {
1352 	Heap *h;
1353 	XDigestState *ds;
1354 	uchar *cdata, *cdigest;
1355 
1356 	if(data != H){
1357 		if(n > data->len)
1358 			n = data->len;
1359 		cdata = data->data;
1360 	}else{
1361 		if(n != 0)
1362 			error(exInval);
1363 		cdata = nil;
1364 	}
1365 
1366 	if(key == H || key->len > 64)
1367 		error(exBadKey);
1368 
1369 	if(digest != H){
1370 		if(digest->len < dlen)
1371 			error(exBadDigest);
1372 		cdigest = digest->data;
1373 	} else
1374 		cdigest = nil;
1375 
1376 	if(state == H){
1377 		h = heap(TDigestState);
1378 		ds = H2D(XDigestState*, h);
1379 		memset(&ds->state, 0, sizeof(ds->state));
1380 	} else
1381 		ds = checktype(state, TDigestState, "DigestState", 1);
1382 
1383 	(*fn)(cdata, n, key->data, key->len, cdigest, &ds->state);
1384 
1385 	return (Keyring_DigestState*)ds;
1386 }
1387 
1388 void
1389 Keyring_hmac_sha1(void *fp)
1390 {
1391 	F_Keyring_hmac_sha1 *f;
1392 	void *r;
1393 
1394 	f = fp;
1395 	r = *f->ret;
1396 	*f->ret = H;
1397 	destroy(r);
1398 	*f->ret = keyring_hmac_x(f->data, f->n, f->key, f->digest, SHA1dlen, f->state, hmac_sha1);
1399 }
1400 
1401 void
1402 Keyring_hmac_md5(void *fp)
1403 {
1404 	F_Keyring_hmac_md5 *f;
1405 	void *r;
1406 
1407 	f = fp;
1408 	r = *f->ret;
1409 	*f->ret = H;
1410 	destroy(r);
1411 	*f->ret = keyring_hmac_x(f->data, f->n, f->key, f->digest, MD5dlen, f->state, hmac_md5);
1412 }
1413 
1414 void
1415 Keyring_dhparams(void *fp)
1416 {
1417 	F_Keyring_dhparams *f;
1418 	mpint *p, *alpha;
1419 	void *v;
1420 
1421 	f = fp;
1422 	v = f->ret->t0;
1423 	f->ret->t0 = H;
1424 	destroy(v);
1425 	v = f->ret->t1;
1426 	f->ret->t1 = H;
1427 	destroy(v);
1428 
1429 	p = mpnew(0);
1430 	alpha = mpnew(0);
1431 	release();
1432 	if(f->nbits == 1024)
1433 		DSAprimes(alpha, p, nil);
1434 	else
1435 		gensafeprime(p, alpha, f->nbits, 0);
1436 	acquire();
1437 	f->ret->t0 = newIPint(alpha);
1438 	f->ret->t1 = newIPint(p);
1439 }
1440 
1441 static int
1442 sendmsg(int fd, void *buf, int n)
1443 {
1444 	char num[10];
1445 
1446 	release();
1447 	snprint(num, sizeof(num), "%4.4d\n", n);
1448 	if(kwrite(fd, num, 5) != 5){
1449 		acquire();
1450 		return -1;
1451 	}
1452 	n = kwrite(fd, buf, n);
1453 	acquire();
1454 	return n;
1455 }
1456 
1457 void
1458 Keyring_sendmsg(void *fp)
1459 {
1460 	F_Keyring_sendmsg *f;
1461 	int n;
1462 
1463 	f = fp;
1464 	*f->ret = -1;
1465 	if(f->fd == H || f->buf == H || f->n < 0)
1466 		return;
1467 	n = f->n;
1468 	if(n < 0 || n > f->buf->len)
1469 		error(exBounds);
1470 	*f->ret = sendmsg(f->fd->fd, f->buf->data, n);
1471 }
1472 
1473 static int
1474 senderr(int fd, char *err, int addrmt)
1475 {
1476 	char num[10];
1477 	int n, m;
1478 
1479 	release();
1480 	n = strlen(err);
1481 	m = 0;
1482 	if(addrmt)
1483 		m = strlen("remote: ");
1484 	snprint(num, sizeof(num), "!%3.3d\n", n+m);
1485 	if(kwrite(fd, num, 5) != 5){
1486 		acquire();
1487 		return -1;
1488 	}
1489 	if(addrmt)
1490 		kwrite(fd, "remote: ", m);
1491 	n = kwrite(fd, err, n);
1492 	acquire();
1493 	return n;
1494 }
1495 
1496 void
1497 Keyring_senderrmsg(void *fp)
1498 {
1499 	F_Keyring_senderrmsg *f;
1500 	char *s;
1501 
1502 	f = fp;
1503 	*f->ret = -1;
1504 	if(f->fd == H)
1505 		return;
1506 	s = string2c(f->s);
1507 	if(senderr(f->fd->fd, s, 0) > 0)
1508 		*f->ret = 0;
1509 }
1510 
1511 static int
1512 nreadn(int fd, void *av, int n)
1513 {
1514 
1515 	char *a;
1516 	long m, t;
1517 
1518 	a = av;
1519 	t = 0;
1520 	while(t < n){
1521 		m = kread(fd, a+t, n-t);
1522 		if(m <= 0){
1523 			if(t == 0)
1524 				return m;
1525 			break;
1526 		}
1527 		t += m;
1528 	}
1529 	return t;
1530 }
1531 
1532 #define MSG "input or format error"
1533 
1534 static void
1535 getmsgerr(char *buf, int n, int r)
1536 {
1537 	char *e;
1538 	int l;
1539 
1540 	e = r>0? MSG: "hungup";
1541 	l = strlen(e)+1;
1542 	if(n > l)
1543 		n = l;
1544 	memmove(buf, e, n-1);
1545 	buf[n-1] = 0;
1546 }
1547 
1548 static int
1549 getmsg(int fd, char *buf, int n)
1550 {
1551 	char num[6];
1552 	int len, r;
1553 
1554 	release();
1555 	if((r = nreadn(fd, num, 5)) != 5){
1556 		getmsgerr(buf, n, r);
1557 		acquire();
1558 		return -1;
1559 	}
1560 	num[5] = 0;
1561 
1562 	if(num[0] == '!')
1563 		len = strtoul(num+1, 0, 10);
1564 	else
1565 		len = strtoul(num, 0, 10);
1566 
1567 	r = -1;
1568 	if(len < 0 || len >= n || (r = nreadn(fd, buf, len)) != len){
1569 		getmsgerr(buf, n, r);
1570 		acquire();
1571 		return -1;
1572 	}
1573 
1574 	buf[len] = 0;
1575 	acquire();
1576 	if(num[0] == '!')
1577 		return -len;
1578 
1579 	return len;
1580 }
1581 
1582 void
1583 Keyring_getmsg(void *fp)
1584 {
1585 	F_Keyring_getmsg *f;
1586 	char *buf;
1587 	int n;
1588 	void *r;
1589 
1590 	f = fp;
1591 	r = *f->ret;
1592 	*f->ret = H;
1593 	destroy(r);
1594 	if(f->fd == H){
1595 		kwerrstr("nil fd");
1596 		return;
1597 	}
1598 
1599 	buf = malloc(Maxmsg);
1600 	if(buf == nil){
1601 		kwerrstr(exNomem);
1602 		return;
1603 	}
1604 
1605 	n = getmsg(f->fd->fd, buf, Maxmsg);
1606 	if(n < 0){
1607 		kwerrstr("%s", buf);
1608 		free(buf);
1609 		return;
1610 	}
1611 
1612 	*f->ret = mem2array(buf, n);
1613 	free(buf);
1614 }
1615 
1616 void
1617 Keyring_auth(void *fp)
1618 {
1619 	F_Keyring_auth *f;
1620 	mpint *r0, *r1, *p, *alpha, *alphar0, *alphar1, *alphar0r1;
1621 	SK *mysk;
1622 	PK *mypk, *spk, *hispk;
1623 	Certificate *cert, *hiscert, *alphacert;
1624 	char *buf, *err;
1625 	uchar *cvb;
1626 	int n, fd, version;
1627 	long now;
1628 
1629 	hispk = H;
1630 	hiscert = H;
1631 	alphacert = H;
1632 	err = nil;
1633 
1634 	/* null out the return values */
1635 	f = fp;
1636 	destroy(f->ret->t0);
1637 	f->ret->t0 = H;
1638 	destroy(f->ret->t1);
1639 	f->ret->t1 = H;
1640 	r0 = r1 = alphar0 = alphar1 = alphar0r1 = nil;
1641 
1642 	/* check args */
1643 	if(f->fd == H || f->fd->fd < 0){
1644 		retstr("bad fd", &f->ret->t0);
1645 		return;
1646 	}
1647 	fd = f->fd->fd;
1648 
1649 	buf = malloc(Maxbuf);
1650 	if(buf == nil){
1651 		retstr(exNomem, &f->ret->t0);
1652 		return;
1653 	}
1654 
1655 	/* send auth protocol version number */
1656 	if(sendmsg(fd, "1", 1) <= 0){
1657 		err = MSG;
1658 		goto out;
1659 	}
1660 
1661 	/* get auth protocol version number */
1662 	n = getmsg(fd, buf, Maxbuf-1);
1663 	if(n < 0){
1664 		err = buf;
1665 		goto out;
1666 	}
1667 	buf[n] = 0;
1668 	version = atoi(buf);
1669 	if(version != 1 || n > 4){
1670 		err = "incompatible authentication protocol";
1671 		goto out;
1672 	}
1673 
1674 	if(f->info == H){
1675 		err = "no authentication information";
1676 		goto out;
1677 	}
1678 	if(f->info->p == H){
1679 		err = "missing diffie hellman mod";
1680 		goto out;
1681 	}
1682 	if(f->info->alpha == H){
1683 		err = "missing diffie hellman base";
1684 		goto out;
1685 	}
1686 	mysk = checkSK(f->info->mysk);
1687 	if(mysk == H){
1688 		err = "bad sk arg";
1689 		goto out;
1690 	}
1691 	mypk = checkPK(f->info->mypk);
1692 	if(mypk == H){
1693 		err = "bad pk arg";
1694 		goto out;
1695 	}
1696 	cert = checkCertificate(f->info->cert);
1697 	if(cert == H){
1698 		err = "bad certificate arg";
1699 		goto out;
1700 	}
1701 	spk = checkPK(f->info->spk);
1702 	if(spk == H){
1703 		err = "bad signer key arg";
1704 		goto out;
1705 	}
1706 
1707 	/* get alpha and p */
1708 	p = checkIPint(f->info->p);
1709 	alpha = checkIPint(f->info->alpha);
1710 
1711 	if(p->sign == -1) {
1712 		err = "-ve modulus";
1713 		goto out;
1714 	}
1715 
1716 	r0 = mpnew(0);
1717 	r1 = mpnew(0);
1718 	alphar0 = mpnew(0);
1719 	alphar0r1 = mpnew(0);
1720 
1721 	/* generate alpha**r0 */
1722 if(0)print("X");
1723 	release();
1724 	mprand(mpsignif(p), genrandom, r0);
1725 	mpexp(alpha, r0, p, alphar0);
1726 	acquire();
1727 if(0)print("Y");
1728 
1729 	/* send alpha**r0 mod p, mycert, and mypk */
1730 	n = bigtobase64(alphar0, buf, Maxbuf);
1731 	if(sendmsg(fd, buf, n) <= 0){
1732 		err = MSG;
1733 		goto out;
1734 	}
1735 
1736 	n = certtostr(cert, buf, Maxbuf);
1737 	if(sendmsg(fd, buf, n) <= 0){
1738 		err = MSG;
1739 		goto out;
1740 	}
1741 
1742 	n = pktostr(mypk, buf, Maxbuf);
1743 	if(sendmsg(fd, buf, n) <= 0){
1744 		err = MSG;
1745 		goto out;
1746 	}
1747 
1748 	/* get alpha**r1 mod p, hiscert, hispk */
1749 	n = getmsg(fd, buf, Maxbuf-1);
1750 	if(n < 0){
1751 		err = buf;
1752 		goto out;
1753 	}
1754 	buf[n] = 0;
1755 	alphar1 = strtomp(buf, nil, 64, nil);
1756 
1757 	/* trying a fast one */
1758 	if(mpcmp(p, alphar1) <= 0){
1759 		err = "implausible parameter value";
1760 		goto out;
1761 	}
1762 
1763 	/* if alpha**r1 == alpha**r0, someone may be trying a replay */
1764 	if(mpcmp(alphar0, alphar1) == 0){
1765 		err = "possible replay attack";
1766 		goto out;
1767 	}
1768 
1769 	n = getmsg(fd, buf, Maxbuf-1);
1770 	if(n < 0){
1771 		err = buf;
1772 		goto out;
1773 	}
1774 	buf[n] = 0;
1775 	hiscert = strtocert(buf);
1776 	if(hiscert == H){
1777 		err = "bad certificate syntax";
1778 		goto out;
1779 	}
1780 	certimmutable(hiscert);		/* hide from the garbage collector */
1781 
1782 	n = getmsg(fd, buf, Maxbuf-1);
1783 	if(n < 0){
1784 		err = buf;
1785 		goto out;
1786 	}
1787 	buf[n] = 0;
1788 	hispk = strtopk(buf);
1789 	if(hispk == H){
1790 		err = "bad public key";
1791 		goto out;
1792 	}
1793 	pkimmutable(hispk);		/* hide from the garbage collector */
1794 
1795 	/* verify his public key */
1796 	if(verify(spk, hiscert, buf, n) == 0){
1797 		err = "pk doesn't match certificate";
1798 		goto out;
1799 	}
1800 
1801 	/* check expiration date - in seconds of epoch */
1802 
1803 	now = osusectime()/1000000;
1804 	if(hiscert->x.exp != 0 && hiscert->x.exp <= now){
1805 		err = "certificate expired";
1806 		goto out;
1807 	}
1808 
1809 	/* sign alpha**r0 and alpha**r1 and send */
1810 	n = bigtobase64(alphar0, buf, Maxbuf);
1811 	n += bigtobase64(alphar1, buf+n, Maxbuf-n);
1812 	alphacert = sign(mysk, "sha1", 0, (uchar*)buf, n);
1813 	n = certtostr(alphacert, buf, Maxbuf);
1814 	if(sendmsg(fd, buf, n) <= 0){
1815 		err = MSG;
1816 		goto out;
1817 	}
1818 	certmutable(alphacert);
1819 	destroy(alphacert);
1820 	alphacert = H;
1821 
1822 	/* get signature of alpha**r1 and alpha**r0 and verify */
1823 	n = getmsg(fd, buf, Maxbuf-1);
1824 	if(n < 0){
1825 		err = buf;
1826 		goto out;
1827 	}
1828 	buf[n] = 0;
1829 	alphacert = strtocert(buf);
1830 	if(alphacert == H){
1831 		err = "alpha**r1 doesn't match certificate";
1832 		goto out;
1833 	}
1834 	certimmutable(alphacert);		/* hide from the garbage collector */
1835 	n = bigtobase64(alphar1, buf, Maxbuf);
1836 	n += bigtobase64(alphar0, buf+n, Maxbuf-n);
1837 	if(verify(hispk, alphacert, buf, n) == 0){
1838 		err = "bad certificate";
1839 		goto out;
1840 	}
1841 
1842 	/* we are now authenticated and have a common secret, alpha**(r0*r1) */
1843 	f->ret->t0 = stringdup(hispk->x.owner);
1844 	mpexp(alphar1, r0, p, alphar0r1);
1845 	n = mptobe(alphar0r1, nil, Maxbuf, &cvb);
1846 	if(n < 0){
1847 		err = "bad conversion";
1848 		goto out;
1849 	}
1850 	f->ret->t1 = mem2array(cvb, n);
1851 	free(cvb);
1852 
1853 out:
1854 	/* return status */
1855 	if(f->ret->t0 == H){
1856 		if(err == buf)
1857 			senderr(fd, "missing your authentication data", 1);
1858 		else
1859 			senderr(fd, err, 1);
1860 	}else
1861 		sendmsg(fd, "OK", 2);
1862 
1863 	/* read responses */
1864 	if(err != buf){
1865 		for(;;){
1866 			n = getmsg(fd, buf, Maxbuf-1);
1867 			if(n < 0){
1868 				destroy(f->ret->t0);
1869 				f->ret->t0 = H;
1870 				destroy(f->ret->t1);
1871 				f->ret->t1 = H;
1872 				if(err == nil){
1873 					if(n < -1)
1874 						err = buf;
1875 					else
1876 						err = MSG;
1877 				}
1878 				break;
1879 			}
1880 			if(n == 2 && buf[0] == 'O' && buf[1] == 'K')
1881 				break;
1882 		}
1883 	}
1884 
1885 	/* set error and id to nobody */
1886 	if(f->ret->t0 == H){
1887 		if(err == nil)
1888 			err = MSG;
1889 		retstr(err, &f->ret->t0);
1890 		if(f->setid)
1891 			setid("nobody", 1);
1892 	} else {
1893 		/* change user id */
1894 		if(f->setid)
1895 			setid(string2c(f->ret->t0), 1);
1896 	}
1897 
1898 	/* free resources */
1899 	if(hispk != H){
1900 		pkmutable(hispk);
1901 		destroy(hispk);
1902 	}
1903 	if(hiscert != H){
1904 		certmutable(hiscert);
1905 		destroy(hiscert);
1906 	}
1907 	if(alphacert != H){
1908 		certmutable(alphacert);
1909 		destroy(alphacert);
1910 	}
1911 	free(buf);
1912 	if(r0 != nil){
1913 		mpfree(r0);
1914 		mpfree(r1);
1915 		mpfree(alphar0);
1916 		mpfree(alphar1);
1917 		mpfree(alphar0r1);
1918 	}
1919 }
1920 
1921 static Keyring_Authinfo*
1922 newAuthinfo(void)
1923 {
1924 	return H2D(Keyring_Authinfo*, heap(TAuthinfo));
1925 }
1926 
1927 void
1928 Keyring_writeauthinfo(void *fp)
1929 {
1930 	F_Keyring_writeauthinfo *f;
1931 	int n, fd;
1932 	char *buf;
1933 	PK *spk;
1934 	SK *mysk;
1935 	Certificate *c;
1936 
1937 	f = fp;
1938 	*f->ret = -1;
1939 
1940 	if(f->filename == H)
1941 		return;
1942 	if(f->info == H)
1943 		return;
1944 	if(f->info->alpha == H || f->info->p == H)
1945 		return;
1946 	if(((IPint*)f->info->alpha)->b == 0 || ((IPint*)f->info->p)->b == H)
1947 		return;
1948 	spk = checkPK(f->info->spk);
1949 	mysk = checkSK(f->info->mysk);
1950 	c = checkCertificate(f->info->cert);
1951 
1952 	buf = malloc(Maxbuf);
1953 	if(buf == nil)
1954 		return;
1955 
1956 	/*
1957 	 *  The file may already exist or be a file2chan file so first
1958 	 *  try opening with truncation since create will change the
1959 	 *  permissions of the file and create doesn't work with a
1960 	 *  file2chan.
1961 	 */
1962 	release();
1963 	fd = kopen(string2c(f->filename), OTRUNC|OWRITE);
1964 	if(fd < 0)
1965 		fd = kcreate(string2c(f->filename), OWRITE, 0600);
1966 	if(fd < 0)
1967 		fd = kopen(string2c(f->filename), OWRITE);
1968 	acquire();
1969 	if(fd < 0)
1970 		goto out;
1971 
1972 	/* signer's public key */
1973 	n = pktostr(spk, buf, Maxmsg);
1974 	if(sendmsg(fd, buf, n) <= 0)
1975 		goto out;
1976 
1977 	/* certificate for my public key */
1978 	n = certtostr(c, buf, Maxmsg);
1979 	if(sendmsg(fd, buf, n) <= 0)
1980 		goto out;
1981 
1982 	/* my secret/public key */
1983 	n = sktostr(mysk, buf, Maxmsg);
1984 	if(sendmsg(fd, buf, n) <= 0)
1985 		goto out;
1986 
1987 	/* diffie hellman base */
1988 	n = bigtobase64(((IPint*)f->info->alpha)->b, buf, Maxbuf);
1989 	if(sendmsg(fd, buf, n) <= 0)
1990 		goto out;
1991 
1992 	/* diffie hellman modulus */
1993 	n = bigtobase64(((IPint*)f->info->p)->b, buf, Maxbuf);
1994 	if(sendmsg(fd, buf, n) <= 0)
1995 		goto out;
1996 
1997 	*f->ret = 0;
1998 out:
1999 	free(buf);
2000 	if(fd >= 0){
2001 		release();
2002 		kclose(fd);
2003 		acquire();
2004 	}
2005 }
2006 
2007 void
2008 Keyring_readauthinfo(void *fp)
2009 {
2010 	F_Keyring_readauthinfo *f;
2011 	int fd;
2012 	char *buf;
2013 	int n, ok;
2014 	PK *mypk;
2015 	SK *mysk;
2016 	SigAlg *sa;
2017 	Keyring_Authinfo *ai;
2018 	mpint *b;
2019 	void *r;
2020 
2021 	f = fp;
2022 	r = *f->ret;
2023 	*f->ret = H;
2024 	destroy(r);
2025 
2026 	ok = 0;
2027 
2028 	if(f->filename == H)
2029 		return;
2030 
2031 	buf = malloc(Maxbuf);
2032 	if(buf == nil)
2033 		return;
2034 
2035 	ai = newAuthinfo();
2036 	*f->ret = ai;
2037 
2038 	release();
2039 	fd = kopen(string2c(f->filename), OREAD);
2040 	acquire();
2041 	if(fd < 0)
2042 		goto out;
2043 
2044 	/* signer's public key */
2045 	n = getmsg(fd, buf, Maxmsg);
2046 	if(n < 0)
2047 		goto out;
2048 
2049 	ai->spk = (Keyring_PK*)strtopk(buf);
2050 	if(ai->spk == H)
2051 		goto out;
2052 
2053 	/* certificate for my public key */
2054 	n = getmsg(fd, buf, Maxmsg);
2055 	if(n < 0)
2056 		goto out;
2057 	ai->cert = (Keyring_Certificate*)strtocert(buf);
2058 	if(ai->cert == H)
2059 		goto out;
2060 
2061 	/* my secret/public key */
2062 	n = getmsg(fd, buf, Maxmsg);
2063 	if(n < 0)
2064 		goto out;
2065 	mysk = strtosk(buf);
2066 	ai->mysk = (Keyring_SK*)mysk;
2067 	if(mysk == H)
2068 		goto out;
2069 	sa = checkSigAlg(mysk->x.sa);
2070 	mypk = newPK(sa, stringdup(mysk->x.owner), 1);
2071 	mypk->key = (*sa->vec->sk2pk)(mysk->key);
2072 	ai->mypk = (Keyring_PK*)mypk;
2073 
2074 	/* diffie hellman base */
2075 	n = getmsg(fd, buf, Maxmsg);
2076 	if(n < 0)
2077 		goto out;
2078 	b = strtomp(buf, nil, 64, nil);
2079 	ai->alpha = newIPint(b);
2080 
2081 	/* diffie hellman modulus */
2082 	n = getmsg(fd, buf, Maxmsg);
2083 	if(n < 0)
2084 		goto out;
2085 	b = strtomp(buf, nil, 64, nil);
2086 	ai->p = newIPint(b);
2087 	ok = 1;
2088 out:
2089 	if(!ok){
2090 		r = *f->ret;
2091 		*f->ret = H;
2092 		destroy(r);
2093 	}
2094 	free(buf);
2095 	if(fd >= 0){
2096 		release();
2097 		kclose(fd);
2098 		acquire();
2099 		kwerrstr("%q: %s", string2c(f->filename), MSG);
2100 	}
2101 }
2102 
2103 void
2104 keyringmodinit(void)
2105 {
2106 	SigAlgVec *sav;
2107 	extern SigAlgVec* elgamalinit(void);
2108 	extern SigAlgVec* rsainit(void);
2109 	extern SigAlgVec* dsainit(void);
2110 
2111 	TIPint = dtype(freeIPint, sizeof(IPint), IPintmap, sizeof(IPintmap));
2112 	TSigAlg = dtype(freeSigAlg, sizeof(SigAlg), SigAlgmap, sizeof(SigAlgmap));
2113 	TSK = dtype(freeSK, sizeof(SK), SKmap, sizeof(SKmap));
2114 	TPK = dtype(freePK, sizeof(PK), PKmap, sizeof(PKmap));
2115 	TCertificate = dtype(freeCertificate, sizeof(Certificate), Certificatemap,
2116 		sizeof(Certificatemap));
2117 	TDigestState = dtype(freeheap, sizeof(XDigestState), DigestStatemap,
2118 		sizeof(DigestStatemap));
2119 	TAESstate = dtype(freeheap, sizeof(XAESstate), AESstatemap,
2120 		sizeof(AESstatemap));
2121 	TDESstate = dtype(freeheap, sizeof(XDESstate), DESstatemap,
2122 		sizeof(DESstatemap));
2123 	TIDEAstate = dtype(freeheap, sizeof(XIDEAstate), IDEAstatemap,
2124 		sizeof(IDEAstatemap));
2125 	TBFstate = dtype(freeheap, sizeof(XBFstate), BFstatemap,
2126 		sizeof(BFstatemap));
2127 	TRC4state = dtype(freeheap, sizeof(XRC4state), RC4statemap,
2128 		sizeof(RC4statemap));
2129 	TAuthinfo = dtype(freeheap, sizeof(Keyring_Authinfo), Authinfomap, sizeof(Authinfomap));
2130 	TDSAsk = dtype(freeheap, sizeof(Keyring_DSAsk), DSAskmap, sizeof(DSAskmap));
2131 	TDSApk = dtype(freeheap, sizeof(Keyring_DSApk), DSApkmap, sizeof(DSApkmap));
2132 	TDSAsig = dtype(freeheap, sizeof(Keyring_DSAsig), DSAsigmap, sizeof(DSAsigmap));
2133 	TEGsk = dtype(freeheap, sizeof(Keyring_EGsk), EGskmap, sizeof(EGskmap));
2134 	TEGpk = dtype(freeheap, sizeof(Keyring_EGpk), EGpkmap, sizeof(EGpkmap));
2135 	TEGsig = dtype(freeheap, sizeof(Keyring_EGsig), EGsigmap, sizeof(EGsigmap));
2136 	TRSAsk = dtype(freeheap, sizeof(Keyring_RSAsk), RSAskmap, sizeof(RSAskmap));
2137 	TRSApk = dtype(freeheap, sizeof(Keyring_RSApk), RSApkmap, sizeof(RSApkmap));
2138 	TRSAsig = dtype(freeheap, sizeof(Keyring_RSAsig), RSAsigmap, sizeof(RSAsigmap));
2139 
2140 	if((sav = elgamalinit()) != nil)
2141 		algs[nalg++] = sav;
2142 	if((sav = rsainit()) != nil)
2143 		algs[nalg++] = sav;
2144 	if((sav = dsainit()) != nil)
2145 		algs[nalg++] = sav;
2146 
2147 	fmtinstall('U', big64conv);
2148 	builtinmod("$Keyring", Keyringmodtab, Keyringmodlen);
2149 }
2150 
2151 /*
2152  *  IO on a delimited channel.  A message starting with 0x00 is a normal
2153  *  message.  One starting with 0xff is an error string.
2154  *
2155  *  return negative number for error messages (including hangup)
2156  */
2157 static int
2158 getbuf(int fd, uchar *buf, int n, char *err, int nerr)
2159 {
2160 	int len;
2161 
2162 	release();
2163 	len = kread(fd, buf, n);
2164 	acquire();
2165 	if(len <= 0){
2166 		strncpy(err, "hungup", nerr);
2167 		buf[nerr-1] = 0;
2168 		return -1;
2169 	}
2170 	if(buf[0] == 0)
2171 		return len-1;
2172 	if(buf[0] != 0xff){
2173 		/*
2174 		 * this happens when the client's password is wrong: both sides use a digest of the
2175 		 * password as a crypt key for devssl. When they don't match decryption garbles
2176 		 * messages
2177 		 */
2178 		strncpy(err, "failure", nerr);
2179 		err[nerr-1] = 0;
2180 		return -1;
2181 	}
2182 
2183 	/* error string */
2184 	len--;
2185 	if(len < 1){
2186 		strncpy(err, "unknown", nerr);
2187 		err[nerr-1] = 0;
2188 	} else {
2189 		if(len >= nerr)
2190 			len = nerr-1;
2191 		memmove(err, buf+1, len);
2192 		err[len] = 0;
2193 	}
2194 	return -1;
2195 }
2196 
2197 void
2198 Keyring_getstring(void *fp)
2199 {
2200 	F_Keyring_getstring *f;
2201 	uchar *buf;
2202 	char err[64];
2203 	int n;
2204 
2205 	f = fp;
2206 	destroy(f->ret->t0);
2207 	f->ret->t0 = H;
2208 	destroy(f->ret->t1);
2209 	f->ret->t1 = H;
2210 
2211 	if(f->fd == H)
2212 		return;
2213 
2214 	buf = malloc(Maxmsg);
2215 	if(buf == nil)
2216 		return;
2217 
2218 	n = getbuf(f->fd->fd, buf, Maxmsg, err, sizeof(err));
2219 	if(n < 0)
2220 		retnstr(err, strlen(err), &f->ret->t1);
2221 	else
2222 		retnstr(((char*)buf)+1, n, &f->ret->t0);
2223 
2224 	free(buf);
2225 }
2226 
2227 void
2228 Keyring_getbytearray(void *fp)
2229 {
2230 	F_Keyring_getbytearray *f;
2231 	uchar *buf;
2232 	char err[64];
2233 	int n;
2234 
2235 	f = fp;
2236 	destroy(f->ret->t0);
2237 	f->ret->t0 = H;
2238 	destroy(f->ret->t1);
2239 	f->ret->t1 = H;
2240 
2241 	if(f->fd == H)
2242 		return;
2243 
2244 	buf = malloc(Maxmsg);
2245 	if(buf == nil)
2246 		return;
2247 
2248 	n = getbuf(f->fd->fd, buf, Maxmsg, err, sizeof(err));
2249 	if(n < 0)
2250 		retnstr(err, strlen(err), &f->ret->t1);
2251 	else
2252 		f->ret->t0 = mem2array(buf+1, n);
2253 
2254 	free(buf);
2255 }
2256 
2257 static int
2258 putbuf(int fd, void *p, int n)
2259 {
2260 	char *buf;
2261 
2262 	buf = malloc(Maxmsg);
2263 	if(buf == nil)
2264 		return -1;
2265 
2266 	release();
2267 	buf[0] = 0;
2268 	if(n < 0){
2269 		buf[0] = 0xff;
2270 		n = -n;
2271 	}
2272 	if(n >= Maxmsg)
2273 		n = Maxmsg - 1;
2274 	memmove(buf+1, p, n);
2275 	n = kwrite(fd, buf, n+1);
2276 	acquire();
2277 
2278 	free(buf);
2279 	return n;
2280 }
2281 
2282 void
2283 Keyring_putstring(void *fp)
2284 {
2285 	F_Keyring_putstring *f;
2286 
2287 	f = fp;
2288 	*f->ret = -1;
2289 	if(f->fd == H || f->s == H)
2290 		return;
2291 	*f->ret = putbuf(f->fd->fd, string2c(f->s), strlen(string2c(f->s)));
2292 }
2293 
2294 void
2295 Keyring_puterror(void *fp)
2296 {
2297 	F_Keyring_puterror *f;
2298 
2299 	f = fp;
2300 	*f->ret = -1;
2301 	if(f->fd == H || f->s == H)
2302 		return;
2303 	*f->ret = putbuf(f->fd->fd, string2c(f->s), -strlen(string2c(f->s)));
2304 }
2305 
2306 void
2307 Keyring_putbytearray(void *fp)
2308 {
2309 	F_Keyring_putbytearray *f;
2310 	int n;
2311 
2312 	f = fp;
2313 	*f->ret = -1;
2314 	if(f->fd == H || f->a == H)
2315 		return;
2316 	n = f->n;
2317 	if(n < 0 || n > f->a->len)
2318 		error(exBounds);
2319 	*f->ret = putbuf(f->fd->fd, f->a->data, n);
2320 }
2321 
2322 void
2323 Keyring_dessetup(void *fp)
2324 {
2325 	F_Keyring_dessetup *f;
2326 	Heap *h;
2327 	XDESstate *ds;
2328 	uchar *ivec;
2329 	void *r;
2330 
2331 	f = fp;
2332 	r = *f->ret;
2333 	*f->ret = H;
2334 	destroy(r);
2335 
2336 	if(f->key == H || f->key->len < 8)
2337 		error(exBadKey);
2338 	if(f->ivec != H){
2339 		if(f->ivec->len < 8)
2340 			error(exBadIvec);
2341 		ivec = f->ivec->data;
2342 	}else
2343 		ivec = nil;
2344 
2345 	h = heap(TDESstate);
2346 	ds = H2D(XDESstate*, h);
2347 	setupDESstate(&ds->state, f->key->data, ivec);
2348 
2349 	*f->ret = (Keyring_DESstate*)ds;
2350 }
2351 
2352 void
2353 Keyring_desecb(void *fp)
2354 {
2355 	F_Keyring_desecb *f;
2356 	XDESstate *ds;
2357 	int i;
2358 	uchar *p;
2359 
2360 	f = fp;
2361 
2362 	if(f->buf == H)
2363 		return;
2364 	if(f->n < 0 || f->n > f->buf->len)
2365 		error(exBounds);
2366 	if(f->n & 7)
2367 		error(exBadBsize);
2368 
2369 	ds = checktype(f->state, TDESstate, exBadState, 0);
2370 	p = f->buf->data;
2371 
2372 	for(i = 8; i <= f->n; i += 8, p += 8)
2373 		block_cipher(ds->state.expanded, p, f->direction);
2374 }
2375 
2376 void
2377 Keyring_descbc(void *fp)
2378 {
2379 	F_Keyring_descbc *f;
2380 	XDESstate *ds;
2381 	uchar *p, *ep, *ip, *p2, *eip;
2382 	uchar tmp[8];
2383 
2384 	f = fp;
2385 
2386 	if(f->buf == H)
2387 		return;
2388 	if(f->n < 0 || f->n > f->buf->len)
2389 		error(exBounds);
2390 	if(f->n & 7)
2391 		error(exBadBsize);
2392 
2393 	ds = checktype(f->state, TDESstate, exBadState, 0);
2394 	p = f->buf->data;
2395 
2396 	if(f->direction == 0){
2397 		for(ep = p + f->n; p < ep; p += 8){
2398 			p2 = p;
2399 			ip = ds->state.ivec;
2400 			for(eip = ip+8; ip < eip; )
2401 				*p2++ ^= *ip++;
2402 			block_cipher(ds->state.expanded, p, 0);
2403 			memmove(ds->state.ivec, p, 8);
2404 		}
2405 	} else {
2406 		for(ep = p + f->n; p < ep; ){
2407 			memmove(tmp, p, 8);
2408 			block_cipher(ds->state.expanded, p, 1);
2409 			p2 = tmp;
2410 			ip = ds->state.ivec;
2411 			for(eip = ip+8; ip < eip; ){
2412 				*p++ ^= *ip;
2413 				*ip++ = *p2++;
2414 			}
2415 		}
2416 	}
2417 }
2418 
2419 void
2420 Keyring_ideasetup(void *fp)
2421 {
2422 	F_Keyring_ideasetup *f;
2423 	Heap *h;
2424 	XIDEAstate *is;
2425 	uchar *ivec;
2426 	void *r;
2427 
2428 	f = fp;
2429 	r = *f->ret;
2430 	*f->ret = H;
2431 	destroy(r);
2432 
2433 	if(f->key == H || f->key->len < 16)
2434 		error(exBadKey);
2435 	if(f->ivec != H){
2436 		if(f->ivec->len < 8)
2437 			error(exBadIvec);
2438 		ivec = f->ivec->data;
2439 	}else
2440 		ivec = nil;
2441 
2442 	h = heap(TIDEAstate);
2443 	is = H2D(XIDEAstate*, h);
2444 
2445 	setupIDEAstate(&is->state, f->key->data, ivec);
2446 
2447 	*f->ret = (Keyring_IDEAstate*)is;
2448 }
2449 
2450 void
2451 Keyring_ideaecb(void *fp)
2452 {
2453 	F_Keyring_ideaecb *f;
2454 	XIDEAstate *is;
2455 	int i;
2456 	uchar *p;
2457 
2458 	f = fp;
2459 
2460 	if(f->buf == H)
2461 		return;
2462 	if(f->n < 0 || f->n > f->buf->len)
2463 		error(exBounds);
2464 	if(f->n & 7)
2465 		error(exBadBsize);
2466 
2467 	is = checktype(f->state, TIDEAstate, exBadState, 0);
2468 	p = f->buf->data;
2469 
2470 	for(i = 8; i <= f->n; i += 8, p += 8)
2471 		idea_cipher(is->state.edkey, p, f->direction);
2472 }
2473 
2474 void
2475 Keyring_ideacbc(void *fp)
2476 {
2477 	F_Keyring_ideacbc *f;
2478 	XIDEAstate *is;
2479 	uchar *p, *ep, *ip, *p2, *eip;
2480 	uchar tmp[8];
2481 
2482 	f = fp;
2483 
2484 	if(f->buf == H)
2485 		return;
2486 	if(f->n < 0 || f->n > f->buf->len)
2487 		error(exBounds);
2488 	if(f->n & 7)
2489 		error(exBadBsize);
2490 
2491 	is = checktype(f->state, TIDEAstate, exBadState, 0);
2492 	p = f->buf->data;
2493 
2494 	if(f->direction == 0){
2495 		for(ep = p + f->n; p < ep; p += 8){
2496 			p2 = p;
2497 			ip = is->state.ivec;
2498 			for(eip = ip+8; ip < eip; )
2499 				*p2++ ^= *ip++;
2500 			idea_cipher(is->state.edkey, p, 0);
2501 			memmove(is->state.ivec, p, 8);
2502 		}
2503 	} else {
2504 		for(ep = p + f->n; p < ep; ){
2505 			memmove(tmp, p, 8);
2506 			idea_cipher(is->state.edkey, p, 1);
2507 			p2 = tmp;
2508 			ip = is->state.ivec;
2509 			for(eip = ip+8; ip < eip; ){
2510 				*p++ ^= *ip;
2511 				*ip++ = *p2++;
2512 			}
2513 		}
2514 	}
2515 }
2516 
2517 void
2518 Keyring_aessetup(void *fp)
2519 {
2520 	F_Keyring_aessetup *f;
2521 	Heap *h;
2522 	XAESstate *is;
2523 	uchar *ivec;
2524 	void *r;
2525 
2526 	f = fp;
2527 	r = *f->ret;
2528 	*f->ret = H;
2529 	destroy(r);
2530 
2531 	if(f->key == H ||
2532 	   f->key->len != 16 && f->key->len != 24 && f->key->len != 32)
2533 		error(exBadKey);
2534 	if(f->ivec != H){
2535 		if(f->ivec->len < AESbsize)
2536 			error(exBadIvec);
2537 		ivec = f->ivec->data;
2538 	}else
2539 		ivec = nil;
2540 
2541 	h = heap(TAESstate);
2542 	is = H2D(XAESstate*, h);
2543 
2544 	setupAESstate(&is->state, f->key->data, f->key->len, ivec);
2545 
2546 	*f->ret = (Keyring_AESstate*)is;
2547 }
2548 
2549 void
2550 Keyring_aescbc(void *fp)
2551 {
2552 	F_Keyring_aescbc *f;
2553 	XAESstate *is;
2554 	uchar *p;
2555 
2556 	f = fp;
2557 
2558 	if(f->buf == H)
2559 		return;
2560 	if(f->n < 0 || f->n > f->buf->len)
2561 		error(exBounds);
2562 
2563 	is = checktype(f->state, TAESstate, exBadState, 0);
2564 	p = f->buf->data;
2565 
2566 	if(f->direction == 0)
2567 		aesCBCencrypt(p, f->n, &is->state);
2568 	else
2569 		aesCBCdecrypt(p, f->n, &is->state);
2570 }
2571 
2572 void
2573 Keyring_blowfishsetup(void *fp)
2574 {
2575 	F_Keyring_blowfishsetup *f;
2576 	Heap *h;
2577 	XBFstate *is;
2578 	uchar *ivec;
2579 	void *r;
2580 
2581 	f = fp;
2582 	r = *f->ret;
2583 	*f->ret = H;
2584 	destroy(r);
2585 
2586 	if(f->key == H || f->key->len <= 0)
2587 		error(exBadKey);
2588 	if(f->ivec != H){
2589 		if(f->ivec->len != BFbsize)
2590 			error(exBadIvec);
2591 		ivec = f->ivec->data;
2592 	}else
2593 		ivec = nil;
2594 
2595 	h = heap(TBFstate);
2596 	is = H2D(XBFstate*, h);
2597 
2598 	setupBFstate(&is->state, f->key->data, f->key->len, ivec);
2599 
2600 	*f->ret = (Keyring_BFstate*)is;
2601 }
2602 
2603 void
2604 Keyring_blowfishcbc(void *fp)
2605 {
2606 	F_Keyring_blowfishcbc *f;
2607 	XBFstate *is;
2608 	uchar *p;
2609 
2610 	f = fp;
2611 
2612 	if(f->buf == H)
2613 		return;
2614 	if(f->n < 0 || f->n > f->buf->len)
2615 		error(exBounds);
2616 	if(f->n & 7)
2617 		error(exBadBsize);
2618 
2619 	is = checktype(f->state, TBFstate, exBadState, 0);
2620 	p = f->buf->data;
2621 
2622 	if(f->direction == 0)
2623 		bfCBCencrypt(p, f->n, &is->state);
2624 	else
2625 		bfCBCdecrypt(p, f->n, &is->state);
2626 }
2627 
2628 void
2629 Keyring_rc4setup(void *fp)
2630 {
2631 	F_Keyring_rc4setup *f;
2632 	Heap *h;
2633 	XRC4state *is;
2634 	void *r;
2635 
2636 	f = fp;
2637 	r = *f->ret;
2638 	*f->ret = H;
2639 	destroy(r);
2640 
2641 	if(f->seed == H)
2642 		return;
2643 
2644 	h = heap(TRC4state);
2645 	is = H2D(XRC4state*, h);
2646 
2647 	setupRC4state(&is->state, f->seed->data, f->seed->len);
2648 
2649 	*f->ret = (Keyring_RC4state*)is;
2650 }
2651 
2652 void
2653 Keyring_rc4(void *fp)
2654 {
2655 	F_Keyring_rc4 *f;
2656 	XRC4state *is;
2657 	uchar *p;
2658 
2659 	f = fp;
2660 	if(f->buf == H)
2661 		return;
2662 	if(f->n < 0 || f->n > f->buf->len)
2663 		error(exBounds);
2664 	is = checktype(f->state, TRC4state, exBadState, 0);
2665 	p = f->buf->data;
2666 	rc4(&is->state, p, f->n);
2667 }
2668 
2669 void
2670 Keyring_rc4skip(void *fp)
2671 {
2672 	F_Keyring_rc4skip *f;
2673 	XRC4state *is;
2674 
2675 	f = fp;
2676 	is = checktype(f->state, TRC4state, exBadState, 0);
2677 	rc4skip(&is->state, f->n);
2678 }
2679 
2680 void
2681 Keyring_rc4back(void *fp)
2682 {
2683 	F_Keyring_rc4back *f;
2684 	XRC4state *is;
2685 
2686 	f = fp;
2687 	is = checktype(f->state, TRC4state, exBadState, 0);
2688 	rc4back(&is->state, f->n);
2689 }
2690 
2691 /*
2692  *  public/secret keys, signing and verifying
2693  */
2694 
2695 static void
2696 dsapk2pub(DSApub* p, Keyring_DSApk* pk)
2697 {
2698 	if(pk == H)
2699 		error(exNilref);
2700 	p->p = checkIPint(pk->p);
2701 	p->q = checkIPint(pk->q);
2702 	p->alpha = checkIPint(pk->alpha);
2703 	p->key = checkIPint(pk->key);
2704 }
2705 
2706 static void
2707 dsask2priv(DSApriv* p, Keyring_DSAsk* sk)
2708 {
2709 	if(sk == H || sk->pk == H)
2710 		error(exNilref);
2711 	dsapk2pub(&p->pub, sk->pk);
2712 	p->secret = checkIPint(sk->secret);
2713 }
2714 
2715 static void
2716 dsapriv2sk(Keyring_DSAsk* sk, DSApriv* p)
2717 {
2718 	Keyring_DSApk* pk;
2719 
2720 	pk = sk->pk;
2721 	pk->p = ipcopymp(p->pub.p);
2722 	pk->q = ipcopymp(p->pub.q);
2723 	pk->alpha = ipcopymp(p->pub.alpha);
2724 	pk->key = ipcopymp(p->pub.key);
2725 	sk->secret = ipcopymp(p->secret);
2726 }
2727 
2728 void
2729 DSAsk_gen(void *fp)
2730 {
2731 	F_DSAsk_gen *f;
2732 	Keyring_DSAsk *sk;
2733 	DSApriv *p;
2734 	DSApub pub, *oldpk;
2735 	void *v;
2736 
2737 	f = fp;
2738 	v = *f->ret;
2739 	sk = newthing(TDSAsk, 0);
2740 	sk->pk = newthing(TDSApk, 0);
2741 	*f->ret = sk;
2742 	destroy(v);
2743 	oldpk = nil;
2744 	if(f->oldpk != H){
2745 		dsapk2pub(&pub, f->oldpk);
2746 		oldpk = &pub;
2747 	}
2748 	release();
2749 	p = dsagen(oldpk);
2750 	acquire();
2751 	dsapriv2sk(sk, p);
2752 	dsaprivfree(p);
2753 }
2754 
2755 void
2756 DSAsk_sign(void *fp)
2757 {
2758 	F_DSAsk_sign *f;
2759 	Keyring_DSAsig *sig;
2760 	DSApriv p;
2761 	mpint *m;
2762 	DSAsig *s;
2763 	void *v;
2764 
2765 	f = fp;
2766 	v = *f->ret;
2767 	sig = newthing(TDSAsig, 0);
2768 	*f->ret = sig;
2769 	destroy(v);
2770 
2771 	dsask2priv(&p, f->k);
2772 	m = checkIPint(f->m);
2773 	release();
2774 	s = dsasign(&p, m);
2775 	acquire();
2776 	sig->r = ipcopymp(s->r);
2777 	sig->s = ipcopymp(s->s);
2778 	dsasigfree(s);
2779 }
2780 
2781 void
2782 DSApk_verify(void *fp)
2783 {
2784 	F_DSApk_verify *f;
2785 	DSApub p;
2786 	DSAsig sig;
2787 	mpint *m;
2788 
2789 	f = fp;
2790 	*f->ret = 0;
2791 	if(f->m == H || f->sig == H)
2792 		return;
2793 	dsapk2pub(&p, f->k);
2794 	sig.r = checkIPint(f->sig->r);
2795 	sig.s = checkIPint(f->sig->s);
2796 	m = checkIPint(f->m);
2797 	release();
2798 	*f->ret = dsaverify(&p, &sig, m) == 0;
2799 	acquire();
2800 }
2801 
2802 static void
2803 egpk2pub(EGpub* p, Keyring_EGpk* pk)
2804 {
2805 	if(pk == H)
2806 		error(exNilref);
2807 	p->p = checkIPint(pk->p);
2808 	p->alpha = checkIPint(pk->alpha);
2809 	p->key = checkIPint(pk->key);
2810 }
2811 
2812 static void
2813 egsk2priv(EGpriv* p, Keyring_EGsk* sk)
2814 {
2815 	if(sk == H || sk->pk == H)
2816 		error(exNilref);
2817 	egpk2pub(&p->pub, sk->pk);
2818 	p->secret = checkIPint(sk->secret);
2819 }
2820 
2821 static void
2822 egpriv2sk(Keyring_EGsk* sk, EGpriv* p)
2823 {
2824 	Keyring_EGpk* pk;
2825 
2826 	pk = sk->pk;
2827 	pk->p = ipcopymp(p->pub.p);
2828 	pk->alpha = ipcopymp(p->pub.alpha);
2829 	pk->key = ipcopymp(p->pub.key);
2830 	sk->secret = ipcopymp(p->secret);
2831 }
2832 
2833 void
2834 EGsk_gen(void *fp)
2835 {
2836 	F_EGsk_gen *f;
2837 	Keyring_EGsk *sk;
2838 	EGpriv *p;
2839 	void *v;
2840 
2841 	f = fp;
2842 	v = *f->ret;
2843 	sk = newthing(TEGsk, 0);
2844 	sk->pk = newthing(TEGpk, 0);
2845 	*f->ret = sk;
2846 	destroy(v);
2847 	release();
2848 	for(;;){
2849 		p = eggen(f->nlen, f->nrep);
2850 		if(mpsignif(p->pub.p) == f->nlen)
2851 			break;
2852 		egprivfree(p);
2853 	}
2854 	acquire();
2855 	egpriv2sk(sk, p);
2856 	egprivfree(p);
2857 }
2858 
2859 void
2860 EGsk_sign(void *fp)
2861 {
2862 	F_EGsk_sign *f;
2863 	Keyring_EGsig *sig;
2864 	EGpriv p;
2865 	mpint *m;
2866 	EGsig *s;
2867 	void *v;
2868 
2869 	f = fp;
2870 	v = *f->ret;
2871 	sig = newthing(TEGsig, 0);
2872 	*f->ret = sig;
2873 	destroy(v);
2874 
2875 	egsk2priv(&p, f->k);
2876 	m = checkIPint(f->m);
2877 	release();
2878 	s = egsign(&p, m);
2879 	acquire();
2880 	sig->r = ipcopymp(s->r);
2881 	sig->s = ipcopymp(s->s);
2882 	egsigfree(s);
2883 }
2884 
2885 void
2886 EGpk_verify(void *fp)
2887 {
2888 	F_EGpk_verify *f;
2889 	EGpub p;
2890 	EGsig sig;
2891 	mpint *m;
2892 
2893 	f = fp;
2894 	*f->ret = 0;
2895 	if(f->m == H || f->sig == H)
2896 		return;
2897 	egpk2pub(&p, f->k);
2898 	sig.r = checkIPint(f->sig->r);
2899 	sig.s = checkIPint(f->sig->s);
2900 	m = checkIPint(f->m);
2901 	release();
2902 	*f->ret = egverify(&p, &sig, m) == 0;
2903 	acquire();
2904 }
2905 
2906 static void
2907 rsapk2pub(RSApub* p, Keyring_RSApk* pk)
2908 {
2909 	if(pk == H)
2910 		error(exNilref);
2911 	memset(p, 0, sizeof(*p));
2912 	p->n = checkIPint(pk->n);
2913 	p->ek = checkIPint(pk->ek);
2914 }
2915 
2916 static void
2917 rsask2priv(RSApriv* p, Keyring_RSAsk* sk)
2918 {
2919 	if(sk == H || sk->pk == H)
2920 		error(exNilref);
2921 	rsapk2pub(&p->pub, sk->pk);
2922 	p->dk = checkIPint(sk->dk);
2923 	p->p = checkIPint(sk->p);
2924 	p->q = checkIPint(sk->q);
2925 	p->kp = checkIPint(sk->kp);
2926 	p->kq = checkIPint(sk->kq);
2927 	p->c2 = checkIPint(sk->c2);
2928 }
2929 
2930 static void
2931 rsapriv2sk(Keyring_RSAsk* sk, RSApriv* p)
2932 {
2933 	Keyring_RSApk* pk;
2934 
2935 	pk = sk->pk;
2936 	pk->n = ipcopymp(p->pub.n);
2937 	pk->ek = ipcopymp(p->pub.ek);
2938 	sk->dk = ipcopymp(p->dk);
2939 	sk->p = ipcopymp(p->p);
2940 	sk->q = ipcopymp(p->q);
2941 	sk->kp = ipcopymp(p->kp);
2942 	sk->kq = ipcopymp(p->kq);
2943 	sk->c2 = ipcopymp(p->c2);
2944 }
2945 
2946 void
2947 RSApk_encrypt(void *fp)
2948 {
2949 	F_RSApk_encrypt *f;
2950 	RSApub p;
2951 	mpint *m, *o;
2952 	void *v;
2953 
2954 	f = fp;
2955 	v = *f->ret;
2956 	*f->ret = H;
2957 	destroy(v);
2958 
2959 	rsapk2pub(&p, f->k);
2960 	m = checkIPint(f->m);
2961 	release();
2962 	o = rsaencrypt(&p, m, nil);
2963 	acquire();
2964 	*f->ret = newIPint(o);
2965 }
2966 
2967 void
2968 RSAsk_gen(void *fp)
2969 {
2970 	F_RSAsk_gen *f;
2971 	Keyring_RSAsk *sk;
2972 	RSApriv *p;
2973 	void *v;
2974 
2975 	f = fp;
2976 	v = *f->ret;
2977 	sk = newthing(TRSAsk, 0);
2978 	sk->pk = newthing(TRSApk, 0);
2979 	*f->ret = sk;
2980 	destroy(v);
2981 	release();
2982 	for(;;){
2983 		p = rsagen(f->nlen, f->elen, f->nrep);
2984 		if(mpsignif(p->pub.n) == f->nlen)
2985 			break;
2986 		rsaprivfree(p);
2987 	}
2988 	acquire();
2989 	rsapriv2sk(sk, p);
2990 	rsaprivfree(p);
2991 }
2992 
2993 void
2994 RSAsk_fill(void *fp)
2995 {
2996 	F_RSAsk_fill *f;
2997 	Keyring_RSAsk *sk;
2998 	RSApriv *p;
2999 	void *v;
3000 
3001 	f = fp;
3002 	v = *f->ret;
3003 	sk = newthing(TRSAsk, 0);
3004 	sk->pk = newthing(TRSApk, 0);
3005 	*f->ret = sk;
3006 	destroy(v);
3007 	release();
3008 	p = rsafill(checkIPint(f->n), checkIPint(f->e), checkIPint(f->d),
3009 			checkIPint(f->p), checkIPint(f->q));
3010 	acquire();
3011 	if(p == nil) {
3012 		*f->ret = H;
3013 		destroy(sk);
3014 	}else{
3015 		rsapriv2sk(sk, p);
3016 		rsaprivfree(p);
3017 	}
3018 }
3019 
3020 void
3021 RSAsk_decrypt(void *fp)
3022 {
3023 	F_RSAsk_decrypt *f;
3024 	RSApriv p;
3025 	mpint *m, *o;
3026 	void *v;
3027 
3028 	f = fp;
3029 	v = *f->ret;
3030 	*f->ret = H;
3031 	destroy(v);
3032 
3033 	rsask2priv(&p, f->k);
3034 	m = checkIPint(f->m);
3035 	release();
3036 	o = rsadecrypt(&p, m, nil);
3037 	acquire();
3038 	*f->ret = newIPint(o);
3039 }
3040 
3041 void
3042 RSAsk_sign(void *fp)
3043 {
3044 	F_RSAsk_sign *f;
3045 	Keyring_RSAsig *sig;
3046 	RSApriv p;
3047 	mpint *m, *s;
3048 	void *v;
3049 
3050 	f = fp;
3051 	v = *f->ret;
3052 	sig = newthing(TRSAsig, 0);
3053 	*f->ret = sig;
3054 	destroy(v);
3055 
3056 	rsask2priv(&p, f->k);
3057 	m = checkIPint(f->m);
3058 	release();
3059 	s = rsadecrypt(&p, m, nil);
3060 	acquire();
3061 	sig->n = newIPint(s);
3062 }
3063 
3064 void
3065 RSApk_verify(void *fp)
3066 {
3067 	F_RSApk_verify *f;
3068 	RSApub p;
3069 	mpint *sig, *m, *t;
3070 
3071 	f = fp;
3072 	*f->ret = 0;
3073 	if(f->m == H || f->sig == H)
3074 		return;
3075 	rsapk2pub(&p, f->k);
3076 	sig = checkIPint(f->sig->n);
3077 	m = checkIPint(f->m);
3078 	release();
3079 	t = rsaencrypt(&p, sig, nil);
3080 	*f->ret = mpcmp(t, m) == 0;
3081 	mpfree(t);
3082 	acquire();
3083 }
3084