2016-05-18 02:24:46 +08:00
|
|
|
/*
|
2018-03-20 21:00:17 +08:00
|
|
|
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
|
1998-12-21 18:52:47 +08:00
|
|
|
*
|
2018-12-06 20:40:06 +08:00
|
|
|
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
2016-05-18 02:24:46 +08:00
|
|
|
* this file except in compliance with the License. You can obtain a copy
|
|
|
|
* in the file LICENSE in the source distribution or at
|
|
|
|
* https://www.openssl.org/source/license.html
|
1998-12-21 18:52:47 +08:00
|
|
|
*/
|
|
|
|
|
2020-01-30 05:23:39 +08:00
|
|
|
/*
|
|
|
|
* DSA low level APIs are deprecated for public use, but still ok for
|
|
|
|
* internal use.
|
|
|
|
*/
|
|
|
|
#include "internal/deprecated.h"
|
|
|
|
|
1998-12-21 18:52:47 +08:00
|
|
|
#include <stdio.h>
|
2015-05-14 22:56:48 +08:00
|
|
|
#include "internal/cryptlib.h"
|
2017-08-22 05:17:35 +08:00
|
|
|
#include "internal/refcount.h"
|
2002-02-14 02:21:51 +08:00
|
|
|
#include <openssl/bn.h>
|
|
|
|
#include <openssl/err.h>
|
1999-04-24 06:13:45 +08:00
|
|
|
#include <openssl/objects.h>
|
|
|
|
#include <openssl/evp.h>
|
|
|
|
#include <openssl/x509.h>
|
2016-03-19 02:30:20 +08:00
|
|
|
#include <openssl/rsa.h>
|
|
|
|
#include <openssl/dsa.h>
|
|
|
|
#include <openssl/dh.h>
|
2018-03-06 01:23:57 +08:00
|
|
|
#include <openssl/cmac.h>
|
2016-03-19 02:30:20 +08:00
|
|
|
#include <openssl/engine.h>
|
2019-05-07 18:39:58 +08:00
|
|
|
#include <openssl/params.h>
|
2019-11-18 08:47:32 +08:00
|
|
|
#include <openssl/serializer.h>
|
2019-05-07 18:39:58 +08:00
|
|
|
#include <openssl/core_names.h>
|
2006-06-05 19:52:46 +08:00
|
|
|
|
2019-09-28 06:45:33 +08:00
|
|
|
#include "crypto/asn1.h"
|
|
|
|
#include "crypto/evp.h"
|
2019-05-07 18:39:58 +08:00
|
|
|
#include "internal/provider.h"
|
2020-01-14 21:11:47 +08:00
|
|
|
#include "evp_local.h"
|
2006-03-23 01:59:49 +08:00
|
|
|
|
2020-01-12 09:32:12 +08:00
|
|
|
static void evp_pkey_free_it(EVP_PKEY *key);
|
|
|
|
|
|
|
|
#ifndef FIPS_MODE
|
2001-08-04 02:48:35 +08:00
|
|
|
|
2016-08-17 20:50:48 +08:00
|
|
|
int EVP_PKEY_bits(const EVP_PKEY *pkey)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2020-01-08 10:44:28 +08:00
|
|
|
if (pkey != NULL) {
|
|
|
|
if (pkey->ameth == NULL)
|
|
|
|
return pkey->cache.bits;
|
|
|
|
else if (pkey->ameth->pkey_bits)
|
|
|
|
return pkey->ameth->pkey_bits(pkey);
|
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
1998-12-21 18:56:39 +08:00
|
|
|
|
2014-01-18 22:51:40 +08:00
|
|
|
int EVP_PKEY_security_bits(const EVP_PKEY *pkey)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (pkey == NULL)
|
|
|
|
return 0;
|
2020-01-08 10:44:28 +08:00
|
|
|
if (pkey->ameth == NULL)
|
|
|
|
return pkey->cache.security_bits;
|
|
|
|
if (pkey->ameth->pkey_security_bits == NULL)
|
2015-01-22 11:40:55 +08:00
|
|
|
return -2;
|
|
|
|
return pkey->ameth->pkey_security_bits(pkey);
|
|
|
|
}
|
2014-01-18 22:51:40 +08:00
|
|
|
|
1999-04-20 05:31:43 +08:00
|
|
|
int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2020-01-12 09:32:12 +08:00
|
|
|
# ifndef OPENSSL_NO_DSA
|
2015-01-22 11:40:55 +08:00
|
|
|
if (pkey->type == EVP_PKEY_DSA) {
|
|
|
|
int ret = pkey->save_parameters;
|
|
|
|
|
|
|
|
if (mode >= 0)
|
|
|
|
pkey->save_parameters = mode;
|
2017-10-17 22:04:09 +08:00
|
|
|
return ret;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2020-01-12 09:32:12 +08:00
|
|
|
# endif
|
|
|
|
# ifndef OPENSSL_NO_EC
|
2015-01-22 11:40:55 +08:00
|
|
|
if (pkey->type == EVP_PKEY_EC) {
|
|
|
|
int ret = pkey->save_parameters;
|
|
|
|
|
|
|
|
if (mode >= 0)
|
|
|
|
pkey->save_parameters = mode;
|
2017-10-17 22:04:09 +08:00
|
|
|
return ret;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2020-01-12 09:32:12 +08:00
|
|
|
# endif
|
2017-10-17 22:04:09 +08:00
|
|
|
return 0;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2003-04-07 18:09:44 +08:00
|
|
|
int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2020-02-05 23:30:21 +08:00
|
|
|
/*
|
|
|
|
* TODO: clean up legacy stuff from this function when legacy support
|
|
|
|
* is gone.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Only check that type match this early when both keys are legacy.
|
|
|
|
* If either of them is provided, we let evp_keymgmt_util_copy()
|
|
|
|
* do this check, after having exported either of them that isn't
|
|
|
|
* provided.
|
|
|
|
*/
|
|
|
|
if (to->keymgmt == NULL && from->keymgmt == NULL) {
|
|
|
|
if (to->type == EVP_PKEY_NONE) {
|
|
|
|
if (EVP_PKEY_set_type(to, from->type) == 0)
|
|
|
|
return 0;
|
|
|
|
} else if (to->type != from->type) {
|
|
|
|
EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_DIFFERENT_KEY_TYPES);
|
|
|
|
goto err;
|
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (EVP_PKEY_missing_parameters(from)) {
|
|
|
|
EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_MISSING_PARAMETERS);
|
|
|
|
goto err;
|
|
|
|
}
|
2016-05-27 21:18:40 +08:00
|
|
|
|
|
|
|
if (!EVP_PKEY_missing_parameters(to)) {
|
|
|
|
if (EVP_PKEY_cmp_parameters(to, from) == 1)
|
|
|
|
return 1;
|
|
|
|
EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_DIFFERENT_PARAMETERS);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-02-05 23:30:21 +08:00
|
|
|
/*
|
|
|
|
* If |from| is provided, we upgrade |to| to be provided as well.
|
|
|
|
* This drops the legacy key from |to|.
|
|
|
|
* evp_pkey_upgrade_to_provider() checks if |to| is already provided,
|
|
|
|
* we don't need to do that here.
|
|
|
|
*
|
|
|
|
* TODO(3.0) We should investigate if that's too aggressive and make
|
|
|
|
* this scenario unsupported instead.
|
|
|
|
*/
|
|
|
|
if (from->keymgmt != NULL) {
|
|
|
|
EVP_KEYMGMT *tmp_keymgmt = from->keymgmt;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The returned pointer is known to be cached, so we don't have to
|
|
|
|
* save it. However, if it's NULL, something went wrong and we can't
|
|
|
|
* copy.
|
|
|
|
*/
|
|
|
|
if (evp_pkey_upgrade_to_provider(to, NULL,
|
|
|
|
&tmp_keymgmt, NULL) == NULL) {
|
|
|
|
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* For purely provided keys, we just call the keymgmt utility */
|
|
|
|
if (to->keymgmt != NULL && from->keymgmt != NULL)
|
|
|
|
return evp_keymgmt_util_copy(to, (EVP_PKEY *)from,
|
|
|
|
OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If |to| is provided, we know that |from| is legacy at this point.
|
|
|
|
* Try exporting |from| to |to|'s keymgmt, then use evp_keymgmt_copy()
|
|
|
|
* to copy the appropriate data to |to|'s keydata.
|
|
|
|
*/
|
|
|
|
if (to->keymgmt != NULL) {
|
|
|
|
EVP_KEYMGMT *to_keymgmt = to->keymgmt;
|
|
|
|
void *from_keydata =
|
|
|
|
evp_pkey_export_to_provider((EVP_PKEY *)from, NULL, &to_keymgmt,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (from_keydata == NULL) {
|
|
|
|
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return evp_keymgmt_copy(to->keymgmt, to->keydata, from_keydata,
|
|
|
|
OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Both keys are legacy */
|
|
|
|
if (from->ameth != NULL && from->ameth->param_copy != NULL)
|
2015-01-22 11:40:55 +08:00
|
|
|
return from->ameth->param_copy(to, from);
|
|
|
|
err:
|
|
|
|
return 0;
|
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2003-04-06 23:31:18 +08:00
|
|
|
int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2020-02-05 17:18:51 +08:00
|
|
|
if (pkey != NULL) {
|
|
|
|
if (pkey->keymgmt != NULL)
|
|
|
|
return !evp_keymgmt_util_has((EVP_PKEY *)pkey,
|
|
|
|
OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
|
|
|
|
else if (pkey->ameth != NULL && pkey->ameth->param_missing != NULL)
|
|
|
|
return pkey->ameth->param_missing(pkey);
|
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2020-02-05 19:55:43 +08:00
|
|
|
/*
|
|
|
|
* This function is called for any mixture of keys except pure legacy pair.
|
|
|
|
* TODO When legacy keys are gone, we replace a call to this functions with
|
|
|
|
* a call to evp_keymgmt_util_match().
|
|
|
|
*/
|
|
|
|
static int evp_pkey_cmp_any(const EVP_PKEY *a, const EVP_PKEY *b,
|
|
|
|
int selection)
|
|
|
|
{
|
|
|
|
EVP_KEYMGMT *keymgmt1 = NULL, *keymgmt2 = NULL;
|
|
|
|
void *keydata1 = NULL, *keydata2 = NULL, *tmp_keydata = NULL;
|
|
|
|
|
|
|
|
/* If none of them are provided, this function shouldn't have been called */
|
|
|
|
if (!ossl_assert(a->keymgmt != NULL || b->keymgmt != NULL))
|
|
|
|
return -2;
|
|
|
|
|
|
|
|
/* For purely provided keys, we just call the keymgmt utility */
|
|
|
|
if (a->keymgmt != NULL && b->keymgmt != NULL)
|
|
|
|
return evp_keymgmt_util_match((EVP_PKEY *)a, (EVP_PKEY *)b, selection);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Here, we know that we have a mixture of legacy and provided keys.
|
|
|
|
* Try cross export and compare the resulting key data.
|
|
|
|
*/
|
|
|
|
keymgmt1 = a->keymgmt;
|
|
|
|
keydata1 = a->keydata;
|
|
|
|
keymgmt2 = b->keymgmt;
|
|
|
|
keydata2 = b->keydata;
|
|
|
|
|
|
|
|
if ((keymgmt1 == NULL
|
|
|
|
&& !EVP_KEYMGMT_is_a(keymgmt2, OBJ_nid2sn(a->type)))
|
|
|
|
|| (keymgmt2 == NULL
|
|
|
|
&& !EVP_KEYMGMT_is_a(keymgmt1, OBJ_nid2sn(b->type))))
|
|
|
|
return -1; /* not the same key type */
|
|
|
|
|
|
|
|
if (keymgmt2 != NULL && keymgmt2->match != NULL) {
|
|
|
|
tmp_keydata =
|
|
|
|
evp_pkey_export_to_provider((EVP_PKEY *)a, NULL, &keymgmt2, NULL);
|
|
|
|
if (tmp_keydata != NULL) {
|
|
|
|
keymgmt1 = keymgmt2;
|
|
|
|
keydata1 = tmp_keydata;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (tmp_keydata == NULL && keymgmt1 != NULL && keymgmt1->match != NULL) {
|
|
|
|
tmp_keydata =
|
|
|
|
evp_pkey_export_to_provider((EVP_PKEY *)b, NULL, &keymgmt1, NULL);
|
|
|
|
if (tmp_keydata != NULL) {
|
|
|
|
keymgmt2 = keymgmt1;
|
|
|
|
keydata2 = tmp_keydata;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If we still don't have matching keymgmt implementations, we give up */
|
|
|
|
if (keymgmt1 != keymgmt2)
|
|
|
|
return -2;
|
|
|
|
|
|
|
|
return evp_keymgmt_match(keymgmt1, keydata1, keydata2, selection);
|
|
|
|
}
|
|
|
|
|
2003-04-06 23:31:18 +08:00
|
|
|
int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2020-02-05 19:55:43 +08:00
|
|
|
/*
|
|
|
|
* TODO: clean up legacy stuff from this function when legacy support
|
|
|
|
* is gone.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (a->keymgmt != NULL || b->keymgmt != NULL)
|
|
|
|
return evp_pkey_cmp_any(a, b, OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
|
|
|
|
|
|
|
|
/* All legacy keys */
|
2015-01-22 11:40:55 +08:00
|
|
|
if (a->type != b->type)
|
|
|
|
return -1;
|
2020-02-05 19:55:43 +08:00
|
|
|
if (a->ameth != NULL && a->ameth->param_cmp != NULL)
|
2015-01-22 11:40:55 +08:00
|
|
|
return a->ameth->param_cmp(a, b);
|
|
|
|
return -2;
|
|
|
|
}
|
1998-12-21 18:56:39 +08:00
|
|
|
|
2003-04-06 23:31:18 +08:00
|
|
|
int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2020-02-05 19:55:43 +08:00
|
|
|
/*
|
|
|
|
* TODO: clean up legacy stuff from this function when legacy support
|
|
|
|
* is gone.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (a->keymgmt != NULL || b->keymgmt != NULL)
|
|
|
|
return evp_pkey_cmp_any(a, b,
|
|
|
|
OSSL_KEYMGMT_SELECT_ALL_PARAMETERS
|
|
|
|
| OSSL_KEYMGMT_SELECT_PUBLIC_KEY);
|
|
|
|
|
|
|
|
/* All legacy keys */
|
2015-01-22 11:40:55 +08:00
|
|
|
if (a->type != b->type)
|
|
|
|
return -1;
|
|
|
|
|
2020-02-05 19:55:43 +08:00
|
|
|
if (a->ameth != NULL) {
|
2015-01-22 11:40:55 +08:00
|
|
|
int ret;
|
|
|
|
/* Compare parameters if the algorithm has them */
|
2020-02-05 19:55:43 +08:00
|
|
|
if (a->ameth->param_cmp != NULL) {
|
2015-01-22 11:40:55 +08:00
|
|
|
ret = a->ameth->param_cmp(a, b);
|
|
|
|
if (ret <= 0)
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2020-02-05 19:55:43 +08:00
|
|
|
if (a->ameth->pub_cmp != NULL)
|
2015-01-22 11:40:55 +08:00
|
|
|
return a->ameth->pub_cmp(a, b);
|
|
|
|
}
|
|
|
|
|
|
|
|
return -2;
|
|
|
|
}
|
2003-04-04 06:27:24 +08:00
|
|
|
|
2015-12-14 01:57:01 +08:00
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
/*
|
|
|
|
* Setup a public key ASN1 method and ENGINE from a NID or a string. If pkey
|
|
|
|
* is NULL just return 1 or 0 if the algorithm exists.
|
2006-06-05 19:52:46 +08:00
|
|
|
*/
|
|
|
|
|
2018-03-05 22:06:41 +08:00
|
|
|
static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str,
|
|
|
|
int len)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
const EVP_PKEY_ASN1_METHOD *ameth;
|
2018-03-05 22:06:41 +08:00
|
|
|
ENGINE **eptr = (e == NULL) ? &e : NULL;
|
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
if (pkey) {
|
|
|
|
if (pkey->pkey.ptr)
|
2020-01-12 09:32:12 +08:00
|
|
|
evp_pkey_free_it(pkey);
|
2015-01-22 11:40:55 +08:00
|
|
|
/*
|
|
|
|
* If key type matches and a method exists then this lookup has
|
|
|
|
* succeeded once so just indicate success.
|
|
|
|
*/
|
|
|
|
if ((type == pkey->save_type) && pkey->ameth)
|
|
|
|
return 1;
|
2020-01-12 09:32:12 +08:00
|
|
|
# ifndef OPENSSL_NO_ENGINE
|
2017-10-09 22:21:11 +08:00
|
|
|
/* If we have ENGINEs release them */
|
2016-02-26 01:09:06 +08:00
|
|
|
ENGINE_finish(pkey->engine);
|
|
|
|
pkey->engine = NULL;
|
2017-10-09 22:21:11 +08:00
|
|
|
ENGINE_finish(pkey->pmeth_engine);
|
|
|
|
pkey->pmeth_engine = NULL;
|
2020-01-12 09:32:12 +08:00
|
|
|
# endif
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
|
|
|
if (str)
|
2018-03-05 22:06:41 +08:00
|
|
|
ameth = EVP_PKEY_asn1_find_str(eptr, str, len);
|
2015-01-22 11:40:55 +08:00
|
|
|
else
|
2018-03-05 22:06:41 +08:00
|
|
|
ameth = EVP_PKEY_asn1_find(eptr, type);
|
2020-01-12 09:32:12 +08:00
|
|
|
# ifndef OPENSSL_NO_ENGINE
|
2018-03-05 22:06:41 +08:00
|
|
|
if (pkey == NULL && eptr != NULL)
|
2015-01-22 11:40:55 +08:00
|
|
|
ENGINE_finish(e);
|
2020-01-12 09:32:12 +08:00
|
|
|
# endif
|
2016-02-26 01:09:06 +08:00
|
|
|
if (ameth == NULL) {
|
2015-01-22 11:40:55 +08:00
|
|
|
EVPerr(EVP_F_PKEY_SET_TYPE, EVP_R_UNSUPPORTED_ALGORITHM);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (pkey) {
|
|
|
|
pkey->ameth = ameth;
|
|
|
|
pkey->engine = e;
|
|
|
|
|
|
|
|
pkey->type = pkey->ameth->pkey_id;
|
|
|
|
pkey->save_type = type;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
2006-06-05 19:52:46 +08:00
|
|
|
|
2018-03-15 20:19:16 +08:00
|
|
|
EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e,
|
|
|
|
const unsigned char *priv,
|
|
|
|
size_t len)
|
2018-03-05 22:06:41 +08:00
|
|
|
{
|
|
|
|
EVP_PKEY *ret = EVP_PKEY_new();
|
|
|
|
|
|
|
|
if (ret == NULL
|
|
|
|
|| !pkey_set_type(ret, e, type, NULL, -1)) {
|
|
|
|
/* EVPerr already called */
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret->ameth->set_priv_key == NULL) {
|
2018-03-15 20:19:16 +08:00
|
|
|
EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY,
|
2018-03-05 22:06:41 +08:00
|
|
|
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ret->ameth->set_priv_key(ret, priv, len)) {
|
2018-03-15 20:19:16 +08:00
|
|
|
EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY, EVP_R_KEY_SETUP_FAILED);
|
2018-03-05 22:06:41 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
err:
|
|
|
|
EVP_PKEY_free(ret);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-03-15 20:19:16 +08:00
|
|
|
EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e,
|
|
|
|
const unsigned char *pub,
|
|
|
|
size_t len)
|
2018-03-05 22:06:41 +08:00
|
|
|
{
|
|
|
|
EVP_PKEY *ret = EVP_PKEY_new();
|
|
|
|
|
|
|
|
if (ret == NULL
|
|
|
|
|| !pkey_set_type(ret, e, type, NULL, -1)) {
|
|
|
|
/* EVPerr already called */
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret->ameth->set_pub_key == NULL) {
|
2018-03-15 20:19:16 +08:00
|
|
|
EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY,
|
2018-03-05 22:06:41 +08:00
|
|
|
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ret->ameth->set_pub_key(ret, pub, len)) {
|
2018-03-15 20:19:16 +08:00
|
|
|
EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY, EVP_R_KEY_SETUP_FAILED);
|
2018-03-05 22:06:41 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
err:
|
|
|
|
EVP_PKEY_free(ret);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-06-01 19:22:28 +08:00
|
|
|
int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, unsigned char *priv,
|
|
|
|
size_t *len)
|
|
|
|
{
|
|
|
|
if (pkey->ameth->get_priv_key == NULL) {
|
|
|
|
EVPerr(EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY,
|
|
|
|
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pkey->ameth->get_priv_key(pkey, priv, len)) {
|
|
|
|
EVPerr(EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY, EVP_R_GET_RAW_KEY_FAILED);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub,
|
|
|
|
size_t *len)
|
|
|
|
{
|
|
|
|
if (pkey->ameth->get_pub_key == NULL) {
|
|
|
|
EVPerr(EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY,
|
|
|
|
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pkey->ameth->get_pub_key(pkey, pub, len)) {
|
|
|
|
EVPerr(EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY, EVP_R_GET_RAW_KEY_FAILED);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2018-03-06 01:23:57 +08:00
|
|
|
EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
|
|
|
|
size_t len, const EVP_CIPHER *cipher)
|
|
|
|
{
|
2020-01-12 09:32:12 +08:00
|
|
|
# ifndef OPENSSL_NO_CMAC
|
|
|
|
# ifndef OPENSSL_NO_ENGINE
|
2019-08-29 18:55:57 +08:00
|
|
|
const char *engine_id = e != NULL ? ENGINE_get_id(e) : NULL;
|
2020-01-12 09:32:12 +08:00
|
|
|
# endif
|
2019-05-07 18:39:58 +08:00
|
|
|
const char *cipher_name = EVP_CIPHER_name(cipher);
|
|
|
|
const OSSL_PROVIDER *prov = EVP_CIPHER_provider(cipher);
|
|
|
|
OPENSSL_CTX *libctx =
|
|
|
|
prov == NULL ? NULL : ossl_provider_library_context(prov);
|
2018-03-06 01:23:57 +08:00
|
|
|
EVP_PKEY *ret = EVP_PKEY_new();
|
2019-08-15 18:39:20 +08:00
|
|
|
EVP_MAC *cmac = EVP_MAC_fetch(libctx, OSSL_MAC_NAME_CMAC, NULL);
|
2019-05-07 18:39:58 +08:00
|
|
|
EVP_MAC_CTX *cmctx = cmac != NULL ? EVP_MAC_CTX_new(cmac) : NULL;
|
|
|
|
OSSL_PARAM params[4];
|
|
|
|
size_t paramsn = 0;
|
2018-03-06 01:23:57 +08:00
|
|
|
|
|
|
|
if (ret == NULL
|
|
|
|
|| cmctx == NULL
|
|
|
|
|| !pkey_set_type(ret, e, EVP_PKEY_CMAC, NULL, -1)) {
|
|
|
|
/* EVPerr already called */
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2020-01-12 09:32:12 +08:00
|
|
|
# ifndef OPENSSL_NO_ENGINE
|
2019-08-29 18:55:57 +08:00
|
|
|
if (engine_id != NULL)
|
2019-05-07 18:39:58 +08:00
|
|
|
params[paramsn++] =
|
2019-09-22 08:43:08 +08:00
|
|
|
OSSL_PARAM_construct_utf8_string("engine", (char *)engine_id, 0);
|
2020-01-12 09:32:12 +08:00
|
|
|
# endif
|
2019-08-28 23:18:05 +08:00
|
|
|
|
2019-05-07 18:39:58 +08:00
|
|
|
params[paramsn++] =
|
2019-08-22 18:50:00 +08:00
|
|
|
OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER,
|
2019-09-04 17:27:08 +08:00
|
|
|
(char *)cipher_name, 0);
|
2019-05-07 18:39:58 +08:00
|
|
|
params[paramsn++] =
|
|
|
|
OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
|
|
|
|
(char *)priv, len);
|
|
|
|
params[paramsn] = OSSL_PARAM_construct_end();
|
|
|
|
|
|
|
|
if (!EVP_MAC_CTX_set_params(cmctx, params)) {
|
2018-03-06 01:23:57 +08:00
|
|
|
EVPerr(EVP_F_EVP_PKEY_NEW_CMAC_KEY, EVP_R_KEY_SETUP_FAILED);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret->pkey.ptr = cmctx;
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
err:
|
|
|
|
EVP_PKEY_free(ret);
|
2018-10-25 03:40:00 +08:00
|
|
|
EVP_MAC_CTX_free(cmctx);
|
2019-05-07 18:39:58 +08:00
|
|
|
EVP_MAC_free(cmac);
|
2018-03-06 01:23:57 +08:00
|
|
|
return NULL;
|
2020-01-12 09:32:12 +08:00
|
|
|
# else
|
2018-03-19 18:35:16 +08:00
|
|
|
EVPerr(EVP_F_EVP_PKEY_NEW_CMAC_KEY,
|
|
|
|
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
|
|
|
return NULL;
|
2020-01-12 09:32:12 +08:00
|
|
|
# endif
|
2018-03-06 01:23:57 +08:00
|
|
|
}
|
2018-03-05 22:06:41 +08:00
|
|
|
|
2006-06-05 19:52:46 +08:00
|
|
|
int EVP_PKEY_set_type(EVP_PKEY *pkey, int type)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2018-03-05 22:06:41 +08:00
|
|
|
return pkey_set_type(pkey, NULL, type, NULL, -1);
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2006-06-05 19:52:46 +08:00
|
|
|
|
|
|
|
int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2018-03-05 22:06:41 +08:00
|
|
|
return pkey_set_type(pkey, NULL, EVP_PKEY_NONE, str, len);
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2018-06-19 03:49:15 +08:00
|
|
|
|
|
|
|
int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type)
|
|
|
|
{
|
|
|
|
if (pkey->type == type) {
|
|
|
|
return 1; /* it already is that type */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The application is requesting to alias this to a different pkey type,
|
|
|
|
* but not one that resolves to the base type.
|
|
|
|
*/
|
|
|
|
if (EVP_PKEY_type(type) != EVP_PKEY_base_id(pkey)) {
|
|
|
|
EVPerr(EVP_F_EVP_PKEY_SET_ALIAS_TYPE, EVP_R_UNSUPPORTED_ALGORITHM);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
pkey->type = type;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-01-12 09:32:12 +08:00
|
|
|
# ifndef OPENSSL_NO_ENGINE
|
2017-10-09 22:21:11 +08:00
|
|
|
int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e)
|
|
|
|
{
|
|
|
|
if (e != NULL) {
|
|
|
|
if (!ENGINE_init(e)) {
|
|
|
|
EVPerr(EVP_F_EVP_PKEY_SET1_ENGINE, ERR_R_ENGINE_LIB);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (ENGINE_get_pkey_meth(e, pkey->type) == NULL) {
|
|
|
|
ENGINE_finish(e);
|
|
|
|
EVPerr(EVP_F_EVP_PKEY_SET1_ENGINE, EVP_R_UNSUPPORTED_ALGORITHM);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ENGINE_finish(pkey->pmeth_engine);
|
|
|
|
pkey->pmeth_engine = e;
|
|
|
|
return 1;
|
|
|
|
}
|
2019-02-25 23:02:33 +08:00
|
|
|
|
|
|
|
ENGINE *EVP_PKEY_get0_engine(const EVP_PKEY *pkey)
|
|
|
|
{
|
|
|
|
return pkey->engine;
|
|
|
|
}
|
2020-01-12 09:32:12 +08:00
|
|
|
# endif
|
2006-06-05 19:52:46 +08:00
|
|
|
int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2020-01-25 00:51:39 +08:00
|
|
|
int alias = type;
|
|
|
|
|
2020-02-06 23:17:28 +08:00
|
|
|
#ifndef OPENSSL_NO_EC
|
2020-01-25 00:51:39 +08:00
|
|
|
if (EVP_PKEY_type(type) == EVP_PKEY_EC) {
|
|
|
|
const EC_GROUP *group = EC_KEY_get0_group(key);
|
|
|
|
|
|
|
|
if (group != NULL && EC_GROUP_get_curve_name(group) == NID_sm2)
|
|
|
|
alias = EVP_PKEY_SM2;
|
|
|
|
}
|
2020-02-06 23:17:28 +08:00
|
|
|
#endif
|
2020-01-25 00:51:39 +08:00
|
|
|
|
2015-09-01 22:31:55 +08:00
|
|
|
if (pkey == NULL || !EVP_PKEY_set_type(pkey, type))
|
2015-01-22 11:40:55 +08:00
|
|
|
return 0;
|
2020-01-25 00:51:39 +08:00
|
|
|
if (!EVP_PKEY_set_alias_type(pkey, alias))
|
|
|
|
return 0;
|
2015-01-22 11:40:55 +08:00
|
|
|
pkey->pkey.ptr = key;
|
|
|
|
return (key != NULL);
|
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2016-01-19 08:21:12 +08:00
|
|
|
void *EVP_PKEY_get0(const EVP_PKEY *pkey)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
return pkey->pkey.ptr;
|
|
|
|
}
|
2006-03-24 21:46:58 +08:00
|
|
|
|
2016-06-16 02:02:04 +08:00
|
|
|
const unsigned char *EVP_PKEY_get0_hmac(const EVP_PKEY *pkey, size_t *len)
|
|
|
|
{
|
|
|
|
ASN1_OCTET_STRING *os = NULL;
|
|
|
|
if (pkey->type != EVP_PKEY_HMAC) {
|
|
|
|
EVPerr(EVP_F_EVP_PKEY_GET0_HMAC, EVP_R_EXPECTING_AN_HMAC_KEY);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
os = EVP_PKEY_get0(pkey);
|
|
|
|
*len = os->length;
|
|
|
|
return os->data;
|
|
|
|
}
|
|
|
|
|
2020-01-12 09:32:12 +08:00
|
|
|
# ifndef OPENSSL_NO_POLY1305
|
2016-12-17 06:00:43 +08:00
|
|
|
const unsigned char *EVP_PKEY_get0_poly1305(const EVP_PKEY *pkey, size_t *len)
|
|
|
|
{
|
|
|
|
ASN1_OCTET_STRING *os = NULL;
|
|
|
|
if (pkey->type != EVP_PKEY_POLY1305) {
|
|
|
|
EVPerr(EVP_F_EVP_PKEY_GET0_POLY1305, EVP_R_EXPECTING_A_POLY1305_KEY);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
os = EVP_PKEY_get0(pkey);
|
|
|
|
*len = os->length;
|
|
|
|
return os->data;
|
|
|
|
}
|
2020-01-12 09:32:12 +08:00
|
|
|
# endif
|
2016-12-17 06:00:43 +08:00
|
|
|
|
2020-01-12 09:32:12 +08:00
|
|
|
# ifndef OPENSSL_NO_SIPHASH
|
2017-01-12 05:38:44 +08:00
|
|
|
const unsigned char *EVP_PKEY_get0_siphash(const EVP_PKEY *pkey, size_t *len)
|
|
|
|
{
|
|
|
|
ASN1_OCTET_STRING *os = NULL;
|
|
|
|
|
|
|
|
if (pkey->type != EVP_PKEY_SIPHASH) {
|
|
|
|
EVPerr(EVP_F_EVP_PKEY_GET0_SIPHASH, EVP_R_EXPECTING_A_SIPHASH_KEY);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
os = EVP_PKEY_get0(pkey);
|
|
|
|
*len = os->length;
|
|
|
|
return os->data;
|
|
|
|
}
|
2020-01-12 09:32:12 +08:00
|
|
|
# endif
|
2017-01-12 05:38:44 +08:00
|
|
|
|
2020-01-12 09:32:12 +08:00
|
|
|
# ifndef OPENSSL_NO_RSA
|
2000-02-26 09:55:33 +08:00
|
|
|
int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key)
|
1999-11-22 06:28:31 +08:00
|
|
|
{
|
2015-01-22 11:40:55 +08:00
|
|
|
int ret = EVP_PKEY_assign_RSA(pkey, key);
|
|
|
|
if (ret)
|
|
|
|
RSA_up_ref(key);
|
|
|
|
return ret;
|
1999-11-22 06:28:31 +08:00
|
|
|
}
|
|
|
|
|
2019-01-16 04:51:25 +08:00
|
|
|
RSA *EVP_PKEY_get0_RSA(const EVP_PKEY *pkey)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2019-10-19 02:44:49 +08:00
|
|
|
if (pkey->type != EVP_PKEY_RSA && pkey->type != EVP_PKEY_RSA_PSS) {
|
2015-12-14 01:57:01 +08:00
|
|
|
EVPerr(EVP_F_EVP_PKEY_GET0_RSA, EVP_R_EXPECTING_AN_RSA_KEY);
|
2015-01-22 11:40:55 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return pkey->pkey.rsa;
|
1999-10-25 10:00:09 +08:00
|
|
|
}
|
2015-12-14 01:57:01 +08:00
|
|
|
|
|
|
|
RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey)
|
|
|
|
{
|
|
|
|
RSA *ret = EVP_PKEY_get0_RSA(pkey);
|
|
|
|
if (ret != NULL)
|
|
|
|
RSA_up_ref(ret);
|
|
|
|
return ret;
|
|
|
|
}
|
2020-01-12 09:32:12 +08:00
|
|
|
# endif
|
1999-10-25 10:00:09 +08:00
|
|
|
|
2020-01-12 09:32:12 +08:00
|
|
|
# ifndef OPENSSL_NO_DSA
|
2000-02-26 09:55:33 +08:00
|
|
|
int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key)
|
1999-11-22 06:28:31 +08:00
|
|
|
{
|
2015-01-22 11:40:55 +08:00
|
|
|
int ret = EVP_PKEY_assign_DSA(pkey, key);
|
|
|
|
if (ret)
|
|
|
|
DSA_up_ref(key);
|
|
|
|
return ret;
|
1999-11-22 06:28:31 +08:00
|
|
|
}
|
|
|
|
|
2019-01-16 04:51:25 +08:00
|
|
|
DSA *EVP_PKEY_get0_DSA(const EVP_PKEY *pkey)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (pkey->type != EVP_PKEY_DSA) {
|
2015-12-14 01:57:01 +08:00
|
|
|
EVPerr(EVP_F_EVP_PKEY_GET0_DSA, EVP_R_EXPECTING_A_DSA_KEY);
|
2015-01-22 11:40:55 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return pkey->pkey.dsa;
|
1999-10-25 10:00:09 +08:00
|
|
|
}
|
2015-12-14 01:57:01 +08:00
|
|
|
|
|
|
|
DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey)
|
|
|
|
{
|
|
|
|
DSA *ret = EVP_PKEY_get0_DSA(pkey);
|
|
|
|
if (ret != NULL)
|
|
|
|
DSA_up_ref(ret);
|
|
|
|
return ret;
|
|
|
|
}
|
2020-01-12 09:32:12 +08:00
|
|
|
# endif
|
1999-10-25 10:00:09 +08:00
|
|
|
|
2020-01-12 09:32:12 +08:00
|
|
|
# ifndef OPENSSL_NO_EC
|
2002-02-14 02:21:51 +08:00
|
|
|
|
2002-08-07 18:49:54 +08:00
|
|
|
int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key)
|
2002-02-14 02:21:51 +08:00
|
|
|
{
|
2015-01-22 11:40:55 +08:00
|
|
|
int ret = EVP_PKEY_assign_EC_KEY(pkey, key);
|
|
|
|
if (ret)
|
|
|
|
EC_KEY_up_ref(key);
|
|
|
|
return ret;
|
2002-02-14 02:21:51 +08:00
|
|
|
}
|
|
|
|
|
2019-01-16 04:51:25 +08:00
|
|
|
EC_KEY *EVP_PKEY_get0_EC_KEY(const EVP_PKEY *pkey)
|
2002-02-14 02:21:51 +08:00
|
|
|
{
|
2020-01-25 00:51:39 +08:00
|
|
|
if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) {
|
2015-12-14 01:57:01 +08:00
|
|
|
EVPerr(EVP_F_EVP_PKEY_GET0_EC_KEY, EVP_R_EXPECTING_A_EC_KEY);
|
2015-01-22 11:40:55 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return pkey->pkey.ec;
|
2002-02-14 02:21:51 +08:00
|
|
|
}
|
2015-12-14 01:57:01 +08:00
|
|
|
|
|
|
|
EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey)
|
|
|
|
{
|
|
|
|
EC_KEY *ret = EVP_PKEY_get0_EC_KEY(pkey);
|
|
|
|
if (ret != NULL)
|
|
|
|
EC_KEY_up_ref(ret);
|
|
|
|
return ret;
|
|
|
|
}
|
2020-01-12 09:32:12 +08:00
|
|
|
# endif
|
2002-02-14 02:21:51 +08:00
|
|
|
|
2020-01-12 09:32:12 +08:00
|
|
|
# ifndef OPENSSL_NO_DH
|
1999-11-22 06:28:31 +08:00
|
|
|
|
2000-02-26 09:55:33 +08:00
|
|
|
int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key)
|
1999-11-22 06:28:31 +08:00
|
|
|
{
|
2019-12-09 19:51:48 +08:00
|
|
|
int type = DH_get0_q(key) == NULL ? EVP_PKEY_DH : EVP_PKEY_DHX;
|
|
|
|
int ret = EVP_PKEY_assign(pkey, type, key);
|
|
|
|
|
2015-01-22 11:40:55 +08:00
|
|
|
if (ret)
|
|
|
|
DH_up_ref(key);
|
|
|
|
return ret;
|
1999-11-22 06:28:31 +08:00
|
|
|
}
|
|
|
|
|
2019-01-16 04:51:25 +08:00
|
|
|
DH *EVP_PKEY_get0_DH(const EVP_PKEY *pkey)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
if (pkey->type != EVP_PKEY_DH && pkey->type != EVP_PKEY_DHX) {
|
2015-12-14 01:57:01 +08:00
|
|
|
EVPerr(EVP_F_EVP_PKEY_GET0_DH, EVP_R_EXPECTING_A_DH_KEY);
|
2015-01-22 11:40:55 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return pkey->pkey.dh;
|
1999-10-25 10:00:09 +08:00
|
|
|
}
|
2015-12-14 01:57:01 +08:00
|
|
|
|
|
|
|
DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey)
|
|
|
|
{
|
|
|
|
DH *ret = EVP_PKEY_get0_DH(pkey);
|
|
|
|
if (ret != NULL)
|
|
|
|
DH_up_ref(ret);
|
|
|
|
return ret;
|
|
|
|
}
|
2020-01-12 09:32:12 +08:00
|
|
|
# endif
|
1999-10-25 10:00:09 +08:00
|
|
|
|
1999-04-20 05:31:43 +08:00
|
|
|
int EVP_PKEY_type(int type)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
const EVP_PKEY_ASN1_METHOD *ameth;
|
|
|
|
ENGINE *e;
|
|
|
|
ameth = EVP_PKEY_asn1_find(&e, type);
|
|
|
|
if (ameth)
|
|
|
|
ret = ameth->pkey_id;
|
|
|
|
else
|
|
|
|
ret = NID_undef;
|
2020-01-12 09:32:12 +08:00
|
|
|
# ifndef OPENSSL_NO_ENGINE
|
2016-02-26 01:09:06 +08:00
|
|
|
ENGINE_finish(e);
|
2020-01-12 09:32:12 +08:00
|
|
|
# endif
|
2015-01-22 11:40:55 +08:00
|
|
|
return ret;
|
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2006-05-12 05:33:00 +08:00
|
|
|
int EVP_PKEY_id(const EVP_PKEY *pkey)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
return pkey->type;
|
|
|
|
}
|
2006-05-12 05:33:00 +08:00
|
|
|
|
|
|
|
int EVP_PKEY_base_id(const EVP_PKEY *pkey)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
|
|
|
return EVP_PKEY_type(pkey->type);
|
|
|
|
}
|
2006-05-12 05:33:00 +08:00
|
|
|
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2019-11-28 01:35:48 +08:00
|
|
|
static int print_reset_indent(BIO **out, int pop_f_prefix, long saved_indent)
|
|
|
|
{
|
|
|
|
BIO_set_indent(*out, saved_indent);
|
|
|
|
if (pop_f_prefix) {
|
|
|
|
BIO *next = BIO_pop(*out);
|
|
|
|
|
|
|
|
BIO_free(*out);
|
|
|
|
*out = next;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int print_set_indent(BIO **out, int *pop_f_prefix, long *saved_indent,
|
|
|
|
long indent)
|
|
|
|
{
|
|
|
|
*pop_f_prefix = 0;
|
|
|
|
*saved_indent = 0;
|
|
|
|
if (indent > 0) {
|
|
|
|
long i = BIO_get_indent(*out);
|
|
|
|
|
|
|
|
*saved_indent = (i < 0 ? 0 : i);
|
|
|
|
if (BIO_set_indent(*out, indent) <= 0) {
|
|
|
|
if ((*out = BIO_push(BIO_new(BIO_f_prefix()), *out)) == NULL)
|
|
|
|
return 0;
|
|
|
|
*pop_f_prefix = 1;
|
|
|
|
}
|
|
|
|
if (BIO_set_indent(*out, indent) <= 0) {
|
|
|
|
print_reset_indent(out, *pop_f_prefix, *saved_indent);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2006-03-22 21:09:35 +08:00
|
|
|
static int unsup_alg(BIO *out, const EVP_PKEY *pkey, int indent,
|
2015-01-22 11:40:55 +08:00
|
|
|
const char *kstr)
|
|
|
|
{
|
2020-01-06 09:23:21 +08:00
|
|
|
return BIO_indent(out, indent, 128)
|
|
|
|
&& BIO_printf(out, "%s algorithm \"%s\" unsupported\n",
|
|
|
|
kstr, OBJ_nid2ln(pkey->type)) > 0;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2006-03-22 21:09:35 +08:00
|
|
|
|
2019-11-28 01:35:48 +08:00
|
|
|
static int print_pkey(const EVP_PKEY *pkey, BIO *out, int indent,
|
|
|
|
const char *propquery /* For provided serialization */,
|
|
|
|
int (*legacy_print)(BIO *out, const EVP_PKEY *pkey,
|
|
|
|
int indent, ASN1_PCTX *pctx),
|
|
|
|
ASN1_PCTX *legacy_pctx /* For legacy print */)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2019-11-28 01:35:48 +08:00
|
|
|
int pop_f_prefix;
|
|
|
|
long saved_indent;
|
|
|
|
OSSL_SERIALIZER_CTX *ctx = NULL;
|
|
|
|
int ret = -2; /* default to unsupported */
|
|
|
|
|
|
|
|
if (!print_set_indent(&out, &pop_f_prefix, &saved_indent, indent))
|
|
|
|
return 0;
|
2019-11-18 08:47:32 +08:00
|
|
|
|
2019-11-28 01:35:48 +08:00
|
|
|
ctx = OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(pkey, propquery);
|
2019-11-18 08:47:32 +08:00
|
|
|
if (OSSL_SERIALIZER_CTX_get_serializer(ctx) != NULL)
|
|
|
|
ret = OSSL_SERIALIZER_to_bio(ctx, out);
|
|
|
|
OSSL_SERIALIZER_CTX_free(ctx);
|
|
|
|
|
|
|
|
if (ret != -2)
|
2019-11-28 01:35:48 +08:00
|
|
|
goto end;
|
2019-11-18 08:47:32 +08:00
|
|
|
|
|
|
|
/* legacy fallback */
|
2019-11-28 01:35:48 +08:00
|
|
|
if (legacy_print != NULL)
|
|
|
|
ret = legacy_print(out, pkey, 0, legacy_pctx);
|
|
|
|
else
|
|
|
|
ret = unsup_alg(out, pkey, 0, "Public Key");
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2019-11-28 01:35:48 +08:00
|
|
|
end:
|
|
|
|
print_reset_indent(&out, pop_f_prefix, saved_indent);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey,
|
|
|
|
int indent, ASN1_PCTX *pctx)
|
|
|
|
{
|
|
|
|
return print_pkey(pkey, out, indent, OSSL_SERIALIZER_PUBKEY_TO_TEXT_PQ,
|
|
|
|
(pkey->ameth != NULL ? pkey->ameth->pub_print : NULL),
|
|
|
|
pctx);
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2006-03-22 21:09:35 +08:00
|
|
|
|
|
|
|
int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey,
|
2015-01-22 11:40:55 +08:00
|
|
|
int indent, ASN1_PCTX *pctx)
|
|
|
|
{
|
2019-11-28 01:35:48 +08:00
|
|
|
return print_pkey(pkey, out, indent, OSSL_SERIALIZER_PrivateKey_TO_TEXT_PQ,
|
|
|
|
(pkey->ameth != NULL ? pkey->ameth->priv_print : NULL),
|
|
|
|
pctx);
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2006-03-22 21:09:35 +08:00
|
|
|
|
|
|
|
int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey,
|
2015-01-22 11:40:55 +08:00
|
|
|
int indent, ASN1_PCTX *pctx)
|
|
|
|
{
|
2019-11-28 01:35:48 +08:00
|
|
|
return print_pkey(pkey, out, indent, OSSL_SERIALIZER_Parameters_TO_TEXT_PQ,
|
|
|
|
(pkey->ameth != NULL ? pkey->ameth->param_print : NULL),
|
|
|
|
pctx);
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2006-05-08 01:09:39 +08:00
|
|
|
|
2020-01-13 15:49:44 +08:00
|
|
|
static int legacy_asn1_ctrl_to_param(EVP_PKEY *pkey, int op,
|
|
|
|
int arg1, void *arg2)
|
|
|
|
{
|
2020-02-21 03:26:16 +08:00
|
|
|
if (pkey->keymgmt == NULL)
|
2020-01-13 15:49:44 +08:00
|
|
|
return 0;
|
|
|
|
switch (op) {
|
|
|
|
case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
|
|
|
|
{
|
|
|
|
char mdname[80] = "";
|
|
|
|
int nid;
|
|
|
|
int rv = EVP_PKEY_get_default_digest_name(pkey, mdname,
|
|
|
|
sizeof(mdname));
|
|
|
|
|
|
|
|
if (rv <= 0)
|
|
|
|
return rv;
|
|
|
|
nid = OBJ_sn2nid(mdname);
|
|
|
|
if (nid == NID_undef)
|
|
|
|
nid = OBJ_ln2nid(mdname);
|
|
|
|
if (nid == NID_undef)
|
|
|
|
return 0;
|
|
|
|
*(int *)arg2 = nid;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-11 05:30:43 +08:00
|
|
|
static int evp_pkey_asn1_ctrl(EVP_PKEY *pkey, int op, int arg1, void *arg2)
|
2015-01-22 11:40:55 +08:00
|
|
|
{
|
2020-01-13 15:49:44 +08:00
|
|
|
if (pkey->ameth == NULL)
|
|
|
|
return legacy_asn1_ctrl_to_param(pkey, op, arg1, arg2);
|
|
|
|
if (pkey->ameth->pkey_ctrl == NULL)
|
2015-01-22 11:40:55 +08:00
|
|
|
return -2;
|
2016-08-11 05:30:43 +08:00
|
|
|
return pkey->ameth->pkey_ctrl(pkey, op, arg1, arg2);
|
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid)
|
|
|
|
{
|
|
|
|
return evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_DEFAULT_MD_NID, 0, pnid);
|
|
|
|
}
|
|
|
|
|
2020-01-13 15:49:44 +08:00
|
|
|
int EVP_PKEY_get_default_digest_name(EVP_PKEY *pkey,
|
|
|
|
char *mdname, size_t mdname_sz)
|
|
|
|
{
|
|
|
|
if (pkey->ameth == NULL) {
|
|
|
|
OSSL_PARAM params[3];
|
|
|
|
char mddefault[100] = "";
|
|
|
|
char mdmandatory[100] = "";
|
|
|
|
|
|
|
|
params[0] =
|
|
|
|
OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_DEFAULT_DIGEST,
|
|
|
|
mddefault, sizeof(mddefault));
|
|
|
|
params[1] =
|
|
|
|
OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST,
|
|
|
|
mdmandatory,
|
|
|
|
sizeof(mdmandatory));
|
|
|
|
params[2] = OSSL_PARAM_construct_end();
|
2020-02-21 03:26:16 +08:00
|
|
|
if (!evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params))
|
2020-01-13 15:49:44 +08:00
|
|
|
return 0;
|
|
|
|
if (mdmandatory[0] != '\0') {
|
|
|
|
OPENSSL_strlcpy(mdname, mdmandatory, mdname_sz);
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
OPENSSL_strlcpy(mdname, mddefault, mdname_sz);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
int nid = NID_undef;
|
|
|
|
int rv = EVP_PKEY_get_default_digest_nid(pkey, &nid);
|
|
|
|
const char *name = rv > 0 ? OBJ_nid2sn(nid) : NULL;
|
|
|
|
|
|
|
|
if (rv > 0)
|
|
|
|
OPENSSL_strlcpy(mdname, name, mdname_sz);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-23 01:49:54 +08:00
|
|
|
int EVP_PKEY_supports_digest_nid(EVP_PKEY *pkey, int nid)
|
|
|
|
{
|
|
|
|
int rv, default_nid;
|
|
|
|
|
|
|
|
rv = evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_SUPPORTS_MD_NID, nid, NULL);
|
|
|
|
if (rv == -2) {
|
|
|
|
/*
|
|
|
|
* If there is a mandatory default digest and this isn't it, then
|
|
|
|
* the answer is 'no'.
|
|
|
|
*/
|
|
|
|
rv = EVP_PKEY_get_default_digest_nid(pkey, &default_nid);
|
|
|
|
if (rv == 2)
|
|
|
|
return (nid == default_nid);
|
|
|
|
/* zero is an error from EVP_PKEY_get_default_digest_nid() */
|
|
|
|
if (rv == 0)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2016-08-11 05:30:43 +08:00
|
|
|
int EVP_PKEY_set1_tls_encodedpoint(EVP_PKEY *pkey,
|
|
|
|
const unsigned char *pt, size_t ptlen)
|
|
|
|
{
|
|
|
|
if (ptlen > INT_MAX)
|
|
|
|
return 0;
|
|
|
|
if (evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_SET1_TLS_ENCPT, ptlen,
|
|
|
|
(void *)pt) <= 0)
|
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t EVP_PKEY_get1_tls_encodedpoint(EVP_PKEY *pkey, unsigned char **ppt)
|
|
|
|
{
|
|
|
|
int rv;
|
|
|
|
rv = evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_GET1_TLS_ENCPT, 0, ppt);
|
|
|
|
if (rv <= 0)
|
|
|
|
return 0;
|
|
|
|
return rv;
|
2015-01-22 11:40:55 +08:00
|
|
|
}
|
2020-01-12 09:32:12 +08:00
|
|
|
|
|
|
|
#endif /* FIPS_MODE */
|
|
|
|
|
|
|
|
/*- All methods below can also be used in FIPS_MODE */
|
|
|
|
|
|
|
|
EVP_PKEY *EVP_PKEY_new(void)
|
|
|
|
{
|
|
|
|
EVP_PKEY *ret = OPENSSL_zalloc(sizeof(*ret));
|
|
|
|
|
|
|
|
if (ret == NULL) {
|
|
|
|
EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
ret->type = EVP_PKEY_NONE;
|
|
|
|
ret->save_type = EVP_PKEY_NONE;
|
|
|
|
ret->references = 1;
|
|
|
|
ret->save_parameters = 1;
|
|
|
|
ret->lock = CRYPTO_THREAD_lock_new();
|
|
|
|
if (ret->lock == NULL) {
|
|
|
|
EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE);
|
|
|
|
OPENSSL_free(ret);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_up_ref(EVP_PKEY *pkey)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (CRYPTO_UP_REF(&pkey->references, &i, pkey->lock) <= 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
REF_PRINT_COUNT("EVP_PKEY", pkey);
|
|
|
|
REF_ASSERT_ISNT(i < 2);
|
|
|
|
return ((i > 1) ? 1 : 0);
|
|
|
|
}
|
|
|
|
|
2020-02-21 05:55:41 +08:00
|
|
|
#ifndef FIPS_MODE
|
2019-10-27 22:09:26 +08:00
|
|
|
void evp_pkey_free_legacy(EVP_PKEY *x)
|
2020-02-21 05:55:41 +08:00
|
|
|
{
|
|
|
|
if (x->ameth != NULL) {
|
2020-02-05 23:30:21 +08:00
|
|
|
if (x->ameth->pkey_free != NULL)
|
2020-02-21 05:55:41 +08:00
|
|
|
x->ameth->pkey_free(x);
|
|
|
|
x->pkey.ptr = NULL;
|
|
|
|
x->ameth = NULL;
|
|
|
|
}
|
|
|
|
# ifndef OPENSSL_NO_ENGINE
|
|
|
|
ENGINE_finish(x->engine);
|
|
|
|
x->engine = NULL;
|
|
|
|
ENGINE_finish(x->pmeth_engine);
|
|
|
|
x->pmeth_engine = NULL;
|
|
|
|
# endif
|
|
|
|
x->type = x->save_type = EVP_PKEY_NONE;
|
|
|
|
}
|
|
|
|
#endif /* FIPS_MODE */
|
|
|
|
|
2020-01-12 09:32:12 +08:00
|
|
|
static void evp_pkey_free_it(EVP_PKEY *x)
|
|
|
|
{
|
|
|
|
/* internal function; x is never NULL */
|
|
|
|
|
2020-02-21 03:26:16 +08:00
|
|
|
evp_keymgmt_util_clear_operation_cache(x);
|
2020-02-21 05:55:41 +08:00
|
|
|
#ifndef FIPS_MODE
|
|
|
|
evp_pkey_free_legacy(x);
|
|
|
|
#endif
|
2020-01-12 09:32:12 +08:00
|
|
|
|
2020-02-21 03:26:16 +08:00
|
|
|
if (x->keymgmt != NULL) {
|
|
|
|
evp_keymgmt_freedata(x->keymgmt, x->keydata);
|
|
|
|
EVP_KEYMGMT_free(x->keymgmt);
|
|
|
|
x->keymgmt = NULL;
|
|
|
|
x->keydata = NULL;
|
|
|
|
}
|
2020-01-12 09:32:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void EVP_PKEY_free(EVP_PKEY *x)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (x == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
CRYPTO_DOWN_REF(&x->references, &i, x->lock);
|
|
|
|
REF_PRINT_COUNT("EVP_PKEY", x);
|
|
|
|
if (i > 0)
|
|
|
|
return;
|
|
|
|
REF_ASSERT_ISNT(i < 0);
|
|
|
|
evp_pkey_free_it(x);
|
|
|
|
CRYPTO_THREAD_lock_free(x->lock);
|
|
|
|
#ifndef FIPS_MODE
|
|
|
|
sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free);
|
|
|
|
#endif
|
|
|
|
OPENSSL_free(x);
|
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_size(const EVP_PKEY *pkey)
|
|
|
|
{
|
2020-01-08 10:44:28 +08:00
|
|
|
if (pkey != NULL) {
|
|
|
|
if (pkey->ameth == NULL)
|
|
|
|
return pkey->cache.size;
|
|
|
|
else if (pkey->ameth->pkey_size != NULL)
|
|
|
|
return pkey->ameth->pkey_size(pkey);
|
|
|
|
}
|
2020-01-12 09:32:12 +08:00
|
|
|
return 0;
|
|
|
|
}
|
2020-01-14 21:11:47 +08:00
|
|
|
|
2020-02-21 03:26:16 +08:00
|
|
|
void *evp_pkey_export_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx,
|
|
|
|
EVP_KEYMGMT **keymgmt,
|
|
|
|
const char *propquery)
|
2020-01-14 21:11:47 +08:00
|
|
|
{
|
|
|
|
EVP_KEYMGMT *allocated_keymgmt = NULL;
|
|
|
|
EVP_KEYMGMT *tmp_keymgmt = NULL;
|
Redesign the KEYMGMT libcrypto <-> provider interface - the basics
The KEYMGMT libcrypto <-> provider interface currently makes a few
assumptions:
1. provider side domain parameters and key data isn't mutable. In
other words, as soon as a key has been created in any (loaded,
imported data, ...), it's set in stone.
2. provider side domain parameters can be strictly separated from the
key data.
This does work for the most part, but there are places where that's a
bit too rigid for the functionality that the EVP_PKEY API delivers.
Key data needs to be mutable to allow the flexibility that functions
like EVP_PKEY_copy_parameters promise, as well as to provide the
combinations of data that an EVP_PKEY is generally assumed to be able
to hold:
- domain parameters only
- public key only
- public key + private key
- domain parameters + public key
- domain parameters + public key + private key
To remedy all this, we:
1. let go of the distinction between domain parameters and key
material proper in the libcrypto <-> provider interface.
As a consequence, functions that still need it gain a selection
argument, which is a set of bits that indicate what parts of the
key object are to be considered in a specific call. This allows
a reduction of very similar functions into one.
2. Rework the libcrypto <-> provider interface so provider side key
objects are created and destructed with a separate function, and
get their data filled and extracted in through import and export.
(future work will see other key object constructors and other
functions to fill them with data)
Fixes #10979
squash! Redesign the KEYMGMT libcrypto <-> provider interface - the basics
Remedy 1 needs a rewrite:
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/11006)
2020-02-03 01:56:07 +08:00
|
|
|
void *keydata = NULL;
|
2020-01-14 21:11:47 +08:00
|
|
|
|
|
|
|
if (pk == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2020-02-12 21:28:50 +08:00
|
|
|
#ifndef FIPS_MODE
|
|
|
|
if (pk->pkey.ptr != NULL) {
|
|
|
|
/*
|
2020-02-21 03:26:16 +08:00
|
|
|
* If the legacy key doesn't have an dirty counter or export function,
|
|
|
|
* give up
|
2020-02-12 21:28:50 +08:00
|
|
|
*/
|
2020-02-21 03:26:16 +08:00
|
|
|
if (pk->ameth->dirty_cnt == NULL || pk->ameth->export_to == NULL)
|
|
|
|
return NULL;
|
2020-02-12 21:28:50 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-02-21 03:26:16 +08:00
|
|
|
if (keymgmt != NULL) {
|
|
|
|
tmp_keymgmt = *keymgmt;
|
|
|
|
*keymgmt = NULL;
|
|
|
|
}
|
|
|
|
|
2020-02-12 21:28:50 +08:00
|
|
|
/* If no keymgmt was given or found, get a default keymgmt */
|
2020-01-14 21:11:47 +08:00
|
|
|
if (tmp_keymgmt == NULL) {
|
2020-01-15 19:10:43 +08:00
|
|
|
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pk, propquery);
|
2020-01-14 21:11:47 +08:00
|
|
|
|
|
|
|
if (ctx != NULL && ctx->keytype != NULL)
|
|
|
|
tmp_keymgmt = allocated_keymgmt =
|
|
|
|
EVP_KEYMGMT_fetch(ctx->libctx, ctx->keytype, propquery);
|
|
|
|
EVP_PKEY_CTX_free(ctx);
|
|
|
|
}
|
|
|
|
|
2020-02-21 03:26:16 +08:00
|
|
|
/* If there's still no keymgmt to be had, give up */
|
2020-02-12 21:28:50 +08:00
|
|
|
if (tmp_keymgmt == NULL)
|
|
|
|
goto end;
|
2020-01-14 21:11:47 +08:00
|
|
|
|
2020-02-12 21:28:50 +08:00
|
|
|
#ifndef FIPS_MODE
|
|
|
|
if (pk->pkey.ptr != NULL) {
|
2020-02-21 03:26:16 +08:00
|
|
|
size_t i = 0;
|
2020-02-12 21:28:50 +08:00
|
|
|
|
|
|
|
/*
|
2020-02-21 03:26:16 +08:00
|
|
|
* If the legacy "origin" hasn't changed since last time, we try
|
|
|
|
* to find our keymgmt in the operation cache. If it has changed,
|
|
|
|
* |i| remains zero, and we will clear the cache further down.
|
2020-02-12 21:28:50 +08:00
|
|
|
*/
|
2020-02-21 03:26:16 +08:00
|
|
|
if (pk->ameth->dirty_cnt(pk) == pk->dirty_cnt_copy) {
|
|
|
|
i = evp_keymgmt_util_find_operation_cache_index(pk, tmp_keymgmt);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If |tmp_keymgmt| is present in the operation cache, it means
|
|
|
|
* that export doesn't need to be redone. In that case, we take
|
|
|
|
* token copies of the cached pointers, to have token success
|
|
|
|
* values to return.
|
|
|
|
*/
|
|
|
|
if (i < OSSL_NELEM(pk->operation_cache)
|
|
|
|
&& pk->operation_cache[i].keymgmt != NULL) {
|
|
|
|
keydata = pk->operation_cache[i].keydata;
|
|
|
|
goto end;
|
|
|
|
}
|
2020-02-12 21:28:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2020-02-21 03:26:16 +08:00
|
|
|
* TODO(3.0) Right now, we assume we have ample space. We will have
|
|
|
|
* to think about a cache aging scheme, though, if |i| indexes outside
|
|
|
|
* the array.
|
2020-02-12 21:28:50 +08:00
|
|
|
*/
|
2020-02-21 03:26:16 +08:00
|
|
|
if (!ossl_assert(i < OSSL_NELEM(pk->operation_cache)))
|
2020-02-12 21:28:50 +08:00
|
|
|
goto end;
|
|
|
|
|
|
|
|
/* Make sure that the keymgmt key type matches the legacy NID */
|
|
|
|
if (!ossl_assert(EVP_KEYMGMT_is_a(tmp_keymgmt, OBJ_nid2sn(pk->type))))
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
if ((keydata = evp_keymgmt_newdata(tmp_keymgmt)) == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
if (!pk->ameth->export_to(pk, keydata, tmp_keymgmt)) {
|
|
|
|
evp_keymgmt_freedata(tmp_keymgmt, keydata);
|
|
|
|
keydata = NULL;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2020-02-21 03:26:16 +08:00
|
|
|
/*
|
|
|
|
* If the dirty counter changed since last time, then clear the
|
|
|
|
* operation cache. In that case, we know that |i| is zero. Just
|
|
|
|
* in case this is a re-export, we increment then decrement the
|
|
|
|
* keymgmt reference counter.
|
|
|
|
*/
|
|
|
|
if (!EVP_KEYMGMT_up_ref(tmp_keymgmt)) { /* refcnt++ */
|
|
|
|
evp_keymgmt_freedata(tmp_keymgmt, keydata);
|
|
|
|
keydata = NULL;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
if (pk->ameth->dirty_cnt(pk) != pk->dirty_cnt_copy)
|
|
|
|
evp_keymgmt_util_clear_operation_cache(pk);
|
|
|
|
EVP_KEYMGMT_free(tmp_keymgmt); /* refcnt-- */
|
|
|
|
|
|
|
|
/* Add the new export to the operation cache */
|
|
|
|
if (!evp_keymgmt_util_cache_keydata(pk, i, tmp_keymgmt, keydata)) {
|
|
|
|
evp_keymgmt_freedata(tmp_keymgmt, keydata);
|
|
|
|
keydata = NULL;
|
|
|
|
goto end;
|
|
|
|
}
|
2020-02-12 21:28:50 +08:00
|
|
|
|
|
|
|
/* Synchronize the dirty count */
|
|
|
|
pk->dirty_cnt_copy = pk->ameth->dirty_cnt(pk);
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
#endif /* FIPS_MODE */
|
|
|
|
|
|
|
|
keydata = evp_keymgmt_util_export_to_provider(pk, tmp_keymgmt);
|
|
|
|
|
|
|
|
end:
|
2020-01-14 21:11:47 +08:00
|
|
|
/*
|
|
|
|
* If nothing was exported, |tmp_keymgmt| might point at a freed
|
|
|
|
* EVP_KEYMGMT, so we clear it to be safe. It shouldn't be useful for
|
|
|
|
* the caller either way in that case.
|
|
|
|
*/
|
Redesign the KEYMGMT libcrypto <-> provider interface - the basics
The KEYMGMT libcrypto <-> provider interface currently makes a few
assumptions:
1. provider side domain parameters and key data isn't mutable. In
other words, as soon as a key has been created in any (loaded,
imported data, ...), it's set in stone.
2. provider side domain parameters can be strictly separated from the
key data.
This does work for the most part, but there are places where that's a
bit too rigid for the functionality that the EVP_PKEY API delivers.
Key data needs to be mutable to allow the flexibility that functions
like EVP_PKEY_copy_parameters promise, as well as to provide the
combinations of data that an EVP_PKEY is generally assumed to be able
to hold:
- domain parameters only
- public key only
- public key + private key
- domain parameters + public key
- domain parameters + public key + private key
To remedy all this, we:
1. let go of the distinction between domain parameters and key
material proper in the libcrypto <-> provider interface.
As a consequence, functions that still need it gain a selection
argument, which is a set of bits that indicate what parts of the
key object are to be considered in a specific call. This allows
a reduction of very similar functions into one.
2. Rework the libcrypto <-> provider interface so provider side key
objects are created and destructed with a separate function, and
get their data filled and extracted in through import and export.
(future work will see other key object constructors and other
functions to fill them with data)
Fixes #10979
squash! Redesign the KEYMGMT libcrypto <-> provider interface - the basics
Remedy 1 needs a rewrite:
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/11006)
2020-02-03 01:56:07 +08:00
|
|
|
if (keydata == NULL)
|
2020-01-14 21:11:47 +08:00
|
|
|
tmp_keymgmt = NULL;
|
|
|
|
|
|
|
|
if (keymgmt != NULL)
|
|
|
|
*keymgmt = tmp_keymgmt;
|
|
|
|
|
|
|
|
EVP_KEYMGMT_free(allocated_keymgmt);
|
Redesign the KEYMGMT libcrypto <-> provider interface - the basics
The KEYMGMT libcrypto <-> provider interface currently makes a few
assumptions:
1. provider side domain parameters and key data isn't mutable. In
other words, as soon as a key has been created in any (loaded,
imported data, ...), it's set in stone.
2. provider side domain parameters can be strictly separated from the
key data.
This does work for the most part, but there are places where that's a
bit too rigid for the functionality that the EVP_PKEY API delivers.
Key data needs to be mutable to allow the flexibility that functions
like EVP_PKEY_copy_parameters promise, as well as to provide the
combinations of data that an EVP_PKEY is generally assumed to be able
to hold:
- domain parameters only
- public key only
- public key + private key
- domain parameters + public key
- domain parameters + public key + private key
To remedy all this, we:
1. let go of the distinction between domain parameters and key
material proper in the libcrypto <-> provider interface.
As a consequence, functions that still need it gain a selection
argument, which is a set of bits that indicate what parts of the
key object are to be considered in a specific call. This allows
a reduction of very similar functions into one.
2. Rework the libcrypto <-> provider interface so provider side key
objects are created and destructed with a separate function, and
get their data filled and extracted in through import and export.
(future work will see other key object constructors and other
functions to fill them with data)
Fixes #10979
squash! Redesign the KEYMGMT libcrypto <-> provider interface - the basics
Remedy 1 needs a rewrite:
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/11006)
2020-02-03 01:56:07 +08:00
|
|
|
return keydata;
|
2020-01-14 21:11:47 +08:00
|
|
|
}
|
2020-02-21 05:55:41 +08:00
|
|
|
|
|
|
|
#ifndef FIPS_MODE
|
|
|
|
/*
|
|
|
|
* This differs from exporting in that it releases the legacy key and assigns
|
|
|
|
* the export keymgmt and keydata to the "origin" provider side key instead
|
|
|
|
* of the operation cache.
|
|
|
|
*/
|
|
|
|
void *evp_pkey_upgrade_to_provider(EVP_PKEY *pk, OPENSSL_CTX *libctx,
|
|
|
|
EVP_KEYMGMT **keymgmt,
|
|
|
|
const char *propquery)
|
|
|
|
{
|
|
|
|
EVP_KEYMGMT *allocated_keymgmt = NULL;
|
|
|
|
EVP_KEYMGMT *tmp_keymgmt = NULL;
|
|
|
|
void *keydata = NULL;
|
|
|
|
|
|
|
|
if (pk == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If this key is already "upgraded", this function shouldn't have been
|
|
|
|
* called.
|
|
|
|
*/
|
|
|
|
if (!ossl_assert(pk->keymgmt == NULL))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (keymgmt != NULL) {
|
|
|
|
tmp_keymgmt = *keymgmt;
|
|
|
|
*keymgmt = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If the key isn't a legacy one, bail out, but with proper values */
|
|
|
|
if (pk->pkey.ptr == NULL) {
|
|
|
|
tmp_keymgmt = pk->keymgmt;
|
|
|
|
keydata = pk->keydata;
|
|
|
|
} else {
|
|
|
|
/* If the legacy key doesn't have an export function, give up */
|
|
|
|
if (pk->ameth->export_to == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
/* If no keymgmt was given, get a default keymgmt */
|
|
|
|
if (tmp_keymgmt == NULL) {
|
|
|
|
EVP_PKEY_CTX *ctx =
|
|
|
|
EVP_PKEY_CTX_new_from_pkey(libctx, pk, propquery);
|
|
|
|
|
|
|
|
if (ctx != NULL && ctx->keytype != NULL)
|
|
|
|
tmp_keymgmt = allocated_keymgmt =
|
|
|
|
EVP_KEYMGMT_fetch(ctx->libctx, ctx->keytype, propquery);
|
|
|
|
EVP_PKEY_CTX_free(ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If we still don't have a keymgmt, give up */
|
|
|
|
if (tmp_keymgmt == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
/* Make sure that the keymgmt key type matches the legacy NID */
|
|
|
|
if (!ossl_assert(EVP_KEYMGMT_is_a(tmp_keymgmt, OBJ_nid2sn(pk->type))))
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
if ((keydata = evp_keymgmt_newdata(tmp_keymgmt)) == NULL)
|
|
|
|
goto end;
|
|
|
|
|
|
|
|
if (!pk->ameth->export_to(pk, keydata, tmp_keymgmt)
|
|
|
|
|| !EVP_KEYMGMT_up_ref(tmp_keymgmt)) {
|
|
|
|
evp_keymgmt_freedata(tmp_keymgmt, keydata);
|
|
|
|
keydata = NULL;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Clear the operation cache, all the legacy data, as well as the
|
|
|
|
* dirty counters
|
|
|
|
*/
|
|
|
|
evp_pkey_free_legacy(pk);
|
|
|
|
pk->dirty_cnt_copy = 0;
|
|
|
|
|
|
|
|
evp_keymgmt_util_clear_operation_cache(pk);
|
|
|
|
pk->keymgmt = tmp_keymgmt;
|
|
|
|
pk->keydata = keydata;
|
|
|
|
evp_keymgmt_util_cache_keyinfo(pk);
|
|
|
|
}
|
|
|
|
|
|
|
|
end:
|
|
|
|
/*
|
|
|
|
* If nothing was upgraded, |tmp_keymgmt| might point at a freed
|
|
|
|
* EVP_KEYMGMT, so we clear it to be safe. It shouldn't be useful for
|
|
|
|
* the caller either way in that case.
|
|
|
|
*/
|
|
|
|
if (keydata == NULL)
|
|
|
|
tmp_keymgmt = NULL;
|
|
|
|
|
|
|
|
if (keymgmt != NULL)
|
|
|
|
*keymgmt = tmp_keymgmt;
|
|
|
|
|
|
|
|
EVP_KEYMGMT_free(allocated_keymgmt);
|
|
|
|
return keydata;
|
|
|
|
}
|
|
|
|
#endif /* FIPS_MODE */
|