summaryrefslogtreecommitdiff
path: root/src/libipsec/esp_context.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libipsec/esp_context.c')
-rw-r--r--src/libipsec/esp_context.c160
1 files changed, 102 insertions, 58 deletions
diff --git a/src/libipsec/esp_context.c b/src/libipsec/esp_context.c
index 44b1117d9..bbcb62add 100644
--- a/src/libipsec/esp_context.c
+++ b/src/libipsec/esp_context.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012-2013 Tobias Brunner
* Copyright (C) 2012 Giuliano Grassi
* Copyright (C) 2012 Ralf Sager
* Hochschule fuer Technik Rapperswil
@@ -22,8 +22,6 @@
#include <library.h>
#include <utils/debug.h>
-#include <crypto/crypters/crypter.h>
-#include <crypto/signers/signer.h>
/**
* Should be a multiple of 8
@@ -43,14 +41,9 @@ struct private_esp_context_t {
esp_context_t public;
/**
- * Crypter used to encrypt/decrypt ESP packets
+ * AEAD wrapper or method to encrypt/decrypt/authenticate ESP packets
*/
- crypter_t *crypter;
-
- /**
- * Signer to authenticate ESP packets
- */
- signer_t *signer;
+ aead_t *aead;
/**
* The highest sequence number that was successfully verified
@@ -197,97 +190,150 @@ METHOD(esp_context_t, next_seqno, bool,
return TRUE;
}
-METHOD(esp_context_t, get_signer, signer_t *,
- private_esp_context_t *this)
-{
- return this->signer;
-}
-
-METHOD(esp_context_t, get_crypter, crypter_t *,
- private_esp_context_t *this)
+METHOD(esp_context_t, get_aead, aead_t*,
+ private_esp_context_t *this)
{
- return this->crypter;
+ return this->aead;
}
METHOD(esp_context_t, destroy, void,
- private_esp_context_t *this)
+ private_esp_context_t *this)
{
chunk_free(&this->window);
- DESTROY_IF(this->crypter);
- DESTROY_IF(this->signer);
+ DESTROY_IF(this->aead);
free(this);
}
/**
- * Described in header.
+ * Create an AEAD algorithm
*/
-esp_context_t *esp_context_create(int enc_alg, chunk_t enc_key,
- int int_alg, chunk_t int_key, bool inbound)
+static bool create_aead(private_esp_context_t *this, int alg,
+ chunk_t key)
{
- private_esp_context_t *this;
+ switch (alg)
+ {
+ case ENCR_AES_GCM_ICV8:
+ case ENCR_AES_GCM_ICV12:
+ case ENCR_AES_GCM_ICV16:
+ /* the key includes a 4 byte salt */
+ this->aead = lib->crypto->create_aead(lib->crypto, alg, key.len-4);
+ break;
+ default:
+ break;
+ }
+ if (!this->aead)
+ {
+ DBG1(DBG_ESP, "failed to create ESP context: unsupported AEAD "
+ "algorithm");
+ return FALSE;
+ }
+ if (!this->aead->set_key(this->aead, key))
+ {
+ DBG1(DBG_ESP, "failed to create ESP context: setting AEAD key failed");
+ return FALSE;
+ }
+ return TRUE;
+}
- INIT(this,
- .public = {
- .get_crypter = _get_crypter,
- .get_signer = _get_signer,
- .get_seqno = _get_seqno,
- .next_seqno = _next_seqno,
- .verify_seqno = _verify_seqno,
- .set_authenticated_seqno = _set_authenticated_seqno,
- .destroy = _destroy,
- },
- .inbound = inbound,
- .window_size = ESP_DEFAULT_WINDOW_SIZE,
- );
+/**
+ * Create AEAD wrapper around traditional encryption/integrity algorithms
+ */
+static bool create_traditional(private_esp_context_t *this, int enc_alg,
+ chunk_t enc_key, int int_alg, chunk_t int_key)
+{
+ crypter_t *crypter = NULL;
+ signer_t *signer = NULL;
- switch(enc_alg)
+ switch (enc_alg)
{
case ENCR_AES_CBC:
- this->crypter = lib->crypto->create_crypter(lib->crypto, enc_alg,
- enc_key.len);
+ crypter = lib->crypto->create_crypter(lib->crypto, enc_alg,
+ enc_key.len);
break;
default:
break;
}
- if (!this->crypter)
+ if (!crypter)
{
DBG1(DBG_ESP, "failed to create ESP context: unsupported encryption "
"algorithm");
- destroy(this);
- return NULL;
+ goto failed;
}
- if (!this->crypter->set_key(this->crypter, enc_key))
+ if (!crypter->set_key(crypter, enc_key))
{
DBG1(DBG_ESP, "failed to create ESP context: setting encryption key "
"failed");
- destroy(this);
- return NULL;
+ goto failed;
}
- switch(int_alg)
+ switch (int_alg)
{
case AUTH_HMAC_SHA1_96:
case AUTH_HMAC_SHA2_256_128:
case AUTH_HMAC_SHA2_384_192:
case AUTH_HMAC_SHA2_512_256:
- this->signer = lib->crypto->create_signer(lib->crypto, int_alg);
+ signer = lib->crypto->create_signer(lib->crypto, int_alg);
break;
default:
break;
}
- if (!this->signer)
+ if (!signer)
{
DBG1(DBG_ESP, "failed to create ESP context: unsupported integrity "
"algorithm");
- destroy(this);
- return NULL;
+ goto failed;
}
- if (!this->signer->set_key(this->signer, int_key))
+ if (!signer->set_key(signer, int_key))
{
DBG1(DBG_ESP, "failed to create ESP context: setting signature key "
"failed");
- destroy(this);
- return NULL;
+ goto failed;
+ }
+ this->aead = aead_create(crypter, signer);
+ return TRUE;
+
+failed:
+ DESTROY_IF(crypter);
+ DESTROY_IF(signer);
+ return FALSE;
+}
+
+/**
+ * Described in header.
+ */
+esp_context_t *esp_context_create(int enc_alg, chunk_t enc_key,
+ int int_alg, chunk_t int_key, bool inbound)
+{
+ private_esp_context_t *this;
+
+ INIT(this,
+ .public = {
+ .get_aead = _get_aead,
+ .get_seqno = _get_seqno,
+ .next_seqno = _next_seqno,
+ .verify_seqno = _verify_seqno,
+ .set_authenticated_seqno = _set_authenticated_seqno,
+ .destroy = _destroy,
+ },
+ .inbound = inbound,
+ .window_size = ESP_DEFAULT_WINDOW_SIZE,
+ );
+
+ if (encryption_algorithm_is_aead(enc_alg))
+ {
+ if (!create_aead(this, enc_alg, enc_key))
+ {
+ destroy(this);
+ return NULL;
+ }
+ }
+ else
+ {
+ if (!create_traditional(this, enc_alg, enc_key, int_alg, int_key))
+ {
+ destroy(this);
+ return NULL;
+ }
}
if (inbound)
@@ -297,5 +343,3 @@ esp_context_t *esp_context_create(int enc_alg, chunk_t enc_key,
}
return &this->public;
}
-
-