diff options
Diffstat (limited to 'src/libstrongswan/plugins/gmp')
-rw-r--r-- | src/libstrongswan/plugins/gmp/Makefile.in | 11 | ||||
-rw-r--r-- | src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c | 68 | ||||
-rw-r--r-- | src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c | 158 |
3 files changed, 60 insertions, 177 deletions
diff --git a/src/libstrongswan/plugins/gmp/Makefile.in b/src/libstrongswan/plugins/gmp/Makefile.in index 11aef42f0..a74d76201 100644 --- a/src/libstrongswan/plugins/gmp/Makefile.in +++ b/src/libstrongswan/plugins/gmp/Makefile.in @@ -311,7 +311,6 @@ PYTHON_VERSION = @PYTHON_VERSION@ PY_TEST = @PY_TEST@ RANLIB = @RANLIB@ RTLIB = @RTLIB@ -RUBY = @RUBY@ RUBYGEMDIR = @RUBYGEMDIR@ SED = @SED@ SET_MAKE = @SET_MAKE@ @@ -337,6 +336,8 @@ am__tar = @am__tar@ am__untar = @am__untar@ attest_plugins = @attest_plugins@ bindir = @bindir@ +botan_CFLAGS = @botan_CFLAGS@ +botan_LIBS = @botan_LIBS@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ @@ -357,8 +358,6 @@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ fips_mode = @fips_mode@ fuzz_plugins = @fuzz_plugins@ -gtk_CFLAGS = @gtk_CFLAGS@ -gtk_LIBS = @gtk_LIBS@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ @@ -413,8 +412,6 @@ random_device = @random_device@ resolv_conf = @resolv_conf@ routing_table = @routing_table@ routing_table_prio = @routing_table_prio@ -ruby_CFLAGS = @ruby_CFLAGS@ -ruby_LIBS = @ruby_LIBS@ runstatedir = @runstatedir@ s_plugins = @s_plugins@ sbindir = @sbindir@ @@ -443,8 +440,12 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ tss2_CFLAGS = @tss2_CFLAGS@ tss2_LIBS = @tss2_LIBS@ +tss2_esys_CFLAGS = @tss2_esys_CFLAGS@ +tss2_esys_LIBS = @tss2_esys_LIBS@ tss2_socket_CFLAGS = @tss2_socket_CFLAGS@ tss2_socket_LIBS = @tss2_socket_LIBS@ +tss2_sys_CFLAGS = @tss2_sys_CFLAGS@ +tss2_sys_LIBS = @tss2_sys_LIBS@ tss2_tabrmd_CFLAGS = @tss2_tabrmd_CFLAGS@ tss2_tabrmd_LIBS = @tss2_tabrmd_LIBS@ urandom_device = @urandom_device@ diff --git a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c index 241ef7d3b..e9a83fdf4 100644 --- a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c +++ b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Tobias Brunner + * Copyright (C) 2017-2018 Tobias Brunner * Copyright (C) 2005 Jan Hutter * Copyright (C) 2005-2009 Martin Willi * Copyright (C) 2012 Andreas Steffen @@ -264,14 +264,15 @@ static chunk_t rsasp1(private_gmp_rsa_private_key_t *this, chunk_t data) } /** - * Build a signature using the PKCS#1 EMSA scheme + * Hashes the data and builds the plaintext signature value with EMSA + * PKCS#1 v1.5 padding. + * + * Allocates the signature data. */ -static bool build_emsa_pkcs1_signature(private_gmp_rsa_private_key_t *this, - hash_algorithm_t hash_algorithm, - chunk_t data, chunk_t *signature) +bool gmp_emsa_pkcs1_signature_data(hash_algorithm_t hash_algorithm, + chunk_t data, size_t keylen, chunk_t *em) { chunk_t digestInfo = chunk_empty; - chunk_t em; if (hash_algorithm != HASH_UNKNOWN) { @@ -295,43 +296,56 @@ static bool build_emsa_pkcs1_signature(private_gmp_rsa_private_key_t *this, /* build DER-encoded digestInfo */ digestInfo = asn1_wrap(ASN1_SEQUENCE, "mm", asn1_algorithmIdentifier(hash_oid), - asn1_simple_object(ASN1_OCTET_STRING, hash) - ); - chunk_free(&hash); + asn1_wrap(ASN1_OCTET_STRING, "m", hash)); + data = digestInfo; } - if (data.len > this->k - 3) + if (data.len > keylen - 11) { - free(digestInfo.ptr); - DBG1(DBG_LIB, "unable to sign %d bytes using a %dbit key", data.len, - mpz_sizeinbase(this->n, 2)); + chunk_free(&digestInfo); + DBG1(DBG_LIB, "signature value of %zu bytes is too long for key of " + "%zu bytes", data.len, keylen); return FALSE; } - /* build chunk to rsa-decrypt: - * EM = 0x00 || 0x01 || PS || 0x00 || T. - * PS = 0xFF padding, with length to fill em + /* EM = 0x00 || 0x01 || PS || 0x00 || T. + * PS = 0xFF padding, with length to fill em (at least 8 bytes) * T = encoded_hash */ - em.len = this->k; - em.ptr = malloc(em.len); + *em = chunk_alloc(keylen); /* fill em with padding */ - memset(em.ptr, 0xFF, em.len); + memset(em->ptr, 0xFF, em->len); /* set magic bytes */ - *(em.ptr) = 0x00; - *(em.ptr+1) = 0x01; - *(em.ptr + em.len - data.len - 1) = 0x00; - /* set DER-encoded hash */ - memcpy(em.ptr + em.len - data.len, data.ptr, data.len); + *(em->ptr) = 0x00; + *(em->ptr+1) = 0x01; + *(em->ptr + em->len - data.len - 1) = 0x00; + /* set encoded hash */ + memcpy(em->ptr + em->len - data.len, data.ptr, data.len); + + chunk_clear(&digestInfo); + return TRUE; +} + +/** + * Build a signature using the PKCS#1 EMSA scheme + */ +static bool build_emsa_pkcs1_signature(private_gmp_rsa_private_key_t *this, + hash_algorithm_t hash_algorithm, + chunk_t data, chunk_t *signature) +{ + chunk_t em; + + if (!gmp_emsa_pkcs1_signature_data(hash_algorithm, data, this->k, &em)) + { + return FALSE; + } /* build signature */ *signature = rsasp1(this, em); - free(digestInfo.ptr); - free(em.ptr); - + chunk_free(&em); return TRUE; } diff --git a/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c b/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c index 52bc9fb38..9b5ee67fa 100644 --- a/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c +++ b/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 Tobias Brunner + * Copyright (C) 2017-2018 Tobias Brunner * Copyright (C) 2005-2009 Martin Willi * Copyright (C) 2005 Jan Hutter * HSR Hochschule fuer Technik Rapperswil @@ -70,7 +70,9 @@ struct private_gmp_rsa_public_key_t { /** * Shared functions defined in gmp_rsa_private_key.c */ -extern chunk_t gmp_mpz_to_chunk(const mpz_t value); +chunk_t gmp_mpz_to_chunk(const mpz_t value); +bool gmp_emsa_pkcs1_signature_data(hash_algorithm_t hash_algorithm, + chunk_t data, size_t keylen, chunk_t *em); /** * RSAEP algorithm specified in PKCS#1. @@ -115,26 +117,13 @@ static chunk_t rsavp1(private_gmp_rsa_public_key_t *this, chunk_t data) } /** - * ASN.1 definition of digestInfo - */ -static const asn1Object_t digestInfoObjects[] = { - { 0, "digestInfo", ASN1_SEQUENCE, ASN1_OBJ }, /* 0 */ - { 1, "digestAlgorithm", ASN1_EOC, ASN1_RAW }, /* 1 */ - { 1, "digest", ASN1_OCTET_STRING, ASN1_BODY }, /* 2 */ - { 0, "exit", ASN1_EOC, ASN1_EXIT } -}; -#define DIGEST_INFO 0 -#define DIGEST_INFO_ALGORITHM 1 -#define DIGEST_INFO_DIGEST 2 - -/** * 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, chunk_t data, chunk_t signature) { - chunk_t em_ori, em; + chunk_t em_expected, em; bool success = FALSE; /* remove any preceding 0-bytes from signature */ @@ -148,140 +137,19 @@ static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this, return FALSE; } - /* unpack signature */ - em_ori = em = rsavp1(this, signature); - - /* result should look like this: - * EM = 0x00 || 0x01 || PS || 0x00 || T. - * PS = 0xFF padding, with length to fill em - * T = oid || hash - */ - - /* check magic bytes */ - if (em.len < 2 || *(em.ptr) != 0x00 || *(em.ptr+1) != 0x01) + /* generate expected signature value */ + if (!gmp_emsa_pkcs1_signature_data(algorithm, data, this->k, &em_expected)) { - goto end; - } - em = chunk_skip(em, 2); - - /* find magic 0x00 */ - while (em.len > 0) - { - if (*em.ptr == 0x00) - { - /* found magic byte, stop */ - em = chunk_skip(em, 1); - break; - } - else if (*em.ptr != 0xFF) - { - /* bad padding, decryption failed ?!*/ - goto end; - } - em = chunk_skip(em, 1); - } - - if (em.len == 0) - { - /* no digestInfo found */ - goto end; - } - - if (algorithm == HASH_UNKNOWN) - { /* IKEv1 signatures without digestInfo */ - if (em.len != data.len) - { - DBG1(DBG_LIB, "hash size in signature is %u bytes instead of" - " %u bytes", em.len, data.len); - goto end; - } - success = memeq_const(em.ptr, data.ptr, data.len); + return FALSE; } - else - { /* IKEv2 and X.509 certificate signatures */ - asn1_parser_t *parser; - chunk_t object; - int objectID; - hash_algorithm_t hash_algorithm = HASH_UNKNOWN; - - DBG2(DBG_LIB, "signature verification:"); - parser = asn1_parser_create(digestInfoObjects, em); - while (parser->iterate(parser, &objectID, &object)) - { - switch (objectID) - { - case DIGEST_INFO: - { - if (em.len > object.len) - { - DBG1(DBG_LIB, "digestInfo field in signature is" - " followed by %u surplus bytes", - em.len - object.len); - goto end_parser; - } - break; - } - case DIGEST_INFO_ALGORITHM: - { - int hash_oid = asn1_parse_algorithmIdentifier(object, - parser->get_level(parser)+1, NULL); - - hash_algorithm = hasher_algorithm_from_oid(hash_oid); - if (hash_algorithm == HASH_UNKNOWN || hash_algorithm != algorithm) - { - DBG1(DBG_LIB, "expected hash algorithm %N, but found" - " %N (OID: %#B)", hash_algorithm_names, algorithm, - hash_algorithm_names, hash_algorithm, &object); - goto end_parser; - } - break; - } - case DIGEST_INFO_DIGEST: - { - chunk_t hash; - hasher_t *hasher; - - hasher = lib->crypto->create_hasher(lib->crypto, hash_algorithm); - if (hasher == NULL) - { - DBG1(DBG_LIB, "hash algorithm %N not supported", - hash_algorithm_names, hash_algorithm); - goto end_parser; - } - - if (object.len != hasher->get_hash_size(hasher)) - { - DBG1(DBG_LIB, "hash size in signature is %u bytes" - " instead of %u bytes", object.len, - hasher->get_hash_size(hasher)); - hasher->destroy(hasher); - goto end_parser; - } - - /* build our own hash and compare */ - if (!hasher->allocate_hash(hasher, data, &hash)) - { - hasher->destroy(hasher); - goto end_parser; - } - hasher->destroy(hasher); - success = memeq_const(object.ptr, hash.ptr, hash.len); - free(hash.ptr); - break; - } - default: - break; - } - } + /* unpack signature */ + em = rsavp1(this, signature); -end_parser: - success &= parser->success(parser); - parser->destroy(parser); - } + success = chunk_equals_const(em_expected, em); -end: - free(em_ori.ptr); + chunk_free(&em_expected); + chunk_free(&em); return success; } |