diff options
author | Wangchong Zhou <fffonion@gmail.com> | 2022-10-28 11:47:50 +0800 |
---|---|---|
committer | Tomas Mraz <tomas@openssl.org> | 2022-11-04 13:31:44 +0100 |
commit | f5a10d5cc19215ab22be55b4a2ee1e41bd38fb14 (patch) | |
tree | 7cd009264f10bf4ba8727e75b3644d26cc77db70 | |
parent | 119b7b5f2ad7efcf273f395e7633747f56ff3f95 (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.c | 8 | ||||
-rw-r--r-- | test/evp_extra_test.c | 76 |
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; } |