From a2393bab41ba0343a42675adbef04c613154c424 Mon Sep 17 00:00:00 2001
From: Benjamin Dauvergne <bdauvergne@entrouvert.com>
Date: Wed, 16 Nov 2022 15:35:27 +0100
Subject: [PATCH 01/11] Use OpenSSL EVP API to work around deprecation of low
 level APIs in OpenSSL 3 (#71313)

OpenSSL API is used to sign query-string values in the SAML 2.0 Redirect binding.
Other binding only need the libxmlsec API as signature are XML DSIG signatures.
---
 lasso/id-ff/provider.c |   2 +-
 lasso/xml/private.h    |   4 +-
 lasso/xml/tools.c      | 325 ++++++++++++++++++++---------------------
 3 files changed, 162 insertions(+), 169 deletions(-)

diff --git a/lasso/id-ff/provider.c b/lasso/id-ff/provider.c
index e6bd6ba9..a4b29337 100644
--- a/lasso/id-ff/provider.c
+++ b/lasso/id-ff/provider.c
@@ -1592,7 +1592,7 @@ lasso_provider_get_key_encryption_method(const LassoProvider *provider)
 int
 lasso_provider_verify_query_signature(LassoProvider *provider, const char *message)
 {
-	int (*check)(const char *, const xmlSecKey *) = NULL;
+	int (*check)(const char *, xmlSecKey *) = NULL;
 	int rc = 0;
 	int signature_rc = 0;
 	GList *public_keys = NULL;
diff --git a/lasso/xml/private.h b/lasso/xml/private.h
index a60d064c..4aa590a4 100644
--- a/lasso/xml/private.h
+++ b/lasso/xml/private.h
@@ -218,9 +218,9 @@ xmlSecKeysMngr* lasso_load_certs_from_pem_certs_chain_file (const char *file);
 
 char* lasso_query_sign(char *query, LassoSignatureContext signature_context);
 
-int lasso_query_verify_signature(const char *query, const xmlSecKey *public_key);
+int lasso_query_verify_signature(const char *query, xmlSecKey *public_key);
 
-int lasso_saml2_query_verify_signature(const char *query, const xmlSecKey *sender_public_key);
+int lasso_saml2_query_verify_signature(const char *query, xmlSecKey *sender_public_key);
 
 char* lasso_sha1(const char *str);
 
diff --git a/lasso/xml/tools.c b/lasso/xml/tools.c
index 820c273b..bc0510c7 100644
--- a/lasso/xml/tools.c
+++ b/lasso/xml/tools.c
@@ -46,10 +46,6 @@
 #include <libxml/parserInternals.h>
 #include <libxml/xmlIO.h>
 
-#include <openssl/pem.h>
-#include <openssl/sha.h>
-#include <openssl/engine.h>
-#include <openssl/hmac.h>
 #include <openssl/evp.h>
 
 #include <xmlsec/base64.h>
@@ -60,6 +56,7 @@
 #include <xmlsec/errors.h>
 #include <xmlsec/openssl/x509.h>
 #include <xmlsec/openssl/crypto.h>
+#include <xmlsec/openssl/evp.h>
 
 #include <zlib.h>
 
@@ -481,22 +478,23 @@ char*
 lasso_query_sign(char *query, LassoSignatureContext context)
 {
 	char *digest = NULL; /* 160 bit buffer */
-	RSA *rsa = NULL;
-	DSA *dsa = NULL;
 	unsigned char *sigret = NULL;
-	unsigned int siglen = 0;
+	size_t siglen = 0;
 	xmlChar *b64_sigret = NULL, *e_b64_sigret = NULL;
 	char *new_query = NULL, *s_new_query = NULL;
 	int status = 0;
 	const xmlChar *algo_href = NULL;
-	char *hmac_key;
+	unsigned char *hmac_key;
 	size_t hmac_key_length;
-	const EVP_MD *md = NULL;
 	xmlSecKey *key;
 	xmlSecKeyData *key_data;
-	unsigned int sigret_size = 0;
 	LassoSignatureMethod sign_method;
-        lasso_error_t rc = 0;
+	lasso_error_t rc = 0;
+
+	const EVP_MD *md = NULL;
+	EVP_MD_CTX *evp_md_ctx = NULL;
+	EVP_PKEY *pkey = NULL;
+	EVP_PKEY *hmac_pkey = NULL;
 
 	g_return_val_if_fail(query != NULL, NULL);
 	g_return_val_if_fail(lasso_ok_signature_method(context.signature_method), NULL);
@@ -546,118 +544,89 @@ lasso_query_sign(char *query, LassoSignatureContext context)
 		xmlFree(BAD_CAST t);
 	}
 
-	/* build buffer digest */
+	/* define the digest algorithm */
 	switch (sign_method) {
 		case LASSO_SIGNATURE_METHOD_RSA_SHA1:
 		case LASSO_SIGNATURE_METHOD_DSA_SHA1:
-			digest = lasso_sha1(new_query);
+		case LASSO_SIGNATURE_METHOD_HMAC_SHA1:
+			md = EVP_sha1();
 			break;
 		case LASSO_SIGNATURE_METHOD_RSA_SHA256:
-			digest = lasso_sha256(new_query);
+		case LASSO_SIGNATURE_METHOD_HMAC_SHA256:
+			md = EVP_sha256();
 			break;
 		case LASSO_SIGNATURE_METHOD_RSA_SHA384:
-			digest = lasso_sha384(new_query);
+		case LASSO_SIGNATURE_METHOD_HMAC_SHA384:
+			md = EVP_sha384();
 			break;
 		case LASSO_SIGNATURE_METHOD_RSA_SHA512:
-			digest = lasso_sha512(new_query);
-		default:
+		case LASSO_SIGNATURE_METHOD_HMAC_SHA512:
+			md = EVP_sha512();
 			break;
+		case LASSO_SIGNATURE_METHOD_NONE:
+		case LASSO_SIGNATURE_METHOD_LAST:
+			g_assert_not_reached();
 	}
+
+	/* Get the signture key */
 	switch (sign_method) {
 		case LASSO_SIGNATURE_METHOD_RSA_SHA1:
-		case LASSO_SIGNATURE_METHOD_DSA_SHA1:
 		case LASSO_SIGNATURE_METHOD_RSA_SHA256:
 		case LASSO_SIGNATURE_METHOD_RSA_SHA384:
 		case LASSO_SIGNATURE_METHOD_RSA_SHA512:
-			if (digest == NULL) {
-				message(G_LOG_LEVEL_CRITICAL, "Failed to build the buffer digest");
+		case LASSO_SIGNATURE_METHOD_DSA_SHA1:
+			pkey = xmlSecOpenSSLEvpKeyDataGetEvp(key_data);
+			if (! pkey) {
+				message(G_LOG_LEVEL_CRITICAL, "Failed to get assymetric key");
 				goto done;
 			}
-		default:
-			break;
-	}
-	/* extract the OpenSSL key */
-	switch (sign_method) {
-		case LASSO_SIGNATURE_METHOD_RSA_SHA1:
-		case LASSO_SIGNATURE_METHOD_RSA_SHA256:
-		case LASSO_SIGNATURE_METHOD_RSA_SHA384:
-		case LASSO_SIGNATURE_METHOD_RSA_SHA512:
-			rsa = xmlSecOpenSSLKeyDataRsaGetRsa(key_data);
-			g_assert(rsa);
-			/* alloc memory for sigret */
-			sigret_size = RSA_size(rsa);
-			break;
-		case LASSO_SIGNATURE_METHOD_DSA_SHA1:
-			dsa = xmlSecOpenSSLKeyDataDsaGetDsa(key_data);
-			g_assert(dsa);
-			/* alloc memory for sigret */
-			sigret_size = DSA_size(dsa);
 			break;
 		case LASSO_SIGNATURE_METHOD_HMAC_SHA1:
-			md = EVP_sha1();
-			sigret_size = EVP_MD_size(md);
-			break;
 		case LASSO_SIGNATURE_METHOD_HMAC_SHA256:
-			md = EVP_sha256();
-			sigret_size = EVP_MD_size(md);
-			break;
 		case LASSO_SIGNATURE_METHOD_HMAC_SHA384:
-			md = EVP_sha384();
-			sigret_size = EVP_MD_size(md);
-			break;
 		case LASSO_SIGNATURE_METHOD_HMAC_SHA512:
-			md = EVP_sha512();
-			sigret_size = EVP_MD_size(md);
+			if ((rc = lasso_get_hmac_key(key, (void**)&hmac_key,
+										 &hmac_key_length))) {
+				message(G_LOG_LEVEL_CRITICAL, "Failed to get hmac key (%s)", lasso_strerror(rc));
+				goto done;
+			}
+			g_assert(hmac_key);
+			hmac_pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, hmac_key, (int)hmac_key_length);
+			if (! hmac_key) {
+				message(G_LOG_LEVEL_CRITICAL, "EVP_PKEY_new_mac_key failed");
+				goto done;
+			}
+			pkey = hmac_pkey;
 			break;
-		default:
+		case LASSO_SIGNATURE_METHOD_LAST:
+		case LASSO_SIGNATURE_METHOD_NONE:
 			g_assert_not_reached();
 	}
-	sigret = (unsigned char *)g_malloc (sigret_size);
 
 	switch (sign_method) {
 		case LASSO_SIGNATURE_METHOD_RSA_SHA1:
-			/* sign digest message */
-			status = RSA_sign(NID_sha1, (unsigned char*)digest, SHA_DIGEST_LENGTH, sigret,
-					&siglen, rsa);
-			break;
 		case LASSO_SIGNATURE_METHOD_RSA_SHA256:
-			/* sign digest message */
-			status = RSA_sign(NID_sha256, (unsigned char*)digest, SHA256_DIGEST_LENGTH, sigret,
-					&siglen, rsa);
-			break;
 		case LASSO_SIGNATURE_METHOD_RSA_SHA384:
-			/* sign digest message */
-			status = RSA_sign(NID_sha384, (unsigned char*)digest, SHA384_DIGEST_LENGTH, sigret,
-					&siglen, rsa);
-			break;
 		case LASSO_SIGNATURE_METHOD_RSA_SHA512:
-			/* sign digest message */
-			status = RSA_sign(NID_sha512, (unsigned char*)digest, SHA512_DIGEST_LENGTH, sigret,
-					&siglen, rsa);
-			break;
 		case LASSO_SIGNATURE_METHOD_DSA_SHA1:
-			status = DSA_sign(NID_sha1, (unsigned char*)digest, SHA_DIGEST_LENGTH, sigret,
-					&siglen, dsa);
-			break;
 		case LASSO_SIGNATURE_METHOD_HMAC_SHA1:
 		case LASSO_SIGNATURE_METHOD_HMAC_SHA256:
 		case LASSO_SIGNATURE_METHOD_HMAC_SHA384:
 		case LASSO_SIGNATURE_METHOD_HMAC_SHA512:
-			if ((rc = lasso_get_hmac_key(key, (void**)&hmac_key,
-										 &hmac_key_length))) {
-				message(G_LOG_LEVEL_CRITICAL, "Failed to get hmac key (%s)", lasso_strerror(rc));
+			evp_md_ctx = EVP_MD_CTX_create();
+			if (EVP_DigestSignInit(evp_md_ctx, NULL, md, NULL, pkey) <= 0) {
+				message(G_LOG_LEVEL_CRITICAL, "EVP_DigestSignInit failed");
 				goto done;
 			}
-			g_assert(hmac_key);
-
-			/* key should be at least 128 bits long */
-			if (hmac_key_length < 16) {
-				critical("HMAC key should be at least 128 bits long");
+			if (EVP_DigestSign(evp_md_ctx, NULL, &siglen, (unsigned char*)new_query, strlen(new_query)) <= 0) {
+				message(G_LOG_LEVEL_CRITICAL, "EVP_DigestSign failed");
+				goto done;
+			}
+			sigret = g_malloc(siglen);
+			if (EVP_DigestSign(evp_md_ctx, sigret, &siglen, (unsigned char*)new_query, strlen(new_query)) <= 0) {
+				message(G_LOG_LEVEL_CRITICAL, "EVP_DigestSign failed");
 				goto done;
 			}
-
-			HMAC(md, hmac_key, hmac_key_length, (unsigned char *)new_query,
-					strlen(new_query), sigret, &siglen);
 			status = 1;
 			break;
 		case LASSO_SIGNATURE_METHOD_LAST:
@@ -665,14 +634,13 @@ lasso_query_sign(char *query, LassoSignatureContext context)
 			g_assert_not_reached();
 	}
 
-	g_assert(siglen == sigret_size);
 
 	if (status == 0) {
 		goto done;
 	}
 
 	/* Base64 encode the signature value */
-	b64_sigret = xmlSecBase64Encode(sigret, sigret_size, 0);
+	b64_sigret = xmlSecBase64Encode(sigret, siglen, 0);
 	/* escape b64_sigret */
 	e_b64_sigret = lasso_xmlURIEscapeStr((xmlChar*)b64_sigret, NULL);
 
@@ -701,7 +669,15 @@ done:
 	lasso_release(sigret);
 	lasso_release_xml_string(b64_sigret);
 	lasso_release_xml_string(e_b64_sigret);
-
+	if (evp_md_ctx) {
+		EVP_MD_CTX_free(evp_md_ctx);
+		evp_md_ctx = NULL;
+	}
+	if (hmac_pkey) {
+		EVP_PKEY_free(hmac_pkey);
+		hmac_pkey = NULL;
+		pkey = NULL;
+	}
 	return s_new_query;
 }
 
@@ -728,153 +704,162 @@ lasso_assertion_encrypt(LassoSaml2Assertion *assertion, char *recipient)
 
 static lasso_error_t
 lasso_query_verify_helper(const char *signed_content, const char *b64_signature, const char *algorithm,
-		const xmlSecKey *key)
+		xmlSecKey *key)
 {
-	RSA *rsa = NULL;
-	DSA *dsa = NULL;
 	char *digest = NULL;
-	xmlSecByte *signature = NULL;
-	int key_size = 0;
+	char *signature = NULL;
+	unsigned int signature_len = 0;
 	unsigned char *hmac_key = NULL;
 	size_t hmac_key_length = 0;
 	const EVP_MD *md = NULL;
 	lasso_error_t rc = 0;
 	LassoSignatureMethod method = LASSO_SIGNATURE_METHOD_NONE;
-	size_t digest_size = 1;
-	int type = -1;
+	EVP_PKEY *hmac_pkey = NULL;
+	unsigned char *new_signature = NULL;
+	EVP_MD_CTX *evp_md_ctx = NULL;
 
 	if (lasso_strisequal(algorithm, (char*)xmlSecHrefRsaSha1)) {
 		goto_cleanup_if_fail_with_rc(key->value->id == xmlSecOpenSSLKeyDataRsaId,
 				LASSO_DS_ERROR_INVALID_SIGALG)
-		rsa = xmlSecOpenSSLKeyDataRsaGetRsa(key->value);
-		key_size = RSA_size(rsa);
 		method = LASSO_SIGNATURE_METHOD_RSA_SHA1;
-		digest_size = SHA_DIGEST_LENGTH;
-		type = NID_sha1;
 	} else if (lasso_strisequal(algorithm, (char*)xmlSecHrefDsaSha1)) {
 		goto_cleanup_if_fail_with_rc(key->value->id == xmlSecOpenSSLKeyDataDsaId, LASSO_DS_ERROR_INVALID_SIGALG);
-		dsa = xmlSecOpenSSLKeyDataDsaGetDsa(key->value);
-		key_size = DSA_size(dsa);
 		method = LASSO_SIGNATURE_METHOD_DSA_SHA1;
-		digest_size = SHA_DIGEST_LENGTH;
-		type = NID_sha1;
 	} else if (lasso_strisequal(algorithm, (char*)xmlSecHrefRsaSha256)) {
 		goto_cleanup_if_fail_with_rc(key->value->id == xmlSecOpenSSLKeyDataRsaId,
 				LASSO_DS_ERROR_INVALID_SIGALG)
-		rsa = xmlSecOpenSSLKeyDataRsaGetRsa(key->value);
-		key_size = RSA_size(rsa);
 		method = LASSO_SIGNATURE_METHOD_RSA_SHA256;
-		digest_size = SHA256_DIGEST_LENGTH;
-		type = NID_sha256;
 	} else if (lasso_strisequal(algorithm, (char*)xmlSecHrefRsaSha384)) {
 		goto_cleanup_if_fail_with_rc(key->value->id == xmlSecOpenSSLKeyDataRsaId,
 				LASSO_DS_ERROR_INVALID_SIGALG)
-		rsa = xmlSecOpenSSLKeyDataRsaGetRsa(key->value);
-		key_size = RSA_size(rsa);
 		method = LASSO_SIGNATURE_METHOD_RSA_SHA384;
-		digest_size = SHA384_DIGEST_LENGTH;
-		type = NID_sha384;
 	} else if (lasso_strisequal(algorithm, (char*)xmlSecHrefRsaSha512)) {
 		goto_cleanup_if_fail_with_rc(key->value->id == xmlSecOpenSSLKeyDataRsaId,
 				LASSO_DS_ERROR_INVALID_SIGALG)
-		rsa = xmlSecOpenSSLKeyDataRsaGetRsa(key->value);
-		key_size = RSA_size(rsa);
 		method = LASSO_SIGNATURE_METHOD_RSA_SHA512;
-		digest_size = SHA512_DIGEST_LENGTH;
-		type = NID_sha512;
 	} else if (lasso_strisequal(algorithm, (char*)xmlSecHrefHmacSha1)) {
 		lasso_check_good_rc(lasso_get_hmac_key(key, (void**)&hmac_key, &hmac_key_length));
-		md = EVP_sha1();
-		key_size = EVP_MD_size(md);
 		method = LASSO_SIGNATURE_METHOD_HMAC_SHA1;
 	} else if (lasso_strisequal(algorithm, (char*)xmlSecHrefHmacSha256)) {
 		lasso_check_good_rc(lasso_get_hmac_key(key, (void**)&hmac_key, &hmac_key_length));
-		md = EVP_sha256();
-		key_size = EVP_MD_size(md);
 		method = LASSO_SIGNATURE_METHOD_HMAC_SHA256;
 	} else if (lasso_strisequal(algorithm, (char*)xmlSecHrefHmacSha384)) {
 		lasso_check_good_rc(lasso_get_hmac_key(key, (void**)&hmac_key, &hmac_key_length));
-		md = EVP_sha384();
-		key_size = EVP_MD_size(md);
 		method = LASSO_SIGNATURE_METHOD_HMAC_SHA384;
 	} else if (lasso_strisequal(algorithm, (char*)xmlSecHrefHmacSha512)) {
 		lasso_check_good_rc(lasso_get_hmac_key(key, (void**)&hmac_key, &hmac_key_length));
-		md = EVP_sha512();
-		key_size = EVP_MD_size(md);
 		method = LASSO_SIGNATURE_METHOD_HMAC_SHA512;
 	} else {
 		goto_cleanup_with_rc(LASSO_DS_ERROR_INVALID_SIGALG);
 	}
 
-	/* is the signature algo allowed */
-	goto_cleanup_if_fail_with_rc(
-                lasso_allowed_signature_method(method),
-                LASSO_DS_ERROR_INVALID_SIGALG);
-
-	/* decode signature */
-	signature = g_malloc(key_size+1);
-	goto_cleanup_if_fail_with_rc(
-			xmlSecBase64Decode((xmlChar*)b64_signature, signature, key_size+1) != 0,
-			LASSO_DS_ERROR_INVALID_SIGNATURE);
-	/* digest */
+	/* define the digest algorithm */
 	switch (method) {
 		case LASSO_SIGNATURE_METHOD_RSA_SHA1:
 		case LASSO_SIGNATURE_METHOD_DSA_SHA1:
-			digest = lasso_sha1(signed_content);
+		case LASSO_SIGNATURE_METHOD_HMAC_SHA1:
+			md = EVP_sha1();
 			break;
 		case LASSO_SIGNATURE_METHOD_RSA_SHA256:
-			digest = lasso_sha256(signed_content);
+		case LASSO_SIGNATURE_METHOD_HMAC_SHA256:
+			md = EVP_sha256();
 			break;
 		case LASSO_SIGNATURE_METHOD_RSA_SHA384:
-			digest = lasso_sha384(signed_content);
+		case LASSO_SIGNATURE_METHOD_HMAC_SHA384:
+			md = EVP_sha384();
 			break;
 		case LASSO_SIGNATURE_METHOD_RSA_SHA512:
-			digest = lasso_sha512(signed_content);
-			break;
-		case LASSO_SIGNATURE_METHOD_HMAC_SHA1:
-		case LASSO_SIGNATURE_METHOD_HMAC_SHA256:
-		case LASSO_SIGNATURE_METHOD_HMAC_SHA384:
 		case LASSO_SIGNATURE_METHOD_HMAC_SHA512:
+			md = EVP_sha512();
 			break;
-		default:
+		case LASSO_SIGNATURE_METHOD_NONE:
+		case LASSO_SIGNATURE_METHOD_LAST:
 			g_assert_not_reached();
 	}
+
+	/* is the signature algo allowed */
+	goto_cleanup_if_fail_with_rc(
+			lasso_allowed_signature_method(method),
+			LASSO_DS_ERROR_INVALID_SIGALG);
+
+	/* decode signature */
+	goto_cleanup_if_fail_with_rc(
+			lasso_base64_decode(b64_signature, &signature, (int*)&signature_len),
+			LASSO_DS_ERROR_INVALID_SIGNATURE);
 	/* verify signature */
+	evp_md_ctx = EVP_MD_CTX_create();
+
 	switch (method) {
 		case LASSO_SIGNATURE_METHOD_RSA_SHA1:
 		case LASSO_SIGNATURE_METHOD_RSA_SHA256:
 		case LASSO_SIGNATURE_METHOD_RSA_SHA384:
 		case LASSO_SIGNATURE_METHOD_RSA_SHA512:
-			goto_cleanup_if_fail_with_rc(
-					RSA_verify(
-						type,
-						(unsigned char*)digest,
-						digest_size,
-						signature,
-						key_size, rsa) == 1,
-					LASSO_DS_ERROR_INVALID_SIGNATURE);
-			break;
 		case LASSO_SIGNATURE_METHOD_DSA_SHA1:
-			goto_cleanup_if_fail_with_rc(
-					DSA_verify(
-						type,
-						(unsigned char*)digest,
-						digest_size,
-						signature,
-						key_size, dsa) == 1,
-					LASSO_DS_ERROR_INVALID_SIGNATURE);
+			{
+				xmlSecKeyData *key_data = xmlSecKeyGetValue(key);
+				if (! key_data) {
+					message(G_LOG_LEVEL_CRITICAL, "Failed to get KeyData");
+					goto_cleanup_with_rc(LASSO_DS_ERROR_INVALID_SIGNATURE);
+				}
+				EVP_PKEY *pkey = xmlSecOpenSSLEvpKeyDataGetEvp(key_data);
+				if (! pkey) {
+					message(G_LOG_LEVEL_CRITICAL, "Failed to get assymetric key");
+					goto_cleanup_with_rc(LASSO_DS_ERROR_INVALID_SIGNATURE);
+				}
+				if (1 != EVP_DigestVerifyInit(evp_md_ctx, NULL, md, NULL, pkey)) {
+					message(G_LOG_LEVEL_CRITICAL, "EVP_DigestVerifyInit failed");
+					goto_cleanup_with_rc(LASSO_DS_ERROR_INVALID_SIGNATURE);
+				}
+				if (1 != EVP_DigestVerifyUpdate(evp_md_ctx, signed_content, strlen(signed_content))) {
+					message(G_LOG_LEVEL_CRITICAL, "EVP_DigestVerifyUpdate failed");
+					goto_cleanup_with_rc(LASSO_DS_ERROR_INVALID_SIGNATURE);
+				}
+				if(1 != EVP_DigestVerifyFinal(evp_md_ctx, (unsigned char*)signature, signature_len)) {
+					goto_cleanup_with_rc(LASSO_DS_ERROR_INVALID_SIGNATURE);
+				}
+			}
 			break;
 		case LASSO_SIGNATURE_METHOD_HMAC_SHA1:
 		case LASSO_SIGNATURE_METHOD_HMAC_SHA256:
 		case LASSO_SIGNATURE_METHOD_HMAC_SHA384:
 		case LASSO_SIGNATURE_METHOD_HMAC_SHA512:
-			digest = g_malloc(key_size);
-			HMAC(md, hmac_key, hmac_key_length, (unsigned char*)signed_content,
-				strlen(signed_content), (unsigned char*)digest, NULL);
+			{
+				unsigned char *hmac_key;
+				size_t hmac_key_length;
+				size_t new_signature_len;
+
+				if ((rc = lasso_get_hmac_key(key, (void**)&hmac_key,
+											 &hmac_key_length))) {
+					message(G_LOG_LEVEL_CRITICAL, "Failed to get hmac key (%s)", lasso_strerror(rc));
+					goto_cleanup_with_rc(LASSO_DS_ERROR_INVALID_SIGNATURE);
+				}
+				g_assert(hmac_key);
+				hmac_pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, hmac_key, (int)hmac_key_length);
+				if (! hmac_key) {
+					message(G_LOG_LEVEL_CRITICAL, "EVP_PKEY_new_mac_key failed");
+					goto_cleanup_with_rc(LASSO_DS_ERROR_INVALID_SIGNATURE);
+				}
 
-			goto_cleanup_if_fail_with_rc(lasso_crypto_memequal(digest, signature,
-						key_size),
-					LASSO_DS_ERROR_INVALID_SIGNATURE);
+				if (EVP_DigestSignInit(evp_md_ctx, NULL, md, NULL, hmac_pkey) != 1) {
+					message(G_LOG_LEVEL_CRITICAL, "EVP_DigestSignInit failed");
+					goto_cleanup_with_rc(LASSO_DS_ERROR_INVALID_SIGNATURE);
+				}
+				if (EVP_DigestSign(evp_md_ctx, NULL, &new_signature_len, (unsigned char*)signed_content, strlen(signed_content)) != 1) {
+					message(G_LOG_LEVEL_CRITICAL, "EVP_DigestSign failed");
+					goto_cleanup_with_rc(LASSO_DS_ERROR_INVALID_SIGNATURE);
+				}
+				if (new_signature_len != signature_len) {
+					goto_cleanup_with_rc(LASSO_DS_ERROR_INVALID_SIGNATURE);
+				}
+				new_signature = g_malloc(new_signature_len);
+				if (EVP_DigestSign(evp_md_ctx, new_signature, &new_signature_len, (unsigned char*)signed_content, strlen(signed_content)) != 1) {
+					message(G_LOG_LEVEL_CRITICAL, "EVP_DigestSign failed");
+					goto_cleanup_with_rc(LASSO_DS_ERROR_INVALID_SIGNATURE);
+				}
+				if (CRYPTO_memcmp(signature, new_signature, signature_len) != 0) {
+					goto_cleanup_with_rc(LASSO_DS_ERROR_INVALID_SIGNATURE);
+				}
+			}
 			break;
 		case LASSO_SIGNATURE_METHOD_NONE:
 		case LASSO_SIGNATURE_METHOD_LAST:
@@ -882,7 +867,15 @@ lasso_query_verify_helper(const char *signed_content, const char *b64_signature,
 	}
 cleanup:
 	lasso_release_string(digest);
-	lasso_release_string(signature);
+	lasso_release_string(new_signature);
+	if (evp_md_ctx) {
+		EVP_MD_CTX_free(evp_md_ctx);
+		evp_md_ctx = NULL;
+	}
+	if (hmac_pkey) {
+		EVP_PKEY_free(hmac_pkey);
+		hmac_pkey = NULL;
+	}
 	return rc;
 
 }
@@ -899,7 +892,7 @@ cleanup:
  * a negative value if an error occurs during verification
  **/
 lasso_error_t
-lasso_query_verify_signature(const char *query, const xmlSecKey *sender_public_key)
+lasso_query_verify_signature(const char *query, xmlSecKey *sender_public_key)
 {
 	gchar **str_split = NULL;
 	char *b64_signature = NULL;
@@ -958,7 +951,7 @@ cleanup:
  * Return value: 0 if signature is validated, an error code otherwise.
  */
 int
-lasso_saml2_query_verify_signature(const char *query, const xmlSecKey *sender_public_key)
+lasso_saml2_query_verify_signature(const char *query, xmlSecKey *sender_public_key)
 {
 	char *b64_signature = NULL;
 	char *query_copy = NULL;
-- 
2.37.2

