]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Check for private key existence before calling eddsa sign functions
authorWangchong Zhou <fffonion@gmail.com>
Fri, 28 Oct 2022 03:47:50 +0000 (11:47 +0800)
committerTomas Mraz <tomas@openssl.org>
Fri, 4 Nov 2022 12:31:44 +0000 (13:31 +0100)
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)

providers/implementations/signature/eddsa_sig.c
test/evp_extra_test.c

index 0229dd74d665dc03323c808173f5eca4c90516ec..f678e64cf8dd91f4576023dfcb3d89462c88c225 100644 (file)
@@ -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) {
index 3115c2d5b2a76ecd56b6e3239913137315800555..113a7e9f8b06d159277356049151bf6c7956adfd 100644 (file)
@@ -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;
 }