summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWangchong Zhou <fffonion@gmail.com>2022-10-28 11:47:50 +0800
committerTomas Mraz <tomas@openssl.org>2022-11-04 13:31:44 +0100
commitf5a10d5cc19215ab22be55b4a2ee1e41bd38fb14 (patch)
tree7cd009264f10bf4ba8727e75b3644d26cc77db70
parent119b7b5f2ad7efcf273f395e7633747f56ff3f95 (diff)
Check for private key existence before calling eddsa sign functions
Fixes #19524 Reviewed-by: Paul Dale <pauli@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/19525)
-rw-r--r--providers/implementations/signature/eddsa_sig.c8
-rw-r--r--test/evp_extra_test.c76
2 files changed, 83 insertions, 1 deletions
diff --git a/providers/implementations/signature/eddsa_sig.c b/providers/implementations/signature/eddsa_sig.c
index 0229dd74d6..f678e64cf8 100644
--- a/providers/implementations/signature/eddsa_sig.c
+++ b/providers/implementations/signature/eddsa_sig.c
@@ -161,6 +161,10 @@ int ed25519_digest_sign(void *vpeddsactx, unsigned char *sigret,
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
+ if (edkey->privkey == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
+ return 0;
+ }
#ifdef S390X_EC_ASM
if (S390X_CAN_SIGN(ED25519)) {
if (s390x_ed25519_digestsign(edkey, sigret, tbs, tbslen) == 0) {
@@ -198,6 +202,10 @@ int ed448_digest_sign(void *vpeddsactx, unsigned char *sigret,
ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
+ if (edkey->privkey == NULL) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
+ return 0;
+ }
#ifdef S390X_EC_ASM
if (S390X_CAN_SIGN(ED448)) {
if (s390x_ed448_digestsign(edkey, sigret, tbs, tbslen) == 0) {
diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c
index 3115c2d5b2..113a7e9f8b 100644
--- a/test/evp_extra_test.c
+++ b/test/evp_extra_test.c
@@ -31,6 +31,7 @@
#include <openssl/decoder.h>
#include <openssl/rsa.h>
#include <openssl/engine.h>
+#include <openssl/proverr.h>
#include "testutil.h"
#include "internal/nelem.h"
#include "internal/sizes.h"
@@ -4622,11 +4623,13 @@ static int test_ecx_short_keys(int tst)
EVP_PKEY *pkey;
- pkey = EVP_PKEY_new_raw_private_key(ecxnids[tst], NULL, &ecxkeydata, 1);
+ pkey = EVP_PKEY_new_raw_private_key_ex(testctx, OBJ_nid2sn(ecxnids[tst]),
+ NULL, &ecxkeydata, 1);
if (!TEST_ptr_null(pkey)) {
EVP_PKEY_free(pkey);
return 0;
}
+
return 1;
}
@@ -4647,6 +4650,73 @@ const OPTIONS *test_get_options(void)
return options;
}
+#ifndef OPENSSL_NO_EC
+/* Test that trying to sign with a public key errors out gracefully */
+static int test_ecx_not_private_key(int tst)
+{
+ EVP_PKEY *pkey = NULL;
+
+ const unsigned char msg[] = { 0x00, 0x01, 0x02, 0x03 };
+ int testresult = 0;
+ EVP_MD_CTX *ctx = NULL;
+ unsigned char *mac = NULL;
+ size_t maclen = 0;
+ unsigned char *pubkey;
+ size_t pubkeylen;
+
+ switch (keys[tst].type) {
+ case NID_X25519:
+ case NID_X448:
+ return TEST_skip("signing not supported for X25519/X448");
+ }
+
+ /* Check if this algorithm supports public keys */
+ if (keys[tst].pub == NULL)
+ return TEST_skip("no public key present");
+
+ pubkey = (unsigned char *)keys[tst].pub;
+ pubkeylen = strlen(keys[tst].pub);
+
+ pkey = EVP_PKEY_new_raw_public_key_ex(testctx, OBJ_nid2sn(keys[tst].type),
+ NULL, pubkey, pubkeylen);
+ if (!TEST_ptr(pkey))
+ goto err;
+
+ if (!TEST_ptr(ctx = EVP_MD_CTX_new()))
+ goto err;
+
+ if (EVP_DigestSignInit(ctx, NULL, NULL, NULL, pkey) != 1)
+ goto check_err;
+
+ if (EVP_DigestSign(ctx, NULL, &maclen, msg, sizeof(msg)) != 1)
+ goto check_err;
+
+ if (!TEST_ptr(mac = OPENSSL_malloc(maclen)))
+ goto err;
+
+ if (!TEST_int_eq(EVP_DigestSign(ctx, mac, &maclen, msg, sizeof(msg)), 0))
+ goto err;
+
+ check_err:
+ /*
+ * Currently only EVP_DigestSign will throw PROV_R_NOT_A_PRIVATE_KEY,
+ * but we relax the check to allow error also thrown by
+ * EVP_DigestSignInit and EVP_DigestSign.
+ */
+ if (ERR_GET_REASON(ERR_peek_error()) == PROV_R_NOT_A_PRIVATE_KEY) {
+ testresult = 1;
+ ERR_clear_error();
+ }
+
+ err:
+ EVP_MD_CTX_free(ctx);
+ OPENSSL_free(mac);
+ EVP_PKEY_free(pkey);
+
+ return testresult;
+}
+#endif /* OPENSSL_NO_EC */
+
int setup_tests(void)
{
OPTION_CHOICE o;
@@ -4782,6 +4852,10 @@ int setup_tests(void)
ADD_ALL_TESTS(test_ecx_short_keys, OSSL_NELEM(ecxnids));
+#ifndef OPENSSL_NO_EC
+ ADD_ALL_TESTS(test_ecx_not_private_key, OSSL_NELEM(keys));
+#endif
+
return 1;
}