Added key strength constraints for RSA or ECDSA trustchains
authorMartin Willi <martin@revosec.ch>
Thu, 25 Nov 2010 14:26:51 +0000 (15:26 +0100)
committerMartin Willi <martin@revosec.ch>
Wed, 5 Jan 2011 15:45:53 +0000 (16:45 +0100)
src/libstrongswan/credentials/auth_cfg.c
src/libstrongswan/credentials/auth_cfg.h
src/libstrongswan/credentials/credential_manager.c

index ce718b9..9bde66d 100644 (file)
@@ -147,6 +147,8 @@ static void destroy_entry_value(entry_t *entry)
                case AUTH_RULE_EAP_VENDOR:
                case AUTH_RULE_CRL_VALIDATION:
                case AUTH_RULE_OCSP_VALIDATION:
+               case AUTH_RULE_RSA_STRENGTH:
+               case AUTH_RULE_ECDSA_STRENGTH:
                        break;
        }
 }
@@ -172,6 +174,8 @@ static void replace(auth_cfg_t *this, entry_enumerator_t *enumerator,
                        case AUTH_RULE_EAP_VENDOR:
                        case AUTH_RULE_CRL_VALIDATION:
                        case AUTH_RULE_OCSP_VALIDATION:
+                       case AUTH_RULE_RSA_STRENGTH:
+                       case AUTH_RULE_ECDSA_STRENGTH:
                                /* integer type */
                                enumerator->current->value = (void*)(uintptr_t)va_arg(args, u_int);
                                break;
@@ -237,6 +241,8 @@ static void* get(private_auth_cfg_t *this, auth_rule_t type)
                case AUTH_RULE_EAP_TYPE:
                        return (void*)EAP_NAK;
                case AUTH_RULE_EAP_VENDOR:
+               case AUTH_RULE_RSA_STRENGTH:
+               case AUTH_RULE_ECDSA_STRENGTH:
                        return (void*)0;
                case AUTH_RULE_CRL_VALIDATION:
                case AUTH_RULE_OCSP_VALIDATION:
@@ -274,6 +280,8 @@ static void add(private_auth_cfg_t *this, auth_rule_t type, ...)
                case AUTH_RULE_EAP_VENDOR:
                case AUTH_RULE_CRL_VALIDATION:
                case AUTH_RULE_OCSP_VALIDATION:
+               case AUTH_RULE_RSA_STRENGTH:
+               case AUTH_RULE_ECDSA_STRENGTH:
                        /* integer type */
                        entry->value = (void*)(uintptr_t)va_arg(args, u_int);
                        break;
@@ -473,6 +481,20 @@ static bool complies(private_auth_cfg_t *this, auth_cfg_t *constraints,
                                e2->destroy(e2);
                                break;
                        }
+                       case AUTH_RULE_RSA_STRENGTH:
+                       case AUTH_RULE_ECDSA_STRENGTH:
+                       {
+                               if ((uintptr_t)value > (uintptr_t)get(this, t1))
+                               {
+                                       success = FALSE;
+                                       if (log_error)
+                                       {
+                                               DBG1(DBG_CFG, "constraint requires %d bit public key "
+                                                        "strength", value);
+                                       }
+                               }
+                               break;
+                       }
                        case AUTH_HELPER_IM_CERT:
                        case AUTH_HELPER_SUBJECT_CERT:
                        case AUTH_HELPER_IM_HASH_URL:
@@ -534,6 +556,8 @@ static void merge(private_auth_cfg_t *this, private_auth_cfg_t *other, bool copy
                                case AUTH_RULE_AUTH_CLASS:
                                case AUTH_RULE_EAP_TYPE:
                                case AUTH_RULE_EAP_VENDOR:
+                               case AUTH_RULE_RSA_STRENGTH:
+                               case AUTH_RULE_ECDSA_STRENGTH:
                                {
                                        add(this, type, (uintptr_t)value);
                                        break;
@@ -600,6 +624,8 @@ static bool equals(private_auth_cfg_t *this, private_auth_cfg_t *other)
                                        case AUTH_RULE_EAP_VENDOR:
                                        case AUTH_RULE_CRL_VALIDATION:
                                        case AUTH_RULE_OCSP_VALIDATION:
+                                       case AUTH_RULE_RSA_STRENGTH:
+                                       case AUTH_RULE_ECDSA_STRENGTH:
                                        {
                                                if (i1->value == i2->value)
                                                {
@@ -741,6 +767,8 @@ static auth_cfg_t* clone_(private_auth_cfg_t *this)
                        case AUTH_RULE_EAP_VENDOR:
                        case AUTH_RULE_CRL_VALIDATION:
                        case AUTH_RULE_OCSP_VALIDATION:
+                       case AUTH_RULE_RSA_STRENGTH:
+                       case AUTH_RULE_ECDSA_STRENGTH:
                                clone->add(clone, entry->type, (uintptr_t)entry->value);
                                break;
                }
index 19624a2..ba92b16 100644 (file)
@@ -90,6 +90,10 @@ enum auth_rule_t {
         * The group membership constraint is fulfilled if the subject is member of
         * one group defined in the constraints. */
        AUTH_RULE_GROUP,
+       /** required RSA public key strength, u_int in bits */
+       AUTH_RULE_RSA_STRENGTH,
+       /** required ECDSA public key strength, u_int in bits */
+       AUTH_RULE_ECDSA_STRENGTH,
 
        /** intermediate certificate, certificate_t* */
        AUTH_HELPER_IM_CERT,
index 97e8d88..bb2bf5b 100644 (file)
@@ -551,6 +551,67 @@ static certificate_t *get_issuer_cert(private_credential_manager_t *this,
 }
 
 /**
+ * Get the strength of the weakest key in a trustchain
+ */
+static void calculate_trustchain_strength(auth_cfg_t *auth)
+{
+       enumerator_t *enumerator;
+       uintptr_t strength = 0;
+       key_type_t type = KEY_ANY;
+       certificate_t *cert;
+       public_key_t *key;
+       auth_rule_t rule;
+
+       enumerator = auth->create_enumerator(auth);
+       while (enumerator->enumerate(enumerator, &rule, &cert))
+       {
+               switch (rule)
+               {
+                       case AUTH_RULE_SUBJECT_CERT:
+                       case AUTH_RULE_IM_CERT:
+                       case AUTH_RULE_CA_CERT:
+                       {
+                               key = cert->get_public_key(cert);
+                               if (!key || (type != KEY_ANY && type != key->get_type(key)))
+                               {       /* no key, or different key families */
+                                       DESTROY_IF(key);
+                                       enumerator->destroy(enumerator);
+                                       return;
+                               }
+                               type = key->get_type(key);
+                               if (!strength)
+                               {
+                                       strength = key->get_keysize(key);
+                               }
+                               else
+                               {
+                                       strength = min(strength, key->get_keysize(key));
+                               }
+                               key->destroy(key);
+                               break;
+                       }
+                       default:
+                               break;
+               }
+       }
+       enumerator->destroy(enumerator);
+       if (strength)
+       {
+               switch (type)
+               {
+                       case KEY_RSA:
+                               auth->add(auth, AUTH_RULE_RSA_STRENGTH, strength);
+                               break;
+                       case KEY_ECDSA:
+                               auth->add(auth, AUTH_RULE_ECDSA_STRENGTH, strength);
+                               break;
+                       default:
+                               break;
+               }
+       }
+}
+
+/**
  * try to verify the trust chain of subject, return TRUE if trusted
  */
 static bool verify_trust_chain(private_credential_manager_t *this,
@@ -685,6 +746,7 @@ METHOD(enumerator_t, trusted_enumerate, bool,
                        {
                                this->auth->add(this->auth, AUTH_RULE_SUBJECT_CERT,
                                                                this->pretrusted->get_ref(this->pretrusted));
+                               calculate_trustchain_strength(this->auth);
                                DBG1(DBG_CFG, "  using trusted certificate \"%Y\"",
                                         this->pretrusted->get_subject(this->pretrusted));
                                *cert = this->pretrusted;
@@ -710,7 +772,10 @@ METHOD(enumerator_t, trusted_enumerate, bool,
                if (verify_trust_chain(this->this, current, this->auth, FALSE,
                                                           this->online))
                {
+                       this->auth->add(this->auth, AUTH_RULE_SUBJECT_CERT,
+                                                       current->get_ref(current));
                        *cert = current;
+                       calculate_trustchain_strength(this->auth);
                        if (auth)
                        {
                                *auth = this->auth;