/*
* Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
*
- * Licensed under the OpenSSL license (the "License"). You may not use
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
* 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
#include <openssl/dh.h>
#include <openssl/cmac.h>
#include <openssl/engine.h>
+#include <openssl/params.h>
+#include <openssl/serializer.h>
+#include <openssl/core_names.h>
-#include "internal/asn1_int.h"
-#include "internal/evp_int.h"
+#include "crypto/asn1.h"
+#include "crypto/evp.h"
+#include "internal/provider.h"
-static void EVP_PKEY_free_it(EVP_PKEY *x);
+static void evp_pkey_free_it(EVP_PKEY *key);
+
+#ifndef FIPS_MODE
int EVP_PKEY_bits(const EVP_PKEY *pkey)
{
{
if (pkey == NULL)
return 0;
- if (!pkey->ameth || !pkey->ameth->pkey_security_bits)
+ if (pkey->ameth == NULL || pkey->ameth->pkey_security_bits == NULL)
return -2;
return pkey->ameth->pkey_security_bits(pkey);
}
-int EVP_PKEY_size(EVP_PKEY *pkey)
-{
- if (pkey && pkey->ameth && pkey->ameth->pkey_size)
- return pkey->ameth->pkey_size(pkey);
- return 0;
-}
-
int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode)
{
-#ifndef OPENSSL_NO_DSA
+# ifndef OPENSSL_NO_DSA
if (pkey->type == EVP_PKEY_DSA) {
int ret = pkey->save_parameters;
pkey->save_parameters = mode;
return ret;
}
-#endif
-#ifndef OPENSSL_NO_EC
+# endif
+# ifndef OPENSSL_NO_EC
if (pkey->type == EVP_PKEY_EC) {
int ret = pkey->save_parameters;
pkey->save_parameters = mode;
return ret;
}
-#endif
+# endif
return 0;
}
int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey)
{
- if (pkey->ameth && pkey->ameth->param_missing)
+ if (pkey != NULL && pkey->ameth && pkey->ameth->param_missing)
return pkey->ameth->param_missing(pkey);
return 0;
}
return -2;
}
-EVP_PKEY *EVP_PKEY_new(void)
-{
- EVP_PKEY *ret = OPENSSL_zalloc(sizeof(*ret));
-
- if (ret == NULL) {
- EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE);
- return NULL;
- }
- ret->type = EVP_PKEY_NONE;
- ret->save_type = EVP_PKEY_NONE;
- ret->references = 1;
- ret->save_parameters = 1;
- ret->lock = CRYPTO_THREAD_lock_new();
- if (ret->lock == NULL) {
- EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE);
- OPENSSL_free(ret);
- return NULL;
- }
- return ret;
-}
-
-int EVP_PKEY_up_ref(EVP_PKEY *pkey)
-{
- int i;
-
- if (CRYPTO_UP_REF(&pkey->references, &i, pkey->lock) <= 0)
- return 0;
-
- REF_PRINT_COUNT("EVP_PKEY", pkey);
- REF_ASSERT_ISNT(i < 2);
- return ((i > 1) ? 1 : 0);
-}
/*
* Setup a public key ASN1 method and ENGINE from a NID or a string. If pkey
if (pkey) {
if (pkey->pkey.ptr)
- EVP_PKEY_free_it(pkey);
+ evp_pkey_free_it(pkey);
/*
* If key type matches and a method exists then this lookup has
* succeeded once so just indicate success.
*/
if ((type == pkey->save_type) && pkey->ameth)
return 1;
-#ifndef OPENSSL_NO_ENGINE
+# 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
}
if (str)
ameth = EVP_PKEY_asn1_find_str(eptr, str, len);
else
ameth = EVP_PKEY_asn1_find(eptr, type);
-#ifndef OPENSSL_NO_ENGINE
+# ifndef OPENSSL_NO_ENGINE
if (pkey == NULL && eptr != NULL)
ENGINE_finish(e);
-#endif
+# endif
if (ameth == NULL) {
EVPerr(EVP_F_PKEY_SET_TYPE, EVP_R_UNSUPPORTED_ALGORITHM);
return 0;
EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
size_t len, const EVP_CIPHER *cipher)
{
-#ifndef OPENSSL_NO_CMAC
+# ifndef OPENSSL_NO_CMAC
+# ifndef OPENSSL_NO_ENGINE
+ const char *engine_id = e != NULL ? ENGINE_get_id(e) : NULL;
+# endif
+ const char *cipher_name = EVP_CIPHER_name(cipher);
+ const OSSL_PROVIDER *prov = EVP_CIPHER_provider(cipher);
+ OPENSSL_CTX *libctx =
+ prov == NULL ? NULL : ossl_provider_library_context(prov);
EVP_PKEY *ret = EVP_PKEY_new();
- CMAC_CTX *cmctx = CMAC_CTX_new();
+ EVP_MAC *cmac = EVP_MAC_fetch(libctx, OSSL_MAC_NAME_CMAC, NULL);
+ EVP_MAC_CTX *cmctx = cmac != NULL ? EVP_MAC_CTX_new(cmac) : NULL;
+ OSSL_PARAM params[4];
+ size_t paramsn = 0;
if (ret == NULL
|| cmctx == NULL
goto err;
}
- if (!CMAC_Init(cmctx, priv, len, cipher, e)) {
+# ifndef OPENSSL_NO_ENGINE
+ if (engine_id != NULL)
+ params[paramsn++] =
+ OSSL_PARAM_construct_utf8_string("engine", (char *)engine_id, 0);
+# endif
+
+ params[paramsn++] =
+ OSSL_PARAM_construct_utf8_string(OSSL_MAC_PARAM_CIPHER,
+ (char *)cipher_name, 0);
+ params[paramsn++] =
+ OSSL_PARAM_construct_octet_string(OSSL_MAC_PARAM_KEY,
+ (char *)priv, len);
+ params[paramsn] = OSSL_PARAM_construct_end();
+
+ if (!EVP_MAC_CTX_set_params(cmctx, params)) {
EVPerr(EVP_F_EVP_PKEY_NEW_CMAC_KEY, EVP_R_KEY_SETUP_FAILED);
goto err;
}
err:
EVP_PKEY_free(ret);
- CMAC_CTX_free(cmctx);
+ EVP_MAC_CTX_free(cmctx);
+ EVP_MAC_free(cmac);
return NULL;
-#else
+# else
EVPerr(EVP_F_EVP_PKEY_NEW_CMAC_KEY,
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return NULL;
-#endif
+# endif
}
int EVP_PKEY_set_type(EVP_PKEY *pkey, int type)
{
return pkey_set_type(pkey, NULL, EVP_PKEY_NONE, str, len);
}
-#ifndef OPENSSL_NO_ENGINE
+
+int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type)
+{
+ if (pkey->type == type) {
+ return 1; /* it already is that type */
+ }
+
+ /*
+ * The application is requesting to alias this to a different pkey type,
+ * but not one that resolves to the base type.
+ */
+ if (EVP_PKEY_type(type) != EVP_PKEY_base_id(pkey)) {
+ EVPerr(EVP_F_EVP_PKEY_SET_ALIAS_TYPE, EVP_R_UNSUPPORTED_ALGORITHM);
+ return 0;
+ }
+
+ pkey->type = type;
+ return 1;
+}
+
+# ifndef OPENSSL_NO_ENGINE
int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e)
{
if (e != NULL) {
pkey->pmeth_engine = e;
return 1;
}
-#endif
+
+ENGINE *EVP_PKEY_get0_engine(const EVP_PKEY *pkey)
+{
+ return pkey->engine;
+}
+# endif
int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key)
{
if (pkey == NULL || !EVP_PKEY_set_type(pkey, type))
return os->data;
}
-#ifndef OPENSSL_NO_POLY1305
+# ifndef OPENSSL_NO_POLY1305
const unsigned char *EVP_PKEY_get0_poly1305(const EVP_PKEY *pkey, size_t *len)
{
ASN1_OCTET_STRING *os = NULL;
*len = os->length;
return os->data;
}
-#endif
+# endif
-#ifndef OPENSSL_NO_SIPHASH
+# ifndef OPENSSL_NO_SIPHASH
const unsigned char *EVP_PKEY_get0_siphash(const EVP_PKEY *pkey, size_t *len)
{
ASN1_OCTET_STRING *os = NULL;
*len = os->length;
return os->data;
}
-#endif
+# endif
-#ifndef OPENSSL_NO_RSA
+# ifndef OPENSSL_NO_RSA
int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key)
{
int ret = EVP_PKEY_assign_RSA(pkey, key);
return ret;
}
-RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey)
+RSA *EVP_PKEY_get0_RSA(const EVP_PKEY *pkey)
{
- if (pkey->type != EVP_PKEY_RSA) {
+ if (pkey->type != EVP_PKEY_RSA && pkey->type != EVP_PKEY_RSA_PSS) {
EVPerr(EVP_F_EVP_PKEY_GET0_RSA, EVP_R_EXPECTING_AN_RSA_KEY);
return NULL;
}
RSA_up_ref(ret);
return ret;
}
-#endif
+# endif
-#ifndef OPENSSL_NO_DSA
+# ifndef OPENSSL_NO_DSA
int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key)
{
int ret = EVP_PKEY_assign_DSA(pkey, key);
return ret;
}
-DSA *EVP_PKEY_get0_DSA(EVP_PKEY *pkey)
+DSA *EVP_PKEY_get0_DSA(const EVP_PKEY *pkey)
{
if (pkey->type != EVP_PKEY_DSA) {
EVPerr(EVP_F_EVP_PKEY_GET0_DSA, EVP_R_EXPECTING_A_DSA_KEY);
DSA_up_ref(ret);
return ret;
}
-#endif
+# endif
-#ifndef OPENSSL_NO_EC
+# ifndef OPENSSL_NO_EC
int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key)
{
return ret;
}
-EC_KEY *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey)
+EC_KEY *EVP_PKEY_get0_EC_KEY(const EVP_PKEY *pkey)
{
if (pkey->type != EVP_PKEY_EC) {
EVPerr(EVP_F_EVP_PKEY_GET0_EC_KEY, EVP_R_EXPECTING_A_EC_KEY);
EC_KEY_up_ref(ret);
return ret;
}
-#endif
+# endif
-#ifndef OPENSSL_NO_DH
+# ifndef OPENSSL_NO_DH
int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key)
{
- int ret = EVP_PKEY_assign_DH(pkey, key);
+ int type = DH_get0_q(key) == NULL ? EVP_PKEY_DH : EVP_PKEY_DHX;
+ int ret = EVP_PKEY_assign(pkey, type, key);
+
if (ret)
DH_up_ref(key);
return ret;
}
-DH *EVP_PKEY_get0_DH(EVP_PKEY *pkey)
+DH *EVP_PKEY_get0_DH(const EVP_PKEY *pkey)
{
if (pkey->type != EVP_PKEY_DH && pkey->type != EVP_PKEY_DHX) {
EVPerr(EVP_F_EVP_PKEY_GET0_DH, EVP_R_EXPECTING_A_DH_KEY);
DH_up_ref(ret);
return ret;
}
-#endif
+# endif
int EVP_PKEY_type(int type)
{
ret = ameth->pkey_id;
else
ret = NID_undef;
-#ifndef OPENSSL_NO_ENGINE
+# ifndef OPENSSL_NO_ENGINE
ENGINE_finish(e);
-#endif
+# endif
return ret;
}
return EVP_PKEY_type(pkey->type);
}
-void EVP_PKEY_free(EVP_PKEY *x)
-{
- int i;
- if (x == NULL)
- return;
+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);
- CRYPTO_DOWN_REF(&x->references, &i, x->lock);
- REF_PRINT_COUNT("EVP_PKEY", x);
- if (i > 0)
- return;
- REF_ASSERT_ISNT(i < 0);
- EVP_PKEY_free_it(x);
- CRYPTO_THREAD_lock_free(x->lock);
- sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free);
- OPENSSL_free(x);
+ BIO_free(*out);
+ *out = next;
+ }
+ return 1;
}
-static void EVP_PKEY_free_it(EVP_PKEY *x)
+static int print_set_indent(BIO **out, int *pop_f_prefix, long *saved_indent,
+ long indent)
{
- /* internal function; x is never NULL */
- if (x->ameth && x->ameth->pkey_free) {
- x->ameth->pkey_free(x);
- x->pkey.ptr = NULL;
+ *pop_f_prefix = 0;
+ *saved_indent = 0;
+ if (indent > 0) {
+ long i = BIO_get_indent(*out);
+
+ *saved_indent = (i < 0 ? 0 : i);
+ if (BIO_set_indent(*out, indent) <= 0) {
+ if ((*out = BIO_push(BIO_new(BIO_f_prefix()), *out)) == NULL)
+ return 0;
+ *pop_f_prefix = 1;
+ }
+ if (BIO_set_indent(*out, indent) <= 0) {
+ print_reset_indent(out, *pop_f_prefix, *saved_indent);
+ return 0;
+ }
}
-#ifndef OPENSSL_NO_ENGINE
- ENGINE_finish(x->engine);
- x->engine = NULL;
- ENGINE_finish(x->pmeth_engine);
- x->pmeth_engine = NULL;
-#endif
+ return 1;
}
static int unsup_alg(BIO *out, const EVP_PKEY *pkey, int indent,
const char *kstr)
{
- BIO_indent(out, indent, 128);
- BIO_printf(out, "%s algorithm \"%s\" unsupported\n",
- kstr, OBJ_nid2ln(pkey->type));
- return 1;
+ return BIO_indent(out, indent, 128)
+ && BIO_printf(out, "%s algorithm \"%s\" unsupported\n",
+ kstr, OBJ_nid2ln(pkey->type)) > 0;
+}
+
+static int print_pkey(const EVP_PKEY *pkey, BIO *out, int indent,
+ const char *propquery /* For provided serialization */,
+ int (*legacy_print)(BIO *out, const EVP_PKEY *pkey,
+ int indent, ASN1_PCTX *pctx),
+ ASN1_PCTX *legacy_pctx /* For legacy print */)
+{
+ int pop_f_prefix;
+ long saved_indent;
+ OSSL_SERIALIZER_CTX *ctx = NULL;
+ int ret = -2; /* default to unsupported */
+
+ if (!print_set_indent(&out, &pop_f_prefix, &saved_indent, indent))
+ return 0;
+
+ ctx = OSSL_SERIALIZER_CTX_new_by_EVP_PKEY(pkey, propquery);
+ if (OSSL_SERIALIZER_CTX_get_serializer(ctx) != NULL)
+ ret = OSSL_SERIALIZER_to_bio(ctx, out);
+ OSSL_SERIALIZER_CTX_free(ctx);
+
+ if (ret != -2)
+ goto end;
+
+ /* legacy fallback */
+ if (legacy_print != NULL)
+ ret = legacy_print(out, pkey, 0, legacy_pctx);
+ else
+ ret = unsup_alg(out, pkey, 0, "Public Key");
+
+ 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)
{
- if (pkey->ameth && pkey->ameth->pub_print)
- return pkey->ameth->pub_print(out, pkey, indent, pctx);
-
- return unsup_alg(out, pkey, indent, "Public Key");
+ return print_pkey(pkey, out, indent, OSSL_SERIALIZER_PUBKEY_TO_TEXT_PQ,
+ (pkey->ameth != NULL ? pkey->ameth->pub_print : NULL),
+ pctx);
}
int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx)
{
- if (pkey->ameth && pkey->ameth->priv_print)
- return pkey->ameth->priv_print(out, pkey, indent, pctx);
-
- return unsup_alg(out, pkey, indent, "Private Key");
+ return print_pkey(pkey, out, indent, OSSL_SERIALIZER_PrivateKey_TO_TEXT_PQ,
+ (pkey->ameth != NULL ? pkey->ameth->priv_print : NULL),
+ pctx);
}
int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx)
{
- if (pkey->ameth && pkey->ameth->param_print)
- return pkey->ameth->param_print(out, pkey, indent, pctx);
- return unsup_alg(out, pkey, indent, "Parameters");
+ return print_pkey(pkey, out, indent, OSSL_SERIALIZER_Parameters_TO_TEXT_PQ,
+ (pkey->ameth != NULL ? pkey->ameth->param_print : NULL),
+ pctx);
}
static int evp_pkey_asn1_ctrl(EVP_PKEY *pkey, int op, int arg1, void *arg2)
return evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_DEFAULT_MD_NID, 0, pnid);
}
+int EVP_PKEY_supports_digest_nid(EVP_PKEY *pkey, int nid)
+{
+ int rv, default_nid;
+
+ rv = evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_SUPPORTS_MD_NID, nid, NULL);
+ if (rv == -2) {
+ /*
+ * If there is a mandatory default digest and this isn't it, then
+ * the answer is 'no'.
+ */
+ rv = EVP_PKEY_get_default_digest_nid(pkey, &default_nid);
+ if (rv == 2)
+ return (nid == default_nid);
+ /* zero is an error from EVP_PKEY_get_default_digest_nid() */
+ if (rv == 0)
+ return -1;
+ }
+ return rv;
+}
+
int EVP_PKEY_set1_tls_encodedpoint(EVP_PKEY *pkey,
const unsigned char *pt, size_t ptlen)
{
return 0;
return rv;
}
+
+#endif /* FIPS_MODE */
+
+/*- All methods below can also be used in FIPS_MODE */
+
+EVP_PKEY *EVP_PKEY_new(void)
+{
+ EVP_PKEY *ret = OPENSSL_zalloc(sizeof(*ret));
+
+ if (ret == NULL) {
+ EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ ret->type = EVP_PKEY_NONE;
+ ret->save_type = EVP_PKEY_NONE;
+ ret->references = 1;
+ ret->save_parameters = 1;
+ ret->lock = CRYPTO_THREAD_lock_new();
+ if (ret->lock == NULL) {
+ EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE);
+ OPENSSL_free(ret);
+ return NULL;
+ }
+ return ret;
+}
+
+int EVP_PKEY_up_ref(EVP_PKEY *pkey)
+{
+ int i;
+
+ if (CRYPTO_UP_REF(&pkey->references, &i, pkey->lock) <= 0)
+ return 0;
+
+ REF_PRINT_COUNT("EVP_PKEY", pkey);
+ REF_ASSERT_ISNT(i < 2);
+ return ((i > 1) ? 1 : 0);
+}
+
+static void evp_pkey_free_it(EVP_PKEY *x)
+{
+ /* internal function; x is never NULL */
+
+ evp_keymgmt_clear_pkey_cache(x);
+
+ if (x->ameth && x->ameth->pkey_free) {
+ x->ameth->pkey_free(x);
+ x->pkey.ptr = NULL;
+ }
+#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
+ ENGINE_finish(x->engine);
+ x->engine = NULL;
+ ENGINE_finish(x->pmeth_engine);
+ x->pmeth_engine = NULL;
+#endif
+}
+
+void EVP_PKEY_free(EVP_PKEY *x)
+{
+ int i;
+
+ if (x == NULL)
+ return;
+
+ CRYPTO_DOWN_REF(&x->references, &i, x->lock);
+ REF_PRINT_COUNT("EVP_PKEY", x);
+ if (i > 0)
+ return;
+ REF_ASSERT_ISNT(i < 0);
+ evp_pkey_free_it(x);
+ CRYPTO_THREAD_lock_free(x->lock);
+#ifndef FIPS_MODE
+ sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free);
+#endif
+ OPENSSL_free(x);
+}
+
+/* TODO (3.0) : Needs to call getparams fo non legacy case */
+int EVP_PKEY_size(const EVP_PKEY *pkey)
+{
+ if (pkey && pkey->ameth && pkey->ameth->pkey_size)
+ return pkey->ameth->pkey_size(pkey);
+ return 0;
+}
+