diff options
author | Tobias Brunner <tobias@strongswan.org> | 2013-04-18 17:02:41 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2013-05-03 15:13:57 +0200 |
commit | 24a8d1253fe40b85de9788f35d7926e3166e2bcf (patch) | |
tree | 8a8e08ae3143ac9fd232a61f414f9798d08c938e /src/libipsec | |
parent | 61fb3267b2456ecc1900ec945a00a73662d0a8ac (diff) | |
download | strongswan-24a8d1253fe40b85de9788f35d7926e3166e2bcf.tar.bz2 strongswan-24a8d1253fe40b85de9788f35d7926e3166e2bcf.tar.xz |
libipsec: Wrap traditional algorithms in AEAD wrapper
Diffstat (limited to 'src/libipsec')
-rw-r--r-- | src/libipsec/esp_context.c | 116 | ||||
-rw-r--r-- | src/libipsec/esp_context.h | 18 | ||||
-rw-r--r-- | src/libipsec/esp_packet.c | 67 |
3 files changed, 91 insertions, 110 deletions
diff --git a/src/libipsec/esp_context.c b/src/libipsec/esp_context.c index 44b1117d9..86e8dd0a8 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,95 +190,106 @@ 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 AEAD wrapper around traditional encryption/integrity algorithms */ -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_traditional(private_esp_context_t *this, int enc_alg, + chunk_t enc_key, int int_alg, chunk_t int_key) { - private_esp_context_t *this; + crypter_t *crypter = NULL; + signer_t *signer = NULL; - 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, - ); - - 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"); + 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 (!create_traditional(this, enc_alg, enc_key, int_alg, int_key)) + { destroy(this); return NULL; } @@ -297,5 +301,3 @@ esp_context_t *esp_context_create(int enc_alg, chunk_t enc_key, } return &this->public; } - - diff --git a/src/libipsec/esp_context.h b/src/libipsec/esp_context.h index db247dced..b33daf589 100644 --- a/src/libipsec/esp_context.h +++ b/src/libipsec/esp_context.h @@ -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 @@ -24,8 +24,7 @@ #define ESP_CONTEXT_H_ #include <library.h> -#include <crypto/crypters/crypter.h> -#include <crypto/signers/signer.h> +#include <crypto/aead.h> typedef struct esp_context_t esp_context_t; @@ -35,18 +34,11 @@ typedef struct esp_context_t esp_context_t; struct esp_context_t { /** - * Get the crypter. + * Get AEAD wrapper or method to encrypt/decrypt/authenticate ESP packets. * - * @return crypter + * @return AEAD wrapper of method */ - crypter_t *(*get_crypter)(esp_context_t *this); - - /** - * Get the signer. - * - * @return signer - */ - signer_t *(*get_signer)(esp_context_t *this); + aead_t *(*get_aead)(esp_context_t *this); /** * Get the current outbound ESP sequence number or the highest authenticated diff --git a/src/libipsec/esp_packet.c b/src/libipsec/esp_packet.c index 43a3c2a97..61389daa4 100644 --- a/src/libipsec/esp_packet.c +++ b/src/libipsec/esp_packet.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 @@ -212,28 +212,27 @@ METHOD(esp_packet_t, decrypt, status_t, { bio_reader_t *reader; u_int32_t spi, seq; - chunk_t data, iv, icv, ciphertext, plaintext; - crypter_t *crypter; - signer_t *signer; + chunk_t data, iv, icv, aad, ciphertext, plaintext; + aead_t *aead; DESTROY_IF(this->payload); this->payload = NULL; data = this->packet->get_data(this->packet); - crypter = esp_context->get_crypter(esp_context); - signer = esp_context->get_signer(esp_context); + aead = esp_context->get_aead(esp_context); reader = bio_reader_create(data); if (!reader->read_uint32(reader, &spi) || !reader->read_uint32(reader, &seq) || - !reader->read_data(reader, crypter->get_iv_size(crypter), &iv) || - !reader->read_data_end(reader, signer->get_block_size(signer), &icv) || - reader->remaining(reader) % crypter->get_block_size(crypter)) + !reader->read_data(reader, aead->get_iv_size(aead), &iv) || + !reader->read_data_end(reader, aead->get_icv_size(aead), &icv) || + reader->remaining(reader) % aead->get_block_size(aead)) { DBG1(DBG_ESP, "ESP decryption failed: invalid length"); return PARSE_ERROR; } ciphertext = reader->peek(reader); + ciphertext.len += icv.len; reader->destroy(reader); if (!esp_context->verify_seqno(esp_context, seq)) @@ -246,20 +245,15 @@ METHOD(esp_packet_t, decrypt, status_t, DBG3(DBG_ESP, "ESP decryption:\n SPI %.8x [seq %u]\n IV %B\n " "encrypted %B\n ICV %B", spi, seq, &iv, &ciphertext, &icv); - if (!signer->get_signature(signer, chunk_create(data.ptr, 8), NULL) || - !signer->get_signature(signer, iv, NULL) || - !signer->verify_signature(signer, ciphertext, icv)) - { - DBG1(DBG_ESP, "ICV verification failed!"); - return FAILED; - } - esp_context->set_authenticated_seqno(esp_context, seq); + /* aad = spi + seq */ + aad = chunk_create(data.ptr, 8); - if (!crypter->decrypt(crypter, ciphertext, iv, &plaintext)) + if (!aead->decrypt(aead, ciphertext, aad, iv, &plaintext)) { - DBG1(DBG_ESP, "ESP decryption failed"); + DBG1(DBG_ESP, "ESP decryption or ICV verification failed"); return FAILED; } + esp_context->set_authenticated_seqno(esp_context, seq); if (!remove_padding(this, plaintext)) { @@ -284,12 +278,11 @@ static void generate_padding(chunk_t padding) METHOD(esp_packet_t, encrypt, status_t, private_esp_packet_t *this, esp_context_t *esp_context, u_int32_t spi) { - chunk_t iv, icv, padding, payload, ciphertext, auth_data; + chunk_t iv, icv, aad, padding, payload, ciphertext; bio_writer_t *writer; u_int32_t next_seqno; size_t blocksize, plainlen; - crypter_t *crypter; - signer_t *signer; + aead_t *aead; rng_t *rng; this->packet->set_data(this->packet, chunk_empty); @@ -306,12 +299,11 @@ METHOD(esp_packet_t, encrypt, status_t, DBG1(DBG_ESP, "ESP encryption failed: could not find RNG"); return NOT_FOUND; } - crypter = esp_context->get_crypter(esp_context); - signer = esp_context->get_signer(esp_context); + aead = esp_context->get_aead(esp_context); - blocksize = crypter->get_block_size(crypter); - iv.len = crypter->get_iv_size(crypter); - icv.len = signer->get_block_size(signer); + blocksize = aead->get_block_size(aead); + iv.len = aead->get_iv_size(aead); + icv.len = aead->get_icv_size(aead); /* plaintext = payload, padding, pad_length, next_header */ payload = this->payload ? this->payload->get_encoding(this->payload) @@ -349,24 +341,19 @@ METHOD(esp_packet_t, encrypt, status_t, writer->write_uint8(writer, padding.len); writer->write_uint8(writer, this->next_header); + /* aad = spi + seq */ + aad = writer->get_buf(writer); + aad.len = 8; + icv = writer->skip(writer, icv.len); + DBG3(DBG_ESP, "ESP before encryption:\n payload = %B\n padding = %B\n " "padding length = %hhu, next header = %hhu", &payload, &padding, (u_int8_t)padding.len, this->next_header); - /* encrypt the content inline */ - if (!crypter->encrypt(crypter, ciphertext, iv, NULL)) - { - DBG1(DBG_ESP, "ESP encryption failed"); - writer->destroy(writer); - return FAILED; - } - - /* calculate signature */ - auth_data = writer->get_buf(writer); - icv = writer->skip(writer, icv.len); - if (!signer->get_signature(signer, auth_data, icv.ptr)) + /* encrypt/authenticate the content inline */ + if (!aead->encrypt(aead, ciphertext, aad, iv, NULL)) { - DBG1(DBG_ESP, "ESP encryption failed: signature generation failed"); + DBG1(DBG_ESP, "ESP encryption or ICV generation failed"); writer->destroy(writer); return FAILED; } |