summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2020-04-24 12:33:33 +0200
committerMatt Caswell <matt@openssl.org>2020-05-04 10:30:55 +0200
commit1c4f340dd35f0ca48e263ab85399a965e1125ac6 (patch)
tree44d1721be9e4346f773c608db6901fee200065fc /crypto
parentrand_unix.c: Ensure requests to KERN_ARND don't exceed 256 bytes. (diff)
downloadopenssl-1c4f340dd35f0ca48e263ab85399a965e1125ac6.tar.xz
openssl-1c4f340dd35f0ca48e263ab85399a965e1125ac6.zip
Make EVP_new_raw_[private|public]_key provider aware
We also introduce variants which are OPENSSL_CTX aware Reviewed-by: Shane Lontis <shane.lontis@oracle.com> (Merged from https://github.com/openssl/openssl/pull/11635)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/evp/p_lib.c171
1 files changed, 132 insertions, 39 deletions
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
index bbeb7276fe..ea74253bdd 100644
--- a/crypto/evp/p_lib.c
+++ b/crypto/evp/p_lib.c
@@ -28,6 +28,7 @@
#include <openssl/cmac.h>
#include <openssl/engine.h>
#include <openssl/params.h>
+#include <openssl/param_build.h>
#include <openssl/serializer.h>
#include <openssl/core_names.h>
@@ -320,64 +321,156 @@ int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
return -2;
}
-EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e,
- const unsigned char *priv,
- size_t len)
+
+static EVP_PKEY *new_raw_key_int(OPENSSL_CTX *libctx,
+ const char *strtype,
+ const char *propq,
+ int nidtype,
+ ENGINE *e,
+ const unsigned char *key,
+ size_t len,
+ int key_is_priv)
{
- EVP_PKEY *ret = EVP_PKEY_new();
+ EVP_PKEY *pkey = NULL;
+ EVP_PKEY_CTX *ctx = NULL;
+ const EVP_PKEY_ASN1_METHOD *ameth = NULL;
+ int result = 0;
- if (ret == NULL
- || !pkey_set_type(ret, e, type, NULL, -1, NULL)) {
- /* EVPerr already called */
- goto err;
- }
+# ifndef OPENSSL_NO_ENGINE
+ /* Check if there is an Engine for this type */
+ if (e == NULL) {
+ ENGINE *tmpe = NULL;
- if (ret->ameth->set_priv_key == NULL) {
- EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
- goto err;
- }
+ 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 (!ret->ameth->set_priv_key(ret, priv, len)) {
- EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY, EVP_R_KEY_SETUP_FAILED);
- goto err;
+ /* If tmpe is NULL then no engine is claiming to support this type */
+ if (tmpe == NULL)
+ ameth = NULL;
+
+ ENGINE_finish(tmpe);
}
+# endif
- return ret;
+ 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);
+ if (ctx == NULL) {
+ EVPerr(0, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ /* May fail if no provider available */
+ ERR_set_mark();
+ if (EVP_PKEY_key_fromdata_init(ctx) == 1) {
+ 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);
+
+ if (EVP_PKEY_fromdata(ctx, &pkey, params) != 1) {
+ EVPerr(0, EVP_R_KEY_SETUP_FAILED);
+ goto err;
+ }
- err:
- EVP_PKEY_free(ret);
- return NULL;
-}
+ EVP_PKEY_CTX_free(ctx);
-EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e,
- const unsigned char *pub,
- size_t len)
-{
- EVP_PKEY *ret = EVP_PKEY_new();
+ return pkey;
+ }
+ ERR_pop_to_mark();
+ /* else not supported so fallback to legacy */
+ }
- if (ret == NULL
- || !pkey_set_type(ret, e, type, NULL, -1, NULL)) {
- /* EVPerr already called */
+ /* Legacy code path */
+
+ pkey = EVP_PKEY_new();
+ if (pkey == NULL) {
+ EVPerr(0, ERR_R_MALLOC_FAILURE);
goto err;
}
- if (ret->ameth->set_pub_key == NULL) {
- EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY,
- EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ if (!pkey_set_type(pkey, e, nidtype, strtype, -1, NULL)) {
+ /* EVPerr already called */
goto err;
}
- if (!ret->ameth->set_pub_key(ret, pub, len)) {
- EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY, EVP_R_KEY_SETUP_FAILED);
+ if (!ossl_assert(pkey->ameth != NULL))
goto err;
- }
- return ret;
+ if (key_is_priv) {
+ if (pkey->ameth->set_priv_key == NULL) {
+ EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ goto err;
+ }
+ if (!pkey->ameth->set_priv_key(pkey, key, len)) {
+ EVPerr(0, EVP_R_KEY_SETUP_FAILED);
+ goto err;
+ }
+ } else {
+ if (pkey->ameth->set_pub_key == NULL) {
+ EVPerr(0, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+ goto err;
+ }
+
+ if (!pkey->ameth->set_pub_key(pkey, key, len)) {
+ EVPerr(0, EVP_R_KEY_SETUP_FAILED);
+ goto err;
+ }
+ }
+
+ result = 1;
err:
- EVP_PKEY_free(ret);
- return NULL;
+ if (!result) {
+ EVP_PKEY_free(pkey);
+ pkey = NULL;
+ }
+ EVP_PKEY_CTX_free(ctx);
+ return pkey;
+}
+
+EVP_PKEY *EVP_PKEY_new_raw_private_key_with_libctx(OPENSSL_CTX *libctx,
+ const char *keytype,
+ const char *propq,
+ const unsigned char *priv,
+ size_t len)
+{
+ return new_raw_key_int(libctx, keytype, propq, EVP_PKEY_NONE, NULL, priv,
+ len, 1);
+}
+
+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);
+}
+
+EVP_PKEY *EVP_PKEY_new_raw_public_key_with_libctx(OPENSSL_CTX *libctx,
+ const char *keytype,
+ const char *propq,
+ const unsigned char *pub,
+ size_t len)
+{
+ 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);
}
int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, unsigned char *priv,