rsa.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414
  1. /*
  2. * Dropbear - a SSH2 server
  3. *
  4. * Copyright (c) 2002,2003 Matt Johnston
  5. * All rights reserved.
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  23. * SOFTWARE. */
  24. /* Perform RSA operations on data, including reading keys, signing and
  25. * verification.
  26. *
  27. * The format is specified in rfc2437, Applied Cryptography or The Handbook of
  28. * Applied Cryptography detail the general algorithm. */
  29. #include "includes.h"
  30. #include "dbutil.h"
  31. #include "bignum.h"
  32. #include "rsa.h"
  33. #include "buffer.h"
  34. #include "ssh.h"
  35. #include "dbrandom.h"
  36. #ifdef DROPBEAR_RSA
  37. static void rsa_pad_em(dropbear_rsa_key * key,
  38. buffer *data_buf, mp_int * rsa_em);
  39. /* Load a public rsa key from a buffer, initialising the values.
  40. * The key will have the same format as buf_put_rsa_key.
  41. * These should be freed with rsa_key_free.
  42. * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
  43. int buf_get_rsa_pub_key(buffer* buf, dropbear_rsa_key *key) {
  44. int ret = DROPBEAR_FAILURE;
  45. TRACE(("enter buf_get_rsa_pub_key"))
  46. dropbear_assert(key != NULL);
  47. m_mp_alloc_init_multi(&key->e, &key->n, NULL);
  48. key->d = NULL;
  49. key->p = NULL;
  50. key->q = NULL;
  51. buf_incrpos(buf, 4+SSH_SIGNKEY_RSA_LEN); /* int + "ssh-rsa" */
  52. if (buf_getmpint(buf, key->e) == DROPBEAR_FAILURE
  53. || buf_getmpint(buf, key->n) == DROPBEAR_FAILURE) {
  54. TRACE(("leave buf_get_rsa_pub_key: failure"))
  55. goto out;
  56. }
  57. if (mp_count_bits(key->n) < MIN_RSA_KEYLEN) {
  58. dropbear_log(LOG_WARNING, "RSA key too short");
  59. goto out;
  60. }
  61. TRACE(("leave buf_get_rsa_pub_key: success"))
  62. ret = DROPBEAR_SUCCESS;
  63. out:
  64. if (ret == DROPBEAR_FAILURE) {
  65. m_free(key->e);
  66. m_free(key->n);
  67. }
  68. return ret;
  69. }
  70. /* Same as buf_get_rsa_pub_key, but reads private bits at the end.
  71. * Loads a private rsa key from a buffer
  72. * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
  73. int buf_get_rsa_priv_key(buffer* buf, dropbear_rsa_key *key) {
  74. int ret = DROPBEAR_FAILURE;
  75. TRACE(("enter buf_get_rsa_priv_key"))
  76. dropbear_assert(key != NULL);
  77. if (buf_get_rsa_pub_key(buf, key) == DROPBEAR_FAILURE) {
  78. TRACE(("leave buf_get_rsa_priv_key: pub: ret == DROPBEAR_FAILURE"))
  79. return DROPBEAR_FAILURE;
  80. }
  81. key->d = NULL;
  82. key->p = NULL;
  83. key->q = NULL;
  84. m_mp_alloc_init_multi(&key->d, NULL);
  85. if (buf_getmpint(buf, key->d) == DROPBEAR_FAILURE) {
  86. TRACE(("leave buf_get_rsa_priv_key: d: ret == DROPBEAR_FAILURE"))
  87. goto out;
  88. }
  89. if (buf->pos == buf->len) {
  90. /* old Dropbear private keys didn't keep p and q, so we will ignore them*/
  91. } else {
  92. m_mp_alloc_init_multi(&key->p, &key->q, NULL);
  93. if (buf_getmpint(buf, key->p) == DROPBEAR_FAILURE) {
  94. TRACE(("leave buf_get_rsa_priv_key: p: ret == DROPBEAR_FAILURE"))
  95. goto out;
  96. }
  97. if (buf_getmpint(buf, key->q) == DROPBEAR_FAILURE) {
  98. TRACE(("leave buf_get_rsa_priv_key: q: ret == DROPBEAR_FAILURE"))
  99. goto out;
  100. }
  101. }
  102. ret = DROPBEAR_SUCCESS;
  103. out:
  104. if (ret == DROPBEAR_FAILURE) {
  105. m_free(key->d);
  106. m_free(key->p);
  107. m_free(key->q);
  108. }
  109. TRACE(("leave buf_get_rsa_priv_key"))
  110. return ret;
  111. }
  112. /* Clear and free the memory used by a public or private key */
  113. void rsa_key_free(dropbear_rsa_key *key) {
  114. TRACE2(("enter rsa_key_free"))
  115. if (key == NULL) {
  116. TRACE2(("leave rsa_key_free: key == NULL"))
  117. return;
  118. }
  119. if (key->d) {
  120. mp_clear(key->d);
  121. m_free(key->d);
  122. }
  123. if (key->e) {
  124. mp_clear(key->e);
  125. m_free(key->e);
  126. }
  127. if (key->n) {
  128. mp_clear(key->n);
  129. m_free(key->n);
  130. }
  131. if (key->p) {
  132. mp_clear(key->p);
  133. m_free(key->p);
  134. }
  135. if (key->q) {
  136. mp_clear(key->q);
  137. m_free(key->q);
  138. }
  139. m_free(key);
  140. TRACE2(("leave rsa_key_free"))
  141. }
  142. /* Put the public rsa key into the buffer in the required format:
  143. *
  144. * string "ssh-rsa"
  145. * mp_int e
  146. * mp_int n
  147. */
  148. void buf_put_rsa_pub_key(buffer* buf, dropbear_rsa_key *key) {
  149. TRACE(("enter buf_put_rsa_pub_key"))
  150. dropbear_assert(key != NULL);
  151. buf_putstring(buf, SSH_SIGNKEY_RSA, SSH_SIGNKEY_RSA_LEN);
  152. buf_putmpint(buf, key->e);
  153. buf_putmpint(buf, key->n);
  154. TRACE(("leave buf_put_rsa_pub_key"))
  155. }
  156. /* Same as buf_put_rsa_pub_key, but with the private "x" key appended */
  157. void buf_put_rsa_priv_key(buffer* buf, dropbear_rsa_key *key) {
  158. TRACE(("enter buf_put_rsa_priv_key"))
  159. dropbear_assert(key != NULL);
  160. buf_put_rsa_pub_key(buf, key);
  161. buf_putmpint(buf, key->d);
  162. /* new versions have p and q, old versions don't */
  163. if (key->p) {
  164. buf_putmpint(buf, key->p);
  165. }
  166. if (key->q) {
  167. buf_putmpint(buf, key->q);
  168. }
  169. TRACE(("leave buf_put_rsa_priv_key"))
  170. }
  171. #ifdef DROPBEAR_SIGNKEY_VERIFY
  172. /* Verify a signature in buf, made on data by the key given.
  173. * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
  174. int buf_rsa_verify(buffer * buf, dropbear_rsa_key *key, buffer *data_buf) {
  175. unsigned int slen;
  176. DEF_MP_INT(rsa_s);
  177. DEF_MP_INT(rsa_mdash);
  178. DEF_MP_INT(rsa_em);
  179. int ret = DROPBEAR_FAILURE;
  180. TRACE(("enter buf_rsa_verify"))
  181. dropbear_assert(key != NULL);
  182. m_mp_init_multi(&rsa_mdash, &rsa_s, &rsa_em, NULL);
  183. slen = buf_getint(buf);
  184. if (slen != (unsigned int)mp_unsigned_bin_size(key->n)) {
  185. TRACE(("bad size"))
  186. goto out;
  187. }
  188. if (mp_read_unsigned_bin(&rsa_s, buf_getptr(buf, buf->len - buf->pos),
  189. buf->len - buf->pos) != MP_OKAY) {
  190. TRACE(("failed reading rsa_s"))
  191. goto out;
  192. }
  193. /* check that s <= n-1 */
  194. if (mp_cmp(&rsa_s, key->n) != MP_LT) {
  195. TRACE(("s > n-1"))
  196. goto out;
  197. }
  198. /* create the magic PKCS padded value */
  199. rsa_pad_em(key, data_buf, &rsa_em);
  200. if (mp_exptmod(&rsa_s, key->e, key->n, &rsa_mdash) != MP_OKAY) {
  201. TRACE(("failed exptmod rsa_s"))
  202. goto out;
  203. }
  204. if (mp_cmp(&rsa_em, &rsa_mdash) == MP_EQ) {
  205. /* signature is valid */
  206. TRACE(("success!"))
  207. ret = DROPBEAR_SUCCESS;
  208. }
  209. out:
  210. mp_clear_multi(&rsa_mdash, &rsa_s, &rsa_em, NULL);
  211. TRACE(("leave buf_rsa_verify: ret %d", ret))
  212. return ret;
  213. }
  214. #endif /* DROPBEAR_SIGNKEY_VERIFY */
  215. /* Sign the data presented with key, writing the signature contents
  216. * to the buffer */
  217. void buf_put_rsa_sign(buffer* buf, dropbear_rsa_key *key, buffer *data_buf) {
  218. unsigned int nsize, ssize;
  219. unsigned int i;
  220. DEF_MP_INT(rsa_s);
  221. DEF_MP_INT(rsa_tmp1);
  222. DEF_MP_INT(rsa_tmp2);
  223. DEF_MP_INT(rsa_tmp3);
  224. TRACE(("enter buf_put_rsa_sign"))
  225. dropbear_assert(key != NULL);
  226. m_mp_init_multi(&rsa_s, &rsa_tmp1, &rsa_tmp2, &rsa_tmp3, NULL);
  227. rsa_pad_em(key, data_buf, &rsa_tmp1);
  228. /* the actual signing of the padded data */
  229. #ifdef RSA_BLINDING
  230. /* With blinding, s = (r^(-1))((em)*r^e)^d mod n */
  231. /* generate the r blinding value */
  232. /* rsa_tmp2 is r */
  233. gen_random_mpint(key->n, &rsa_tmp2);
  234. /* rsa_tmp1 is em */
  235. /* em' = em * r^e mod n */
  236. /* rsa_s used as a temp var*/
  237. if (mp_exptmod(&rsa_tmp2, key->e, key->n, &rsa_s) != MP_OKAY) {
  238. dropbear_exit("RSA error");
  239. }
  240. if (mp_invmod(&rsa_tmp2, key->n, &rsa_tmp3) != MP_OKAY) {
  241. dropbear_exit("RSA error");
  242. }
  243. if (mp_mulmod(&rsa_tmp1, &rsa_s, key->n, &rsa_tmp2) != MP_OKAY) {
  244. dropbear_exit("RSA error");
  245. }
  246. /* rsa_tmp2 is em' */
  247. /* s' = (em')^d mod n */
  248. if (mp_exptmod(&rsa_tmp2, key->d, key->n, &rsa_tmp1) != MP_OKAY) {
  249. dropbear_exit("RSA error");
  250. }
  251. /* rsa_tmp1 is s' */
  252. /* rsa_tmp3 is r^(-1) mod n */
  253. /* s = (s')r^(-1) mod n */
  254. if (mp_mulmod(&rsa_tmp1, &rsa_tmp3, key->n, &rsa_s) != MP_OKAY) {
  255. dropbear_exit("RSA error");
  256. }
  257. #else
  258. /* s = em^d mod n */
  259. /* rsa_tmp1 is em */
  260. if (mp_exptmod(&rsa_tmp1, key->d, key->n, &rsa_s) != MP_OKAY) {
  261. dropbear_exit("RSA error");
  262. }
  263. #endif /* RSA_BLINDING */
  264. mp_clear_multi(&rsa_tmp1, &rsa_tmp2, &rsa_tmp3, NULL);
  265. /* create the signature to return */
  266. buf_putstring(buf, SSH_SIGNKEY_RSA, SSH_SIGNKEY_RSA_LEN);
  267. nsize = mp_unsigned_bin_size(key->n);
  268. /* string rsa_signature_blob length */
  269. buf_putint(buf, nsize);
  270. /* pad out s to same length as n */
  271. ssize = mp_unsigned_bin_size(&rsa_s);
  272. dropbear_assert(ssize <= nsize);
  273. for (i = 0; i < nsize-ssize; i++) {
  274. buf_putbyte(buf, 0x00);
  275. }
  276. if (mp_to_unsigned_bin(&rsa_s, buf_getwriteptr(buf, ssize)) != MP_OKAY) {
  277. dropbear_exit("RSA error");
  278. }
  279. buf_incrwritepos(buf, ssize);
  280. mp_clear(&rsa_s);
  281. #if defined(DEBUG_RSA) && defined(DEBUG_TRACE)
  282. if (!debug_trace) {
  283. printhex("RSA sig", buf->data, buf->len);
  284. }
  285. #endif
  286. TRACE(("leave buf_put_rsa_sign"))
  287. }
  288. /* Creates the message value as expected by PKCS, see rfc2437 etc */
  289. /* format to be padded to is:
  290. * EM = 01 | FF* | 00 | prefix | hash
  291. *
  292. * where FF is repeated enough times to make EM one byte
  293. * shorter than the size of key->n
  294. *
  295. * prefix is the ASN1 designator prefix,
  296. * hex 30 21 30 09 06 05 2B 0E 03 02 1A 05 00 04 14
  297. *
  298. * rsa_em must be a pointer to an initialised mp_int.
  299. */
  300. static void rsa_pad_em(dropbear_rsa_key * key,
  301. buffer *data_buf, mp_int * rsa_em) {
  302. /* ASN1 designator (including the 0x00 preceding) */
  303. const unsigned char rsa_asn1_magic[] =
  304. {0x00, 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b,
  305. 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14};
  306. const unsigned int RSA_ASN1_MAGIC_LEN = 16;
  307. buffer * rsa_EM = NULL;
  308. hash_state hs;
  309. unsigned int nsize;
  310. dropbear_assert(key != NULL);
  311. nsize = mp_unsigned_bin_size(key->n);
  312. rsa_EM = buf_new(nsize-1);
  313. /* type byte */
  314. buf_putbyte(rsa_EM, 0x01);
  315. /* Padding with 0xFF bytes */
  316. while(rsa_EM->pos != rsa_EM->size - RSA_ASN1_MAGIC_LEN - SHA1_HASH_SIZE) {
  317. buf_putbyte(rsa_EM, 0xff);
  318. }
  319. /* Magic ASN1 stuff */
  320. memcpy(buf_getwriteptr(rsa_EM, RSA_ASN1_MAGIC_LEN),
  321. rsa_asn1_magic, RSA_ASN1_MAGIC_LEN);
  322. buf_incrwritepos(rsa_EM, RSA_ASN1_MAGIC_LEN);
  323. /* The hash of the data */
  324. sha1_init(&hs);
  325. sha1_process(&hs, data_buf->data, data_buf->len);
  326. sha1_done(&hs, buf_getwriteptr(rsa_EM, SHA1_HASH_SIZE));
  327. buf_incrwritepos(rsa_EM, SHA1_HASH_SIZE);
  328. dropbear_assert(rsa_EM->pos == rsa_EM->size);
  329. /* Create the mp_int from the encoded bytes */
  330. buf_setpos(rsa_EM, 0);
  331. bytes_to_mp(rsa_em, buf_getptr(rsa_EM, rsa_EM->size),
  332. rsa_EM->size);
  333. buf_free(rsa_EM);
  334. }
  335. #endif /* DROPBEAR_RSA */