pmeth_gn.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. /*
  2. * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License 2.0 (the "License"). You may not use
  5. * this file except in compliance with the License. You can obtain a copy
  6. * in the file LICENSE in the source distribution or at
  7. * https://www.openssl.org/source/license.html
  8. */
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <openssl/core.h>
  12. #include <openssl/core_names.h>
  13. #include "internal/cryptlib.h"
  14. #include "internal/core.h"
  15. #include <openssl/objects.h>
  16. #include <openssl/evp.h>
  17. #include "crypto/bn.h"
  18. #include "crypto/asn1.h"
  19. #include "crypto/evp.h"
  20. #include "evp_local.h"
  21. #if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_EC)
  22. # define TMP_SM2_HACK
  23. #endif
  24. /* TODO(3.0) remove when provider SM2 key generation is implemented */
  25. #ifdef TMP_SM2_HACK
  26. # include <openssl/ec.h>
  27. # include "internal/sizes.h"
  28. #endif
  29. static int gen_init(EVP_PKEY_CTX *ctx, int operation)
  30. {
  31. int ret = 0;
  32. if (ctx == NULL)
  33. goto not_supported;
  34. evp_pkey_ctx_free_old_ops(ctx);
  35. ctx->operation = operation;
  36. if (ctx->keymgmt == NULL || ctx->keymgmt->gen_init == NULL)
  37. goto legacy;
  38. /* TODO remove when provider SM2 key generation is implemented */
  39. #ifdef TMP_SM2_HACK
  40. if (ctx->pmeth != NULL && ctx->pmeth->pkey_id == EVP_PKEY_SM2)
  41. goto legacy;
  42. #endif
  43. switch (operation) {
  44. case EVP_PKEY_OP_PARAMGEN:
  45. ctx->op.keymgmt.genctx =
  46. evp_keymgmt_gen_init(ctx->keymgmt,
  47. OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
  48. break;
  49. case EVP_PKEY_OP_KEYGEN:
  50. ctx->op.keymgmt.genctx =
  51. evp_keymgmt_gen_init(ctx->keymgmt, OSSL_KEYMGMT_SELECT_KEYPAIR);
  52. break;
  53. }
  54. if (ctx->op.keymgmt.genctx == NULL)
  55. ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
  56. else
  57. ret = 1;
  58. goto end;
  59. legacy:
  60. #ifdef FIPS_MODULE
  61. goto not_supported;
  62. #else
  63. if (ctx->pmeth == NULL
  64. || (operation == EVP_PKEY_OP_PARAMGEN
  65. && ctx->pmeth->paramgen == NULL)
  66. || (operation == EVP_PKEY_OP_KEYGEN
  67. && ctx->pmeth->keygen == NULL))
  68. goto not_supported;
  69. ret = 1;
  70. switch (operation) {
  71. case EVP_PKEY_OP_PARAMGEN:
  72. if (ctx->pmeth->paramgen_init != NULL)
  73. ret = ctx->pmeth->paramgen_init(ctx);
  74. break;
  75. case EVP_PKEY_OP_KEYGEN:
  76. if (ctx->pmeth->keygen_init != NULL)
  77. ret = ctx->pmeth->keygen_init(ctx);
  78. break;
  79. }
  80. #endif
  81. end:
  82. if (ret <= 0 && ctx != NULL) {
  83. evp_pkey_ctx_free_old_ops(ctx);
  84. ctx->operation = EVP_PKEY_OP_UNDEFINED;
  85. }
  86. return ret;
  87. not_supported:
  88. ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
  89. ret = -2;
  90. goto end;
  91. }
  92. int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx)
  93. {
  94. return gen_init(ctx, EVP_PKEY_OP_PARAMGEN);
  95. }
  96. int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx)
  97. {
  98. return gen_init(ctx, EVP_PKEY_OP_KEYGEN);
  99. }
  100. static int ossl_callback_to_pkey_gencb(const OSSL_PARAM params[], void *arg)
  101. {
  102. EVP_PKEY_CTX *ctx = arg;
  103. const OSSL_PARAM *param = NULL;
  104. int p = -1, n = -1;
  105. if (ctx->pkey_gencb == NULL)
  106. return 1; /* No callback? That's fine */
  107. if ((param = OSSL_PARAM_locate_const(params, OSSL_GEN_PARAM_POTENTIAL))
  108. == NULL
  109. || !OSSL_PARAM_get_int(param, &p))
  110. return 0;
  111. if ((param = OSSL_PARAM_locate_const(params, OSSL_GEN_PARAM_ITERATION))
  112. == NULL
  113. || !OSSL_PARAM_get_int(param, &n))
  114. return 0;
  115. ctx->keygen_info[0] = p;
  116. ctx->keygen_info[1] = n;
  117. return ctx->pkey_gencb(ctx);
  118. }
  119. int EVP_PKEY_gen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
  120. {
  121. int ret = 0;
  122. OSSL_CALLBACK cb;
  123. EVP_PKEY *allocated_pkey = NULL;
  124. /* Legacy compatible keygen callback info, only used with provider impls */
  125. int gentmp[2];
  126. if (ppkey == NULL)
  127. return -1;
  128. if (ctx == NULL)
  129. goto not_supported;
  130. if ((ctx->operation & EVP_PKEY_OP_TYPE_GEN) == 0)
  131. goto not_initialized;
  132. if (*ppkey == NULL)
  133. *ppkey = allocated_pkey = EVP_PKEY_new();
  134. if (*ppkey == NULL) {
  135. ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
  136. return -1;
  137. }
  138. if (ctx->op.keymgmt.genctx == NULL)
  139. goto legacy;
  140. /*
  141. * Asssigning gentmp to ctx->keygen_info is something our legacy
  142. * implementations do. Because the provider implementations aren't
  143. * allowed to reach into our EVP_PKEY_CTX, we need to provide similar
  144. * space for backward compatibility. It's ok that we attach a local
  145. * variable, as it should only be useful in the calls down from here.
  146. * This is cleared as soon as it isn't useful any more, i.e. directly
  147. * after the evp_keymgmt_util_gen() call.
  148. */
  149. ctx->keygen_info = gentmp;
  150. ctx->keygen_info_count = 2;
  151. ret = 1;
  152. if (ctx->pkey != NULL) {
  153. EVP_KEYMGMT *tmp_keymgmt = ctx->keymgmt;
  154. void *keydata =
  155. evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
  156. &tmp_keymgmt, ctx->propquery);
  157. if (tmp_keymgmt == NULL)
  158. goto not_supported;
  159. /*
  160. * It's ok if keydata is NULL here. The backend is expected to deal
  161. * with that as it sees fit.
  162. */
  163. ret = evp_keymgmt_gen_set_template(ctx->keymgmt,
  164. ctx->op.keymgmt.genctx, keydata);
  165. }
  166. /*
  167. * the returned value from evp_keymgmt_util_gen() is cached in *ppkey,
  168. * so we so not need to save it, just check it.
  169. */
  170. ret = ret
  171. && (evp_keymgmt_util_gen(*ppkey, ctx->keymgmt, ctx->op.keymgmt.genctx,
  172. ossl_callback_to_pkey_gencb, ctx)
  173. != NULL);
  174. ctx->keygen_info = NULL;
  175. #ifndef FIPS_MODULE
  176. /* In case |*ppkey| was originally a legacy key */
  177. if (ret)
  178. evp_pkey_free_legacy(*ppkey);
  179. #endif
  180. /*
  181. * Because we still have legacy keys, and evp_pkey_downgrade()
  182. * TODO remove this #legacy internal keys are gone
  183. */
  184. (*ppkey)->type = ctx->legacy_keytype;
  185. /* TODO remove when SM2 key have been cleanly separated from EC keys */
  186. #ifdef TMP_SM2_HACK
  187. /*
  188. * Legacy SM2 keys are implemented as EC_KEY with a twist. The legacy
  189. * key generation detects the SM2 curve and "magically" changes the pkey
  190. * id accordingly.
  191. * Since we don't have SM2 in the provider implementation, we need to
  192. * downgrade the generated provider side key to a legacy one under the
  193. * same conditions.
  194. *
  195. * THIS IS AN UGLY BUT TEMPORARY HACK
  196. */
  197. {
  198. char curve_name[OSSL_MAX_NAME_SIZE] = "";
  199. if (!EVP_PKEY_get_utf8_string_param(*ppkey, OSSL_PKEY_PARAM_GROUP_NAME,
  200. curve_name, sizeof(curve_name),
  201. NULL)
  202. || strcmp(curve_name, "SM2") != 0)
  203. goto end;
  204. }
  205. if (!evp_pkey_downgrade(*ppkey)
  206. || !EVP_PKEY_set_alias_type(*ppkey, EVP_PKEY_SM2))
  207. ret = 0;
  208. #endif
  209. goto end;
  210. legacy:
  211. #ifdef FIPS_MODULE
  212. goto not_supported;
  213. #else
  214. if (ctx->pkey && !evp_pkey_downgrade(ctx->pkey))
  215. goto not_accessible;
  216. switch (ctx->operation) {
  217. case EVP_PKEY_OP_PARAMGEN:
  218. ret = ctx->pmeth->paramgen(ctx, *ppkey);
  219. break;
  220. case EVP_PKEY_OP_KEYGEN:
  221. ret = ctx->pmeth->keygen(ctx, *ppkey);
  222. break;
  223. default:
  224. goto not_supported;
  225. }
  226. #endif
  227. end:
  228. if (ret <= 0) {
  229. if (allocated_pkey != NULL)
  230. *ppkey = NULL;
  231. EVP_PKEY_free(allocated_pkey);
  232. }
  233. return ret;
  234. not_supported:
  235. ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
  236. ret = -2;
  237. goto end;
  238. not_initialized:
  239. ERR_raise(ERR_LIB_EVP, EVP_R_OPERATON_NOT_INITIALIZED);
  240. ret = -1;
  241. goto end;
  242. #ifndef FIPS_MODULE
  243. not_accessible:
  244. ERR_raise(ERR_LIB_EVP, EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS);
  245. ret = -1;
  246. goto end;
  247. #endif
  248. }
  249. int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
  250. {
  251. if (ctx->operation != EVP_PKEY_OP_PARAMGEN) {
  252. ERR_raise(ERR_LIB_EVP, EVP_R_OPERATON_NOT_INITIALIZED);
  253. return -1;
  254. }
  255. return EVP_PKEY_gen(ctx, ppkey);
  256. }
  257. int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
  258. {
  259. if (ctx->operation != EVP_PKEY_OP_KEYGEN) {
  260. ERR_raise(ERR_LIB_EVP, EVP_R_OPERATON_NOT_INITIALIZED);
  261. return -1;
  262. }
  263. return EVP_PKEY_gen(ctx, ppkey);
  264. }
  265. void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb)
  266. {
  267. ctx->pkey_gencb = cb;
  268. }
  269. EVP_PKEY_gen_cb *EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx)
  270. {
  271. return ctx->pkey_gencb;
  272. }
  273. /*
  274. * "translation callback" to call EVP_PKEY_CTX callbacks using BN_GENCB style
  275. * callbacks.
  276. */
  277. static int trans_cb(int a, int b, BN_GENCB *gcb)
  278. {
  279. EVP_PKEY_CTX *ctx = BN_GENCB_get_arg(gcb);
  280. ctx->keygen_info[0] = a;
  281. ctx->keygen_info[1] = b;
  282. return ctx->pkey_gencb(ctx);
  283. }
  284. void evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx)
  285. {
  286. BN_GENCB_set(cb, trans_cb, ctx);
  287. }
  288. int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx)
  289. {
  290. if (idx == -1)
  291. return ctx->keygen_info_count;
  292. if (idx < 0 || idx > ctx->keygen_info_count)
  293. return 0;
  294. return ctx->keygen_info[idx];
  295. }
  296. #ifndef FIPS_MODULE
  297. EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e,
  298. const unsigned char *key, int keylen)
  299. {
  300. EVP_PKEY_CTX *mac_ctx = NULL;
  301. EVP_PKEY *mac_key = NULL;
  302. mac_ctx = EVP_PKEY_CTX_new_id(type, e);
  303. if (!mac_ctx)
  304. return NULL;
  305. if (EVP_PKEY_keygen_init(mac_ctx) <= 0)
  306. goto merr;
  307. if (EVP_PKEY_CTX_set_mac_key(mac_ctx, key, keylen) <= 0)
  308. goto merr;
  309. if (EVP_PKEY_keygen(mac_ctx, &mac_key) <= 0)
  310. goto merr;
  311. merr:
  312. EVP_PKEY_CTX_free(mac_ctx);
  313. return mac_key;
  314. }
  315. #endif /* FIPS_MODULE */
  316. /*- All methods below can also be used in FIPS_MODULE */
  317. static int fromdata_init(EVP_PKEY_CTX *ctx, int operation)
  318. {
  319. if (ctx == NULL || ctx->keytype == NULL)
  320. goto not_supported;
  321. evp_pkey_ctx_free_old_ops(ctx);
  322. if (ctx->keymgmt == NULL)
  323. goto not_supported;
  324. ctx->operation = operation;
  325. return 1;
  326. not_supported:
  327. if (ctx != NULL)
  328. ctx->operation = EVP_PKEY_OP_UNDEFINED;
  329. ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
  330. return -2;
  331. }
  332. int EVP_PKEY_param_fromdata_init(EVP_PKEY_CTX *ctx)
  333. {
  334. return fromdata_init(ctx, EVP_PKEY_OP_PARAMFROMDATA);
  335. }
  336. int EVP_PKEY_key_fromdata_init(EVP_PKEY_CTX *ctx)
  337. {
  338. return fromdata_init(ctx, EVP_PKEY_OP_KEYFROMDATA);
  339. }
  340. int EVP_PKEY_fromdata(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey, OSSL_PARAM params[])
  341. {
  342. void *keydata = NULL;
  343. int selection;
  344. if (ctx == NULL || (ctx->operation & EVP_PKEY_OP_TYPE_FROMDATA) == 0) {
  345. ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
  346. return -2;
  347. }
  348. if (ppkey == NULL)
  349. return -1;
  350. if (*ppkey == NULL)
  351. *ppkey = EVP_PKEY_new();
  352. if (*ppkey == NULL) {
  353. ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
  354. return -1;
  355. }
  356. if (ctx->operation == EVP_PKEY_OP_PARAMFROMDATA)
  357. selection = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS;
  358. else
  359. selection = OSSL_KEYMGMT_SELECT_ALL;
  360. keydata = evp_keymgmt_util_fromdata(*ppkey, ctx->keymgmt, selection,
  361. params);
  362. if (keydata == NULL)
  363. return 0;
  364. /* keydata is cached in *ppkey, so we need not bother with it further */
  365. return 1;
  366. }
  367. /*
  368. * TODO(3.0) Re-evaluate the names, it's possible that we find these to be
  369. * better:
  370. *
  371. * EVP_PKEY_param_settable()
  372. * EVP_PKEY_param_gettable()
  373. */
  374. const OSSL_PARAM *EVP_PKEY_param_fromdata_settable(EVP_PKEY_CTX *ctx)
  375. {
  376. /* We call fromdata_init to get ctx->keymgmt populated */
  377. if (fromdata_init(ctx, EVP_PKEY_OP_UNDEFINED))
  378. return evp_keymgmt_import_types(ctx->keymgmt,
  379. OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
  380. return NULL;
  381. }
  382. const OSSL_PARAM *EVP_PKEY_key_fromdata_settable(EVP_PKEY_CTX *ctx)
  383. {
  384. /* We call fromdata_init to get ctx->keymgmt populated */
  385. if (fromdata_init(ctx, EVP_PKEY_OP_UNDEFINED))
  386. return evp_keymgmt_import_types(ctx->keymgmt,
  387. OSSL_KEYMGMT_SELECT_ALL);
  388. return NULL;
  389. }