diff options
author | Tobias Brunner <tobias@strongswan.org> | 2017-10-10 15:52:19 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2017-11-08 16:48:10 +0100 |
commit | c2935b03c4477a333e0ccb5d9811af7a89a6fa52 (patch) | |
tree | 4489accd428de889c45dfb778f3e69ab0f600321 | |
parent | 72b7c0ffd820895e73973108426c47123499c78f (diff) | |
download | strongswan-c2935b03c4477a333e0ccb5d9811af7a89a6fa52.tar.bz2 strongswan-c2935b03c4477a333e0ccb5d9811af7a89a6fa52.tar.xz |
signature-params: Add helper struct for signature scheme and parameters
-rw-r--r-- | src/libstrongswan/credentials/keys/signature_params.c | 163 | ||||
-rw-r--r-- | src/libstrongswan/credentials/keys/signature_params.h | 46 | ||||
-rw-r--r-- | src/libstrongswan/tests/suites/test_signature_params.c | 128 |
3 files changed, 319 insertions, 18 deletions
diff --git a/src/libstrongswan/credentials/keys/signature_params.c b/src/libstrongswan/credentials/keys/signature_params.c index 72a61e15a..e8ac75d3b 100644 --- a/src/libstrongswan/credentials/keys/signature_params.c +++ b/src/libstrongswan/credentials/keys/signature_params.c @@ -19,6 +19,147 @@ #include <asn1/asn1_parser.h> /** + * Determine the salt length in case it is not configured + */ +static ssize_t rsa_pss_salt_length(rsa_pss_params_t *pss) +{ + ssize_t salt_len = pss->salt_len; + + if (salt_len <= RSA_PSS_SALT_LEN_DEFAULT) + { + salt_len = hasher_hash_size(pss->hash); + if (!salt_len) + { + return -1; + } + } + return salt_len; +} + +/** + * Compare two signature schemes and their parameters + */ +static bool compare_params(signature_params_t *a, signature_params_t *b, + bool strict) +{ + if (!a && !b) + { + return TRUE; + } + if (!a || !b) + { + return FALSE; + } + if (a->scheme != b->scheme) + { + return FALSE; + } + if (!a->params && !b->params) + { + return TRUE; + } + if (a->params && b->params) + { + switch (a->scheme) + { + case SIGN_RSA_EMSA_PSS: + { + rsa_pss_params_t *pss_a = a->params, *pss_b = b->params; + + return pss_a->hash == pss_b->hash && + pss_a->mgf1_hash == pss_b->mgf1_hash && + (!strict || + rsa_pss_salt_length(pss_a) == rsa_pss_salt_length(pss_b)); + } + default: + break; + } + } + return FALSE; +} + +/* + * Described in header + */ +bool signature_params_equal(signature_params_t *a, signature_params_t *b) +{ + return compare_params(a, b, TRUE); +} + +/* + * Described in header + */ +bool signature_params_comply(signature_params_t *c, signature_params_t *s) +{ /* the salt is variable, so it does not necessarily have to be the same */ + return compare_params(c, s, FALSE); +} + +/* + * Described in header + */ +signature_params_t *signature_params_clone(signature_params_t *this) +{ + signature_params_t *clone; + + if (!this) + { + return NULL; + } + + INIT(clone, + .scheme = this->scheme, + ); + if (this->params) + { + switch (this->scheme) + { + case SIGN_RSA_EMSA_PSS: + { + rsa_pss_params_t *pss, *pss_clone; + + pss = this->params; + INIT(pss_clone, + .hash = pss->hash, + .mgf1_hash = pss->mgf1_hash, + .salt_len = pss->salt_len, + /* ignore salt as only used for unit tests */ + ); + clone->params = pss_clone; + break; + } + default: + break; + } + } + return clone; +} + +/* + * Described in header + */ +void signature_params_destroy(signature_params_t *this) +{ + if (this) + { + free(this->params); + free(this); + } +} + +/* + * Described in header + */ +void signature_params_clear(signature_params_t *this) +{ + if (this) + { + free(this->params); + this->params = NULL; + this->scheme = SIGN_UNKNOWN; + } +} + +/** * ASN.1 definition of RSASSA-PSS-params */ static const asn1Object_t RSASSAPSSParamsObjects[] = { @@ -119,6 +260,7 @@ end: bool rsa_pss_params_build(rsa_pss_params_t *params, chunk_t *asn1) { chunk_t hash = chunk_empty, mgf = chunk_empty, slen = chunk_empty; + ssize_t salt_len; int alg; if (params->hash != HASH_SHA1) @@ -141,23 +283,16 @@ bool rsa_pss_params_build(rsa_pss_params_t *params, chunk_t *asn1) mgf = asn1_wrap(ASN1_SEQUENCE, "mm", asn1_build_known_oid(OID_MGF1), asn1_algorithmIdentifier(alg)); } - if (params->salt_len > RSA_PSS_SALT_LEN_DEFAULT) + salt_len = rsa_pss_salt_length(params); + if (salt_len < 0) { - if (params->salt_len != HASH_SIZE_SHA1) - { - slen = asn1_integer("m", asn1_integer_from_uint64(params->salt_len)); - } + chunk_free(&hash); + chunk_free(&mgf); + return FALSE; } - else if (params->hash != HASH_SHA1) + else if (salt_len != HASH_SIZE_SHA1) { - size_t hlen = hasher_hash_size(params->hash); - if (!hlen) - { - chunk_free(&hash); - chunk_free(&mgf); - return FALSE; - } - slen = asn1_integer("m", asn1_integer_from_uint64(hlen)); + slen = asn1_integer("m", asn1_integer_from_uint64(salt_len)); } *asn1 = asn1_wrap(ASN1_SEQUENCE, "mmm", hash.len ? asn1_wrap(ASN1_CONTEXT_C_0, "m", hash) : chunk_empty, diff --git a/src/libstrongswan/credentials/keys/signature_params.h b/src/libstrongswan/credentials/keys/signature_params.h index 52a7ad7e5..4cde94c8f 100644 --- a/src/libstrongswan/credentials/keys/signature_params.h +++ b/src/libstrongswan/credentials/keys/signature_params.h @@ -21,11 +21,57 @@ #ifndef SIGNATURE_PARAMS_H_ #define SIGNATURE_PARAMS_H_ +typedef struct signature_params_t signature_params_t; typedef struct rsa_pss_params_t rsa_pss_params_t; #include <crypto/hashers/hasher.h> /** + * Signature scheme with parameters + */ +struct signature_params_t { + /** Signature scheme */ + signature_scheme_t scheme; + /** Parameters, depending on scheme */ + void *params; +}; + +/** + * Compare two signature schemes and their parameters + * + * @param a first scheme + * @param b second scheme + * @return TRUE if schemes and parameters are equal + */ +bool signature_params_equal(signature_params_t *a, signature_params_t *b); + +/** + * Compare two signature schemes and their parameters + * + * @param c constraint + * @param s scheme + * @return TRUE if scheme complies to constraint + */ +bool signature_params_comply(signature_params_t *c, signature_params_t *s); + +/** + * Clone the given scheme and parameters, if any + * + * @return cloned object + */ +signature_params_t *signature_params_clone(signature_params_t *this); + +/** + * Destroy the given scheme and parameters, if any + */ +void signature_params_destroy(signature_params_t *this); + +/** + * Clear the given parameters, if any, sets the scheme to SIGN_UNKNOWN + */ +void signature_params_clear(signature_params_t *this); + +/** * Parameters for SIGN_RSA_EMSA_PSS signature scheme */ struct rsa_pss_params_t { diff --git a/src/libstrongswan/tests/suites/test_signature_params.c b/src/libstrongswan/tests/suites/test_signature_params.c index 0b6988076..0ac00c3c7 100644 --- a/src/libstrongswan/tests/suites/test_signature_params.c +++ b/src/libstrongswan/tests/suites/test_signature_params.c @@ -19,7 +19,7 @@ #include <asn1/asn1.h> #include <credentials/keys/signature_params.h> -struct { +static struct { chunk_t aid; rsa_pss_params_t params; } rsa_pss_parse_tests[] = { @@ -125,7 +125,7 @@ START_TEST(test_rsa_pss_params_parse_invalid) } END_TEST -struct { +static struct { chunk_t aid; rsa_pss_params_t params; } rsa_pss_build_tests[] = { @@ -209,6 +209,111 @@ START_TEST(test_rsa_pss_params_build_invalid) } END_TEST +static rsa_pss_params_t rsa_pss_params_sha1 = { .hash = HASH_SHA1, .mgf1_hash = HASH_SHA1, .salt_len = HASH_SIZE_SHA1, }; +static rsa_pss_params_t rsa_pss_params_sha256 = { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = HASH_SIZE_SHA256, }; +static rsa_pss_params_t rsa_pss_params_sha256_mgf1 = { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA512, .salt_len = HASH_SIZE_SHA256, }; +static rsa_pss_params_t rsa_pss_params_sha256_salt = { .hash = HASH_SHA256, .mgf1_hash = HASH_SHA256, .salt_len = 10, }; + +static struct { + bool equal; + bool complies; + signature_params_t a; + signature_params_t b; +} params_compare_tests[] = { + { TRUE, TRUE, { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_256, }, { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_256, }, }, + { FALSE, FALSE, { .scheme = SIGN_RSA_EMSA_PKCS1_SHA1, }, { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_256, }, }, + { TRUE, TRUE, { .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha256 }, + { .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha256 }, }, + { FALSE, FALSE, { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_256, .params = &rsa_pss_params_sha256 }, + { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_256, .params = &rsa_pss_params_sha256 }, }, + { FALSE, FALSE, { .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha256 }, + { .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha256_mgf1 }, }, + { FALSE, TRUE, { .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha256 }, + { .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha256_salt }, }, + { FALSE, FALSE, { .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha1 }, + { .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha256 }, }, + { FALSE, FALSE, { .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha256 }, + { .scheme = SIGN_RSA_EMSA_PSS, }, }, +}; + +START_TEST(test_params_compare) +{ + bool res; + + res = signature_params_equal(¶ms_compare_tests[_i].a, + ¶ms_compare_tests[_i].b); + ck_assert(res == params_compare_tests[_i].equal); + res = signature_params_comply(¶ms_compare_tests[_i].a, + ¶ms_compare_tests[_i].b); + ck_assert(res == params_compare_tests[_i].complies); + res = signature_params_comply(¶ms_compare_tests[_i].b, + ¶ms_compare_tests[_i].a); + ck_assert(res == params_compare_tests[_i].complies); +} +END_TEST + +START_TEST(test_params_compare_null) +{ + ck_assert(signature_params_equal(NULL, NULL)); + ck_assert(!signature_params_equal(¶ms_compare_tests[0].a, NULL)); + ck_assert(!signature_params_equal(NULL, ¶ms_compare_tests[0].a)); +} +END_TEST + +static struct { + signature_params_t src; + signature_params_t res; +} params_clone_tests[] = { + { { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_256, }, { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_256, }, }, + { { .scheme = SIGN_RSA_EMSA_PSS }, { .scheme = SIGN_RSA_EMSA_PSS }, }, + { { .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha256 }, + { .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha256 }, }, + { { .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha256_salt }, + { .scheme = SIGN_RSA_EMSA_PSS, .params = &rsa_pss_params_sha256_salt }, }, + { { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_256, .params = &rsa_pss_params_sha256 }, + { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_256 }, }, +}; + +START_TEST(test_params_clone) +{ + signature_params_t *clone = NULL; + + clone = signature_params_clone(¶ms_clone_tests[_i].src); + ck_assert(signature_params_equal(clone, ¶ms_clone_tests[_i].res)); + signature_params_destroy(clone); +} +END_TEST + +START_TEST(test_params_clone_null) +{ + signature_params_t *clone = NULL; + + clone = signature_params_clone(clone); + ck_assert(!clone); + signature_params_destroy(clone); +} +END_TEST + +START_TEST(test_params_clear) +{ + signature_params_t *clone; + + clone = signature_params_clone(¶ms_clone_tests[_i].src); + signature_params_clear(clone); + ck_assert_int_eq(clone->scheme, SIGN_UNKNOWN); + ck_assert(!clone->params); + free(clone); +} +END_TEST + +START_TEST(test_params_clear_null) +{ + signature_params_t *clone = NULL; + + signature_params_clear(clone); +} +END_TEST + Suite *signature_params_suite_create() { Suite *s; @@ -216,15 +321,30 @@ Suite *signature_params_suite_create() s = suite_create("signature params"); - tc = tcase_create("parse"); + tc = tcase_create("rsa/pss parse"); tcase_add_loop_test(tc, test_rsa_pss_params_parse, 0, countof(rsa_pss_parse_tests)); tcase_add_loop_test(tc, test_rsa_pss_params_parse_invalid, 0, countof(rsa_pss_parse_invalid_tests)); suite_add_tcase(s, tc); - tc = tcase_create("build"); + tc = tcase_create("rsa/pss build"); tcase_add_loop_test(tc, test_rsa_pss_params_build, 0, countof(rsa_pss_build_tests)); tcase_add_loop_test(tc, test_rsa_pss_params_build_invalid, 0, countof(rsa_pss_build_invalid_tests)); suite_add_tcase(s, tc); + tc = tcase_create("params compare"); + tcase_add_loop_test(tc, test_params_compare, 0, countof(params_compare_tests)); + tcase_add_test(tc, test_params_compare_null); + suite_add_tcase(s, tc); + + tc = tcase_create("params clone"); + tcase_add_loop_test(tc, test_params_clone, 0, countof(params_clone_tests)); + tcase_add_test(tc, test_params_clone_null); + suite_add_tcase(s, tc); + + tc = tcase_create("params clear"); + tcase_add_loop_test(tc, test_params_clear, 0, countof(params_clone_tests)); + tcase_add_test(tc, test_params_clear_null); + suite_add_tcase(s, tc); + return s; } |