aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTobias Brunner <tobias@strongswan.org>2014-06-12 19:04:24 +0200
committerTobias Brunner <tobias@strongswan.org>2014-10-10 09:31:17 +0200
commit44996b5866928e3cc05e22e7f08209bd74aecda3 (patch)
treeeb5ed52029b103eff6b362537d7271c308de767c /src
parent41751a70d90494c5931e9678279b1006da34c1a2 (diff)
downloadstrongswan-44996b5866928e3cc05e22e7f08209bd74aecda3.tar.bz2
strongswan-44996b5866928e3cc05e22e7f08209bd74aecda3.tar.xz
encrypted_payload: Extract some utility functions
Diffstat (limited to 'src')
-rw-r--r--src/libcharon/encoding/payloads/encrypted_payload.c184
1 files changed, 110 insertions, 74 deletions
diff --git a/src/libcharon/encoding/payloads/encrypted_payload.c b/src/libcharon/encoding/payloads/encrypted_payload.c
index d71f514c2..bd309a974 100644
--- a/src/libcharon/encoding/payloads/encrypted_payload.c
+++ b/src/libcharon/encoding/payloads/encrypted_payload.c
@@ -1,7 +1,7 @@
/*
+ * Copyright (C) 2011-2014 Tobias Brunner
* Copyright (C) 2005-2010 Martin Willi
* Copyright (C) 2010 revosec AG
- * Copyright (C) 2011 Tobias Brunner
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -180,13 +180,30 @@ METHOD(payload_t, set_next_type, void,
}
/**
+ * Get length of encryption/integrity overhead for the given plaintext length
+ */
+static size_t compute_overhead(aead_t *aead, size_t len)
+{
+ size_t bs, overhead;
+
+ /* padding */
+ bs = aead->get_block_size(aead);
+ overhead = bs - (len % bs);
+ /* add iv */
+ overhead += aead->get_iv_size(aead);
+ /* add icv */
+ overhead += aead->get_icv_size(aead);
+ return overhead;
+}
+
+/**
* Compute the length of the whole payload
*/
static void compute_length(private_encrypted_payload_t *this)
{
enumerator_t *enumerator;
payload_t *payload;
- size_t bs, length = 0;
+ size_t length = 0;
if (this->encrypted.len)
{
@@ -203,13 +220,7 @@ static void compute_length(private_encrypted_payload_t *this)
if (this->aead)
{
- /* append padding */
- bs = this->aead->get_block_size(this->aead);
- length += bs - (length % bs);
- /* add iv */
- length += this->aead->get_iv_size(this->aead);
- /* add icv */
- length += this->aead->get_icv_size(this->aead);
+ length += compute_overhead(this->aead, length);
}
}
length += get_header_length(this);
@@ -304,44 +315,36 @@ static chunk_t append_header(private_encrypted_payload_t *this, chunk_t assoc)
return chunk_cat("cc", assoc, chunk_from_thing(header));
}
-METHOD(encrypted_payload_t, encrypt, status_t,
- private_encrypted_payload_t *this, u_int64_t mid, chunk_t assoc)
+/**
+ * Encrypts the data in plain and returns it in an allocated chunk.
+ */
+static status_t encrypt_content(char *label, aead_t *aead, u_int64_t mid,
+ chunk_t plain, chunk_t assoc, chunk_t *encrypted)
{
- chunk_t iv, plain, padding, icv, crypt;
- generator_t *generator;
+ chunk_t iv, padding, icv, crypt;
iv_gen_t *iv_gen;
rng_t *rng;
size_t bs;
- if (this->aead == NULL)
- {
- DBG1(DBG_ENC, "encrypting encrypted payload failed, transform missing");
- return INVALID_STATE;
- }
-
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
if (!rng)
{
- DBG1(DBG_ENC, "encrypting encrypted payload failed, no RNG found");
+ DBG1(DBG_ENC, "encrypting %s failed, no RNG found", label);
return NOT_SUPPORTED;
}
- iv_gen = this->aead->get_iv_gen(this->aead);
+ iv_gen = aead->get_iv_gen(aead);
if (!iv_gen)
{
- DBG1(DBG_ENC, "encrypting encrypted payload failed, no IV generator");
+ DBG1(DBG_ENC, "encrypting %s failed, no IV generator", label);
return NOT_SUPPORTED;
}
- assoc = append_header(this, assoc);
-
- generator = generator_create();
- plain = generate(this, generator);
- bs = this->aead->get_block_size(this->aead);
+ bs = aead->get_block_size(aead);
/* we need at least one byte padding to store the padding length */
padding.len = bs - (plain.len % bs);
- iv.len = this->aead->get_iv_size(this->aead);
- icv.len = this->aead->get_icv_size(this->aead);
+ iv.len = aead->get_iv_size(aead);
+ icv.len = aead->get_icv_size(aead);
/* prepare data to authenticate-encrypt:
* | IV | plain | padding | ICV |
@@ -350,45 +353,62 @@ METHOD(encrypted_payload_t, encrypt, status_t,
* v /
* assoc -> + ------->/
*/
- free(this->encrypted.ptr);
- this->encrypted = chunk_alloc(iv.len + plain.len + padding.len + icv.len);
- iv.ptr = this->encrypted.ptr;
+ *encrypted = chunk_alloc(iv.len + plain.len + padding.len + icv.len);
+ iv.ptr = encrypted->ptr;
memcpy(iv.ptr + iv.len, plain.ptr, plain.len);
plain.ptr = iv.ptr + iv.len;
padding.ptr = plain.ptr + plain.len;
icv.ptr = padding.ptr + padding.len;
crypt = chunk_create(plain.ptr, plain.len + padding.len);
- generator->destroy(generator);
if (!iv_gen->get_iv(iv_gen, mid, iv.len, iv.ptr) ||
!rng->get_bytes(rng, padding.len - 1, padding.ptr))
{
- DBG1(DBG_ENC, "encrypting encrypted payload failed, no IV or padding");
+ DBG1(DBG_ENC, "encrypting %s failed, no IV or padding", label);
rng->destroy(rng);
- free(assoc.ptr);
+
return FAILED;
}
padding.ptr[padding.len - 1] = padding.len - 1;
rng->destroy(rng);
- DBG3(DBG_ENC, "encrypted payload encryption:");
+ DBG3(DBG_ENC, "%s encryption:", label);
DBG3(DBG_ENC, "IV %B", &iv);
DBG3(DBG_ENC, "plain %B", &plain);
DBG3(DBG_ENC, "padding %B", &padding);
DBG3(DBG_ENC, "assoc %B", &assoc);
- if (!this->aead->encrypt(this->aead, crypt, assoc, iv, NULL))
+ if (!aead->encrypt(aead, crypt, assoc, iv, NULL))
{
- free(assoc.ptr);
return FAILED;
}
-
DBG3(DBG_ENC, "encrypted %B", &crypt);
DBG3(DBG_ENC, "ICV %B", &icv);
+ return SUCCESS;
+}
- free(assoc.ptr);
+METHOD(encrypted_payload_t, encrypt, status_t,
+ private_encrypted_payload_t *this, u_int64_t mid, chunk_t assoc)
+{
+ generator_t *generator;
+ chunk_t plain;
+ status_t status;
- return SUCCESS;
+ if (this->aead == NULL)
+ {
+ DBG1(DBG_ENC, "encrypting encrypted payload failed, transform missing");
+ return INVALID_STATE;
+ }
+
+ free(this->encrypted.ptr);
+ generator = generator_create();
+ plain = generate(this, generator);
+ assoc = append_header(this, assoc);
+ status = encrypt_content("encrypted payload", this->aead, mid, plain, assoc,
+ &this->encrypted);
+ generator->destroy(generator);
+ free(assoc.ptr);
+ return status;
}
METHOD(encrypted_payload_t, encrypt_v1, status_t,
@@ -476,18 +496,16 @@ static status_t parse(private_encrypted_payload_t *this, chunk_t plain)
return SUCCESS;
}
-METHOD(encrypted_payload_t, decrypt, status_t,
- private_encrypted_payload_t *this, chunk_t assoc)
+/**
+ * Decrypts the given data in-place and returns a chunk pointing to the
+ * resulting plaintext.
+ */
+static status_t decrypt_content(char *label, aead_t *aead, chunk_t encrypted,
+ chunk_t assoc, chunk_t *plain)
{
- chunk_t iv, plain, padding, icv, crypt;
+ chunk_t iv, padding, icv, crypt;
size_t bs;
- if (this->aead == NULL)
- {
- DBG1(DBG_ENC, "decrypting encrypted payload failed, transform missing");
- return INVALID_STATE;
- }
-
/* prepare data to authenticate-decrypt:
* | IV | plain | padding | ICV |
* \____crypt______/ ^
@@ -495,52 +513,70 @@ METHOD(encrypted_payload_t, decrypt, status_t,
* v /
* assoc -> + ------->/
*/
-
- bs = this->aead->get_block_size(this->aead);
- iv.len = this->aead->get_iv_size(this->aead);
- iv.ptr = this->encrypted.ptr;
- icv.len = this->aead->get_icv_size(this->aead);
- icv.ptr = this->encrypted.ptr + this->encrypted.len - icv.len;
+ bs = aead->get_block_size(aead);
+ iv.len = aead->get_iv_size(aead);
+ iv.ptr = encrypted.ptr;
+ icv.len = aead->get_icv_size(aead);
+ icv.ptr = encrypted.ptr + encrypted.len - icv.len;
crypt.ptr = iv.ptr + iv.len;
- crypt.len = this->encrypted.len - iv.len;
+ crypt.len = encrypted.len - iv.len;
- if (iv.len + icv.len > this->encrypted.len ||
+ if (iv.len + icv.len > encrypted.len ||
(crypt.len - icv.len) % bs)
{
- DBG1(DBG_ENC, "decrypting encrypted payload failed, invalid length");
+ DBG1(DBG_ENC, "decrypting %s payload failed, invalid length", label);
return FAILED;
}
- assoc = append_header(this, assoc);
-
- DBG3(DBG_ENC, "encrypted payload decryption:");
+ DBG3(DBG_ENC, "%s decryption:", label);
DBG3(DBG_ENC, "IV %B", &iv);
DBG3(DBG_ENC, "encrypted %B", &crypt);
DBG3(DBG_ENC, "ICV %B", &icv);
DBG3(DBG_ENC, "assoc %B", &assoc);
- if (!this->aead->decrypt(this->aead, crypt, assoc, iv, NULL))
+ if (!aead->decrypt(aead, crypt, assoc, iv, NULL))
{
- DBG1(DBG_ENC, "verifying encrypted payload integrity failed");
- free(assoc.ptr);
+ DBG1(DBG_ENC, "verifying %s integrity failed", label);
return FAILED;
}
- free(assoc.ptr);
- plain = chunk_create(crypt.ptr, crypt.len - icv.len);
- padding.len = plain.ptr[plain.len - 1] + 1;
- if (padding.len > plain.len)
+ *plain = chunk_create(crypt.ptr, crypt.len - icv.len);
+ padding.len = plain->ptr[plain->len - 1] + 1;
+ if (padding.len > plain->len)
{
- DBG1(DBG_ENC, "decrypting encrypted payload failed, "
- "padding invalid %B", &crypt);
+ DBG1(DBG_ENC, "decrypting %s failed, padding invalid %B", label,
+ &crypt);
return PARSE_ERROR;
}
- plain.len -= padding.len;
- padding.ptr = plain.ptr + plain.len;
+ plain->len -= padding.len;
+ padding.ptr = plain->ptr + plain->len;
- DBG3(DBG_ENC, "plain %B", &plain);
+ DBG3(DBG_ENC, "plain %B", plain);
DBG3(DBG_ENC, "padding %B", &padding);
+ return SUCCESS;
+}
+
+METHOD(encrypted_payload_t, decrypt, status_t,
+ private_encrypted_payload_t *this, chunk_t assoc)
+{
+ chunk_t plain;
+ status_t status;
+ if (this->aead == NULL)
+ {
+ DBG1(DBG_ENC, "decrypting encrypted payload failed, transform missing");
+ return INVALID_STATE;
+ }
+
+ assoc = append_header(this, assoc);
+ status = decrypt_content("encrypted payload", this->aead, this->encrypted,
+ assoc, &plain);
+ free(assoc.ptr);
+
+ if (status != SUCCESS)
+ {
+ return status;
+ }
return parse(this, plain);
}