crypto_ecc.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2012, 2013, 2015 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file util/crypto_ecc.c
  18. * @brief public key cryptography (ECC) with libgcrypt
  19. * @author Christian Grothoff
  20. * @author Florian Dold
  21. */
  22. #include "platform.h"
  23. #include <gcrypt.h>
  24. #include <sodium.h>
  25. #include "gnunet_crypto_lib.h"
  26. #include "gnunet_strings_lib.h"
  27. #include "benchmark.h"
  28. #define EXTRA_CHECKS 0
  29. /**
  30. * IMPLEMENTATION NOTICE:
  31. *
  32. * ECDSA: We use a non-standard curve for ECDSA: Ed25519.
  33. * For performance reasons, we use cryptographic operations from
  34. * libsodium wherever we can get away with it, even though libsodium
  35. * itself does not support ECDSA.
  36. * This is why the sign and verifiy functionality from libgcrypt is
  37. * required and used.
  38. *
  39. * EdDSA: We use a standard EdDSA construction.
  40. * (We still use libgcrypt for hashing and RNG, but not EC)
  41. *
  42. * ECDHE: For both EdDSA and ECDSA keys, we use libsodium for
  43. * ECDHE due to performance benefits over libgcrypt.
  44. */
  45. /**
  46. * Name of the curve we are using. Note that we have hard-coded
  47. * structs that use 256 bits, so using a bigger curve will require
  48. * changes that break stuff badly. The name of the curve given here
  49. * must be agreed by all peers and be supported by libgcrypt.
  50. */
  51. #define CURVE "Ed25519"
  52. #define LOG(kind, ...) GNUNET_log_from (kind, "util-crypto-ecc", __VA_ARGS__)
  53. #define LOG_STRERROR(kind, syscall) \
  54. GNUNET_log_from_strerror (kind, "util-crypto-ecc", syscall)
  55. #define LOG_STRERROR_FILE(kind, syscall, filename) \
  56. GNUNET_log_from_strerror_file (kind, "util-crypto-ecc", syscall, filename)
  57. /**
  58. * Log an error message at log-level 'level' that indicates
  59. * a failure of the command 'cmd' with the message given
  60. * by gcry_strerror(rc).
  61. */
  62. #define LOG_GCRY(level, cmd, rc) \
  63. do \
  64. { \
  65. LOG (level, \
  66. _ ("`%s' failed at %s:%d with error: %s\n"), \
  67. cmd, \
  68. __FILE__, \
  69. __LINE__, \
  70. gcry_strerror (rc)); \
  71. } while (0)
  72. /**
  73. * Extract values from an S-expression.
  74. *
  75. * @param array where to store the result(s)
  76. * @param sexp S-expression to parse
  77. * @param topname top-level name in the S-expression that is of interest
  78. * @param elems names of the elements to extract
  79. * @return 0 on success
  80. */
  81. static int
  82. key_from_sexp (gcry_mpi_t *array,
  83. gcry_sexp_t sexp,
  84. const char *topname,
  85. const char *elems)
  86. {
  87. gcry_sexp_t list;
  88. gcry_sexp_t l2;
  89. unsigned int idx;
  90. list = gcry_sexp_find_token (sexp, topname, 0);
  91. if (! list)
  92. return 1;
  93. l2 = gcry_sexp_cadr (list);
  94. gcry_sexp_release (list);
  95. list = l2;
  96. if (! list)
  97. return 2;
  98. idx = 0;
  99. for (const char *s = elems; *s; s++, idx++)
  100. {
  101. l2 = gcry_sexp_find_token (list, s, 1);
  102. if (! l2)
  103. {
  104. for (unsigned int i = 0; i < idx; i++)
  105. {
  106. gcry_free (array[i]);
  107. array[i] = NULL;
  108. }
  109. gcry_sexp_release (list);
  110. return 3; /* required parameter not found */
  111. }
  112. array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
  113. gcry_sexp_release (l2);
  114. if (! array[idx])
  115. {
  116. for (unsigned int i = 0; i < idx; i++)
  117. {
  118. gcry_free (array[i]);
  119. array[i] = NULL;
  120. }
  121. gcry_sexp_release (list);
  122. return 4; /* required parameter is invalid */
  123. }
  124. }
  125. gcry_sexp_release (list);
  126. return 0;
  127. }
  128. /**
  129. * Convert the given private key from the network format to the
  130. * S-expression that can be used by libgcrypt.
  131. *
  132. * @param priv private key to decode
  133. * @return NULL on error
  134. */
  135. static gcry_sexp_t
  136. decode_private_ecdsa_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
  137. {
  138. gcry_sexp_t result;
  139. int rc;
  140. uint8_t d[32];
  141. for (size_t i = 0; i<32; i++)
  142. d[i] = priv->d[31 - i];
  143. rc = gcry_sexp_build (&result,
  144. NULL,
  145. "(private-key(ecc(curve \"" CURVE "\")"
  146. "(d %b)))",
  147. 32,
  148. d);
  149. if (0 != rc)
  150. {
  151. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
  152. GNUNET_assert (0);
  153. }
  154. #if EXTRA_CHECKS
  155. if (0 != (rc = gcry_pk_testkey (result)))
  156. {
  157. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
  158. GNUNET_assert (0);
  159. }
  160. #endif
  161. return result;
  162. }
  163. void
  164. GNUNET_CRYPTO_ecdsa_key_get_public (
  165. const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
  166. struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
  167. {
  168. BENCHMARK_START (ecdsa_key_get_public);
  169. crypto_scalarmult_ed25519_base_noclamp (pub->q_y, priv->d);
  170. BENCHMARK_END (ecdsa_key_get_public);
  171. }
  172. void
  173. GNUNET_CRYPTO_eddsa_key_get_public (
  174. const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
  175. struct GNUNET_CRYPTO_EddsaPublicKey *pub)
  176. {
  177. unsigned char pk[crypto_sign_PUBLICKEYBYTES];
  178. unsigned char sk[crypto_sign_SECRETKEYBYTES];
  179. BENCHMARK_START (eddsa_key_get_public);
  180. GNUNET_assert (0 == crypto_sign_seed_keypair (pk, sk, priv->d));
  181. GNUNET_memcpy (pub->q_y, pk, crypto_sign_PUBLICKEYBYTES);
  182. sodium_memzero (sk, crypto_sign_SECRETKEYBYTES);
  183. BENCHMARK_END (eddsa_key_get_public);
  184. }
  185. void
  186. GNUNET_CRYPTO_ecdhe_key_get_public (
  187. const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
  188. struct GNUNET_CRYPTO_EcdhePublicKey *pub)
  189. {
  190. BENCHMARK_START (ecdhe_key_get_public);
  191. GNUNET_assert (0 == crypto_scalarmult_base (pub->q_y, priv->d));
  192. BENCHMARK_END (ecdhe_key_get_public);
  193. }
  194. char *
  195. GNUNET_CRYPTO_ecdsa_public_key_to_string (
  196. const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
  197. {
  198. char *pubkeybuf;
  199. size_t keylen = (sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
  200. char *end;
  201. if (keylen % 5 > 0)
  202. keylen += 5 - keylen % 5;
  203. keylen /= 5;
  204. pubkeybuf = GNUNET_malloc (keylen + 1);
  205. end =
  206. GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
  207. sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey),
  208. pubkeybuf,
  209. keylen);
  210. if (NULL == end)
  211. {
  212. GNUNET_free (pubkeybuf);
  213. return NULL;
  214. }
  215. *end = '\0';
  216. return pubkeybuf;
  217. }
  218. char *
  219. GNUNET_CRYPTO_eddsa_public_key_to_string (
  220. const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
  221. {
  222. char *pubkeybuf;
  223. size_t keylen = (sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
  224. char *end;
  225. if (keylen % 5 > 0)
  226. keylen += 5 - keylen % 5;
  227. keylen /= 5;
  228. pubkeybuf = GNUNET_malloc (keylen + 1);
  229. end =
  230. GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
  231. sizeof(struct GNUNET_CRYPTO_EddsaPublicKey),
  232. pubkeybuf,
  233. keylen);
  234. if (NULL == end)
  235. {
  236. GNUNET_free (pubkeybuf);
  237. return NULL;
  238. }
  239. *end = '\0';
  240. return pubkeybuf;
  241. }
  242. char *
  243. GNUNET_CRYPTO_eddsa_private_key_to_string (
  244. const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
  245. {
  246. char *privkeybuf;
  247. size_t keylen = (sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
  248. char *end;
  249. if (keylen % 5 > 0)
  250. keylen += 5 - keylen % 5;
  251. keylen /= 5;
  252. privkeybuf = GNUNET_malloc (keylen + 1);
  253. end = GNUNET_STRINGS_data_to_string ((unsigned char *) priv,
  254. sizeof(
  255. struct GNUNET_CRYPTO_EddsaPrivateKey),
  256. privkeybuf,
  257. keylen);
  258. if (NULL == end)
  259. {
  260. GNUNET_free (privkeybuf);
  261. return NULL;
  262. }
  263. *end = '\0';
  264. return privkeybuf;
  265. }
  266. char *
  267. GNUNET_CRYPTO_ecdsa_private_key_to_string (
  268. const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
  269. {
  270. char *privkeybuf;
  271. size_t keylen = (sizeof(struct GNUNET_CRYPTO_EcdsaPrivateKey)) * 8;
  272. char *end;
  273. if (keylen % 5 > 0)
  274. keylen += 5 - keylen % 5;
  275. keylen /= 5;
  276. privkeybuf = GNUNET_malloc (keylen + 1);
  277. end = GNUNET_STRINGS_data_to_string ((unsigned char *) priv,
  278. sizeof(
  279. struct GNUNET_CRYPTO_EcdsaPrivateKey),
  280. privkeybuf,
  281. keylen);
  282. if (NULL == end)
  283. {
  284. GNUNET_free (privkeybuf);
  285. return NULL;
  286. }
  287. *end = '\0';
  288. return privkeybuf;
  289. }
  290. enum GNUNET_GenericReturnValue
  291. GNUNET_CRYPTO_ecdsa_public_key_from_string (
  292. const char *enc,
  293. size_t enclen,
  294. struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
  295. {
  296. size_t keylen = (sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
  297. if (keylen % 5 > 0)
  298. keylen += 5 - keylen % 5;
  299. keylen /= 5;
  300. if (enclen != keylen)
  301. return GNUNET_SYSERR;
  302. if (GNUNET_OK !=
  303. GNUNET_STRINGS_string_to_data (enc,
  304. enclen,
  305. pub,
  306. sizeof(
  307. struct GNUNET_CRYPTO_EcdsaPublicKey)))
  308. return GNUNET_SYSERR;
  309. return GNUNET_OK;
  310. }
  311. enum GNUNET_GenericReturnValue
  312. GNUNET_CRYPTO_eddsa_public_key_from_string (
  313. const char *enc,
  314. size_t enclen,
  315. struct GNUNET_CRYPTO_EddsaPublicKey *pub)
  316. {
  317. size_t keylen = (sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
  318. if (keylen % 5 > 0)
  319. keylen += 5 - keylen % 5;
  320. keylen /= 5;
  321. if (enclen != keylen)
  322. return GNUNET_SYSERR;
  323. if (GNUNET_OK !=
  324. GNUNET_STRINGS_string_to_data (enc,
  325. enclen,
  326. pub,
  327. sizeof(
  328. struct GNUNET_CRYPTO_EddsaPublicKey)))
  329. return GNUNET_SYSERR;
  330. return GNUNET_OK;
  331. }
  332. enum GNUNET_GenericReturnValue
  333. GNUNET_CRYPTO_eddsa_private_key_from_string (
  334. const char *enc,
  335. size_t enclen,
  336. struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
  337. {
  338. size_t keylen = (sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
  339. if (keylen % 5 > 0)
  340. keylen += 5 - keylen % 5;
  341. keylen /= 5;
  342. if (enclen != keylen)
  343. return GNUNET_SYSERR;
  344. if (GNUNET_OK !=
  345. GNUNET_STRINGS_string_to_data (enc,
  346. enclen,
  347. priv,
  348. sizeof(
  349. struct GNUNET_CRYPTO_EddsaPrivateKey)))
  350. return GNUNET_SYSERR;
  351. #if CRYPTO_BUG
  352. if (GNUNET_OK != check_eddsa_key (priv))
  353. {
  354. GNUNET_break (0);
  355. return GNUNET_OK;
  356. }
  357. #endif
  358. return GNUNET_OK;
  359. }
  360. void
  361. GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
  362. {
  363. memset (pk, 0, sizeof(struct GNUNET_CRYPTO_EcdhePrivateKey));
  364. }
  365. void
  366. GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
  367. {
  368. memset (pk, 0, sizeof(struct GNUNET_CRYPTO_EcdsaPrivateKey));
  369. }
  370. void
  371. GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
  372. {
  373. memset (pk, 0, sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey));
  374. }
  375. void
  376. GNUNET_CRYPTO_ecdhe_key_create (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
  377. {
  378. BENCHMARK_START (ecdhe_key_create);
  379. GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
  380. pk,
  381. sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
  382. BENCHMARK_END (ecdhe_key_create);
  383. }
  384. void
  385. GNUNET_CRYPTO_ecdsa_key_create (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
  386. {
  387. BENCHMARK_START (ecdsa_key_create);
  388. GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
  389. pk,
  390. sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey));
  391. pk->d[0] &= 248;
  392. pk->d[31] &= 127;
  393. pk->d[31] |= 64;
  394. BENCHMARK_END (ecdsa_key_create);
  395. }
  396. void
  397. GNUNET_CRYPTO_eddsa_key_create (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
  398. {
  399. BENCHMARK_START (eddsa_key_create);
  400. /*
  401. * We do not clamp for EdDSA, since all functions that use the private key do
  402. * their own clamping (just like in libsodium). What we call "private key"
  403. * here, actually corresponds to the seed in libsodium.
  404. *
  405. * (Contrast this to ECDSA, where functions using the private key can't clamp
  406. * due to properties needed for GNS. That is a worse/unsafer API, but
  407. * required for the GNS constructions to work.)
  408. */
  409. GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
  410. pk,
  411. sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey));
  412. BENCHMARK_END (eddsa_key_create);
  413. }
  414. const struct GNUNET_CRYPTO_EcdsaPrivateKey *
  415. GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
  416. {
  417. /**
  418. * 'anonymous' pseudonym (global static, d=1, public key = G
  419. * (generator).
  420. */
  421. static struct GNUNET_CRYPTO_EcdsaPrivateKey anonymous;
  422. static int once;
  423. if (once)
  424. return &anonymous;
  425. GNUNET_CRYPTO_mpi_print_unsigned (anonymous.d,
  426. sizeof(anonymous.d),
  427. GCRYMPI_CONST_ONE);
  428. anonymous.d[0] &= 248;
  429. anonymous.d[31] &= 127;
  430. anonymous.d[31] |= 64;
  431. once = 1;
  432. return &anonymous;
  433. }
  434. /**
  435. * Convert the data specified in the given purpose argument to an
  436. * S-expression suitable for signature operations.
  437. *
  438. * @param purpose data to convert
  439. * @return converted s-expression
  440. */
  441. static gcry_sexp_t
  442. data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
  443. {
  444. gcry_sexp_t data;
  445. int rc;
  446. /* See #5398 */
  447. #if 1
  448. struct GNUNET_HashCode hc;
  449. GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
  450. if (0 != (rc = gcry_sexp_build (&data,
  451. NULL,
  452. "(data(flags rfc6979)(hash %s %b))",
  453. "sha512",
  454. (int) sizeof(hc),
  455. &hc)))
  456. {
  457. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
  458. return NULL;
  459. }
  460. #else
  461. if (0 != (rc = gcry_sexp_build (&data,
  462. NULL,
  463. "(data(flags rfc6979)(hash %s %b))",
  464. "sha512",
  465. ntohl (purpose->size),
  466. purpose)))
  467. {
  468. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
  469. return NULL;
  470. }
  471. #endif
  472. return data;
  473. }
  474. enum GNUNET_GenericReturnValue
  475. GNUNET_CRYPTO_ecdsa_sign_ (
  476. const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
  477. const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
  478. struct GNUNET_CRYPTO_EcdsaSignature *sig)
  479. {
  480. gcry_sexp_t priv_sexp;
  481. gcry_sexp_t sig_sexp;
  482. gcry_sexp_t data;
  483. int rc;
  484. gcry_mpi_t rs[2];
  485. BENCHMARK_START (ecdsa_sign);
  486. priv_sexp = decode_private_ecdsa_key (priv);
  487. data = data_to_ecdsa_value (purpose);
  488. if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
  489. {
  490. LOG (GNUNET_ERROR_TYPE_WARNING,
  491. _ ("ECC signing failed at %s:%d: %s\n"),
  492. __FILE__,
  493. __LINE__,
  494. gcry_strerror (rc));
  495. gcry_sexp_release (data);
  496. gcry_sexp_release (priv_sexp);
  497. return GNUNET_SYSERR;
  498. }
  499. gcry_sexp_release (priv_sexp);
  500. gcry_sexp_release (data);
  501. /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
  502. 'signature' */
  503. if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
  504. {
  505. GNUNET_break (0);
  506. gcry_sexp_release (sig_sexp);
  507. return GNUNET_SYSERR;
  508. }
  509. gcry_sexp_release (sig_sexp);
  510. GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof(sig->r), rs[0]);
  511. GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof(sig->s), rs[1]);
  512. gcry_mpi_release (rs[0]);
  513. gcry_mpi_release (rs[1]);
  514. BENCHMARK_END (ecdsa_sign);
  515. return GNUNET_OK;
  516. }
  517. enum GNUNET_GenericReturnValue
  518. GNUNET_CRYPTO_eddsa_sign_ (
  519. const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
  520. const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
  521. struct GNUNET_CRYPTO_EddsaSignature *sig)
  522. {
  523. size_t mlen = ntohl (purpose->size);
  524. unsigned char sk[crypto_sign_SECRETKEYBYTES];
  525. unsigned char pk[crypto_sign_PUBLICKEYBYTES];
  526. int res;
  527. BENCHMARK_START (eddsa_sign);
  528. GNUNET_assert (0 == crypto_sign_seed_keypair (pk, sk, priv->d));
  529. res = crypto_sign_detached ((uint8_t *) sig,
  530. NULL,
  531. (uint8_t *) purpose,
  532. mlen,
  533. sk);
  534. BENCHMARK_END (eddsa_sign);
  535. return (res == 0) ? GNUNET_OK : GNUNET_SYSERR;
  536. }
  537. enum GNUNET_GenericReturnValue
  538. GNUNET_CRYPTO_ecdsa_verify_ (
  539. uint32_t purpose,
  540. const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
  541. const struct GNUNET_CRYPTO_EcdsaSignature *sig,
  542. const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
  543. {
  544. gcry_sexp_t data;
  545. gcry_sexp_t sig_sexpr;
  546. gcry_sexp_t pub_sexpr;
  547. int rc;
  548. BENCHMARK_START (ecdsa_verify);
  549. if (purpose != ntohl (validate->purpose))
  550. return GNUNET_SYSERR; /* purpose mismatch */
  551. /* build s-expression for signature */
  552. if (0 != (rc = gcry_sexp_build (&sig_sexpr,
  553. NULL,
  554. "(sig-val(ecdsa(r %b)(s %b)))",
  555. (int) sizeof(sig->r),
  556. sig->r,
  557. (int) sizeof(sig->s),
  558. sig->s)))
  559. {
  560. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
  561. return GNUNET_SYSERR;
  562. }
  563. data = data_to_ecdsa_value (validate);
  564. if (0 != (rc = gcry_sexp_build (&pub_sexpr,
  565. NULL,
  566. "(public-key(ecc(curve " CURVE ")(q %b)))",
  567. (int) sizeof(pub->q_y),
  568. pub->q_y)))
  569. {
  570. gcry_sexp_release (data);
  571. gcry_sexp_release (sig_sexpr);
  572. return GNUNET_SYSERR;
  573. }
  574. rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
  575. gcry_sexp_release (pub_sexpr);
  576. gcry_sexp_release (data);
  577. gcry_sexp_release (sig_sexpr);
  578. if (0 != rc)
  579. {
  580. LOG (GNUNET_ERROR_TYPE_INFO,
  581. _ ("ECDSA signature verification failed at %s:%d: %s\n"),
  582. __FILE__,
  583. __LINE__,
  584. gcry_strerror (rc));
  585. BENCHMARK_END (ecdsa_verify);
  586. return GNUNET_SYSERR;
  587. }
  588. BENCHMARK_END (ecdsa_verify);
  589. return GNUNET_OK;
  590. }
  591. enum GNUNET_GenericReturnValue
  592. GNUNET_CRYPTO_eddsa_verify_ (
  593. uint32_t purpose,
  594. const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
  595. const struct GNUNET_CRYPTO_EddsaSignature *sig,
  596. const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
  597. {
  598. const unsigned char *m = (const void *) validate;
  599. size_t mlen = ntohl (validate->size);
  600. const unsigned char *s = (const void *) sig;
  601. int res;
  602. if (purpose != ntohl (validate->purpose))
  603. return GNUNET_SYSERR; /* purpose mismatch */
  604. BENCHMARK_START (eddsa_verify);
  605. res = crypto_sign_verify_detached (s, m, mlen, pub->q_y);
  606. BENCHMARK_END (eddsa_verify);
  607. return (res == 0) ? GNUNET_OK : GNUNET_SYSERR;
  608. }
  609. enum GNUNET_GenericReturnValue
  610. GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
  611. const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
  612. struct GNUNET_HashCode *key_material)
  613. {
  614. uint8_t p[crypto_scalarmult_BYTES];
  615. if (0 != crypto_scalarmult (p, priv->d, pub->q_y))
  616. return GNUNET_SYSERR;
  617. GNUNET_CRYPTO_hash (p, crypto_scalarmult_BYTES, key_material);
  618. return GNUNET_OK;
  619. }
  620. /**
  621. * Derive the 'h' value for key derivation, where
  622. * 'h = H(l,P)'.
  623. *
  624. * @param pub public key for deriviation
  625. * @param label label for deriviation
  626. * @param context additional context to use for HKDF of 'h';
  627. * typically the name of the subsystem/application
  628. * @return h value
  629. */
  630. static gcry_mpi_t
  631. derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
  632. const char *label,
  633. const char *context)
  634. {
  635. gcry_mpi_t h;
  636. struct GNUNET_HashCode hc;
  637. static const char *const salt = "key-derivation";
  638. GNUNET_CRYPTO_kdf (&hc,
  639. sizeof(hc),
  640. salt,
  641. strlen (salt),
  642. pub,
  643. sizeof(*pub),
  644. label,
  645. strlen (label),
  646. context,
  647. strlen (context),
  648. NULL,
  649. 0);
  650. GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc));
  651. return h;
  652. }
  653. struct GNUNET_CRYPTO_EcdsaPrivateKey *
  654. GNUNET_CRYPTO_ecdsa_private_key_derive (
  655. const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
  656. const char *label,
  657. const char *context)
  658. {
  659. struct GNUNET_CRYPTO_EcdsaPublicKey pub;
  660. struct GNUNET_CRYPTO_EcdsaPrivateKey *ret;
  661. uint8_t dc[32];
  662. gcry_mpi_t h;
  663. gcry_mpi_t x;
  664. gcry_mpi_t d;
  665. gcry_mpi_t n;
  666. gcry_ctx_t ctx;
  667. GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
  668. n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
  669. GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
  670. h = derive_h (&pub, label, context);
  671. /* Convert to big endian for libgcrypt */
  672. for (size_t i = 0; i < 32; i++)
  673. dc[i] = priv->d[31 - i];
  674. GNUNET_CRYPTO_mpi_scan_unsigned (&x, dc, sizeof(dc));
  675. d = gcry_mpi_new (256);
  676. gcry_mpi_mulm (d, h, x, n);
  677. gcry_mpi_release (h);
  678. gcry_mpi_release (x);
  679. gcry_mpi_release (n);
  680. gcry_ctx_release (ctx);
  681. ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
  682. GNUNET_CRYPTO_mpi_print_unsigned (dc, sizeof(dc), d);
  683. /* Convert to big endian for libgcrypt */
  684. for (size_t i = 0; i < 32; i++)
  685. ret->d[i] = dc[31 - i];
  686. sodium_memzero (dc, sizeof(dc));
  687. gcry_mpi_release (d);
  688. return ret;
  689. }
  690. void
  691. GNUNET_CRYPTO_ecdsa_public_key_derive (
  692. const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
  693. const char *label,
  694. const char *context,
  695. struct GNUNET_CRYPTO_EcdsaPublicKey *result)
  696. {
  697. gcry_ctx_t ctx;
  698. gcry_mpi_t q_y;
  699. gcry_mpi_t h;
  700. gcry_mpi_t n;
  701. gcry_mpi_t h_mod_n;
  702. gcry_mpi_point_t q;
  703. gcry_mpi_point_t v;
  704. GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
  705. /* obtain point 'q' from original public key. The provided 'q' is
  706. compressed thus we first store it in the context and then get it
  707. back as a (decompresssed) point. */
  708. q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8 * sizeof(pub->q_y));
  709. GNUNET_assert (NULL != q_y);
  710. GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
  711. gcry_mpi_release (q_y);
  712. q = gcry_mpi_ec_get_point ("q", ctx, 0);
  713. GNUNET_assert (q);
  714. /* calculate h_mod_n = h % n */
  715. h = derive_h (pub, label, context);
  716. n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
  717. h_mod_n = gcry_mpi_new (256);
  718. gcry_mpi_mod (h_mod_n, h, n);
  719. /* calculate v = h_mod_n * q */
  720. v = gcry_mpi_point_new (0);
  721. gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
  722. gcry_mpi_release (h_mod_n);
  723. gcry_mpi_release (h);
  724. gcry_mpi_release (n);
  725. gcry_mpi_point_release (q);
  726. /* convert point 'v' to public key that we return */
  727. GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
  728. gcry_mpi_point_release (v);
  729. q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
  730. GNUNET_assert (q_y);
  731. GNUNET_CRYPTO_mpi_print_unsigned (result->q_y, sizeof(result->q_y), q_y);
  732. gcry_mpi_release (q_y);
  733. gcry_ctx_release (ctx);
  734. }
  735. enum GNUNET_GenericReturnValue
  736. GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
  737. const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
  738. struct GNUNET_HashCode *key_material)
  739. {
  740. struct GNUNET_HashCode hc;
  741. uint8_t a[crypto_scalarmult_SCALARBYTES];
  742. uint8_t p[crypto_scalarmult_BYTES];
  743. GNUNET_CRYPTO_hash (priv,
  744. sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey),
  745. &hc);
  746. memcpy (a, &hc, sizeof (struct GNUNET_CRYPTO_EcdhePrivateKey));
  747. if (0 != crypto_scalarmult (p, a, pub->q_y))
  748. return GNUNET_SYSERR;
  749. GNUNET_CRYPTO_hash (p,
  750. crypto_scalarmult_BYTES,
  751. key_material);
  752. return GNUNET_OK;
  753. }
  754. enum GNUNET_GenericReturnValue
  755. GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
  756. const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
  757. struct GNUNET_HashCode *key_material)
  758. {
  759. uint8_t p[crypto_scalarmult_BYTES];
  760. BENCHMARK_START (ecdsa_ecdh);
  761. if (0 != crypto_scalarmult (p, priv->d, pub->q_y))
  762. return GNUNET_SYSERR;
  763. GNUNET_CRYPTO_hash (p,
  764. crypto_scalarmult_BYTES,
  765. key_material);
  766. BENCHMARK_END (ecdsa_ecdh);
  767. return GNUNET_OK;
  768. }
  769. enum GNUNET_GenericReturnValue
  770. GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
  771. const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
  772. struct GNUNET_HashCode *key_material)
  773. {
  774. uint8_t p[crypto_scalarmult_BYTES];
  775. uint8_t curve25510_pk[crypto_scalarmult_BYTES];
  776. if (0 != crypto_sign_ed25519_pk_to_curve25519 (curve25510_pk, pub->q_y))
  777. return GNUNET_SYSERR;
  778. if (0 != crypto_scalarmult (p, priv->d, curve25510_pk))
  779. return GNUNET_SYSERR;
  780. GNUNET_CRYPTO_hash (p, crypto_scalarmult_BYTES, key_material);
  781. return GNUNET_OK;
  782. }
  783. enum GNUNET_GenericReturnValue
  784. GNUNET_CRYPTO_ecdh_ecdsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
  785. const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
  786. struct GNUNET_HashCode *key_material)
  787. {
  788. uint8_t p[crypto_scalarmult_BYTES];
  789. uint8_t curve25510_pk[crypto_scalarmult_BYTES];
  790. if (0 != crypto_sign_ed25519_pk_to_curve25519 (curve25510_pk, pub->q_y))
  791. return GNUNET_SYSERR;
  792. if (0 != crypto_scalarmult (p, priv->d, curve25510_pk))
  793. return GNUNET_SYSERR;
  794. GNUNET_CRYPTO_hash (p, crypto_scalarmult_BYTES, key_material);
  795. return GNUNET_OK;
  796. }
  797. /* end of crypto_ecc.c */