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, &params)) 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;
}



Reply via email to