added PSK support
authorAndreas Steffen <andreas.steffen@strongswan.org>
Mon, 18 Sep 2006 07:42:57 +0000 (07:42 -0000)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Mon, 18 Sep 2006 07:42:57 +0000 (07:42 -0000)
src/charon/config/credentials/credential_store.h
src/charon/config/credentials/local_credential_store.c
src/charon/config/policies/local_policy_store.c
src/charon/daemon.c
src/charon/sa/authenticator.c
src/charon/sa/authenticator.h
src/charon/sa/transactions/ike_auth.c
src/charon/threads/stroke_interface.c

index f8db8bd..a9d72b4 100755 (executable)
@@ -45,21 +45,20 @@ typedef struct credential_store_t credential_store_t;
 struct credential_store_t { 
 
        /**
-        * @brief Returns the preshared secret of a specific ID.
+        * @brief Returns the secret shared by two specific IDs.
         * 
         * The returned chunk must be destroyed by the caller after usage.
         * 
         * @param this                                  calling object
-        * @param id                                    identification_t object identifiying the secret.
-        * @param[out] preshared_secret the preshared secret will be written there.
+        * @param my_id                                 my ID identifiying the secret.
+        * @param other_id                              peer ID identifying the secret.
+        * @param[out] secret                   the pre-shared secret will be written there.
         * @return
         *                                                              - NOT_FOUND     if no preshared secrets for specific ID could be found
         *                                                              - SUCCESS
         *
-        * @todo We should use two IDs to query shared secrets, since we want to use different
-        * keys for different peers...
         */     
-       status_t (*get_shared_secret) (credential_store_t *this, identification_t *id, chunk_t *secret);
+       status_t (*get_shared_key) (credential_store_t *this, identification_t *my_id, identification_t *other_id, chunk_t *shared_key);
        
        /**
         * @brief Returns the RSA public key of a specific ID.
@@ -184,15 +183,14 @@ struct credential_store_t {
        void (*load_crls) (credential_store_t *this);
        
        /**
-        * @brief Loads RSA private keys defined in ipsec.secrets
+        * @brief Loads secrets in ipsec.secrets
         * 
-        * Currently, all keys must be unencrypted in either DER or PEM format.
-        * Other formats are ignored. Further, a certificate for the specific private
-        * key must already be loaded to get the ID from.
+        * Currently, all RSA private key files must be in unencrypted form
+     * either in DER or PEM format.
         * 
         * @param this                  calling object
         */
-       void (*load_private_keys) (credential_store_t *this);
+       void (*load_secrets) (credential_store_t *this);
 
        /**
         * @brief Destroys a credential_store_t object.
index 96c16d7..b60fd8a 100644 (file)
 #include <crypto/rsa/rsa_public_key.h>
 #include <crypto/x509.h>
 #include <crypto/crl.h>
+#include <asn1/ttodata.h>
 
 #include "local_credential_store.h"
 
 #define PATH_BUF                       256
 #define MAX_CA_PATH_LEN                7
 
+typedef struct shared_key_t shared_key_t;
+
+/**
+ * Private date of a shared_key_t object
+ */
+struct shared_key_t {
+
+       /**
+        * shared secret
+        */
+       chunk_t secret;
+
+       /**
+        * list of peer IDs
+        */
+       linked_list_t *peers;
+
+       /**
+        * @brief Destroys a shared_key_t object.
+        *
+        * @param this                  calling object
+        */
+       void (*destroy) (shared_key_t *this);
+};
+
+
+/**
+ * Implementation of shared_key_t.destroy.
+ */
+static void shared_key_destroy(shared_key_t *this)
+{
+       identification_t *id;
+
+    /* destroy peer id list */
+       while (this->peers->remove_last(this->peers, (void**)&id) == SUCCESS)
+       {
+               id->destroy(id);
+       }
+       this->peers->destroy(this->peers);
+
+       free(this);
+}
+
+/**
+ * @brief Creates a shared_key_t object.
+ * 
+ * @param shared_key           shared key value
+ * 
+ * @return                                     shared_key_t object
+ * 
+ * @ingroup config
+ */
+static shared_key_t *shared_key_create(chunk_t secret)
+{
+       shared_key_t *this = malloc_thing(shared_key_t);
+
+       /* private functions */
+       this->destroy = shared_key_destroy;
+
+       /* private data */
+       this->secret = chunk_clone(secret);
+       this->peers = linked_list_create();
+
+       return (this);
+}
+
+
 typedef struct private_local_credential_store_t private_local_credential_store_t;
 
 /**
@@ -52,6 +120,11 @@ struct private_local_credential_store_t {
        local_credential_store_t public;
        
        /**
+        * list of shared keys
+        */
+       linked_list_t *shared_keys;
+       
+       /**
         * list of key_entry_t's with private keys
         */
        linked_list_t *private_keys;
@@ -89,11 +162,75 @@ struct private_local_credential_store_t {
 
 
 /**
- * Implementation of local_credential_store_t.get_shared_secret.
+ * Implementation of local_credential_store_t.get_shared_key.
  */    
-static status_t get_shared_secret(private_local_credential_store_t *this, identification_t *id, chunk_t *secret)
+static status_t get_shared_key(private_local_credential_store_t *this, identification_t *my_id, identification_t *other_id, chunk_t *secret)
 {
-       return FAILED;
+       typedef enum {
+               PRIO_UNDEFINED=         0x00,
+               PRIO_ANY_MATCH=         0x01,
+               PRIO_MY_MATCH=          0x02,
+               PRIO_OTHER_MATCH=       0x04,
+       } prio_t;
+
+       prio_t best_prio = PRIO_UNDEFINED;
+       chunk_t found = CHUNK_INITIALIZER;
+
+       iterator_t *iterator = this->shared_keys->create_iterator(this->shared_keys, TRUE);
+
+       while (iterator->has_next(iterator))
+       {
+               shared_key_t *shared_key;
+               iterator_t *peer_iterator;
+
+               prio_t prio = PRIO_UNDEFINED;
+
+               iterator->current(iterator, (void**)&shared_key);
+
+               peer_iterator = shared_key->peers->create_iterator(shared_key->peers, TRUE);
+
+               if (peer_iterator->get_count(peer_iterator) == 0)
+               {
+                       /* this is a wildcard shared key */
+                       prio = PRIO_ANY_MATCH;
+               }
+               else
+               {
+                       while (peer_iterator->has_next(peer_iterator))
+                       {
+                               identification_t *peer_id;
+
+                               peer_iterator->current(peer_iterator, (void**)&peer_id);
+
+                               if (my_id->equals(my_id, peer_id))
+                               {
+                                       prio |= PRIO_MY_MATCH; 
+                               }
+                               if (other_id->equals(other_id, peer_id))
+                               {
+                                       prio |= PRIO_OTHER_MATCH; 
+                               }
+                       }
+               }
+               peer_iterator->destroy(peer_iterator);
+
+               if (prio > best_prio)
+               {
+                       best_prio = prio;
+                       found = shared_key->secret;
+               }
+       }
+       iterator->destroy(iterator);
+
+       if (best_prio = PRIO_UNDEFINED)
+       {
+               return NOT_FOUND;
+       }
+       else
+       {
+               *secret = chunk_clone(found);
+               return SUCCESS;
+       }
 }
 
 /**
@@ -767,9 +904,67 @@ static void load_crls(private_local_credential_store_t *this)
 }
 
 /**
- * Implements local_credential_store_t.load_private_keys
+ * Convert a string of characters into a binary secret
+ * A string between single or double quotes is treated as ASCII characters
+ * A string prepended by 0x is treated as HEX and prepended by 0s as Base64
+ */
+static err_t extract_secret(chunk_t *secret, chunk_t *line)
+{
+       chunk_t raw_secret;
+       size_t len;
+       char delimiter = ' ';
+       bool quotes = FALSE;
+
+       if (!eat_whitespace(line))
+       {
+               return "missing secret";
+       }
+
+       if (*line->ptr == '\'' || *line->ptr == '"')
+       {
+               quotes = TRUE;
+               delimiter = *line->ptr;
+               line->ptr++;  line->len--;
+       }
+
+       if (!extract_token(&raw_secret, delimiter, line))
+       {
+               if (delimiter == ' ')
+               {
+                       raw_secret = *line;
+               }
+               else
+               {
+                       return "missing second delimiter";
+               }
+       }
+
+       if (quotes)
+       {       /* treat as an ASCII string */
+               
+               if (raw_secret.len > secret->len)
+                       return "secret larger than buffer";
+               memcpy(secret->ptr, raw_secret.ptr, raw_secret.len);
+               secret->len = raw_secret.len;
+       }
+       else
+       {       /* convert from HEX or Base64 to binary */
+               size_t len;
+               err_t ugh = ttodata(raw_secret.ptr, raw_secret.len, 0, secret->ptr, secret->len, &len);
+
+           if (ugh != NULL)
+                       return ugh;
+               if (len > secret->len)
+                       return "secret larger than buffer";
+               secret->len = len;
+       }
+       return NULL;
+}
+
+/**
+ * Implements local_credential_store_t.load_secrets
  */
-static void load_private_keys(private_local_credential_store_t *this)
+static void load_secrets(private_local_credential_store_t *this)
 {
        FILE *fd = fopen(SECRETS_FILE, "r");
 
@@ -814,6 +1009,7 @@ static void load_private_keys(private_local_credential_store_t *this)
                        {
                                char path[PATH_BUF];
                                chunk_t filename;
+                               rsa_private_key_t *key;
 
                                err_t ugh = extract_value(&filename, &line);
 
@@ -839,7 +1035,7 @@ static void load_private_keys(private_local_credential_store_t *this)
                                        snprintf(path, sizeof(path), "%s/%.*s", PRIVATE_KEY_DIR, filename.len, filename.ptr);
                                }
 
-                               rsa_private_key_t *key = rsa_private_key_create_from_file(path, NULL);
+                               key = rsa_private_key_create_from_file(path, NULL);
                                if (key)
                                {
                                        this->private_keys->insert_last(this->private_keys, (void*)key);
@@ -847,7 +1043,55 @@ static void load_private_keys(private_local_credential_store_t *this)
                        }
                        else if (match("PSK", &token))
                        {
+                               shared_key_t *shared_key;
+
+                               char buf[BUF_LEN];
+                               chunk_t secret = { buf, BUF_LEN };
+
+                               err_t ugh = extract_secret(&secret, &line);
+                               if (ugh != NULL)
+                               {
+                                       this->logger->log(this->logger, ERROR, "line %d: malformed secret: %s", line_nr, ugh);
+                                       goto error;
+                               }
+
+                               if (ids.len > 0)
+                                       this->logger->log(this->logger, CONTROL, "  loaded shared key for %.*s", ids.len, ids.ptr);
+                               else
+                                       this->logger->log(this->logger, CONTROL, "  loaded shared key for %%any");
 
+                               this->logger->log_chunk(this->logger, PRIVATE, "  secret:", secret);
+
+                               shared_key = shared_key_create(secret);
+                               if (shared_key)
+                               {
+                                       this->shared_keys->insert_last(this->shared_keys, (void*)shared_key);
+                               }
+                               while (ids.len > 0)
+                               {
+                                       chunk_t id;
+                                       identification_t *peer_id;
+
+                                       ugh = extract_value(&id, &ids);
+                                       if (ugh != NULL)
+                                       {
+                                               this->logger->log(this->logger, ERROR, "line %d: %s", line_nr, ugh);
+                                               goto error;
+                                       }
+                                       if (id.len == 0)
+                                               continue;
+
+                                       /* NULL terminate the ID string */
+                                       *(id.ptr + id.len) = '\0';
+
+                                       peer_id = identification_create_from_string(id.ptr);
+                                       if (peer_id->get_type(peer_id) == ID_ANY)
+                                       {
+                                               peer_id->destroy(peer_id);
+                                               continue;
+                                       }
+                                       shared_key->peers->insert_last(shared_key->peers, (void*)peer_id);
+                               }
                        }
                        else if (match("PIN", &token))
                        {
@@ -878,6 +1122,7 @@ static void destroy(private_local_credential_store_t *this)
        x509_t *cert;
        crl_t *crl;
        rsa_private_key_t *key;
+       shared_key_t *shared_key;
        
        /* destroy cert list */
        while (this->certs->remove_last(this->certs, (void**)&cert) == SUCCESS)
@@ -909,6 +1154,13 @@ static void destroy(private_local_credential_store_t *this)
        }
        this->private_keys->destroy(this->private_keys);
 
+    /* destroy shared keys list */
+       while (this->shared_keys->remove_last(this->shared_keys, (void**)&shared_key) == SUCCESS)
+       {
+               shared_key->destroy(shared_key);
+       }
+       this->shared_keys->destroy(this->shared_keys);
+
        free(this);
 }
 
@@ -919,7 +1171,7 @@ local_credential_store_t * local_credential_store_create(bool strict)
 {
        private_local_credential_store_t *this = malloc_thing(private_local_credential_store_t);
 
-       this->public.credential_store.get_shared_secret = (status_t (*) (credential_store_t*,identification_t*,chunk_t*))get_shared_secret;
+       this->public.credential_store.get_shared_key = (status_t (*) (credential_store_t*,identification_t*,identification_t*,chunk_t*))get_shared_key;
        this->public.credential_store.get_rsa_public_key = (rsa_public_key_t*(*)(credential_store_t*,identification_t*))get_rsa_public_key;
        this->public.credential_store.get_rsa_private_key = (rsa_private_key_t* (*) (credential_store_t*,rsa_public_key_t*))get_rsa_private_key;
        this->public.credential_store.has_rsa_private_key = (bool (*) (credential_store_t*,rsa_public_key_t*))has_rsa_private_key;
@@ -933,17 +1185,18 @@ local_credential_store_t * local_credential_store_create(bool strict)
        this->public.credential_store.log_crls = (void (*) (credential_store_t*,logger_t*,bool))log_crls;
        this->public.credential_store.load_ca_certificates = (void (*) (credential_store_t*))load_ca_certificates;
        this->public.credential_store.load_crls = (void (*) (credential_store_t*))load_crls;
-       this->public.credential_store.load_private_keys = (void (*) (credential_store_t*))load_private_keys;
+       this->public.credential_store.load_secrets = (void (*) (credential_store_t*))load_secrets;
        this->public.credential_store.destroy = (void (*) (credential_store_t*))destroy;
        
        /* initialize mutexes */
        pthread_mutex_init(&(this->crls_mutex), NULL);
 
        /* private variables */
+       this->shared_keys  = linked_list_create();
        this->private_keys = linked_list_create();
-       this->certs = linked_list_create();
-       this->ca_certs = linked_list_create();
-       this->crls = linked_list_create();
+       this->certs        = linked_list_create();
+       this->ca_certs     = linked_list_create();
+       this->crls         = linked_list_create();
        this->strict = strict;
        this->logger = logger_manager->get_logger(logger_manager, CONFIG);
 
index 0c3e0ee..9ab8948 100644 (file)
@@ -200,7 +200,7 @@ static policy_t *get_policy_by_name(private_local_policy_store_t *this, char *na
        iterator_t *iterator;
        policy_t *current, *found = NULL;
        
-       this->logger->log(this->logger, CONTROL|LEVEL1, "Looking for policy \"%s\"", name);
+       this->logger->log(this->logger, CONTROL|LEVEL1, "looking for policy \"%s\"", name);
        
        pthread_mutex_lock(&(this->mutex));
        iterator = this->policies->create_iterator(this->policies, TRUE);
index 68846fc..cad9bee 100644 (file)
@@ -186,11 +186,11 @@ static void initialize(private_daemon_t *this, bool strict)
        this->public.policies = (policy_store_t*)local_policy_store_create();
        this->public.credentials = (credential_store_t*)local_credential_store_create(strict);
 
-       /* load keys, ca certificates and crls */
+       /* load secrets, ca certificates and crls */
        credentials = this->public.credentials;
        credentials->load_ca_certificates(credentials);
        credentials->load_crls(credentials);
-       credentials->load_private_keys(credentials);
+       credentials->load_secrets(credentials);
        
        /* start building threads, we are multi-threaded NOW */
        this->public.stroke = stroke_create();
index 8dcfc04..436bd24 100644 (file)
@@ -68,23 +68,22 @@ struct private_authenticator_t {
        logger_t *logger;
        
        /**
-        * @brief Creates the octets which are signed (RSA) or MACed (shared secret) as described in section 
-        * 2.15 of RFC.
+        * @brief Builds the octets to be signed (RSA or PSK) as described in section 2.15 of RFC 4306.
         * 
         * @param this                          calling object
         * @param last_message          the last message to include in created octets 
         *                                                      (either binary form of IKE_SA_INIT request or IKE_SA_INIT response)
         * @param other_nonce           Nonce data received from other peer
-        * @param my_id                         id_payload_t object representing an ID payload
+        * @param id                            ID of signer
         * @param initiator                     Type of peer. TRUE, if it is original initiator, FALSE otherwise
         * @return                                      octets as described in section 2.15. Memory gets allocated and has to get 
         *                                                      destroyed by caller.
         */
-       chunk_t (*allocate_octets) (private_authenticator_t *this,
-                                                               chunk_t last_message,
-                                                               chunk_t other_nonce,
-                                                               id_payload_t *my_id,
-                                                               bool initiator);
+       chunk_t (*build_tbs_octets) (private_authenticator_t *this,
+                                                                chunk_t last_message,
+                                                                chunk_t other_nonce,
+                                                                identification_t *id,
+                                                                bool initiator);
        
        /**
         * @brief Creates the AUTH data using auth method SHARED_KEY_MESSAGE_INTEGRITY_CODE.
@@ -93,49 +92,45 @@ struct private_authenticator_t {
         * @param last_message          the last message
         *                                                      (either binary form of IKE_SA_INIT request or IKE_SA_INIT response)
         * @param nonce                         Nonce data to include in auth data compution
-        * @param id_payload            id_payload_t object representing an ID payload
+        * @param id                            ID of signer
         * @param initiator                     Type of peer. TRUE, if it is original initiator, FALSE otherwise
-        * @param shared_secret         shared secret as chunk_t. If shared secret is a string,
+        * @param secret                        shared secret as chunk_t. If shared secret is a string,
         *                                                      the NULL termination is not included.
         * @return                                      AUTH data as dscribed in section 2.15 for 
         *                                                      AUTH method SHARED_KEY_MESSAGE_INTEGRITY_CODE.
         *                                                      Memory gets allocated and has to get destroyed by caller.
         */
-       chunk_t (*build_preshared_secret_signature) (private_authenticator_t *this,
-                                                                                                chunk_t last_message,
-                                                                                                chunk_t nonce,
-                                                                                                id_payload_t *id_payload,
-                                                                                                bool initiator,
-                                                                                                chunk_t preshared_secret);
+       chunk_t (*build_shared_key_signature) (private_authenticator_t *this,
+                                                                                  chunk_t last_message,
+                                                                                  chunk_t nonce,
+                                                                                  identification_t *id,
+                                                                                  bool initiator,
+                                                                                  chunk_t secret);
 };
 
 /**
- * Implementation of private_authenticator_t.allocate_octets.
+ * Implementation of private_authenticator_t.build_tbs_octets.
  */
-static chunk_t allocate_octets(private_authenticator_t *this,
+static chunk_t build_tbs_octets(private_authenticator_t *this,
                                                                chunk_t last_message, 
                                                                chunk_t other_nonce,
-                                                               id_payload_t *my_id,
+                                                               identification_t *id,
                                                                bool initiator)
 {
        prf_t *prf;
-       chunk_t id_chunk = my_id->get_data(my_id);
-       u_int8_t id_with_header[4 + id_chunk.len];
-       /*
-        * IKEv2 for linux (http://sf.net/projects/ikev2/) 
-        * is not compatible with IKEv2 Draft and so not compatible with this
-        * implementation, cause AUTH data are computed without
-        * ID type and the three reserved bytes.
-        */
+
+       chunk_t  id_encoding = id->get_encoding(id);
+       u_int8_t id_with_header[4 + id_encoding.len];
        chunk_t id_with_header_chunk = {ptr:id_with_header, len: sizeof(id_with_header)};
+
        u_int8_t *current_pos;
        chunk_t octets;
        
-       id_with_header[0] = my_id->get_id_type(my_id);
+       id_with_header[0] = id->get_type(id);
        id_with_header[1] = 0x00;
        id_with_header[2] = 0x00;
        id_with_header[3] = 0x00;
-       memcpy(id_with_header + 4,id_chunk.ptr,id_chunk.len);
+       memcpy(id_with_header + 4, id_encoding.ptr, id_encoding.len);
        
        if (initiator)
        {
@@ -150,9 +145,9 @@ static chunk_t allocate_octets(private_authenticator_t *this,
        octets.len = last_message.len + other_nonce.len + prf->get_block_size(prf);
        octets.ptr = malloc(octets.len);
        current_pos = octets.ptr;
-       memcpy(current_pos,last_message.ptr,last_message.len);
+       memcpy(current_pos, last_message.ptr, last_message.len);
        current_pos += last_message.len;
-       memcpy(current_pos,other_nonce.ptr,other_nonce.len);
+       memcpy(current_pos, other_nonce.ptr, other_nonce.len);
        current_pos += other_nonce.len;
        prf->get_bytes(prf, id_with_header_chunk, current_pos);
        
@@ -161,29 +156,29 @@ static chunk_t allocate_octets(private_authenticator_t *this,
 }
 
 /**
- * Implementation of private_authenticator_t.build_preshared_secret_signature.
+ * Implementation of private_authenticator_t.build_shared_key_signature.
  */
-static chunk_t build_preshared_secret_signature(private_authenticator_t *this,
-                                                                                                                       chunk_t last_message,
-                                                                                                                       chunk_t nonce,
-                                                                                                                       id_payload_t *id_payload,
-                                                                                                                       bool initiator,
-                                                                                                                       chunk_t preshared_secret)
+static chunk_t build_shared_key_signature(private_authenticator_t *this,
+                                                                                 chunk_t last_message,
+                                                                                 chunk_t nonce,
+                                                                                 identification_t *id,
+                                                                                 bool initiator,
+                                                                                 chunk_t secret)
 {
        chunk_t key_pad = {ptr: IKEV2_KEY_PAD, len:strlen(IKEV2_KEY_PAD)};
        u_int8_t key_buffer[this->prf->get_block_size(this->prf)];
        chunk_t key = {ptr: key_buffer, len: sizeof(key_buffer)};
        chunk_t auth_data;
 
-       chunk_t octets = this->allocate_octets(this,last_message,nonce,id_payload,initiator);
+       chunk_t octets = this->build_tbs_octets(this, last_message, nonce, id, initiator);
        
        /* AUTH = prf(prf(Shared Secret,"Key Pad for IKEv2"), <msg octets>) */
-       this->prf->set_key(this->prf, preshared_secret);
+       this->prf->set_key(this->prf, secret);
        this->prf->get_bytes(this->prf, key_pad, key_buffer);
        this->prf->set_key(this->prf, key);
        this->prf->allocate_bytes(this->prf, octets, &auth_data);
        chunk_free(&octets);
-       this->logger->log_chunk(this->logger,RAW | LEVEL2, "authenticated data",auth_data);
+       this->logger->log_chunk(this->logger,RAW | LEVEL2, "authenticated data", auth_data);
 
        return auth_data;
 }
@@ -195,36 +190,36 @@ static status_t verify_auth_data (private_authenticator_t *this,
                                                                        auth_payload_t *auth_payload,
                                                                        chunk_t last_received_packet,
                                                                        chunk_t my_nonce,
-                                                                       id_payload_t *other_id_payload,
+                                                                       identification_t *my_id,
+                                                                       identification_t *other_id,
                                                                        bool initiator)
 {
        switch(auth_payload->get_auth_method(auth_payload))
        {
                case SHARED_KEY_MESSAGE_INTEGRITY_CODE:
                {
-                       identification_t *other_id = other_id_payload->get_identification(other_id_payload);
                        chunk_t auth_data = auth_payload->get_data(auth_payload);
-                       chunk_t preshared_secret;
+                       chunk_t shared_key;
                        status_t status;
                                                
-                       status = charon->credentials->get_shared_secret(charon->credentials,
-                                                                                                                       other_id,
-                                                                                                                       &preshared_secret);
+                       status = charon->credentials->get_shared_key(charon->credentials,
+                                                                                                                my_id,
+                                                                                                                other_id,
+                                                                                                                &shared_key);
                        if (status != SUCCESS)
                        {
-                               this->logger->log(this->logger, ERROR, "no shared secret found for '%s'",
-                                                                 other_id->get_string(other_id));
-                               other_id->destroy(other_id);
+                               this->logger->log(this->logger, ERROR, "no shared key found for '%s' and '%s'",
+                                                                 my_id->get_string(my_id), other_id->get_string(other_id));
                                return status;  
                        }
                        
-                       chunk_t my_auth_data = this->build_preshared_secret_signature(this,
-                                                                                                                                                 last_received_packet,
-                                                                                                                                                 my_nonce,
-                                                                                                                                                 other_id_payload,
-                                                                                                                                                 initiator,
-                                                                                                                                                 preshared_secret);
-                       chunk_free(&preshared_secret);
+                       chunk_t my_auth_data = this->build_shared_key_signature(this,
+                                                                                                                                       last_received_packet,
+                                                                                                                                       my_nonce,
+                                                                                                                                       other_id,
+                                                                                                                                       initiator,
+                                                                                                                                       shared_key);
+                       chunk_free(&shared_key);
                        
                        if (auth_data.len != my_auth_data.len)
                        {
@@ -233,17 +228,16 @@ static status_t verify_auth_data (private_authenticator_t *this,
                        }
                        else if (memcmp(auth_data.ptr,my_auth_data.ptr, my_auth_data.len) == 0)
                        {
-                               this->logger->log(this->logger, CONTROL, "authentication of '%s' with preshared secret successful",
+                               this->logger->log(this->logger, CONTROL, "authentication of '%s' with pre-shared key successful",
                                                                                other_id->get_string(other_id));
                                status = SUCCESS;
                        }
                        else
                        {
-                               this->logger->log(this->logger, ERROR, "authentication of '%s' with preshared secret failed",
+                               this->logger->log(this->logger, ERROR, "authentication of '%s' with pre-shared key failed",
                                                                                other_id->get_string(other_id));
                                status = FAILED;
                        }
-                       other_id->destroy(other_id);
                        chunk_free(&my_auth_data);
                        return status;
                }
@@ -252,34 +246,30 @@ static status_t verify_auth_data (private_authenticator_t *this,
                        status_t status;
                        chunk_t octets;
                        chunk_t auth_data = auth_payload->get_data(auth_payload);
-                       identification_t *other_id = other_id_payload->get_identification(other_id_payload);
 
                        rsa_public_key_t *public_key =
                                charon->credentials->get_trusted_public_key(charon->credentials, other_id);
 
                        if (public_key == NULL)
                        {
-                               this->logger->log(this->logger, ERROR, "no public key found for '%s'",
+                               this->logger->log(this->logger, ERROR, "no RSA public key found for '%s'",
                                                                  other_id->get_string(other_id));
-                               other_id->destroy(other_id);
                                return NOT_FOUND;       
                        }
                        
-                       octets = this->allocate_octets(this,last_received_packet, my_nonce,other_id_payload, initiator);
+                       octets = this->build_tbs_octets(this, last_received_packet, my_nonce, other_id, initiator);
                        
                        status = public_key->verify_emsa_pkcs1_signature(public_key, octets, auth_data);
                        if (status == SUCCESS)
                        {
-                               this->logger->log(this->logger, CONTROL, "authentication of '%s' with RSA successful",
+                               this->logger->log(this->logger, CONTROL, "authentication of '%s' with RSA signature successful",
                                                                                other_id->get_string(other_id));
                        }
                        else
                        {
-                               this->logger->log(this->logger, ERROR, "authentication of '%s' with RSA failed",
+                               this->logger->log(this->logger, ERROR, "authentication of '%s' with RSA signature failed",
                                                                                other_id->get_string(other_id));
                        }
-                       
-                       other_id->destroy(other_id);
                        chunk_free(&octets);
                        return status;
                }
@@ -294,37 +284,39 @@ static status_t verify_auth_data (private_authenticator_t *this,
  * Implementation of authenticator_t.compute_auth_data.
  */
 static status_t compute_auth_data (private_authenticator_t *this,
-                                                                       auth_payload_t **auth_payload,
-                                                                       chunk_t last_sent_packet,
-                                                                       chunk_t other_nonce,
-                                                                       id_payload_t *my_id_payload,
-                                                                       bool initiator)
+                                                                  auth_payload_t **auth_payload,
+                                                                  chunk_t last_sent_packet,
+                                                                  chunk_t other_nonce,
+                                                                  identification_t *my_id,
+                                                                  identification_t *other_id,
+                                                                  bool initiator)
 {      
-       switch(this->auth_method)
+       switch (this->auth_method)
        {
                case SHARED_KEY_MESSAGE_INTEGRITY_CODE:
                {
-                       identification_t *my_id = my_id_payload->get_identification(my_id_payload);
-                       chunk_t preshared_secret;
-                       status_t status;
+                       chunk_t shared_key;
                        chunk_t auth_data;
 
-                       status = charon->credentials->get_shared_secret(charon->credentials,
-                                                                                                                       my_id,
-                                                                                                                       &preshared_secret);
+                       status_t status = charon->credentials->get_shared_key(charon->credentials,
+                                                                                                                                 my_id,
+                                                                                                                                 other_id,
+                                                                                                                                 &shared_key);
 
                        if (status != SUCCESS)
                        {
-                               this->logger->log(this->logger, ERROR, "no shared secret found for %s",
-                                                                 my_id->get_string(my_id));
-                               my_id->destroy(my_id);
+                               this->logger->log(this->logger, ERROR, "no shared key found for '%s' and '%s'",
+                                                                 my_id->get_string(my_id), other_id->get_string(other_id));
                                return status;  
                        }
-                       my_id->destroy(my_id);
                        
-                       auth_data = this->build_preshared_secret_signature(this, last_sent_packet, other_nonce,
-                                                                                                                          my_id_payload, initiator, preshared_secret);
-                       chunk_free(&preshared_secret);
+                       auth_data = this->build_shared_key_signature(this,
+                                                                                                                last_sent_packet,
+                                                                                                                other_nonce,
+                                                                                                                my_id,
+                                                                                                                initiator,
+                                                                                                                shared_key);
+                       chunk_free(&shared_key);
                        *auth_payload = auth_payload_create();
                        (*auth_payload)->set_auth_method(*auth_payload, SHARED_KEY_MESSAGE_INTEGRITY_CODE);
                        (*auth_payload)->set_data(*auth_payload, auth_data);
@@ -335,27 +327,26 @@ static status_t compute_auth_data (private_authenticator_t *this,
                case RSA_DIGITAL_SIGNATURE:
                {
                        char buf[BUF_LEN];
-                       chunk_t octets, auth_data;
-                       status_t status = NOT_FOUND;
+                       chunk_t octets;
+                       chunk_t auth_data;
+                       status_t status;
                        rsa_public_key_t  *my_pubkey;
                        rsa_private_key_t *my_key;
 
-                       identification_t  *my_id = my_id_payload->get_identification(my_id_payload);
-                       
-                       this->logger->log(this->logger, CONTROL|LEVEL1, "looking for public key belonging to '%s'",
+                       this->logger->log(this->logger, CONTROL|LEVEL1, "looking for RSA public key belonging to '%s'",
                                                          my_id->get_string(my_id));
 
                        my_pubkey = charon->credentials->get_rsa_public_key(charon->credentials, my_id);
                        if (my_pubkey == NULL)
                        {
-                               this->logger->log(this->logger, ERROR, "no public key found for '%s'",
+                               this->logger->log(this->logger, ERROR, "no RSA public key found for '%s'",
                                                                  my_id->get_string(my_id));
-                               goto end_rsa;
+                               return NOT_FOUND;
                        }
-                       this->logger->log(this->logger, CONTROL|LEVEL2, "matching public key found");
+                       this->logger->log(this->logger, CONTROL|LEVEL2, "matching RSA public key found");
                        
                        chunk_to_hex(buf, BUF_LEN, my_pubkey->get_keyid(my_pubkey));
-                       this->logger->log(this->logger, CONTROL|LEVEL1, "looking for private key with keyid %s", buf);
+                       this->logger->log(this->logger, CONTROL|LEVEL1, "looking for RSA private key with keyid %s", buf);
 
                        my_key = charon->credentials->get_rsa_private_key(charon->credentials, my_pubkey);
                        if (my_key == NULL)
@@ -363,21 +354,22 @@ static status_t compute_auth_data (private_authenticator_t *this,
                                char buf[BUF_LEN];
 
                                chunk_to_hex(buf, BUF_LEN, my_pubkey->get_keyid(my_pubkey));
-                               this->logger->log(this->logger, ERROR, "no private key found with for %s with keyid %s",
+                               this->logger->log(this->logger, ERROR, "no RSA private key found with for %s with keyid %s",
                                                                  my_id->get_string(my_id), buf);
-                               goto end_rsa;
+                               return NOT_FOUND;
                        }
-                       this->logger->log(this->logger, CONTROL|LEVEL2, "matching private key found");
+                       this->logger->log(this->logger, CONTROL|LEVEL2, "matching RSA private key found");
 
-                       octets = this->allocate_octets(this,last_sent_packet,other_nonce,my_id_payload,initiator);
+                       octets = this->build_tbs_octets(this, last_sent_packet, other_nonce, my_id, initiator);
                        status = my_key->build_emsa_pkcs1_signature(my_key, HASH_SHA1, octets, &auth_data);
                        chunk_free(&octets);
 
                        if (status != SUCCESS)
                        {
                                my_key->destroy(my_key);
-                               goto end_rsa;
+                               return status;
                        }
+                       this->logger->log(this->logger, CONTROL|LEVEL2, "successfully signed with RSA private key");
                        
                        *auth_payload = auth_payload_create();
                        (*auth_payload)->set_auth_method(*auth_payload, RSA_DIGITAL_SIGNATURE);
@@ -385,10 +377,7 @@ static status_t compute_auth_data (private_authenticator_t *this,
 
                        my_key->destroy(my_key);
                        chunk_free(&auth_data);
-
-               end_rsa:
-                       my_id->destroy(my_id);
-                       return status;
+                       return SUCCESS;
                }
                default:
                {
@@ -414,12 +403,14 @@ authenticator_t *authenticator_create(ike_sa_t *ike_sa, auth_method_t auth_metho
 
        /* Public functions */
        this->public.destroy = (void(*)(authenticator_t*))destroy;
-       this->public.verify_auth_data = (status_t (*) (authenticator_t *,auth_payload_t *, chunk_t ,chunk_t ,id_payload_t *,bool)) verify_auth_data;
-       this->public.compute_auth_data = (status_t (*) (authenticator_t *,auth_payload_t **, chunk_t ,chunk_t ,id_payload_t *,bool)) compute_auth_data;
+       this->public.verify_auth_data = (status_t (*) (authenticator_t*,auth_payload_t*,chunk_t,
+                                                                                                  chunk_t,identification_t*,identification_t*,bool)) verify_auth_data;
+       this->public.compute_auth_data = (status_t (*) (authenticator_t*,auth_payload_t**,chunk_t,
+                                                                                                   chunk_t,identification_t*,identification_t*,bool)) compute_auth_data;
        
        /* private functions */
-       this->allocate_octets = allocate_octets;
-       this->build_preshared_secret_signature = build_preshared_secret_signature;
+       this->build_tbs_octets = build_tbs_octets;
+       this->build_shared_key_signature = build_shared_key_signature;
        
        /* private data */
        this->ike_sa = ike_sa;
index 645e39b..4fb7766 100644 (file)
@@ -62,8 +62,9 @@ struct authenticator_t {
         * @param this                                  calling object
         * @param last_received_packet  binary representation of the last received IKEv2-Message
         * @param my_nonce                              the sent nonce (without payload header)
-        * @param other_id_payload              the ID payload received from other peer
-        * @param initiator                             type of other peer. TRUE, if it is original initiator, FALSE otherwise
+        * @param my_id                                 my ID
+        * @param other_id                              peer ID
+        * @param initiator                             type of peer. TRUE, if it is original initiator, FALSE otherwise
         * 
         * @todo Document RSA error status types
         * 
@@ -75,11 +76,12 @@ struct authenticator_t {
         *                                                                      (e.g. shared secret, rsa key)
         */
        status_t (*verify_auth_data) (authenticator_t *this,
-                                                                       auth_payload_t *auth_payload, 
-                                                                       chunk_t last_received_packet,
-                                                                       chunk_t my_nonce,
-                                                                       id_payload_t *other_id_payload, 
-                                                                       bool initiator);
+                                                                 auth_payload_t *auth_payload, 
+                                                                 chunk_t last_received_packet,
+                                                                 chunk_t my_nonce,
+                                                                 identification_t *my_id,
+                                                                 identification_t *other_id,
+                                                                 bool initiator);
 
        /**
         * @brief Computes authentication data and creates specific AUTH payload.
@@ -93,7 +95,8 @@ struct authenticator_t {
         * @param[out] auth_payload             The object of typee auth_payload_t will be created at pointing location
         * @param last_sent_packet              binary representation of the last sent IKEv2-Message
         * @param other_nonce                   the received nonce (without payload header)
-        * @param my_id_payload                 the ID payload going to send to other peer
+        * @param my_id                                 my ID
+        * @param other_id                              peer ID
         * @param initiator                             type of myself. TRUE, if I'm original initiator, FALSE otherwise
         *
         * @todo Document RSA error status types
@@ -104,11 +107,12 @@ struct authenticator_t {
         *                                                              - NOT_FOUND if the data for AUTH method could not be found
         */
        status_t (*compute_auth_data) (authenticator_t *this,
-                                                                       auth_payload_t **auth_payload,
-                                                                       chunk_t last_sent_packet,
-                                                                       chunk_t other_nonce,
-                                                                       id_payload_t *my_id_payload,
-                                                                       bool initiator);
+                                                                  auth_payload_t **auth_payload,
+                                                                  chunk_t last_sent_packet,
+                                                                  chunk_t other_nonce,
+                                                                  identification_t *my_id,
+                                                                  identification_t *other_id,
+                                                                  bool initiator);
 
        /**
         * @brief Destroys a authenticator_t object.
index 681c764..e32dc3c 100644 (file)
@@ -261,12 +261,14 @@ static status_t get_request(private_ike_auth_t *this, message_t **result)
                
        }
        
-       if (this->connection->get_cert_policy(this->connection) != CERT_NEVER_SEND)
-       {       /* build certificate payload. TODO: Handle certreq from init_ike_sa. */
-               x509_t *cert;
+       /* build certificate payload. TODO: Handle certreq from init_ike_sa. */
+       if (this->connection->get_auth_method(this->connection) == RSA_DIGITAL_SIGNATURE
+       &&  this->connection->get_cert_policy(this->connection) != CERT_NEVER_SEND)
+       {
                cert_payload_t *cert_payload;
                
-               cert = charon->credentials->get_certificate(charon->credentials, my_id);
+               x509_t *cert = charon->credentials->get_certificate(charon->credentials, my_id);
+
                if (cert)
                {
                        cert_payload = cert_payload_create_from_x509(cert);
@@ -296,8 +298,13 @@ static status_t get_request(private_ike_auth_t *this, message_t **result)
                
                auth_method = this->connection->get_auth_method(this->connection);
                authenticator = authenticator_create(this->ike_sa, auth_method);
-               status = authenticator->compute_auth_data(authenticator, &auth_payload,
-                               this->init_request, this->nonce_r, my_id_payload, TRUE);
+               status = authenticator->compute_auth_data(authenticator,
+                                                                                                 &auth_payload,
+                                                                                                 this->init_request,
+                                                                                                 this->nonce_r,
+                                                                                                 my_id,
+                                                                                                 other_id,
+                                                                                                 TRUE);
                authenticator->destroy(authenticator);
                if (status != SUCCESS)
                {
@@ -704,19 +711,23 @@ static status_t get_response(private_ike_auth_t *this, message_t *request,
                response->add_payload(response, (payload_t*)idr_response);
        }
        
-       if (this->connection->get_cert_policy(this->connection) != CERT_NEVER_SEND)
+       if (this->connection->get_auth_method(this->connection) == RSA_DIGITAL_SIGNATURE
+       &&  this->connection->get_cert_policy(this->connection) != CERT_NEVER_SEND)
        {       /* build certificate payload */
                x509_t *cert;
                cert_payload_t *cert_payload;
                
                cert = charon->credentials->get_certificate(charon->credentials, my_id);
-               if (cert == NULL)
+               if (cert)
+               {
+                       cert_payload = cert_payload_create_from_x509(cert);
+                       response->add_payload(response, (payload_t *)cert_payload);
+               }
+               else
                {
                        this->logger->log(this->logger, ERROR,
                                                          "could not find my certificate, cert payload omitted");
                }
-               cert_payload = cert_payload_create_from_x509(cert);
-               response->add_payload(response, (payload_t *)cert_payload);
        }
        
        if (cert_request)
@@ -733,9 +744,11 @@ static status_t get_response(private_ike_auth_t *this, message_t *request,
                auth_method = this->connection->get_auth_method(this->connection);
                authenticator = authenticator_create(this->ike_sa, auth_method);
                status = authenticator->verify_auth_data(authenticator, auth_request,
-                                                                                               this->init_request,
-                                                                                               this->nonce_r, idi_request,
-                                                                                               TRUE);
+                                                                                                this->init_request,
+                                                                                                this->nonce_r,
+                                                                                                my_id,
+                                                                                                other_id,
+                                                                                                TRUE);
                if (status != SUCCESS)
                {
                        this->logger->log(this->logger, AUDIT, 
@@ -746,7 +759,9 @@ static status_t get_response(private_ike_auth_t *this, message_t *request,
                }
                status = authenticator->compute_auth_data(authenticator, &auth_response,
                                                                                                  this->init_response,
-                                                                                                 this->nonce_i, idr_response,
+                                                                                                 this->nonce_i,
+                                                                                                 my_id,
+                                                                                                 other_id,
                                                                                                  FALSE);
                authenticator->destroy(authenticator);
                if (status != SUCCESS)
@@ -939,14 +954,20 @@ static status_t conclude(private_ike_auth_t *this, message_t *response,
        {       /* authenticate peer */
                authenticator_t *authenticator;
                auth_method_t auth_method;
+               identification_t *my_id;
                status_t status;
                
                auth_method = this->connection->get_auth_method(this->connection);
                authenticator = authenticator_create(this->ike_sa, auth_method);
-               status = authenticator->verify_auth_data(authenticator, auth_payload,
-                               this->init_response,
-                               this->nonce_i, idr_payload,
-                               FALSE);
+               my_id = this->policy->get_my_id(this->policy);
+
+               status = authenticator->verify_auth_data(authenticator,
+                                                                                                auth_payload,
+                                                                                                this->init_response,
+                                                                                                this->nonce_i,
+                                                                                                my_id,
+                                                                                                other_id,
+                                                                                                FALSE);
                authenticator->destroy(authenticator);
                if (status != SUCCESS)
                {
index 3c84415..a5f32f0 100755 (executable)
@@ -362,7 +362,7 @@ static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg)
                                                                   msg->add_conn.me.sendcert,
                                                                   msg->add_conn.other.sendcert,
                                                                   my_host, other_host,
-                                                                  RSA_DIGITAL_SIGNATURE,
+                                                                  msg->add_conn.auth_method,
                                                                   msg->add_conn.dpd.delay,
                                                                   msg->add_conn.rekey.tries,
                                                                   msg->add_conn.rekey.ike_lifetime,