diff options
author | Andreas Steffen <andreas.steffen@strongswan.org> | 2006-09-18 07:42:57 +0000 |
---|---|---|
committer | Andreas Steffen <andreas.steffen@strongswan.org> | 2006-09-18 07:42:57 +0000 |
commit | e2de376c745854597eb71b98b24e5b7a3e000ecf (patch) | |
tree | 9c14d6dd9b89ce76212d0fb7c4755451f7ef0b6d | |
parent | 957115957a805c62f80d08ef61760195b1bff37a (diff) | |
download | strongswan-e2de376c745854597eb71b98b24e5b7a3e000ecf.tar.bz2 strongswan-e2de376c745854597eb71b98b24e5b7a3e000ecf.tar.xz |
added PSK support
-rwxr-xr-x | src/charon/config/credentials/credential_store.h | 20 | ||||
-rw-r--r-- | src/charon/config/credentials/local_credential_store.c | 275 | ||||
-rw-r--r-- | src/charon/config/policies/local_policy_store.c | 2 | ||||
-rw-r--r-- | src/charon/daemon.c | 4 | ||||
-rw-r--r-- | src/charon/sa/authenticator.c | 209 | ||||
-rw-r--r-- | src/charon/sa/authenticator.h | 30 | ||||
-rw-r--r-- | src/charon/sa/transactions/ike_auth.c | 57 | ||||
-rwxr-xr-x | src/charon/threads/stroke_interface.c | 2 |
8 files changed, 433 insertions, 166 deletions
diff --git a/src/charon/config/credentials/credential_store.h b/src/charon/config/credentials/credential_store.h index f8db8bd4b..a9d72b47f 100755 --- a/src/charon/config/credentials/credential_store.h +++ b/src/charon/config/credentials/credential_store.h @@ -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. diff --git a/src/charon/config/credentials/local_credential_store.c b/src/charon/config/credentials/local_credential_store.c index 96c16d7ae..b60fd8aa9 100644 --- a/src/charon/config/credentials/local_credential_store.c +++ b/src/charon/config/credentials/local_credential_store.c @@ -33,12 +33,80 @@ #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); diff --git a/src/charon/config/policies/local_policy_store.c b/src/charon/config/policies/local_policy_store.c index 0c3e0ee04..9ab894818 100644 --- a/src/charon/config/policies/local_policy_store.c +++ b/src/charon/config/policies/local_policy_store.c @@ -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); diff --git a/src/charon/daemon.c b/src/charon/daemon.c index 68846fc2e..cad9bee2a 100644 --- a/src/charon/daemon.c +++ b/src/charon/daemon.c @@ -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(); diff --git a/src/charon/sa/authenticator.c b/src/charon/sa/authenticator.c index 8dcfc049f..436bd2424 100644 --- a/src/charon/sa/authenticator.c +++ b/src/charon/sa/authenticator.c @@ -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; diff --git a/src/charon/sa/authenticator.h b/src/charon/sa/authenticator.h index 645e39b81..4fb776619 100644 --- a/src/charon/sa/authenticator.h +++ b/src/charon/sa/authenticator.h @@ -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. diff --git a/src/charon/sa/transactions/ike_auth.c b/src/charon/sa/transactions/ike_auth.c index 681c76427..e32dc3c72 100644 --- a/src/charon/sa/transactions/ike_auth.c +++ b/src/charon/sa/transactions/ike_auth.c @@ -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) { diff --git a/src/charon/threads/stroke_interface.c b/src/charon/threads/stroke_interface.c index 3c84415f4..a5f32f040 100755 --- a/src/charon/threads/stroke_interface.c +++ b/src/charon/threads/stroke_interface.c @@ -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, |