Skip to content

Commit

Permalink
Check for private key existence before calling eddsa sign functions
Browse files Browse the repository at this point in the history
Fixes #19524

Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from #19525)

(cherry picked from commit f5a10d5)
  • Loading branch information
fffonion authored and t8m committed Nov 4, 2022
1 parent 733084a commit db30d8f
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 1 deletion.
8 changes: 8 additions & 0 deletions providers/implementations/signature/eddsa_sig.c
Expand Up @@ -164,6 +164,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) {
Expand Down Expand Up @@ -201,6 +205,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) {
Expand Down
76 changes: 75 additions & 1 deletion test/evp_extra_test.c
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down

0 comments on commit db30d8f

Please sign in to comment.