diff options
Diffstat (limited to 'src/libstrongswan/plugins/gcrypt')
-rw-r--r-- | src/libstrongswan/plugins/gcrypt/Makefile.in | 2 | ||||
-rw-r--r-- | src/libstrongswan/plugins/gcrypt/gcrypt_dh.c | 6 | ||||
-rw-r--r-- | src/libstrongswan/plugins/gcrypt/gcrypt_dh.h | 6 | ||||
-rw-r--r-- | src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c | 22 | ||||
-rw-r--r-- | src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c | 229 | ||||
-rw-r--r-- | src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c | 75 |
6 files changed, 297 insertions, 43 deletions
diff --git a/src/libstrongswan/plugins/gcrypt/Makefile.in b/src/libstrongswan/plugins/gcrypt/Makefile.in index 2212be0e2..3ed4a910f 100644 --- a/src/libstrongswan/plugins/gcrypt/Makefile.in +++ b/src/libstrongswan/plugins/gcrypt/Makefile.in @@ -248,9 +248,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/gcrypt/gcrypt_dh.c b/src/libstrongswan/plugins/gcrypt/gcrypt_dh.c index cee25ea74..5519125ba 100644 --- a/src/libstrongswan/plugins/gcrypt/gcrypt_dh.c +++ b/src/libstrongswan/plugins/gcrypt/gcrypt_dh.c @@ -289,11 +289,13 @@ gcrypt_dh_t *gcrypt_dh_create(diffie_hellman_group_t group) /* * Described in header. */ -gcrypt_dh_t *gcrypt_dh_create_custom(diffie_hellman_group_t group, - chunk_t g, chunk_t p) +gcrypt_dh_t *gcrypt_dh_create_custom(diffie_hellman_group_t group, ...) { if (group == MODP_CUSTOM) { + chunk_t g, p; + + VA_ARGS_GET(group, g, p); return create_generic(group, p.len, g, p); } return NULL; diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_dh.h b/src/libstrongswan/plugins/gcrypt/gcrypt_dh.h index a70958dc4..c6259f7ac 100644 --- a/src/libstrongswan/plugins/gcrypt/gcrypt_dh.h +++ b/src/libstrongswan/plugins/gcrypt/gcrypt_dh.h @@ -48,12 +48,10 @@ gcrypt_dh_t *gcrypt_dh_create(diffie_hellman_group_t group); * Creates a new gcrypt_dh_t object for MODP_CUSTOM. * * @param group MODP_CUSTOM - * @param g generator - * @param p prime + * @param ... expects generator and prime as chunk_t * @return gcrypt_dh_t object, NULL if not supported */ -gcrypt_dh_t *gcrypt_dh_create_custom(diffie_hellman_group_t group, - chunk_t g, chunk_t p); +gcrypt_dh_t *gcrypt_dh_create_custom(diffie_hellman_group_t group, ...); #endif /** GCRYPT_DH_H_ @}*/ diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c b/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c index 7ecba8fa9..8a3de1e01 100644 --- a/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c +++ b/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c @@ -118,6 +118,28 @@ METHOD(plugin_t, get_features, int, PLUGIN_PROVIDE(PRIVKEY, KEY_RSA), PLUGIN_REGISTER(PRIVKEY_GEN, gcrypt_rsa_private_key_gen, FALSE), PLUGIN_PROVIDE(PRIVKEY_GEN, KEY_RSA), + /* signature schemes, private */ +#if GCRYPT_VERSION_NUMBER >= 0x010700 + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PSS), +#endif + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_NULL), + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA2_224), + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA2_256), + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA2_384), + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA2_512), + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA1), + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_MD5), + /* signature verification schemes */ +#if GCRYPT_VERSION_NUMBER >= 0x010700 + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PSS), +#endif + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_NULL), + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA2_224), + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA2_256), + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA2_384), + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA2_512), + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA1), + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_MD5), /* random numbers */ PLUGIN_REGISTER(RNG, gcrypt_rng_create), PLUGIN_PROVIDE(RNG, RNG_WEAK), diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c index 15b876b3f..c06f43348 100644 --- a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c +++ b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c @@ -1,6 +1,7 @@ /* + * Copyright (C) 2017 Tobias Brunner * Copyright (C) 2005-2009 Martin Willi - * 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 @@ -21,6 +22,7 @@ #include <asn1/oid.h> #include <asn1/asn1.h> #include <asn1/asn1_parser.h> +#include <credentials/keys/signature_params.h> typedef struct private_gcrypt_rsa_private_key_t private_gcrypt_rsa_private_key_t; @@ -147,51 +149,100 @@ static bool sign_raw(private_gcrypt_rsa_private_key_t *this, } /** - * Sign a chunk of data using hashing and PKCS#1 encoding + * Sign a chunk of data using hashing and PKCS#1v1.5/EMSA-PSS encoding */ static bool sign_pkcs1(private_gcrypt_rsa_private_key_t *this, - hash_algorithm_t hash_algorithm, char *hash_name, + hash_algorithm_t hash_algorithm, rsa_pss_params_t *pss, chunk_t data, chunk_t *signature) { hasher_t *hasher; chunk_t hash; gcry_error_t err; gcry_sexp_t in, out; - int hash_oid; + char *hash_name = enum_to_name(hash_algorithm_short_names, hash_algorithm); - hash_oid = hasher_algorithm_to_oid(hash_algorithm); - if (hash_oid == OID_UNKNOWN) + hasher = lib->crypto->create_hasher(lib->crypto, hash_algorithm); + if (!hasher) { + DBG1(DBG_LIB, "hash algorithm %N not supported", + hash_algorithm_names, hash_algorithm); return FALSE; } - hasher = lib->crypto->create_hasher(lib->crypto, hash_algorithm); - if (!hasher || !hasher->allocate_hash(hasher, data, &hash)) + if (!hasher->allocate_hash(hasher, data, &hash)) { - DESTROY_IF(hasher); + hasher->destroy(hasher); return FALSE; } hasher->destroy(hasher); - err = gcry_sexp_build(&in, NULL, "(data(flags pkcs1)(hash %s %b))", - hash_name, hash.len, hash.ptr); + if (pss) + { + if (pss->salt.len) + { + err = gcry_sexp_build(&in, NULL, + "(data(flags pss)(salt-length %u)" + "(random-override %b)(hash %s %b))", + pss->salt.len, pss->salt.len, pss->salt.ptr, + hash_name, hash.len, hash.ptr); + } + else + { + u_int slen = hasher_hash_size(hash_algorithm); + if (pss->salt_len > RSA_PSS_SALT_LEN_DEFAULT) + { + slen = pss->salt_len; + } + err = gcry_sexp_build(&in, NULL, + "(data(flags pss)(salt-length %u)(hash %s %b))", + slen, hash_name, hash.len, hash.ptr); + } + } + else + { + err = gcry_sexp_build(&in, NULL, "(data(flags pkcs1)(hash %s %b))", + hash_name, hash.len, hash.ptr); + } chunk_free(&hash); if (err) { - DBG1(DBG_LIB, "building signature S-expression failed: %s", gpg_strerror(err)); + DBG1(DBG_LIB, "building signature S-expression failed: %s", + gpg_strerror(err)); return FALSE; } err = gcry_pk_sign(&out, in, this->key); gcry_sexp_release(in); if (err) { - DBG1(DBG_LIB, "creating pkcs1 signature failed: %s", gpg_strerror(err)); + DBG1(DBG_LIB, "creating pkcs1 signature failed: %s", + gpg_strerror(err)); return FALSE; } + *signature = gcrypt_rsa_find_token(out, "s", this->key); gcry_sexp_release(out); return !!signature->len; } +#if GCRYPT_VERSION_NUMBER >= 0x010700 +/** + * Sign a chunk of data using hashing and EMSA-PSS encoding + */ +static bool sign_pss(private_gcrypt_rsa_private_key_t *this, + rsa_pss_params_t *params, chunk_t data, chunk_t *signature) +{ + if (!params) + { + return FALSE; + } + if (params->mgf1_hash != params->hash) + { + DBG1(DBG_LIB, "unable to use a different MGF1 hash for RSA-PSS"); + return FALSE; + } + return sign_pkcs1(this, params->hash, params, data, signature); +} +#endif + METHOD(private_key_t, get_type, key_type_t, private_gcrypt_rsa_private_key_t *this) { @@ -200,24 +251,28 @@ METHOD(private_key_t, get_type, key_type_t, METHOD(private_key_t, sign, bool, private_gcrypt_rsa_private_key_t *this, signature_scheme_t scheme, - chunk_t data, chunk_t *sig) + void *params, chunk_t data, chunk_t *sig) { switch (scheme) { case SIGN_RSA_EMSA_PKCS1_NULL: return sign_raw(this, data, sig); case SIGN_RSA_EMSA_PKCS1_SHA2_224: - return sign_pkcs1(this, HASH_SHA224, "sha224", data, sig); + return sign_pkcs1(this, HASH_SHA224, NULL, data, sig); case SIGN_RSA_EMSA_PKCS1_SHA2_256: - return sign_pkcs1(this, HASH_SHA256, "sha256", data, sig); + return sign_pkcs1(this, HASH_SHA256, NULL, data, sig); case SIGN_RSA_EMSA_PKCS1_SHA2_384: - return sign_pkcs1(this, HASH_SHA384, "sha384", data, sig); + return sign_pkcs1(this, HASH_SHA384, NULL, data, sig); case SIGN_RSA_EMSA_PKCS1_SHA2_512: - return sign_pkcs1(this, HASH_SHA512, "sha512", data, sig); + return sign_pkcs1(this, HASH_SHA512, NULL, data, sig); case SIGN_RSA_EMSA_PKCS1_SHA1: - return sign_pkcs1(this, HASH_SHA1, "sha1", data, sig); + return sign_pkcs1(this, HASH_SHA1, NULL, data, sig); case SIGN_RSA_EMSA_PKCS1_MD5: - return sign_pkcs1(this, HASH_MD5, "md5", data, sig); + return sign_pkcs1(this, HASH_MD5, NULL, data, sig); +#if GCRYPT_VERSION_NUMBER >= 0x010700 + case SIGN_RSA_EMSA_PSS: + return sign_pss(this, params, data, sig); +#endif default: DBG1(DBG_LIB, "signature scheme %N not supported in RSA", signature_scheme_names, scheme); @@ -498,16 +553,131 @@ gcrypt_rsa_private_key_t *gcrypt_rsa_private_key_gen(key_type_t type, } /** + * Recover the primes from n, e and d using the algorithm described in + * Appendix C of NIST SP 800-56B. + */ +static bool calculate_pqu(chunk_t cn, chunk_t ce, chunk_t cd, chunk_t *cp, + chunk_t *cq, chunk_t *cu) +{ + gcry_mpi_t n, e, d, p, q, u, k, r, g, y, n1, x, two; + int i, t, j; + gcry_error_t err; + bool success = FALSE; + + n = e = d = p = q = u = k = r = g = y = n1 = x = two = NULL; + err = gcry_mpi_scan(&n, GCRYMPI_FMT_USG, cn.ptr, cn.len, NULL) + | gcry_mpi_scan(&e, GCRYMPI_FMT_USG, ce.ptr, ce.len, NULL) + | gcry_mpi_scan(&d, GCRYMPI_FMT_USG, cd.ptr, cd.len, NULL); + if (err) + { + goto error; + } + /* k = (d * e) - 1 */ + k = gcry_mpi_new(gcry_mpi_get_nbits(n)); + gcry_mpi_mul(k, d, e); + gcry_mpi_sub_ui(k, k, 1); + if (gcry_mpi_test_bit(k, 0)) + { + goto error; + } + /* k = 2^t * r, where r is the largest odd integer dividing k, and t >= 1 */ + r = gcry_mpi_copy(k); + for (t = 0; !gcry_mpi_test_bit(r, 0); t++) + { /* r = r/2 */ + gcry_mpi_rshift(r, r, 1); + } + /* we need n-1 below */ + n1 = gcry_mpi_new(gcry_mpi_get_nbits(n)); + gcry_mpi_sub_ui(n1, n, 1); + y = gcry_mpi_new(gcry_mpi_get_nbits(n)); + g = gcry_mpi_new(gcry_mpi_get_nbits(n)); + x = gcry_mpi_new(gcry_mpi_get_nbits(n)); + two = gcry_mpi_set_ui(NULL, 2); + for (i = 0; i < 100; i++) + { /* generate random integer g in [0, n-1] */ + do + { + gcry_mpi_randomize(g, gcry_mpi_get_nbits(n), GCRY_WEAK_RANDOM); + } + while (gcry_mpi_cmp(n, g) <= 0); + /* y = g^r mod n */ + gcry_mpi_powm(y, g, r, n); + /* try again if y == 1 or y == n-1 */ + if (gcry_mpi_cmp_ui(y, 1) == 0 || gcry_mpi_cmp(y, n1) == 0) + { + continue; + } + for (j = 0; j < t; j++) + { /* x = y^2 mod n */ + gcry_mpi_powm(x, y, two, n); + /* stop if x == 1 */ + if (gcry_mpi_cmp_ui(x, 1) == 0) + { + goto done; + } + /* retry with new g if x = n-1 */ + if (gcry_mpi_cmp(x, n1) == 0) + { + break; + } + /* y = x */ + gcry_mpi_set(y, x); + } + } + goto error; + +done: + /* p = gcd(y-1, n) */ + gcry_mpi_sub_ui(y, y, 1); + p = gcry_mpi_new(gcry_mpi_get_nbits(n)); + gcry_mpi_gcd(p, y, n); + /* q = n/p */ + q = gcry_mpi_new(gcry_mpi_get_nbits(n)); + gcry_mpi_div(q, NULL, n, p, 0); + if (gcry_mpi_cmp(p, q) > 0) + { /* gcrypt expects q < p */ + gcry_mpi_swap(p, q); + } + /* u = q^-1 mod p */ + u = gcry_mpi_new(gcry_mpi_get_nbits(n)); + gcry_mpi_invm(u, p, q); + err = gcry_mpi_aprint(GCRYMPI_FMT_USG, &cp->ptr, &cp->len, p) + | gcry_mpi_aprint(GCRYMPI_FMT_USG, &cq->ptr, &cq->len, q) + | gcry_mpi_aprint(GCRYMPI_FMT_USG, &cu->ptr, &cu->len, u); + if (err) + { + goto error; + } + success = TRUE; + +error: + gcry_mpi_release(n); + gcry_mpi_release(e); + gcry_mpi_release(d); + gcry_mpi_release(p); + gcry_mpi_release(q); + gcry_mpi_release(u); + gcry_mpi_release(k); + gcry_mpi_release(r); + gcry_mpi_release(g); + gcry_mpi_release(y); + gcry_mpi_release(n1); + gcry_mpi_release(x); + gcry_mpi_release(two); + return success; +} + +/** * See header. */ gcrypt_rsa_private_key_t *gcrypt_rsa_private_key_load(key_type_t type, va_list args) { private_gcrypt_rsa_private_key_t *this; - chunk_t n, e, d, p, q, u; + chunk_t n, e, d, p, q, u, np, nq, nu; gcry_error_t err; - n = e = d = p = q = u = chunk_empty; + n = e = d = p = q = u = np = nq = nu = chunk_empty; while (TRUE) { switch (va_arg(args, builder_part_t)) @@ -543,12 +713,25 @@ gcrypt_rsa_private_key_t *gcrypt_rsa_private_key_load(key_type_t type, } break; } - + if (!p.len || !q.len || !u.len) + { + if (!calculate_pqu(n, e, d, &np, &nq, &nu)) + { + return NULL; + } + p = np; + q = nq; + u = nu; + } this = create_empty(); err = gcry_sexp_build(&this->key, NULL, "(private-key(rsa(n %b)(e %b)(d %b)(p %b)(q %b)(u %b)))", n.len, n.ptr, e.len, e.ptr, d.len, d.ptr, p.len, p.ptr, q.len, q.ptr, u.len, u.ptr); + + chunk_clear(&np); + chunk_clear(&nq); + chunk_clear(&nu); if (err) { DBG1(DBG_LIB, "loading private key failed: %s", gpg_strerror(err)); diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c index 90829e052..9e2ac1287 100644 --- a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c +++ b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c @@ -1,6 +1,7 @@ /* + * Copyright (C) 2017 Tobias Brunner * Copyright (C) 2005-2009 Martin Willi - * 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 @@ -22,6 +23,7 @@ #include <asn1/asn1.h> #include <asn1/asn1_parser.h> #include <crypto/hashers/hasher.h> +#include <credentials/keys/signature_params.h> typedef struct private_gcrypt_rsa_public_key_t private_gcrypt_rsa_public_key_t; @@ -109,27 +111,48 @@ static bool verify_raw(private_gcrypt_rsa_public_key_t *this, } /** - * Verification of an EMSA PKCS1 signature described in PKCS#1 + * Verification of an EMSA PKCS1v1.5 / EMSA-PSS signature described in PKCS#1 */ static bool verify_pkcs1(private_gcrypt_rsa_public_key_t *this, - hash_algorithm_t algorithm, char *hash_name, + hash_algorithm_t algorithm, rsa_pss_params_t *pss, chunk_t data, chunk_t signature) { hasher_t *hasher; chunk_t hash; gcry_error_t err; gcry_sexp_t in, sig; + char *hash_name = enum_to_name(hash_algorithm_short_names, algorithm); hasher = lib->crypto->create_hasher(lib->crypto, algorithm); - if (!hasher || !hasher->allocate_hash(hasher, data, &hash)) + if (!hasher) { - DESTROY_IF(hasher); + DBG1(DBG_LIB, "hash algorithm %N not supported", + hash_algorithm_names, algorithm); + return FALSE; + } + if (!hasher->allocate_hash(hasher, data, &hash)) + { + hasher->destroy(hasher); return FALSE; } hasher->destroy(hasher); - err = gcry_sexp_build(&in, NULL, "(data(flags pkcs1)(hash %s %b))", - hash_name, hash.len, hash.ptr); + if (pss) + { + u_int slen = hasher_hash_size(algorithm); + if (pss->salt_len > RSA_PSS_SALT_LEN_DEFAULT) + { + slen = pss->salt_len; + } + err = gcry_sexp_build(&in, NULL, + "(data(flags pss)(salt-length %u)(hash %s %b))", + slen, hash_name, hash.len, hash.ptr); + } + else + { + err = gcry_sexp_build(&in, NULL, "(data(flags pkcs1)(hash %s %b))", + hash_name, hash.len, hash.ptr); + } chunk_free(&hash); if (err) { @@ -159,6 +182,26 @@ static bool verify_pkcs1(private_gcrypt_rsa_public_key_t *this, return TRUE; } +#if GCRYPT_VERSION_NUMBER >= 0x010700 +/** + * Verification of an EMSA-PSS signature described in PKCS#1 + */ +static bool verify_pss(private_gcrypt_rsa_public_key_t *this, + rsa_pss_params_t *params, chunk_t data, chunk_t sig) +{ + if (!params) + { + return FALSE; + } + if (params->mgf1_hash != params->hash) + { + DBG1(DBG_LIB, "unable to use a different MGF1 hash for RSA-PSS"); + return FALSE; + } + return verify_pkcs1(this, params->hash, params, data, sig); +} +#endif + METHOD(public_key_t, get_type, key_type_t, private_gcrypt_rsa_public_key_t *this) { @@ -167,24 +210,28 @@ METHOD(public_key_t, get_type, key_type_t, METHOD(public_key_t, verify, bool, private_gcrypt_rsa_public_key_t *this, signature_scheme_t scheme, - chunk_t data, chunk_t signature) + void *params, chunk_t data, chunk_t signature) { switch (scheme) { case SIGN_RSA_EMSA_PKCS1_NULL: return verify_raw(this, data, signature); case SIGN_RSA_EMSA_PKCS1_SHA2_224: - return verify_pkcs1(this, HASH_SHA224, "sha224", data, signature); + return verify_pkcs1(this, HASH_SHA224, NULL, data, signature); case SIGN_RSA_EMSA_PKCS1_SHA2_256: - return verify_pkcs1(this, HASH_SHA256, "sha256", data, signature); + return verify_pkcs1(this, HASH_SHA256, NULL, data, signature); case SIGN_RSA_EMSA_PKCS1_SHA2_384: - return verify_pkcs1(this, HASH_SHA384, "sha384", data, signature); + return verify_pkcs1(this, HASH_SHA384, NULL, data, signature); case SIGN_RSA_EMSA_PKCS1_SHA2_512: - return verify_pkcs1(this, HASH_SHA512, "sha512", data, signature); + return verify_pkcs1(this, HASH_SHA512, NULL, data, signature); case SIGN_RSA_EMSA_PKCS1_SHA1: - return verify_pkcs1(this, HASH_SHA1, "sha1", data, signature); + return verify_pkcs1(this, HASH_SHA1, NULL, data, signature); case SIGN_RSA_EMSA_PKCS1_MD5: - return verify_pkcs1(this, HASH_MD5, "md5", data, signature); + return verify_pkcs1(this, HASH_MD5, NULL, data, signature); +#if GCRYPT_VERSION_NUMBER >= 0x010700 + case SIGN_RSA_EMSA_PSS: + return verify_pss(this, params, data, signature); +#endif default: DBG1(DBG_LIB, "signature scheme %N not supported in RSA", signature_scheme_names, scheme); |