aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2017-10-10 15:52:19 +0200
committerTobias Brunner <tobias@strongswan.org>2017-11-08 16:48:10 +0100
commitc2935b03c4477a333e0ccb5d9811af7a89a6fa52 (patch)
tree4489accd428de889c45dfb778f3e69ab0f600321
parent72b7c0ffd820895e73973108426c47123499c78f (diff)
downloadstrongswan-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.c163
-rw-r--r--src/libstrongswan/credentials/keys/signature_params.h46
-rw-r--r--src/libstrongswan/tests/suites/test_signature_params.c128
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(&params_compare_tests[_i].a,
+ &params_compare_tests[_i].b);
+ ck_assert(res == params_compare_tests[_i].equal);
+ res = signature_params_comply(&params_compare_tests[_i].a,
+ &params_compare_tests[_i].b);
+ ck_assert(res == params_compare_tests[_i].complies);
+ res = signature_params_comply(&params_compare_tests[_i].b,
+ &params_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(&params_compare_tests[0].a, NULL));
+ ck_assert(!signature_params_equal(NULL, &params_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(&params_clone_tests[_i].src);
+ ck_assert(signature_params_equal(clone, &params_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(&params_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;
}