sshdss.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
  1. /*
  2. * Digital Signature Standard implementation for PuTTY.
  3. */
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <assert.h>
  7. #include "ssh.h"
  8. #include "misc.h"
  9. static void sha_mpint(SHA_State * s, Bignum b)
  10. {
  11. unsigned char lenbuf[4];
  12. int len;
  13. len = (bignum_bitcount(b) + 8) / 8;
  14. PUT_32BIT(lenbuf, len);
  15. SHA_Bytes(s, lenbuf, 4);
  16. while (len-- > 0) {
  17. lenbuf[0] = bignum_byte(b, len);
  18. SHA_Bytes(s, lenbuf, 1);
  19. }
  20. smemclr(lenbuf, sizeof(lenbuf));
  21. }
  22. static void sha512_mpint(SHA512_State * s, Bignum b)
  23. {
  24. unsigned char lenbuf[4];
  25. int len;
  26. len = (bignum_bitcount(b) + 8) / 8;
  27. PUT_32BIT(lenbuf, len);
  28. SHA512_Bytes(s, lenbuf, 4);
  29. while (len-- > 0) {
  30. lenbuf[0] = bignum_byte(b, len);
  31. SHA512_Bytes(s, lenbuf, 1);
  32. }
  33. smemclr(lenbuf, sizeof(lenbuf));
  34. }
  35. static void getstring(char **data, int *datalen, char **p, int *length)
  36. {
  37. *p = NULL;
  38. if (*datalen < 4)
  39. return;
  40. *length = toint(GET_32BIT(*data));
  41. if (*length < 0)
  42. return;
  43. *datalen -= 4;
  44. *data += 4;
  45. if (*datalen < *length)
  46. return;
  47. *p = *data;
  48. *data += *length;
  49. *datalen -= *length;
  50. }
  51. static Bignum getmp(char **data, int *datalen)
  52. {
  53. char *p;
  54. int length;
  55. Bignum b;
  56. getstring(data, datalen, &p, &length);
  57. if (!p)
  58. return NULL;
  59. if (p[0] & 0x80)
  60. return NULL; /* negative mp */
  61. b = bignum_from_bytes((unsigned char *)p, length);
  62. return b;
  63. }
  64. static Bignum get160(char **data, int *datalen)
  65. {
  66. Bignum b;
  67. if (*datalen < 20)
  68. return NULL;
  69. b = bignum_from_bytes((unsigned char *)*data, 20);
  70. *data += 20;
  71. *datalen -= 20;
  72. return b;
  73. }
  74. static void dss_freekey(void *key); /* forward reference */
  75. static void *dss_newkey(char *data, int len)
  76. {
  77. char *p;
  78. int slen;
  79. struct dss_key *dss;
  80. dss = snew(struct dss_key);
  81. getstring(&data, &len, &p, &slen);
  82. #ifdef DEBUG_DSS
  83. {
  84. int i;
  85. printf("key:");
  86. for (i = 0; i < len; i++)
  87. printf(" %02x", (unsigned char) (data[i]));
  88. printf("\n");
  89. }
  90. #endif
  91. if (!p || slen != 7 || memcmp(p, "ssh-dss", 7)) {
  92. sfree(dss);
  93. return NULL;
  94. }
  95. dss->p = getmp(&data, &len);
  96. dss->q = getmp(&data, &len);
  97. dss->g = getmp(&data, &len);
  98. dss->y = getmp(&data, &len);
  99. dss->x = NULL;
  100. if (!dss->p || !dss->q || !dss->g || !dss->y ||
  101. !bignum_cmp(dss->q, Zero) || !bignum_cmp(dss->p, Zero)) {
  102. /* Invalid key. */
  103. dss_freekey(dss);
  104. return NULL;
  105. }
  106. return dss;
  107. }
  108. static void dss_freekey(void *key)
  109. {
  110. struct dss_key *dss = (struct dss_key *) key;
  111. if (dss->p)
  112. freebn(dss->p);
  113. if (dss->q)
  114. freebn(dss->q);
  115. if (dss->g)
  116. freebn(dss->g);
  117. if (dss->y)
  118. freebn(dss->y);
  119. if (dss->x)
  120. freebn(dss->x);
  121. sfree(dss);
  122. }
  123. static char *dss_fmtkey(void *key)
  124. {
  125. struct dss_key *dss = (struct dss_key *) key;
  126. char *p;
  127. int len, i, pos, nibbles;
  128. static const char hex[] = "0123456789abcdef";
  129. if (!dss->p)
  130. return NULL;
  131. len = 8 + 4 + 1; /* 4 x "0x", punctuation, \0 */
  132. len += 4 * (bignum_bitcount(dss->p) + 15) / 16;
  133. len += 4 * (bignum_bitcount(dss->q) + 15) / 16;
  134. len += 4 * (bignum_bitcount(dss->g) + 15) / 16;
  135. len += 4 * (bignum_bitcount(dss->y) + 15) / 16;
  136. p = snewn(len, char);
  137. if (!p)
  138. return NULL;
  139. pos = 0;
  140. pos += sprintf(p + pos, "0x");
  141. nibbles = (3 + bignum_bitcount(dss->p)) / 4;
  142. if (nibbles < 1)
  143. nibbles = 1;
  144. for (i = nibbles; i--;)
  145. p[pos++] =
  146. hex[(bignum_byte(dss->p, i / 2) >> (4 * (i % 2))) & 0xF];
  147. pos += sprintf(p + pos, ",0x");
  148. nibbles = (3 + bignum_bitcount(dss->q)) / 4;
  149. if (nibbles < 1)
  150. nibbles = 1;
  151. for (i = nibbles; i--;)
  152. p[pos++] =
  153. hex[(bignum_byte(dss->q, i / 2) >> (4 * (i % 2))) & 0xF];
  154. pos += sprintf(p + pos, ",0x");
  155. nibbles = (3 + bignum_bitcount(dss->g)) / 4;
  156. if (nibbles < 1)
  157. nibbles = 1;
  158. for (i = nibbles; i--;)
  159. p[pos++] =
  160. hex[(bignum_byte(dss->g, i / 2) >> (4 * (i % 2))) & 0xF];
  161. pos += sprintf(p + pos, ",0x");
  162. nibbles = (3 + bignum_bitcount(dss->y)) / 4;
  163. if (nibbles < 1)
  164. nibbles = 1;
  165. for (i = nibbles; i--;)
  166. p[pos++] =
  167. hex[(bignum_byte(dss->y, i / 2) >> (4 * (i % 2))) & 0xF];
  168. p[pos] = '\0';
  169. return p;
  170. }
  171. static char *dss_fingerprint(void *key)
  172. {
  173. struct dss_key *dss = (struct dss_key *) key;
  174. struct MD5Context md5c;
  175. unsigned char digest[16], lenbuf[4];
  176. char buffer[16 * 3 + 40];
  177. char *ret;
  178. int numlen, i;
  179. MD5Init(&md5c);
  180. MD5Update(&md5c, (unsigned char *)"\0\0\0\7ssh-dss", 11);
  181. #define ADD_BIGNUM(bignum) \
  182. numlen = (bignum_bitcount(bignum)+8)/8; \
  183. PUT_32BIT(lenbuf, numlen); MD5Update(&md5c, lenbuf, 4); \
  184. for (i = numlen; i-- ;) { \
  185. unsigned char c = bignum_byte(bignum, i); \
  186. MD5Update(&md5c, &c, 1); \
  187. }
  188. ADD_BIGNUM(dss->p);
  189. ADD_BIGNUM(dss->q);
  190. ADD_BIGNUM(dss->g);
  191. ADD_BIGNUM(dss->y);
  192. #undef ADD_BIGNUM
  193. MD5Final(digest, &md5c);
  194. sprintf(buffer, "ssh-dss %d ", bignum_bitcount(dss->p));
  195. for (i = 0; i < 16; i++)
  196. sprintf(buffer + strlen(buffer), "%s%02x", i ? ":" : "",
  197. digest[i]);
  198. ret = snewn(strlen(buffer) + 1, char);
  199. if (ret)
  200. strcpy(ret, buffer);
  201. return ret;
  202. }
  203. static int dss_verifysig(void *key, char *sig, int siglen,
  204. char *data, int datalen)
  205. {
  206. struct dss_key *dss = (struct dss_key *) key;
  207. char *p;
  208. int slen;
  209. char hash[20];
  210. Bignum r, s, w, gu1p, yu2p, gu1yu2p, u1, u2, sha, v;
  211. int ret;
  212. if (!dss->p)
  213. return 0;
  214. #ifdef DEBUG_DSS
  215. {
  216. int i;
  217. printf("sig:");
  218. for (i = 0; i < siglen; i++)
  219. printf(" %02x", (unsigned char) (sig[i]));
  220. printf("\n");
  221. }
  222. #endif
  223. /*
  224. * Commercial SSH (2.0.13) and OpenSSH disagree over the format
  225. * of a DSA signature. OpenSSH is in line with RFC 4253:
  226. * it uses a string "ssh-dss", followed by a 40-byte string
  227. * containing two 160-bit integers end-to-end. Commercial SSH
  228. * can't be bothered with the header bit, and considers a DSA
  229. * signature blob to be _just_ the 40-byte string containing
  230. * the two 160-bit integers. We tell them apart by measuring
  231. * the length: length 40 means the commercial-SSH bug, anything
  232. * else is assumed to be RFC-compliant.
  233. */
  234. if (siglen != 40) { /* bug not present; read admin fields */
  235. getstring(&sig, &siglen, &p, &slen);
  236. if (!p || slen != 7 || memcmp(p, "ssh-dss", 7)) {
  237. return 0;
  238. }
  239. sig += 4, siglen -= 4; /* skip yet another length field */
  240. }
  241. r = get160(&sig, &siglen);
  242. s = get160(&sig, &siglen);
  243. if (!r || !s) {
  244. if (r)
  245. freebn(r);
  246. if (s)
  247. freebn(s);
  248. return 0;
  249. }
  250. if (!bignum_cmp(s, Zero)) {
  251. freebn(r);
  252. freebn(s);
  253. return 0;
  254. }
  255. /*
  256. * Step 1. w <- s^-1 mod q.
  257. */
  258. w = modinv(s, dss->q);
  259. if (!w) {
  260. freebn(r);
  261. freebn(s);
  262. return 0;
  263. }
  264. /*
  265. * Step 2. u1 <- SHA(message) * w mod q.
  266. */
  267. SHA_Simple(data, datalen, (unsigned char *)hash);
  268. p = hash;
  269. slen = 20;
  270. sha = get160(&p, &slen);
  271. u1 = modmul(sha, w, dss->q);
  272. /*
  273. * Step 3. u2 <- r * w mod q.
  274. */
  275. u2 = modmul(r, w, dss->q);
  276. /*
  277. * Step 4. v <- (g^u1 * y^u2 mod p) mod q.
  278. */
  279. gu1p = modpow(dss->g, u1, dss->p);
  280. yu2p = modpow(dss->y, u2, dss->p);
  281. gu1yu2p = modmul(gu1p, yu2p, dss->p);
  282. v = modmul(gu1yu2p, One, dss->q);
  283. /*
  284. * Step 5. v should now be equal to r.
  285. */
  286. ret = !bignum_cmp(v, r);
  287. freebn(w);
  288. freebn(sha);
  289. freebn(u1);
  290. freebn(u2);
  291. freebn(gu1p);
  292. freebn(yu2p);
  293. freebn(gu1yu2p);
  294. freebn(v);
  295. freebn(r);
  296. freebn(s);
  297. return ret;
  298. }
  299. static unsigned char *dss_public_blob(void *key, int *len)
  300. {
  301. struct dss_key *dss = (struct dss_key *) key;
  302. int plen, qlen, glen, ylen, bloblen;
  303. int i;
  304. unsigned char *blob, *p;
  305. plen = (bignum_bitcount(dss->p) + 8) / 8;
  306. qlen = (bignum_bitcount(dss->q) + 8) / 8;
  307. glen = (bignum_bitcount(dss->g) + 8) / 8;
  308. ylen = (bignum_bitcount(dss->y) + 8) / 8;
  309. /*
  310. * string "ssh-dss", mpint p, mpint q, mpint g, mpint y. Total
  311. * 27 + sum of lengths. (five length fields, 20+7=27).
  312. */
  313. bloblen = 27 + plen + qlen + glen + ylen;
  314. blob = snewn(bloblen, unsigned char);
  315. p = blob;
  316. PUT_32BIT(p, 7);
  317. p += 4;
  318. memcpy(p, "ssh-dss", 7);
  319. p += 7;
  320. PUT_32BIT(p, plen);
  321. p += 4;
  322. for (i = plen; i--;)
  323. *p++ = bignum_byte(dss->p, i);
  324. PUT_32BIT(p, qlen);
  325. p += 4;
  326. for (i = qlen; i--;)
  327. *p++ = bignum_byte(dss->q, i);
  328. PUT_32BIT(p, glen);
  329. p += 4;
  330. for (i = glen; i--;)
  331. *p++ = bignum_byte(dss->g, i);
  332. PUT_32BIT(p, ylen);
  333. p += 4;
  334. for (i = ylen; i--;)
  335. *p++ = bignum_byte(dss->y, i);
  336. assert(p == blob + bloblen);
  337. *len = bloblen;
  338. return blob;
  339. }
  340. static unsigned char *dss_private_blob(void *key, int *len)
  341. {
  342. struct dss_key *dss = (struct dss_key *) key;
  343. int xlen, bloblen;
  344. int i;
  345. unsigned char *blob, *p;
  346. xlen = (bignum_bitcount(dss->x) + 8) / 8;
  347. /*
  348. * mpint x, string[20] the SHA of p||q||g. Total 4 + xlen.
  349. */
  350. bloblen = 4 + xlen;
  351. blob = snewn(bloblen, unsigned char);
  352. p = blob;
  353. PUT_32BIT(p, xlen);
  354. p += 4;
  355. for (i = xlen; i--;)
  356. *p++ = bignum_byte(dss->x, i);
  357. assert(p == blob + bloblen);
  358. *len = bloblen;
  359. return blob;
  360. }
  361. static void *dss_createkey(unsigned char *pub_blob, int pub_len,
  362. unsigned char *priv_blob, int priv_len)
  363. {
  364. struct dss_key *dss;
  365. char *pb = (char *) priv_blob;
  366. char *hash;
  367. int hashlen;
  368. SHA_State s;
  369. unsigned char digest[20];
  370. Bignum ytest;
  371. dss = dss_newkey((char *) pub_blob, pub_len);
  372. if (!dss)
  373. return NULL;
  374. dss->x = getmp(&pb, &priv_len);
  375. if (!dss->x) {
  376. dss_freekey(dss);
  377. return NULL;
  378. }
  379. /*
  380. * Check the obsolete hash in the old DSS key format.
  381. */
  382. hashlen = -1;
  383. getstring(&pb, &priv_len, &hash, &hashlen);
  384. if (hashlen == 20) {
  385. SHA_Init(&s);
  386. sha_mpint(&s, dss->p);
  387. sha_mpint(&s, dss->q);
  388. sha_mpint(&s, dss->g);
  389. SHA_Final(&s, digest);
  390. if (0 != memcmp(hash, digest, 20)) {
  391. dss_freekey(dss);
  392. return NULL;
  393. }
  394. }
  395. /*
  396. * Now ensure g^x mod p really is y.
  397. */
  398. ytest = modpow(dss->g, dss->x, dss->p);
  399. if (0 != bignum_cmp(ytest, dss->y)) {
  400. dss_freekey(dss);
  401. freebn(ytest);
  402. return NULL;
  403. }
  404. freebn(ytest);
  405. return dss;
  406. }
  407. static void *dss_openssh_createkey(unsigned char **blob, int *len)
  408. {
  409. char **b = (char **) blob;
  410. struct dss_key *dss;
  411. dss = snew(struct dss_key);
  412. dss->p = getmp(b, len);
  413. dss->q = getmp(b, len);
  414. dss->g = getmp(b, len);
  415. dss->y = getmp(b, len);
  416. dss->x = getmp(b, len);
  417. if (!dss->p || !dss->q || !dss->g || !dss->y || !dss->x ||
  418. !bignum_cmp(dss->q, Zero) || !bignum_cmp(dss->p, Zero)) {
  419. /* Invalid key. */
  420. dss_freekey(dss);
  421. return NULL;
  422. }
  423. return dss;
  424. }
  425. static int dss_openssh_fmtkey(void *key, unsigned char *blob, int len)
  426. {
  427. struct dss_key *dss = (struct dss_key *) key;
  428. int bloblen, i;
  429. bloblen =
  430. ssh2_bignum_length(dss->p) +
  431. ssh2_bignum_length(dss->q) +
  432. ssh2_bignum_length(dss->g) +
  433. ssh2_bignum_length(dss->y) +
  434. ssh2_bignum_length(dss->x);
  435. if (bloblen > len)
  436. return bloblen;
  437. bloblen = 0;
  438. #define ENC(x) \
  439. PUT_32BIT(blob+bloblen, ssh2_bignum_length((x))-4); bloblen += 4; \
  440. for (i = ssh2_bignum_length((x))-4; i-- ;) blob[bloblen++]=bignum_byte((x),i);
  441. ENC(dss->p);
  442. ENC(dss->q);
  443. ENC(dss->g);
  444. ENC(dss->y);
  445. ENC(dss->x);
  446. return bloblen;
  447. }
  448. static int dss_pubkey_bits(void *blob, int len)
  449. {
  450. struct dss_key *dss;
  451. int ret;
  452. dss = dss_newkey((char *) blob, len);
  453. if (!dss)
  454. return -1;
  455. ret = bignum_bitcount(dss->p);
  456. dss_freekey(dss);
  457. return ret;
  458. }
  459. static unsigned char *dss_sign(void *key, char *data, int datalen, int *siglen)
  460. {
  461. /*
  462. * The basic DSS signing algorithm is:
  463. *
  464. * - invent a random k between 1 and q-1 (exclusive).
  465. * - Compute r = (g^k mod p) mod q.
  466. * - Compute s = k^-1 * (hash + x*r) mod q.
  467. *
  468. * This has the dangerous properties that:
  469. *
  470. * - if an attacker in possession of the public key _and_ the
  471. * signature (for example, the host you just authenticated
  472. * to) can guess your k, he can reverse the computation of s
  473. * and work out x = r^-1 * (s*k - hash) mod q. That is, he
  474. * can deduce the private half of your key, and masquerade
  475. * as you for as long as the key is still valid.
  476. *
  477. * - since r is a function purely of k and the public key, if
  478. * the attacker only has a _range of possibilities_ for k
  479. * it's easy for him to work through them all and check each
  480. * one against r; he'll never be unsure of whether he's got
  481. * the right one.
  482. *
  483. * - if you ever sign two different hashes with the same k, it
  484. * will be immediately obvious because the two signatures
  485. * will have the same r, and moreover an attacker in
  486. * possession of both signatures (and the public key of
  487. * course) can compute k = (hash1-hash2) * (s1-s2)^-1 mod q,
  488. * and from there deduce x as before.
  489. *
  490. * - the Bleichenbacher attack on DSA makes use of methods of
  491. * generating k which are significantly non-uniformly
  492. * distributed; in particular, generating a 160-bit random
  493. * number and reducing it mod q is right out.
  494. *
  495. * For this reason we must be pretty careful about how we
  496. * generate our k. Since this code runs on Windows, with no
  497. * particularly good system entropy sources, we can't trust our
  498. * RNG itself to produce properly unpredictable data. Hence, we
  499. * use a totally different scheme instead.
  500. *
  501. * What we do is to take a SHA-512 (_big_) hash of the private
  502. * key x, and then feed this into another SHA-512 hash that
  503. * also includes the message hash being signed. That is:
  504. *
  505. * proto_k = SHA512 ( SHA512(x) || SHA160(message) )
  506. *
  507. * This number is 512 bits long, so reducing it mod q won't be
  508. * noticeably non-uniform. So
  509. *
  510. * k = proto_k mod q
  511. *
  512. * This has the interesting property that it's _deterministic_:
  513. * signing the same hash twice with the same key yields the
  514. * same signature.
  515. *
  516. * Despite this determinism, it's still not predictable to an
  517. * attacker, because in order to repeat the SHA-512
  518. * construction that created it, the attacker would have to
  519. * know the private key value x - and by assumption he doesn't,
  520. * because if he knew that he wouldn't be attacking k!
  521. *
  522. * (This trick doesn't, _per se_, protect against reuse of k.
  523. * Reuse of k is left to chance; all it does is prevent
  524. * _excessively high_ chances of reuse of k due to entropy
  525. * problems.)
  526. *
  527. * Thanks to Colin Plumb for the general idea of using x to
  528. * ensure k is hard to guess, and to the Cambridge University
  529. * Computer Security Group for helping to argue out all the
  530. * fine details.
  531. */
  532. struct dss_key *dss = (struct dss_key *) key;
  533. SHA512_State ss;
  534. unsigned char digest[20], digest512[64];
  535. Bignum proto_k, k, gkp, hash, kinv, hxr, r, s;
  536. unsigned char *bytes;
  537. int nbytes, i;
  538. SHA_Simple(data, datalen, digest);
  539. /*
  540. * Hash some identifying text plus x.
  541. */
  542. SHA512_Init(&ss);
  543. SHA512_Bytes(&ss, "DSA deterministic k generator", 30);
  544. sha512_mpint(&ss, dss->x);
  545. SHA512_Final(&ss, digest512);
  546. /*
  547. * Now hash that digest plus the message hash.
  548. */
  549. SHA512_Init(&ss);
  550. SHA512_Bytes(&ss, digest512, sizeof(digest512));
  551. SHA512_Bytes(&ss, digest, sizeof(digest));
  552. while (1) {
  553. SHA512_State ss2 = ss; /* structure copy */
  554. SHA512_Final(&ss2, digest512);
  555. smemclr(&ss2, sizeof(ss2));
  556. /*
  557. * Now convert the result into a bignum, and reduce it mod q.
  558. */
  559. proto_k = bignum_from_bytes(digest512, 64);
  560. k = bigmod(proto_k, dss->q);
  561. freebn(proto_k);
  562. kinv = modinv(k, dss->q); /* k^-1 mod q */
  563. if (!kinv) { /* very unlikely */
  564. freebn(k);
  565. /* Perturb the hash to think of a different k. */
  566. SHA512_Bytes(&ss, "x", 1);
  567. /* Go round and try again. */
  568. continue;
  569. }
  570. break;
  571. }
  572. smemclr(&ss, sizeof(ss));
  573. smemclr(digest512, sizeof(digest512));
  574. /*
  575. * Now we have k, so just go ahead and compute the signature.
  576. */
  577. gkp = modpow(dss->g, k, dss->p); /* g^k mod p */
  578. r = bigmod(gkp, dss->q); /* r = (g^k mod p) mod q */
  579. freebn(gkp);
  580. hash = bignum_from_bytes(digest, 20);
  581. hxr = bigmuladd(dss->x, r, hash); /* hash + x*r */
  582. s = modmul(kinv, hxr, dss->q); /* s = k^-1 * (hash + x*r) mod q */
  583. freebn(hxr);
  584. freebn(kinv);
  585. freebn(k);
  586. freebn(hash);
  587. /*
  588. * Signature blob is
  589. *
  590. * string "ssh-dss"
  591. * string two 20-byte numbers r and s, end to end
  592. *
  593. * i.e. 4+7 + 4+40 bytes.
  594. */
  595. nbytes = 4 + 7 + 4 + 40;
  596. bytes = snewn(nbytes, unsigned char);
  597. PUT_32BIT(bytes, 7);
  598. memcpy(bytes + 4, "ssh-dss", 7);
  599. PUT_32BIT(bytes + 4 + 7, 40);
  600. for (i = 0; i < 20; i++) {
  601. bytes[4 + 7 + 4 + i] = bignum_byte(r, 19 - i);
  602. bytes[4 + 7 + 4 + 20 + i] = bignum_byte(s, 19 - i);
  603. }
  604. freebn(r);
  605. freebn(s);
  606. *siglen = nbytes;
  607. return bytes;
  608. }
  609. const struct ssh_signkey ssh_dss = {
  610. dss_newkey,
  611. dss_freekey,
  612. dss_fmtkey,
  613. dss_public_blob,
  614. dss_private_blob,
  615. dss_createkey,
  616. dss_openssh_createkey,
  617. dss_openssh_fmtkey,
  618. dss_pubkey_bits,
  619. dss_fingerprint,
  620. dss_verifysig,
  621. dss_sign,
  622. "ssh-dss",
  623. "dss"
  624. };