[openssl-commits] [openssl] master update
Dr. Stephen Henson
steve at openssl.org
Wed Oct 11 23:06:13 UTC 2017
The branch master has been updated
via 8e826a339f8cda20a4311fa88a1de782972cf40d (commit)
via e3662075c3bf3db9b1d2dbf7e165b820873a55b4 (commit)
via 3f8b368a270c928e92c6b06cbe8002c343aedfcf (commit)
via d19b01ad79f9e2aac5c87496b5ca5f80016daeb7 (commit)
via 918a27facd3558444c69b1edbedb49478e82dff5 (commit)
via c2976edf4b22691d8bebb0e3ca2db18b3d0c71c6 (commit)
from e913d11f444e0b46ec1ebbf3340813693f4d869d (commit)
- Log -----------------------------------------------------------------
commit 8e826a339f8cda20a4311fa88a1de782972cf40d
Author: Dr. Stephen Henson <steve at openssl.org>
Date: Tue Oct 10 13:42:24 2017 +0100
Document EVP_PKEY_set1_engine()
Reviewed-by: Matt Caswell <matt at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4503)
commit e3662075c3bf3db9b1d2dbf7e165b820873a55b4
Author: Dr. Stephen Henson <steve at openssl.org>
Date: Mon Oct 9 23:24:51 2017 +0100
Add EVP_PKEY_METHOD redirection test
Reviewed-by: Matt Caswell <matt at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4503)
commit 3f8b368a270c928e92c6b06cbe8002c343aedfcf
Author: Dr. Stephen Henson <steve at openssl.org>
Date: Tue Oct 10 13:31:04 2017 +0100
make update
Reviewed-by: Matt Caswell <matt at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4503)
commit d19b01ad79f9e2aac5c87496b5ca5f80016daeb7
Author: Dr. Stephen Henson <steve at openssl.org>
Date: Mon Oct 9 15:21:11 2017 +0100
Add EVP_PKEY_set1_engine() function.
Add an ENGINE to EVP_PKEY structure which can be used for cryptographic
operations: this will typically be used by an HSM key to redirect calls
to a custom EVP_PKEY_METHOD.
Reviewed-by: Matt Caswell <matt at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4503)
commit 918a27facd3558444c69b1edbedb49478e82dff5
Author: Dr. Stephen Henson <steve at openssl.org>
Date: Mon Oct 9 23:24:26 2017 +0100
Fix memory leak on lookup failure
Reviewed-by: Matt Caswell <matt at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4503)
commit c2976edf4b22691d8bebb0e3ca2db18b3d0c71c6
Author: Dr. Stephen Henson <steve at openssl.org>
Date: Mon Oct 9 14:37:21 2017 +0100
Don't ignore passed ENGINE.
If we are passed an ENGINE to use in int_ctx_new e.g. via EVP_PKEY_CTX_new()
use it instead of the default.
Reviewed-by: Matt Caswell <matt at openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4503)
-----------------------------------------------------------------------
Summary of changes:
crypto/err/openssl.txt | 1 +
crypto/evp/evp_err.c | 2 +
crypto/evp/p_lib.c | 26 +++++-
crypto/evp/pmeth_lib.c | 10 ++-
crypto/include/internal/evp_int.h | 1 +
doc/man3/EVP_PKEY_set1_RSA.pod | 19 ++++-
include/openssl/evp.h | 3 +
include/openssl/evperr.h | 1 +
test/enginetest.c | 170 ++++++++++++++++++++++++++++++++++++++
util/libcrypto.num | 1 +
10 files changed, 225 insertions(+), 9 deletions(-)
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 58b9019..f711dac 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -689,6 +689,7 @@ EVP_F_EVP_PKEY_KEYGEN_INIT:147:EVP_PKEY_keygen_init
EVP_F_EVP_PKEY_NEW:106:EVP_PKEY_new
EVP_F_EVP_PKEY_PARAMGEN:148:EVP_PKEY_paramgen
EVP_F_EVP_PKEY_PARAMGEN_INIT:149:EVP_PKEY_paramgen_init
+EVP_F_EVP_PKEY_SET1_ENGINE:187:EVP_PKEY_set1_engine
EVP_F_EVP_PKEY_SIGN:140:EVP_PKEY_sign
EVP_F_EVP_PKEY_SIGN_INIT:141:EVP_PKEY_sign_init
EVP_F_EVP_PKEY_VERIFY:142:EVP_PKEY_verify
diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c
index cc32a3b..bb3abe3 100644
--- a/crypto/evp/evp_err.c
+++ b/crypto/evp/evp_err.c
@@ -95,6 +95,8 @@ static const ERR_STRING_DATA EVP_str_functs[] = {
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_PARAMGEN, 0), "EVP_PKEY_paramgen"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_PARAMGEN_INIT, 0),
"EVP_PKEY_paramgen_init"},
+ {ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_SET1_ENGINE, 0),
+ "EVP_PKEY_set1_engine"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_SIGN, 0), "EVP_PKEY_sign"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_SIGN_INIT, 0), "EVP_PKEY_sign_init"},
{ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_VERIFY, 0), "EVP_PKEY_verify"},
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
index 7453937..f0c3075 100644
--- a/crypto/evp/p_lib.c
+++ b/crypto/evp/p_lib.c
@@ -188,9 +188,11 @@ static int pkey_set_type(EVP_PKEY *pkey, int type, const char *str, int len)
if ((type == pkey->save_type) && pkey->ameth)
return 1;
#ifndef OPENSSL_NO_ENGINE
- /* If we have an ENGINE release it */
+ /* If we have ENGINEs release them */
ENGINE_finish(pkey->engine);
pkey->engine = NULL;
+ ENGINE_finish(pkey->pmeth_engine);
+ pkey->pmeth_engine = NULL;
#endif
}
if (str)
@@ -224,7 +226,25 @@ int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len)
{
return pkey_set_type(pkey, EVP_PKEY_NONE, str, len);
}
-
+#ifndef OPENSSL_NO_ENGINE
+int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e)
+{
+ if (e != NULL) {
+ if (!ENGINE_init(e)) {
+ EVPerr(EVP_F_EVP_PKEY_SET1_ENGINE, ERR_R_ENGINE_LIB);
+ return 0;
+ }
+ if (ENGINE_get_pkey_meth(e, pkey->type) == NULL) {
+ ENGINE_finish(e);
+ EVPerr(EVP_F_EVP_PKEY_SET1_ENGINE, EVP_R_UNSUPPORTED_ALGORITHM);
+ return 0;
+ }
+ }
+ ENGINE_finish(pkey->pmeth_engine);
+ pkey->pmeth_engine = e;
+ return 1;
+}
+#endif
int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key)
{
if (pkey == NULL || !EVP_PKEY_set_type(pkey, type))
@@ -443,6 +463,8 @@ static void EVP_PKEY_free_it(EVP_PKEY *x)
#ifndef OPENSSL_NO_ENGINE
ENGINE_finish(x->engine);
x->engine = NULL;
+ ENGINE_finish(x->pmeth_engine);
+ x->pmeth_engine = NULL;
#endif
}
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c
index 2b9b8a9..37c5e85 100644
--- a/crypto/evp/pmeth_lib.c
+++ b/crypto/evp/pmeth_lib.c
@@ -105,16 +105,17 @@ static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id)
id = pkey->ameth->pkey_id;
}
#ifndef OPENSSL_NO_ENGINE
- if (pkey && pkey->engine)
- e = pkey->engine;
+ if (e == NULL && pkey != NULL)
+ e = pkey->pmeth_engine != NULL ? pkey->pmeth_engine : pkey->engine;
/* Try to find an ENGINE which implements this method */
if (e) {
if (!ENGINE_init(e)) {
EVPerr(EVP_F_INT_CTX_NEW, ERR_R_ENGINE_LIB);
return NULL;
}
- } else
+ } else {
e = ENGINE_get_pkey_meth_engine(id);
+ }
/*
* If an ENGINE handled this method look it up. Otherwise use internal
@@ -128,6 +129,9 @@ static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id)
pmeth = EVP_PKEY_meth_find(id);
if (pmeth == NULL) {
+#ifndef OPENSSL_NO_ENGINE
+ ENGINE_finish(e);
+#endif
EVPerr(EVP_F_INT_CTX_NEW, EVP_R_UNSUPPORTED_ALGORITHM);
return NULL;
}
diff --git a/crypto/include/internal/evp_int.h b/crypto/include/internal/evp_int.h
index ccfa97c..f409400 100644
--- a/crypto/include/internal/evp_int.h
+++ b/crypto/include/internal/evp_int.h
@@ -369,6 +369,7 @@ struct evp_pkey_st {
CRYPTO_REF_COUNT references;
const EVP_PKEY_ASN1_METHOD *ameth;
ENGINE *engine;
+ ENGINE *pmeth_engine; /* If not NULL public key ENGINE to use */
union {
void *ptr;
# ifndef OPENSSL_NO_RSA
diff --git a/doc/man3/EVP_PKEY_set1_RSA.pod b/doc/man3/EVP_PKEY_set1_RSA.pod
index e1b7110..884cf91 100644
--- a/doc/man3/EVP_PKEY_set1_RSA.pod
+++ b/doc/man3/EVP_PKEY_set1_RSA.pod
@@ -5,10 +5,9 @@
EVP_PKEY_set1_RSA, EVP_PKEY_set1_DSA, EVP_PKEY_set1_DH, EVP_PKEY_set1_EC_KEY,
EVP_PKEY_get1_RSA, EVP_PKEY_get1_DSA, EVP_PKEY_get1_DH, EVP_PKEY_get1_EC_KEY,
EVP_PKEY_get0_RSA, EVP_PKEY_get0_DSA, EVP_PKEY_get0_DH, EVP_PKEY_get0_EC_KEY,
-EVP_PKEY_assign_RSA, EVP_PKEY_assign_DSA, EVP_PKEY_assign_DH, EVP_PKEY_assign_EC_KEY,
-EVP_PKEY_get0_hmac,
-EVP_PKEY_type, EVP_PKEY_id, EVP_PKEY_base_id
-- EVP_PKEY assignment functions
+EVP_PKEY_assign_RSA, EVP_PKEY_assign_DSA, EVP_PKEY_assign_DH,
+EVP_PKEY_assign_EC_KEY, EVP_PKEY_get0_hmac, EVP_PKEY_type, EVP_PKEY_id,
+EVP_PKEY_base_id, EVP_PKEY_set1_engine - EVP_PKEY assignment functions
=head1 SYNOPSIS
@@ -39,6 +38,8 @@ EVP_PKEY_type, EVP_PKEY_id, EVP_PKEY_base_id
int EVP_PKEY_base_id(const EVP_PKEY *pkey);
int EVP_PKEY_type(int type);
+ int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *engine);
+
=head1 DESCRIPTION
EVP_PKEY_set1_RSA(), EVP_PKEY_set1_DSA(), EVP_PKEY_set1_DH() and
@@ -72,6 +73,11 @@ often seen in practice.
EVP_PKEY_type() returns the underlying type of the NID B<type>. For example
EVP_PKEY_type(EVP_PKEY_RSA2) will return B<EVP_PKEY_RSA>.
+EVP_PKEY_set1_engine() sets the ENGINE handling B<pkey> to B<engine>. It
+must be called after the key algorithm and components are set up.
+If B<engine> does not include an B<EVP_PKEY_METHOD> for B<pkey> an
+error occurs.
+
=head1 NOTES
In accordance with the OpenSSL naming convention the key obtained
@@ -89,6 +95,9 @@ Previous versions of this document suggested using EVP_PKEY_type(pkey->type)
to determine the type of a key. Since B<EVP_PKEY> is now opaque this
is no longer possible: the equivalent is EVP_PKEY_base_id(pkey).
+EVP_PKEY_set1_engine() is typically used by an ENGINE returning an HSM
+key as part of its routine to load a private key.
+
=head1 RETURN VALUES
EVP_PKEY_set1_RSA(), EVP_PKEY_set1_DSA(), EVP_PKEY_set1_DH() and
@@ -104,6 +113,8 @@ and EVP_PKEY_assign_EC_KEY() return 1 for success and 0 for failure.
EVP_PKEY_base_id(), EVP_PKEY_id() and EVP_PKEY_type() return a key
type or B<NID_undef> (equivalently B<EVP_PKEY_NONE>) on error.
+EVP_PKEY_set1_engine() returns 1 for success and 0 for failure.
+
=head1 SEE ALSO
L<EVP_PKEY_new(3)>
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index 34c009a..40ed8d2 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -978,6 +978,9 @@ int EVP_PKEY_security_bits(const EVP_PKEY *pkey);
int EVP_PKEY_size(EVP_PKEY *pkey);
int EVP_PKEY_set_type(EVP_PKEY *pkey, int type);
int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len);
+# ifndef OPENSSL_NO_ENGINE
+int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e);
+# endif
int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key);
void *EVP_PKEY_get0(const EVP_PKEY *pkey);
const unsigned char *EVP_PKEY_get0_hmac(const EVP_PKEY *pkey, size_t *len);
diff --git a/include/openssl/evperr.h b/include/openssl/evperr.h
index 9bb2bca..222ba3f 100644
--- a/include/openssl/evperr.h
+++ b/include/openssl/evperr.h
@@ -82,6 +82,7 @@ int ERR_load_EVP_strings(void);
# define EVP_F_EVP_PKEY_NEW 106
# define EVP_F_EVP_PKEY_PARAMGEN 148
# define EVP_F_EVP_PKEY_PARAMGEN_INIT 149
+# define EVP_F_EVP_PKEY_SET1_ENGINE 187
# define EVP_F_EVP_PKEY_SIGN 140
# define EVP_F_EVP_PKEY_SIGN_INIT 141
# define EVP_F_EVP_PKEY_VERIFY 142
diff --git a/test/enginetest.c b/test/enginetest.c
index 4e78277..be57f16 100644
--- a/test/enginetest.c
+++ b/test/enginetest.c
@@ -18,6 +18,7 @@
# include <openssl/buffer.h>
# include <openssl/crypto.h>
# include <openssl/engine.h>
+# include <openssl/rsa.h>
# include <openssl/err.h>
static void display_engine_list(void)
@@ -175,6 +176,174 @@ static int test_engines(void)
ENGINE_free(block[loop]);
return to_return;
}
+
+/* Test EVP_PKEY method */
+static EVP_PKEY_METHOD *test_rsa = NULL;
+
+static int called_encrypt = 0;
+
+/* Test function to check operation has been redirected */
+static int test_encrypt(EVP_PKEY_CTX *ctx, unsigned char *sig,
+ size_t *siglen, const unsigned char *tbs, size_t tbslen)
+{
+ called_encrypt = 1;
+ return 1;
+}
+
+static int test_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth,
+ const int **pnids, int nid)
+{
+ static const int rnid = EVP_PKEY_RSA;
+ if (pmeth == NULL) {
+ *pnids = &rnid;
+ return 1;
+ }
+
+ if (nid == EVP_PKEY_RSA) {
+ *pmeth = test_rsa;
+ return 1;
+ }
+
+ *pmeth = NULL;
+ return 0;
+}
+
+/* Return a test EVP_PKEY value */
+
+static EVP_PKEY *get_test_pkey(void)
+{
+ static unsigned char n[] =
+ "\x00\xAA\x36\xAB\xCE\x88\xAC\xFD\xFF\x55\x52\x3C\x7F\xC4\x52\x3F"
+ "\x90\xEF\xA0\x0D\xF3\x77\x4A\x25\x9F\x2E\x62\xB4\xC5\xD9\x9C\xB5"
+ "\xAD\xB3\x00\xA0\x28\x5E\x53\x01\x93\x0E\x0C\x70\xFB\x68\x76\x93"
+ "\x9C\xE6\x16\xCE\x62\x4A\x11\xE0\x08\x6D\x34\x1E\xBC\xAC\xA0\xA1"
+ "\xF5";
+ static unsigned char e[] = "\x11";
+
+ RSA *rsa = RSA_new();
+ EVP_PKEY *pk = EVP_PKEY_new();
+
+ if (rsa == NULL || pk == NULL || !EVP_PKEY_assign_RSA(pk, rsa)) {
+ RSA_free(rsa);
+ EVP_PKEY_free(pk);
+ return NULL;
+ }
+
+ if (!RSA_set0_key(rsa, BN_bin2bn(n, sizeof(n)-1, NULL),
+ BN_bin2bn(e, sizeof(e)-1, NULL), NULL)) {
+ EVP_PKEY_free(pk);
+ return NULL;
+ }
+
+ return pk;
+}
+
+static int test_redirect(void)
+{
+ const unsigned char pt[] = "Hello World\n";
+ unsigned char *tmp = NULL;
+ size_t len;
+ EVP_PKEY_CTX *ctx = NULL;
+ ENGINE *e = NULL;
+ EVP_PKEY *pkey = NULL;
+
+ int to_return = 0;
+
+ if (!TEST_ptr(pkey = get_test_pkey()))
+ goto err;
+
+ len = EVP_PKEY_size(pkey);
+ if (!TEST_ptr(tmp = OPENSSL_malloc(len)))
+ goto err;
+
+ if (!TEST_ptr(ctx = EVP_PKEY_CTX_new(pkey, NULL)))
+ goto err;
+ TEST_info("EVP_PKEY_encrypt test: no redirection");
+ /* Encrypt some data: should succeed but not be redirected */
+ if (!TEST_int_gt(EVP_PKEY_encrypt_init(ctx), 0)
+ || !TEST_int_gt(EVP_PKEY_encrypt(ctx, tmp, &len, pt, sizeof(pt)), 0)
+ || !TEST_false(called_encrypt))
+ goto err;
+ EVP_PKEY_CTX_free(ctx);
+ ctx = NULL;
+
+ /* Create a test ENGINE */
+ if (!TEST_ptr(e = ENGINE_new())
+ || !TEST_true(ENGINE_set_id(e, "Test redirect engine"))
+ || !TEST_true(ENGINE_set_name(e, "Test redirect engine")))
+ goto err;
+
+ /*
+ * Try to create a context for this engine and test key.
+ * Try setting test key engine. Both should fail because the
+ * engine has no public key methods.
+ */
+ if (!TEST_ptr_null(EVP_PKEY_CTX_new(pkey, e))
+ || !TEST_int_le(EVP_PKEY_set1_engine(pkey, e), 0))
+ goto err;
+
+ /* Setup an empty test EVP_PKEY_METHOD and set callback to return it */
+ if (!TEST_ptr(test_rsa = EVP_PKEY_meth_new(EVP_PKEY_RSA, 0)))
+ goto err;
+ ENGINE_set_pkey_meths(e, test_pkey_meths);
+
+ /* Getting a context for test ENGINE should now succeed */
+ if (!TEST_ptr(ctx = EVP_PKEY_CTX_new(pkey, e)))
+ goto err;
+ /* Encrypt should fail because operation is not supported */
+ if (!TEST_int_le(EVP_PKEY_encrypt_init(ctx), 0))
+ goto err;
+ EVP_PKEY_CTX_free(ctx);
+ ctx = NULL;
+
+ /* Add test encrypt operation to method */
+ EVP_PKEY_meth_set_encrypt(test_rsa, 0, test_encrypt);
+
+ TEST_info("EVP_PKEY_encrypt test: redirection via EVP_PKEY_CTX_new()");
+ if (!TEST_ptr(ctx = EVP_PKEY_CTX_new(pkey, e)))
+ goto err;
+ /* Encrypt some data: should succeed and be redirected */
+ if (!TEST_int_gt(EVP_PKEY_encrypt_init(ctx), 0)
+ || !TEST_int_gt(EVP_PKEY_encrypt(ctx, tmp, &len, pt, sizeof(pt)), 0)
+ || !TEST_true(called_encrypt))
+ goto err;
+
+ EVP_PKEY_CTX_free(ctx);
+ ctx = NULL;
+ called_encrypt = 0;
+
+ /* Create context with default engine: should not be redirected */
+ if (!TEST_ptr(ctx = EVP_PKEY_CTX_new(pkey, NULL))
+ || !TEST_int_gt(EVP_PKEY_encrypt_init(ctx), 0)
+ || !TEST_int_gt(EVP_PKEY_encrypt(ctx, tmp, &len, pt, sizeof(pt)), 0)
+ || !TEST_false(called_encrypt))
+ goto err;
+
+ EVP_PKEY_CTX_free(ctx);
+ ctx = NULL;
+
+ /* Set engine explicitly for test key */
+ if (!TEST_true(EVP_PKEY_set1_engine(pkey, e)))
+ goto err;
+
+ TEST_info("EVP_PKEY_encrypt test: redirection via EVP_PKEY_set1_engine()");
+
+ /* Create context with default engine: should be redirected now */
+ if (!TEST_ptr(ctx = EVP_PKEY_CTX_new(pkey, NULL))
+ || !TEST_int_gt(EVP_PKEY_encrypt_init(ctx), 0)
+ || !TEST_int_gt(EVP_PKEY_encrypt(ctx, tmp, &len, pt, sizeof(pt)), 0)
+ || !TEST_true(called_encrypt))
+ goto err;
+
+ to_return = 1;
+
+ err:
+ EVP_PKEY_CTX_free(ctx);
+ EVP_PKEY_free(pkey);
+ ENGINE_free(e);
+ OPENSSL_free(tmp);
+ return to_return;
+}
#endif
int setup_tests(void)
@@ -183,6 +352,7 @@ int setup_tests(void)
TEST_note("No ENGINE support");
#else
ADD_TEST(test_engines);
+ ADD_TEST(test_redirect);
#endif
return 1;
}
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 5343aed..548716d 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4400,3 +4400,4 @@ EVP_PKEY_meth_remove 4343 1_1_1 EXIST::FUNCTION:
OPENSSL_sk_reserve 4344 1_1_1 EXIST::FUNCTION:
CRYPTO_atomic_read 4345 1_1_1 EXIST::FUNCTION:
CRYPTO_atomic_write 4346 1_1_1 EXIST::FUNCTION:
+EVP_PKEY_set1_engine 4347 1_1_0g EXIST::FUNCTION:ENGINE
More information about the openssl-commits
mailing list