crypto_ecc.c 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675
  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. */
  21. #include "platform.h"
  22. #include <gcrypt.h>
  23. #include "gnunet_crypto_lib.h"
  24. #include "gnunet_strings_lib.h"
  25. #include "benchmark.h"
  26. #define EXTRA_CHECKS 0
  27. /**
  28. * Name of the curve we are using. Note that we have hard-coded
  29. * structs that use 256 bits, so using a bigger curve will require
  30. * changes that break stuff badly. The name of the curve given here
  31. * must be agreed by all peers and be supported by libgcrypt.
  32. */
  33. #define CURVE "Ed25519"
  34. #define LOG(kind, ...) GNUNET_log_from (kind, "util-crypto-ecc", __VA_ARGS__)
  35. #define LOG_STRERROR(kind, syscall) \
  36. GNUNET_log_from_strerror (kind, "util-crypto-ecc", syscall)
  37. #define LOG_STRERROR_FILE(kind, syscall, filename) \
  38. GNUNET_log_from_strerror_file (kind, "util-crypto-ecc", syscall, filename)
  39. /**
  40. * Log an error message at log-level 'level' that indicates
  41. * a failure of the command 'cmd' with the message given
  42. * by gcry_strerror(rc).
  43. */
  44. #define LOG_GCRY(level, cmd, rc) \
  45. do \
  46. { \
  47. LOG (level, \
  48. _ ("`%s' failed at %s:%d with error: %s\n"), \
  49. cmd, \
  50. __FILE__, \
  51. __LINE__, \
  52. gcry_strerror (rc)); \
  53. } while (0)
  54. /**
  55. * Extract values from an S-expression.
  56. *
  57. * @param array where to store the result(s)
  58. * @param sexp S-expression to parse
  59. * @param topname top-level name in the S-expression that is of interest
  60. * @param elems names of the elements to extract
  61. * @return 0 on success
  62. */
  63. static int
  64. key_from_sexp (gcry_mpi_t *array,
  65. gcry_sexp_t sexp,
  66. const char *topname,
  67. const char *elems)
  68. {
  69. gcry_sexp_t list;
  70. gcry_sexp_t l2;
  71. unsigned int idx;
  72. list = gcry_sexp_find_token (sexp, topname, 0);
  73. if (! list)
  74. return 1;
  75. l2 = gcry_sexp_cadr (list);
  76. gcry_sexp_release (list);
  77. list = l2;
  78. if (! list)
  79. return 2;
  80. idx = 0;
  81. for (const char *s = elems; *s; s++, idx++)
  82. {
  83. l2 = gcry_sexp_find_token (list, s, 1);
  84. if (! l2)
  85. {
  86. for (unsigned int i = 0; i < idx; i++)
  87. {
  88. gcry_free (array[i]);
  89. array[i] = NULL;
  90. }
  91. gcry_sexp_release (list);
  92. return 3; /* required parameter not found */
  93. }
  94. array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
  95. gcry_sexp_release (l2);
  96. if (! array[idx])
  97. {
  98. for (unsigned int i = 0; i < idx; i++)
  99. {
  100. gcry_free (array[i]);
  101. array[i] = NULL;
  102. }
  103. gcry_sexp_release (list);
  104. return 4; /* required parameter is invalid */
  105. }
  106. }
  107. gcry_sexp_release (list);
  108. return 0;
  109. }
  110. /**
  111. * Convert the given private key from the network format to the
  112. * S-expression that can be used by libgcrypt.
  113. *
  114. * @param priv private key to decode
  115. * @return NULL on error
  116. */
  117. static gcry_sexp_t
  118. decode_private_ecdsa_key (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
  119. {
  120. gcry_sexp_t result;
  121. int rc;
  122. rc = gcry_sexp_build (&result,
  123. NULL,
  124. "(private-key(ecc(curve \"" CURVE "\")"
  125. "(d %b)))",
  126. (int) sizeof(priv->d),
  127. priv->d);
  128. if (0 != rc)
  129. {
  130. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
  131. GNUNET_assert (0);
  132. }
  133. #if EXTRA_CHECKS
  134. if (0 != (rc = gcry_pk_testkey (result)))
  135. {
  136. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
  137. GNUNET_assert (0);
  138. }
  139. #endif
  140. return result;
  141. }
  142. /**
  143. * Convert the given private key from the network format to the
  144. * S-expression that can be used by libgcrypt.
  145. *
  146. * @param priv private key to decode
  147. * @return NULL on error
  148. */
  149. static gcry_sexp_t
  150. decode_private_eddsa_key (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
  151. {
  152. gcry_sexp_t result;
  153. int rc;
  154. rc = gcry_sexp_build (&result,
  155. NULL,
  156. "(private-key(ecc(curve \"" CURVE "\")"
  157. "(flags eddsa)(d %b)))",
  158. (int) sizeof(priv->d),
  159. priv->d);
  160. if (0 != rc)
  161. {
  162. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
  163. GNUNET_assert (0);
  164. }
  165. #if EXTRA_CHECKS
  166. if (0 != (rc = gcry_pk_testkey (result)))
  167. {
  168. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
  169. GNUNET_assert (0);
  170. }
  171. #endif
  172. return result;
  173. }
  174. /**
  175. * Convert the given private key from the network format to the
  176. * S-expression that can be used by libgcrypt.
  177. *
  178. * @param priv private key to decode
  179. * @return NULL on error
  180. */
  181. static gcry_sexp_t
  182. decode_private_ecdhe_key (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv)
  183. {
  184. gcry_sexp_t result;
  185. int rc;
  186. rc = gcry_sexp_build (&result,
  187. NULL,
  188. "(private-key(ecc(curve \"" CURVE "\")"
  189. "(d %b)))",
  190. (int) sizeof(priv->d),
  191. priv->d);
  192. if (0 != rc)
  193. {
  194. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
  195. GNUNET_assert (0);
  196. }
  197. #if EXTRA_CHECKS
  198. if (0 != (rc = gcry_pk_testkey (result)))
  199. {
  200. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
  201. GNUNET_assert (0);
  202. }
  203. #endif
  204. return result;
  205. }
  206. /**
  207. * Extract the public key for the given private key.
  208. *
  209. * @param priv the private key
  210. * @param pub where to write the public key
  211. */
  212. void
  213. GNUNET_CRYPTO_ecdsa_key_get_public (
  214. const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
  215. struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
  216. {
  217. gcry_sexp_t sexp;
  218. gcry_ctx_t ctx;
  219. gcry_mpi_t q;
  220. BENCHMARK_START (ecdsa_key_get_public);
  221. sexp = decode_private_ecdsa_key (priv);
  222. GNUNET_assert (NULL != sexp);
  223. GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
  224. gcry_sexp_release (sexp);
  225. q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
  226. GNUNET_assert (NULL != q);
  227. GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof(pub->q_y), q);
  228. gcry_mpi_release (q);
  229. gcry_ctx_release (ctx);
  230. BENCHMARK_END (ecdsa_key_get_public);
  231. }
  232. /**
  233. * Extract the public key for the given private key.
  234. *
  235. * @param priv the private key
  236. * @param pub where to write the public key
  237. */
  238. void
  239. GNUNET_CRYPTO_eddsa_key_get_public (
  240. const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
  241. struct GNUNET_CRYPTO_EddsaPublicKey *pub)
  242. {
  243. gcry_sexp_t sexp;
  244. gcry_ctx_t ctx;
  245. gcry_mpi_t q;
  246. BENCHMARK_START (eddsa_key_get_public);
  247. sexp = decode_private_eddsa_key (priv);
  248. GNUNET_assert (NULL != sexp);
  249. GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
  250. gcry_sexp_release (sexp);
  251. q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
  252. GNUNET_assert (q);
  253. GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof(pub->q_y), q);
  254. gcry_mpi_release (q);
  255. gcry_ctx_release (ctx);
  256. BENCHMARK_END (eddsa_key_get_public);
  257. }
  258. /**
  259. * Extract the public key for the given private key.
  260. *
  261. * @param priv the private key
  262. * @param pub where to write the public key
  263. */
  264. void
  265. GNUNET_CRYPTO_ecdhe_key_get_public (
  266. const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
  267. struct GNUNET_CRYPTO_EcdhePublicKey *pub)
  268. {
  269. gcry_sexp_t sexp;
  270. gcry_ctx_t ctx;
  271. gcry_mpi_t q;
  272. BENCHMARK_START (ecdhe_key_get_public);
  273. sexp = decode_private_ecdhe_key (priv);
  274. GNUNET_assert (NULL != sexp);
  275. GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
  276. gcry_sexp_release (sexp);
  277. q = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
  278. GNUNET_assert (q);
  279. GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof(pub->q_y), q);
  280. gcry_mpi_release (q);
  281. gcry_ctx_release (ctx);
  282. BENCHMARK_END (ecdhe_key_get_public);
  283. }
  284. /**
  285. * Convert a public key to a string.
  286. *
  287. * @param pub key to convert
  288. * @return string representing @a pub
  289. */
  290. char *
  291. GNUNET_CRYPTO_ecdsa_public_key_to_string (
  292. const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
  293. {
  294. char *pubkeybuf;
  295. size_t keylen = (sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
  296. char *end;
  297. if (keylen % 5 > 0)
  298. keylen += 5 - keylen % 5;
  299. keylen /= 5;
  300. pubkeybuf = GNUNET_malloc (keylen + 1);
  301. end =
  302. GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
  303. sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey),
  304. pubkeybuf,
  305. keylen);
  306. if (NULL == end)
  307. {
  308. GNUNET_free (pubkeybuf);
  309. return NULL;
  310. }
  311. *end = '\0';
  312. return pubkeybuf;
  313. }
  314. /**
  315. * Convert a public key to a string.
  316. *
  317. * @param pub key to convert
  318. * @return string representing @a pub
  319. */
  320. char *
  321. GNUNET_CRYPTO_eddsa_public_key_to_string (
  322. const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
  323. {
  324. char *pubkeybuf;
  325. size_t keylen = (sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
  326. char *end;
  327. if (keylen % 5 > 0)
  328. keylen += 5 - keylen % 5;
  329. keylen /= 5;
  330. pubkeybuf = GNUNET_malloc (keylen + 1);
  331. end =
  332. GNUNET_STRINGS_data_to_string ((unsigned char *) pub,
  333. sizeof(struct GNUNET_CRYPTO_EddsaPublicKey),
  334. pubkeybuf,
  335. keylen);
  336. if (NULL == end)
  337. {
  338. GNUNET_free (pubkeybuf);
  339. return NULL;
  340. }
  341. *end = '\0';
  342. return pubkeybuf;
  343. }
  344. /**
  345. * Convert a private key to a string.
  346. *
  347. * @param priv key to convert
  348. * @return string representing @a pub
  349. */
  350. char *
  351. GNUNET_CRYPTO_eddsa_private_key_to_string (
  352. const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
  353. {
  354. char *privkeybuf;
  355. size_t keylen = (sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
  356. char *end;
  357. if (keylen % 5 > 0)
  358. keylen += 5 - keylen % 5;
  359. keylen /= 5;
  360. privkeybuf = GNUNET_malloc (keylen + 1);
  361. end = GNUNET_STRINGS_data_to_string ((unsigned char *) priv,
  362. sizeof(
  363. struct GNUNET_CRYPTO_EddsaPrivateKey),
  364. privkeybuf,
  365. keylen);
  366. if (NULL == end)
  367. {
  368. GNUNET_free (privkeybuf);
  369. return NULL;
  370. }
  371. *end = '\0';
  372. return privkeybuf;
  373. }
  374. /**
  375. * Convert a private key to a string.
  376. *
  377. * @param priv key to convert
  378. * @return string representing @a priv
  379. */
  380. char *
  381. GNUNET_CRYPTO_ecdsa_private_key_to_string (
  382. const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv)
  383. {
  384. char *privkeybuf;
  385. size_t keylen = (sizeof(struct GNUNET_CRYPTO_EcdsaPrivateKey)) * 8;
  386. char *end;
  387. if (keylen % 5 > 0)
  388. keylen += 5 - keylen % 5;
  389. keylen /= 5;
  390. privkeybuf = GNUNET_malloc (keylen + 1);
  391. end = GNUNET_STRINGS_data_to_string ((unsigned char *) priv,
  392. sizeof(
  393. struct GNUNET_CRYPTO_EcdsaPrivateKey),
  394. privkeybuf,
  395. keylen);
  396. if (NULL == end)
  397. {
  398. GNUNET_free (privkeybuf);
  399. return NULL;
  400. }
  401. *end = '\0';
  402. return privkeybuf;
  403. }
  404. /**
  405. * Convert a string representing a public key to a public key.
  406. *
  407. * @param enc encoded public key
  408. * @param enclen number of bytes in @a enc (without 0-terminator)
  409. * @param pub where to store the public key
  410. * @return #GNUNET_OK on success
  411. */
  412. int
  413. GNUNET_CRYPTO_ecdsa_public_key_from_string (
  414. const char *enc,
  415. size_t enclen,
  416. struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
  417. {
  418. size_t keylen = (sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey)) * 8;
  419. if (keylen % 5 > 0)
  420. keylen += 5 - keylen % 5;
  421. keylen /= 5;
  422. if (enclen != keylen)
  423. return GNUNET_SYSERR;
  424. if (GNUNET_OK !=
  425. GNUNET_STRINGS_string_to_data (enc,
  426. enclen,
  427. pub,
  428. sizeof(
  429. struct GNUNET_CRYPTO_EcdsaPublicKey)))
  430. return GNUNET_SYSERR;
  431. return GNUNET_OK;
  432. }
  433. /**
  434. * Convert a string representing a public key to a public key.
  435. *
  436. * @param enc encoded public key
  437. * @param enclen number of bytes in @a enc (without 0-terminator)
  438. * @param pub where to store the public key
  439. * @return #GNUNET_OK on success
  440. */
  441. int
  442. GNUNET_CRYPTO_eddsa_public_key_from_string (
  443. const char *enc,
  444. size_t enclen,
  445. struct GNUNET_CRYPTO_EddsaPublicKey *pub)
  446. {
  447. size_t keylen = (sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)) * 8;
  448. if (keylen % 5 > 0)
  449. keylen += 5 - keylen % 5;
  450. keylen /= 5;
  451. if (enclen != keylen)
  452. return GNUNET_SYSERR;
  453. if (GNUNET_OK !=
  454. GNUNET_STRINGS_string_to_data (enc,
  455. enclen,
  456. pub,
  457. sizeof(
  458. struct GNUNET_CRYPTO_EddsaPublicKey)))
  459. return GNUNET_SYSERR;
  460. return GNUNET_OK;
  461. }
  462. /**
  463. * Convert a string representing a private key to a private key.
  464. *
  465. * @param enc encoded public key
  466. * @param enclen number of bytes in @a enc (without 0-terminator)
  467. * @param priv where to store the private key
  468. * @return #GNUNET_OK on success
  469. */
  470. int
  471. GNUNET_CRYPTO_eddsa_private_key_from_string (
  472. const char *enc,
  473. size_t enclen,
  474. struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
  475. {
  476. size_t keylen = (sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
  477. if (keylen % 5 > 0)
  478. keylen += 5 - keylen % 5;
  479. keylen /= 5;
  480. if (enclen != keylen)
  481. return GNUNET_SYSERR;
  482. if (GNUNET_OK !=
  483. GNUNET_STRINGS_string_to_data (enc,
  484. enclen,
  485. priv,
  486. sizeof(
  487. struct GNUNET_CRYPTO_EddsaPrivateKey)))
  488. return GNUNET_SYSERR;
  489. #if CRYPTO_BUG
  490. if (GNUNET_OK != check_eddsa_key (priv))
  491. {
  492. GNUNET_break (0);
  493. return GNUNET_OK;
  494. }
  495. #endif
  496. return GNUNET_OK;
  497. }
  498. /**
  499. * @ingroup crypto
  500. * Clear memory that was used to store a private key.
  501. *
  502. * @param pk location of the key
  503. */
  504. void
  505. GNUNET_CRYPTO_ecdhe_key_clear (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
  506. {
  507. memset (pk, 0, sizeof(struct GNUNET_CRYPTO_EcdhePrivateKey));
  508. }
  509. /**
  510. * @ingroup crypto
  511. * Clear memory that was used to store a private key.
  512. *
  513. * @param pk location of the key
  514. */
  515. void
  516. GNUNET_CRYPTO_ecdsa_key_clear (struct GNUNET_CRYPTO_EcdsaPrivateKey *pk)
  517. {
  518. memset (pk, 0, sizeof(struct GNUNET_CRYPTO_EcdsaPrivateKey));
  519. }
  520. /**
  521. * @ingroup crypto
  522. * Clear memory that was used to store a private key.
  523. *
  524. * @param pk location of the key
  525. */
  526. void
  527. GNUNET_CRYPTO_eddsa_key_clear (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
  528. {
  529. memset (pk, 0, sizeof(struct GNUNET_CRYPTO_EddsaPrivateKey));
  530. }
  531. /**
  532. * Create a new private key. Caller must free return value.
  533. *
  534. * @return fresh private key
  535. */
  536. struct GNUNET_CRYPTO_EcdhePrivateKey *
  537. GNUNET_CRYPTO_ecdhe_key_create ()
  538. {
  539. struct GNUNET_CRYPTO_EcdhePrivateKey *priv;
  540. priv = GNUNET_new (struct GNUNET_CRYPTO_EcdhePrivateKey);
  541. if (GNUNET_OK != GNUNET_CRYPTO_ecdhe_key_create2 (priv))
  542. {
  543. GNUNET_free (priv);
  544. return NULL;
  545. }
  546. return priv;
  547. }
  548. /**
  549. * @ingroup crypto
  550. * Create a new private key. Clear with #GNUNET_CRYPTO_ecdhe_key_clear().
  551. *
  552. * @param[out] pk set to fresh private key;
  553. * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
  554. */
  555. int
  556. GNUNET_CRYPTO_ecdhe_key_create2 (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
  557. {
  558. gcry_sexp_t priv_sexp;
  559. gcry_sexp_t s_keyparam;
  560. gcry_mpi_t d;
  561. int rc;
  562. BENCHMARK_START (ecdhe_key_create);
  563. /* NOTE: For libgcrypt >= 1.7, we do not need the 'eddsa' flag here,
  564. but should also be harmless. For libgcrypt < 1.7, using 'eddsa'
  565. disables an expensive key testing routine. We do not want to run
  566. the expensive check for ECDHE, as we generate TONS of keys to
  567. use for a very short time. */
  568. if (0 != (rc = gcry_sexp_build (&s_keyparam,
  569. NULL,
  570. "(genkey(ecc(curve \"" CURVE "\")"
  571. "(flags eddsa no-keytest)))")))
  572. {
  573. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
  574. return GNUNET_SYSERR;
  575. }
  576. if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
  577. {
  578. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
  579. gcry_sexp_release (s_keyparam);
  580. return GNUNET_SYSERR;
  581. }
  582. gcry_sexp_release (s_keyparam);
  583. #if EXTRA_CHECKS
  584. if (0 != (rc = gcry_pk_testkey (priv_sexp)))
  585. {
  586. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
  587. gcry_sexp_release (priv_sexp);
  588. return GNUNET_SYSERR;
  589. }
  590. #endif
  591. if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
  592. {
  593. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
  594. gcry_sexp_release (priv_sexp);
  595. return GNUNET_SYSERR;
  596. }
  597. gcry_sexp_release (priv_sexp);
  598. GNUNET_CRYPTO_mpi_print_unsigned (pk->d, sizeof(pk->d), d);
  599. gcry_mpi_release (d);
  600. BENCHMARK_END (ecdhe_key_create);
  601. return GNUNET_OK;
  602. }
  603. /**
  604. * Create a new private key. Caller must free return value.
  605. *
  606. * @return fresh private key
  607. */
  608. struct GNUNET_CRYPTO_EcdsaPrivateKey *
  609. GNUNET_CRYPTO_ecdsa_key_create ()
  610. {
  611. struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
  612. gcry_sexp_t priv_sexp;
  613. gcry_sexp_t s_keyparam;
  614. gcry_mpi_t d;
  615. int rc;
  616. BENCHMARK_START (ecdsa_key_create);
  617. if (0 != (rc = gcry_sexp_build (&s_keyparam,
  618. NULL,
  619. "(genkey(ecc(curve \"" CURVE "\")"
  620. "(flags)))")))
  621. {
  622. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
  623. return NULL;
  624. }
  625. if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
  626. {
  627. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
  628. gcry_sexp_release (s_keyparam);
  629. return NULL;
  630. }
  631. gcry_sexp_release (s_keyparam);
  632. #if EXTRA_CHECKS
  633. if (0 != (rc = gcry_pk_testkey (priv_sexp)))
  634. {
  635. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
  636. gcry_sexp_release (priv_sexp);
  637. return NULL;
  638. }
  639. #endif
  640. if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
  641. {
  642. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
  643. gcry_sexp_release (priv_sexp);
  644. return NULL;
  645. }
  646. gcry_sexp_release (priv_sexp);
  647. priv = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
  648. GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof(priv->d), d);
  649. gcry_mpi_release (d);
  650. BENCHMARK_END (ecdsa_key_create);
  651. return priv;
  652. }
  653. /**
  654. * Create a new private key. Caller must free return value.
  655. *
  656. * @return fresh private key
  657. */
  658. struct GNUNET_CRYPTO_EddsaPrivateKey *
  659. GNUNET_CRYPTO_eddsa_key_create ()
  660. {
  661. struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
  662. gcry_sexp_t priv_sexp;
  663. gcry_sexp_t s_keyparam;
  664. gcry_mpi_t d;
  665. int rc;
  666. BENCHMARK_START (eddsa_key_create);
  667. #if CRYPTO_BUG
  668. again:
  669. #endif
  670. if (0 != (rc = gcry_sexp_build (&s_keyparam,
  671. NULL,
  672. "(genkey(ecc(curve \"" CURVE "\")"
  673. "(flags eddsa)))")))
  674. {
  675. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
  676. return NULL;
  677. }
  678. if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
  679. {
  680. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
  681. gcry_sexp_release (s_keyparam);
  682. return NULL;
  683. }
  684. gcry_sexp_release (s_keyparam);
  685. #if EXTRA_CHECKS
  686. if (0 != (rc = gcry_pk_testkey (priv_sexp)))
  687. {
  688. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
  689. gcry_sexp_release (priv_sexp);
  690. return NULL;
  691. }
  692. #endif
  693. if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
  694. {
  695. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
  696. gcry_sexp_release (priv_sexp);
  697. return NULL;
  698. }
  699. gcry_sexp_release (priv_sexp);
  700. priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
  701. GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof(priv->d), d);
  702. gcry_mpi_release (d);
  703. #if CRYPTO_BUG
  704. if (GNUNET_OK != check_eddsa_key (priv))
  705. {
  706. GNUNET_break (0);
  707. GNUNET_free (priv);
  708. goto again;
  709. }
  710. #endif
  711. BENCHMARK_END (eddsa_key_create);
  712. return priv;
  713. }
  714. /**
  715. * Get the shared private key we use for anonymous users.
  716. *
  717. * @return "anonymous" private key
  718. */
  719. const struct GNUNET_CRYPTO_EcdsaPrivateKey *
  720. GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
  721. {
  722. /**
  723. * 'anonymous' pseudonym (global static, d=1, public key = G
  724. * (generator).
  725. */
  726. static struct GNUNET_CRYPTO_EcdsaPrivateKey anonymous;
  727. static int once;
  728. if (once)
  729. return &anonymous;
  730. GNUNET_CRYPTO_mpi_print_unsigned (anonymous.d,
  731. sizeof(anonymous.d),
  732. GCRYMPI_CONST_ONE);
  733. once = 1;
  734. return &anonymous;
  735. }
  736. /**
  737. * Convert the data specified in the given purpose argument to an
  738. * S-expression suitable for signature operations.
  739. *
  740. * @param purpose data to convert
  741. * @return converted s-expression
  742. */
  743. static gcry_sexp_t
  744. data_to_eddsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
  745. {
  746. gcry_sexp_t data;
  747. int rc;
  748. /* SEE #5398 */
  749. #if 1
  750. struct GNUNET_HashCode hc;
  751. GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
  752. if (0 != (rc = gcry_sexp_build (&data,
  753. NULL,
  754. "(data(flags eddsa)(hash-algo %s)(value %b))",
  755. "sha512",
  756. (int) sizeof(hc),
  757. &hc)))
  758. {
  759. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
  760. return NULL;
  761. }
  762. #else
  763. GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
  764. if (0 != (rc = gcry_sexp_build (&data,
  765. NULL,
  766. "(data(flags eddsa)(hash-algo %s)(value %b))",
  767. "sha512",
  768. ntohl (purpose->size),
  769. purpose)))
  770. {
  771. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
  772. return NULL;
  773. }
  774. #endif
  775. return data;
  776. }
  777. /**
  778. * Convert the data specified in the given purpose argument to an
  779. * S-expression suitable for signature operations.
  780. *
  781. * @param purpose data to convert
  782. * @return converted s-expression
  783. */
  784. static gcry_sexp_t
  785. data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
  786. {
  787. gcry_sexp_t data;
  788. int rc;
  789. /* See #5398 */
  790. #if 1
  791. struct GNUNET_HashCode hc;
  792. GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
  793. if (0 != (rc = gcry_sexp_build (&data,
  794. NULL,
  795. "(data(flags rfc6979)(hash %s %b))",
  796. "sha512",
  797. (int) sizeof(hc),
  798. &hc)))
  799. {
  800. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
  801. return NULL;
  802. }
  803. #else
  804. if (0 != (rc = gcry_sexp_build (&data,
  805. NULL,
  806. "(data(flags rfc6979)(hash %s %b))",
  807. "sha512",
  808. ntohl (purpose->size),
  809. purpose)))
  810. {
  811. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
  812. return NULL;
  813. }
  814. #endif
  815. return data;
  816. }
  817. /**
  818. * Sign a given block.
  819. *
  820. * @param priv private key to use for the signing
  821. * @param purpose what to sign (size, purpose)
  822. * @param sig where to write the signature
  823. * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
  824. */
  825. int
  826. GNUNET_CRYPTO_ecdsa_sign (
  827. const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
  828. const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
  829. struct GNUNET_CRYPTO_EcdsaSignature *sig)
  830. {
  831. gcry_sexp_t priv_sexp;
  832. gcry_sexp_t sig_sexp;
  833. gcry_sexp_t data;
  834. int rc;
  835. gcry_mpi_t rs[2];
  836. BENCHMARK_START (ecdsa_sign);
  837. priv_sexp = decode_private_ecdsa_key (priv);
  838. data = data_to_ecdsa_value (purpose);
  839. if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
  840. {
  841. LOG (GNUNET_ERROR_TYPE_WARNING,
  842. _ ("ECC signing failed at %s:%d: %s\n"),
  843. __FILE__,
  844. __LINE__,
  845. gcry_strerror (rc));
  846. gcry_sexp_release (data);
  847. gcry_sexp_release (priv_sexp);
  848. return GNUNET_SYSERR;
  849. }
  850. gcry_sexp_release (priv_sexp);
  851. gcry_sexp_release (data);
  852. /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
  853. 'signature' */
  854. if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
  855. {
  856. GNUNET_break (0);
  857. gcry_sexp_release (sig_sexp);
  858. return GNUNET_SYSERR;
  859. }
  860. gcry_sexp_release (sig_sexp);
  861. GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof(sig->r), rs[0]);
  862. GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof(sig->s), rs[1]);
  863. gcry_mpi_release (rs[0]);
  864. gcry_mpi_release (rs[1]);
  865. BENCHMARK_END (ecdsa_sign);
  866. return GNUNET_OK;
  867. }
  868. /**
  869. * Sign a given block.
  870. *
  871. * @param priv private key to use for the signing
  872. * @param purpose what to sign (size, purpose)
  873. * @param sig where to write the signature
  874. * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
  875. */
  876. int
  877. GNUNET_CRYPTO_eddsa_sign (
  878. const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
  879. const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
  880. struct GNUNET_CRYPTO_EddsaSignature *sig)
  881. {
  882. gcry_sexp_t priv_sexp;
  883. gcry_sexp_t sig_sexp;
  884. gcry_sexp_t data;
  885. int rc;
  886. gcry_mpi_t rs[2];
  887. BENCHMARK_START (eddsa_sign);
  888. priv_sexp = decode_private_eddsa_key (priv);
  889. data = data_to_eddsa_value (purpose);
  890. if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
  891. {
  892. LOG (GNUNET_ERROR_TYPE_WARNING,
  893. _ ("EdDSA signing failed at %s:%d: %s\n"),
  894. __FILE__,
  895. __LINE__,
  896. gcry_strerror (rc));
  897. gcry_sexp_release (data);
  898. gcry_sexp_release (priv_sexp);
  899. return GNUNET_SYSERR;
  900. }
  901. gcry_sexp_release (priv_sexp);
  902. gcry_sexp_release (data);
  903. /* extract 'r' and 's' values from sexpression 'sig_sexp' and store in
  904. 'signature' */
  905. if (0 != (rc = key_from_sexp (rs, sig_sexp, "sig-val", "rs")))
  906. {
  907. GNUNET_break (0);
  908. gcry_sexp_release (sig_sexp);
  909. return GNUNET_SYSERR;
  910. }
  911. gcry_sexp_release (sig_sexp);
  912. GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof(sig->r), rs[0]);
  913. GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof(sig->s), rs[1]);
  914. gcry_mpi_release (rs[0]);
  915. gcry_mpi_release (rs[1]);
  916. BENCHMARK_END (eddsa_sign);
  917. return GNUNET_OK;
  918. }
  919. /**
  920. * Verify signature.
  921. *
  922. * @param purpose what is the purpose that the signature should have?
  923. * @param validate block to validate (size, purpose, data)
  924. * @param sig signature that is being validated
  925. * @param pub public key of the signer
  926. * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
  927. */
  928. int
  929. GNUNET_CRYPTO_ecdsa_verify (
  930. uint32_t purpose,
  931. const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
  932. const struct GNUNET_CRYPTO_EcdsaSignature *sig,
  933. const struct GNUNET_CRYPTO_EcdsaPublicKey *pub)
  934. {
  935. gcry_sexp_t data;
  936. gcry_sexp_t sig_sexpr;
  937. gcry_sexp_t pub_sexpr;
  938. int rc;
  939. BENCHMARK_START (ecdsa_verify);
  940. if (purpose != ntohl (validate->purpose))
  941. return GNUNET_SYSERR; /* purpose mismatch */
  942. /* build s-expression for signature */
  943. if (0 != (rc = gcry_sexp_build (&sig_sexpr,
  944. NULL,
  945. "(sig-val(ecdsa(r %b)(s %b)))",
  946. (int) sizeof(sig->r),
  947. sig->r,
  948. (int) sizeof(sig->s),
  949. sig->s)))
  950. {
  951. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
  952. return GNUNET_SYSERR;
  953. }
  954. data = data_to_ecdsa_value (validate);
  955. if (0 != (rc = gcry_sexp_build (&pub_sexpr,
  956. NULL,
  957. "(public-key(ecc(curve " CURVE ")(q %b)))",
  958. (int) sizeof(pub->q_y),
  959. pub->q_y)))
  960. {
  961. gcry_sexp_release (data);
  962. gcry_sexp_release (sig_sexpr);
  963. return GNUNET_SYSERR;
  964. }
  965. rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
  966. gcry_sexp_release (pub_sexpr);
  967. gcry_sexp_release (data);
  968. gcry_sexp_release (sig_sexpr);
  969. if (0 != rc)
  970. {
  971. LOG (GNUNET_ERROR_TYPE_INFO,
  972. _ ("ECDSA signature verification failed at %s:%d: %s\n"),
  973. __FILE__,
  974. __LINE__,
  975. gcry_strerror (rc));
  976. BENCHMARK_END (ecdsa_verify);
  977. return GNUNET_SYSERR;
  978. }
  979. BENCHMARK_END (ecdsa_verify);
  980. return GNUNET_OK;
  981. }
  982. /**
  983. * Verify signature.
  984. *
  985. * @param purpose what is the purpose that the signature should have?
  986. * @param validate block to validate (size, purpose, data)
  987. * @param sig signature that is being validated
  988. * @param pub public key of the signer
  989. * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
  990. */
  991. int
  992. GNUNET_CRYPTO_eddsa_verify (
  993. uint32_t purpose,
  994. const struct GNUNET_CRYPTO_EccSignaturePurpose *validate,
  995. const struct GNUNET_CRYPTO_EddsaSignature *sig,
  996. const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
  997. {
  998. gcry_sexp_t data;
  999. gcry_sexp_t sig_sexpr;
  1000. gcry_sexp_t pub_sexpr;
  1001. int rc;
  1002. BENCHMARK_START (eddsa_verify);
  1003. if (purpose != ntohl (validate->purpose))
  1004. return GNUNET_SYSERR; /* purpose mismatch */
  1005. /* build s-expression for signature */
  1006. if (0 != (rc = gcry_sexp_build (&sig_sexpr,
  1007. NULL,
  1008. "(sig-val(eddsa(r %b)(s %b)))",
  1009. (int) sizeof(sig->r),
  1010. sig->r,
  1011. (int) sizeof(sig->s),
  1012. sig->s)))
  1013. {
  1014. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
  1015. return GNUNET_SYSERR;
  1016. }
  1017. data = data_to_eddsa_value (validate);
  1018. if (0 != (rc = gcry_sexp_build (&pub_sexpr,
  1019. NULL,
  1020. "(public-key(ecc(curve " CURVE
  1021. ")(flags eddsa)(q %b)))",
  1022. (int) sizeof(pub->q_y),
  1023. pub->q_y)))
  1024. {
  1025. gcry_sexp_release (data);
  1026. gcry_sexp_release (sig_sexpr);
  1027. return GNUNET_SYSERR;
  1028. }
  1029. rc = gcry_pk_verify (sig_sexpr, data, pub_sexpr);
  1030. gcry_sexp_release (pub_sexpr);
  1031. gcry_sexp_release (data);
  1032. gcry_sexp_release (sig_sexpr);
  1033. if (0 != rc)
  1034. {
  1035. LOG (GNUNET_ERROR_TYPE_INFO,
  1036. _ ("EdDSA signature verification of type %u failed at %s:%d: %s\n"),
  1037. (unsigned int) purpose,
  1038. __FILE__,
  1039. __LINE__,
  1040. gcry_strerror (rc));
  1041. BENCHMARK_END (eddsa_verify);
  1042. return GNUNET_SYSERR;
  1043. }
  1044. BENCHMARK_END (eddsa_verify);
  1045. return GNUNET_OK;
  1046. }
  1047. /**
  1048. * Derive key material from a public and a private ECDHE key.
  1049. *
  1050. * @param priv private key to use for the ECDH (x)
  1051. * @param pub public key to use for the ECDH (yG)
  1052. * @param key_material where to write the key material (xyG)
  1053. * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
  1054. */
  1055. int
  1056. GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
  1057. const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
  1058. struct GNUNET_HashCode *key_material)
  1059. {
  1060. gcry_mpi_point_t result;
  1061. gcry_mpi_point_t q;
  1062. gcry_mpi_t d;
  1063. gcry_ctx_t ctx;
  1064. gcry_sexp_t pub_sexpr;
  1065. gcry_mpi_t result_x;
  1066. unsigned char xbuf[256 / 8];
  1067. size_t rsize;
  1068. BENCHMARK_START (ecc_ecdh);
  1069. /* first, extract the q = dP value from the public key */
  1070. if (0 != gcry_sexp_build (&pub_sexpr,
  1071. NULL,
  1072. "(public-key(ecc(curve " CURVE ")(q %b)))",
  1073. (int) sizeof(pub->q_y),
  1074. pub->q_y))
  1075. return GNUNET_SYSERR;
  1076. GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
  1077. gcry_sexp_release (pub_sexpr);
  1078. q = gcry_mpi_ec_get_point ("q", ctx, 0);
  1079. /* second, extract the d value from our private key */
  1080. GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof(priv->d));
  1081. /* then call the 'multiply' function, to compute the product */
  1082. result = gcry_mpi_point_new (0);
  1083. gcry_mpi_ec_mul (result, d, q, ctx);
  1084. gcry_mpi_point_release (q);
  1085. gcry_mpi_release (d);
  1086. /* finally, convert point to string for hashing */
  1087. result_x = gcry_mpi_new (256);
  1088. if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
  1089. {
  1090. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
  1091. gcry_mpi_point_release (result);
  1092. gcry_ctx_release (ctx);
  1093. return GNUNET_SYSERR;
  1094. }
  1095. gcry_mpi_point_release (result);
  1096. gcry_ctx_release (ctx);
  1097. rsize = sizeof(xbuf);
  1098. GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
  1099. /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
  1100. as that does not include the sign bit; x should be a 255-bit
  1101. value, so with the sign it should fit snugly into the 256-bit
  1102. xbuf */
  1103. GNUNET_assert (
  1104. 0 == gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize, result_x));
  1105. GNUNET_CRYPTO_hash (xbuf, rsize, key_material);
  1106. gcry_mpi_release (result_x);
  1107. BENCHMARK_END (ecc_ecdh);
  1108. return GNUNET_OK;
  1109. }
  1110. /**
  1111. * Derive the 'h' value for key derivation, where
  1112. * 'h = H(l,P)'.
  1113. *
  1114. * @param pub public key for deriviation
  1115. * @param label label for deriviation
  1116. * @param context additional context to use for HKDF of 'h';
  1117. * typically the name of the subsystem/application
  1118. * @return h value
  1119. */
  1120. static gcry_mpi_t
  1121. derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
  1122. const char *label,
  1123. const char *context)
  1124. {
  1125. gcry_mpi_t h;
  1126. struct GNUNET_HashCode hc;
  1127. static const char *const salt = "key-derivation";
  1128. GNUNET_CRYPTO_kdf (&hc,
  1129. sizeof(hc),
  1130. salt,
  1131. strlen (salt),
  1132. pub,
  1133. sizeof(*pub),
  1134. label,
  1135. strlen (label),
  1136. context,
  1137. strlen (context),
  1138. NULL,
  1139. 0);
  1140. GNUNET_CRYPTO_mpi_scan_unsigned (&h, (unsigned char *) &hc, sizeof(hc));
  1141. return h;
  1142. }
  1143. /**
  1144. * Derive a private key from a given private key and a label.
  1145. * Essentially calculates a private key 'd = H(l,P) * x mod n'
  1146. * where n is the size of the ECC group and P is the public
  1147. * key associated with the private key 'd'.
  1148. *
  1149. * @param priv original private key
  1150. * @param label label to use for key deriviation
  1151. * @param context additional context to use for HKDF of 'h';
  1152. * typically the name of the subsystem/application
  1153. * @return derived private key
  1154. */
  1155. struct GNUNET_CRYPTO_EcdsaPrivateKey *
  1156. GNUNET_CRYPTO_ecdsa_private_key_derive (
  1157. const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
  1158. const char *label,
  1159. const char *context)
  1160. {
  1161. struct GNUNET_CRYPTO_EcdsaPublicKey pub;
  1162. struct GNUNET_CRYPTO_EcdsaPrivateKey *ret;
  1163. gcry_mpi_t h;
  1164. gcry_mpi_t x;
  1165. gcry_mpi_t d;
  1166. gcry_mpi_t n;
  1167. gcry_ctx_t ctx;
  1168. GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
  1169. n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
  1170. GNUNET_CRYPTO_ecdsa_key_get_public (priv, &pub);
  1171. h = derive_h (&pub, label, context);
  1172. GNUNET_CRYPTO_mpi_scan_unsigned (&x, priv->d, sizeof(priv->d));
  1173. d = gcry_mpi_new (256);
  1174. gcry_mpi_mulm (d, h, x, n);
  1175. gcry_mpi_release (h);
  1176. gcry_mpi_release (x);
  1177. gcry_mpi_release (n);
  1178. gcry_ctx_release (ctx);
  1179. ret = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
  1180. GNUNET_CRYPTO_mpi_print_unsigned (ret->d, sizeof(ret->d), d);
  1181. gcry_mpi_release (d);
  1182. return ret;
  1183. }
  1184. /**
  1185. * Derive a public key from a given public key and a label.
  1186. * Essentially calculates a public key 'V = H(l,P) * P'.
  1187. *
  1188. * @param pub original public key
  1189. * @param label label to use for key derivation
  1190. * @param context additional context to use for HKDF of 'h';
  1191. * typically the name of the subsystem/application
  1192. * @param result where to write the derived public key
  1193. */
  1194. void
  1195. GNUNET_CRYPTO_ecdsa_public_key_derive (
  1196. const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
  1197. const char *label,
  1198. const char *context,
  1199. struct GNUNET_CRYPTO_EcdsaPublicKey *result)
  1200. {
  1201. gcry_ctx_t ctx;
  1202. gcry_mpi_t q_y;
  1203. gcry_mpi_t h;
  1204. gcry_mpi_t n;
  1205. gcry_mpi_t h_mod_n;
  1206. gcry_mpi_point_t q;
  1207. gcry_mpi_point_t v;
  1208. GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
  1209. /* obtain point 'q' from original public key. The provided 'q' is
  1210. compressed thus we first store it in the context and then get it
  1211. back as a (decompresssed) point. */
  1212. q_y = gcry_mpi_set_opaque_copy (NULL, pub->q_y, 8 * sizeof(pub->q_y));
  1213. GNUNET_assert (NULL != q_y);
  1214. GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
  1215. gcry_mpi_release (q_y);
  1216. q = gcry_mpi_ec_get_point ("q", ctx, 0);
  1217. GNUNET_assert (q);
  1218. /* calculate h_mod_n = h % n */
  1219. h = derive_h (pub, label, context);
  1220. n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
  1221. h_mod_n = gcry_mpi_new (256);
  1222. gcry_mpi_mod (h_mod_n, h, n);
  1223. /* calculate v = h_mod_n * q */
  1224. v = gcry_mpi_point_new (0);
  1225. gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
  1226. gcry_mpi_release (h_mod_n);
  1227. gcry_mpi_release (h);
  1228. gcry_mpi_release (n);
  1229. gcry_mpi_point_release (q);
  1230. /* convert point 'v' to public key that we return */
  1231. GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
  1232. gcry_mpi_point_release (v);
  1233. q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
  1234. GNUNET_assert (q_y);
  1235. GNUNET_CRYPTO_mpi_print_unsigned (result->q_y, sizeof(result->q_y), q_y);
  1236. gcry_mpi_release (q_y);
  1237. gcry_ctx_release (ctx);
  1238. }
  1239. /**
  1240. * Reverse the sequence of the bytes in @a buffer
  1241. *
  1242. * @param[in|out] buffer buffer to invert
  1243. * @param length number of bytes in @a buffer
  1244. */
  1245. static void
  1246. reverse_buffer (unsigned char *buffer, size_t length)
  1247. {
  1248. unsigned char tmp;
  1249. size_t i;
  1250. for (i = 0; i < length / 2; i++)
  1251. {
  1252. tmp = buffer[i];
  1253. buffer[i] = buffer[length - 1 - i];
  1254. buffer[length - 1 - i] = tmp;
  1255. }
  1256. }
  1257. /**
  1258. * Convert the secret @a d of an EdDSA key to the
  1259. * value that is actually used in the EdDSA computation.
  1260. *
  1261. * @param d secret input
  1262. * @return value used for the calculation in EdDSA
  1263. */
  1264. static gcry_mpi_t
  1265. eddsa_d_to_a (gcry_mpi_t d)
  1266. {
  1267. unsigned char rawmpi[32]; /* 256-bit value */
  1268. size_t rawmpilen;
  1269. unsigned char digest[64]; /* 512-bit hash value */
  1270. gcry_buffer_t hvec[2];
  1271. unsigned int b;
  1272. gcry_mpi_t a;
  1273. b = 256 / 8; /* number of bytes in `d` */
  1274. /* Note that we clear DIGEST so we can use it as input to left pad
  1275. the key with zeroes for hashing. */
  1276. memset (digest, 0, sizeof digest);
  1277. memset (hvec, 0, sizeof hvec);
  1278. rawmpilen = sizeof(rawmpi);
  1279. GNUNET_assert (
  1280. 0 == gcry_mpi_print (GCRYMPI_FMT_USG, rawmpi, rawmpilen, &rawmpilen, d));
  1281. hvec[0].data = digest;
  1282. hvec[0].off = 0;
  1283. hvec[0].len = b > rawmpilen ? (b - rawmpilen) : 0;
  1284. hvec[1].data = rawmpi;
  1285. hvec[1].off = 0;
  1286. hvec[1].len = rawmpilen;
  1287. GNUNET_assert (
  1288. 0 == gcry_md_hash_buffers (GCRY_MD_SHA512, 0 /* flags */, digest, hvec, 2));
  1289. /* Compute the A value. */
  1290. reverse_buffer (digest, 32); /* Only the first half of the hash. */
  1291. digest[0] = (digest[0] & 0x7f) | 0x40;
  1292. digest[31] &= 0xf8;
  1293. GNUNET_CRYPTO_mpi_scan_unsigned (&a, digest, 32);
  1294. return a;
  1295. }
  1296. /**
  1297. * Take point from ECDH and convert it to key material.
  1298. *
  1299. * @param result point from ECDH
  1300. * @param ctx ECC context
  1301. * @param key_material[out] set to derived key material
  1302. * @return #GNUNET_OK on success
  1303. */
  1304. static int
  1305. point_to_hash (gcry_mpi_point_t result,
  1306. gcry_ctx_t ctx,
  1307. struct GNUNET_HashCode *key_material)
  1308. {
  1309. gcry_mpi_t result_x;
  1310. unsigned char xbuf[256 / 8];
  1311. size_t rsize;
  1312. /* finally, convert point to string for hashing */
  1313. result_x = gcry_mpi_new (256);
  1314. if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
  1315. {
  1316. LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
  1317. return GNUNET_SYSERR;
  1318. }
  1319. rsize = sizeof(xbuf);
  1320. GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
  1321. /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
  1322. as that does not include the sign bit; x should be a 255-bit
  1323. value, so with the sign it should fit snugly into the 256-bit
  1324. xbuf */
  1325. GNUNET_assert (
  1326. 0 == gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize, result_x));
  1327. GNUNET_CRYPTO_hash (xbuf, rsize, key_material);
  1328. gcry_mpi_release (result_x);
  1329. return GNUNET_OK;
  1330. }
  1331. /**
  1332. * @ingroup crypto
  1333. * Derive key material from a ECDH public key and a private EdDSA key.
  1334. * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
  1335. *
  1336. * @param priv private key from EdDSA to use for the ECDH (x)
  1337. * @param pub public key to use for the ECDH (yG)
  1338. * @param key_material where to write the key material H(h(x)yG)
  1339. * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
  1340. */
  1341. int
  1342. GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
  1343. const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
  1344. struct GNUNET_HashCode *key_material)
  1345. {
  1346. gcry_mpi_point_t result;
  1347. gcry_mpi_point_t q;
  1348. gcry_mpi_t d;
  1349. gcry_mpi_t a;
  1350. gcry_ctx_t ctx;
  1351. gcry_sexp_t pub_sexpr;
  1352. int ret;
  1353. BENCHMARK_START (eddsa_ecdh);
  1354. /* first, extract the q = dP value from the public key */
  1355. if (0 != gcry_sexp_build (&pub_sexpr,
  1356. NULL,
  1357. "(public-key(ecc(curve " CURVE ")(q %b)))",
  1358. (int) sizeof(pub->q_y),
  1359. pub->q_y))
  1360. return GNUNET_SYSERR;
  1361. GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
  1362. gcry_sexp_release (pub_sexpr);
  1363. q = gcry_mpi_ec_get_point ("q", ctx, 0);
  1364. /* second, extract the d value from our private key */
  1365. GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof(priv->d));
  1366. /* NOW, because this is EdDSA, HASH 'd' first! */
  1367. a = eddsa_d_to_a (d);
  1368. gcry_mpi_release (d);
  1369. /* then call the 'multiply' function, to compute the product */
  1370. result = gcry_mpi_point_new (0);
  1371. gcry_mpi_ec_mul (result, a, q, ctx);
  1372. gcry_mpi_point_release (q);
  1373. gcry_mpi_release (a);
  1374. ret = point_to_hash (result, ctx, key_material);
  1375. gcry_mpi_point_release (result);
  1376. gcry_ctx_release (ctx);
  1377. BENCHMARK_END (eddsa_ecdh);
  1378. return ret;
  1379. }
  1380. /**
  1381. * @ingroup crypto
  1382. * Derive key material from a ECDH public key and a private ECDSA key.
  1383. * Dual to #GNUNET_CRRYPTO_ecdh_eddsa.
  1384. *
  1385. * @param priv private key from ECDSA to use for the ECDH (x)
  1386. * @param pub public key to use for the ECDH (yG)
  1387. * @param key_material where to write the key material H(h(x)yG)
  1388. * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
  1389. */
  1390. int
  1391. GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
  1392. const struct GNUNET_CRYPTO_EcdhePublicKey *pub,
  1393. struct GNUNET_HashCode *key_material)
  1394. {
  1395. gcry_mpi_point_t result;
  1396. gcry_mpi_point_t q;
  1397. gcry_mpi_t d;
  1398. gcry_ctx_t ctx;
  1399. gcry_sexp_t pub_sexpr;
  1400. int ret;
  1401. BENCHMARK_START (ecdsa_ecdh);
  1402. /* first, extract the q = dP value from the public key */
  1403. if (0 != gcry_sexp_build (&pub_sexpr,
  1404. NULL,
  1405. "(public-key(ecc(curve " CURVE ")(q %b)))",
  1406. (int) sizeof(pub->q_y),
  1407. pub->q_y))
  1408. return GNUNET_SYSERR;
  1409. GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
  1410. gcry_sexp_release (pub_sexpr);
  1411. q = gcry_mpi_ec_get_point ("q", ctx, 0);
  1412. /* second, extract the d value from our private key */
  1413. GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof(priv->d));
  1414. /* then call the 'multiply' function, to compute the product */
  1415. result = gcry_mpi_point_new (0);
  1416. gcry_mpi_ec_mul (result, d, q, ctx);
  1417. gcry_mpi_point_release (q);
  1418. gcry_mpi_release (d);
  1419. /* finally, convert point to string for hashing */
  1420. ret = point_to_hash (result, ctx, key_material);
  1421. gcry_mpi_point_release (result);
  1422. gcry_ctx_release (ctx);
  1423. BENCHMARK_END (ecdsa_ecdh);
  1424. return ret;
  1425. }
  1426. /**
  1427. * @ingroup crypto
  1428. * Derive key material from a EdDSA public key and a private ECDH key.
  1429. * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
  1430. *
  1431. * @param priv private key to use for the ECDH (y)
  1432. * @param pub public key from EdDSA to use for the ECDH (X=h(x)G)
  1433. * @param key_material where to write the key material H(yX)=H(h(x)yG)
  1434. * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
  1435. */
  1436. int
  1437. GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
  1438. const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
  1439. struct GNUNET_HashCode *key_material)
  1440. {
  1441. gcry_mpi_point_t result;
  1442. gcry_mpi_point_t q;
  1443. gcry_mpi_t d;
  1444. gcry_ctx_t ctx;
  1445. gcry_sexp_t pub_sexpr;
  1446. int ret;
  1447. BENCHMARK_START (ecdh_eddsa);
  1448. /* first, extract the q = dP value from the public key */
  1449. if (0 != gcry_sexp_build (&pub_sexpr,
  1450. NULL,
  1451. "(public-key(ecc(curve " CURVE ")(q %b)))",
  1452. (int) sizeof(pub->q_y),
  1453. pub->q_y))
  1454. return GNUNET_SYSERR;
  1455. GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
  1456. gcry_sexp_release (pub_sexpr);
  1457. q = gcry_mpi_ec_get_point ("q", ctx, 0);
  1458. /* second, extract the d value from our private key */
  1459. GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof(priv->d));
  1460. /* then call the 'multiply' function, to compute the product */
  1461. result = gcry_mpi_point_new (0);
  1462. gcry_mpi_ec_mul (result, d, q, ctx);
  1463. gcry_mpi_point_release (q);
  1464. gcry_mpi_release (d);
  1465. /* finally, convert point to string for hashing */
  1466. ret = point_to_hash (result, ctx, key_material);
  1467. gcry_mpi_point_release (result);
  1468. gcry_ctx_release (ctx);
  1469. BENCHMARK_END (ecdh_eddsa);
  1470. return ret;
  1471. }
  1472. /**
  1473. * @ingroup crypto
  1474. * Derive key material from a ECDSA public key and a private ECDH key.
  1475. * Dual to #GNUNET_CRRYPTO_eddsa_ecdh.
  1476. *
  1477. * @param priv private key to use for the ECDH (y)
  1478. * @param pub public key from ECDSA to use for the ECDH (X=h(x)G)
  1479. * @param key_material where to write the key material H(yX)=H(h(x)yG)
  1480. * @return #GNUNET_SYSERR on error, #GNUNET_OK on success
  1481. */
  1482. int
  1483. GNUNET_CRYPTO_ecdh_ecdsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
  1484. const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
  1485. struct GNUNET_HashCode *key_material)
  1486. {
  1487. return GNUNET_CRYPTO_ecdh_eddsa (priv,
  1488. (const struct GNUNET_CRYPTO_EddsaPublicKey *)
  1489. pub,
  1490. key_material);
  1491. }
  1492. /* end of crypto_ecc.c */