OSDN Git Service

Add LogList To GitBlame
[tortoisegit/TortoiseGitJp.git] / src / TortoisePlink / SSHRSA.C
1 /*\r
2  * RSA implementation for PuTTY.\r
3  */\r
4 \r
5 #include <stdio.h>\r
6 #include <stdlib.h>\r
7 #include <string.h>\r
8 #include <assert.h>\r
9 \r
10 #include "ssh.h"\r
11 #include "misc.h"\r
12 \r
13 int makekey(unsigned char *data, int len, struct RSAKey *result,\r
14             unsigned char **keystr, int order)\r
15 {\r
16     unsigned char *p = data;\r
17     int i, n;\r
18 \r
19     if (len < 4)\r
20         return -1;\r
21 \r
22     if (result) {\r
23         result->bits = 0;\r
24         for (i = 0; i < 4; i++)\r
25             result->bits = (result->bits << 8) + *p++;\r
26     } else\r
27         p += 4;\r
28 \r
29     len -= 4;\r
30 \r
31     /*\r
32      * order=0 means exponent then modulus (the keys sent by the\r
33      * server). order=1 means modulus then exponent (the keys\r
34      * stored in a keyfile).\r
35      */\r
36 \r
37     if (order == 0) {\r
38         n = ssh1_read_bignum(p, len, result ? &result->exponent : NULL);\r
39         if (n < 0) return -1;\r
40         p += n;\r
41         len -= n;\r
42     }\r
43 \r
44     n = ssh1_read_bignum(p, len, result ? &result->modulus : NULL);\r
45     if (n < 0 || (result && bignum_bitcount(result->modulus) == 0)) return -1;\r
46     if (result)\r
47         result->bytes = n - 2;\r
48     if (keystr)\r
49         *keystr = p + 2;\r
50     p += n;\r
51     len -= n;\r
52 \r
53     if (order == 1) {\r
54         n = ssh1_read_bignum(p, len, result ? &result->exponent : NULL);\r
55         if (n < 0) return -1;\r
56         p += n;\r
57         len -= n;\r
58     }\r
59     return p - data;\r
60 }\r
61 \r
62 int makeprivate(unsigned char *data, int len, struct RSAKey *result)\r
63 {\r
64     return ssh1_read_bignum(data, len, &result->private_exponent);\r
65 }\r
66 \r
67 int rsaencrypt(unsigned char *data, int length, struct RSAKey *key)\r
68 {\r
69     Bignum b1, b2;\r
70     int i;\r
71     unsigned char *p;\r
72 \r
73     if (key->bytes < length + 4)\r
74         return 0;                      /* RSA key too short! */\r
75 \r
76     memmove(data + key->bytes - length, data, length);\r
77     data[0] = 0;\r
78     data[1] = 2;\r
79 \r
80     for (i = 2; i < key->bytes - length - 1; i++) {\r
81         do {\r
82             data[i] = random_byte();\r
83         } while (data[i] == 0);\r
84     }\r
85     data[key->bytes - length - 1] = 0;\r
86 \r
87     b1 = bignum_from_bytes(data, key->bytes);\r
88 \r
89     b2 = modpow(b1, key->exponent, key->modulus);\r
90 \r
91     p = data;\r
92     for (i = key->bytes; i--;) {\r
93         *p++ = bignum_byte(b2, i);\r
94     }\r
95 \r
96     freebn(b1);\r
97     freebn(b2);\r
98 \r
99     return 1;\r
100 }\r
101 \r
102 static void sha512_mpint(SHA512_State * s, Bignum b)\r
103 {\r
104     unsigned char lenbuf[4];\r
105     int len;\r
106     len = (bignum_bitcount(b) + 8) / 8;\r
107     PUT_32BIT(lenbuf, len);\r
108     SHA512_Bytes(s, lenbuf, 4);\r
109     while (len-- > 0) {\r
110         lenbuf[0] = bignum_byte(b, len);\r
111         SHA512_Bytes(s, lenbuf, 1);\r
112     }\r
113     memset(lenbuf, 0, sizeof(lenbuf));\r
114 }\r
115 \r
116 /*\r
117  * This function is a wrapper on modpow(). It has the same effect\r
118  * as modpow(), but employs RSA blinding to protect against timing\r
119  * attacks.\r
120  */\r
121 static Bignum rsa_privkey_op(Bignum input, struct RSAKey *key)\r
122 {\r
123     Bignum random, random_encrypted, random_inverse;\r
124     Bignum input_blinded, ret_blinded;\r
125     Bignum ret;\r
126 \r
127     SHA512_State ss;\r
128     unsigned char digest512[64];\r
129     int digestused = lenof(digest512);\r
130     int hashseq = 0;\r
131 \r
132     /*\r
133      * Start by inventing a random number chosen uniformly from the\r
134      * range 2..modulus-1. (We do this by preparing a random number\r
135      * of the right length and retrying if it's greater than the\r
136      * modulus, to prevent any potential Bleichenbacher-like\r
137      * attacks making use of the uneven distribution within the\r
138      * range that would arise from just reducing our number mod n.\r
139      * There are timing implications to the potential retries, of\r
140      * course, but all they tell you is the modulus, which you\r
141      * already knew.)\r
142      * \r
143      * To preserve determinism and avoid Pageant needing to share\r
144      * the random number pool, we actually generate this `random'\r
145      * number by hashing stuff with the private key.\r
146      */\r
147     while (1) {\r
148         int bits, byte, bitsleft, v;\r
149         random = copybn(key->modulus);\r
150         /*\r
151          * Find the topmost set bit. (This function will return its\r
152          * index plus one.) Then we'll set all bits from that one\r
153          * downwards randomly.\r
154          */\r
155         bits = bignum_bitcount(random);\r
156         byte = 0;\r
157         bitsleft = 0;\r
158         while (bits--) {\r
159             if (bitsleft <= 0) {\r
160                 bitsleft = 8;\r
161                 /*\r
162                  * Conceptually the following few lines are equivalent to\r
163                  *    byte = random_byte();\r
164                  */\r
165                 if (digestused >= lenof(digest512)) {\r
166                     unsigned char seqbuf[4];\r
167                     PUT_32BIT(seqbuf, hashseq);\r
168                     SHA512_Init(&ss);\r
169                     SHA512_Bytes(&ss, "RSA deterministic blinding", 26);\r
170                     SHA512_Bytes(&ss, seqbuf, sizeof(seqbuf));\r
171                     sha512_mpint(&ss, key->private_exponent);\r
172                     SHA512_Final(&ss, digest512);\r
173                     hashseq++;\r
174 \r
175                     /*\r
176                      * Now hash that digest plus the signature\r
177                      * input.\r
178                      */\r
179                     SHA512_Init(&ss);\r
180                     SHA512_Bytes(&ss, digest512, sizeof(digest512));\r
181                     sha512_mpint(&ss, input);\r
182                     SHA512_Final(&ss, digest512);\r
183 \r
184                     digestused = 0;\r
185                 }\r
186                 byte = digest512[digestused++];\r
187             }\r
188             v = byte & 1;\r
189             byte >>= 1;\r
190             bitsleft--;\r
191             bignum_set_bit(random, bits, v);\r
192         }\r
193 \r
194         /*\r
195          * Now check that this number is strictly greater than\r
196          * zero, and strictly less than modulus.\r
197          */\r
198         if (bignum_cmp(random, Zero) <= 0 ||\r
199             bignum_cmp(random, key->modulus) >= 0) {\r
200             freebn(random);\r
201             continue;\r
202         } else {\r
203             break;\r
204         }\r
205     }\r
206 \r
207     /*\r
208      * RSA blinding relies on the fact that (xy)^d mod n is equal\r
209      * to (x^d mod n) * (y^d mod n) mod n. We invent a random pair\r
210      * y and y^d; then we multiply x by y, raise to the power d mod\r
211      * n as usual, and divide by y^d to recover x^d. Thus an\r
212      * attacker can't correlate the timing of the modpow with the\r
213      * input, because they don't know anything about the number\r
214      * that was input to the actual modpow.\r
215      * \r
216      * The clever bit is that we don't have to do a huge modpow to\r
217      * get y and y^d; we will use the number we just invented as\r
218      * _y^d_, and use the _public_ exponent to compute (y^d)^e = y\r
219      * from it, which is much faster to do.\r
220      */\r
221     random_encrypted = modpow(random, key->exponent, key->modulus);\r
222     random_inverse = modinv(random, key->modulus);\r
223     input_blinded = modmul(input, random_encrypted, key->modulus);\r
224     ret_blinded = modpow(input_blinded, key->private_exponent, key->modulus);\r
225     ret = modmul(ret_blinded, random_inverse, key->modulus);\r
226 \r
227     freebn(ret_blinded);\r
228     freebn(input_blinded);\r
229     freebn(random_inverse);\r
230     freebn(random_encrypted);\r
231     freebn(random);\r
232 \r
233     return ret;\r
234 }\r
235 \r
236 Bignum rsadecrypt(Bignum input, struct RSAKey *key)\r
237 {\r
238     return rsa_privkey_op(input, key);\r
239 }\r
240 \r
241 int rsastr_len(struct RSAKey *key)\r
242 {\r
243     Bignum md, ex;\r
244     int mdlen, exlen;\r
245 \r
246     md = key->modulus;\r
247     ex = key->exponent;\r
248     mdlen = (bignum_bitcount(md) + 15) / 16;\r
249     exlen = (bignum_bitcount(ex) + 15) / 16;\r
250     return 4 * (mdlen + exlen) + 20;\r
251 }\r
252 \r
253 void rsastr_fmt(char *str, struct RSAKey *key)\r
254 {\r
255     Bignum md, ex;\r
256     int len = 0, i, nibbles;\r
257     static const char hex[] = "0123456789abcdef";\r
258 \r
259     md = key->modulus;\r
260     ex = key->exponent;\r
261 \r
262     len += sprintf(str + len, "0x");\r
263 \r
264     nibbles = (3 + bignum_bitcount(ex)) / 4;\r
265     if (nibbles < 1)\r
266         nibbles = 1;\r
267     for (i = nibbles; i--;)\r
268         str[len++] = hex[(bignum_byte(ex, i / 2) >> (4 * (i % 2))) & 0xF];\r
269 \r
270     len += sprintf(str + len, ",0x");\r
271 \r
272     nibbles = (3 + bignum_bitcount(md)) / 4;\r
273     if (nibbles < 1)\r
274         nibbles = 1;\r
275     for (i = nibbles; i--;)\r
276         str[len++] = hex[(bignum_byte(md, i / 2) >> (4 * (i % 2))) & 0xF];\r
277 \r
278     str[len] = '\0';\r
279 }\r
280 \r
281 /*\r
282  * Generate a fingerprint string for the key. Compatible with the\r
283  * OpenSSH fingerprint code.\r
284  */\r
285 void rsa_fingerprint(char *str, int len, struct RSAKey *key)\r
286 {\r
287     struct MD5Context md5c;\r
288     unsigned char digest[16];\r
289     char buffer[16 * 3 + 40];\r
290     int numlen, slen, i;\r
291 \r
292     MD5Init(&md5c);\r
293     numlen = ssh1_bignum_length(key->modulus) - 2;\r
294     for (i = numlen; i--;) {\r
295         unsigned char c = bignum_byte(key->modulus, i);\r
296         MD5Update(&md5c, &c, 1);\r
297     }\r
298     numlen = ssh1_bignum_length(key->exponent) - 2;\r
299     for (i = numlen; i--;) {\r
300         unsigned char c = bignum_byte(key->exponent, i);\r
301         MD5Update(&md5c, &c, 1);\r
302     }\r
303     MD5Final(digest, &md5c);\r
304 \r
305     sprintf(buffer, "%d ", bignum_bitcount(key->modulus));\r
306     for (i = 0; i < 16; i++)\r
307         sprintf(buffer + strlen(buffer), "%s%02x", i ? ":" : "",\r
308                 digest[i]);\r
309     strncpy(str, buffer, len);\r
310     str[len - 1] = '\0';\r
311     slen = strlen(str);\r
312     if (key->comment && slen < len - 1) {\r
313         str[slen] = ' ';\r
314         strncpy(str + slen + 1, key->comment, len - slen - 1);\r
315         str[len - 1] = '\0';\r
316     }\r
317 }\r
318 \r
319 /*\r
320  * Verify that the public data in an RSA key matches the private\r
321  * data. We also check the private data itself: we ensure that p >\r
322  * q and that iqmp really is the inverse of q mod p.\r
323  */\r
324 int rsa_verify(struct RSAKey *key)\r
325 {\r
326     Bignum n, ed, pm1, qm1;\r
327     int cmp;\r
328 \r
329     /* n must equal pq. */\r
330     n = bigmul(key->p, key->q);\r
331     cmp = bignum_cmp(n, key->modulus);\r
332     freebn(n);\r
333     if (cmp != 0)\r
334         return 0;\r
335 \r
336     /* e * d must be congruent to 1, modulo (p-1) and modulo (q-1). */\r
337     pm1 = copybn(key->p);\r
338     decbn(pm1);\r
339     ed = modmul(key->exponent, key->private_exponent, pm1);\r
340     cmp = bignum_cmp(ed, One);\r
341     sfree(ed);\r
342     if (cmp != 0)\r
343         return 0;\r
344 \r
345     qm1 = copybn(key->q);\r
346     decbn(qm1);\r
347     ed = modmul(key->exponent, key->private_exponent, qm1);\r
348     cmp = bignum_cmp(ed, One);\r
349     sfree(ed);\r
350     if (cmp != 0)\r
351         return 0;\r
352 \r
353     /*\r
354      * Ensure p > q.\r
355      */\r
356     if (bignum_cmp(key->p, key->q) <= 0)\r
357         return 0;\r
358 \r
359     /*\r
360      * Ensure iqmp * q is congruent to 1, modulo p.\r
361      */\r
362     n = modmul(key->iqmp, key->q, key->p);\r
363     cmp = bignum_cmp(n, One);\r
364     sfree(n);\r
365     if (cmp != 0)\r
366         return 0;\r
367 \r
368     return 1;\r
369 }\r
370 \r
371 /* Public key blob as used by Pageant: exponent before modulus. */\r
372 unsigned char *rsa_public_blob(struct RSAKey *key, int *len)\r
373 {\r
374     int length, pos;\r
375     unsigned char *ret;\r
376 \r
377     length = (ssh1_bignum_length(key->modulus) +\r
378               ssh1_bignum_length(key->exponent) + 4);\r
379     ret = snewn(length, unsigned char);\r
380 \r
381     PUT_32BIT(ret, bignum_bitcount(key->modulus));\r
382     pos = 4;\r
383     pos += ssh1_write_bignum(ret + pos, key->exponent);\r
384     pos += ssh1_write_bignum(ret + pos, key->modulus);\r
385 \r
386     *len = length;\r
387     return ret;\r
388 }\r
389 \r
390 /* Given a public blob, determine its length. */\r
391 int rsa_public_blob_len(void *data, int maxlen)\r
392 {\r
393     unsigned char *p = (unsigned char *)data;\r
394     int n;\r
395 \r
396     if (maxlen < 4)\r
397         return -1;\r
398     p += 4;                            /* length word */\r
399     maxlen -= 4;\r
400 \r
401     n = ssh1_read_bignum(p, maxlen, NULL);    /* exponent */\r
402     if (n < 0)\r
403         return -1;\r
404     p += n;\r
405 \r
406     n = ssh1_read_bignum(p, maxlen, NULL);    /* modulus */\r
407     if (n < 0)\r
408         return -1;\r
409     p += n;\r
410 \r
411     return p - (unsigned char *)data;\r
412 }\r
413 \r
414 void freersakey(struct RSAKey *key)\r
415 {\r
416     if (key->modulus)\r
417         freebn(key->modulus);\r
418     if (key->exponent)\r
419         freebn(key->exponent);\r
420     if (key->private_exponent)\r
421         freebn(key->private_exponent);\r
422     if (key->comment)\r
423         sfree(key->comment);\r
424 }\r
425 \r
426 /* ----------------------------------------------------------------------\r
427  * Implementation of the ssh-rsa signing key type. \r
428  */\r
429 \r
430 static void getstring(char **data, int *datalen, char **p, int *length)\r
431 {\r
432     *p = NULL;\r
433     if (*datalen < 4)\r
434         return;\r
435     *length = GET_32BIT(*data);\r
436     *datalen -= 4;\r
437     *data += 4;\r
438     if (*datalen < *length)\r
439         return;\r
440     *p = *data;\r
441     *data += *length;\r
442     *datalen -= *length;\r
443 }\r
444 static Bignum getmp(char **data, int *datalen)\r
445 {\r
446     char *p;\r
447     int length;\r
448     Bignum b;\r
449 \r
450     getstring(data, datalen, &p, &length);\r
451     if (!p)\r
452         return NULL;\r
453     b = bignum_from_bytes((unsigned char *)p, length);\r
454     return b;\r
455 }\r
456 \r
457 static void *rsa2_newkey(char *data, int len)\r
458 {\r
459     char *p;\r
460     int slen;\r
461     struct RSAKey *rsa;\r
462 \r
463     rsa = snew(struct RSAKey);\r
464     if (!rsa)\r
465         return NULL;\r
466     getstring(&data, &len, &p, &slen);\r
467 \r
468     if (!p || slen != 7 || memcmp(p, "ssh-rsa", 7)) {\r
469         sfree(rsa);\r
470         return NULL;\r
471     }\r
472     rsa->exponent = getmp(&data, &len);\r
473     rsa->modulus = getmp(&data, &len);\r
474     rsa->private_exponent = NULL;\r
475     rsa->comment = NULL;\r
476 \r
477     return rsa;\r
478 }\r
479 \r
480 static void rsa2_freekey(void *key)\r
481 {\r
482     struct RSAKey *rsa = (struct RSAKey *) key;\r
483     freersakey(rsa);\r
484     sfree(rsa);\r
485 }\r
486 \r
487 static char *rsa2_fmtkey(void *key)\r
488 {\r
489     struct RSAKey *rsa = (struct RSAKey *) key;\r
490     char *p;\r
491     int len;\r
492 \r
493     len = rsastr_len(rsa);\r
494     p = snewn(len, char);\r
495     rsastr_fmt(p, rsa);\r
496     return p;\r
497 }\r
498 \r
499 static unsigned char *rsa2_public_blob(void *key, int *len)\r
500 {\r
501     struct RSAKey *rsa = (struct RSAKey *) key;\r
502     int elen, mlen, bloblen;\r
503     int i;\r
504     unsigned char *blob, *p;\r
505 \r
506     elen = (bignum_bitcount(rsa->exponent) + 8) / 8;\r
507     mlen = (bignum_bitcount(rsa->modulus) + 8) / 8;\r
508 \r
509     /*\r
510      * string "ssh-rsa", mpint exp, mpint mod. Total 19+elen+mlen.\r
511      * (three length fields, 12+7=19).\r
512      */\r
513     bloblen = 19 + elen + mlen;\r
514     blob = snewn(bloblen, unsigned char);\r
515     p = blob;\r
516     PUT_32BIT(p, 7);\r
517     p += 4;\r
518     memcpy(p, "ssh-rsa", 7);\r
519     p += 7;\r
520     PUT_32BIT(p, elen);\r
521     p += 4;\r
522     for (i = elen; i--;)\r
523         *p++ = bignum_byte(rsa->exponent, i);\r
524     PUT_32BIT(p, mlen);\r
525     p += 4;\r
526     for (i = mlen; i--;)\r
527         *p++ = bignum_byte(rsa->modulus, i);\r
528     assert(p == blob + bloblen);\r
529     *len = bloblen;\r
530     return blob;\r
531 }\r
532 \r
533 static unsigned char *rsa2_private_blob(void *key, int *len)\r
534 {\r
535     struct RSAKey *rsa = (struct RSAKey *) key;\r
536     int dlen, plen, qlen, ulen, bloblen;\r
537     int i;\r
538     unsigned char *blob, *p;\r
539 \r
540     dlen = (bignum_bitcount(rsa->private_exponent) + 8) / 8;\r
541     plen = (bignum_bitcount(rsa->p) + 8) / 8;\r
542     qlen = (bignum_bitcount(rsa->q) + 8) / 8;\r
543     ulen = (bignum_bitcount(rsa->iqmp) + 8) / 8;\r
544 \r
545     /*\r
546      * mpint private_exp, mpint p, mpint q, mpint iqmp. Total 16 +\r
547      * sum of lengths.\r
548      */\r
549     bloblen = 16 + dlen + plen + qlen + ulen;\r
550     blob = snewn(bloblen, unsigned char);\r
551     p = blob;\r
552     PUT_32BIT(p, dlen);\r
553     p += 4;\r
554     for (i = dlen; i--;)\r
555         *p++ = bignum_byte(rsa->private_exponent, i);\r
556     PUT_32BIT(p, plen);\r
557     p += 4;\r
558     for (i = plen; i--;)\r
559         *p++ = bignum_byte(rsa->p, i);\r
560     PUT_32BIT(p, qlen);\r
561     p += 4;\r
562     for (i = qlen; i--;)\r
563         *p++ = bignum_byte(rsa->q, i);\r
564     PUT_32BIT(p, ulen);\r
565     p += 4;\r
566     for (i = ulen; i--;)\r
567         *p++ = bignum_byte(rsa->iqmp, i);\r
568     assert(p == blob + bloblen);\r
569     *len = bloblen;\r
570     return blob;\r
571 }\r
572 \r
573 static void *rsa2_createkey(unsigned char *pub_blob, int pub_len,\r
574                             unsigned char *priv_blob, int priv_len)\r
575 {\r
576     struct RSAKey *rsa;\r
577     char *pb = (char *) priv_blob;\r
578 \r
579     rsa = rsa2_newkey((char *) pub_blob, pub_len);\r
580     rsa->private_exponent = getmp(&pb, &priv_len);\r
581     rsa->p = getmp(&pb, &priv_len);\r
582     rsa->q = getmp(&pb, &priv_len);\r
583     rsa->iqmp = getmp(&pb, &priv_len);\r
584 \r
585     if (!rsa_verify(rsa)) {\r
586         rsa2_freekey(rsa);\r
587         return NULL;\r
588     }\r
589 \r
590     return rsa;\r
591 }\r
592 \r
593 static void *rsa2_openssh_createkey(unsigned char **blob, int *len)\r
594 {\r
595     char **b = (char **) blob;\r
596     struct RSAKey *rsa;\r
597 \r
598     rsa = snew(struct RSAKey);\r
599     if (!rsa)\r
600         return NULL;\r
601     rsa->comment = NULL;\r
602 \r
603     rsa->modulus = getmp(b, len);\r
604     rsa->exponent = getmp(b, len);\r
605     rsa->private_exponent = getmp(b, len);\r
606     rsa->iqmp = getmp(b, len);\r
607     rsa->p = getmp(b, len);\r
608     rsa->q = getmp(b, len);\r
609 \r
610     if (!rsa->modulus || !rsa->exponent || !rsa->private_exponent ||\r
611         !rsa->iqmp || !rsa->p || !rsa->q) {\r
612         sfree(rsa->modulus);\r
613         sfree(rsa->exponent);\r
614         sfree(rsa->private_exponent);\r
615         sfree(rsa->iqmp);\r
616         sfree(rsa->p);\r
617         sfree(rsa->q);\r
618         sfree(rsa);\r
619         return NULL;\r
620     }\r
621 \r
622     return rsa;\r
623 }\r
624 \r
625 static int rsa2_openssh_fmtkey(void *key, unsigned char *blob, int len)\r
626 {\r
627     struct RSAKey *rsa = (struct RSAKey *) key;\r
628     int bloblen, i;\r
629 \r
630     bloblen =\r
631         ssh2_bignum_length(rsa->modulus) +\r
632         ssh2_bignum_length(rsa->exponent) +\r
633         ssh2_bignum_length(rsa->private_exponent) +\r
634         ssh2_bignum_length(rsa->iqmp) +\r
635         ssh2_bignum_length(rsa->p) + ssh2_bignum_length(rsa->q);\r
636 \r
637     if (bloblen > len)\r
638         return bloblen;\r
639 \r
640     bloblen = 0;\r
641 #define ENC(x) \\r
642     PUT_32BIT(blob+bloblen, ssh2_bignum_length((x))-4); bloblen += 4; \\r
643     for (i = ssh2_bignum_length((x))-4; i-- ;) blob[bloblen++]=bignum_byte((x),i);\r
644     ENC(rsa->modulus);\r
645     ENC(rsa->exponent);\r
646     ENC(rsa->private_exponent);\r
647     ENC(rsa->iqmp);\r
648     ENC(rsa->p);\r
649     ENC(rsa->q);\r
650 \r
651     return bloblen;\r
652 }\r
653 \r
654 static int rsa2_pubkey_bits(void *blob, int len)\r
655 {\r
656     struct RSAKey *rsa;\r
657     int ret;\r
658 \r
659     rsa = rsa2_newkey((char *) blob, len);\r
660     ret = bignum_bitcount(rsa->modulus);\r
661     rsa2_freekey(rsa);\r
662 \r
663     return ret;\r
664 }\r
665 \r
666 static char *rsa2_fingerprint(void *key)\r
667 {\r
668     struct RSAKey *rsa = (struct RSAKey *) key;\r
669     struct MD5Context md5c;\r
670     unsigned char digest[16], lenbuf[4];\r
671     char buffer[16 * 3 + 40];\r
672     char *ret;\r
673     int numlen, i;\r
674 \r
675     MD5Init(&md5c);\r
676     MD5Update(&md5c, (unsigned char *)"\0\0\0\7ssh-rsa", 11);\r
677 \r
678 #define ADD_BIGNUM(bignum) \\r
679     numlen = (bignum_bitcount(bignum)+8)/8; \\r
680     PUT_32BIT(lenbuf, numlen); MD5Update(&md5c, lenbuf, 4); \\r
681     for (i = numlen; i-- ;) { \\r
682         unsigned char c = bignum_byte(bignum, i); \\r
683         MD5Update(&md5c, &c, 1); \\r
684     }\r
685     ADD_BIGNUM(rsa->exponent);\r
686     ADD_BIGNUM(rsa->modulus);\r
687 #undef ADD_BIGNUM\r
688 \r
689     MD5Final(digest, &md5c);\r
690 \r
691     sprintf(buffer, "ssh-rsa %d ", bignum_bitcount(rsa->modulus));\r
692     for (i = 0; i < 16; i++)\r
693         sprintf(buffer + strlen(buffer), "%s%02x", i ? ":" : "",\r
694                 digest[i]);\r
695     ret = snewn(strlen(buffer) + 1, char);\r
696     if (ret)\r
697         strcpy(ret, buffer);\r
698     return ret;\r
699 }\r
700 \r
701 /*\r
702  * This is the magic ASN.1/DER prefix that goes in the decoded\r
703  * signature, between the string of FFs and the actual SHA hash\r
704  * value. The meaning of it is:\r
705  * \r
706  * 00 -- this marks the end of the FFs; not part of the ASN.1 bit itself\r
707  * \r
708  * 30 21 -- a constructed SEQUENCE of length 0x21\r
709  *    30 09 -- a constructed sub-SEQUENCE of length 9\r
710  *       06 05 -- an object identifier, length 5\r
711  *          2B 0E 03 02 1A -- object id { 1 3 14 3 2 26 }\r
712  *                            (the 1,3 comes from 0x2B = 43 = 40*1+3)\r
713  *       05 00 -- NULL\r
714  *    04 14 -- a primitive OCTET STRING of length 0x14\r
715  *       [0x14 bytes of hash data follows]\r
716  * \r
717  * The object id in the middle there is listed as `id-sha1' in\r
718  * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1d2.asn (the\r
719  * ASN module for PKCS #1) and its expanded form is as follows:\r
720  * \r
721  * id-sha1                OBJECT IDENTIFIER ::= {\r
722  *    iso(1) identified-organization(3) oiw(14) secsig(3)\r
723  *    algorithms(2) 26 }\r
724  */\r
725 static const unsigned char asn1_weird_stuff[] = {\r
726     0x00, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B,\r
727     0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14,\r
728 };\r
729 \r
730 #define ASN1_LEN ( (int) sizeof(asn1_weird_stuff) )\r
731 \r
732 static int rsa2_verifysig(void *key, char *sig, int siglen,\r
733                           char *data, int datalen)\r
734 {\r
735     struct RSAKey *rsa = (struct RSAKey *) key;\r
736     Bignum in, out;\r
737     char *p;\r
738     int slen;\r
739     int bytes, i, j, ret;\r
740     unsigned char hash[20];\r
741 \r
742     getstring(&sig, &siglen, &p, &slen);\r
743     if (!p || slen != 7 || memcmp(p, "ssh-rsa", 7)) {\r
744         return 0;\r
745     }\r
746     in = getmp(&sig, &siglen);\r
747     out = modpow(in, rsa->exponent, rsa->modulus);\r
748     freebn(in);\r
749 \r
750     ret = 1;\r
751 \r
752     bytes = (bignum_bitcount(rsa->modulus)+7) / 8;\r
753     /* Top (partial) byte should be zero. */\r
754     if (bignum_byte(out, bytes - 1) != 0)\r
755         ret = 0;\r
756     /* First whole byte should be 1. */\r
757     if (bignum_byte(out, bytes - 2) != 1)\r
758         ret = 0;\r
759     /* Most of the rest should be FF. */\r
760     for (i = bytes - 3; i >= 20 + ASN1_LEN; i--) {\r
761         if (bignum_byte(out, i) != 0xFF)\r
762             ret = 0;\r
763     }\r
764     /* Then we expect to see the asn1_weird_stuff. */\r
765     for (i = 20 + ASN1_LEN - 1, j = 0; i >= 20; i--, j++) {\r
766         if (bignum_byte(out, i) != asn1_weird_stuff[j])\r
767             ret = 0;\r
768     }\r
769     /* Finally, we expect to see the SHA-1 hash of the signed data. */\r
770     SHA_Simple(data, datalen, hash);\r
771     for (i = 19, j = 0; i >= 0; i--, j++) {\r
772         if (bignum_byte(out, i) != hash[j])\r
773             ret = 0;\r
774     }\r
775     freebn(out);\r
776 \r
777     return ret;\r
778 }\r
779 \r
780 static unsigned char *rsa2_sign(void *key, char *data, int datalen,\r
781                                 int *siglen)\r
782 {\r
783     struct RSAKey *rsa = (struct RSAKey *) key;\r
784     unsigned char *bytes;\r
785     int nbytes;\r
786     unsigned char hash[20];\r
787     Bignum in, out;\r
788     int i, j;\r
789 \r
790     SHA_Simple(data, datalen, hash);\r
791 \r
792     nbytes = (bignum_bitcount(rsa->modulus) - 1) / 8;\r
793     assert(1 <= nbytes - 20 - ASN1_LEN);\r
794     bytes = snewn(nbytes, unsigned char);\r
795 \r
796     bytes[0] = 1;\r
797     for (i = 1; i < nbytes - 20 - ASN1_LEN; i++)\r
798         bytes[i] = 0xFF;\r
799     for (i = nbytes - 20 - ASN1_LEN, j = 0; i < nbytes - 20; i++, j++)\r
800         bytes[i] = asn1_weird_stuff[j];\r
801     for (i = nbytes - 20, j = 0; i < nbytes; i++, j++)\r
802         bytes[i] = hash[j];\r
803 \r
804     in = bignum_from_bytes(bytes, nbytes);\r
805     sfree(bytes);\r
806 \r
807     out = rsa_privkey_op(in, rsa);\r
808     freebn(in);\r
809 \r
810     nbytes = (bignum_bitcount(out) + 7) / 8;\r
811     bytes = snewn(4 + 7 + 4 + nbytes, unsigned char);\r
812     PUT_32BIT(bytes, 7);\r
813     memcpy(bytes + 4, "ssh-rsa", 7);\r
814     PUT_32BIT(bytes + 4 + 7, nbytes);\r
815     for (i = 0; i < nbytes; i++)\r
816         bytes[4 + 7 + 4 + i] = bignum_byte(out, nbytes - 1 - i);\r
817     freebn(out);\r
818 \r
819     *siglen = 4 + 7 + 4 + nbytes;\r
820     return bytes;\r
821 }\r
822 \r
823 const struct ssh_signkey ssh_rsa = {\r
824     rsa2_newkey,\r
825     rsa2_freekey,\r
826     rsa2_fmtkey,\r
827     rsa2_public_blob,\r
828     rsa2_private_blob,\r
829     rsa2_createkey,\r
830     rsa2_openssh_createkey,\r
831     rsa2_openssh_fmtkey,\r
832     rsa2_pubkey_bits,\r
833     rsa2_fingerprint,\r
834     rsa2_verifysig,\r
835     rsa2_sign,\r
836     "ssh-rsa",\r
837     "rsa2"\r
838 };\r