diff options
Diffstat (limited to 'src/libipsec/esp_context.c')
-rw-r--r-- | src/libipsec/esp_context.c | 160 |
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; } - - |