4 * Old ssh client protocol:
6 * if you don't like it, read another, repeat
10 * all numbers are hexadecimal biginits parsable with strtomp.
12 * Sign (PKCS #1 using hash=sha1 or hash=md5)
14 * read signature(hash(msg))
18 * write signature(hash(msg))
35 static char *phasenames[] = {
36 [CHavePub] "CHavePub",
37 [CHaveResp] "CHaveResp",
38 [VNeedHash] "VNeedHash",
39 [VNeedSig] "VNeedSig",
40 [VHaveResp] "VHaveResp",
41 [SNeedHash] "SNeedHash",
42 [SHaveResp] "SHaveResp",
55 static mpint* mkdigest(RSApub *key, char *hashalg, uchar *hash, uint dlen);
63 priv = rsaprivalloc();
65 if((a=_strfindattr(k->attr, "ek"))==nil || (priv->pub.ek=strtomp(a, nil, 16, nil))==nil)
67 if((a=_strfindattr(k->attr, "n"))==nil || (priv->pub.n=strtomp(a, nil, 16, nil))==nil)
69 if(k->privattr == nil) /* only public half */
71 if((a=_strfindattr(k->privattr, "!p"))==nil || (priv->p=strtomp(a, nil, 16, nil))==nil)
73 if((a=_strfindattr(k->privattr, "!q"))==nil || (priv->q=strtomp(a, nil, 16, nil))==nil)
75 if((a=_strfindattr(k->privattr, "!kp"))==nil || (priv->kp=strtomp(a, nil, 16, nil))==nil)
77 if((a=_strfindattr(k->privattr, "!kq"))==nil || (priv->kq=strtomp(a, nil, 16, nil))==nil)
79 if((a=_strfindattr(k->privattr, "!c2"))==nil || (priv->c2=strtomp(a, nil, 16, nil))==nil)
81 if((a=_strfindattr(k->privattr, "!dk"))==nil || (priv->dk=strtomp(a, nil, 16, nil))==nil)
91 rsainit(Proto*, Fsstate *fss)
97 if((role = _strfindattr(fss->attr, "role")) == nil)
98 return failure(fss, "rsa role not specified");
99 if(strcmp(role, "client") == 0)
100 fss->phase = CHavePub;
101 else if(strcmp(role, "sign") == 0)
102 fss->phase = SNeedHash;
103 else if(strcmp(role, "verify") == 0)
104 fss->phase = VNeedHash;
106 return failure(fss, "rsa role %s unimplemented", role);
108 s = emalloc(sizeof *s);
109 fss->phasename = phasenames;
110 fss->maxphase = Maxphase;
116 mkkeyinfo(&ki, fss, nil);
117 if(findkey(&s->key, &ki, nil) != RpcOk)
118 return failure(fss, nil);
119 /* signing needs private key */
120 if(fss->phase == SNeedHash && s->key->privattr == nil)
122 "missing private half of key -- cannot sign");
128 rsaread(Fsstate *fss, void *va, uint *n)
139 return phaseerror(fss, "read");
145 mkkeyinfo(&ki, fss, nil);
148 if(findkey(&s->key, &ki, nil) != RpcOk)
149 return failure(fss, nil);
152 *n = snprint(va, *n, "%B %B", priv->pub.n, priv->pub.ek);
155 *n = snprint(va, *n, "%B", s->resp);
156 fss->phase = Established;
160 len = (mpsignif(priv->pub.n)+7)/8;
162 return failure(fss, "signature buffer too short");
164 m = rsadecrypt(priv, s->digest, nil);
165 mptober(m, (uchar*)va, len);
167 fss->phase = Established;
170 *n = snprint(va, *n, "%s", s->sigresp == 0? "ok":
171 "signature does not verify");
172 fss->phase = Established;
178 rsawrite(Fsstate *fss, void *va, uint n)
189 return phaseerror(fss, "write");
192 return failure(fss, "no current key");
193 switch(canusekey(fss, s->key)){
197 return failure(fss, "confirmation denied");
201 m = strtomp(va, nil, 16, nil);
203 return failure(fss, "invalid challenge value");
204 m = rsadecrypt(s->key->priv, m, m);
206 fss->phase = CHaveResp;
210 /* get hash type from key */
211 hash = _strfindattr(s->key->attr, "hash");
214 if(strcmp(hash, "sha1") == 0)
216 else if(strcmp(hash, "md5") == 0)
218 else if(strcmp(hash, "sha256") == 0)
221 return failure(fss, "unknown hash function %s", hash);
223 return failure(fss, "hash length %d should be %d",
226 s->digest = mkdigest(&priv->pub, hash, (uchar *)va, n);
228 return failure(fss, nil);
229 if(fss->phase == VNeedHash)
230 fss->phase = VNeedSig;
232 fss->phase = SHaveResp;
236 m = betomp((uchar*)va, n, nil);
237 mm = rsaencrypt(&priv->pub, m, nil);
238 s->sigresp = mpcmp(s->digest, mm);
241 fss->phase = VHaveResp;
247 rsaclose(Fsstate *fss)
262 rsaaddkey(Key *k, int before)
264 fmtinstall('B', mpfmt);
266 if((k->priv = readrsapriv(k)) == nil){
267 werrstr("malformed key data");
270 return replacekey(k, before);
276 rsaprivfree(k->priv);
286 .closekey= rsaclosekey,
290 * Simple ASN.1 encodings.
291 * Lengths < 128 are encoded as 1-bytes constants,
292 * making our life easy.
298 * SHA1 = 1.3.14.3.2.26
299 * MDx = 1.2.840.113549.2.x
300 * SHA256 = 2.16.840.1.101.3.4.2.1
302 #define O0(a,b) ((a)*40+(b))
304 (((x)>> 7)&0x7F)|0x80, \
307 (((x)>>14)&0x7F)|0x80, \
308 (((x)>> 7)&0x7F)|0x80, \
310 uchar oidsha1[] = { O0(1, 3), 14, 3, 2, 26 };
311 uchar oidmd5[] = { O0(1, 2), O2(840), O3(113549), 2, 5 };
312 uchar oidsha256[] = { O0(2, 16), O2(840), 1, 101, 3, 4, 2, 1 };
314 * DigestInfo ::= SEQUENCE {
315 * digestAlgorithm AlgorithmIdentifier,
316 * digest OCTET STRING
319 * except that OpenSSL seems to sign
321 * DigestInfo ::= SEQUENCE {
322 * SEQUENCE{ digestAlgorithm AlgorithmIdentifier, NULL }
323 * digest OCTET STRING
329 mkasn1(uchar *asn1, char *alg, uchar *d, uint dlen)
334 if(strcmp(alg, "sha1") == 0){
336 olen = sizeof(oidsha1);
337 }else if(strcmp(alg, "md5") == 0){
339 olen = sizeof(oidmd5);
340 }else if(strcmp(alg, "sha256") == 0){
342 olen = sizeof(oidsha256);
344 sysfatal("bad alg in mkasn1");
349 *p++ = 0x30; /* sequence */
352 *p++ = 0x30; /* another sequence */
355 *p++ = 0x06; /* object id */
357 memmove(p, obj, olen);
360 *p++ = 0x05; /* null */
363 asn1[3] = p - (asn1+4); /* end of inner sequence */
365 *p++ = 0x04; /* octet string */
370 asn1[1] = p - (asn1+2); /* end of outer sequence */
375 mkdigest(RSApub *key, char *hashalg, uchar *hash, uint dlen)
378 uchar asn1[512], *buf;
384 n = mkasn1(asn1, hashalg, hash, dlen);
389 len = (mpsignif(key->n)+7)/8 - 1;
391 werrstr("rsa key too short");
397 memset(buf+1, 0xFF, pad);
399 memmove(buf+1+pad+1, asn1, n);
400 m = betomp(buf, len, nil);