1 #include "std.h"
2 #include "dat.h"
3 
4 /*
5  * DSA signing and verification
6  *
7  * Sign:
8  *	start p=xxx q=xxx alpha=xxx key=xxx
9  *	write msg
10  *	read signature(msg)
11  *
12  * Verify: (not implemented)
13  *	start p=xxx q=xxx alpha=xxx key=xxx
14  *	write msg
15  *	write signature(msg)
16  *	read ok or fail
17  *
18  * all numbers are hexadecimal bigints parsable with strtomp.
19  */
20 
21 static int
xdsasign(Conv * c)22 xdsasign(Conv *c)
23 {
24 	int n;
25 	mpint *m;
26 	uchar digest[SHA1dlen], sigblob[20+20];
27 	DSAsig *sig;
28 	Key *k;
29 
30 	k = keylookup("%A", c->attr);
31 	if(k == nil)
32 		return -1;
33 
34 	c->state = "read data";
35 	if((n=convread(c, digest, SHA1dlen)) < 0){
36 		keyclose(k);
37 		return -1;
38 	}
39 	m = betomp(digest, SHA1dlen, nil);
40 	if(m == nil){
41 		keyclose(k);
42 		return -1;
43 	}
44 	sig = dsasign(k->priv, m);
45 	keyclose(k);
46 	mpfree(m);
47 	if(sig == nil)
48 		return -1;
49 	if(mpsignif(sig->r) > 20*8 || mpsignif(sig->s) > 20*8){
50 		werrstr("signature too long");
51 		return -1;
52 	}
53 	mptoberjust(sig->r, sigblob, 20);
54 	mptoberjust(sig->s, sigblob+20, 20);
55 	convwrite(c, sigblob, sizeof sigblob);
56 	dsasigfree(sig);
57 	return 0;
58 }
59 
60 /*
61  * convert to canonical form (lower case)
62  * for use in attribute matches.
63  */
64 static void
strlwr(char * a)65 strlwr(char *a)
66 {
67 	for(; *a; a++){
68 		if('A' <= *a && *a <= 'Z')
69 			*a += 'a' - 'A';
70 	}
71 }
72 
73 static DSApriv*
readdsapriv(Key * k)74 readdsapriv(Key *k)
75 {
76 	char *a;
77 	DSApriv *priv;
78 
79 	priv = dsaprivalloc();
80 
81 	if((a=strfindattr(k->attr, "p"))==nil
82 	|| (priv->pub.p=strtomp(a, nil, 16, nil))==nil)
83 		goto Error;
84 	strlwr(a);
85 	if((a=strfindattr(k->attr, "q"))==nil
86 	|| (priv->pub.q=strtomp(a, nil, 16, nil))==nil)
87 		goto Error;
88 	strlwr(a);
89 	if(!probably_prime(priv->pub.p, 20) && !probably_prime(priv->pub.q, 20)) {
90 		werrstr("dsa: p or q not prime");
91 		goto Error;
92 	}
93 	if((a=strfindattr(k->attr, "alpha"))==nil
94 	|| (priv->pub.alpha=strtomp(a, nil, 16, nil))==nil)
95 		goto Error;
96 	strlwr(a);
97 	if((a=strfindattr(k->attr, "key"))==nil
98 	|| (priv->pub.key=strtomp(a, nil, 16, nil))==nil)
99 		goto Error;
100 	strlwr(a);
101 	if((a=strfindattr(k->privattr, "!secret"))==nil
102 	|| (priv->secret=strtomp(a, nil, 16, nil))==nil)
103 		goto Error;
104 	strlwr(a);
105 	return priv;
106 
107 Error:
108 	dsaprivfree(priv);
109 	return nil;
110 }
111 
112 static int
dsacheck(Key * k)113 dsacheck(Key *k)
114 {
115 	static int first = 1;
116 
117 	if(first){
118 		fmtinstall('B', mpfmt);
119 		first = 0;
120 	}
121 
122 	if((k->priv = readdsapriv(k)) == nil){
123 		werrstr("malformed key data");
124 		return -1;
125 	}
126 	return 0;
127 }
128 
129 static void
dsaclose(Key * k)130 dsaclose(Key *k)
131 {
132 	dsaprivfree(k->priv);
133 	k->priv = nil;
134 }
135 
136 static Role
137 dsaroles[] =
138 {
139 	"sign",	xdsasign,
140 	0
141 };
142 
143 Proto dsa = {
144 	"dsa",
145 	dsaroles,
146 	nil,
147 	dsacheck,
148 	dsaclose
149 };
150