public-key: Add helper to determine acceptable signature schemes for keys
authorTobias Brunner <tobias@strongswan.org>
Thu, 26 Feb 2015 16:31:18 +0000 (17:31 +0100)
committerTobias Brunner <tobias@strongswan.org>
Wed, 4 Mar 2015 12:54:10 +0000 (13:54 +0100)
src/libstrongswan/credentials/keys/public_key.c
src/libstrongswan/credentials/keys/public_key.h
src/libstrongswan/tests/suites/test_utils.c

index b6e5216..bd5915e 100644 (file)
@@ -191,6 +191,73 @@ int signature_scheme_to_oid(signature_scheme_t scheme)
        return OID_UNKNOWN;
 }
 
+/**
+ * Map for signature schemes to the key type and maximum key size allowed.
+ * We only cover schemes with hash algorithms supported by IKEv2 signature
+ * authentication.
+ */
+static struct {
+       signature_scheme_t scheme;
+       key_type_t type;
+       int max_keysize;
+} scheme_map[] = {
+       { SIGN_RSA_EMSA_PKCS1_SHA256, KEY_RSA,   3072 },
+       { SIGN_RSA_EMSA_PKCS1_SHA384, KEY_RSA,   7680 },
+       { SIGN_RSA_EMSA_PKCS1_SHA512, KEY_RSA,   0 },
+       { SIGN_ECDSA_WITH_SHA256_DER, KEY_ECDSA, 256 },
+       { SIGN_ECDSA_WITH_SHA384_DER, KEY_ECDSA, 384 },
+       { SIGN_ECDSA_WITH_SHA512_DER, KEY_ECDSA, 0 },
+       { SIGN_BLISS_WITH_SHA256,     KEY_BLISS, 128 },
+       { SIGN_BLISS_WITH_SHA384,     KEY_BLISS, 192 },
+       { SIGN_BLISS_WITH_SHA512,     KEY_BLISS, 0 },
+};
+
+/**
+ * Private data for signature scheme enumerator
+ */
+typedef struct  {
+       enumerator_t public;
+       int index;
+       key_type_t type;
+       int size;
+} private_enumerator_t;
+
+METHOD(enumerator_t, signature_schemes_enumerate, bool,
+       private_enumerator_t *this, signature_scheme_t *scheme)
+{
+       while (++this->index < countof(scheme_map))
+       {
+               if (this->type == scheme_map[this->index].type &&
+                  (this->size <= scheme_map[this->index].max_keysize ||
+                       !scheme_map[this->index].max_keysize))
+               {
+                       *scheme = scheme_map[this->index].scheme;
+                       return TRUE;
+               }
+       }
+       return FALSE;
+}
+
+/*
+ * Defined in header.
+ */
+enumerator_t *signature_schemes_for_key(key_type_t type, int size)
+{
+       private_enumerator_t *this;
+
+       INIT(this,
+               .public = {
+                       .enumerate = (void*)_signature_schemes_enumerate,
+                       .destroy = (void*)free,
+               },
+               .index = -1,
+               .type = type,
+               .size = size,
+       );
+
+       return &this->public;
+}
+
 /*
  * Defined in header.
  */
index a106663..66e98b2 100644 (file)
@@ -257,6 +257,16 @@ signature_scheme_t signature_scheme_from_oid(int oid);
 int signature_scheme_to_oid(signature_scheme_t scheme);
 
 /**
+ * Enumerate signature schemes that are appropriate for a key of the given type
+ * and size|strength.
+ *
+ * @param type                 type of the key
+ * @param size                 size or strength of the key
+ * @return                             enumerator over signature_scheme_t (increasing strength)
+ */
+enumerator_t *signature_schemes_for_key(key_type_t type, int size);
+
+/**
  * Determine the type of key associated with a given signature scheme.
  *
  * @param scheme               signature scheme
@@ -264,4 +274,5 @@ int signature_scheme_to_oid(signature_scheme_t scheme);
  */
 key_type_t key_type_from_signature_scheme(signature_scheme_t scheme);
 
