curve25519.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. /* curve25519.c
  2. *
  3. * Copyright (C) 2006-2021 wolfSSL Inc.
  4. *
  5. * This file is part of wolfSSL.
  6. *
  7. * wolfSSL is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * wolfSSL is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
  20. */
  21. /* Based On Daniel J Bernstein's curve25519 Public Domain ref10 work. */
  22. #ifdef HAVE_CONFIG_H
  23. #include <config.h>
  24. #endif
  25. #include <wolfssl/wolfcrypt/settings.h>
  26. #ifdef HAVE_CURVE25519
  27. #include <wolfssl/wolfcrypt/curve25519.h>
  28. #include <wolfssl/wolfcrypt/error-crypt.h>
  29. #ifdef NO_INLINE
  30. #include <wolfssl/wolfcrypt/misc.h>
  31. #else
  32. #define WOLFSSL_MISC_INCLUDED
  33. #include <wolfcrypt/src/misc.c>
  34. #endif
  35. #if defined(FREESCALE_LTC_ECC)
  36. #include <wolfssl/wolfcrypt/port/nxp/ksdk_port.h>
  37. #endif
  38. #ifdef WOLF_CRYPTO_CB
  39. #include <wolfssl/wolfcrypt/cryptocb.h>
  40. #endif
  41. const curve25519_set_type curve25519_sets[] = {
  42. {
  43. CURVE25519_KEYSIZE,
  44. "CURVE25519",
  45. }
  46. };
  47. static const unsigned char kCurve25519BasePoint[CURVE25519_KEYSIZE] = {9};
  48. /* Curve25519 private key must be less than order */
  49. /* These functions clamp private k and check it */
  50. static WC_INLINE int curve25519_priv_clamp(byte* priv)
  51. {
  52. priv[0] &= 248;
  53. priv[CURVE25519_KEYSIZE-1] &= 127;
  54. priv[CURVE25519_KEYSIZE-1] |= 64;
  55. return 0;
  56. }
  57. static WC_INLINE int curve25519_priv_clamp_check(const byte* priv)
  58. {
  59. /* check that private part of key has been clamped */
  60. int ret = 0;
  61. if ((priv[0] & ~248) ||
  62. (priv[CURVE25519_KEYSIZE-1] & 128)) {
  63. ret = ECC_BAD_ARG_E;
  64. }
  65. return ret;
  66. }
  67. static WC_INLINE void curve25519_copy_point(byte* out, const byte* point,
  68. int endian)
  69. {
  70. int i;
  71. if (endian == EC25519_BIG_ENDIAN) {
  72. /* put shared secret key in Big Endian format */
  73. for (i = 0; i < CURVE25519_KEYSIZE; i++) {
  74. out[i] = point[CURVE25519_KEYSIZE - i -1];
  75. }
  76. }
  77. else { /* put shared secret key in Little Endian format */
  78. XMEMCPY(out, point, CURVE25519_KEYSIZE);
  79. }
  80. }
  81. /* compute the public key from an existing private key, using bare vectors.
  82. *
  83. * return value is propagated from curve25519() (0 on success), or
  84. * ECC_BAD_ARG_E, and the byte vectors are little endian.
  85. */
  86. int wc_curve25519_make_pub(int public_size, byte* pub, int private_size,
  87. const byte* priv)
  88. {
  89. int ret;
  90. #ifdef FREESCALE_LTC_ECC
  91. const ECPoint* basepoint = nxp_ltc_curve25519_GetBasePoint();
  92. ECPoint wc_pub;
  93. #endif
  94. if ( (public_size != CURVE25519_KEYSIZE) ||
  95. (private_size != CURVE25519_KEYSIZE)) {
  96. return ECC_BAD_ARG_E;
  97. }
  98. if ((pub == NULL) || (priv == NULL)) {
  99. return ECC_BAD_ARG_E;
  100. }
  101. /* check clamping */
  102. ret = curve25519_priv_clamp_check(priv);
  103. if (ret != 0)
  104. return ret;
  105. #ifdef FREESCALE_LTC_ECC
  106. /* input basepoint on Weierstrass curve */
  107. ret = nxp_ltc_curve25519(&wc_pub, priv, basepoint, kLTC_Weierstrass);
  108. if (ret == 0) {
  109. XMEMCPY(pub, wc_pub.point, CURVE25519_KEYSIZE);
  110. }
  111. #else
  112. fe_init();
  113. SAVE_VECTOR_REGISTERS(return _svr_ret;);
  114. ret = curve25519(pub, priv, kCurve25519BasePoint);
  115. RESTORE_VECTOR_REGISTERS();
  116. #endif
  117. return ret;
  118. }
  119. /* compute the public key from an existing private key, with supplied basepoint,
  120. * using bare vectors.
  121. *
  122. * return value is propagated from curve25519() (0 on success),
  123. * and the byte vectors are little endian.
  124. */
  125. int wc_curve25519_generic(int public_size, byte* pub,
  126. int private_size, const byte* priv,
  127. int basepoint_size, const byte* basepoint)
  128. {
  129. #ifdef FREESCALE_LTC_ECC
  130. /* unsupported with NXP LTC, only supports single basepoint with
  131. * nxp_ltc_curve25519_GetBasePoint() */
  132. return WC_HW_E;
  133. #else
  134. int ret;
  135. if ((public_size != CURVE25519_KEYSIZE) ||
  136. (private_size != CURVE25519_KEYSIZE) ||
  137. (basepoint_size != CURVE25519_KEYSIZE)) {
  138. return ECC_BAD_ARG_E;
  139. }
  140. if ((pub == NULL) || (priv == NULL) || (basepoint == NULL))
  141. return ECC_BAD_ARG_E;
  142. /* check clamping */
  143. ret = curve25519_priv_clamp_check(priv);
  144. if (ret != 0)
  145. return ret;
  146. fe_init();
  147. SAVE_VECTOR_REGISTERS(return _svr_ret;);
  148. ret = curve25519(pub, priv, basepoint);
  149. RESTORE_VECTOR_REGISTERS();
  150. return ret;
  151. #endif /* FREESCALE_LTC_ECC */
  152. }
  153. /* generate a new private key, as a bare vector.
  154. *
  155. * return value is propagated from wc_RNG_GenerateBlock(() (0 on success),
  156. * or BAD_FUNC_ARG/ECC_BAD_ARG_E, and the byte vector is little endian.
  157. */
  158. int wc_curve25519_make_priv(WC_RNG* rng, int keysize, byte* key)
  159. {
  160. int ret;
  161. if (key == NULL || rng == NULL)
  162. return BAD_FUNC_ARG;
  163. /* currently only a key size of 32 bytes is used */
  164. if (keysize != CURVE25519_KEYSIZE)
  165. return ECC_BAD_ARG_E;
  166. /* random number for private key */
  167. ret = wc_RNG_GenerateBlock(rng, key, keysize);
  168. if (ret == 0) {
  169. /* Clamp the private key */
  170. ret = curve25519_priv_clamp(key);
  171. }
  172. return ret;
  173. }
  174. /* generate a new keypair.
  175. *
  176. * return value is propagated from wc_curve25519_make_private() or
  177. * wc_curve25519_make_pub() (0 on success).
  178. */
  179. int wc_curve25519_make_key(WC_RNG* rng, int keysize, curve25519_key* key)
  180. {
  181. int ret;
  182. if (key == NULL || rng == NULL)
  183. return BAD_FUNC_ARG;
  184. #ifdef WOLF_CRYPTO_CB
  185. if (key->devId != INVALID_DEVID) {
  186. ret = wc_CryptoCb_Curve25519Gen(rng, keysize, key);
  187. if (ret != CRYPTOCB_UNAVAILABLE)
  188. return ret;
  189. /* fall-through when unavailable */
  190. }
  191. #endif
  192. ret = wc_curve25519_make_priv(rng, keysize, key->k);
  193. if (ret == 0) {
  194. key->privSet = 1;
  195. ret = wc_curve25519_make_pub((int)sizeof(key->p.point), key->p.point,
  196. (int)sizeof(key->k), key->k);
  197. key->pubSet = (ret == 0);
  198. }
  199. return ret;
  200. }
  201. #ifdef HAVE_CURVE25519_SHARED_SECRET
  202. int wc_curve25519_shared_secret(curve25519_key* private_key,
  203. curve25519_key* public_key,
  204. byte* out, word32* outlen)
  205. {
  206. return wc_curve25519_shared_secret_ex(private_key, public_key,
  207. out, outlen, EC25519_BIG_ENDIAN);
  208. }
  209. int wc_curve25519_shared_secret_ex(curve25519_key* private_key,
  210. curve25519_key* public_key,
  211. byte* out, word32* outlen, int endian)
  212. {
  213. ECPoint o;
  214. int ret = 0;
  215. /* sanity check */
  216. if (private_key == NULL || public_key == NULL ||
  217. out == NULL || outlen == NULL || *outlen < CURVE25519_KEYSIZE) {
  218. return BAD_FUNC_ARG;
  219. }
  220. /* make sure we have a populated private and public key */
  221. if (!private_key->privSet || !public_key->pubSet) {
  222. return ECC_BAD_ARG_E;
  223. }
  224. /* avoid implementation fingerprinting - make sure signed bit is not set */
  225. if (public_key->p.point[CURVE25519_KEYSIZE-1] & 0x80) {
  226. return ECC_BAD_ARG_E;
  227. }
  228. XMEMSET(&o, 0, sizeof(o));
  229. #ifdef WOLF_CRYPTO_CB
  230. if (private_key->devId != INVALID_DEVID) {
  231. ret = wc_CryptoCb_Curve25519(private_key, public_key, out, outlen,
  232. endian);
  233. if (ret != CRYPTOCB_UNAVAILABLE)
  234. return ret;
  235. /* fall-through when unavailable */
  236. }
  237. #endif
  238. #ifdef FREESCALE_LTC_ECC
  239. /* input point P on Curve25519 */
  240. ret = nxp_ltc_curve25519(&o, private_key->k, &public_key->p,
  241. kLTC_Curve25519);
  242. #else
  243. SAVE_VECTOR_REGISTERS(return _svr_ret;);
  244. ret = curve25519(o.point, private_key->k, public_key->p.point);
  245. RESTORE_VECTOR_REGISTERS();
  246. #endif
  247. if (ret != 0) {
  248. ForceZero(&o, sizeof(o));
  249. return ret;
  250. }
  251. curve25519_copy_point(out, o.point, endian);
  252. *outlen = CURVE25519_KEYSIZE;
  253. ForceZero(&o, sizeof(o));
  254. return ret;
  255. }
  256. #endif /* HAVE_CURVE25519_SHARED_SECRET */
  257. #ifdef HAVE_CURVE25519_KEY_EXPORT
  258. /* export curve25519 public key (Big endian)
  259. * return 0 on success */
  260. int wc_curve25519_export_public(curve25519_key* key, byte* out, word32* outLen)
  261. {
  262. return wc_curve25519_export_public_ex(key, out, outLen, EC25519_BIG_ENDIAN);
  263. }
  264. /* export curve25519 public key (Big or Little endian)
  265. * return 0 on success */
  266. int wc_curve25519_export_public_ex(curve25519_key* key, byte* out,
  267. word32* outLen, int endian)
  268. {
  269. int ret = 0;
  270. if (key == NULL || out == NULL || outLen == NULL) {
  271. return BAD_FUNC_ARG;
  272. }
  273. /* check and set outgoing key size */
  274. if (*outLen < CURVE25519_KEYSIZE) {
  275. *outLen = CURVE25519_KEYSIZE;
  276. return ECC_BAD_ARG_E;
  277. }
  278. /* calculate public if missing */
  279. if (!key->pubSet) {
  280. ret = wc_curve25519_make_pub((int)sizeof(key->p.point), key->p.point,
  281. (int)sizeof(key->k), key->k);
  282. key->pubSet = (ret == 0);
  283. }
  284. /* export public point with endianess */
  285. curve25519_copy_point(out, key->p.point, endian);
  286. *outLen = CURVE25519_KEYSIZE;
  287. return ret;
  288. }
  289. #endif /* HAVE_CURVE25519_KEY_EXPORT */
  290. #ifdef HAVE_CURVE25519_KEY_IMPORT
  291. /* import curve25519 public key (Big endian)
  292. * return 0 on success */
  293. int wc_curve25519_import_public(const byte* in, word32 inLen,
  294. curve25519_key* key)
  295. {
  296. return wc_curve25519_import_public_ex(in, inLen, key, EC25519_BIG_ENDIAN);
  297. }
  298. /* import curve25519 public key (Big or Little endian)
  299. * return 0 on success */
  300. int wc_curve25519_import_public_ex(const byte* in, word32 inLen,
  301. curve25519_key* key, int endian)
  302. {
  303. #ifdef FREESCALE_LTC_ECC
  304. ltc_pkha_ecc_point_t ltcPoint;
  305. #endif
  306. /* sanity check */
  307. if (key == NULL || in == NULL) {
  308. return BAD_FUNC_ARG;
  309. }
  310. /* check size of incoming keys */
  311. if (inLen != CURVE25519_KEYSIZE) {
  312. return ECC_BAD_ARG_E;
  313. }
  314. /* import public point with endianess */
  315. curve25519_copy_point(key->p.point, in, endian);
  316. key->pubSet = 1;
  317. key->dp = &curve25519_sets[0];
  318. /* LTC needs also Y coordinate - let's compute it */
  319. #ifdef FREESCALE_LTC_ECC
  320. ltcPoint.X = &key->p.point[0];
  321. ltcPoint.Y = &key->p.pointY[0];
  322. LTC_PKHA_Curve25519ComputeY(&ltcPoint);
  323. #endif
  324. return 0;
  325. }
  326. /* Check the public key value (big or little endian)
  327. *
  328. * pub Public key bytes.
  329. * pubSz Size of public key in bytes.
  330. * endian Public key bytes passed in as big-endian or little-endian.
  331. * returns BAD_FUNC_ARGS when pub is NULL,
  332. * BUFFER_E when size of public key is zero;
  333. * ECC_OUT_OF_RANGE_E if the high bit is set;
  334. * ECC_BAD_ARG_E if key length is not 32 bytes, public key value is
  335. * zero or one; and
  336. * 0 otherwise.
  337. */
  338. int wc_curve25519_check_public(const byte* pub, word32 pubSz, int endian)
  339. {
  340. word32 i;
  341. if (pub == NULL)
  342. return BAD_FUNC_ARG;
  343. /* Check for empty key data */
  344. if (pubSz == 0)
  345. return BUFFER_E;
  346. /* Check key length */
  347. if (pubSz != CURVE25519_KEYSIZE)
  348. return ECC_BAD_ARG_E;
  349. if (endian == EC25519_LITTLE_ENDIAN) {
  350. /* Check for value of zero or one */
  351. for (i = pubSz - 1; i > 0; i--) {
  352. if (pub[i] != 0)
  353. break;
  354. }
  355. if (i == 0 && (pub[0] == 0 || pub[0] == 1))
  356. return ECC_BAD_ARG_E;
  357. /* Check high bit set */
  358. if (pub[CURVE25519_KEYSIZE-1] & 0x80)
  359. return ECC_OUT_OF_RANGE_E;
  360. }
  361. else {
  362. /* Check for value of zero or one */
  363. for (i = 0; i < pubSz-1; i++) {
  364. if (pub[i] != 0)
  365. break;
  366. }
  367. if (i == pubSz - 1 && (pub[i] == 0 || pub[i] == 1))
  368. return ECC_BAD_ARG_E;
  369. /* Check high bit set */
  370. if (pub[0] & 0x80)
  371. return ECC_OUT_OF_RANGE_E;
  372. }
  373. return 0;
  374. }
  375. #endif /* HAVE_CURVE25519_KEY_IMPORT */
  376. #ifdef HAVE_CURVE25519_KEY_EXPORT
  377. /* export curve25519 private key only raw (Big endian)
  378. * outLen is in/out size
  379. * return 0 on success */
  380. int wc_curve25519_export_private_raw(curve25519_key* key, byte* out,
  381. word32* outLen)
  382. {
  383. return wc_curve25519_export_private_raw_ex(key, out, outLen,
  384. EC25519_BIG_ENDIAN);
  385. }
  386. /* export curve25519 private key only raw (Big or Little endian)
  387. * outLen is in/out size
  388. * return 0 on success */
  389. int wc_curve25519_export_private_raw_ex(curve25519_key* key, byte* out,
  390. word32* outLen, int endian)
  391. {
  392. /* sanity check */
  393. if (key == NULL || out == NULL || outLen == NULL)
  394. return BAD_FUNC_ARG;
  395. /* check size of outgoing buffer */
  396. if (*outLen < CURVE25519_KEYSIZE) {
  397. *outLen = CURVE25519_KEYSIZE;
  398. return ECC_BAD_ARG_E;
  399. }
  400. /* export private scalar with endianess */
  401. curve25519_copy_point(out, key->k, endian);
  402. *outLen = CURVE25519_KEYSIZE;
  403. return 0;
  404. }
  405. /* curve25519 key pair export (Big or Little endian)
  406. * return 0 on success */
  407. int wc_curve25519_export_key_raw(curve25519_key* key,
  408. byte* priv, word32 *privSz,
  409. byte* pub, word32 *pubSz)
  410. {
  411. return wc_curve25519_export_key_raw_ex(key, priv, privSz,
  412. pub, pubSz, EC25519_BIG_ENDIAN);
  413. }
  414. /* curve25519 key pair export (Big or Little endian)
  415. * return 0 on success */
  416. int wc_curve25519_export_key_raw_ex(curve25519_key* key,
  417. byte* priv, word32 *privSz,
  418. byte* pub, word32 *pubSz,
  419. int endian)
  420. {
  421. int ret;
  422. /* export private part */
  423. ret = wc_curve25519_export_private_raw_ex(key, priv, privSz, endian);
  424. if (ret != 0)
  425. return ret;
  426. /* export public part */
  427. return wc_curve25519_export_public_ex(key, pub, pubSz, endian);
  428. }
  429. #endif /* HAVE_CURVE25519_KEY_EXPORT */
  430. #ifdef HAVE_CURVE25519_KEY_IMPORT
  431. /* curve25519 private key import (Big endian)
  432. * Public key to match private key needs to be imported too
  433. * return 0 on success */
  434. int wc_curve25519_import_private_raw(const byte* priv, word32 privSz,
  435. const byte* pub, word32 pubSz,
  436. curve25519_key* key)
  437. {
  438. return wc_curve25519_import_private_raw_ex(priv, privSz, pub, pubSz,
  439. key, EC25519_BIG_ENDIAN);
  440. }
  441. /* curve25519 private key import (Big or Little endian)
  442. * Public key to match private key needs to be imported too
  443. * return 0 on success */
  444. int wc_curve25519_import_private_raw_ex(const byte* priv, word32 privSz,
  445. const byte* pub, word32 pubSz,
  446. curve25519_key* key, int endian)
  447. {
  448. int ret;
  449. /* import private part */
  450. ret = wc_curve25519_import_private_ex(priv, privSz, key, endian);
  451. if (ret != 0)
  452. return ret;
  453. /* import public part */
  454. return wc_curve25519_import_public_ex(pub, pubSz, key, endian);
  455. }
  456. /* curve25519 private key import only. (Big endian)
  457. * return 0 on success */
  458. int wc_curve25519_import_private(const byte* priv, word32 privSz,
  459. curve25519_key* key)
  460. {
  461. return wc_curve25519_import_private_ex(priv, privSz,
  462. key, EC25519_BIG_ENDIAN);
  463. }
  464. /* curve25519 private key import only. (Big or Little endian)
  465. * return 0 on success */
  466. int wc_curve25519_import_private_ex(const byte* priv, word32 privSz,
  467. curve25519_key* key, int endian)
  468. {
  469. /* sanity check */
  470. if (key == NULL || priv == NULL) {
  471. return BAD_FUNC_ARG;
  472. }
  473. /* check size of incoming keys */
  474. if ((int)privSz != CURVE25519_KEYSIZE) {
  475. return ECC_BAD_ARG_E;
  476. }
  477. /* import private scalar with endianess */
  478. curve25519_copy_point(key->k, priv, endian);
  479. key->privSet = 1;
  480. key->dp = &curve25519_sets[0];
  481. /* Clamp the key */
  482. return curve25519_priv_clamp(key->k);
  483. }
  484. #endif /* HAVE_CURVE25519_KEY_IMPORT */
  485. int wc_curve25519_init_ex(curve25519_key* key, void* heap, int devId)
  486. {
  487. if (key == NULL)
  488. return BAD_FUNC_ARG;
  489. XMEMSET(key, 0, sizeof(*key));
  490. /* currently the format for curve25519 */
  491. key->dp = &curve25519_sets[0];
  492. #ifdef WOLF_CRYPTO_CB
  493. key->devId = devId;
  494. #else
  495. (void)devId;
  496. #endif
  497. (void)heap; /* if needed for XMALLOC/XFREE in future */
  498. #ifndef FREESCALE_LTC_ECC
  499. fe_init();
  500. #endif
  501. return 0;
  502. }
  503. int wc_curve25519_init(curve25519_key* key)
  504. {
  505. return wc_curve25519_init_ex(key, NULL, INVALID_DEVID);
  506. }
  507. /* Clean the memory of a key */
  508. void wc_curve25519_free(curve25519_key* key)
  509. {
  510. if (key == NULL)
  511. return;
  512. key->dp = NULL;
  513. ForceZero(key->k, sizeof(key->k));
  514. XMEMSET(&key->p, 0, sizeof(key->p));
  515. key->pubSet = 0;
  516. key->privSet = 0;
  517. }
  518. /* get key size */
  519. int wc_curve25519_size(curve25519_key* key)
  520. {
  521. if (key == NULL)
  522. return 0;
  523. return key->dp->size;
  524. }
  525. #endif /*HAVE_CURVE25519*/