diff options
author | Tobias Brunner <tobias@strongswan.org> | 2017-09-23 15:33:11 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2017-11-08 16:48:10 +0100 |
commit | 154ee7f66acbe76f01674b9e67c9cf074ef21013 (patch) | |
tree | bf3d01b9327fae5da9985ce573ec0e20cf62f252 | |
parent | 00d161f2dbcfa07d915aea0c88bd1ec80265a5ff (diff) | |
download | strongswan-154ee7f66acbe76f01674b9e67c9cf074ef21013.tar.bz2 strongswan-154ee7f66acbe76f01674b9e67c9cf074ef21013.tar.xz |
gmp: Add support for RSASSA-PSS signature creation
-rw-r--r-- | src/libstrongswan/plugins/gmp/gmp_plugin.c | 8 | ||||
-rw-r--r-- | src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c | 122 |
2 files changed, 130 insertions, 0 deletions
diff --git a/src/libstrongswan/plugins/gmp/gmp_plugin.c b/src/libstrongswan/plugins/gmp/gmp_plugin.c index c75975301..6b09f4f0d 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), diff --git a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c index 821ae7e1a..3a9296535 100644 --- a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c +++ b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c @@ -28,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 @@ -334,6 +335,125 @@ 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; + } + switch (params->mgf1_hash) + { + case HASH_SHA1: + xof = XOF_MGF1_SHA1; + break; + case HASH_SHA256: + xof = XOF_MGF1_SHA256; + break; + case HASH_SHA512: + xof = XOF_MGF1_SHA512; + break; + default: + 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 > RSA_PSS_SALT_LEN_DEFAULT) + { + salt.len = params->salt_len; + } + if (emlen < (hash.len + salt.len + 2)) + { /* too long */ + goto error; + } + if (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) { @@ -368,6 +488,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); |