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 <[email protected]>
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;
}