kem.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. /* kem.c - Key Encapsulation Mechanisms
  2. * Copyright (C) 2023 Simon Josefsson <simon@josefsson.org>
  3. * Copyright (C) 2023 g10 Code GmbH
  4. *
  5. * This file is part of Libgcrypt.
  6. *
  7. * Libgcrypt is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU Lesser General Public License as
  9. * published by the Free Software Foundation; either version 2.1 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * Libgcrypt is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this program; if not, see <https://www.gnu.org/licenses/>.
  19. * SPDX-License-Identifier: LGPL-2.1-or-later
  20. */
  21. #include <config.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <errno.h>
  26. #include "g10lib.h"
  27. #include "cipher.h"
  28. #include "sntrup761.h"
  29. #include "mceliece6688128f.h"
  30. #include "kyber.h"
  31. #include "kem-ecc.h"
  32. /* Information about the the KEM algoithms for use by the s-expression
  33. * interface. */
  34. static const struct
  35. {
  36. const char *name; /* Name of the algo. */
  37. unsigned int namelen; /* Only here to avoid strlen calls. */
  38. int algo; /* KEM algo number. */
  39. unsigned int nbits; /* Number of bits. */
  40. unsigned int fips:1; /* True if this is a FIPS140-3 approved KEM. */
  41. int pubkey_len; /* Length of the public key. */
  42. int seckey_len; /* Length of the secret key. */
  43. } kem_infos[] =
  44. {
  45. { "sntrup761", 9, GCRY_KEM_SNTRUP761, 761, 0,
  46. GCRY_KEM_SNTRUP761_PUBKEY_LEN, GCRY_KEM_SNTRUP761_SECKEY_LEN },
  47. { "kyber512", 8, GCRY_KEM_MLKEM512, 512, 0,
  48. GCRY_KEM_MLKEM512_PUBKEY_LEN, GCRY_KEM_MLKEM512_SECKEY_LEN },
  49. { "kyber768", 8, GCRY_KEM_MLKEM768, 768, 1,
  50. GCRY_KEM_MLKEM768_PUBKEY_LEN, GCRY_KEM_MLKEM768_SECKEY_LEN },
  51. { "kyber1024", 9, GCRY_KEM_MLKEM1024, 1024, 1,
  52. GCRY_KEM_MLKEM1024_PUBKEY_LEN, GCRY_KEM_MLKEM1024_SECKEY_LEN },
  53. { NULL }
  54. };
  55. /* This is a short version of kem_infos from above. It is required
  56. * for the algoithm module interface. Keep in sync. */
  57. static const char *kem_names[] =
  58. {
  59. "sntrup761",
  60. "kyber512",
  61. "kyber768",
  62. "kyber1024",
  63. NULL
  64. };
  65. /* Helper for sntrup761. */
  66. static void
  67. sntrup761_random (void *ctx, size_t length, uint8_t *dst)
  68. {
  69. (void)ctx;
  70. _gcry_randomize (dst, length, GCRY_STRONG_RANDOM);
  71. }
  72. gcry_err_code_t
  73. _gcry_kem_keypair (int algo,
  74. void *pubkey, size_t pubkey_len,
  75. void *seckey, size_t seckey_len)
  76. {
  77. switch (algo)
  78. {
  79. case GCRY_KEM_SNTRUP761:
  80. if (seckey_len != GCRY_KEM_SNTRUP761_SECKEY_LEN
  81. || pubkey_len != GCRY_KEM_SNTRUP761_PUBKEY_LEN)
  82. return GPG_ERR_INV_ARG;
  83. sntrup761_keypair (pubkey, seckey, NULL, sntrup761_random);
  84. return 0;
  85. case GCRY_KEM_CM6688128F:
  86. mceliece6688128f_keypair (pubkey, seckey);
  87. return 0;
  88. case GCRY_KEM_MLKEM512:
  89. if (seckey_len != GCRY_KEM_MLKEM512_SECKEY_LEN
  90. || pubkey_len != GCRY_KEM_MLKEM512_PUBKEY_LEN)
  91. return GPG_ERR_INV_ARG;
  92. kyber_keypair (algo, pubkey, seckey);
  93. return 0;
  94. case GCRY_KEM_MLKEM768:
  95. if (seckey_len != GCRY_KEM_MLKEM768_SECKEY_LEN
  96. || pubkey_len != GCRY_KEM_MLKEM768_PUBKEY_LEN)
  97. return GPG_ERR_INV_ARG;
  98. kyber_keypair (algo, pubkey, seckey);
  99. return 0;
  100. case GCRY_KEM_MLKEM1024:
  101. if (seckey_len != GCRY_KEM_MLKEM1024_SECKEY_LEN
  102. || pubkey_len != GCRY_KEM_MLKEM1024_PUBKEY_LEN)
  103. return GPG_ERR_INV_ARG;
  104. kyber_keypair (algo, pubkey, seckey);
  105. return 0;
  106. case GCRY_KEM_RAW_X25519:
  107. case GCRY_KEM_RAW_X448:
  108. case GCRY_KEM_RAW_BP256:
  109. case GCRY_KEM_RAW_BP384:
  110. case GCRY_KEM_RAW_BP512:
  111. case GCRY_KEM_RAW_P256R1:
  112. case GCRY_KEM_RAW_P384R1:
  113. case GCRY_KEM_RAW_P521R1:
  114. case GCRY_KEM_DHKEM25519:
  115. case GCRY_KEM_DHKEM448:
  116. return _gcry_ecc_raw_keypair (algo, pubkey, pubkey_len,
  117. seckey, seckey_len);
  118. default:
  119. return GPG_ERR_UNKNOWN_ALGORITHM;
  120. }
  121. return GPG_ERR_UNKNOWN_ALGORITHM;
  122. }
  123. gcry_err_code_t
  124. _gcry_kem_encap (int algo,
  125. const void *pubkey, size_t pubkey_len,
  126. void *ciphertext, size_t ciphertext_len,
  127. void *shared, size_t shared_len,
  128. const void *optional, size_t optional_len)
  129. {
  130. switch (algo)
  131. {
  132. case GCRY_KEM_SNTRUP761:
  133. if (optional != NULL || optional_len != 0)
  134. return GPG_ERR_INV_VALUE;
  135. if (pubkey_len != GCRY_KEM_SNTRUP761_PUBKEY_LEN
  136. || ciphertext_len != GCRY_KEM_SNTRUP761_ENCAPS_LEN
  137. || shared_len != GCRY_KEM_SNTRUP761_SHARED_LEN)
  138. return GPG_ERR_INV_VALUE;
  139. sntrup761_enc (ciphertext, shared, pubkey, NULL, sntrup761_random);
  140. return 0;
  141. case GCRY_KEM_CM6688128F:
  142. if (optional != NULL)
  143. return GPG_ERR_INV_VALUE;
  144. mceliece6688128f_enc (ciphertext, shared, pubkey);
  145. return 0;
  146. case GCRY_KEM_MLKEM512:
  147. case GCRY_KEM_MLKEM768:
  148. case GCRY_KEM_MLKEM1024:
  149. if (optional != NULL)
  150. return GPG_ERR_INV_VALUE;
  151. kyber_encap (algo, ciphertext, shared, pubkey);
  152. return 0;
  153. case GCRY_KEM_RAW_X25519:
  154. case GCRY_KEM_RAW_X448:
  155. case GCRY_KEM_RAW_BP256:
  156. case GCRY_KEM_RAW_BP384:
  157. case GCRY_KEM_RAW_BP512:
  158. case GCRY_KEM_RAW_P256R1:
  159. case GCRY_KEM_RAW_P384R1:
  160. case GCRY_KEM_RAW_P521R1:
  161. if (optional != NULL)
  162. return GPG_ERR_INV_VALUE;
  163. return _gcry_ecc_raw_encap (algo, pubkey, pubkey_len,
  164. ciphertext, ciphertext_len,
  165. shared, shared_len);
  166. case GCRY_KEM_DHKEM25519:
  167. case GCRY_KEM_DHKEM448:
  168. if (optional != NULL)
  169. return GPG_ERR_INV_VALUE;
  170. return _gcry_ecc_dhkem_encap (algo, pubkey, ciphertext, shared);
  171. default:
  172. return GPG_ERR_UNKNOWN_ALGORITHM;
  173. }
  174. return GPG_ERR_UNKNOWN_ALGORITHM;
  175. }
  176. gcry_err_code_t
  177. _gcry_kem_decap (int algo,
  178. const void *seckey, size_t seckey_len,
  179. const void *ciphertext, size_t ciphertext_len,
  180. void *shared, size_t shared_len,
  181. const void *optional, size_t optional_len)
  182. {
  183. switch (algo)
  184. {
  185. case GCRY_KEM_SNTRUP761:
  186. if (optional != NULL || optional_len != 0)
  187. return GPG_ERR_INV_VALUE;
  188. if (seckey_len != GCRY_KEM_SNTRUP761_SECKEY_LEN
  189. || ciphertext_len != GCRY_KEM_SNTRUP761_ENCAPS_LEN
  190. || shared_len != GCRY_KEM_SNTRUP761_SHARED_LEN)
  191. return GPG_ERR_INV_VALUE;
  192. sntrup761_dec (shared, ciphertext, seckey);
  193. return 0;
  194. case GCRY_KEM_CM6688128F:
  195. if (optional != NULL)
  196. return GPG_ERR_INV_VALUE;
  197. mceliece6688128f_dec (shared, ciphertext, seckey);
  198. return 0;
  199. case GCRY_KEM_MLKEM512:
  200. case GCRY_KEM_MLKEM768:
  201. case GCRY_KEM_MLKEM1024:
  202. if (optional != NULL)
  203. return GPG_ERR_INV_VALUE;
  204. kyber_decap (algo, shared, ciphertext, seckey);
  205. return 0;
  206. case GCRY_KEM_RAW_X25519:
  207. case GCRY_KEM_RAW_X448:
  208. case GCRY_KEM_RAW_BP256:
  209. case GCRY_KEM_RAW_BP384:
  210. case GCRY_KEM_RAW_BP512:
  211. case GCRY_KEM_RAW_P256R1:
  212. case GCRY_KEM_RAW_P384R1:
  213. case GCRY_KEM_RAW_P521R1:
  214. if (optional != NULL)
  215. return GPG_ERR_INV_VALUE;
  216. return _gcry_ecc_raw_decap (algo, seckey, seckey_len,
  217. ciphertext, ciphertext_len,
  218. shared, shared_len);
  219. case GCRY_KEM_DHKEM25519:
  220. case GCRY_KEM_DHKEM448:
  221. return _gcry_ecc_dhkem_decap (algo, seckey, ciphertext, shared,
  222. optional);
  223. default:
  224. return GPG_ERR_UNKNOWN_ALGORITHM;
  225. }
  226. return GPG_ERR_UNKNOWN_ALGORITHM;
  227. }
  228. /* Generate a KEM keypair using the s-expression interface. The
  229. * GENPARAMS is prety simple in this case because it has only the
  230. * algorithm name. For example:
  231. * (kyber768)
  232. */
  233. static gcry_err_code_t
  234. kem_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
  235. {
  236. gpg_err_code_t ec;
  237. const char *algo;
  238. size_t algolen;
  239. const char *name;
  240. int i;
  241. int algoid;
  242. void *pubkey = NULL;
  243. void *seckey = NULL;
  244. size_t pubkey_len, seckey_len;
  245. algo = sexp_nth_data (genparms, 0, &algolen);
  246. if (!algo || !algolen)
  247. return GPG_ERR_PUBKEY_ALGO;
  248. for (i=0; (name=kem_infos[i].name); i++)
  249. if (kem_infos[i].namelen == algolen && !memcmp (name, algo, algolen))
  250. break;
  251. if (!name)
  252. return GPG_ERR_WRONG_PUBKEY_ALGO;
  253. algoid = kem_infos[i].algo;
  254. pubkey_len = kem_infos[i].pubkey_len;
  255. seckey_len = kem_infos[i].seckey_len;
  256. /* (from here on we can jump to leave for cleanup) */
  257. /* Allocate buffers for the created key. */
  258. seckey = xtrycalloc_secure (1, seckey_len);
  259. if (!seckey)
  260. {
  261. ec = gpg_err_code_from_syserror ();
  262. goto leave;
  263. }
  264. pubkey = xtrycalloc (1, pubkey_len);
  265. if (!pubkey)
  266. {
  267. ec = gpg_err_code_from_syserror ();
  268. goto leave;
  269. }
  270. /* Generate key. */
  271. ec = _gcry_kem_keypair (algoid, pubkey, pubkey_len, seckey, seckey_len);
  272. if (ec)
  273. goto leave;
  274. /* Put the key into an s-expression. */
  275. ec = sexp_build (r_skey, NULL,
  276. "(key-data"
  277. " (public-key"
  278. " (%s(p%b)))"
  279. " (private-key"
  280. " (%s(p%b)(s%b))))",
  281. name,
  282. (int)pubkey_len, pubkey,
  283. name,
  284. (int)pubkey_len, pubkey,
  285. (int)seckey_len, seckey);
  286. /* FIXME: Add FIPS selftest. */
  287. leave:
  288. if (seckey)
  289. {
  290. wipememory (seckey, seckey_len);
  291. xfree (seckey);
  292. }
  293. xfree (pubkey);
  294. return ec;
  295. }
  296. /* Compute a keygrip. MD is the hash context which we are going to
  297. * update. KEYPARAM is an S-expression with the key parameters, this
  298. * is usually a public key but may also be a secret key. An example
  299. * of such an S-expression is:
  300. *
  301. * (kyber768
  302. * (p #4243...#)
  303. * (s #1718...#))
  304. *
  305. * What we hash is the algorithm name, \x00 and the value of p.
  306. * Including the algorithm name allows us to see a different key
  307. * despite that it uses the same parameters. Whether this is a good
  308. * decision is not clear - but it should not harm.
  309. */
  310. static gpg_err_code_t
  311. kem_compute_keygrip (gcry_md_hd_t md, gcry_sexp_t keyparam)
  312. {
  313. gcry_sexp_t l1;
  314. const char *algo, *data;
  315. size_t algolen, datalen;
  316. const char *name;
  317. int i;
  318. algo = sexp_nth_data (keyparam, 0, &algolen);
  319. if (!algo || !algolen)
  320. return GPG_ERR_PUBKEY_ALGO;
  321. for (i=0; (name=kem_infos[i].name); i++)
  322. if (kem_infos[i].namelen == algolen && !memcmp (name, algo, algolen))
  323. break;
  324. if (!name)
  325. return GPG_ERR_WRONG_PUBKEY_ALGO;
  326. _gcry_md_write (md, name, algolen+1); /* (also hash the nul) */
  327. l1 = sexp_find_token (keyparam, "p", 1);
  328. if (!l1)
  329. return GPG_ERR_NO_OBJ;
  330. data = sexp_nth_data (l1, 1, &datalen);
  331. if (!data)
  332. {
  333. sexp_release (l1);
  334. return GPG_ERR_NO_OBJ;
  335. }
  336. _gcry_md_write (md, data, datalen);
  337. sexp_release (l1);
  338. return 0;
  339. }
  340. /* Return the number of bits for the key described by PARMS. On error
  341. * 0 is returned. */
  342. static unsigned int
  343. kem_get_nbits (gcry_sexp_t keyparam)
  344. {
  345. const char *algo;
  346. size_t algolen;
  347. const char *name;
  348. int i;
  349. algo = sexp_nth_data (keyparam, 0, &algolen);
  350. if (!algo || !algolen)
  351. return 0; /* GPG_ERR_PUBKEY_ALGO */
  352. for (i=0; (name=kem_infos[i].name); i++)
  353. if (kem_infos[i].namelen == algolen && !memcmp (name, algo, algolen))
  354. break;
  355. if (!name)
  356. return 0; /* GPG_ERR_WRONG_PUBKEY_ALGO */
  357. return kem_infos[i].nbits;
  358. }
  359. /* Generic structure to represent some KEM algorithms in our public
  360. * key system. */
  361. gcry_pk_spec_t _gcry_pubkey_spec_kem =
  362. {
  363. GCRY_PK_KEM, { 0, 0 },
  364. GCRY_PK_USAGE_ENCR,
  365. "KEM", kem_names,
  366. "p", "s", "k", "", "p",
  367. kem_generate,
  368. NULL, /* kem_check_secret_key */
  369. NULL, /* encrypt_raw - Use gcry_kem_encap instead. */
  370. NULL, /* decrypt_raw - Use gcry_kem_decap unstead. */
  371. NULL, /* sign */
  372. NULL, /* verify */
  373. kem_get_nbits,
  374. NULL, /* selftests */
  375. kem_compute_keygrip,
  376. NULL, /* get_curve */
  377. NULL /* get_curve_param */
  378. };