2016-05-18 02:24:46 +08:00
|
|
|
/*
|
2024-03-20 20:07:54 +08:00
|
|
|
* Copyright 1995-2024 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"
|
|
|
|
|
2021-02-25 00:38:28 +08:00
|
|
|
#include <assert.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"
|
2021-01-19 19:36:24 +08:00
|
|
|
#include "internal/namemap.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>
|
2016-03-19 02:30:20 +08:00
|
|
|
#include <openssl/rsa.h>
|
|
|
|
#include <openssl/dsa.h>
|
|
|
|
#include <openssl/dh.h>
|
2020-03-17 01:55:32 +08:00
|
|
|
#include <openssl/ec.h>
|
2018-03-06 01:23:57 +08:00
|
|
|
#include <openssl/cmac.h>
|
2021-07-01 23:41:02 +08:00
|
|
|
#ifndef FIPS_MODULE
|
|
|
|
# include <openssl/engine.h>
|
|
|
|
#endif
|
2019-05-07 18:39:58 +08:00
|
|
|
#include <openssl/params.h>
|
2020-04-24 18:33:33 +08:00
|
|
|
#include <openssl/param_build.h>
|
2020-08-17 03:25:08 +08:00
|
|
|
#include <openssl/encoder.h>
|
2019-05-07 18:39:58 +08:00
|
|
|
#include <openssl/core_names.h>
|
2006-06-05 19:52:46 +08:00
|
|
|
|
2021-05-18 03:38:51 +08:00
|
|
|
#include "internal/numbers.h" /* includes SIZE_MAX */
|
2020-12-04 13:32:24 +08:00
|
|
|
#include "internal/ffc.h"
|
2019-09-28 06:45:33 +08:00
|
|
|
#include "crypto/evp.h"
|
2021-04-13 23:31:08 +08:00
|
|
|
#include "crypto/dh.h"
|
|
|
|
#include "crypto/dsa.h"
|
2020-12-02 02:21:04 +08:00
|
|
|
#include "crypto/ec.h"
|
2020-07-28 00:40:05 +08:00
|
|
|
#include "crypto/ecx.h"
|
2021-04-13 23:31:08 +08:00
|
|
|
#include "crypto/rsa.h"
|
2021-07-01 23:41:02 +08:00
|
|
|
#ifndef FIPS_MODULE
|
|
|
|
# include "crypto/asn1.h"
|
|
|
|
# include "crypto/x509.h"
|
|
|
|
#endif
|
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-03-21 13:14:25 +08:00
|
|
|
static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str,
|
|
|
|
int len, EVP_KEYMGMT *keymgmt);
|
2020-01-12 09:32:12 +08:00
|
|
|
static void evp_pkey_free_it(EVP_PKEY *key);
|
|
|
|
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2001-08-04 02:48:35 +08:00
|
|
|
|
2020-03-23 13:03:16 +08:00
|
|
|
/* The type of parameters selected in key parameter functions */
|
|
|
|
# define SELECT_PARAMETERS OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS
|
|
|
|
|
Rename all getters to use get/get0 in name
For functions that exist in 1.1.1 provide a simple aliases via #define.
Fixes #15236
Functions with OSSL_DECODER_, OSSL_ENCODER_, OSSL_STORE_LOADER_,
EVP_KEYEXCH_, EVP_KEM_, EVP_ASYM_CIPHER_, EVP_SIGNATURE_,
EVP_KEYMGMT_, EVP_RAND_, EVP_MAC_, EVP_KDF_, EVP_PKEY_,
EVP_MD_, and EVP_CIPHER_ prefixes are renamed.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15405)
2021-05-21 22:58:08 +08:00
|
|
|
int EVP_PKEY_get_bits(const EVP_PKEY *pkey)
|
1998-12-21 18:56:39 +08:00
|
|
|
{
|
2020-12-04 16:34:25 +08:00
|
|
|
int size = 0;
|
|
|
|
|
2020-01-08 10:44:28 +08:00
|
|
|
if (pkey != NULL) {
|
2020-12-04 16:34:25 +08:00
|
|
|
size = pkey->cache.bits;
|
|
|
|
if (pkey->ameth != NULL && pkey->ameth->pkey_bits != NULL)
|
|
|
|
size = pkey->ameth->pkey_bits(pkey);
|
2020-01-08 10:44:28 +08:00
|
|
|
}
|
2023-10-21 02:51:17 +08:00
|
|
|
if (size <= 0) {
|
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_UNKNOWN_BITS);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return size;
|
1998-12-21 18:56:39 +08:00
|
|
|
}
|
|
|
|
|
Rename all getters to use get/get0 in name
For functions that exist in 1.1.1 provide a simple aliases via #define.
Fixes #15236
Functions with OSSL_DECODER_, OSSL_ENCODER_, OSSL_STORE_LOADER_,
EVP_KEYEXCH_, EVP_KEM_, EVP_ASYM_CIPHER_, EVP_SIGNATURE_,
EVP_KEYMGMT_, EVP_RAND_, EVP_MAC_, EVP_KDF_, EVP_PKEY_,
EVP_MD_, and EVP_CIPHER_ prefixes are renamed.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15405)
2021-05-21 22:58:08 +08:00
|
|
|
int EVP_PKEY_get_security_bits(const EVP_PKEY *pkey)
|
2014-01-18 22:51:40 +08:00
|
|
|
{
|
2020-12-04 16:34:25 +08:00
|
|
|
int size = 0;
|
|
|
|
|
|
|
|
if (pkey != NULL) {
|
|
|
|
size = pkey->cache.security_bits;
|
|
|
|
if (pkey->ameth != NULL && pkey->ameth->pkey_security_bits != NULL)
|
|
|
|
size = pkey->ameth->pkey_security_bits(pkey);
|
|
|
|
}
|
2023-10-21 02:51:17 +08:00
|
|
|
if (size <= 0) {
|
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_UNKNOWN_SECURITY_BITS);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return size;
|
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)
|
1998-12-21 18:52:47 +08:00
|
|
|
{
|
2020-01-12 09:32:12 +08:00
|
|
|
# ifndef OPENSSL_NO_DSA
|
1998-12-21 18:52:47 +08:00
|
|
|
if (pkey->type == EVP_PKEY_DSA) {
|
2000-11-07 05:12:21 +08:00
|
|
|
int ret = pkey->save_parameters;
|
2015-01-22 11:40:55 +08:00
|
|
|
|
1998-12-21 18:52:47 +08:00
|
|
|
if (mode >= 0)
|
|
|
|
pkey->save_parameters = mode;
|
2017-10-17 22:04:09 +08:00
|
|
|
return ret;
|
1998-12-21 18:52:47 +08:00
|
|
|
}
|
2020-01-12 09:32:12 +08:00
|
|
|
# endif
|
|
|
|
# ifndef OPENSSL_NO_EC
|
2002-08-12 16:47:41 +08:00
|
|
|
if (pkey->type == EVP_PKEY_EC) {
|
2002-02-14 02:21:51 +08:00
|
|
|
int ret = pkey->save_parameters;
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2002-02-14 02:21:51 +08:00
|
|
|
if (mode >= 0)
|
|
|
|
pkey->save_parameters = mode;
|
2017-10-17 22:04:09 +08:00
|
|
|
return ret;
|
2002-02-14 02:21:51 +08:00
|
|
|
}
|
2020-01-12 09:32:12 +08:00
|
|
|
# endif
|
2017-10-17 22:04:09 +08:00
|
|
|
return 0;
|
1998-12-21 18:52:47 +08:00
|
|
|
}
|
|
|
|
|
2020-04-07 08:18:09 +08:00
|
|
|
int EVP_PKEY_set_ex_data(EVP_PKEY *key, int idx, void *arg)
|
|
|
|
{
|
|
|
|
return CRYPTO_set_ex_data(&key->ex_data, idx, arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
void *EVP_PKEY_get_ex_data(const EVP_PKEY *key, int idx)
|
|
|
|
{
|
|
|
|
return CRYPTO_get_ex_data(&key->ex_data, idx);
|
|
|
|
}
|
|
|
|
|
2003-04-07 18:09:44 +08:00
|
|
|
int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
|
1998-12-21 18:52:47 +08:00
|
|
|
{
|
2020-02-05 23:30:21 +08:00
|
|
|
/*
|
2020-10-15 11:41:59 +08:00
|
|
|
* Clean up legacy stuff from this function when legacy support is gone.
|
2020-02-05 23:30:21 +08:00
|
|
|
*/
|
|
|
|
|
2020-11-07 18:31:35 +08:00
|
|
|
EVP_PKEY *downgraded_from = NULL;
|
|
|
|
int ok = 0;
|
|
|
|
|
2020-02-05 23:30:21 +08:00
|
|
|
/*
|
2020-11-07 18:31:35 +08:00
|
|
|
* If |to| is a legacy key and |from| isn't, we must make a downgraded
|
|
|
|
* copy of |from|. If that fails, this function fails.
|
2020-02-05 23:30:21 +08:00
|
|
|
*/
|
2020-11-07 18:31:35 +08:00
|
|
|
if (evp_pkey_is_legacy(to) && evp_pkey_is_provided(from)) {
|
|
|
|
if (!evp_pkey_copy_downgraded(&downgraded_from, from))
|
|
|
|
goto end;
|
|
|
|
from = downgraded_from;
|
|
|
|
}
|
2020-03-21 13:21:26 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Make sure |to| is typed. Content is less important at this early
|
|
|
|
* stage.
|
|
|
|
*
|
|
|
|
* 1. If |to| is untyped, assign |from|'s key type to it.
|
|
|
|
* 2. If |to| contains a legacy key, compare its |type| to |from|'s.
|
|
|
|
* (|from| was already downgraded above)
|
|
|
|
*
|
|
|
|
* If |to| is a provided key, there's nothing more to do here, functions
|
|
|
|
* like evp_keymgmt_util_copy() and evp_pkey_export_to_provider() called
|
|
|
|
* further down help us find out if they are the same or not.
|
|
|
|
*/
|
Re-introduce legacy EVP_PKEY types for provided keys
EVP_PKEYs with provider side internal keys got the key type
EVP_PKEY_NONE. This turned out to be too disruptive, so we try
instead to find a matching EVP_PKEY_ASN1_METHOD and use whatever
EVP_PKEY type it uses.
To make internal coding easier, we introduce a few internal macros to
distinguish what can be expected from a EVP_PKEY:
- evp_pkey_is_blank(), to detect an unassigned EVP_PKEY.
- evp_pkey_is_typed(), to detect that an EVP_PKEY has been assigned a
type, which may be an old style type number or a EVP_KEYMGMT method.
- evp_pkey_is_assigned(), to detect that an EVP_PKEY has been assigned
an key value.
- evp_pkey_is_legacy(), to detect that the internal EVP_PKEY key is a
legacy one, i.e. will be handled via an EVP_PKEY_ASN1_METHOD and an
EVP_PKEY_METHOD.
- evp_pkey_is_provided(), to detect that the internal EVP_PKEY key is
a provider side one, i.e. will be handdled via an EVP_KEYMGMT and
other provider methods.
This also introduces EVP_PKEY_KEYMGMT, to indicate that this EVP_PKEY
contains a provider side key for which there are no known
EVP_PKEY_ASN1_METHODs or EVP_PKEY_METHODs, i.e. these can only be
handled via EVP_KEYMGMT and other provider methods.
Fixes #11823
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/11913)
2020-05-22 21:41:28 +08:00
|
|
|
if (evp_pkey_is_blank(to)) {
|
|
|
|
if (evp_pkey_is_legacy(from)) {
|
2020-02-05 23:30:21 +08:00
|
|
|
if (EVP_PKEY_set_type(to, from->type) == 0)
|
2020-11-07 18:31:35 +08:00
|
|
|
goto end;
|
2020-03-21 13:21:26 +08:00
|
|
|
} else {
|
|
|
|
if (EVP_PKEY_set_type_by_keymgmt(to, from->keymgmt) == 0)
|
2020-11-07 18:31:35 +08:00
|
|
|
goto end;
|
2020-03-21 13:21:26 +08:00
|
|
|
}
|
Re-introduce legacy EVP_PKEY types for provided keys
EVP_PKEYs with provider side internal keys got the key type
EVP_PKEY_NONE. This turned out to be too disruptive, so we try
instead to find a matching EVP_PKEY_ASN1_METHOD and use whatever
EVP_PKEY type it uses.
To make internal coding easier, we introduce a few internal macros to
distinguish what can be expected from a EVP_PKEY:
- evp_pkey_is_blank(), to detect an unassigned EVP_PKEY.
- evp_pkey_is_typed(), to detect that an EVP_PKEY has been assigned a
type, which may be an old style type number or a EVP_KEYMGMT method.
- evp_pkey_is_assigned(), to detect that an EVP_PKEY has been assigned
an key value.
- evp_pkey_is_legacy(), to detect that the internal EVP_PKEY key is a
legacy one, i.e. will be handled via an EVP_PKEY_ASN1_METHOD and an
EVP_PKEY_METHOD.
- evp_pkey_is_provided(), to detect that the internal EVP_PKEY key is
a provider side one, i.e. will be handdled via an EVP_KEYMGMT and
other provider methods.
This also introduces EVP_PKEY_KEYMGMT, to indicate that this EVP_PKEY
contains a provider side key for which there are no known
EVP_PKEY_ASN1_METHODs or EVP_PKEY_METHODs, i.e. these can only be
handled via EVP_KEYMGMT and other provider methods.
Fixes #11823
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/11913)
2020-05-22 21:41:28 +08:00
|
|
|
} else if (evp_pkey_is_legacy(to)) {
|
2020-03-21 13:21:26 +08:00
|
|
|
if (to->type != from->type) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES);
|
2020-11-07 18:31:35 +08:00
|
|
|
goto end;
|
2020-02-05 23:30:21 +08:00
|
|
|
}
|
1998-12-21 18:52:47 +08:00
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
|
1998-12-21 18:52:47 +08:00
|
|
|
if (EVP_PKEY_missing_parameters(from)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_MISSING_PARAMETERS);
|
2020-11-07 18:31:35 +08:00
|
|
|
goto end;
|
1998-12-21 18:52:47 +08:00
|
|
|
}
|
2016-05-27 21:18:40 +08:00
|
|
|
|
|
|
|
if (!EVP_PKEY_missing_parameters(to)) {
|
2020-05-25 19:17:51 +08:00
|
|
|
if (EVP_PKEY_parameters_eq(to, from) == 1)
|
2020-11-07 18:31:35 +08:00
|
|
|
ok = 1;
|
|
|
|
else
|
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_PARAMETERS);
|
|
|
|
goto end;
|
2016-05-27 21:18:40 +08:00
|
|
|
}
|
|
|
|
|
2020-02-05 23:30:21 +08:00
|
|
|
/* For purely provided keys, we just call the keymgmt utility */
|
2020-11-07 18:31:35 +08:00
|
|
|
if (to->keymgmt != NULL && from->keymgmt != NULL) {
|
|
|
|
ok = evp_keymgmt_util_copy(to, (EVP_PKEY *)from, SELECT_PARAMETERS);
|
|
|
|
goto end;
|
|
|
|
}
|
2020-02-05 23:30:21 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If |to| is provided, we know that |from| is legacy at this point.
|
2021-04-09 01:02:44 +08:00
|
|
|
* Try exporting |from| to |to|'s keymgmt, then use evp_keymgmt_dup()
|
2020-02-05 23:30:21 +08:00
|
|
|
* to copy the appropriate data to |to|'s keydata.
|
2021-04-09 01:02:44 +08:00
|
|
|
* We cannot override existing data so do it only if there is no keydata
|
|
|
|
* in |to| yet.
|
2020-02-05 23:30:21 +08:00
|
|
|
*/
|
2021-04-09 01:02:44 +08:00
|
|
|
if (to->keymgmt != NULL && to->keydata == NULL) {
|
2020-02-05 23:30:21 +08:00
|
|
|
EVP_KEYMGMT *to_keymgmt = to->keymgmt;
|
|
|
|
void *from_keydata =
|
|
|
|
evp_pkey_export_to_provider((EVP_PKEY *)from, NULL, &to_keymgmt,
|
|
|
|
NULL);
|
|
|
|
|
2020-03-21 13:21:26 +08:00
|
|
|
/*
|
|
|
|
* If we get a NULL, it could be an internal error, or it could be
|
|
|
|
* that there's a key mismatch. We're pretending the latter...
|
|
|
|
*/
|
2020-11-07 18:31:35 +08:00
|
|
|
if (from_keydata == NULL)
|
2020-03-21 13:21:26 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_DIFFERENT_KEY_TYPES);
|
2020-11-07 18:31:35 +08:00
|
|
|
else
|
2021-04-09 01:02:44 +08:00
|
|
|
ok = (to->keydata = evp_keymgmt_dup(to->keymgmt,
|
|
|
|
from_keydata,
|
|
|
|
SELECT_PARAMETERS)) != NULL;
|
2020-11-07 18:31:35 +08:00
|
|
|
goto end;
|
2020-02-05 23:30:21 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Both keys are legacy */
|
|
|
|
if (from->ameth != NULL && from->ameth->param_copy != NULL)
|
2020-11-07 18:31:35 +08:00
|
|
|
ok = from->ameth->param_copy(to, from);
|
|
|
|
end:
|
|
|
|
EVP_PKEY_free(downgraded_from);
|
|
|
|
return ok;
|
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)
|
1998-12-21 18:52:47 +08:00
|
|
|
{
|
2020-02-05 17:18:51 +08:00
|
|
|
if (pkey != NULL) {
|
|
|
|
if (pkey->keymgmt != NULL)
|
2020-03-23 13:03:16 +08:00
|
|
|
return !evp_keymgmt_util_has((EVP_PKEY *)pkey, SELECT_PARAMETERS);
|
2020-02-05 17:18:51 +08:00
|
|
|
else if (pkey->ameth != NULL && pkey->ameth->param_missing != NULL)
|
|
|
|
return pkey->ameth->param_missing(pkey);
|
|
|
|
}
|
2006-03-21 01:56:05 +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.
|
2021-03-16 00:10:26 +08:00
|
|
|
* When legacy keys are gone, we replace a call to this functions with
|
2020-02-05 19:55:43 +08:00
|
|
|
* 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 */
|
2020-07-20 16:50:04 +08:00
|
|
|
if (!ossl_assert(evp_pkey_is_provided(a) || evp_pkey_is_provided(b)))
|
2020-02-05 19:55:43 +08:00
|
|
|
return -2;
|
|
|
|
|
|
|
|
/* For purely provided keys, we just call the keymgmt utility */
|
2020-07-20 16:50:04 +08:00
|
|
|
if (evp_pkey_is_provided(a) && evp_pkey_is_provided(b))
|
2020-02-05 19:55:43 +08:00
|
|
|
return evp_keymgmt_util_match((EVP_PKEY *)a, (EVP_PKEY *)b, selection);
|
|
|
|
|
|
|
|
/*
|
2020-03-21 13:21:26 +08:00
|
|
|
* At this point, one of them is provided, the other not. This allows
|
|
|
|
* us to compare types using legacy NIDs.
|
|
|
|
*/
|
2020-07-20 16:50:04 +08:00
|
|
|
if (evp_pkey_is_legacy(a)
|
|
|
|
&& !EVP_KEYMGMT_is_a(b->keymgmt, OBJ_nid2sn(a->type)))
|
|
|
|
return -1; /* not the same key type */
|
|
|
|
if (evp_pkey_is_legacy(b)
|
|
|
|
&& !EVP_KEYMGMT_is_a(a->keymgmt, OBJ_nid2sn(b->type)))
|
2020-03-21 13:21:26 +08:00
|
|
|
return -1; /* not the same key type */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We've determined that they both are the same keytype, so the next
|
|
|
|
* step is to do a bit of cross export to ensure we have keydata for
|
|
|
|
* both keys in the same keymgmt.
|
2020-02-05 19:55:43 +08:00
|
|
|
*/
|
|
|
|
keymgmt1 = a->keymgmt;
|
|
|
|
keydata1 = a->keydata;
|
|
|
|
keymgmt2 = b->keymgmt;
|
|
|
|
keydata2 = b->keydata;
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
2020-08-08 00:47:04 +08:00
|
|
|
/* If the keymgmt implementations are NULL, the export failed */
|
|
|
|
if (keymgmt1 == NULL)
|
|
|
|
return -2;
|
|
|
|
|
2020-02-05 19:55:43 +08:00
|
|
|
return evp_keymgmt_match(keymgmt1, keydata1, keydata2, selection);
|
|
|
|
}
|
|
|
|
|
2021-04-23 08:53:03 +08:00
|
|
|
# ifndef OPENSSL_NO_DEPRECATED_3_0
|
2003-04-06 23:31:18 +08:00
|
|
|
int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
|
2020-05-25 19:17:51 +08:00
|
|
|
{
|
|
|
|
return EVP_PKEY_parameters_eq(a, b);
|
|
|
|
}
|
2021-04-23 08:53:03 +08:00
|
|
|
#endif
|
2020-05-25 19:17:51 +08:00
|
|
|
|
|
|
|
int EVP_PKEY_parameters_eq(const EVP_PKEY *a, const EVP_PKEY *b)
|
1998-12-21 18:56:39 +08:00
|
|
|
{
|
2020-02-05 19:55:43 +08:00
|
|
|
/*
|
2021-03-16 00:10:26 +08:00
|
|
|
* This will just call evp_keymgmt_util_match when legacy support
|
2020-02-05 19:55:43 +08:00
|
|
|
* is gone.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (a->keymgmt != NULL || b->keymgmt != NULL)
|
2020-03-23 13:03:16 +08:00
|
|
|
return evp_pkey_cmp_any(a, b, SELECT_PARAMETERS);
|
2020-02-05 19:55:43 +08:00
|
|
|
|
|
|
|
/* All legacy keys */
|
2006-03-21 01:56:05 +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)
|
2006-03-21 01:56:05 +08:00
|
|
|
return a->ameth->param_cmp(a, b);
|
2006-04-28 20:27:37 +08:00
|
|
|
return -2;
|
1998-12-21 18:56:39 +08:00
|
|
|
}
|
|
|
|
|
2021-04-23 08:53:03 +08:00
|
|
|
# ifndef OPENSSL_NO_DEPRECATED_3_0
|
2003-04-06 23:31:18 +08:00
|
|
|
int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
|
2020-05-25 19:17:51 +08:00
|
|
|
{
|
|
|
|
return EVP_PKEY_eq(a, b);
|
|
|
|
}
|
2021-04-23 08:53:03 +08:00
|
|
|
#endif
|
2020-05-25 19:17:51 +08:00
|
|
|
|
|
|
|
int EVP_PKEY_eq(const EVP_PKEY *a, const EVP_PKEY *b)
|
2003-04-04 06:27:24 +08:00
|
|
|
{
|
2020-02-05 19:55:43 +08:00
|
|
|
/*
|
2021-03-16 00:10:26 +08:00
|
|
|
* This will just call evp_keymgmt_util_match when legacy support
|
2020-02-05 19:55:43 +08:00
|
|
|
* is gone.
|
|
|
|
*/
|
|
|
|
|
2021-04-20 22:39:00 +08:00
|
|
|
/* Trivial shortcuts */
|
|
|
|
if (a == b)
|
|
|
|
return 1;
|
|
|
|
if (a == NULL || b == NULL)
|
|
|
|
return 0;
|
|
|
|
|
2022-09-13 12:37:05 +08:00
|
|
|
if (a->keymgmt != NULL || b->keymgmt != NULL) {
|
|
|
|
int selection = SELECT_PARAMETERS;
|
|
|
|
|
|
|
|
if (evp_keymgmt_util_has((EVP_PKEY *)a, OSSL_KEYMGMT_SELECT_PUBLIC_KEY)
|
|
|
|
&& evp_keymgmt_util_has((EVP_PKEY *)b, OSSL_KEYMGMT_SELECT_PUBLIC_KEY))
|
|
|
|
selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
|
|
|
|
else
|
|
|
|
selection |= OSSL_KEYMGMT_SELECT_KEYPAIR;
|
|
|
|
return evp_pkey_cmp_any(a, b, selection);
|
|
|
|
}
|
2020-02-05 19:55:43 +08:00
|
|
|
|
|
|
|
/* All legacy keys */
|
2003-04-04 06:27:24 +08:00
|
|
|
if (a->type != b->type)
|
|
|
|
return -1;
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2020-02-05 19:55:43 +08:00
|
|
|
if (a->ameth != NULL) {
|
2006-07-03 05:12:40 +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) {
|
2006-07-05 04:27:44 +08:00
|
|
|
ret = a->ameth->param_cmp(a, b);
|
2006-07-03 05:12:40 +08:00
|
|
|
if (ret <= 0)
|
|
|
|
return ret;
|
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2020-02-05 19:55:43 +08:00
|
|
|
if (a->ameth->pub_cmp != NULL)
|
2006-07-03 05:12:40 +08:00
|
|
|
return a->ameth->pub_cmp(a, b);
|
|
|
|
}
|
2015-01-22 11:40:55 +08:00
|
|
|
|
2006-03-21 01:56:05 +08:00
|
|
|
return -2;
|
2003-04-04 06:27:24 +08:00
|
|
|
}
|
|
|
|
|
2020-04-24 18:33:33 +08:00
|
|
|
|
2020-10-15 17:55:50 +08:00
|
|
|
static EVP_PKEY *new_raw_key_int(OSSL_LIB_CTX *libctx,
|
2020-04-24 18:33:33 +08:00
|
|
|
const char *strtype,
|
|
|
|
const char *propq,
|
|
|
|
int nidtype,
|
|
|
|
ENGINE *e,
|
|
|
|
const unsigned char *key,
|
|
|
|
size_t len,
|
|
|
|
int key_is_priv)
|
2018-03-05 22:06:41 +08:00
|
|
|
{
|
2020-04-24 18:33:33 +08:00
|
|
|
EVP_PKEY *pkey = NULL;
|
|
|
|
EVP_PKEY_CTX *ctx = NULL;
|
|
|
|
const EVP_PKEY_ASN1_METHOD *ameth = NULL;
|
|
|
|
int result = 0;
|
|
|
|
|
|
|
|
# ifndef OPENSSL_NO_ENGINE
|
|
|
|
/* Check if there is an Engine for this type */
|
|
|
|
if (e == NULL) {
|
|
|
|
ENGINE *tmpe = NULL;
|
|
|
|
|
|
|
|
if (strtype != NULL)
|
|
|
|
ameth = EVP_PKEY_asn1_find_str(&tmpe, strtype, -1);
|
|
|
|
else if (nidtype != EVP_PKEY_NONE)
|
|
|
|
ameth = EVP_PKEY_asn1_find(&tmpe, nidtype);
|
|
|
|
|
|
|
|
/* If tmpe is NULL then no engine is claiming to support this type */
|
|
|
|
if (tmpe == NULL)
|
|
|
|
ameth = NULL;
|
|
|
|
|
|
|
|
ENGINE_finish(tmpe);
|
|
|
|
}
|
|
|
|
# endif
|
2018-03-05 22:06:41 +08:00
|
|
|
|
2020-04-24 18:33:33 +08:00
|
|
|
if (e == NULL && ameth == NULL) {
|
|
|
|
/*
|
|
|
|
* No engine is claiming to support this type, so lets see if we have
|
|
|
|
* a provider.
|
|
|
|
*/
|
|
|
|
ctx = EVP_PKEY_CTX_new_from_name(libctx,
|
|
|
|
strtype != NULL ? strtype
|
|
|
|
: OBJ_nid2sn(nidtype),
|
|
|
|
propq);
|
2020-08-30 02:48:51 +08:00
|
|
|
if (ctx == NULL)
|
2020-04-24 18:33:33 +08:00
|
|
|
goto err;
|
|
|
|
/* May fail if no provider available */
|
|
|
|
ERR_set_mark();
|
2021-02-05 11:55:50 +08:00
|
|
|
if (EVP_PKEY_fromdata_init(ctx) == 1) {
|
2020-04-24 18:33:33 +08:00
|
|
|
OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
|
|
|
|
|
|
|
|
ERR_clear_last_mark();
|
|
|
|
params[0] = OSSL_PARAM_construct_octet_string(
|
|
|
|
key_is_priv ? OSSL_PKEY_PARAM_PRIV_KEY
|
|
|
|
: OSSL_PKEY_PARAM_PUB_KEY,
|
|
|
|
(void *)key, len);
|
|
|
|
|
2021-02-05 11:55:50 +08:00
|
|
|
if (EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEYPAIR, params) != 1) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_KEY_SETUP_FAILED);
|
2020-04-24 18:33:33 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
EVP_PKEY_CTX_free(ctx);
|
|
|
|
|
|
|
|
return pkey;
|
|
|
|
}
|
|
|
|
ERR_pop_to_mark();
|
|
|
|
/* else not supported so fallback to legacy */
|
2018-03-05 22:06:41 +08:00
|
|
|
}
|
|
|
|
|
2020-04-24 18:33:33 +08:00
|
|
|
/* Legacy code path */
|
|
|
|
|
|
|
|
pkey = EVP_PKEY_new();
|
|
|
|
if (pkey == NULL) {
|
2022-09-29 19:57:34 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB);
|
2018-03-05 22:06:41 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2020-04-24 18:33:33 +08:00
|
|
|
if (!pkey_set_type(pkey, e, nidtype, strtype, -1, NULL)) {
|
2022-08-26 16:04:01 +08:00
|
|
|
/* ERR_raise(ERR_LIB_EVP, ...) already called */
|
2018-03-05 22:06:41 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2020-04-24 18:33:33 +08:00
|
|
|
if (!ossl_assert(pkey->ameth != NULL))
|
|
|
|
goto err;
|
2018-03-05 22:06:41 +08:00
|
|
|
|
2020-04-24 18:33:33 +08:00
|
|
|
if (key_is_priv) {
|
|
|
|
if (pkey->ameth->set_priv_key == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
2020-04-24 18:33:33 +08:00
|
|
|
goto err;
|
|
|
|
}
|
2018-03-05 22:06:41 +08:00
|
|
|
|
2020-04-24 18:33:33 +08:00
|
|
|
if (!pkey->ameth->set_priv_key(pkey, key, len)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_KEY_SETUP_FAILED);
|
2020-04-24 18:33:33 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (pkey->ameth->set_pub_key == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
2020-04-24 18:33:33 +08:00
|
|
|
goto err;
|
|
|
|
}
|
2018-03-05 22:06:41 +08:00
|
|
|
|
2020-04-24 18:33:33 +08:00
|
|
|
if (!pkey->ameth->set_pub_key(pkey, key, len)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_KEY_SETUP_FAILED);
|
2020-04-24 18:33:33 +08:00
|
|
|
goto err;
|
|
|
|
}
|
2018-03-05 22:06:41 +08:00
|
|
|
}
|
|
|
|
|
2020-04-24 18:33:33 +08:00
|
|
|
result = 1;
|
|
|
|
err:
|
|
|
|
if (!result) {
|
|
|
|
EVP_PKEY_free(pkey);
|
|
|
|
pkey = NULL;
|
2018-03-05 22:06:41 +08:00
|
|
|
}
|
2020-04-24 18:33:33 +08:00
|
|
|
EVP_PKEY_CTX_free(ctx);
|
|
|
|
return pkey;
|
|
|
|
}
|
2018-03-05 22:06:41 +08:00
|
|
|
|
2020-10-15 17:55:50 +08:00
|
|
|
EVP_PKEY *EVP_PKEY_new_raw_private_key_ex(OSSL_LIB_CTX *libctx,
|
2020-09-24 17:42:23 +08:00
|
|
|
const char *keytype,
|
|
|
|
const char *propq,
|
|
|
|
const unsigned char *priv, size_t len)
|
2020-04-24 18:33:33 +08:00
|
|
|
{
|
|
|
|
return new_raw_key_int(libctx, keytype, propq, EVP_PKEY_NONE, NULL, priv,
|
|
|
|
len, 1);
|
|
|
|
}
|
2018-03-05 22:06:41 +08:00
|
|
|
|
2020-04-24 18:33:33 +08:00
|
|
|
EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e,
|
|
|
|
const unsigned char *priv,
|
|
|
|
size_t len)
|
|
|
|
{
|
|
|
|
return new_raw_key_int(NULL, NULL, NULL, type, e, priv, len, 1);
|
|
|
|
}
|
2018-03-05 22:06:41 +08:00
|
|
|
|
2020-10-15 17:55:50 +08:00
|
|
|
EVP_PKEY *EVP_PKEY_new_raw_public_key_ex(OSSL_LIB_CTX *libctx,
|
2020-09-24 17:42:23 +08:00
|
|
|
const char *keytype, const char *propq,
|
|
|
|
const unsigned char *pub, size_t len)
|
2020-04-24 18:33:33 +08:00
|
|
|
{
|
|
|
|
return new_raw_key_int(libctx, keytype, propq, EVP_PKEY_NONE, NULL, pub,
|
|
|
|
len, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e,
|
|
|
|
const unsigned char *pub,
|
|
|
|
size_t len)
|
|
|
|
{
|
|
|
|
return new_raw_key_int(NULL, NULL, NULL, type, e, pub, len, 0);
|
2018-03-05 22:06:41 +08:00
|
|
|
}
|
|
|
|
|
2020-04-24 23:19:25 +08:00
|
|
|
struct raw_key_details_st
|
|
|
|
{
|
|
|
|
unsigned char **key;
|
|
|
|
size_t *len;
|
|
|
|
int selection;
|
|
|
|
};
|
|
|
|
|
|
|
|
static OSSL_CALLBACK get_raw_key_details;
|
|
|
|
static int get_raw_key_details(const OSSL_PARAM params[], void *arg)
|
|
|
|
{
|
|
|
|
const OSSL_PARAM *p = NULL;
|
|
|
|
struct raw_key_details_st *raw_key = arg;
|
|
|
|
|
|
|
|
if (raw_key->selection == OSSL_KEYMGMT_SELECT_PRIVATE_KEY) {
|
|
|
|
if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY))
|
|
|
|
!= NULL)
|
|
|
|
return OSSL_PARAM_get_octet_string(p, (void **)raw_key->key,
|
2021-10-07 18:33:17 +08:00
|
|
|
raw_key->key == NULL ? 0 : *raw_key->len,
|
|
|
|
raw_key->len);
|
2020-04-24 23:19:25 +08:00
|
|
|
} else if (raw_key->selection == OSSL_KEYMGMT_SELECT_PUBLIC_KEY) {
|
|
|
|
if ((p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY))
|
|
|
|
!= NULL)
|
|
|
|
return OSSL_PARAM_get_octet_string(p, (void **)raw_key->key,
|
2021-10-07 18:33:17 +08:00
|
|
|
raw_key->key == NULL ? 0 : *raw_key->len,
|
|
|
|
raw_key->len);
|
2020-04-24 23:19:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
{
|
2020-04-24 23:19:25 +08:00
|
|
|
if (pkey->keymgmt != NULL) {
|
|
|
|
struct raw_key_details_st raw_key;
|
|
|
|
|
|
|
|
raw_key.key = priv == NULL ? NULL : &priv;
|
|
|
|
raw_key.len = len;
|
|
|
|
raw_key.selection = OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
|
|
|
|
|
2020-09-11 14:35:26 +08:00
|
|
|
return evp_keymgmt_util_export(pkey, OSSL_KEYMGMT_SELECT_PRIVATE_KEY,
|
|
|
|
get_raw_key_details, &raw_key);
|
2020-04-24 23:19:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (pkey->ameth == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
2020-04-24 23:19:25 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pkey->ameth->get_priv_key == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
2018-06-01 19:22:28 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pkey->ameth->get_priv_key(pkey, priv, len)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_GET_RAW_KEY_FAILED);
|
2018-06-01 19:22:28 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub,
|
|
|
|
size_t *len)
|
|
|
|
{
|
2020-04-24 23:19:25 +08:00
|
|
|
if (pkey->keymgmt != NULL) {
|
|
|
|
struct raw_key_details_st raw_key;
|
|
|
|
|
|
|
|
raw_key.key = pub == NULL ? NULL : &pub;
|
|
|
|
raw_key.len = len;
|
|
|
|
raw_key.selection = OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
|
|
|
|
|
2020-09-11 14:35:26 +08:00
|
|
|
return evp_keymgmt_util_export(pkey, OSSL_KEYMGMT_SELECT_PUBLIC_KEY,
|
|
|
|
get_raw_key_details, &raw_key);
|
2020-04-24 23:19:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (pkey->ameth == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
2020-04-24 23:19:25 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-06-01 19:22:28 +08:00
|
|
|
if (pkey->ameth->get_pub_key == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
2018-06-01 19:22:28 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pkey->ameth->get_pub_key(pkey, pub, len)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_GET_RAW_KEY_FAILED);
|
2018-06-01 19:22:28 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-08-11 23:17:00 +08:00
|
|
|
static EVP_PKEY *new_cmac_key_int(const unsigned char *priv, size_t len,
|
|
|
|
const char *cipher_name,
|
2020-10-15 17:55:50 +08:00
|
|
|
const EVP_CIPHER *cipher,
|
|
|
|
OSSL_LIB_CTX *libctx,
|
2020-08-11 23:17:00 +08:00
|
|
|
const char *propq, ENGINE *e)
|
2018-03-06 01:23:57 +08:00
|
|
|
{
|
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
|
2020-08-17 22:14:14 +08:00
|
|
|
OSSL_PARAM params[5], *p = params;
|
2020-08-11 23:17:00 +08:00
|
|
|
EVP_PKEY *pkey = NULL;
|
|
|
|
EVP_PKEY_CTX *ctx;
|
|
|
|
|
|
|
|
if (cipher != NULL)
|
Rename all getters to use get/get0 in name
For functions that exist in 1.1.1 provide a simple aliases via #define.
Fixes #15236
Functions with OSSL_DECODER_, OSSL_ENCODER_, OSSL_STORE_LOADER_,
EVP_KEYEXCH_, EVP_KEM_, EVP_ASYM_CIPHER_, EVP_SIGNATURE_,
EVP_KEYMGMT_, EVP_RAND_, EVP_MAC_, EVP_KDF_, EVP_PKEY_,
EVP_MD_, and EVP_CIPHER_ prefixes are renamed.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15405)
2021-05-21 22:58:08 +08:00
|
|
|
cipher_name = EVP_CIPHER_get0_name(cipher);
|
2020-08-11 23:17:00 +08:00
|
|
|
|
|
|
|
if (cipher_name == NULL) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_KEY_SETUP_FAILED);
|
2020-08-11 23:17:00 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx = EVP_PKEY_CTX_new_from_name(libctx, "CMAC", propq);
|
2020-09-03 18:42:43 +08:00
|
|
|
if (ctx == NULL)
|
2020-08-11 23:17:00 +08:00
|
|
|
goto err;
|
|
|
|
|
2021-10-08 16:59:00 +08:00
|
|
|
if (EVP_PKEY_fromdata_init(ctx) <= 0) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_KEY_SETUP_FAILED);
|
2018-03-06 01:23:57 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2020-08-11 23:17:00 +08:00
|
|
|
*p++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
|
|
|
|
(void *)priv, len);
|
|
|
|
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_CIPHER,
|
|
|
|
(char *)cipher_name, 0);
|
2020-08-17 22:14:14 +08:00
|
|
|
if (propq != NULL)
|
|
|
|
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_PROPERTIES,
|
|
|
|
(char *)propq, 0);
|
2020-01-12 09:32:12 +08:00
|
|
|
# ifndef OPENSSL_NO_ENGINE
|
2019-08-29 18:55:57 +08:00
|
|
|
if (engine_id != NULL)
|
2020-08-11 23:17:00 +08:00
|
|
|
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_ENGINE,
|
|
|
|
(char *)engine_id, 0);
|
2020-01-12 09:32:12 +08:00
|
|
|
# endif
|
2020-08-11 23:17:00 +08:00
|
|
|
*p = OSSL_PARAM_construct_end();
|
2019-08-28 23:18:05 +08:00
|
|
|
|
2021-10-08 17:01:47 +08:00
|
|
|
if (EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_KEYPAIR, params) <= 0) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_KEY_SETUP_FAILED);
|
2018-03-06 01:23:57 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
err:
|
2020-08-11 23:17:00 +08:00
|
|
|
EVP_PKEY_CTX_free(ctx);
|
|
|
|
|
|
|
|
return pkey;
|
2020-01-12 09:32:12 +08:00
|
|
|
# else
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
|
2018-03-19 18:35:16 +08:00
|
|
|
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
|
|
|
|
2020-08-11 23:17:00 +08:00
|
|
|
EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
|
|
|
|
size_t len, const EVP_CIPHER *cipher)
|
|
|
|
{
|
|
|
|
return new_cmac_key_int(priv, len, NULL, cipher, NULL, NULL, e);
|
|
|
|
}
|
|
|
|
|
2006-06-05 19:52:46 +08:00
|
|
|
int EVP_PKEY_set_type(EVP_PKEY *pkey, int type)
|
|
|
|
{
|
2020-03-21 13:14:25 +08:00
|
|
|
return pkey_set_type(pkey, NULL, type, NULL, -1, NULL);
|
2006-06-05 19:52:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len)
|
|
|
|
{
|
2020-03-21 13:14:25 +08:00
|
|
|
return pkey_set_type(pkey, NULL, EVP_PKEY_NONE, str, len, NULL);
|
2006-06-05 19:52:46 +08:00
|
|
|
}
|
2018-06-19 03:49:15 +08:00
|
|
|
|
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)) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, ERR_R_ENGINE_LIB);
|
2017-10-09 22:21:11 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (ENGINE_get_pkey_meth(e, pkey->type) == NULL) {
|
|
|
|
ENGINE_finish(e);
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_ALGORITHM);
|
2017-10-09 22:21:11 +08:00
|
|
|
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
|
2021-02-26 00:27:46 +08:00
|
|
|
|
|
|
|
# ifndef OPENSSL_NO_DEPRECATED_3_0
|
2021-04-13 23:31:08 +08:00
|
|
|
static void detect_foreign_key(EVP_PKEY *pkey)
|
|
|
|
{
|
|
|
|
switch (pkey->type) {
|
|
|
|
case EVP_PKEY_RSA:
|
2023-08-23 21:08:51 +08:00
|
|
|
case EVP_PKEY_RSA_PSS:
|
2021-04-13 23:31:08 +08:00
|
|
|
pkey->foreign = pkey->pkey.rsa != NULL
|
|
|
|
&& ossl_rsa_is_foreign(pkey->pkey.rsa);
|
|
|
|
break;
|
|
|
|
# ifndef OPENSSL_NO_EC
|
|
|
|
case EVP_PKEY_SM2:
|
2023-06-10 19:36:17 +08:00
|
|
|
break;
|
2021-04-13 23:31:08 +08:00
|
|
|
case EVP_PKEY_EC:
|
|
|
|
pkey->foreign = pkey->pkey.ec != NULL
|
|
|
|
&& ossl_ec_key_is_foreign(pkey->pkey.ec);
|
|
|
|
break;
|
|
|
|
# endif
|
|
|
|
# ifndef OPENSSL_NO_DSA
|
|
|
|
case EVP_PKEY_DSA:
|
|
|
|
pkey->foreign = pkey->pkey.dsa != NULL
|
|
|
|
&& ossl_dsa_is_foreign(pkey->pkey.dsa);
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
# ifndef OPENSSL_NO_DH
|
|
|
|
case EVP_PKEY_DH:
|
|
|
|
pkey->foreign = pkey->pkey.dh != NULL
|
|
|
|
&& ossl_dh_is_foreign(pkey->pkey.dh);
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
pkey->foreign = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-06-05 19:52:46 +08:00
|
|
|
int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key)
|
|
|
|
{
|
2021-02-26 00:27:46 +08:00
|
|
|
# ifndef OPENSSL_NO_EC
|
2021-04-08 23:22:51 +08:00
|
|
|
int pktype;
|
|
|
|
|
|
|
|
pktype = EVP_PKEY_type(type);
|
|
|
|
if ((key != NULL) && (pktype == EVP_PKEY_EC || pktype == EVP_PKEY_SM2)) {
|
2020-01-25 00:51:39 +08:00
|
|
|
const EC_GROUP *group = EC_KEY_get0_group(key);
|
|
|
|
|
2021-04-08 23:22:51 +08:00
|
|
|
if (group != NULL) {
|
|
|
|
int curve = EC_GROUP_get_curve_name(group);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Regardless of what is requested the SM2 curve must be SM2 type,
|
|
|
|
* and non SM2 curves are EC type.
|
|
|
|
*/
|
|
|
|
if (curve == NID_sm2 && pktype == EVP_PKEY_EC)
|
|
|
|
type = EVP_PKEY_SM2;
|
|
|
|
else if(curve != NID_sm2 && pktype == EVP_PKEY_SM2)
|
|
|
|
type = EVP_PKEY_EC;
|
|
|
|
}
|
2020-01-25 00:51:39 +08:00
|
|
|
}
|
2021-02-26 00:27:46 +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))
|
2006-06-05 19:52:46 +08:00
|
|
|
return 0;
|
2021-04-08 23:22:51 +08:00
|
|
|
|
1998-12-21 18:52:47 +08:00
|
|
|
pkey->pkey.ptr = key;
|
2021-04-13 23:31:08 +08:00
|
|
|
detect_foreign_key(pkey);
|
|
|
|
|
2006-06-05 19:52:46 +08:00
|
|
|
return (key != NULL);
|
1998-12-21 18:52:47 +08:00
|
|
|
}
|
2021-02-26 00:27:46 +08:00
|
|
|
# endif
|
1998-12-21 18:52:47 +08:00
|
|
|
|
2021-03-09 04:36:10 +08:00
|
|
|
void *EVP_PKEY_get0(const EVP_PKEY *pkey)
|
2006-03-24 21:46:58 +08:00
|
|
|
{
|
2020-08-11 13:03:42 +08:00
|
|
|
if (pkey == NULL)
|
|
|
|
return NULL;
|
2021-02-25 00:38:28 +08:00
|
|
|
|
2021-03-09 04:36:10 +08:00
|
|
|
if (!evp_pkey_is_provided(pkey))
|
|
|
|
return pkey->pkey.ptr;
|
|
|
|
|
|
|
|
return NULL;
|
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)
|
|
|
|
{
|
2021-03-02 23:52:00 +08:00
|
|
|
const ASN1_OCTET_STRING *os = NULL;
|
2016-06-16 02:02:04 +08:00
|
|
|
if (pkey->type != EVP_PKEY_HMAC) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_EXPECTING_AN_HMAC_KEY);
|
2016-06-16 02:02:04 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
2021-03-09 04:36:10 +08:00
|
|
|
os = evp_pkey_get_legacy((EVP_PKEY *)pkey);
|
|
|
|
if (os != NULL) {
|
|
|
|
*len = os->length;
|
|
|
|
return os->data;
|
|
|
|
}
|
|
|
|
return NULL;
|
2016-06-16 02:02:04 +08:00
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
{
|
2021-03-02 23:52:00 +08:00
|
|
|
const ASN1_OCTET_STRING *os = NULL;
|
2016-12-17 06:00:43 +08:00
|
|
|
if (pkey->type != EVP_PKEY_POLY1305) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_EXPECTING_A_POLY1305_KEY);
|
2016-12-17 06:00:43 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
2021-03-09 04:36:10 +08:00
|
|
|
os = evp_pkey_get_legacy((EVP_PKEY *)pkey);
|
|
|
|
if (os != NULL) {
|
|
|
|
*len = os->length;
|
|
|
|
return os->data;
|
|
|
|
}
|
|
|
|
return NULL;
|
2016-12-17 06:00:43 +08:00
|
|
|
}
|
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)
|
|
|
|
{
|
2021-03-02 23:52:00 +08:00
|
|
|
const ASN1_OCTET_STRING *os = NULL;
|
2017-01-12 05:38:44 +08:00
|
|
|
|
|
|
|
if (pkey->type != EVP_PKEY_SIPHASH) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_EXPECTING_A_SIPHASH_KEY);
|
2017-01-12 05:38:44 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
2021-03-09 04:36:10 +08:00
|
|
|
os = evp_pkey_get_legacy((EVP_PKEY *)pkey);
|
|
|
|
if (os != NULL) {
|
|
|
|
*len = os->length;
|
|
|
|
return os->data;
|
|
|
|
}
|
|
|
|
return NULL;
|
2017-01-12 05:38:44 +08:00
|
|
|
}
|
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_DSA
|
2021-03-02 23:52:00 +08:00
|
|
|
static DSA *evp_pkey_get0_DSA_int(const EVP_PKEY *pkey)
|
1999-10-25 10:00:09 +08:00
|
|
|
{
|
|
|
|
if (pkey->type != EVP_PKEY_DSA) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_EXPECTING_A_DSA_KEY);
|
1999-10-25 10:00:09 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
2021-02-25 00:38:28 +08:00
|
|
|
return evp_pkey_get_legacy((EVP_PKEY *)pkey);
|
1999-10-25 10:00:09 +08:00
|
|
|
}
|
2015-12-14 01:57:01 +08:00
|
|
|
|
2021-03-02 23:52:00 +08:00
|
|
|
const DSA *EVP_PKEY_get0_DSA(const EVP_PKEY *pkey)
|
|
|
|
{
|
|
|
|
return evp_pkey_get0_DSA_int(pkey);
|
|
|
|
}
|
|
|
|
|
2020-04-15 19:02:52 +08:00
|
|
|
int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key)
|
|
|
|
{
|
|
|
|
int ret = EVP_PKEY_assign_DSA(pkey, key);
|
|
|
|
if (ret)
|
|
|
|
DSA_up_ref(key);
|
|
|
|
return ret;
|
|
|
|
}
|
2015-12-14 01:57:01 +08:00
|
|
|
DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey)
|
|
|
|
{
|
2021-03-02 23:52:00 +08:00
|
|
|
DSA *ret = evp_pkey_get0_DSA_int(pkey);
|
|
|
|
|
2015-12-14 01:57:01 +08:00
|
|
|
if (ret != NULL)
|
|
|
|
DSA_up_ref(ret);
|
|
|
|
return ret;
|
|
|
|
}
|
2020-04-15 19:02:52 +08:00
|
|
|
# endif /* OPENSSL_NO_DSA */
|
1999-10-25 10:00:09 +08:00
|
|
|
|
2023-04-17 16:20:31 +08:00
|
|
|
# ifndef OPENSSL_NO_ECX
|
2021-03-02 23:52:00 +08:00
|
|
|
static const ECX_KEY *evp_pkey_get0_ECX_KEY(const EVP_PKEY *pkey, int type)
|
2020-07-28 00:40:05 +08:00
|
|
|
{
|
Rename all getters to use get/get0 in name
For functions that exist in 1.1.1 provide a simple aliases via #define.
Fixes #15236
Functions with OSSL_DECODER_, OSSL_ENCODER_, OSSL_STORE_LOADER_,
EVP_KEYEXCH_, EVP_KEM_, EVP_ASYM_CIPHER_, EVP_SIGNATURE_,
EVP_KEYMGMT_, EVP_RAND_, EVP_MAC_, EVP_KDF_, EVP_PKEY_,
EVP_MD_, and EVP_CIPHER_ prefixes are renamed.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15405)
2021-05-21 22:58:08 +08:00
|
|
|
if (EVP_PKEY_get_base_id(pkey) != type) {
|
2020-07-28 00:40:05 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_EXPECTING_A_ECX_KEY);
|
|
|
|
return NULL;
|
|
|
|
}
|
2021-02-25 00:38:28 +08:00
|
|
|
return evp_pkey_get_legacy((EVP_PKEY *)pkey);
|
2020-07-28 00:40:05 +08:00
|
|
|
}
|
|
|
|
|
2020-09-25 10:12:22 +08:00
|
|
|
static ECX_KEY *evp_pkey_get1_ECX_KEY(EVP_PKEY *pkey, int type)
|
2020-07-28 00:40:05 +08:00
|
|
|
{
|
2021-03-02 23:52:00 +08:00
|
|
|
ECX_KEY *ret = (ECX_KEY *)evp_pkey_get0_ECX_KEY(pkey, type);
|
2021-03-19 07:43:24 +08:00
|
|
|
|
|
|
|
if (ret != NULL && !ossl_ecx_key_up_ref(ret))
|
|
|
|
ret = NULL;
|
2020-07-28 00:40:05 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
# define IMPLEMENT_ECX_VARIANT(NAME) \
|
2021-02-18 18:27:26 +08:00
|
|
|
ECX_KEY *ossl_evp_pkey_get1_##NAME(EVP_PKEY *pkey) \
|
2020-07-28 00:40:05 +08:00
|
|
|
{ \
|
2020-09-25 10:12:22 +08:00
|
|
|
return evp_pkey_get1_ECX_KEY(pkey, EVP_PKEY_##NAME); \
|
2020-07-28 00:40:05 +08:00
|
|
|
}
|
|
|
|
IMPLEMENT_ECX_VARIANT(X25519)
|
|
|
|
IMPLEMENT_ECX_VARIANT(X448)
|
|
|
|
IMPLEMENT_ECX_VARIANT(ED25519)
|
|
|
|
IMPLEMENT_ECX_VARIANT(ED448)
|
|
|
|
|
2023-04-17 16:20:31 +08:00
|
|
|
# endif /* OPENSSL_NO_ECX */
|
2002-02-14 02:21:51 +08:00
|
|
|
|
2020-10-14 21:19:38 +08:00
|
|
|
# if !defined(OPENSSL_NO_DH) && !defined(OPENSSL_NO_DEPRECATED_3_0)
|
1999-11-22 06:28:31 +08:00
|
|
|
|
2021-04-15 16:25:17 +08:00
|
|
|
int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *dhkey)
|
1999-11-22 06:28:31 +08:00
|
|
|
{
|
2021-04-15 16:25:17 +08:00
|
|
|
int ret, type;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ossl_dh_is_named_safe_prime_group() returns 1 for named safe prime groups
|
|
|
|
* related to ffdhe and modp (which cache q = (p - 1) / 2),
|
|
|
|
* and returns 0 for all other dh parameter generation types including
|
|
|
|
* RFC5114 named groups.
|
|
|
|
*
|
|
|
|
* The EVP_PKEY_DH type is used for dh parameter generation types:
|
|
|
|
* - named safe prime groups related to ffdhe and modp
|
|
|
|
* - safe prime generator
|
|
|
|
*
|
|
|
|
* The type EVP_PKEY_DHX is used for dh parameter generation types
|
|
|
|
* - fips186-4 and fips186-2
|
|
|
|
* - rfc5114 named groups.
|
|
|
|
*
|
|
|
|
* The EVP_PKEY_DH type is used to save PKCS#3 data than can be stored
|
|
|
|
* without a q value.
|
|
|
|
* The EVP_PKEY_DHX type is used to save X9.42 data that requires the
|
|
|
|
* q value to be stored.
|
|
|
|
*/
|
|
|
|
if (ossl_dh_is_named_safe_prime_group(dhkey))
|
|
|
|
type = EVP_PKEY_DH;
|
|
|
|
else
|
|
|
|
type = DH_get0_q(dhkey) == NULL ? EVP_PKEY_DH : EVP_PKEY_DHX;
|
|
|
|
|
|
|
|
ret = EVP_PKEY_assign(pkey, type, dhkey);
|
2019-12-09 19:51:48 +08:00
|
|
|
|
2001-08-26 01:28:23 +08:00
|
|
|
if (ret)
|
2021-04-15 16:25:17 +08:00
|
|
|
DH_up_ref(dhkey);
|
1999-11-24 02:50:28 +08:00
|
|
|
return ret;
|
1999-11-22 06:28:31 +08:00
|
|
|
}
|
|
|
|
|
2021-03-02 23:52:00 +08:00
|
|
|
DH *evp_pkey_get0_DH_int(const EVP_PKEY *pkey)
|
1999-10-25 10:00:09 +08:00
|
|
|
{
|
2012-04-19 01:03:29 +08:00
|
|
|
if (pkey->type != EVP_PKEY_DH && pkey->type != EVP_PKEY_DHX) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_EXPECTING_A_DH_KEY);
|
1999-10-25 10:00:09 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
2021-02-25 00:38:28 +08:00
|
|
|
return evp_pkey_get_legacy((EVP_PKEY *)pkey);
|
1999-10-25 10:00:09 +08:00
|
|
|
}
|
2015-12-14 01:57:01 +08:00
|
|
|
|
2021-03-02 23:52:00 +08:00
|
|
|
const DH *EVP_PKEY_get0_DH(const EVP_PKEY *pkey)
|
|
|
|
{
|
|
|
|
return evp_pkey_get0_DH_int(pkey);
|
|
|
|
}
|
|
|
|
|
2015-12-14 01:57:01 +08:00
|
|
|
DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey)
|
|
|
|
{
|
2021-03-02 23:52:00 +08:00
|
|
|
DH *ret = evp_pkey_get0_DH_int(pkey);
|
|
|
|
|
2015-12-14 01:57:01 +08:00
|
|
|
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)
|
1998-12-21 18:52:47 +08:00
|
|
|
{
|
2006-06-05 19:52:46 +08:00
|
|
|
int ret;
|
2006-03-21 01:56:05 +08:00
|
|
|
const EVP_PKEY_ASN1_METHOD *ameth;
|
2006-06-05 19:52:46 +08:00
|
|
|
ENGINE *e;
|
|
|
|
ameth = EVP_PKEY_asn1_find(&e, type);
|
2006-03-21 01:56:05 +08:00
|
|
|
if (ameth)
|
2006-06-05 19:52:46 +08:00
|
|
|
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
|
2006-06-05 19:52:46 +08:00
|
|
|
return ret;
|
1998-12-21 18:52:47 +08:00
|
|
|
}
|
|
|
|
|
Rename all getters to use get/get0 in name
For functions that exist in 1.1.1 provide a simple aliases via #define.
Fixes #15236
Functions with OSSL_DECODER_, OSSL_ENCODER_, OSSL_STORE_LOADER_,
EVP_KEYEXCH_, EVP_KEM_, EVP_ASYM_CIPHER_, EVP_SIGNATURE_,
EVP_KEYMGMT_, EVP_RAND_, EVP_MAC_, EVP_KDF_, EVP_PKEY_,
EVP_MD_, and EVP_CIPHER_ prefixes are renamed.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15405)
2021-05-21 22:58:08 +08:00
|
|
|
int EVP_PKEY_get_id(const EVP_PKEY *pkey)
|
2006-05-12 05:33:00 +08:00
|
|
|
{
|
|
|
|
return pkey->type;
|
|
|
|
}
|
|
|
|
|
Rename all getters to use get/get0 in name
For functions that exist in 1.1.1 provide a simple aliases via #define.
Fixes #15236
Functions with OSSL_DECODER_, OSSL_ENCODER_, OSSL_STORE_LOADER_,
EVP_KEYEXCH_, EVP_KEM_, EVP_ASYM_CIPHER_, EVP_SIGNATURE_,
EVP_KEYMGMT_, EVP_RAND_, EVP_MAC_, EVP_KDF_, EVP_PKEY_,
EVP_MD_, and EVP_CIPHER_ prefixes are renamed.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15405)
2021-05-21 22:58:08 +08:00
|
|
|
int EVP_PKEY_get_base_id(const EVP_PKEY *pkey)
|
2006-05-12 05:33:00 +08:00
|
|
|
{
|
|
|
|
return EVP_PKEY_type(pkey->type);
|
|
|
|
}
|
|
|
|
|
2021-01-27 18:07:38 +08:00
|
|
|
/*
|
|
|
|
* These hard coded cases are pure hackery to get around the fact
|
|
|
|
* that names in crypto/objects/objects.txt are a mess. There is
|
|
|
|
* no "EC", and "RSA" leads to the NID for 2.5.8.1.1, an OID that's
|
|
|
|
* fallen out in favor of { pkcs-1 1 }, i.e. 1.2.840.113549.1.1.1,
|
|
|
|
* the NID of which is used for EVP_PKEY_RSA. Strangely enough,
|
|
|
|
* "DSA" is accurate... but still, better be safe and hard-code
|
|
|
|
* names that we know.
|
|
|
|
* On a similar topic, EVP_PKEY_type(EVP_PKEY_SM2) will result in
|
|
|
|
* EVP_PKEY_EC, because of aliasing.
|
2021-03-16 00:10:26 +08:00
|
|
|
* This should be cleaned away along with all other #legacy support.
|
2021-01-27 18:07:38 +08:00
|
|
|
*/
|
|
|
|
static const OSSL_ITEM standard_name2type[] = {
|
|
|
|
{ EVP_PKEY_RSA, "RSA" },
|
|
|
|
{ EVP_PKEY_RSA_PSS, "RSA-PSS" },
|
|
|
|
{ EVP_PKEY_EC, "EC" },
|
|
|
|
{ EVP_PKEY_ED25519, "ED25519" },
|
|
|
|
{ EVP_PKEY_ED448, "ED448" },
|
|
|
|
{ EVP_PKEY_X25519, "X25519" },
|
|
|
|
{ EVP_PKEY_X448, "X448" },
|
|
|
|
{ EVP_PKEY_SM2, "SM2" },
|
|
|
|
{ EVP_PKEY_DH, "DH" },
|
|
|
|
{ EVP_PKEY_DHX, "X9.42 DH" },
|
|
|
|
{ EVP_PKEY_DHX, "DHX" },
|
|
|
|
{ EVP_PKEY_DSA, "DSA" },
|
|
|
|
};
|
|
|
|
|
2020-09-02 15:30:42 +08:00
|
|
|
int evp_pkey_name2type(const char *name)
|
|
|
|
{
|
2021-01-27 18:07:38 +08:00
|
|
|
int type;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < OSSL_NELEM(standard_name2type); i++) {
|
2022-04-12 18:30:08 +08:00
|
|
|
if (OPENSSL_strcasecmp(name, standard_name2type[i].ptr) == 0)
|
2021-01-27 18:07:38 +08:00
|
|
|
return (int)standard_name2type[i].id;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((type = EVP_PKEY_type(OBJ_sn2nid(name))) != NID_undef)
|
|
|
|
return type;
|
|
|
|
return EVP_PKEY_type(OBJ_ln2nid(name));
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *evp_pkey_type2name(int type)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < OSSL_NELEM(standard_name2type); i++) {
|
|
|
|
if (type == (int)standard_name2type[i].id)
|
|
|
|
return standard_name2type[i].ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return OBJ_nid2sn(type);
|
2020-09-02 15:30:42 +08:00
|
|
|
}
|
|
|
|
|
2020-03-17 01:55:32 +08:00
|
|
|
int EVP_PKEY_is_a(const EVP_PKEY *pkey, const char *name)
|
|
|
|
{
|
2022-07-14 13:17:41 +08:00
|
|
|
if (pkey == NULL)
|
|
|
|
return 0;
|
|
|
|
if (pkey->keymgmt == NULL)
|
|
|
|
return pkey->type == evp_pkey_name2type(name);
|
2020-03-17 01:55:32 +08:00
|
|
|
return EVP_KEYMGMT_is_a(pkey->keymgmt, name);
|
|
|
|
}
|
|
|
|
|
2021-04-14 18:42:30 +08:00
|
|
|
int EVP_PKEY_type_names_do_all(const EVP_PKEY *pkey,
|
|
|
|
void (*fn)(const char *name, void *data),
|
|
|
|
void *data)
|
2020-09-14 17:21:37 +08:00
|
|
|
{
|
|
|
|
if (!evp_pkey_is_typed(pkey))
|
2021-02-20 01:03:43 +08:00
|
|
|
return 0;
|
2020-09-14 17:21:37 +08:00
|
|
|
|
|
|
|
if (!evp_pkey_is_provided(pkey)) {
|
Rename all getters to use get/get0 in name
For functions that exist in 1.1.1 provide a simple aliases via #define.
Fixes #15236
Functions with OSSL_DECODER_, OSSL_ENCODER_, OSSL_STORE_LOADER_,
EVP_KEYEXCH_, EVP_KEM_, EVP_ASYM_CIPHER_, EVP_SIGNATURE_,
EVP_KEYMGMT_, EVP_RAND_, EVP_MAC_, EVP_KDF_, EVP_PKEY_,
EVP_MD_, and EVP_CIPHER_ prefixes are renamed.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15405)
2021-05-21 22:58:08 +08:00
|
|
|
const char *name = OBJ_nid2sn(EVP_PKEY_get_id(pkey));
|
2020-09-14 17:21:37 +08:00
|
|
|
|
|
|
|
fn(name, data);
|
2021-02-20 01:03:43 +08:00
|
|
|
return 1;
|
2020-09-14 17:21:37 +08:00
|
|
|
}
|
2021-02-20 01:03:43 +08:00
|
|
|
return EVP_KEYMGMT_names_do_all(pkey->keymgmt, fn, data);
|
2020-09-14 17:21:37 +08:00
|
|
|
}
|
|
|
|
|
2020-03-17 01:55:32 +08:00
|
|
|
int EVP_PKEY_can_sign(const EVP_PKEY *pkey)
|
|
|
|
{
|
|
|
|
if (pkey->keymgmt == NULL) {
|
Rename all getters to use get/get0 in name
For functions that exist in 1.1.1 provide a simple aliases via #define.
Fixes #15236
Functions with OSSL_DECODER_, OSSL_ENCODER_, OSSL_STORE_LOADER_,
EVP_KEYEXCH_, EVP_KEM_, EVP_ASYM_CIPHER_, EVP_SIGNATURE_,
EVP_KEYMGMT_, EVP_RAND_, EVP_MAC_, EVP_KDF_, EVP_PKEY_,
EVP_MD_, and EVP_CIPHER_ prefixes are renamed.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15405)
2021-05-21 22:58:08 +08:00
|
|
|
switch (EVP_PKEY_get_base_id(pkey)) {
|
2020-03-17 01:55:32 +08:00
|
|
|
case EVP_PKEY_RSA:
|
2023-08-23 21:08:51 +08:00
|
|
|
case EVP_PKEY_RSA_PSS:
|
2020-03-17 01:55:32 +08:00
|
|
|
return 1;
|
2021-03-17 01:29:19 +08:00
|
|
|
# ifndef OPENSSL_NO_DSA
|
2020-03-17 01:55:32 +08:00
|
|
|
case EVP_PKEY_DSA:
|
|
|
|
return 1;
|
2021-03-17 01:29:19 +08:00
|
|
|
# endif
|
|
|
|
# ifndef OPENSSL_NO_EC
|
2020-03-17 01:55:32 +08:00
|
|
|
case EVP_PKEY_ED25519:
|
|
|
|
case EVP_PKEY_ED448:
|
|
|
|
return 1;
|
|
|
|
case EVP_PKEY_EC: /* Including SM2 */
|
|
|
|
return EC_KEY_can_sign(pkey->pkey.ec);
|
2021-03-17 01:29:19 +08:00
|
|
|
# endif
|
2020-03-17 01:55:32 +08:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
Rename all getters to use get/get0 in name
For functions that exist in 1.1.1 provide a simple aliases via #define.
Fixes #15236
Functions with OSSL_DECODER_, OSSL_ENCODER_, OSSL_STORE_LOADER_,
EVP_KEYEXCH_, EVP_KEM_, EVP_ASYM_CIPHER_, EVP_SIGNATURE_,
EVP_KEYMGMT_, EVP_RAND_, EVP_MAC_, EVP_KDF_, EVP_PKEY_,
EVP_MD_, and EVP_CIPHER_ prefixes are renamed.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15405)
2021-05-21 22:58:08 +08:00
|
|
|
const OSSL_PROVIDER *prov = EVP_KEYMGMT_get0_provider(pkey->keymgmt);
|
2020-10-15 17:55:50 +08:00
|
|
|
OSSL_LIB_CTX *libctx = ossl_provider_libctx(prov);
|
2020-03-17 01:55:32 +08:00
|
|
|
const char *supported_sig =
|
|
|
|
pkey->keymgmt->query_operation_name != NULL
|
|
|
|
? pkey->keymgmt->query_operation_name(OSSL_OP_SIGNATURE)
|
Rename all getters to use get/get0 in name
For functions that exist in 1.1.1 provide a simple aliases via #define.
Fixes #15236
Functions with OSSL_DECODER_, OSSL_ENCODER_, OSSL_STORE_LOADER_,
EVP_KEYEXCH_, EVP_KEM_, EVP_ASYM_CIPHER_, EVP_SIGNATURE_,
EVP_KEYMGMT_, EVP_RAND_, EVP_MAC_, EVP_KDF_, EVP_PKEY_,
EVP_MD_, and EVP_CIPHER_ prefixes are renamed.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15405)
2021-05-21 22:58:08 +08:00
|
|
|
: EVP_KEYMGMT_get0_name(pkey->keymgmt);
|
2020-03-17 01:55:32 +08:00
|
|
|
EVP_SIGNATURE *signature = NULL;
|
|
|
|
|
|
|
|
signature = EVP_SIGNATURE_fetch(libctx, supported_sig, NULL);
|
|
|
|
if (signature != NULL) {
|
|
|
|
EVP_SIGNATURE_free(signature);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
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) {
|
2022-06-08 00:49:29 +08:00
|
|
|
BIO *prefbio = BIO_new(BIO_f_prefix());
|
|
|
|
|
|
|
|
if (prefbio == NULL)
|
2019-11-28 01:35:48 +08:00
|
|
|
return 0;
|
2022-06-08 00:49:29 +08:00
|
|
|
*out = BIO_push(prefbio, *out);
|
2019-11-28 01:35:48 +08:00
|
|
|
*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,
|
|
|
|
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;
|
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,
|
2020-09-14 16:42:05 +08:00
|
|
|
int selection /* For provided encoding */,
|
2020-08-17 03:25:08 +08:00
|
|
|
const char *propquery /* For provided encoding */,
|
2019-11-28 01:35:48 +08:00
|
|
|
int (*legacy_print)(BIO *out, const EVP_PKEY *pkey,
|
|
|
|
int indent, ASN1_PCTX *pctx),
|
|
|
|
ASN1_PCTX *legacy_pctx /* For legacy print */)
|
2006-03-22 21:09:35 +08:00
|
|
|
{
|
2019-11-28 01:35:48 +08:00
|
|
|
int pop_f_prefix;
|
|
|
|
long saved_indent;
|
2020-08-17 03:25:08 +08:00
|
|
|
OSSL_ENCODER_CTX *ctx = NULL;
|
2019-11-28 01:35:48 +08:00
|
|
|
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
|
|
|
|
2021-02-11 23:57:37 +08:00
|
|
|
ctx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection, "TEXT", NULL,
|
|
|
|
propquery);
|
2020-09-14 16:42:05 +08:00
|
|
|
if (OSSL_ENCODER_CTX_get_num_encoders(ctx) != 0)
|
2020-08-17 03:25:08 +08:00
|
|
|
ret = OSSL_ENCODER_to_bio(ctx, out);
|
|
|
|
OSSL_ENCODER_CTX_free(ctx);
|
2019-11-18 08:47:32 +08:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2020-11-27 15:03:23 +08:00
|
|
|
return print_pkey(pkey, out, indent, EVP_PKEY_PUBLIC_KEY, NULL,
|
2019-11-28 01:35:48 +08:00
|
|
|
(pkey->ameth != NULL ? pkey->ameth->pub_print : NULL),
|
|
|
|
pctx);
|
2006-03-22 21:09:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey,
|
|
|
|
int indent, ASN1_PCTX *pctx)
|
|
|
|
{
|
Restore the meaning of EVP_PKEY_print_private()
With pre-3.0 OpenSSL, EVP_PKEY_print_private() calls the EVP_PKEY_ASN1_METHOD
function "priv_print", effectively asking the backend to print whatever it
regards as private key components.
In all backends that were built into libcrypto, this function printed what
was included in the private key structure, which usually includes the
public key components as well.
With OpenSSL 3.0, some of the corresponding key2text encoders got a
slightly different behavior, where the presence of the selector
OSSL_KEYMGMT_SELECT_PRIVATE_KEY without the presence of the selector
OSSL_KEYMGMT_SELECT_PUBLIC_KEY would only get what would intuitively be
regarded as private key components printed. This isn't entirely consistent,
though, as the RSA key2text encoder will still print the public key
components regardless.
To compensate for the changed backend behavior, EVP_PKEY_print_private()
was made to ask the encoder to print the keypair rather than just the
private key, thereby moving the backend semantics to the application API.
Unfortunately, this causes confusion for providers where the key2text
encoder really should print the private key only.
This change restores the built-in 1.1.1 backend behavior in the encoders
that OpenSSL provides, and renders EVP_PKEY_print_private() more true to its
documented behavior, leaving it to the backend to decide what it regards as
"private key components".
Fixes #22233
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/22237)
2023-10-02 15:12:12 +08:00
|
|
|
return print_pkey(pkey, out, indent, EVP_PKEY_PRIVATE_KEY, NULL,
|
2019-11-28 01:35:48 +08:00
|
|
|
(pkey->ameth != NULL ? pkey->ameth->priv_print : NULL),
|
|
|
|
pctx);
|
2006-03-22 21:09:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey,
|
|
|
|
int indent, ASN1_PCTX *pctx)
|
|
|
|
{
|
2020-11-27 15:03:23 +08:00
|
|
|
return print_pkey(pkey, out, indent, EVP_PKEY_KEY_PARAMETERS, NULL,
|
2019-11-28 01:35:48 +08:00
|
|
|
(pkey->ameth != NULL ? pkey->ameth->param_print : NULL),
|
|
|
|
pctx);
|
2006-03-22 21:09:35 +08:00
|
|
|
}
|
2006-05-08 01:09:39 +08:00
|
|
|
|
2021-03-17 01:29:19 +08:00
|
|
|
# ifndef OPENSSL_NO_STDIO
|
|
|
|
int EVP_PKEY_print_public_fp(FILE *fp, const EVP_PKEY *pkey,
|
|
|
|
int indent, ASN1_PCTX *pctx)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
|
|
|
|
|
|
|
|
if (b == NULL)
|
|
|
|
return 0;
|
|
|
|
ret = EVP_PKEY_print_public(b, pkey, indent, pctx);
|
|
|
|
BIO_free(b);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_print_private_fp(FILE *fp, const EVP_PKEY *pkey,
|
|
|
|
int indent, ASN1_PCTX *pctx)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
|
|
|
|
|
|
|
|
if (b == NULL)
|
|
|
|
return 0;
|
|
|
|
ret = EVP_PKEY_print_private(b, pkey, indent, pctx);
|
|
|
|
BIO_free(b);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_print_params_fp(FILE *fp, const EVP_PKEY *pkey,
|
|
|
|
int indent, ASN1_PCTX *pctx)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
BIO *b = BIO_new_fp(fp, BIO_NOCLOSE);
|
|
|
|
|
|
|
|
if (b == NULL)
|
|
|
|
return 0;
|
|
|
|
ret = EVP_PKEY_print_params(b, pkey, indent, pctx);
|
|
|
|
BIO_free(b);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
# endif
|
|
|
|
|
2021-01-19 00:50:07 +08:00
|
|
|
static void mdname2nid(const char *mdname, void *data)
|
2021-01-19 19:36:24 +08:00
|
|
|
{
|
|
|
|
int *nid = (int *)data;
|
|
|
|
|
|
|
|
if (*nid != NID_undef)
|
|
|
|
return;
|
|
|
|
|
|
|
|
*nid = OBJ_sn2nid(mdname);
|
|
|
|
if (*nid == NID_undef)
|
|
|
|
*nid = OBJ_ln2nid(mdname);
|
|
|
|
}
|
|
|
|
|
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 rv = EVP_PKEY_get_default_digest_name(pkey, mdname,
|
|
|
|
sizeof(mdname));
|
|
|
|
|
2020-08-05 16:40:01 +08:00
|
|
|
if (rv > 0) {
|
2021-01-19 19:36:24 +08:00
|
|
|
int mdnum;
|
|
|
|
OSSL_LIB_CTX *libctx = ossl_provider_libctx(pkey->keymgmt->prov);
|
|
|
|
/* Make sure the MD is in the namemap if available */
|
2021-05-29 15:16:22 +08:00
|
|
|
EVP_MD *md;
|
|
|
|
OSSL_NAMEMAP *namemap;
|
2021-01-19 19:36:24 +08:00
|
|
|
int nid = NID_undef;
|
|
|
|
|
2021-05-29 15:16:22 +08:00
|
|
|
(void)ERR_set_mark();
|
|
|
|
md = EVP_MD_fetch(libctx, mdname, NULL);
|
|
|
|
(void)ERR_pop_to_mark();
|
|
|
|
namemap = ossl_namemap_stored(libctx);
|
|
|
|
|
2021-01-19 19:36:24 +08:00
|
|
|
/*
|
|
|
|
* The only reason to fetch the MD was to make sure it is in the
|
|
|
|
* namemap. We can immediately free it.
|
|
|
|
*/
|
|
|
|
EVP_MD_free(md);
|
|
|
|
mdnum = ossl_namemap_name2num(namemap, mdname);
|
|
|
|
if (mdnum == 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We have the namemap number - now we need to find the
|
|
|
|
* associated nid
|
|
|
|
*/
|
2021-02-20 01:03:43 +08:00
|
|
|
if (!ossl_namemap_doall_names(namemap, mdnum, mdname2nid, &nid))
|
|
|
|
return 0;
|
2020-08-05 16:40:01 +08:00
|
|
|
*(int *)arg2 = nid;
|
|
|
|
}
|
|
|
|
return rv;
|
2020-01-13 15:49:44 +08:00
|
|
|
}
|
|
|
|
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)
|
2006-05-08 01:09:39 +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)
|
2006-05-08 01:09:39 +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)
|
|
|
|
{
|
2023-02-15 10:43:01 +08:00
|
|
|
if (pkey == NULL)
|
|
|
|
return 0;
|
2016-08-11 05:30:43 +08:00
|
|
|
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)
|
|
|
|
{
|
2020-04-20 15:14:59 +08:00
|
|
|
if (pkey->ameth == NULL)
|
|
|
|
return evp_keymgmt_util_get_deflt_digest_name(pkey->keymgmt,
|
|
|
|
pkey->keydata,
|
|
|
|
mdname, mdname_sz);
|
2020-01-13 15:49:44 +08:00
|
|
|
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-04 13:32:24 +08:00
|
|
|
int EVP_PKEY_get_group_name(const EVP_PKEY *pkey, char *gname, size_t gname_sz,
|
|
|
|
size_t *gname_len)
|
|
|
|
{
|
2021-01-21 06:10:48 +08:00
|
|
|
return EVP_PKEY_get_utf8_string_param(pkey, OSSL_PKEY_PARAM_GROUP_NAME,
|
|
|
|
gname, gname_sz, gname_len);
|
2020-12-04 13:32:24 +08:00
|
|
|
}
|
|
|
|
|
2021-05-07 23:44:26 +08:00
|
|
|
int EVP_PKEY_digestsign_supports_digest(EVP_PKEY *pkey, OSSL_LIB_CTX *libctx,
|
|
|
|
const char *name, const char *propq)
|
2018-10-23 01:49:54 +08:00
|
|
|
{
|
2021-05-07 23:44:26 +08:00
|
|
|
int rv;
|
|
|
|
EVP_MD_CTX *ctx = NULL;
|
2018-10-23 01:49:54 +08:00
|
|
|
|
2021-05-07 23:44:26 +08:00
|
|
|
if ((ctx = EVP_MD_CTX_new()) == NULL)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
ERR_set_mark();
|
|
|
|
rv = EVP_DigestSignInit_ex(ctx, NULL, name, libctx,
|
|
|
|
propq, pkey, NULL);
|
|
|
|
ERR_pop_to_mark();
|
|
|
|
|
|
|
|
EVP_MD_CTX_free(ctx);
|
2018-10-23 01:49:54 +08:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2020-10-09 21:19:42 +08:00
|
|
|
int EVP_PKEY_set1_encoded_public_key(EVP_PKEY *pkey, const unsigned char *pub,
|
|
|
|
size_t publen)
|
2016-08-11 05:30:43 +08:00
|
|
|
{
|
2023-02-15 10:43:01 +08:00
|
|
|
if (pkey == NULL)
|
|
|
|
return 0;
|
|
|
|
if (evp_pkey_is_provided(pkey))
|
2021-02-03 23:48:21 +08:00
|
|
|
return
|
|
|
|
EVP_PKEY_set_octet_string_param(pkey,
|
|
|
|
OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
|
|
|
|
(unsigned char *)pub, publen);
|
2020-05-20 23:20:27 +08:00
|
|
|
|
2020-10-09 21:19:42 +08:00
|
|
|
if (publen > INT_MAX)
|
2016-08-11 05:30:43 +08:00
|
|
|
return 0;
|
2020-10-09 21:19:42 +08:00
|
|
|
/* Historically this function was EVP_PKEY_set1_tls_encodedpoint */
|
|
|
|
if (evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_SET1_TLS_ENCPT, publen,
|
|
|
|
(void *)pub) <= 0)
|
2016-08-11 05:30:43 +08:00
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-10-09 21:19:42 +08:00
|
|
|
size_t EVP_PKEY_get1_encoded_public_key(EVP_PKEY *pkey, unsigned char **ppub)
|
2016-08-11 05:30:43 +08:00
|
|
|
{
|
|
|
|
int rv;
|
2020-05-20 23:20:27 +08:00
|
|
|
|
2023-02-15 10:43:01 +08:00
|
|
|
if (pkey == NULL)
|
|
|
|
return 0;
|
|
|
|
if (evp_pkey_is_provided(pkey)) {
|
2021-02-03 23:48:21 +08:00
|
|
|
size_t return_size = OSSL_PARAM_UNMODIFIED;
|
2022-07-07 13:03:08 +08:00
|
|
|
unsigned char *buf;
|
2020-05-20 23:20:27 +08:00
|
|
|
|
2021-02-03 23:48:21 +08:00
|
|
|
/*
|
|
|
|
* We know that this is going to fail, but it will give us a size
|
|
|
|
* to allocate.
|
|
|
|
*/
|
|
|
|
EVP_PKEY_get_octet_string_param(pkey,
|
|
|
|
OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
|
|
|
|
NULL, 0, &return_size);
|
|
|
|
if (return_size == OSSL_PARAM_UNMODIFIED)
|
2020-05-20 23:20:27 +08:00
|
|
|
return 0;
|
|
|
|
|
2022-07-07 13:03:08 +08:00
|
|
|
*ppub = NULL;
|
|
|
|
buf = OPENSSL_malloc(return_size);
|
|
|
|
if (buf == NULL)
|
2020-05-20 23:20:27 +08:00
|
|
|
return 0;
|
|
|
|
|
2021-02-03 23:48:21 +08:00
|
|
|
if (!EVP_PKEY_get_octet_string_param(pkey,
|
|
|
|
OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY,
|
2022-07-07 13:03:08 +08:00
|
|
|
buf, return_size, NULL)) {
|
|
|
|
OPENSSL_free(buf);
|
2020-05-20 23:20:27 +08:00
|
|
|
return 0;
|
2022-07-07 13:03:08 +08:00
|
|
|
}
|
|
|
|
*ppub = buf;
|
2021-02-03 23:48:21 +08:00
|
|
|
return return_size;
|
2020-05-20 23:20:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-10-09 21:19:42 +08:00
|
|
|
rv = evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_GET1_TLS_ENCPT, 0, ppub);
|
2016-08-11 05:30:43 +08:00
|
|
|
if (rv <= 0)
|
|
|
|
return 0;
|
|
|
|
return rv;
|
2006-05-08 01:09:39 +08:00
|
|
|
}
|
2020-01-12 09:32:12 +08:00
|
|
|
|
2020-04-14 04:34:56 +08:00
|
|
|
#endif /* FIPS_MODULE */
|
2020-01-12 09:32:12 +08:00
|
|
|
|
2020-04-14 04:34:56 +08:00
|
|
|
/*- All methods below can also be used in FIPS_MODULE */
|
2020-01-12 09:32:12 +08:00
|
|
|
|
|
|
|
EVP_PKEY *EVP_PKEY_new(void)
|
|
|
|
{
|
|
|
|
EVP_PKEY *ret = OPENSSL_zalloc(sizeof(*ret));
|
|
|
|
|
2022-09-29 19:57:34 +08:00
|
|
|
if (ret == NULL)
|
2020-01-12 09:32:12 +08:00
|
|
|
return NULL;
|
2020-08-27 16:07:09 +08:00
|
|
|
|
2021-02-25 00:38:28 +08:00
|
|
|
ret->type = EVP_PKEY_NONE;
|
|
|
|
ret->save_type = EVP_PKEY_NONE;
|
2023-06-22 07:48:49 +08:00
|
|
|
|
|
|
|
if (!CRYPTO_NEW_REF(&ret->references, 1))
|
|
|
|
goto err;
|
2020-08-27 16:07:09 +08:00
|
|
|
|
2020-11-11 12:23:11 +08:00
|
|
|
ret->lock = CRYPTO_THREAD_lock_new();
|
|
|
|
if (ret->lock == NULL) {
|
2022-09-29 19:57:34 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, ERR_R_CRYPTO_LIB);
|
2020-11-11 12:23:11 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2021-04-13 23:31:08 +08:00
|
|
|
ret->save_parameters = 1;
|
2020-04-07 08:18:09 +08:00
|
|
|
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_EVP_PKEY, ret, &ret->ex_data)) {
|
2022-09-29 19:57:34 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, ERR_R_CRYPTO_LIB);
|
2020-04-07 08:18:09 +08:00
|
|
|
goto err;
|
2020-01-12 09:32:12 +08:00
|
|
|
}
|
2020-04-07 08:18:09 +08:00
|
|
|
#endif
|
2020-01-12 09:32:12 +08:00
|
|
|
return ret;
|
2020-04-07 08:18:09 +08:00
|
|
|
|
|
|
|
err:
|
2023-06-22 07:48:49 +08:00
|
|
|
CRYPTO_FREE_REF(&ret->references);
|
2020-04-07 08:18:09 +08:00
|
|
|
CRYPTO_THREAD_lock_free(ret->lock);
|
|
|
|
OPENSSL_free(ret);
|
|
|
|
return NULL;
|
2020-01-12 09:32:12 +08:00
|
|
|
}
|
|
|
|
|
2020-03-21 13:14:25 +08:00
|
|
|
/*
|
|
|
|
* Setup a public key management method.
|
|
|
|
*
|
|
|
|
* For legacy keys, either |type| or |str| is expected to have the type
|
|
|
|
* information. In this case, the setup consists of finding an ASN1 method
|
|
|
|
* and potentially an ENGINE, and setting those fields in |pkey|.
|
|
|
|
*
|
|
|
|
* For provider side keys, |keymgmt| is expected to be non-NULL. In this
|
|
|
|
* case, the setup consists of setting the |keymgmt| field in |pkey|.
|
|
|
|
*
|
|
|
|
* If pkey is NULL just return 1 or 0 if the key management method exists.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str,
|
|
|
|
int len, EVP_KEYMGMT *keymgmt)
|
|
|
|
{
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2020-03-21 13:14:25 +08:00
|
|
|
const EVP_PKEY_ASN1_METHOD *ameth = NULL;
|
|
|
|
ENGINE **eptr = (e == NULL) ? &e : NULL;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The setups can't set both legacy and provider side methods.
|
|
|
|
* It is forbidden
|
|
|
|
*/
|
|
|
|
if (!ossl_assert(type == EVP_PKEY_NONE || keymgmt == NULL)
|
|
|
|
|| !ossl_assert(e == NULL || keymgmt == NULL)) {
|
|
|
|
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pkey != NULL) {
|
|
|
|
int free_it = 0;
|
|
|
|
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2020-03-21 13:14:25 +08:00
|
|
|
free_it = free_it || pkey->pkey.ptr != NULL;
|
|
|
|
#endif
|
|
|
|
free_it = free_it || pkey->keydata != NULL;
|
|
|
|
if (free_it)
|
|
|
|
evp_pkey_free_it(pkey);
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2020-03-21 13:14:25 +08:00
|
|
|
/*
|
|
|
|
* If key type matches and a method exists then this lookup has
|
|
|
|
* succeeded once so just indicate success.
|
|
|
|
*/
|
|
|
|
if (pkey->type != EVP_PKEY_NONE
|
|
|
|
&& type == pkey->save_type
|
|
|
|
&& pkey->ameth != NULL)
|
|
|
|
return 1;
|
|
|
|
# ifndef OPENSSL_NO_ENGINE
|
|
|
|
/* If we have ENGINEs release them */
|
|
|
|
ENGINE_finish(pkey->engine);
|
|
|
|
pkey->engine = NULL;
|
|
|
|
ENGINE_finish(pkey->pmeth_engine);
|
|
|
|
pkey->pmeth_engine = NULL;
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
}
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2020-03-21 13:14:25 +08:00
|
|
|
if (str != NULL)
|
|
|
|
ameth = EVP_PKEY_asn1_find_str(eptr, str, len);
|
|
|
|
else if (type != EVP_PKEY_NONE)
|
|
|
|
ameth = EVP_PKEY_asn1_find(eptr, type);
|
|
|
|
# ifndef OPENSSL_NO_ENGINE
|
|
|
|
if (pkey == NULL && eptr != NULL)
|
|
|
|
ENGINE_finish(e);
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
int check = 1;
|
|
|
|
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2020-03-21 13:14:25 +08:00
|
|
|
check = check && ameth == NULL;
|
|
|
|
#endif
|
|
|
|
check = check && keymgmt == NULL;
|
|
|
|
if (check) {
|
2020-11-04 19:23:19 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_ALGORITHM);
|
2020-03-21 13:14:25 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (pkey != NULL) {
|
|
|
|
if (keymgmt != NULL && !EVP_KEYMGMT_up_ref(keymgmt)) {
|
|
|
|
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
pkey->keymgmt = keymgmt;
|
|
|
|
|
|
|
|
pkey->save_type = type;
|
|
|
|
pkey->type = type;
|
|
|
|
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2020-03-21 13:14:25 +08:00
|
|
|
/*
|
|
|
|
* If the internal "origin" key is provider side, don't save |ameth|.
|
|
|
|
* The main reason is that |ameth| is one factor to detect that the
|
|
|
|
* internal "origin" key is a legacy one.
|
|
|
|
*/
|
|
|
|
if (keymgmt == NULL)
|
|
|
|
pkey->ameth = ameth;
|
|
|
|
|
|
|
|
/*
|
Re-introduce legacy EVP_PKEY types for provided keys
EVP_PKEYs with provider side internal keys got the key type
EVP_PKEY_NONE. This turned out to be too disruptive, so we try
instead to find a matching EVP_PKEY_ASN1_METHOD and use whatever
EVP_PKEY type it uses.
To make internal coding easier, we introduce a few internal macros to
distinguish what can be expected from a EVP_PKEY:
- evp_pkey_is_blank(), to detect an unassigned EVP_PKEY.
- evp_pkey_is_typed(), to detect that an EVP_PKEY has been assigned a
type, which may be an old style type number or a EVP_KEYMGMT method.
- evp_pkey_is_assigned(), to detect that an EVP_PKEY has been assigned
an key value.
- evp_pkey_is_legacy(), to detect that the internal EVP_PKEY key is a
legacy one, i.e. will be handled via an EVP_PKEY_ASN1_METHOD and an
EVP_PKEY_METHOD.
- evp_pkey_is_provided(), to detect that the internal EVP_PKEY key is
a provider side one, i.e. will be handdled via an EVP_KEYMGMT and
other provider methods.
This also introduces EVP_PKEY_KEYMGMT, to indicate that this EVP_PKEY
contains a provider side key for which there are no known
EVP_PKEY_ASN1_METHODs or EVP_PKEY_METHODs, i.e. these can only be
handled via EVP_KEYMGMT and other provider methods.
Fixes #11823
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/11913)
2020-05-22 21:41:28 +08:00
|
|
|
* The EVP_PKEY_ASN1_METHOD |pkey_id| retains its legacy key purpose
|
|
|
|
* for any key type that has a legacy implementation, regardless of
|
|
|
|
* if the internal key is a legacy or a provider side one. When
|
|
|
|
* there is no legacy implementation for the key, the type becomes
|
|
|
|
* EVP_PKEY_KEYMGMT, which indicates that one should be cautious
|
|
|
|
* with functions that expect legacy internal keys.
|
2020-03-21 13:14:25 +08:00
|
|
|
*/
|
2021-04-08 23:22:51 +08:00
|
|
|
if (ameth != NULL) {
|
|
|
|
if (type == EVP_PKEY_NONE)
|
|
|
|
pkey->type = ameth->pkey_id;
|
|
|
|
} else {
|
Re-introduce legacy EVP_PKEY types for provided keys
EVP_PKEYs with provider side internal keys got the key type
EVP_PKEY_NONE. This turned out to be too disruptive, so we try
instead to find a matching EVP_PKEY_ASN1_METHOD and use whatever
EVP_PKEY type it uses.
To make internal coding easier, we introduce a few internal macros to
distinguish what can be expected from a EVP_PKEY:
- evp_pkey_is_blank(), to detect an unassigned EVP_PKEY.
- evp_pkey_is_typed(), to detect that an EVP_PKEY has been assigned a
type, which may be an old style type number or a EVP_KEYMGMT method.
- evp_pkey_is_assigned(), to detect that an EVP_PKEY has been assigned
an key value.
- evp_pkey_is_legacy(), to detect that the internal EVP_PKEY key is a
legacy one, i.e. will be handled via an EVP_PKEY_ASN1_METHOD and an
EVP_PKEY_METHOD.
- evp_pkey_is_provided(), to detect that the internal EVP_PKEY key is
a provider side one, i.e. will be handdled via an EVP_KEYMGMT and
other provider methods.
This also introduces EVP_PKEY_KEYMGMT, to indicate that this EVP_PKEY
contains a provider side key for which there are no known
EVP_PKEY_ASN1_METHODs or EVP_PKEY_METHODs, i.e. these can only be
handled via EVP_KEYMGMT and other provider methods.
Fixes #11823
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/11913)
2020-05-22 21:41:28 +08:00
|
|
|
pkey->type = EVP_PKEY_KEYMGMT;
|
2021-04-08 23:22:51 +08:00
|
|
|
}
|
2021-10-15 23:23:31 +08:00
|
|
|
# ifndef OPENSSL_NO_ENGINE
|
|
|
|
if (eptr == NULL && e != NULL && !ENGINE_init(e)) {
|
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
# endif
|
|
|
|
pkey->engine = e;
|
2020-03-21 13:14:25 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2020-03-21 13:14:25 +08:00
|
|
|
static void find_ameth(const char *name, void *data)
|
|
|
|
{
|
|
|
|
const char **str = data;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The error messages from pkey_set_type() are uninteresting here,
|
|
|
|
* and misleading.
|
|
|
|
*/
|
|
|
|
ERR_set_mark();
|
|
|
|
|
|
|
|
if (pkey_set_type(NULL, NULL, EVP_PKEY_NONE, name, strlen(name),
|
|
|
|
NULL)) {
|
|
|
|
if (str[0] == NULL)
|
|
|
|
str[0] = name;
|
|
|
|
else if (str[1] == NULL)
|
|
|
|
str[1] = name;
|
|
|
|
}
|
|
|
|
|
|
|
|
ERR_pop_to_mark();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int EVP_PKEY_set_type_by_keymgmt(EVP_PKEY *pkey, EVP_KEYMGMT *keymgmt)
|
|
|
|
{
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2020-03-21 13:14:25 +08:00
|
|
|
# define EVP_PKEY_TYPE_STR str[0]
|
|
|
|
# define EVP_PKEY_TYPE_STRLEN (str[0] == NULL ? -1 : (int)strlen(str[0]))
|
|
|
|
/*
|
|
|
|
* Find at most two strings that have an associated EVP_PKEY_ASN1_METHOD
|
|
|
|
* Ideally, only one should be found. If two (or more) are found, the
|
|
|
|
* match is ambiguous. This should never happen, but...
|
|
|
|
*/
|
|
|
|
const char *str[2] = { NULL, NULL };
|
|
|
|
|
2021-02-20 01:03:43 +08:00
|
|
|
if (!EVP_KEYMGMT_names_do_all(keymgmt, find_ameth, &str)
|
|
|
|
|| str[1] != NULL) {
|
2020-03-21 13:14:25 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
# define EVP_PKEY_TYPE_STR NULL
|
|
|
|
# define EVP_PKEY_TYPE_STRLEN -1
|
|
|
|
#endif
|
|
|
|
return pkey_set_type(pkey, NULL, EVP_PKEY_NONE,
|
|
|
|
EVP_PKEY_TYPE_STR, EVP_PKEY_TYPE_STRLEN,
|
|
|
|
keymgmt);
|
|
|
|
|
|
|
|
#undef EVP_PKEY_TYPE_STR
|
|
|
|
#undef EVP_PKEY_TYPE_STRLEN
|
|
|
|
}
|
|
|
|
|
2020-01-12 09:32:12 +08:00
|
|
|
int EVP_PKEY_up_ref(EVP_PKEY *pkey)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2023-06-22 07:48:49 +08:00
|
|
|
if (CRYPTO_UP_REF(&pkey->references, &i) <= 0)
|
2020-01-12 09:32:12 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
REF_PRINT_COUNT("EVP_PKEY", pkey);
|
|
|
|
REF_ASSERT_ISNT(i < 2);
|
|
|
|
return ((i > 1) ? 1 : 0);
|
|
|
|
}
|
|
|
|
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2021-03-20 01:45:43 +08:00
|
|
|
EVP_PKEY *EVP_PKEY_dup(EVP_PKEY *pkey)
|
|
|
|
{
|
|
|
|
EVP_PKEY *dup_pk;
|
|
|
|
|
|
|
|
if (pkey == NULL) {
|
|
|
|
ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((dup_pk = EVP_PKEY_new()) == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (evp_pkey_is_blank(pkey))
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
if (evp_pkey_is_provided(pkey)) {
|
|
|
|
if (!evp_keymgmt_util_copy(dup_pk, pkey,
|
|
|
|
OSSL_KEYMGMT_SELECT_ALL))
|
|
|
|
goto err;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (evp_pkey_is_legacy(pkey)) {
|
|
|
|
const EVP_PKEY_ASN1_METHOD *ameth = pkey->ameth;
|
|
|
|
|
|
|
|
if (ameth == NULL || ameth->copy == NULL) {
|
|
|
|
if (pkey->pkey.ptr == NULL /* empty key, just set type */
|
|
|
|
&& EVP_PKEY_set_type(dup_pk, pkey->type) != 0)
|
|
|
|
goto done;
|
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_UNSUPPORTED_KEY_TYPE);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
if (!ameth->copy(dup_pk, pkey))
|
|
|
|
goto err;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
goto err;
|
|
|
|
done:
|
|
|
|
/* copy auxiliary data */
|
|
|
|
if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EVP_PKEY,
|
|
|
|
&dup_pk->ex_data, &pkey->ex_data))
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if (pkey->attributes != NULL) {
|
|
|
|
if ((dup_pk->attributes = ossl_x509at_dup(pkey->attributes)) == NULL)
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
return dup_pk;
|
|
|
|
err:
|
|
|
|
EVP_PKEY_free(dup_pk);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-10-27 22:09:26 +08:00
|
|
|
void evp_pkey_free_legacy(EVP_PKEY *x)
|
2020-02-21 05:55:41 +08:00
|
|
|
{
|
2021-02-25 00:38:28 +08:00
|
|
|
const EVP_PKEY_ASN1_METHOD *ameth = x->ameth;
|
|
|
|
ENGINE *tmpe = NULL;
|
|
|
|
|
|
|
|
if (ameth == NULL && x->legacy_cache_pkey.ptr != NULL)
|
|
|
|
ameth = EVP_PKEY_asn1_find(&tmpe, x->type);
|
|
|
|
|
|
|
|
if (ameth != NULL) {
|
|
|
|
if (x->legacy_cache_pkey.ptr != NULL) {
|
|
|
|
/*
|
|
|
|
* We should never have both a legacy origin key, and a key in the
|
|
|
|
* legacy cache.
|
|
|
|
*/
|
|
|
|
assert(x->pkey.ptr == NULL);
|
|
|
|
/*
|
|
|
|
* For the purposes of freeing we make the legacy cache look like
|
|
|
|
* a legacy origin key.
|
|
|
|
*/
|
|
|
|
x->pkey = x->legacy_cache_pkey;
|
|
|
|
x->legacy_cache_pkey.ptr = NULL;
|
|
|
|
}
|
|
|
|
if (ameth->pkey_free != NULL)
|
|
|
|
ameth->pkey_free(x);
|
2020-02-21 05:55:41 +08:00
|
|
|
x->pkey.ptr = NULL;
|
|
|
|
}
|
|
|
|
# ifndef OPENSSL_NO_ENGINE
|
2021-02-25 00:38:28 +08:00
|
|
|
ENGINE_finish(tmpe);
|
2020-02-21 05:55:41 +08:00
|
|
|
ENGINE_finish(x->engine);
|
|
|
|
x->engine = NULL;
|
|
|
|
ENGINE_finish(x->pmeth_engine);
|
|
|
|
x->pmeth_engine = NULL;
|
|
|
|
# endif
|
|
|
|
}
|
2020-04-14 04:34:56 +08:00
|
|
|
#endif /* FIPS_MODULE */
|
2020-02-21 05:55:41 +08:00
|
|
|
|
2020-01-12 09:32:12 +08:00
|
|
|
static void evp_pkey_free_it(EVP_PKEY *x)
|
|
|
|
{
|
|
|
|
/* internal function; x is never NULL */
|
2023-05-10 23:27:03 +08:00
|
|
|
evp_keymgmt_util_clear_operation_cache(x);
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2020-02-21 05:55:41 +08:00
|
|
|
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;
|
|
|
|
}
|
Re-introduce legacy EVP_PKEY types for provided keys
EVP_PKEYs with provider side internal keys got the key type
EVP_PKEY_NONE. This turned out to be too disruptive, so we try
instead to find a matching EVP_PKEY_ASN1_METHOD and use whatever
EVP_PKEY type it uses.
To make internal coding easier, we introduce a few internal macros to
distinguish what can be expected from a EVP_PKEY:
- evp_pkey_is_blank(), to detect an unassigned EVP_PKEY.
- evp_pkey_is_typed(), to detect that an EVP_PKEY has been assigned a
type, which may be an old style type number or a EVP_KEYMGMT method.
- evp_pkey_is_assigned(), to detect that an EVP_PKEY has been assigned
an key value.
- evp_pkey_is_legacy(), to detect that the internal EVP_PKEY key is a
legacy one, i.e. will be handled via an EVP_PKEY_ASN1_METHOD and an
EVP_PKEY_METHOD.
- evp_pkey_is_provided(), to detect that the internal EVP_PKEY key is
a provider side one, i.e. will be handdled via an EVP_KEYMGMT and
other provider methods.
This also introduces EVP_PKEY_KEYMGMT, to indicate that this EVP_PKEY
contains a provider side key for which there are no known
EVP_PKEY_ASN1_METHODs or EVP_PKEY_METHODs, i.e. these can only be
handled via EVP_KEYMGMT and other provider methods.
Fixes #11823
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/11913)
2020-05-22 21:41:28 +08:00
|
|
|
x->type = EVP_PKEY_NONE;
|
2020-01-12 09:32:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void EVP_PKEY_free(EVP_PKEY *x)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (x == NULL)
|
|
|
|
return;
|
|
|
|
|
2023-06-22 07:48:49 +08:00
|
|
|
CRYPTO_DOWN_REF(&x->references, &i);
|
2020-01-12 09:32:12 +08:00
|
|
|
REF_PRINT_COUNT("EVP_PKEY", x);
|
|
|
|
if (i > 0)
|
|
|
|
return;
|
|
|
|
REF_ASSERT_ISNT(i < 0);
|
|
|
|
evp_pkey_free_it(x);
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2020-04-07 08:18:09 +08:00
|
|
|
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_EVP_PKEY, x, &x->ex_data);
|
|
|
|
#endif
|
2020-01-12 09:32:12 +08:00
|
|
|
CRYPTO_THREAD_lock_free(x->lock);
|
2023-06-22 07:48:49 +08:00
|
|
|
CRYPTO_FREE_REF(&x->references);
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2020-01-12 09:32:12 +08:00
|
|
|
sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free);
|
|
|
|
#endif
|
|
|
|
OPENSSL_free(x);
|
|
|
|
}
|
|
|
|
|
Rename all getters to use get/get0 in name
For functions that exist in 1.1.1 provide a simple aliases via #define.
Fixes #15236
Functions with OSSL_DECODER_, OSSL_ENCODER_, OSSL_STORE_LOADER_,
EVP_KEYEXCH_, EVP_KEM_, EVP_ASYM_CIPHER_, EVP_SIGNATURE_,
EVP_KEYMGMT_, EVP_RAND_, EVP_MAC_, EVP_KDF_, EVP_PKEY_,
EVP_MD_, and EVP_CIPHER_ prefixes are renamed.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15405)
2021-05-21 22:58:08 +08:00
|
|
|
int EVP_PKEY_get_size(const EVP_PKEY *pkey)
|
2020-01-12 09:32:12 +08:00
|
|
|
{
|
2020-03-21 13:03:39 +08:00
|
|
|
int size = 0;
|
|
|
|
|
2020-01-08 10:44:28 +08:00
|
|
|
if (pkey != NULL) {
|
2020-03-21 13:03:39 +08:00
|
|
|
size = pkey->cache.size;
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2020-03-21 13:03:39 +08:00
|
|
|
if (pkey->ameth != NULL && pkey->ameth->pkey_size != NULL)
|
|
|
|
size = pkey->ameth->pkey_size(pkey);
|
|
|
|
#endif
|
2020-01-08 10:44:28 +08:00
|
|
|
}
|
2023-10-21 02:51:17 +08:00
|
|
|
if (size <= 0) {
|
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_UNKNOWN_MAX_SIZE);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return size;
|
2020-01-12 09:32:12 +08:00
|
|
|
}
|
2020-01-14 21:11:47 +08:00
|
|
|
|
Rename all getters to use get/get0 in name
For functions that exist in 1.1.1 provide a simple aliases via #define.
Fixes #15236
Functions with OSSL_DECODER_, OSSL_ENCODER_, OSSL_STORE_LOADER_,
EVP_KEYEXCH_, EVP_KEM_, EVP_ASYM_CIPHER_, EVP_SIGNATURE_,
EVP_KEYMGMT_, EVP_RAND_, EVP_MAC_, EVP_KDF_, EVP_PKEY_,
EVP_MD_, and EVP_CIPHER_ prefixes are renamed.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15405)
2021-05-21 22:58:08 +08:00
|
|
|
const char *EVP_PKEY_get0_description(const EVP_PKEY *pkey)
|
EVP: Add EVP_<TYPE>_description()
The following operation types are covered:
EVP_MD, EVP_CIPHER, EVP_MAC, EVP_RAND, EVP_KEYMGMT, EVP_SIGNATURE,
EVP_ASYM_CIPHER, EVP_KEM, EVP_KEYEXCH, EVP_KDF. Also EVP_PKEY.
For EVP_MD and EVP_CIPHER, OBJ_nid2ln() is used as a fallback for
legacy implementations.
For EVP_PKEY, the info field of the EVP_PKEY_ASN1_METHOD is used as a
fallback for legacy implementations.
Fixes #14514
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/14656)
2021-03-16 21:23:54 +08:00
|
|
|
{
|
|
|
|
if (!evp_pkey_is_assigned(pkey))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (evp_pkey_is_provided(pkey) && pkey->keymgmt->description != NULL)
|
|
|
|
return pkey->keymgmt->description;
|
|
|
|
#ifndef FIPS_MODULE
|
|
|
|
if (pkey->ameth != NULL)
|
|
|
|
return pkey->ameth->info;
|
|
|
|
#endif
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-10-15 17:55:50 +08:00
|
|
|
void *evp_pkey_export_to_provider(EVP_PKEY *pk, OSSL_LIB_CTX *libctx,
|
2020-02-21 03:26:16 +08:00
|
|
|
EVP_KEYMGMT **keymgmt,
|
|
|
|
const char *propquery)
|
2020-01-14 21:11:47 +08:00
|
|
|
{
|
|
|
|
EVP_KEYMGMT *allocated_keymgmt = NULL;
|
|
|
|
EVP_KEYMGMT *tmp_keymgmt = NULL;
|
2022-11-10 23:46:32 +08:00
|
|
|
int selection = OSSL_KEYMGMT_SELECT_ALL;
|
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-03-21 13:03:39 +08:00
|
|
|
int check;
|
2020-01-14 21:11:47 +08:00
|
|
|
|
|
|
|
if (pk == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2020-03-21 13:03:39 +08:00
|
|
|
/* No key data => nothing to export */
|
|
|
|
check = 1;
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2020-03-21 13:03:39 +08:00
|
|
|
check = check && pk->pkey.ptr == NULL;
|
|
|
|
#endif
|
|
|
|
check = check && pk->keydata == NULL;
|
|
|
|
if (check)
|
|
|
|
return NULL;
|
|
|
|
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2020-02-12 21:28:50 +08:00
|
|
|
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-03-17 21:37:47 +08:00
|
|
|
/*
|
|
|
|
* If no keymgmt was given or found, get a default keymgmt. We do so by
|
|
|
|
* letting EVP_PKEY_CTX_new_from_pkey() do it for us, then we steal it.
|
|
|
|
*/
|
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
|
|
|
|
2021-10-22 22:50:27 +08:00
|
|
|
if (ctx == NULL)
|
|
|
|
goto end;
|
2022-06-08 16:41:16 +08:00
|
|
|
allocated_keymgmt = tmp_keymgmt = ctx->keymgmt;
|
2020-03-17 21:37:47 +08:00
|
|
|
ctx->keymgmt = NULL;
|
2020-01-14 21:11:47 +08:00
|
|
|
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-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2020-02-12 21:28:50 +08:00
|
|
|
if (pk->pkey.ptr != NULL) {
|
2021-02-04 12:40:19 +08:00
|
|
|
OP_CACHE_ELEM *op;
|
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) {
|
2021-01-28 01:18:27 +08:00
|
|
|
if (!CRYPTO_THREAD_read_lock(pk->lock))
|
|
|
|
goto end;
|
2022-11-10 23:46:32 +08:00
|
|
|
op = evp_keymgmt_util_find_operation_cache(pk, tmp_keymgmt,
|
|
|
|
selection);
|
2020-02-21 03:26:16 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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
|
2024-03-13 23:19:43 +08:00
|
|
|
* values to return. It is possible (e.g. in a no-cached-fetch
|
|
|
|
* build), for op->keymgmt to be a different pointer to tmp_keymgmt
|
|
|
|
* even though the name/provider must be the same. In other words
|
|
|
|
* the keymgmt instance may be different but still equivalent, i.e.
|
|
|
|
* same algorithm/provider instance - but we make the simplifying
|
|
|
|
* assumption that the keydata can be used with either keymgmt
|
|
|
|
* instance. Not doing so introduces significant complexity and
|
|
|
|
* probably requires refactoring - since we would have to ripple
|
|
|
|
* the change in keymgmt instance up the call chain.
|
2020-02-21 03:26:16 +08:00
|
|
|
*/
|
2021-02-04 12:40:19 +08:00
|
|
|
if (op != NULL && op->keymgmt != NULL) {
|
|
|
|
keydata = op->keydata;
|
2021-01-28 01:18:27 +08:00
|
|
|
CRYPTO_THREAD_unlock(pk->lock);
|
2020-02-21 03:26:16 +08:00
|
|
|
goto end;
|
|
|
|
}
|
2021-01-28 01:18:27 +08:00
|
|
|
CRYPTO_THREAD_unlock(pk->lock);
|
2020-02-12 21:28:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Make sure that the keymgmt key type matches the legacy NID */
|
2021-03-12 10:32:44 +08:00
|
|
|
if (!EVP_KEYMGMT_is_a(tmp_keymgmt, OBJ_nid2sn(pk->type)))
|
2020-02-12 21:28:50 +08:00
|
|
|
goto end;
|
|
|
|
|
|
|
|
if ((keydata = evp_keymgmt_newdata(tmp_keymgmt)) == NULL)
|
|
|
|
goto end;
|
|
|
|
|
2021-05-15 13:43:06 +08:00
|
|
|
if (!pk->ameth->export_to(pk, keydata, tmp_keymgmt->import,
|
|
|
|
libctx, propquery)) {
|
2020-02-12 21:28:50 +08:00
|
|
|
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;
|
|
|
|
}
|
2021-01-28 01:18:27 +08:00
|
|
|
|
|
|
|
if (!CRYPTO_THREAD_write_lock(pk->lock))
|
|
|
|
goto end;
|
|
|
|
if (pk->ameth->dirty_cnt(pk) != pk->dirty_cnt_copy
|
2023-05-10 23:27:03 +08:00
|
|
|
&& !evp_keymgmt_util_clear_operation_cache(pk)) {
|
2021-01-28 01:18:27 +08:00
|
|
|
CRYPTO_THREAD_unlock(pk->lock);
|
|
|
|
evp_keymgmt_freedata(tmp_keymgmt, keydata);
|
|
|
|
keydata = NULL;
|
|
|
|
EVP_KEYMGMT_free(tmp_keymgmt);
|
|
|
|
goto end;
|
|
|
|
}
|
2020-02-21 03:26:16 +08:00
|
|
|
EVP_KEYMGMT_free(tmp_keymgmt); /* refcnt-- */
|
|
|
|
|
2021-02-04 12:40:19 +08:00
|
|
|
/* Check to make sure some other thread didn't get there first */
|
2022-11-10 23:46:32 +08:00
|
|
|
op = evp_keymgmt_util_find_operation_cache(pk, tmp_keymgmt, selection);
|
2021-02-04 12:40:19 +08:00
|
|
|
if (op != NULL && op->keymgmt != NULL) {
|
|
|
|
void *tmp_keydata = op->keydata;
|
|
|
|
|
|
|
|
CRYPTO_THREAD_unlock(pk->lock);
|
|
|
|
evp_keymgmt_freedata(tmp_keymgmt, keydata);
|
|
|
|
keydata = tmp_keydata;
|
|
|
|
goto end;
|
|
|
|
}
|
|
|
|
|
2020-02-21 03:26:16 +08:00
|
|
|
/* Add the new export to the operation cache */
|
2022-11-10 23:46:32 +08:00
|
|
|
if (!evp_keymgmt_util_cache_keydata(pk, tmp_keymgmt, keydata,
|
|
|
|
selection)) {
|
2021-01-28 01:18:27 +08:00
|
|
|
CRYPTO_THREAD_unlock(pk->lock);
|
2020-02-21 03:26:16 +08:00
|
|
|
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);
|
2021-04-08 01:35:13 +08:00
|
|
|
|
2021-01-28 01:18:27 +08:00
|
|
|
CRYPTO_THREAD_unlock(pk->lock);
|
2020-02-12 21:28:50 +08:00
|
|
|
goto end;
|
|
|
|
}
|
2020-04-14 04:34:56 +08:00
|
|
|
#endif /* FIPS_MODULE */
|
2020-02-12 21:28:50 +08:00
|
|
|
|
2022-11-10 23:46:32 +08:00
|
|
|
keydata = evp_keymgmt_util_export_to_provider(pk, tmp_keymgmt, selection);
|
2020-02-12 21:28:50 +08:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2022-06-08 16:41:16 +08:00
|
|
|
if (keymgmt != NULL && tmp_keymgmt != NULL) {
|
2020-01-14 21:11:47 +08:00
|
|
|
*keymgmt = tmp_keymgmt;
|
2022-06-08 16:41:16 +08:00
|
|
|
allocated_keymgmt = NULL;
|
|
|
|
}
|
2020-01-14 21:11:47 +08:00
|
|
|
|
|
|
|
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
|
|
|
|
2020-04-14 04:34:56 +08:00
|
|
|
#ifndef FIPS_MODULE
|
2020-08-27 16:07:09 +08:00
|
|
|
int evp_pkey_copy_downgraded(EVP_PKEY **dest, const EVP_PKEY *src)
|
2020-02-21 05:55:41 +08:00
|
|
|
{
|
2022-06-03 21:01:22 +08:00
|
|
|
EVP_PKEY *allocpkey = NULL;
|
|
|
|
|
2020-08-27 16:07:09 +08:00
|
|
|
if (!ossl_assert(dest != NULL))
|
|
|
|
return 0;
|
2020-02-21 05:55:41 +08:00
|
|
|
|
2020-08-27 16:07:09 +08:00
|
|
|
if (evp_pkey_is_assigned(src) && evp_pkey_is_provided(src)) {
|
|
|
|
EVP_KEYMGMT *keymgmt = src->keymgmt;
|
|
|
|
void *keydata = src->keydata;
|
|
|
|
int type = src->type;
|
|
|
|
const char *keytype = NULL;
|
2020-03-21 13:21:26 +08:00
|
|
|
|
Rename all getters to use get/get0 in name
For functions that exist in 1.1.1 provide a simple aliases via #define.
Fixes #15236
Functions with OSSL_DECODER_, OSSL_ENCODER_, OSSL_STORE_LOADER_,
EVP_KEYEXCH_, EVP_KEM_, EVP_ASYM_CIPHER_, EVP_SIGNATURE_,
EVP_KEYMGMT_, EVP_RAND_, EVP_MAC_, EVP_KDF_, EVP_PKEY_,
EVP_MD_, and EVP_CIPHER_ prefixes are renamed.
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/15405)
2021-05-21 22:58:08 +08:00
|
|
|
keytype = EVP_KEYMGMT_get0_name(keymgmt);
|
2020-02-21 05:55:41 +08:00
|
|
|
|
2020-08-27 16:07:09 +08:00
|
|
|
/*
|
|
|
|
* If the type is EVP_PKEY_NONE, then we have a problem somewhere
|
|
|
|
* else in our code. If it's not one of the well known EVP_PKEY_xxx
|
|
|
|
* values, it should at least be EVP_PKEY_KEYMGMT at this point.
|
2021-03-16 00:10:26 +08:00
|
|
|
* The check is kept as a safety measure.
|
2020-08-27 16:07:09 +08:00
|
|
|
*/
|
|
|
|
if (!ossl_assert(type != EVP_PKEY_NONE)) {
|
|
|
|
ERR_raise_data(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR,
|
|
|
|
"keymgmt key type = %s but legacy type = EVP_PKEY_NONE",
|
|
|
|
keytype);
|
|
|
|
return 0;
|
|
|
|
}
|
2020-02-21 05:55:41 +08:00
|
|
|
|
2020-08-27 16:07:09 +08:00
|
|
|
/* Prefer the legacy key type name for error reporting */
|
|
|
|
if (type != EVP_PKEY_KEYMGMT)
|
|
|
|
keytype = OBJ_nid2sn(type);
|
Re-introduce legacy EVP_PKEY types for provided keys
EVP_PKEYs with provider side internal keys got the key type
EVP_PKEY_NONE. This turned out to be too disruptive, so we try
instead to find a matching EVP_PKEY_ASN1_METHOD and use whatever
EVP_PKEY type it uses.
To make internal coding easier, we introduce a few internal macros to
distinguish what can be expected from a EVP_PKEY:
- evp_pkey_is_blank(), to detect an unassigned EVP_PKEY.
- evp_pkey_is_typed(), to detect that an EVP_PKEY has been assigned a
type, which may be an old style type number or a EVP_KEYMGMT method.
- evp_pkey_is_assigned(), to detect that an EVP_PKEY has been assigned
an key value.
- evp_pkey_is_legacy(), to detect that the internal EVP_PKEY key is a
legacy one, i.e. will be handled via an EVP_PKEY_ASN1_METHOD and an
EVP_PKEY_METHOD.
- evp_pkey_is_provided(), to detect that the internal EVP_PKEY key is
a provider side one, i.e. will be handdled via an EVP_KEYMGMT and
other provider methods.
This also introduces EVP_PKEY_KEYMGMT, to indicate that this EVP_PKEY
contains a provider side key for which there are no known
EVP_PKEY_ASN1_METHODs or EVP_PKEY_METHODs, i.e. these can only be
handled via EVP_KEYMGMT and other provider methods.
Fixes #11823
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/11913)
2020-05-22 21:41:28 +08:00
|
|
|
|
2020-08-27 16:07:09 +08:00
|
|
|
/* Make sure we have a clean slate to copy into */
|
2021-02-24 23:04:41 +08:00
|
|
|
if (*dest == NULL) {
|
2022-06-03 21:01:22 +08:00
|
|
|
allocpkey = *dest = EVP_PKEY_new();
|
2021-02-24 23:04:41 +08:00
|
|
|
if (*dest == NULL) {
|
2022-09-29 19:57:34 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB);
|
2021-02-24 23:04:41 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
} else {
|
2020-08-27 16:07:09 +08:00
|
|
|
evp_pkey_free_it(*dest);
|
2021-02-24 23:04:41 +08:00
|
|
|
}
|
2020-02-21 05:55:41 +08:00
|
|
|
|
2020-08-27 16:07:09 +08:00
|
|
|
if (EVP_PKEY_set_type(*dest, type)) {
|
|
|
|
/* If the key is typed but empty, we're done */
|
|
|
|
if (keydata == NULL)
|
|
|
|
return 1;
|
2020-04-11 01:28:24 +08:00
|
|
|
|
2020-08-27 16:07:09 +08:00
|
|
|
if ((*dest)->ameth->import_from == NULL) {
|
|
|
|
ERR_raise_data(ERR_LIB_EVP, EVP_R_NO_IMPORT_FUNCTION,
|
|
|
|
"key type = %s", keytype);
|
|
|
|
} else {
|
2020-04-11 01:28:24 +08:00
|
|
|
/*
|
2020-08-27 16:07:09 +08:00
|
|
|
* We perform the export in the same libctx as the keymgmt
|
|
|
|
* that we are using.
|
2020-04-11 01:28:24 +08:00
|
|
|
*/
|
2020-10-15 17:55:50 +08:00
|
|
|
OSSL_LIB_CTX *libctx =
|
2020-10-15 17:55:50 +08:00
|
|
|
ossl_provider_libctx(keymgmt->prov);
|
2020-08-27 16:07:09 +08:00
|
|
|
EVP_PKEY_CTX *pctx =
|
|
|
|
EVP_PKEY_CTX_new_from_pkey(libctx, *dest, NULL);
|
2020-04-11 01:28:24 +08:00
|
|
|
|
2020-08-27 16:07:09 +08:00
|
|
|
if (pctx == NULL)
|
2022-09-29 19:57:34 +08:00
|
|
|
ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB);
|
2020-04-11 01:28:24 +08:00
|
|
|
|
2020-08-27 16:07:09 +08:00
|
|
|
if (pctx != NULL
|
|
|
|
&& evp_keymgmt_export(keymgmt, keydata,
|
|
|
|
OSSL_KEYMGMT_SELECT_ALL,
|
|
|
|
(*dest)->ameth->import_from,
|
|
|
|
pctx)) {
|
|
|
|
/* Synchronize the dirty count */
|
|
|
|
(*dest)->dirty_cnt_copy = (*dest)->ameth->dirty_cnt(*dest);
|
|
|
|
|
|
|
|
EVP_PKEY_CTX_free(pctx);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
EVP_PKEY_CTX_free(pctx);
|
2020-04-11 01:28:24 +08:00
|
|
|
}
|
2020-02-21 05:55:41 +08:00
|
|
|
|
2020-08-27 16:07:09 +08:00
|
|
|
ERR_raise_data(ERR_LIB_EVP, EVP_R_KEYMGMT_EXPORT_FAILURE,
|
|
|
|
"key type = %s", keytype);
|
|
|
|
}
|
2020-02-21 05:55:41 +08:00
|
|
|
}
|
|
|
|
|
2022-06-03 21:01:22 +08:00
|
|
|
if (allocpkey != NULL) {
|
|
|
|
EVP_PKEY_free(allocpkey);
|
|
|
|
*dest = NULL;
|
|
|
|
}
|
2020-08-27 16:07:09 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-02-25 00:38:28 +08:00
|
|
|
void *evp_pkey_get_legacy(EVP_PKEY *pk)
|
2020-08-27 16:07:09 +08:00
|
|
|
{
|
2021-02-25 00:38:28 +08:00
|
|
|
EVP_PKEY *tmp_copy = NULL;
|
|
|
|
void *ret = NULL;
|
2020-09-25 15:28:14 +08:00
|
|
|
|
|
|
|
if (!ossl_assert(pk != NULL))
|
2021-02-25 00:38:28 +08:00
|
|
|
return NULL;
|
2020-09-25 15:28:14 +08:00
|
|
|
|
|
|
|
/*
|
2021-02-25 00:38:28 +08:00
|
|
|
* If this isn't an assigned provider side key, we just use any existing
|
|
|
|
* origin legacy key.
|
2020-09-25 15:28:14 +08:00
|
|
|
*/
|
2021-02-25 00:38:28 +08:00
|
|
|
if (!evp_pkey_is_assigned(pk))
|
|
|
|
return NULL;
|
|
|
|
if (!evp_pkey_is_provided(pk))
|
|
|
|
return pk->pkey.ptr;
|
2020-08-27 16:07:09 +08:00
|
|
|
|
2021-02-25 00:38:28 +08:00
|
|
|
if (!CRYPTO_THREAD_read_lock(pk->lock))
|
|
|
|
return NULL;
|
2020-08-27 16:07:09 +08:00
|
|
|
|
2021-02-25 00:38:28 +08:00
|
|
|
ret = pk->legacy_cache_pkey.ptr;
|
2020-08-27 16:07:09 +08:00
|
|
|
|
2021-02-25 00:38:28 +08:00
|
|
|
if (!CRYPTO_THREAD_unlock(pk->lock))
|
|
|
|
return NULL;
|
2020-09-25 15:28:14 +08:00
|
|
|
|
2021-02-25 00:38:28 +08:00
|
|
|
if (ret != NULL)
|
|
|
|
return ret;
|
2020-08-27 16:07:09 +08:00
|
|
|
|
2021-02-25 00:38:28 +08:00
|
|
|
if (!evp_pkey_copy_downgraded(&tmp_copy, pk))
|
2022-06-08 00:49:29 +08:00
|
|
|
goto err;
|
2020-08-27 16:07:09 +08:00
|
|
|
|
2021-02-25 00:38:28 +08:00
|
|
|
if (!CRYPTO_THREAD_write_lock(pk->lock))
|
|
|
|
goto err;
|
2020-08-27 16:07:09 +08:00
|
|
|
|
2021-02-25 00:38:28 +08:00
|
|
|
/* Check again in case some other thread has updated it in the meantime */
|
|
|
|
ret = pk->legacy_cache_pkey.ptr;
|
|
|
|
if (ret == NULL) {
|
|
|
|
/* Steal the legacy key reference from the temporary copy */
|
|
|
|
ret = pk->legacy_cache_pkey.ptr = tmp_copy->pkey.ptr;
|
|
|
|
tmp_copy->pkey.ptr = NULL;
|
|
|
|
}
|
2020-08-27 16:07:09 +08:00
|
|
|
|
2021-02-25 00:38:28 +08:00
|
|
|
if (!CRYPTO_THREAD_unlock(pk->lock)) {
|
|
|
|
ret = NULL;
|
|
|
|
goto err;
|
2020-03-21 13:21:26 +08:00
|
|
|
}
|
2020-08-27 16:07:09 +08:00
|
|
|
|
2021-02-25 00:38:28 +08:00
|
|
|
err:
|
|
|
|
EVP_PKEY_free(tmp_copy);
|
|
|
|
|
|
|
|
return ret;
|
2020-02-21 05:55:41 +08:00
|
|
|
}
|
2020-04-14 04:34:56 +08:00
|
|
|
#endif /* FIPS_MODULE */
|
2020-04-01 13:51:18 +08:00
|
|
|
|
2020-12-04 13:30:28 +08:00
|
|
|
int EVP_PKEY_get_bn_param(const EVP_PKEY *pkey, const char *key_name,
|
|
|
|
BIGNUM **bn)
|
2020-04-01 13:51:18 +08:00
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
OSSL_PARAM params[2];
|
|
|
|
unsigned char buffer[2048];
|
|
|
|
unsigned char *buf = NULL;
|
|
|
|
size_t buf_sz = 0;
|
|
|
|
|
2021-02-03 21:10:08 +08:00
|
|
|
if (key_name == NULL
|
2021-03-18 21:22:20 +08:00
|
|
|
|| bn == NULL)
|
2020-04-01 13:51:18 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
memset(buffer, 0, sizeof(buffer));
|
|
|
|
params[0] = OSSL_PARAM_construct_BN(key_name, buffer, sizeof(buffer));
|
|
|
|
params[1] = OSSL_PARAM_construct_end();
|
2021-02-03 20:55:30 +08:00
|
|
|
if (!EVP_PKEY_get_params(pkey, params)) {
|
2020-04-22 12:20:11 +08:00
|
|
|
if (!OSSL_PARAM_modified(params) || params[0].return_size == 0)
|
2020-04-01 13:51:18 +08:00
|
|
|
return 0;
|
|
|
|
buf_sz = params[0].return_size;
|
|
|
|
/*
|
|
|
|
* If it failed because the buffer was too small then allocate the
|
|
|
|
* required buffer size and retry.
|
|
|
|
*/
|
|
|
|
buf = OPENSSL_zalloc(buf_sz);
|
|
|
|
if (buf == NULL)
|
|
|
|
return 0;
|
|
|
|
params[0].data = buf;
|
|
|
|
params[0].data_size = buf_sz;
|
|
|
|
|
2021-02-03 20:55:30 +08:00
|
|
|
if (!EVP_PKEY_get_params(pkey, params))
|
2020-04-01 13:51:18 +08:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
/* Fail if the param was not found */
|
2020-04-22 12:20:11 +08:00
|
|
|
if (!OSSL_PARAM_modified(params))
|
2020-04-01 13:51:18 +08:00
|
|
|
goto err;
|
|
|
|
ret = OSSL_PARAM_get_BN(params, bn);
|
|
|
|
err:
|
2023-03-29 22:16:48 +08:00
|
|
|
if (buf != NULL) {
|
|
|
|
if (OSSL_PARAM_modified(params))
|
|
|
|
OPENSSL_clear_free(buf, buf_sz);
|
|
|
|
else
|
|
|
|
OPENSSL_free(buf);
|
|
|
|
} else if (OSSL_PARAM_modified(params)) {
|
|
|
|
OPENSSL_cleanse(buffer, params[0].data_size);
|
|
|
|
}
|
2020-04-01 13:51:18 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2020-12-04 13:30:28 +08:00
|
|
|
int EVP_PKEY_get_octet_string_param(const EVP_PKEY *pkey, const char *key_name,
|
2020-04-01 13:51:18 +08:00
|
|
|
unsigned char *buf, size_t max_buf_sz,
|
2021-08-17 14:46:23 +08:00
|
|
|
size_t *out_len)
|
2020-04-01 13:51:18 +08:00
|
|
|
{
|
|
|
|
OSSL_PARAM params[2];
|
2021-02-03 23:48:21 +08:00
|
|
|
int ret1 = 0, ret2 = 0;
|
2020-04-01 13:51:18 +08:00
|
|
|
|
2021-03-18 21:22:20 +08:00
|
|
|
if (key_name == NULL)
|
2020-04-01 13:51:18 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
params[0] = OSSL_PARAM_construct_octet_string(key_name, buf, max_buf_sz);
|
|
|
|
params[1] = OSSL_PARAM_construct_end();
|
2021-02-03 23:48:21 +08:00
|
|
|
if ((ret1 = EVP_PKEY_get_params(pkey, params)))
|
|
|
|
ret2 = OSSL_PARAM_modified(params);
|
2021-08-17 14:46:23 +08:00
|
|
|
if (ret2 && out_len != NULL)
|
|
|
|
*out_len = params[0].return_size;
|
2021-02-03 23:48:21 +08:00
|
|
|
return ret1 && ret2;
|
2020-04-01 13:51:18 +08:00
|
|
|
}
|
|
|
|
|
2020-12-04 13:30:28 +08:00
|
|
|
int EVP_PKEY_get_utf8_string_param(const EVP_PKEY *pkey, const char *key_name,
|
2020-04-01 13:51:18 +08:00
|
|
|
char *str, size_t max_buf_sz,
|
2021-08-17 14:46:23 +08:00
|
|
|
size_t *out_len)
|
2020-04-01 13:51:18 +08:00
|
|
|
{
|
|
|
|
OSSL_PARAM params[2];
|
2021-02-03 23:48:21 +08:00
|
|
|
int ret1 = 0, ret2 = 0;
|
2020-04-01 13:51:18 +08:00
|
|
|
|
2021-02-03 21:10:08 +08:00
|
|
|
if (key_name == NULL)
|
2020-04-01 13:51:18 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
params[0] = OSSL_PARAM_construct_utf8_string(key_name, str, max_buf_sz);
|
|
|
|
params[1] = OSSL_PARAM_construct_end();
|
2021-02-03 23:48:21 +08:00
|
|
|
if ((ret1 = EVP_PKEY_get_params(pkey, params)))
|
|
|
|
ret2 = OSSL_PARAM_modified(params);
|
2021-08-17 14:46:23 +08:00
|
|
|
if (ret2 && out_len != NULL)
|
|
|
|
*out_len = params[0].return_size;
|
|
|
|
|
|
|
|
if (ret2 && params[0].return_size == max_buf_sz)
|
|
|
|
/* There was no space for a NUL byte */
|
|
|
|
return 0;
|
|
|
|
/* Add a terminating NUL byte for good measure */
|
|
|
|
if (ret2 && str != NULL)
|
|
|
|
str[params[0].return_size] = '\0';
|
|
|
|
|
2021-02-03 23:48:21 +08:00
|
|
|
return ret1 && ret2;
|
2020-04-01 13:51:18 +08:00
|
|
|
}
|
|
|
|
|
2020-12-04 13:30:28 +08:00
|
|
|
int EVP_PKEY_get_int_param(const EVP_PKEY *pkey, const char *key_name,
|
|
|
|
int *out)
|
2020-04-01 13:51:18 +08:00
|
|
|
{
|
|
|
|
OSSL_PARAM params[2];
|
|
|
|
|
2021-02-03 21:10:08 +08:00
|
|
|
if (key_name == NULL)
|
2020-04-01 13:51:18 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
params[0] = OSSL_PARAM_construct_int(key_name, out);
|
|
|
|
params[1] = OSSL_PARAM_construct_end();
|
2021-02-03 20:55:30 +08:00
|
|
|
return EVP_PKEY_get_params(pkey, params)
|
|
|
|
&& OSSL_PARAM_modified(params);
|
2020-04-01 13:51:18 +08:00
|
|
|
}
|
|
|
|
|
2020-12-04 13:30:28 +08:00
|
|
|
int EVP_PKEY_get_size_t_param(const EVP_PKEY *pkey, const char *key_name,
|
|
|
|
size_t *out)
|
2020-04-01 13:51:18 +08:00
|
|
|
{
|
|
|
|
OSSL_PARAM params[2];
|
|
|
|
|
2021-02-03 21:10:08 +08:00
|
|
|
if (key_name == NULL)
|
2020-04-01 13:51:18 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
params[0] = OSSL_PARAM_construct_size_t(key_name, out);
|
|
|
|
params[1] = OSSL_PARAM_construct_end();
|
2021-02-03 20:55:30 +08:00
|
|
|
return EVP_PKEY_get_params(pkey, params)
|
|
|
|
&& OSSL_PARAM_modified(params);
|
2020-04-01 13:51:18 +08:00
|
|
|
}
|
2020-10-15 11:39:02 +08:00
|
|
|
|
|
|
|
int EVP_PKEY_set_int_param(EVP_PKEY *pkey, const char *key_name, int in)
|
|
|
|
{
|
|
|
|
OSSL_PARAM params[2];
|
|
|
|
|
2021-02-03 21:10:08 +08:00
|
|
|
if (key_name == NULL)
|
2020-10-15 11:39:02 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
params[0] = OSSL_PARAM_construct_int(key_name, &in);
|
|
|
|
params[1] = OSSL_PARAM_construct_end();
|
2021-02-03 20:55:30 +08:00
|
|
|
return EVP_PKEY_set_params(pkey, params);
|
2020-10-15 11:39:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_set_size_t_param(EVP_PKEY *pkey, const char *key_name, size_t in)
|
|
|
|
{
|
|
|
|
OSSL_PARAM params[2];
|
|
|
|
|
2021-02-03 21:10:08 +08:00
|
|
|
if (key_name == NULL)
|
2020-10-15 11:39:02 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
params[0] = OSSL_PARAM_construct_size_t(key_name, &in);
|
|
|
|
params[1] = OSSL_PARAM_construct_end();
|
2021-02-03 20:55:30 +08:00
|
|
|
return EVP_PKEY_set_params(pkey, params);
|
2020-10-15 11:39:02 +08:00
|
|
|
}
|
|
|
|
|
2021-02-03 20:55:30 +08:00
|
|
|
int EVP_PKEY_set_bn_param(EVP_PKEY *pkey, const char *key_name,
|
|
|
|
const BIGNUM *bn)
|
2020-10-15 11:39:02 +08:00
|
|
|
{
|
|
|
|
OSSL_PARAM params[2];
|
|
|
|
unsigned char buffer[2048];
|
|
|
|
int bsize = 0;
|
|
|
|
|
2021-02-03 21:10:08 +08:00
|
|
|
if (key_name == NULL
|
|
|
|
|| bn == NULL
|
|
|
|
|| pkey == NULL
|
2021-01-21 06:10:48 +08:00
|
|
|
|| !evp_pkey_is_assigned(pkey))
|
2020-10-15 11:39:02 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
bsize = BN_num_bytes(bn);
|
|
|
|
if (!ossl_assert(bsize <= (int)sizeof(buffer)))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (BN_bn2nativepad(bn, buffer, bsize) < 0)
|
|
|
|
return 0;
|
|
|
|
params[0] = OSSL_PARAM_construct_BN(key_name, buffer, bsize);
|
|
|
|
params[1] = OSSL_PARAM_construct_end();
|
2021-02-03 20:55:30 +08:00
|
|
|
return EVP_PKEY_set_params(pkey, params);
|
2020-10-15 11:39:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_set_utf8_string_param(EVP_PKEY *pkey, const char *key_name,
|
2021-02-03 20:55:30 +08:00
|
|
|
const char *str)
|
2020-10-15 11:39:02 +08:00
|
|
|
{
|
|
|
|
OSSL_PARAM params[2];
|
|
|
|
|
2021-02-03 21:10:08 +08:00
|
|
|
if (key_name == NULL)
|
2020-10-15 11:39:02 +08:00
|
|
|
return 0;
|
|
|
|
|
2021-02-03 20:55:30 +08:00
|
|
|
params[0] = OSSL_PARAM_construct_utf8_string(key_name, (char *)str, 0);
|
2020-10-15 11:39:02 +08:00
|
|
|
params[1] = OSSL_PARAM_construct_end();
|
2021-02-03 20:55:30 +08:00
|
|
|
return EVP_PKEY_set_params(pkey, params);
|
2020-10-15 11:39:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_set_octet_string_param(EVP_PKEY *pkey, const char *key_name,
|
2021-02-03 20:55:30 +08:00
|
|
|
const unsigned char *buf, size_t bsize)
|
2020-10-15 11:39:02 +08:00
|
|
|
{
|
|
|
|
OSSL_PARAM params[2];
|
|
|
|
|
2021-02-03 21:10:08 +08:00
|
|
|
if (key_name == NULL)
|
2020-10-15 11:39:02 +08:00
|
|
|
return 0;
|
|
|
|
|
2021-02-03 20:55:30 +08:00
|
|
|
params[0] = OSSL_PARAM_construct_octet_string(key_name,
|
|
|
|
(unsigned char *)buf, bsize);
|
2020-10-15 11:39:02 +08:00
|
|
|
params[1] = OSSL_PARAM_construct_end();
|
2021-02-03 20:55:30 +08:00
|
|
|
return EVP_PKEY_set_params(pkey, params);
|
2020-10-15 11:39:02 +08:00
|
|
|
}
|
|
|
|
|
2021-02-03 21:10:08 +08:00
|
|
|
const OSSL_PARAM *EVP_PKEY_settable_params(const EVP_PKEY *pkey)
|
2020-10-15 11:39:02 +08:00
|
|
|
{
|
2021-02-03 21:10:08 +08:00
|
|
|
return (pkey != NULL && evp_pkey_is_provided(pkey))
|
|
|
|
? EVP_KEYMGMT_settable_params(pkey->keymgmt)
|
|
|
|
: NULL;
|
2020-10-15 11:39:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_set_params(EVP_PKEY *pkey, OSSL_PARAM params[])
|
|
|
|
{
|
2021-01-21 06:10:48 +08:00
|
|
|
if (pkey != NULL) {
|
|
|
|
if (evp_pkey_is_provided(pkey)) {
|
|
|
|
pkey->dirty_cnt++;
|
|
|
|
return evp_keymgmt_set_params(pkey->keymgmt, pkey->keydata, params);
|
|
|
|
}
|
|
|
|
#ifndef FIPS_MODULE
|
|
|
|
/*
|
|
|
|
* We will hopefully never find the need to set individual data in
|
|
|
|
* EVP_PKEYs with a legacy internal key, but we can't be entirely
|
|
|
|
* sure. This bit of code can be enabled if we find the need. If
|
|
|
|
* not, it can safely be removed when #legacy support is removed.
|
|
|
|
*/
|
|
|
|
# if 0
|
|
|
|
else if (evp_pkey_is_legacy(pkey)) {
|
|
|
|
return evp_pkey_set_params_to_ctrl(pkey, params);
|
|
|
|
}
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY);
|
|
|
|
return 0;
|
2020-10-15 11:39:02 +08:00
|
|
|
}
|
2021-01-19 00:05:43 +08:00
|
|
|
|
2021-02-03 20:55:30 +08:00
|
|
|
const OSSL_PARAM *EVP_PKEY_gettable_params(const EVP_PKEY *pkey)
|
|
|
|
{
|
2021-02-03 21:10:08 +08:00
|
|
|
return (pkey != NULL && evp_pkey_is_provided(pkey))
|
|
|
|
? EVP_KEYMGMT_gettable_params(pkey->keymgmt)
|
|
|
|
: NULL;
|
2021-02-03 20:55:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_get_params(const EVP_PKEY *pkey, OSSL_PARAM params[])
|
|
|
|
{
|
2021-01-21 06:10:48 +08:00
|
|
|
if (pkey != NULL) {
|
|
|
|
if (evp_pkey_is_provided(pkey))
|
2022-05-21 15:27:04 +08:00
|
|
|
return evp_keymgmt_get_params(pkey->keymgmt, pkey->keydata, params) > 0;
|
2021-01-21 06:10:48 +08:00
|
|
|
#ifndef FIPS_MODULE
|
|
|
|
else if (evp_pkey_is_legacy(pkey))
|
2022-05-21 15:27:04 +08:00
|
|
|
return evp_pkey_get_params_to_ctrl(pkey, params) > 0;
|
2021-01-21 06:10:48 +08:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY);
|
|
|
|
return 0;
|
2021-02-03 20:55:30 +08:00
|
|
|
}
|
|
|
|
|
2021-01-19 00:05:43 +08:00
|
|
|
#ifndef FIPS_MODULE
|
|
|
|
int EVP_PKEY_get_ec_point_conv_form(const EVP_PKEY *pkey)
|
|
|
|
{
|
|
|
|
char name[80];
|
|
|
|
size_t name_len;
|
|
|
|
|
|
|
|
if (pkey == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (pkey->keymgmt == NULL
|
|
|
|
|| pkey->keydata == NULL) {
|
2021-03-17 01:29:19 +08:00
|
|
|
# ifndef OPENSSL_NO_EC
|
2021-01-19 00:05:43 +08:00
|
|
|
/* Might work through the legacy route */
|
2021-03-02 23:52:00 +08:00
|
|
|
const EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
|
2021-01-19 00:05:43 +08:00
|
|
|
|
|
|
|
if (ec == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return EC_KEY_get_conv_form(ec);
|
2021-03-17 01:29:19 +08:00
|
|
|
# else
|
2021-01-19 00:05:43 +08:00
|
|
|
return 0;
|
2021-03-17 01:29:19 +08:00
|
|
|
# endif
|
2021-01-19 00:05:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!EVP_PKEY_get_utf8_string_param(pkey,
|
|
|
|
OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
|
|
|
|
name, sizeof(name), &name_len))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (strcmp(name, "uncompressed") == 0)
|
|
|
|
return POINT_CONVERSION_UNCOMPRESSED;
|
|
|
|
|
|
|
|
if (strcmp(name, "compressed") == 0)
|
|
|
|
return POINT_CONVERSION_COMPRESSED;
|
|
|
|
|
|
|
|
if (strcmp(name, "hybrid") == 0)
|
|
|
|
return POINT_CONVERSION_HYBRID;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int EVP_PKEY_get_field_type(const EVP_PKEY *pkey)
|
|
|
|
{
|
|
|
|
char fstr[80];
|
|
|
|
size_t fstrlen;
|
|
|
|
|
|
|
|
if (pkey == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (pkey->keymgmt == NULL
|
|
|
|
|| pkey->keydata == NULL) {
|
2021-03-17 01:29:19 +08:00
|
|
|
# ifndef OPENSSL_NO_EC
|
2021-01-19 00:05:43 +08:00
|
|
|
/* Might work through the legacy route */
|
2021-03-02 23:52:00 +08:00
|
|
|
const EC_KEY *ec = EVP_PKEY_get0_EC_KEY(pkey);
|
2021-01-19 00:05:43 +08:00
|
|
|
const EC_GROUP *grp;
|
|
|
|
|
|
|
|
if (ec == NULL)
|
|
|
|
return 0;
|
|
|
|
grp = EC_KEY_get0_group(ec);
|
2021-01-22 20:59:54 +08:00
|
|
|
if (grp == NULL)
|
|
|
|
return 0;
|
2021-01-19 00:05:43 +08:00
|
|
|
|
|
|
|
return EC_GROUP_get_field_type(grp);
|
2021-03-17 01:29:19 +08:00
|
|
|
# else
|
2021-01-19 00:05:43 +08:00
|
|
|
return 0;
|
2021-03-17 01:29:19 +08:00
|
|
|
# endif
|
2021-01-19 00:05:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!EVP_PKEY_get_utf8_string_param(pkey, OSSL_PKEY_PARAM_EC_FIELD_TYPE,
|
|
|
|
fstr, sizeof(fstr), &fstrlen))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (strcmp(fstr, SN_X9_62_prime_field) == 0)
|
|
|
|
return NID_X9_62_prime_field;
|
|
|
|
else if (strcmp(fstr, SN_X9_62_characteristic_two_field))
|
|
|
|
return NID_X9_62_characteristic_two_field;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|