ecdsa.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. #include "options.h"
  2. #include "includes.h"
  3. #include "dbutil.h"
  4. #include "crypto_desc.h"
  5. #include "ecc.h"
  6. #include "ecdsa.h"
  7. #include "signkey.h"
  8. #ifdef DROPBEAR_ECDSA
  9. int signkey_is_ecdsa(enum signkey_type type)
  10. {
  11. return type == DROPBEAR_SIGNKEY_ECDSA_NISTP256
  12. || type == DROPBEAR_SIGNKEY_ECDSA_NISTP384
  13. || type == DROPBEAR_SIGNKEY_ECDSA_NISTP521;
  14. }
  15. enum signkey_type ecdsa_signkey_type(ecc_key * key) {
  16. #ifdef DROPBEAR_ECC_256
  17. if (key->dp == ecc_curve_nistp256.dp) {
  18. return DROPBEAR_SIGNKEY_ECDSA_NISTP256;
  19. }
  20. #endif
  21. #ifdef DROPBEAR_ECC_384
  22. if (key->dp == ecc_curve_nistp384.dp) {
  23. return DROPBEAR_SIGNKEY_ECDSA_NISTP384;
  24. }
  25. #endif
  26. #ifdef DROPBEAR_ECC_521
  27. if (key->dp == ecc_curve_nistp521.dp) {
  28. return DROPBEAR_SIGNKEY_ECDSA_NISTP521;
  29. }
  30. #endif
  31. return DROPBEAR_SIGNKEY_NONE;
  32. }
  33. ecc_key *gen_ecdsa_priv_key(unsigned int bit_size) {
  34. const ltc_ecc_set_type *dp = NULL; /* curve domain parameters */
  35. ecc_key *new_key = NULL;
  36. switch (bit_size) {
  37. #ifdef DROPBEAR_ECC_256
  38. case 256:
  39. dp = ecc_curve_nistp256.dp;
  40. break;
  41. #endif
  42. #ifdef DROPBEAR_ECC_384
  43. case 384:
  44. dp = ecc_curve_nistp384.dp;
  45. break;
  46. #endif
  47. #ifdef DROPBEAR_ECC_521
  48. case 521:
  49. dp = ecc_curve_nistp521.dp;
  50. break;
  51. #endif
  52. }
  53. if (!dp) {
  54. dropbear_exit("Key size %d isn't valid. Try "
  55. #ifdef DROPBEAR_ECC_256
  56. "256 "
  57. #endif
  58. #ifdef DROPBEAR_ECC_384
  59. "384 "
  60. #endif
  61. #ifdef DROPBEAR_ECC_521
  62. "521 "
  63. #endif
  64. , bit_size);
  65. }
  66. new_key = m_malloc(sizeof(*new_key));
  67. if (ecc_make_key_ex(NULL, dropbear_ltc_prng, new_key, dp) != CRYPT_OK) {
  68. dropbear_exit("ECC error");
  69. }
  70. return new_key;
  71. }
  72. ecc_key *buf_get_ecdsa_pub_key(buffer* buf) {
  73. unsigned char *key_ident = NULL, *identifier = NULL;
  74. unsigned int key_ident_len, identifier_len;
  75. buffer *q_buf = NULL;
  76. struct dropbear_ecc_curve **curve;
  77. ecc_key *new_key = NULL;
  78. /* string "ecdsa-sha2-[identifier]" */
  79. key_ident = (unsigned char*)buf_getstring(buf, &key_ident_len);
  80. /* string "[identifier]" */
  81. identifier = (unsigned char*)buf_getstring(buf, &identifier_len);
  82. if (key_ident_len != identifier_len + strlen("ecdsa-sha2-")) {
  83. TRACE(("Bad identifier lengths"))
  84. goto out;
  85. }
  86. if (memcmp(&key_ident[strlen("ecdsa-sha2-")], identifier, identifier_len) != 0) {
  87. TRACE(("mismatching identifiers"))
  88. goto out;
  89. }
  90. for (curve = dropbear_ecc_curves; *curve; curve++) {
  91. if (memcmp(identifier, (char*)(*curve)->name, strlen((char*)(*curve)->name)) == 0) {
  92. break;
  93. }
  94. }
  95. if (!*curve) {
  96. TRACE(("couldn't match ecc curve"))
  97. goto out;
  98. }
  99. /* string Q */
  100. q_buf = buf_getstringbuf(buf);
  101. new_key = buf_get_ecc_raw_pubkey(q_buf, *curve);
  102. out:
  103. m_free(key_ident);
  104. m_free(identifier);
  105. if (q_buf) {
  106. buf_free(q_buf);
  107. q_buf = NULL;
  108. }
  109. TRACE(("leave buf_get_ecdsa_pub_key"))
  110. return new_key;
  111. }
  112. ecc_key *buf_get_ecdsa_priv_key(buffer *buf) {
  113. ecc_key *new_key = NULL;
  114. TRACE(("enter buf_get_ecdsa_priv_key"))
  115. new_key = buf_get_ecdsa_pub_key(buf);
  116. if (!new_key) {
  117. return NULL;
  118. }
  119. if (buf_getmpint(buf, new_key->k) != DROPBEAR_SUCCESS) {
  120. ecc_free(new_key);
  121. m_free(new_key);
  122. return NULL;
  123. }
  124. return new_key;
  125. }
  126. void buf_put_ecdsa_pub_key(buffer *buf, ecc_key *key) {
  127. struct dropbear_ecc_curve *curve = NULL;
  128. char key_ident[30];
  129. curve = curve_for_dp(key->dp);
  130. snprintf(key_ident, sizeof(key_ident), "ecdsa-sha2-%s", curve->name);
  131. buf_putstring(buf, key_ident, strlen(key_ident));
  132. buf_putstring(buf, curve->name, strlen(curve->name));
  133. buf_put_ecc_raw_pubkey_string(buf, key);
  134. }
  135. void buf_put_ecdsa_priv_key(buffer *buf, ecc_key *key) {
  136. buf_put_ecdsa_pub_key(buf, key);
  137. buf_putmpint(buf, key->k);
  138. }
  139. void buf_put_ecdsa_sign(buffer *buf, ecc_key *key, buffer *data_buf) {
  140. /* Based on libtomcrypt's ecc_sign_hash but without the asn1 */
  141. int err = DROPBEAR_FAILURE;
  142. struct dropbear_ecc_curve *curve = NULL;
  143. hash_state hs;
  144. unsigned char hash[64];
  145. void *e = NULL, *p = NULL, *s = NULL, *r;
  146. char key_ident[30];
  147. buffer *sigbuf = NULL;
  148. TRACE(("buf_put_ecdsa_sign"))
  149. curve = curve_for_dp(key->dp);
  150. if (ltc_init_multi(&r, &s, &p, &e, NULL) != CRYPT_OK) {
  151. goto out;
  152. }
  153. curve->hash_desc->init(&hs);
  154. curve->hash_desc->process(&hs, data_buf->data, data_buf->len);
  155. curve->hash_desc->done(&hs, hash);
  156. if (ltc_mp.unsigned_read(e, hash, curve->hash_desc->hashsize) != CRYPT_OK) {
  157. goto out;
  158. }
  159. if (ltc_mp.read_radix(p, (char *)key->dp->order, 16) != CRYPT_OK) {
  160. goto out;
  161. }
  162. for (;;) {
  163. ecc_key R_key; /* ephemeral key */
  164. if (ecc_make_key_ex(NULL, dropbear_ltc_prng, &R_key, key->dp) != CRYPT_OK) {
  165. goto out;
  166. }
  167. if (ltc_mp.mpdiv(R_key.pubkey.x, p, NULL, r) != CRYPT_OK) {
  168. goto out;
  169. }
  170. if (ltc_mp.compare_d(r, 0) == LTC_MP_EQ) {
  171. /* try again */
  172. ecc_free(&R_key);
  173. continue;
  174. }
  175. /* k = 1/k */
  176. if (ltc_mp.invmod(R_key.k, p, R_key.k) != CRYPT_OK) {
  177. goto out;
  178. }
  179. /* s = xr */
  180. if (ltc_mp.mulmod(key->k, r, p, s) != CRYPT_OK) {
  181. goto out;
  182. }
  183. /* s = e + xr */
  184. if (ltc_mp.add(e, s, s) != CRYPT_OK) {
  185. goto out;
  186. }
  187. if (ltc_mp.mpdiv(s, p, NULL, s) != CRYPT_OK) {
  188. goto out;
  189. }
  190. /* s = (e + xr)/k */
  191. if (ltc_mp.mulmod(s, R_key.k, p, s) != CRYPT_OK) {
  192. goto out;
  193. }
  194. ecc_free(&R_key);
  195. if (ltc_mp.compare_d(s, 0) != LTC_MP_EQ) {
  196. break;
  197. }
  198. }
  199. snprintf(key_ident, sizeof(key_ident), "ecdsa-sha2-%s", curve->name);
  200. buf_putstring(buf, key_ident, strlen(key_ident));
  201. /* enough for nistp521 */
  202. sigbuf = buf_new(200);
  203. buf_putmpint(sigbuf, (mp_int*)r);
  204. buf_putmpint(sigbuf, (mp_int*)s);
  205. buf_putbufstring(buf, sigbuf);
  206. err = DROPBEAR_SUCCESS;
  207. out:
  208. if (r && s && p && e) {
  209. ltc_deinit_multi(r, s, p, e, NULL);
  210. }
  211. if (sigbuf) {
  212. buf_free(sigbuf);
  213. }
  214. if (err == DROPBEAR_FAILURE) {
  215. dropbear_exit("ECC error");
  216. }
  217. }
  218. /* returns values in s and r
  219. returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
  220. static int buf_get_ecdsa_verify_params(buffer *buf,
  221. void *r, void* s) {
  222. int ret = DROPBEAR_FAILURE;
  223. unsigned int sig_len;
  224. unsigned int sig_pos;
  225. sig_len = buf_getint(buf);
  226. sig_pos = buf->pos;
  227. if (buf_getmpint(buf, r) != DROPBEAR_SUCCESS) {
  228. goto out;
  229. }
  230. if (buf_getmpint(buf, s) != DROPBEAR_SUCCESS) {
  231. goto out;
  232. }
  233. if (buf->pos - sig_pos != sig_len) {
  234. goto out;
  235. }
  236. ret = DROPBEAR_SUCCESS;
  237. out:
  238. return ret;
  239. }
  240. int buf_ecdsa_verify(buffer *buf, ecc_key *key, buffer *data_buf) {
  241. /* Based on libtomcrypt's ecc_verify_hash but without the asn1 */
  242. int ret = DROPBEAR_FAILURE;
  243. hash_state hs;
  244. struct dropbear_ecc_curve *curve = NULL;
  245. unsigned char hash[64];
  246. ecc_point *mG = NULL, *mQ = NULL;
  247. void *r = NULL, *s = NULL, *v = NULL, *w = NULL, *u1 = NULL, *u2 = NULL,
  248. *e = NULL, *p = NULL, *m = NULL;
  249. void *mp = NULL;
  250. /* verify
  251. *
  252. * w = s^-1 mod n
  253. * u1 = xw
  254. * u2 = rw
  255. * X = u1*G + u2*Q
  256. * v = X_x1 mod n
  257. * accept if v == r
  258. */
  259. TRACE(("buf_ecdsa_verify"))
  260. curve = curve_for_dp(key->dp);
  261. mG = ltc_ecc_new_point();
  262. mQ = ltc_ecc_new_point();
  263. if (ltc_init_multi(&r, &s, &v, &w, &u1, &u2, &p, &e, &m, NULL) != CRYPT_OK
  264. || !mG
  265. || !mQ) {
  266. dropbear_exit("ECC error");
  267. }
  268. if (buf_get_ecdsa_verify_params(buf, r, s) != DROPBEAR_SUCCESS) {
  269. goto out;
  270. }
  271. curve->hash_desc->init(&hs);
  272. curve->hash_desc->process(&hs, data_buf->data, data_buf->len);
  273. curve->hash_desc->done(&hs, hash);
  274. if (ltc_mp.unsigned_read(e, hash, curve->hash_desc->hashsize) != CRYPT_OK) {
  275. goto out;
  276. }
  277. /* get the order */
  278. if (ltc_mp.read_radix(p, (char *)key->dp->order, 16) != CRYPT_OK) {
  279. goto out;
  280. }
  281. /* get the modulus */
  282. if (ltc_mp.read_radix(m, (char *)key->dp->prime, 16) != CRYPT_OK) {
  283. goto out;
  284. }
  285. /* check for zero */
  286. if (ltc_mp.compare_d(r, 0) == LTC_MP_EQ
  287. || ltc_mp.compare_d(s, 0) == LTC_MP_EQ
  288. || ltc_mp.compare(r, p) != LTC_MP_LT
  289. || ltc_mp.compare(s, p) != LTC_MP_LT) {
  290. goto out;
  291. }
  292. /* w = s^-1 mod n */
  293. if (ltc_mp.invmod(s, p, w) != CRYPT_OK) {
  294. goto out;
  295. }
  296. /* u1 = ew */
  297. if (ltc_mp.mulmod(e, w, p, u1) != CRYPT_OK) {
  298. goto out;
  299. }
  300. /* u2 = rw */
  301. if (ltc_mp.mulmod(r, w, p, u2) != CRYPT_OK) {
  302. goto out;
  303. }
  304. /* find mG and mQ */
  305. if (ltc_mp.read_radix(mG->x, (char *)key->dp->Gx, 16) != CRYPT_OK) {
  306. goto out;
  307. }
  308. if (ltc_mp.read_radix(mG->y, (char *)key->dp->Gy, 16) != CRYPT_OK) {
  309. goto out;
  310. }
  311. if (ltc_mp.set_int(mG->z, 1) != CRYPT_OK) {
  312. goto out;
  313. }
  314. if (ltc_mp.copy(key->pubkey.x, mQ->x) != CRYPT_OK
  315. || ltc_mp.copy(key->pubkey.y, mQ->y) != CRYPT_OK
  316. || ltc_mp.copy(key->pubkey.z, mQ->z) != CRYPT_OK) {
  317. goto out;
  318. }
  319. /* compute u1*mG + u2*mQ = mG */
  320. if (ltc_mp.ecc_mul2add == NULL) {
  321. if (ltc_mp.ecc_ptmul(u1, mG, mG, m, 0) != CRYPT_OK) {
  322. goto out;
  323. }
  324. if (ltc_mp.ecc_ptmul(u2, mQ, mQ, m, 0) != CRYPT_OK) {
  325. goto out;
  326. }
  327. /* find the montgomery mp */
  328. if (ltc_mp.montgomery_setup(m, &mp) != CRYPT_OK) {
  329. goto out;
  330. }
  331. /* add them */
  332. if (ltc_mp.ecc_ptadd(mQ, mG, mG, m, mp) != CRYPT_OK) {
  333. goto out;
  334. }
  335. /* reduce */
  336. if (ltc_mp.ecc_map(mG, m, mp) != CRYPT_OK) {
  337. goto out;
  338. }
  339. } else {
  340. /* use Shamir's trick to compute u1*mG + u2*mQ using half of the doubles */
  341. if (ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, m) != CRYPT_OK) {
  342. goto out;
  343. }
  344. }
  345. /* v = X_x1 mod n */
  346. if (ltc_mp.mpdiv(mG->x, p, NULL, v) != CRYPT_OK) {
  347. goto out;
  348. }
  349. /* does v == r */
  350. if (ltc_mp.compare(v, r) == LTC_MP_EQ) {
  351. ret = DROPBEAR_SUCCESS;
  352. }
  353. out:
  354. ltc_ecc_del_point(mG);
  355. ltc_ecc_del_point(mQ);
  356. ltc_deinit_multi(r, s, v, w, u1, u2, p, e, m, NULL);
  357. if (mp != NULL) {
  358. ltc_mp.montgomery_deinit(mp);
  359. }
  360. return ret;
  361. }
  362. #endif /* DROPBEAR_ECDSA */