+
 #endif /** PUBLIC_KEY_H_ @}*/
index abca462..85a8544 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Tobias Brunner
+ * Copyright (C) 2013-2015 Tobias Brunner
  * Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -18,6 +18,7 @@
 #include <library.h>
 #include <utils/utils.h>
 #include <ipsec/ipsec_types.h>
+#include <credentials/keys/public_key.h>
 
 #include <time.h>
 
@@ -695,6 +696,44 @@ START_TEST(test_mark_from_string)
 }
 END_TEST
 
+/*******************************************************************************
+ * signature_schemes_for_key
+ */
+
+static struct {
+       key_type_t type;
+       int size;
+       signature_scheme_t expected[4];
+} scheme_data[] = {
+       {KEY_RSA,   1024, { SIGN_RSA_EMSA_PKCS1_SHA256, SIGN_RSA_EMSA_PKCS1_SHA384, SIGN_RSA_EMSA_PKCS1_SHA512, SIGN_UNKNOWN }},
+       {KEY_RSA,   2048, { SIGN_RSA_EMSA_PKCS1_SHA256, SIGN_RSA_EMSA_PKCS1_SHA384, SIGN_RSA_EMSA_PKCS1_SHA512, SIGN_UNKNOWN }},
+       {KEY_RSA,   4096, { SIGN_RSA_EMSA_PKCS1_SHA384, SIGN_RSA_EMSA_PKCS1_SHA512, SIGN_UNKNOWN }},
+       {KEY_RSA,   8192, { SIGN_RSA_EMSA_PKCS1_SHA512, SIGN_UNKNOWN }},
+       {KEY_ECDSA,  256, { SIGN_ECDSA_WITH_SHA256_DER, SIGN_ECDSA_WITH_SHA384_DER, SIGN_ECDSA_WITH_SHA512_DER, SIGN_UNKNOWN }},
+       {KEY_ECDSA,  384, { SIGN_ECDSA_WITH_SHA384_DER, SIGN_ECDSA_WITH_SHA512_DER, SIGN_UNKNOWN }},
+       {KEY_ECDSA,  512, { SIGN_ECDSA_WITH_SHA512_DER, SIGN_UNKNOWN }},
+       {KEY_BLISS,  128, { SIGN_BLISS_WITH_SHA256, SIGN_BLISS_WITH_SHA384, SIGN_BLISS_WITH_SHA512, SIGN_UNKNOWN }},
+       {KEY_BLISS,  192, { SIGN_BLISS_WITH_SHA384, SIGN_BLISS_WITH_SHA512, SIGN_UNKNOWN }},
+       {KEY_BLISS,  256, { SIGN_BLISS_WITH_SHA512, SIGN_UNKNOWN }},
+};
+
+START_TEST(test_signature_schemes_for_key)
+{
+       enumerator_t  *enumerator;
+       signature_scheme_t scheme;
+       int i;
+
+       enumerator = signature_schemes_for_key(scheme_data[_i].type, scheme_data[_i].size);
+       for (i = 0; scheme_data[_i].expected[i] != SIGN_UNKNOWN; i++)
+       {
+               ck_assert(enumerator->enumerate(enumerator, &scheme));
+               ck_assert_int_eq(scheme_data[_i].expected[i], scheme);
+       }
+       ck_assert(!enumerator->enumerate(enumerator, &scheme));
+       enumerator->destroy(enumerator);
+}
+END_TEST
+
 Suite *utils_suite_create()
 {
        Suite *s;
@@ -777,5 +816,9 @@ Suite *utils_suite_create()
        tcase_add_loop_test(tc, test_mark_from_string, 0, countof(mark_data));
        suite_add_tcase(s, tc);
 
+       tc = tcase_create("signature_schemes_for_key");
+       tcase_add_loop_test(tc, test_signature_schemes_for_key, 0, countof(scheme_data));
+       suite_add_tcase(s, tc);
+
        return s;
 }