crypto_ecc.c 44 KB

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