rsa.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  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. #include "signkey.h"
  37. #if DROPBEAR_RSA
  38. #if !(DROPBEAR_RSA_SHA1 || DROPBEAR_RSA_SHA256)
  39. #error Somehow RSA was enabled with neither DROPBEAR_RSA_SHA1 nor DROPBEAR_RSA_SHA256
  40. #endif
  41. static void rsa_pad_em(const dropbear_rsa_key * key,
  42. const buffer *data_buf, mp_int * rsa_em, enum signature_type sigtype);
  43. /* Load a public rsa key from a buffer, initialising the values.
  44. * The key will have the same format as buf_put_rsa_key.
  45. * These should be freed with rsa_key_free.
  46. * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
  47. int buf_get_rsa_pub_key(buffer* buf, dropbear_rsa_key *key) {
  48. int ret = DROPBEAR_FAILURE;
  49. TRACE(("enter buf_get_rsa_pub_key"))
  50. dropbear_assert(key != NULL);
  51. m_mp_alloc_init_multi(&key->e, &key->n, NULL);
  52. key->d = NULL;
  53. key->p = NULL;
  54. key->q = NULL;
  55. buf_incrpos(buf, 4+SSH_SIGNKEY_RSA_LEN); /* int + "ssh-rsa" */
  56. if (buf_getmpint(buf, key->e) == DROPBEAR_FAILURE
  57. || buf_getmpint(buf, key->n) == DROPBEAR_FAILURE) {
  58. TRACE(("leave buf_get_rsa_pub_key: failure"))
  59. goto out;
  60. }
  61. if (mp_count_bits(key->n) < MIN_RSA_KEYLEN) {
  62. dropbear_log(LOG_WARNING, "RSA key too short");
  63. goto out;
  64. }
  65. /* 64 bit is limit used by openssl, so we won't block any keys in the wild */
  66. if (mp_count_bits(key->e) > 64) {
  67. dropbear_log(LOG_WARNING, "RSA key bad e");
  68. goto out;
  69. }
  70. TRACE(("leave buf_get_rsa_pub_key: success"))
  71. ret = DROPBEAR_SUCCESS;
  72. out:
  73. if (ret == DROPBEAR_FAILURE) {
  74. m_mp_free_multi(&key->e, &key->n, NULL);
  75. }
  76. return ret;
  77. }
  78. /* Same as buf_get_rsa_pub_key, but reads private bits at the end.
  79. * Loads a private rsa key from a buffer
  80. * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
  81. int buf_get_rsa_priv_key(buffer* buf, dropbear_rsa_key *key) {
  82. int ret = DROPBEAR_FAILURE;
  83. TRACE(("enter buf_get_rsa_priv_key"))
  84. dropbear_assert(key != NULL);
  85. if (buf_get_rsa_pub_key(buf, key) == DROPBEAR_FAILURE) {
  86. TRACE(("leave buf_get_rsa_priv_key: pub: ret == DROPBEAR_FAILURE"))
  87. return DROPBEAR_FAILURE;
  88. }
  89. key->d = NULL;
  90. key->p = NULL;
  91. key->q = NULL;
  92. m_mp_alloc_init_multi(&key->d, NULL);
  93. if (buf_getmpint(buf, key->d) == DROPBEAR_FAILURE) {
  94. TRACE(("leave buf_get_rsa_priv_key: d: ret == DROPBEAR_FAILURE"))
  95. goto out;
  96. }
  97. if (buf->pos == buf->len) {
  98. /* old Dropbear private keys didn't keep p and q, so we will ignore them*/
  99. } else {
  100. m_mp_alloc_init_multi(&key->p, &key->q, NULL);
  101. if (buf_getmpint(buf, key->p) == DROPBEAR_FAILURE) {
  102. TRACE(("leave buf_get_rsa_priv_key: p: ret == DROPBEAR_FAILURE"))
  103. goto out;
  104. }
  105. if (buf_getmpint(buf, key->q) == DROPBEAR_FAILURE) {
  106. TRACE(("leave buf_get_rsa_priv_key: q: ret == DROPBEAR_FAILURE"))
  107. goto out;
  108. }
  109. }
  110. ret = DROPBEAR_SUCCESS;
  111. out:
  112. if (ret == DROPBEAR_FAILURE) {
  113. m_mp_free_multi(&key->d, &key->p, &key->q, NULL);
  114. }
  115. TRACE(("leave buf_get_rsa_priv_key"))
  116. return ret;
  117. }
  118. /* Clear and free the memory used by a public or private key */
  119. void rsa_key_free(dropbear_rsa_key *key) {
  120. TRACE2(("enter rsa_key_free"))
  121. if (key == NULL) {
  122. TRACE2(("leave rsa_key_free: key == NULL"))
  123. return;
  124. }
  125. m_mp_free_multi(&key->d, &key->e, &key->p, &key->q, &key->n, NULL);
  126. m_free(key);
  127. TRACE2(("leave rsa_key_free"))
  128. }
  129. /* Put the public rsa key into the buffer in the required format:
  130. *
  131. * string "ssh-rsa"
  132. * mp_int e
  133. * mp_int n
  134. */
  135. void buf_put_rsa_pub_key(buffer* buf, const dropbear_rsa_key *key) {
  136. TRACE(("enter buf_put_rsa_pub_key"))
  137. dropbear_assert(key != NULL);
  138. buf_putstring(buf, SSH_SIGNKEY_RSA, SSH_SIGNKEY_RSA_LEN);
  139. buf_putmpint(buf, key->e);
  140. buf_putmpint(buf, key->n);
  141. TRACE(("leave buf_put_rsa_pub_key"))
  142. }
  143. /* Same as buf_put_rsa_pub_key, but with the private "x" key appended */
  144. void buf_put_rsa_priv_key(buffer* buf, const dropbear_rsa_key *key) {
  145. TRACE(("enter buf_put_rsa_priv_key"))
  146. dropbear_assert(key != NULL);
  147. buf_put_rsa_pub_key(buf, key);
  148. buf_putmpint(buf, key->d);
  149. /* new versions have p and q, old versions don't */
  150. if (key->p) {
  151. buf_putmpint(buf, key->p);
  152. }
  153. if (key->q) {
  154. buf_putmpint(buf, key->q);
  155. }
  156. TRACE(("leave buf_put_rsa_priv_key"))
  157. }
  158. #if DROPBEAR_SIGNKEY_VERIFY
  159. /* Verify a signature in buf, made on data by the key given.
  160. * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
  161. int buf_rsa_verify(buffer * buf, const dropbear_rsa_key *key,
  162. enum signature_type sigtype, const buffer *data_buf) {
  163. unsigned int slen;
  164. DEF_MP_INT(rsa_s);
  165. DEF_MP_INT(rsa_mdash);
  166. DEF_MP_INT(rsa_em);
  167. int ret = DROPBEAR_FAILURE;
  168. TRACE(("enter buf_rsa_verify"))
  169. dropbear_assert(key != NULL);
  170. m_mp_init_multi(&rsa_mdash, &rsa_s, &rsa_em, NULL);
  171. slen = buf_getint(buf);
  172. if (slen != (unsigned int)mp_ubin_size(key->n)) {
  173. TRACE(("bad size"))
  174. goto out;
  175. }
  176. if (mp_from_ubin(&rsa_s, buf_getptr(buf, buf->len - buf->pos),
  177. buf->len - buf->pos) != MP_OKAY) {
  178. TRACE(("failed reading rsa_s"))
  179. goto out;
  180. }
  181. /* check that s <= n-1 */
  182. if (mp_cmp(&rsa_s, key->n) != MP_LT) {
  183. TRACE(("s > n-1"))
  184. goto out;
  185. }
  186. /* create the magic PKCS padded value */
  187. rsa_pad_em(key, data_buf, &rsa_em, sigtype);
  188. if (mp_exptmod(&rsa_s, key->e, key->n, &rsa_mdash) != MP_OKAY) {
  189. TRACE(("failed exptmod rsa_s"))
  190. goto out;
  191. }
  192. if (mp_cmp(&rsa_em, &rsa_mdash) == MP_EQ) {
  193. /* signature is valid */
  194. TRACE(("success!"))
  195. ret = DROPBEAR_SUCCESS;
  196. }
  197. out:
  198. mp_clear_multi(&rsa_mdash, &rsa_s, &rsa_em, NULL);
  199. TRACE(("leave buf_rsa_verify: ret %d", ret))
  200. return ret;
  201. }
  202. #endif /* DROPBEAR_SIGNKEY_VERIFY */
  203. /* Sign the data presented with key, writing the signature contents
  204. * to the buffer */
  205. void buf_put_rsa_sign(buffer* buf, const dropbear_rsa_key *key,
  206. enum signature_type sigtype, const buffer *data_buf) {
  207. const char *name = NULL;
  208. unsigned int nsize, ssize, namelen = 0;
  209. unsigned int i;
  210. size_t written;
  211. DEF_MP_INT(rsa_s);
  212. DEF_MP_INT(rsa_tmp1);
  213. DEF_MP_INT(rsa_tmp2);
  214. DEF_MP_INT(rsa_tmp3);
  215. TRACE(("enter buf_put_rsa_sign"))
  216. dropbear_assert(key != NULL);
  217. m_mp_init_multi(&rsa_s, &rsa_tmp1, &rsa_tmp2, &rsa_tmp3, NULL);
  218. rsa_pad_em(key, data_buf, &rsa_tmp1, sigtype);
  219. /* the actual signing of the padded data */
  220. #if DROPBEAR_RSA_BLINDING
  221. /* With blinding, s = (r^(-1))((em)*r^e)^d mod n */
  222. /* generate the r blinding value */
  223. /* rsa_tmp2 is r */
  224. gen_random_mpint(key->n, &rsa_tmp2);
  225. /* rsa_tmp1 is em */
  226. /* em' = em * r^e mod n */
  227. /* rsa_s used as a temp var*/
  228. if (mp_exptmod(&rsa_tmp2, key->e, key->n, &rsa_s) != MP_OKAY) {
  229. dropbear_exit("RSA error");
  230. }
  231. if (mp_invmod(&rsa_tmp2, key->n, &rsa_tmp3) != MP_OKAY) {
  232. dropbear_exit("RSA error");
  233. }
  234. if (mp_mulmod(&rsa_tmp1, &rsa_s, key->n, &rsa_tmp2) != MP_OKAY) {
  235. dropbear_exit("RSA error");
  236. }
  237. /* rsa_tmp2 is em' */
  238. /* s' = (em')^d mod n */
  239. if (mp_exptmod(&rsa_tmp2, key->d, key->n, &rsa_tmp1) != MP_OKAY) {
  240. dropbear_exit("RSA error");
  241. }
  242. /* rsa_tmp1 is s' */
  243. /* rsa_tmp3 is r^(-1) mod n */
  244. /* s = (s')r^(-1) mod n */
  245. if (mp_mulmod(&rsa_tmp1, &rsa_tmp3, key->n, &rsa_s) != MP_OKAY) {
  246. dropbear_exit("RSA error");
  247. }
  248. #else
  249. /* s = em^d mod n */
  250. /* rsa_tmp1 is em */
  251. if (mp_exptmod(&rsa_tmp1, key->d, key->n, &rsa_s) != MP_OKAY) {
  252. dropbear_exit("RSA error");
  253. }
  254. #endif /* DROPBEAR_RSA_BLINDING */
  255. mp_clear_multi(&rsa_tmp1, &rsa_tmp2, &rsa_tmp3, NULL);
  256. /* create the signature to return */
  257. name = signature_name_from_type(sigtype, &namelen);
  258. buf_putstring(buf, name, namelen);
  259. nsize = mp_ubin_size(key->n);
  260. /* string rsa_signature_blob length */
  261. buf_putint(buf, nsize);
  262. /* pad out s to same length as n */
  263. ssize = mp_ubin_size(&rsa_s);
  264. dropbear_assert(ssize <= nsize);
  265. for (i = 0; i < nsize-ssize; i++) {
  266. buf_putbyte(buf, 0x00);
  267. }
  268. if (mp_to_ubin(&rsa_s, buf_getwriteptr(buf, ssize), ssize, &written) != MP_OKAY) {
  269. dropbear_exit("RSA error");
  270. }
  271. buf_incrwritepos(buf, written);
  272. mp_clear(&rsa_s);
  273. #if defined(DEBUG_RSA) && DEBUG_TRACE
  274. if (!debug_trace) {
  275. printhex("RSA sig", buf->data, buf->len);
  276. }
  277. #endif
  278. TRACE(("leave buf_put_rsa_sign"))
  279. }
  280. /* Creates the message value as expected by PKCS,
  281. see rfc8017 section 9.2 */
  282. static void rsa_pad_em(const dropbear_rsa_key * key,
  283. const buffer *data_buf, mp_int * rsa_em, enum signature_type sigtype) {
  284. /* EM = 0x00 || 0x01 || PS || 0x00 || T
  285. PS is padding of 0xff to make EM the size of key->n
  286. T is the DER encoding of the hash alg (sha1 or sha256)
  287. */
  288. /* From rfc8017 page 46 */
  289. #if DROPBEAR_RSA_SHA1
  290. const unsigned char T_sha1[] =
  291. {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b,
  292. 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14};
  293. #endif
  294. #if DROPBEAR_RSA_SHA256
  295. const unsigned char T_sha256[] =
  296. {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
  297. 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
  298. #endif
  299. int Tlen = 0;
  300. const unsigned char *T = NULL;
  301. const struct ltc_hash_descriptor *hash_desc = NULL;
  302. buffer * rsa_EM = NULL;
  303. hash_state hs;
  304. unsigned int nsize;
  305. switch (sigtype) {
  306. #if DROPBEAR_RSA_SHA1
  307. case DROPBEAR_SIGNATURE_RSA_SHA1:
  308. Tlen = sizeof(T_sha1);
  309. T = T_sha1;
  310. hash_desc = &sha1_desc;
  311. break;
  312. #endif
  313. #if DROPBEAR_RSA_SHA256
  314. case DROPBEAR_SIGNATURE_RSA_SHA256:
  315. Tlen = sizeof(T_sha256);
  316. T = T_sha256;
  317. hash_desc = &sha256_desc;
  318. break;
  319. #endif
  320. default:
  321. assert(0);
  322. }
  323. nsize = mp_ubin_size(key->n);
  324. rsa_EM = buf_new(nsize);
  325. /* type byte */
  326. buf_putbyte(rsa_EM, 0x00);
  327. buf_putbyte(rsa_EM, 0x01);
  328. /* Padding with PS 0xFF bytes */
  329. while(rsa_EM->pos != rsa_EM->size - (1 + Tlen + hash_desc->hashsize)) {
  330. buf_putbyte(rsa_EM, 0xff);
  331. }
  332. buf_putbyte(rsa_EM, 0x00);
  333. /* Magic ASN1 stuff */
  334. buf_putbytes(rsa_EM, T, Tlen);
  335. /* The hash of the data */
  336. hash_desc->init(&hs);
  337. hash_desc->process(&hs, data_buf->data, data_buf->len);
  338. hash_desc->done(&hs, buf_getwriteptr(rsa_EM, hash_desc->hashsize));
  339. buf_incrwritepos(rsa_EM, hash_desc->hashsize);
  340. dropbear_assert(rsa_EM->pos == rsa_EM->size);
  341. /* Create the mp_int from the encoded bytes */
  342. buf_setpos(rsa_EM, 0);
  343. bytes_to_mp(rsa_em, buf_getptr(rsa_EM, rsa_EM->size),
  344. rsa_EM->size);
  345. buf_free(rsa_EM);
  346. }
  347. #endif /* DROPBEAR_RSA */