summaryrefslogtreecommitdiff
path: root/src/libstrongswan/plugins/gmp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/plugins/gmp')
-rw-r--r--src/libstrongswan/plugins/gmp/Makefile.in2
-rw-r--r--src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c11
-rw-r--r--src/libstrongswan/plugins/gmp/gmp_diffie_hellman.h5
-rw-r--r--src/libstrongswan/plugins/gmp/gmp_plugin.c15
-rw-r--r--src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c232
-rw-r--r--src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c128
6 files changed, 379 insertions, 14 deletions
diff --git a/src/libstrongswan/plugins/gmp/Makefile.in b/src/libstrongswan/plugins/gmp/Makefile.in
index 39a2bcabb..11aef42f0 100644
--- a/src/libstrongswan/plugins/gmp/Makefile.in
+++ b/src/libstrongswan/plugins/gmp/Makefile.in
@@ -245,9 +245,11 @@ ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
+FUZZING_LDFLAGS = @FUZZING_LDFLAGS@
GEM = @GEM@
GENHTML = @GENHTML@
GPERF = @GPERF@
+GPERF_LEN_TYPE = @GPERF_LEN_TYPE@
GPRBUILD = @GPRBUILD@
GREP = @GREP@
INSTALL = @INSTALL@
diff --git a/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c b/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c
index b7ee94ee0..b01adfe01 100644
--- a/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c
+++ b/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c
@@ -272,7 +272,7 @@ static gmp_diffie_hellman_t *create_generic(diffie_hellman_group_t group,
}
/*
- * Described in header.
+ * Described in header
*/
gmp_diffie_hellman_t *gmp_diffie_hellman_create(diffie_hellman_group_t group)
{
@@ -287,12 +287,17 @@ gmp_diffie_hellman_t *gmp_diffie_hellman_create(diffie_hellman_group_t group)
params->generator, params->prime);
}
-
+/*
+ * Described in header
+ */
gmp_diffie_hellman_t *gmp_diffie_hellman_create_custom(
- diffie_hellman_group_t group, chunk_t g, chunk_t p)
+ diffie_hellman_group_t group, ...)
{
if (group == MODP_CUSTOM)
{
+ chunk_t g, p;
+
+ VA_ARGS_GET(group, g, p);
return create_generic(MODP_CUSTOM, p.len, g, p);
}
return NULL;
diff --git a/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.h b/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.h
index 6d73c0863..a8cde7bca 100644
--- a/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.h
+++ b/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.h
@@ -49,12 +49,11 @@ gmp_diffie_hellman_t *gmp_diffie_hellman_create(diffie_hellman_group_t group);
* Creates a new gmp_diffie_hellman_t object for MODP_CUSTOM.
*
* @param group MODP_CUSTOM
- * @param g generator
- * @param p prime
+ * @param ... expects generator and prime as chunk_t
* @return gmp_diffie_hellman_t object, NULL if not supported
*/
gmp_diffie_hellman_t *gmp_diffie_hellman_create_custom(
- diffie_hellman_group_t group, chunk_t g, chunk_t p);
+ diffie_hellman_group_t group, ...);
#endif /** GMP_DIFFIE_HELLMAN_H_ @}*/
diff --git a/src/libstrongswan/plugins/gmp/gmp_plugin.c b/src/libstrongswan/plugins/gmp/gmp_plugin.c
index c75975301..700e29bf6 100644
--- a/src/libstrongswan/plugins/gmp/gmp_plugin.c
+++ b/src/libstrongswan/plugins/gmp/gmp_plugin.c
@@ -79,6 +79,14 @@ METHOD(plugin_t, get_features, int,
PLUGIN_REGISTER(PUBKEY, gmp_rsa_public_key_load, TRUE),
PLUGIN_PROVIDE(PUBKEY, KEY_RSA),
/* signature schemes, private */
+ PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PSS),
+ PLUGIN_SDEPEND(HASHER, HASH_SHA1),
+ PLUGIN_SDEPEND(HASHER, HASH_SHA256),
+ PLUGIN_SDEPEND(HASHER, HASH_SHA512),
+ PLUGIN_SDEPEND(RNG, RNG_STRONG),
+ PLUGIN_SDEPEND(XOF, XOF_MGF1_SHA1),
+ PLUGIN_SDEPEND(XOF, XOF_MGF1_SHA256),
+ PLUGIN_SDEPEND(XOF, XOF_MGF1_SHA512),
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_NULL),
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA2_224),
PLUGIN_DEPENDS(HASHER, HASH_SHA224),
@@ -101,6 +109,13 @@ METHOD(plugin_t, get_features, int,
PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_MD5),
PLUGIN_DEPENDS(HASHER, HASH_MD5),
/* signature verification schemes */
+ PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PSS),
+ PLUGIN_SDEPEND(HASHER, HASH_SHA1),
+ PLUGIN_SDEPEND(HASHER, HASH_SHA256),
+ PLUGIN_SDEPEND(HASHER, HASH_SHA512),
+ PLUGIN_SDEPEND(XOF, XOF_MGF1_SHA1),
+ PLUGIN_SDEPEND(XOF, XOF_MGF1_SHA256),
+ PLUGIN_SDEPEND(XOF, XOF_MGF1_SHA512),
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_NULL),
PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA2_224),
PLUGIN_DEPENDS(HASHER, HASH_SHA224),
diff --git a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
index 21b420866..aca232c86 100644
--- a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
+++ b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2017 Tobias Brunner
* Copyright (C) 2005 Jan Hutter
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2012 Andreas Steffen
@@ -27,6 +28,7 @@
#include <asn1/oid.h>
#include <asn1/asn1.h>
#include <asn1/asn1_parser.h>
+#include <credentials/keys/signature_params.h>
#ifdef HAVE_MPZ_POWM_SEC
# undef mpz_powm
@@ -333,6 +335,120 @@ static bool build_emsa_pkcs1_signature(private_gmp_rsa_private_key_t *this,
return TRUE;
}
+/**
+ * Build a signature using the PKCS#1 EMSA PSS scheme
+ */
+static bool build_emsa_pss_signature(private_gmp_rsa_private_key_t *this,
+ rsa_pss_params_t *params, chunk_t data,
+ chunk_t *signature)
+{
+ ext_out_function_t xof;
+ hasher_t *hasher = NULL;
+ rng_t *rng = NULL;
+ xof_t *mgf = NULL;
+ chunk_t hash, salt = chunk_empty, m, ps, db, dbmask, em;
+ size_t embits, emlen, maskbits;
+ bool success = FALSE;
+
+ if (!params)
+ {
+ return FALSE;
+ }
+ xof = xof_mgf1_from_hash_algorithm(params->mgf1_hash);
+ if (xof == XOF_UNDEFINED)
+ {
+ DBG1(DBG_LIB, "%N is not supported for MGF1", hash_algorithm_names,
+ params->mgf1_hash);
+ return FALSE;
+ }
+ /* emBits = modBits - 1 */
+ embits = mpz_sizeinbase(this->n, 2) - 1;
+ /* emLen = ceil(emBits/8) */
+ emlen = (embits + 7) / BITS_PER_BYTE;
+ /* mHash = Hash(M) */
+ hasher = lib->crypto->create_hasher(lib->crypto, params->hash);
+ if (!hasher)
+ {
+ DBG1(DBG_LIB, "hash algorithm %N not supported",
+ hash_algorithm_names, params->hash);
+ return FALSE;
+ }
+ hash = chunk_alloca(hasher->get_hash_size(hasher));
+ if (!hasher->get_hash(hasher, data, hash.ptr))
+ {
+ goto error;
+ }
+
+ salt.len = hash.len;
+ if (params->salt.len)
+ {
+ salt = params->salt;
+ }
+ else if (params->salt_len > RSA_PSS_SALT_LEN_DEFAULT)
+ {
+ salt.len = params->salt_len;
+ }
+ if (emlen < (hash.len + salt.len + 2))
+ { /* too long */
+ goto error;
+ }
+ if (salt.len && !params->salt.len)
+ {
+ salt = chunk_alloca(salt.len);
+ rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
+ if (!rng || !rng->get_bytes(rng, salt.len, salt.ptr))
+ {
+ goto error;
+ }
+ }
+ /* M' = 0x0000000000000000 | mHash | salt */
+ m = chunk_cata("ccc",
+ chunk_from_chars(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00),
+ hash, salt);
+ /* H = Hash(M') */
+ if (!hasher->get_hash(hasher, m, hash.ptr))
+ {
+ goto error;
+ }
+ /* PS = 00...<padding depending on hash and salt length> */
+ ps = chunk_alloca(emlen - salt.len - hash.len - 2);
+ memset(ps.ptr, 0, ps.len);
+ /* DB = PS | 0x01 | salt */
+ db = chunk_cata("ccc", ps, chunk_from_chars(0x01), salt);
+ /* dbMask = MGF(H, emLen - hLen - 1) */
+ mgf = lib->crypto->create_xof(lib->crypto, xof);
+ dbmask = chunk_alloca(db.len);
+ if (!mgf)
+ {
+ DBG1(DBG_LIB, "%N not supported", ext_out_function_names, xof);
+ goto error;
+ }
+ if (!mgf->set_seed(mgf, hash) ||
+ !mgf->get_bytes(mgf, dbmask.len, dbmask.ptr))
+ {
+ goto error;
+ }
+ /* maskedDB = DB xor dbMask */
+ memxor(db.ptr, dbmask.ptr, db.len);
+ /* zero out unused bits */
+ maskbits = (8 * emlen) - embits;
+ if (maskbits)
+ {
+ db.ptr[0] &= (0xff >> maskbits);
+ }
+ /* EM = maskedDB | H | 0xbc */
+ em = chunk_cata("ccc", db, hash, chunk_from_chars(0xbc));
+ /* S = RSASP1(K, EM) */
+ *signature = rsasp1(this, em);
+ success = TRUE;
+
+error:
+ DESTROY_IF(hasher);
+ DESTROY_IF(rng);
+ DESTROY_IF(mgf);
+ return success;
+}
+
METHOD(private_key_t, get_type, key_type_t,
private_gmp_rsa_private_key_t *this)
{
@@ -341,7 +457,7 @@ METHOD(private_key_t, get_type, key_type_t,
METHOD(private_key_t, sign, bool,
private_gmp_rsa_private_key_t *this, signature_scheme_t scheme,
- chunk_t data, chunk_t *signature)
+ void *params, chunk_t data, chunk_t *signature)
{
switch (scheme)
{
@@ -367,6 +483,8 @@ METHOD(private_key_t, sign, bool,
return build_emsa_pkcs1_signature(this, HASH_SHA1, data, signature);
case SIGN_RSA_EMSA_PKCS1_MD5:
return build_emsa_pkcs1_signature(this, HASH_MD5, data, signature);
+ case SIGN_RSA_EMSA_PSS:
+ return build_emsa_pss_signature(this, params, data, signature);
default:
DBG1(DBG_LIB, "signature scheme %N not supported in RSA",
signature_scheme_names, scheme);
@@ -807,6 +925,82 @@ gmp_rsa_private_key_t *gmp_rsa_private_key_gen(key_type_t type, va_list args)
}
/**
+ * Recover the primes from n, e and d using the algorithm described in
+ * Appendix C of NIST SP 800-56B.
+ */
+static bool calculate_pq(private_gmp_rsa_private_key_t *this)
+{
+ gmp_randstate_t rstate;
+ mpz_t k, r, g, y, n1, x;
+ int i, t, j;
+ bool success = FALSE;
+
+ gmp_randinit_default(rstate);
+ mpz_inits(k, r, g, y, n1, x, NULL);
+ /* k = (d * e) - 1 */
+ mpz_mul(k, *this->d, this->e);
+ mpz_sub_ui(k, k, 1);
+ if (mpz_odd_p(k))
+ {
+ goto error;
+ }
+ /* k = 2^t * r, where r is the largest odd integer dividing k, and t >= 1 */
+ mpz_set(r, k);
+ for (t = 0; !mpz_odd_p(r); t++)
+ { /* r = r/2 */
+ mpz_divexact_ui(r, r, 2);
+ }
+ /* we need n-1 below */
+ mpz_sub_ui(n1, this->n, 1);
+ for (i = 0; i < 100; i++)
+ { /* generate random integer g in [0, n-1] */
+ mpz_urandomm(g, rstate, this->n);
+ /* y = g^r mod n */
+ mpz_powm_sec(y, g, r, this->n);
+ /* try again if y == 1 or y == n-1 */
+ if (mpz_cmp_ui(y, 1) == 0 || mpz_cmp(y, n1) == 0)
+ {
+ continue;
+ }
+ for (j = 0; j < t; j++)
+ { /* x = y^2 mod n */
+ mpz_powm_ui(x, y, 2, this->n);
+ /* stop if x == 1 */
+ if (mpz_cmp_ui(x, 1) == 0)
+ {
+ goto done;
+ }
+ /* retry with new g if x = n-1 */
+ if (mpz_cmp(x, n1) == 0)
+ {
+ break;
+ }
+ /* y = x */
+ mpz_set(y, x);
+ }
+ }
+ goto error;
+
+done:
+ /* p = gcd(y-1, n) */
+ mpz_sub_ui(y, y, 1);
+ mpz_gcd(this->p, y, this->n);
+ /* q = n/p */
+ mpz_divexact(this->q, this->n, this->p);
+ success = TRUE;
+
+error:
+ mpz_clear_sensitive(k);
+ mpz_clear_sensitive(r);
+ mpz_clear_sensitive(g);
+ mpz_clear_sensitive(y);
+ mpz_clear_sensitive(x);
+ mpz_clear(n1);
+ gmp_randclear(rstate);
+ return success;
+}
+
+/**
* See header.
*/
gmp_rsa_private_key_t *gmp_rsa_private_key_load(key_type_t type, va_list args)
@@ -868,9 +1062,30 @@ gmp_rsa_private_key_t *gmp_rsa_private_key_load(key_type_t type, va_list args)
mpz_import(this->n, n.len, 1, 1, 1, 0, n.ptr);
mpz_import(this->e, e.len, 1, 1, 1, 0, e.ptr);
mpz_import(*this->d, d.len, 1, 1, 1, 0, d.ptr);
- mpz_import(this->p, p.len, 1, 1, 1, 0, p.ptr);
- mpz_import(this->q, q.len, 1, 1, 1, 0, q.ptr);
- mpz_import(this->coeff, coeff.len, 1, 1, 1, 0, coeff.ptr);
+ if (p.len)
+ {
+ mpz_import(this->p, p.len, 1, 1, 1, 0, p.ptr);
+ }
+ if (q.len)
+ {
+ mpz_import(this->q, q.len, 1, 1, 1, 0, q.ptr);
+ }
+ if (!p.len && !q.len)
+ { /* p and q missing in key, recalculate from n, e and d */
+ if (!calculate_pq(this))
+ {
+ destroy(this);
+ return NULL;
+ }
+ }
+ else if (!p.len)
+ { /* p missing in key, recalculate: p = n / q */
+ mpz_divexact(this->p, this->n, this->q);
+ }
+ else if (!q.len)
+ { /* q missing in key, recalculate: q = n / p */
+ mpz_divexact(this->q, this->n, this->p);
+ }
if (!exp1.len)
{ /* exp1 missing in key, recalculate: exp1 = d mod (p-1) */
mpz_sub_ui(this->exp1, this->p, 1);
@@ -889,6 +1104,14 @@ gmp_rsa_private_key_t *gmp_rsa_private_key_load(key_type_t type, va_list args)
{
mpz_import(this->exp2, exp2.len, 1, 1, 1, 0, exp2.ptr);
}
+ if (!coeff.len)
+ { /* coeff missing in key, recalculate: coeff = q^-1 mod p */
+ mpz_invert(this->coeff, this->q, this->p);
+ }
+ else
+ {
+ mpz_import(this->coeff, coeff.len, 1, 1, 1, 0, coeff.ptr);
+ }
this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE;
if (check(this) != SUCCESS)
{
@@ -897,4 +1120,3 @@ gmp_rsa_private_key_t *gmp_rsa_private_key_load(key_type_t type, va_list args)
}
return &this->public;
}
-
diff --git a/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c b/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c
index 065c88903..52bc9fb38 100644
--- a/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c
+++ b/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c
@@ -1,7 +1,8 @@
/*
+ * Copyright (C) 2017 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
- * Hochschule fuer Technik Rapperswil
+ * HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -27,6 +28,7 @@
#include <asn1/asn1.h>
#include <asn1/asn1_parser.h>
#include <crypto/hashers/hasher.h>
+#include <credentials/keys/signature_params.h>
#ifdef HAVE_MPZ_POWM_SEC
# undef mpz_powm
@@ -126,7 +128,7 @@ static const asn1Object_t digestInfoObjects[] = {
#define DIGEST_INFO_DIGEST 2
/**
- * Verification of an EMPSA PKCS1 signature described in PKCS#1
+ * Verification of an EMSA PKCS1 signature described in PKCS#1
*/
static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this,
hash_algorithm_t algorithm,
@@ -283,6 +285,124 @@ end:
return success;
}
+/**
+ * Verification of an EMSA PSS signature described in PKCS#1
+ */
+static bool verify_emsa_pss_signature(private_gmp_rsa_public_key_t *this,
+ rsa_pss_params_t *params, chunk_t data,
+ chunk_t signature)
+{
+ ext_out_function_t xof;
+ hasher_t *hasher = NULL;
+ xof_t *mgf = NULL;
+ chunk_t em, hash, salt, db, h, dbmask, m;
+ size_t embits, maskbits;
+ int i;
+ bool success = FALSE;
+
+ if (!params)
+ {
+ return FALSE;
+ }
+ xof = xof_mgf1_from_hash_algorithm(params->mgf1_hash);
+ if (xof == XOF_UNDEFINED)
+ {
+ DBG1(DBG_LIB, "%N is not supported for MGF1", hash_algorithm_names,
+ params->mgf1_hash);
+ return FALSE;
+ }
+ chunk_skip_zero(signature);
+ if (signature.len == 0 || signature.len > this->k)
+ {
+ return FALSE;
+ }
+ /* EM = RSAVP1((n, e), S) */
+ em = rsavp1(this, signature);
+ if (!em.len)
+ {
+ goto error;
+ }
+ /* emBits = modBits - 1 */
+ embits = mpz_sizeinbase(this->n, 2) - 1;
+ /* mHash = Hash(M) */
+ hasher = lib->crypto->create_hasher(lib->crypto, params->hash);
+ if (!hasher)
+ {
+ DBG1(DBG_LIB, "hash algorithm %N not supported",
+ hash_algorithm_names, params->hash);
+ goto error;
+ }
+ hash = chunk_alloca(hasher->get_hash_size(hasher));
+ if (!hasher->get_hash(hasher, data, hash.ptr))
+ {
+ goto error;
+ }
+ /* determine salt length */
+ salt.len = hash.len;
+ if (params->salt_len > RSA_PSS_SALT_LEN_DEFAULT)
+ {
+ salt.len = params->salt_len;
+ }
+ /* verify general structure of EM */
+ maskbits = (8 * em.len) - embits;
+ if (em.len < (hash.len + salt.len + 2) || em.ptr[em.len-1] != 0xbc ||
+ (em.ptr[0] & (0xff << (8-maskbits))))
+ { /* inconsistent */
+ goto error;
+ }
+ /* split EM in maskedDB and H */
+ db = chunk_create(em.ptr, em.len - hash.len - 1);
+ h = chunk_create(em.ptr + db.len, hash.len);
+ /* dbMask = MGF(H, emLen - hLen - 1) */
+ mgf = lib->crypto->create_xof(lib->crypto, xof);
+ if (!mgf)
+ {
+ DBG1(DBG_LIB, "%N not supported", ext_out_function_names, xof);
+ goto error;
+ }
+ dbmask = chunk_alloca(db.len);
+ if (!mgf->set_seed(mgf, h) ||
+ !mgf->get_bytes(mgf, dbmask.len, dbmask.ptr))
+ {
+ DBG1(DBG_LIB, "%N not supported or failed", ext_out_function_names, xof);
+ goto error;
+ }
+ /* DB = maskedDB xor dbMask */
+ memxor(db.ptr, dbmask.ptr, db.len);
+ if (maskbits)
+ {
+ db.ptr[0] &= (0xff >> maskbits);
+ }
+ /* check DB = PS | 0x01 | salt */
+ for (i = 0; i < (db.len - salt.len - 1); i++)
+ {
+ if (db.ptr[i])
+ { /* padding not 0 */
+ goto error;
+ }
+ }
+ if (db.ptr[i++] != 0x01)
+ { /* 0x01 not found */
+ goto error;
+ }
+ salt.ptr = &db.ptr[i];
+ /* M' = 0x0000000000000000 | mHash | salt */
+ m = chunk_cata("ccc",
+ chunk_from_chars(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00),
+ hash, salt);
+ if (!hasher->get_hash(hasher, m, hash.ptr))
+ {
+ goto error;
+ }
+ success = memeq_const(h.ptr, hash.ptr, hash.len);
+
+error:
+ DESTROY_IF(hasher);
+ DESTROY_IF(mgf);
+ free(em.ptr);
+ return success;
+}
+
METHOD(public_key_t, get_type, key_type_t,
private_gmp_rsa_public_key_t *this)
{
@@ -290,7 +410,7 @@ METHOD(public_key_t, get_type, key_type_t,
}
METHOD(public_key_t, verify, bool,
- private_gmp_rsa_public_key_t *this, signature_scheme_t scheme,
+ private_gmp_rsa_public_key_t *this, signature_scheme_t scheme, void *params,
chunk_t data, chunk_t signature)
{
switch (scheme)
@@ -317,6 +437,8 @@ METHOD(public_key_t, verify, bool,
return verify_emsa_pkcs1_signature(this, HASH_SHA1, data, signature);
case SIGN_RSA_EMSA_PKCS1_MD5:
return verify_emsa_pkcs1_signature(this, HASH_MD5, data, signature);
+ case SIGN_RSA_EMSA_PSS:
+ return verify_emsa_pss_signature(this, params, data, signature);
default:
DBG1(DBG_LIB, "signature scheme %N not supported in RSA",
signature_scheme_names, scheme);