Hello The attached patch fixes an issue identified during a discussion on the users list here:
http://openssl.6102.n7.nabble.com/Problem-with-DSA-signing-verification-td47553.html If the verification of a DSA signature fails then an error is added to the OpenSSL error stack erroneously - no error has actually occurred, just a verification failure. The attached patch has been tested and works against the latest git versions for 1.1, 1.0.2 and 1.0.1. Also attached is the code I used to test this which signs a message using DSA and then deliberately forces a verification failure. Output before the patch: Sign Success 140173552527040:error:0A071003:dsa routines:DSA_do_verify:BN lib:dsa_ossl.c:454: Verify Failed Output after patch: Sign Success Verify Failed Matt
>From 48a66681367f80016360c5bff47744fff4132ed3 Mon Sep 17 00:00:00 2001 From: Matt Caswell <fr...@baggins.org> Date: Fri, 6 Dec 2013 14:08:27 +0000 Subject: [PATCH] Fixed spurious error message in the event of a DSA verification failure --- crypto/dsa/dsa_ossl.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c index edaee59..846e162 100644 --- a/crypto/dsa/dsa_ossl.c +++ b/crypto/dsa/dsa_ossl.c @@ -449,9 +449,7 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, ret=(BN_ucmp(&u1, sig->r) == 0); err: - /* XXX: surely this is wrong - if ret is 0, it just didn't verify; - there is no error in BN. Test should be ret == -1 (Ben) */ - if (ret != 1) DSAerr(DSA_F_DSA_DO_VERIFY,ERR_R_BN_LIB); + if (ret < 0) DSAerr(DSA_F_DSA_DO_VERIFY,ERR_R_BN_LIB); if (ctx != NULL) BN_CTX_free(ctx); BN_free(&u1); BN_free(&u2); -- 1.8.3.2
#include <openssl/evp.h> #include <openssl/dsa.h> #include <openssl/obj_mac.h> #include <string.h> #include <openssl/err.h> EVP_PKEY *generate_key(); int main(int arc, char *argv[]) { unsigned char *sig; size_t slen; EVP_PKEY *key; char *msg = "message1"; char *msg2 = "message2"; int ret; /* Initialise the library */ ERR_load_crypto_strings(); key = generate_key(); if(key == NULL) { printf("Error generating key\n"); goto err; } /* Sign the message */ if(doSign(key, msg, &sig, &slen)) { printf("Sign Success\n"); } else { printf("Sign Error\n"); goto err; } /* Verify the altered message */ ret= doVerify(key, msg2, sig, slen); if(ret>0) { printf("Verify Success\n"); } else if(ret == 0) { printf("Verify Failed\n"); } else { printf("Verify Error\n"); } /* Clean up */ err: ERR_print_errors_fp(stderr); ERR_free_strings(); } EVP_PKEY *generate_key() { EVP_PKEY_CTX *pctx = NULL, *kctx = NULL; EVP_PKEY *params = NULL, *key = NULL; /* Create the context for generating the parameters */ if(!(pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL))) goto err; if(!EVP_PKEY_paramgen_init(pctx)) goto err; if(!EVP_PKEY_CTX_set_dsa_paramgen_bits(pctx, 2048)) goto err; /* Generate parameters */ if (!EVP_PKEY_paramgen(pctx, ¶ms)) goto err; /* Create context for the key generation */ if(!(kctx = EVP_PKEY_CTX_new(params, NULL))) goto err; /* Generate the key */ if(!EVP_PKEY_keygen_init(kctx)) goto err; if (!EVP_PKEY_keygen(kctx, &key)) key = NULL; err: ERR_print_errors_fp(stderr); if(pctx) EVP_PKEY_CTX_free(pctx); if(params) EVP_PKEY_free(params); if(kctx) EVP_PKEY_CTX_free(kctx); return key; } int doSign(EVP_PKEY *key, char * msg, unsigned char **sig, size_t *slen) { EVP_MD_CTX *mdctx = NULL; int ret = 0; *sig = NULL; /* Create the Message Digest Context */ if(!(mdctx = EVP_MD_CTX_create())) goto err; /* if(!EVP_SignInit_ex(mdctx, EVP_sha256(), NULL)) goto err; if(!EVP_SignUpdate(mdctx, msg, strlen(msg))) goto err; if(!EVP_SignFinal(mdctx, *sig, s, key)) goto err; */ /* Initialise the DigestSign operation */ if(1 != EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), NULL, key)) goto err; /* Call update with the message */ if(1 != EVP_DigestSignUpdate(mdctx, msg, strlen(msg))) goto err; /* Finalise the Digestsign operation */ if(1 != EVP_DigestSignFinal(mdctx, *sig, slen)) goto err; if(!(*sig = OPENSSL_malloc(sizeof(unsigned char) * (*slen)))) goto err; if(1 != EVP_DigestSignFinal(mdctx, *sig, slen)) goto err; /* Success */ ret = 1; err: if(ret != 1) { ERR_print_errors_fp(stderr); } if(*sig && !ret) OPENSSL_free(*sig); if(mdctx) EVP_MD_CTX_destroy(mdctx); return ret; } int doVerify(EVP_PKEY *key, char * msg, unsigned char *sig, size_t slen) { EVP_MD_CTX *mdctx = NULL; int ret = 0; unsigned char *sigtmp = NULL; size_t sigtmplen; if(!(mdctx = EVP_MD_CTX_create())) goto err; /* if(!EVP_SignInit_ex(mdctx, EVP_sha256(), NULL)) goto err; if(!EVP_SignUpdate(mdctx, msg, strlen(msg))) goto err; if(!EVP_SignFinal(mdctx, *sig, s, key)) goto err; */ if(1 != EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, key)) goto err; if(1 != EVP_DigestVerifyUpdate(mdctx, msg, strlen(msg))) goto err; ret = EVP_DigestVerifyFinal(mdctx, sig, slen); /* Success */ err: ERR_print_errors_fp(stderr); if(mdctx) EVP_MD_CTX_destroy(mdctx); if(sigtmp) OPENSSL_free(sigtmp); return ret; }