--- eid-mw-4.4.19/tests/unit/sign.c	2019-07-11 16:08:46.000000000 +0200
+++ eid-mw-git/tests/unit/sign.c	2019-08-04 17:40:08.683942928 +0200
@@ -19,10 +19,13 @@
 **************************************************************************** */
 #ifdef WIN32
 #include <win32.h>
+#pragma pack(push, cryptoki, 1)
+#include "pkcs11.h"
+#pragma pack(pop, cryptoki)
 #else
 #include <unix.h>
-#endif
 #include <pkcs11.h>
+#endif
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
@@ -33,66 +36,88 @@
 #include <config.h>
 #endif
 
+#include <stdbool.h>
+
 #if HAVE_OPENSSL
-#include <openssl/rsa.h>
+#include <openssl/opensslv.h>
+#include <openssl/evp.h>
 #include <openssl/engine.h>
 
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
-static int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) {
-	if(!r || !n || !e) {
-		return 0;
-	}
-	r->n = n;
-	r->e = e;
-	r->d = d;
-	return 1;
-}
-#endif
-
-CK_BYTE digest_sha256[] = {
-                0x2c, 0x26, 0xb4, 0x6b,
-                0x68, 0xff, 0xc6, 0x8f,
-                0xf9, 0x9b, 0x45, 0x3c,
-                0x1d, 0x30, 0x41, 0x34,
-                0x13, 0x42, 0x2d, 0x70,
-		0x64, 0x83, 0xbf, 0xa0,
-		0xf9, 0x8a, 0x5e, 0x88,
-		0x62, 0x66, 0xe7, 0xae
-};
-
-int verify_sig(unsigned char* sig, CK_ULONG siglen, CK_BYTE_PTR modulus, CK_ULONG modlen, CK_BYTE_PTR exponent, CK_ULONG explen) {
-	RSA* rsa = RSA_new();
-	unsigned char* s = malloc(siglen);
-	int ret;
-
-	RSA_set0_key(rsa, BN_bin2bn(modulus, (int) modlen, NULL), BN_bin2bn(exponent, (int) explen, NULL), NULL);
-
-	int v = RSA_verify(NID_sha256, digest_sha256, sizeof(digest_sha256), sig, siglen, rsa);
-
-	printf("Signature verification returned: %d\n", v);
-	if(!v) {
-		unsigned long e = ERR_get_error();
-		printf("error %ld: %s\n", e, ERR_error_string(e, NULL));
-		ret = TEST_RV_FAIL;
-	} else {
-		ret = TEST_RV_OK;
+// These were copied from eid-test-ca:derencode.c
+int verify_sig(const unsigned char *sig_in, CK_ULONG siglen, const unsigned char *certificate, size_t certlen, bool is_rsa) {
+#if OPENSSL_VERSION_NUMBER > 0x10100000L
+	X509 *cert = NULL;
+	EVP_PKEY *pkey = NULL;
+	EVP_MD_CTX *mdctx;
+	EVP_PKEY_CTX *pctx;
+	const EVP_MD *md = EVP_get_digestbyname("sha256");
+	unsigned char *sig = (unsigned char*)sig_in;
+
+	if(d2i_X509(&cert, &certificate, certlen) == NULL) {
+		fprintf(stderr, "E: could not parse X509 certificate\n");
+		return TEST_RV_FAIL;
+	}
+	pkey = X509_get0_pubkey(cert);
+	if(pkey == NULL) {
+		fprintf(stderr, "E: could not find public key in certificate\n");
+		return TEST_RV_FAIL;
+	}
+	mdctx = EVP_MD_CTX_new();
+	if(EVP_DigestVerifyInit(mdctx, &pctx, md, NULL, pkey) != 1) {
+		fprintf(stderr, "E: initialization for signature validation failed!\n");
+		return TEST_RV_FAIL;
+	}
+	if(EVP_DigestVerifyUpdate(mdctx, (const unsigned char*)"foo", 3) != 1) {
+		fprintf(stderr, "E: hashing for signature failed!\n");
+		return TEST_RV_FAIL;
 	}
 
-	free(s);
-	RSA_free(rsa);
-
-	return ret;
+	ECDSA_SIG* ec_sig;
+	if(!is_rsa) {
+		BIGNUM *r;
+		BIGNUM *s;
+		ec_sig = ECDSA_SIG_new();
+		if((r = BN_bin2bn(sig, siglen / 2, NULL)) == NULL) {
+			fprintf(stderr, "E: could not convert R part of ECDSA signature!\n");
+			return TEST_RV_FAIL;
+		}
+		if((s = BN_bin2bn(sig + (siglen / 2), siglen / 2, NULL)) == NULL) {
+			fprintf(stderr, "E: could not convert S part of ECDSA signature!\n");
+			return TEST_RV_FAIL;
+		}
+		if(ECDSA_SIG_set0(ec_sig, r, s) == 0) {
+			fprintf(stderr, "E: could not set ECDSA_SIG structure!\n");
+			return TEST_RV_FAIL;
+		}
+		siglen = i2d_ECDSA_SIG(ec_sig, NULL);
+		unsigned char *dersig = sig = malloc(siglen);
+		siglen = i2d_ECDSA_SIG(ec_sig, &dersig);
+	}
+	if(EVP_DigestVerifyFinal(mdctx, sig, siglen) != 1) {
+		fprintf(stderr, "E: signature fails validation!\n");
+		return TEST_RV_FAIL;
+	}
+	if(!is_rsa) {
+		free(sig);
+	}
+	printf("signature verified\n");
+	return TEST_RV_OK;
+#else
+	printf("OpenSSL too old for verification\n");
+#endif
 }
-
 #endif
 
-int test_key(char* label, CK_SESSION_HANDLE session, CK_SLOT_ID slot EIDT_UNUSED) {
+int test_key(char* label, CK_SESSION_HANDLE session, CK_SLOT_ID slot) {
 	CK_ATTRIBUTE attr[2];
 	CK_MECHANISM mech;
+	CK_MECHANISM_TYPE_PTR mechlist;
 	CK_BYTE data[] = { 'f', 'o', 'o' };
 	CK_BYTE_PTR sig, mod, exp;
 	CK_ULONG sig_len, type, count;
-	CK_OBJECT_HANDLE privatekey, publickey;
+	CK_OBJECT_HANDLE privatekey, publickey, certificate;
+	bool is_rsa = false;
+	int i;
 
 	attr[0].type = CKA_CLASS;
 	attr[0].pValue = &type;
@@ -113,7 +138,22 @@
 		return TEST_RV_SKIP;
 	}
 
-	mech.mechanism = CKM_SHA256_RSA_PKCS;
+	check_rv(C_GetMechanismList(slot, NULL_PTR, &count));
+	mechlist = malloc(sizeof(CK_MECHANISM_TYPE) * count);
+#undef CHECK_RV_DEALLOCATE
+#define CHECK_RV_DEALLOCATE free(mechlist)
+
+	check_rv(C_GetMechanismList(slot, mechlist, &count));
+
+	for(i=0; i<count; i++) {
+		if(mechlist[i] == CKM_SHA256_RSA_PKCS) {
+			mech.mechanism = mechlist[i];
+			i=count;
+			is_rsa = true;
+			break;
+		}
+	}
+
 	check_rv(C_SignInit(session, &mech, privatekey));
 
 	check_rv(C_Sign(session, data, sizeof(data), NULL, &sig_len));
@@ -124,42 +164,68 @@
 
 	hex_dump((char*)sig, sig_len);
 
-	type = CKO_PUBLIC_KEY;
-	check_rv(C_FindObjectsInit(session, attr, 2));
-	check_rv(C_FindObjects(session, &publickey, 1, &count));
-	verbose_assert(count == 1);
-	check_rv(C_FindObjectsFinal(session));
+	if(is_rsa) {
+		type = CKO_PUBLIC_KEY;
+		check_rv(C_FindObjectsInit(session, attr, 2));
+		check_rv(C_FindObjects(session, &publickey, 1, &count));
+		verbose_assert(count == 1);
+		check_rv(C_FindObjectsFinal(session));
 
-	attr[0].type = CKA_MODULUS;
-	attr[0].pValue = NULL_PTR;
-	attr[0].ulValueLen = 0;
+		attr[0].type = CKA_MODULUS;
+		attr[0].pValue = NULL_PTR;
+		attr[0].ulValueLen = 0;
 
-	attr[1].type = CKA_PUBLIC_EXPONENT;
-	attr[1].pValue = NULL_PTR;
-	attr[1].ulValueLen = 0;
+		attr[1].type = CKA_PUBLIC_EXPONENT;
+		attr[1].pValue = NULL_PTR;
+		attr[1].ulValueLen = 0;
 
-	check_rv(C_GetAttributeValue(session, publickey, attr, 2));
+		check_rv(C_GetAttributeValue(session, publickey, attr, 2));
 
-	verbose_assert(attr[0].ulValueLen == sig_len);
+		verbose_assert(attr[0].ulValueLen == sig_len);
 
-	mod = malloc(attr[0].ulValueLen);
-	mod[0] = 0xde; mod[1] = 0xad; mod[2] = 0xbe; mod[3] = 0xef;
-	exp = malloc(attr[1].ulValueLen);
-	exp[0] = 0xde; exp[1] = 0xad; exp[2] = 0xbe; exp[3] = 0xef;
+		mod = malloc(attr[0].ulValueLen);
+		mod[0] = 0xde; mod[1] = 0xad; mod[2] = 0xbe; mod[3] = 0xef;
+		exp = malloc(attr[1].ulValueLen);
+		exp[0] = 0xde; exp[1] = 0xad; exp[2] = 0xbe; exp[3] = 0xef;
 
-	attr[0].pValue = mod;
-	attr[1].pValue = exp;
+		attr[0].pValue = mod;
+		attr[1].pValue = exp;
 
-	check_rv(C_GetAttributeValue(session, publickey, attr, 2));
+		check_rv(C_GetAttributeValue(session, publickey, attr, 2));
 
-	printf("Received key modulus with length %lu:\n", attr[0].ulValueLen);
-	hex_dump((char*)mod, attr[0].ulValueLen);
+		printf("Received key modulus with length %lu:\n", attr[0].ulValueLen);
+		hex_dump((char*)mod, attr[0].ulValueLen);
 
-	printf("Received public exponent of key with length %lu:\n", attr[1].ulValueLen);
-	hex_dump((char*)exp, attr[1].ulValueLen);
+		printf("Received public exponent of key with length %lu:\n", attr[1].ulValueLen);
+		hex_dump((char*)exp, attr[1].ulValueLen);
+	}
 
-#if HAVE_OPENSSL
-	return verify_sig(sig, sig_len, mod, attr[0].ulValueLen, exp, attr[1].ulValueLen);
+#if HAVE_OPENSSL && OPENSSL_VERSION_NUMBER > 0x10100000L
+	unsigned char cert[4096];
+	attr[0].type = CKA_CLASS;
+	attr[0].pValue = &type;
+	type = CKO_CERTIFICATE;
+	attr[0].ulValueLen = sizeof(CK_ULONG);
+
+	attr[1].type = CKA_LABEL;
+	attr[1].pValue = label;
+	attr[1].ulValueLen = strlen(label);
+
+	check_rv(C_FindObjectsInit(session, attr, 2));
+	check_rv(C_FindObjects(session, &certificate, 1, &count));
+	verbose_assert(count == 1);
+	check_rv(C_FindObjectsFinal(session));
+
+	attr[0].type = CKA_VALUE;
+	attr[0].pValue = cert;
+	attr[0].ulValueLen = sizeof(cert);
+
+	check_rv(C_GetAttributeValue(session, certificate, attr, 1));
+
+	printf("Received certificate with length %lu:\n", attr[0].ulValueLen);
+	hex_dump((char*)cert, attr[0].ulValueLen);
+
+	return verify_sig(sig, sig_len, cert, attr[0].ulValueLen, is_rsa);
 #else
 	return TEST_RV_OK;
 #endif
