diff options
Diffstat (limited to 'src/libcharon/encoding/payloads')
-rw-r--r-- | src/libcharon/encoding/payloads/encodings.c | 3 | ||||
-rw-r--r-- | src/libcharon/encoding/payloads/encodings.h | 5 | ||||
-rw-r--r-- | src/libcharon/encoding/payloads/encryption_payload.c | 131 | ||||
-rw-r--r-- | src/libcharon/encoding/payloads/encryption_payload.h | 3 | ||||
-rw-r--r-- | src/libcharon/encoding/payloads/payload.c | 3 | ||||
-rw-r--r-- | src/libcharon/encoding/payloads/payload.h | 15 |
6 files changed, 145 insertions, 15 deletions
diff --git a/src/libcharon/encoding/payloads/encodings.c b/src/libcharon/encoding/payloads/encodings.c index 3dc8ee4ec..7306dcf10 100644 --- a/src/libcharon/encoding/payloads/encodings.c +++ b/src/libcharon/encoding/payloads/encodings.c @@ -17,7 +17,7 @@ #include "encodings.h" -ENUM(encoding_type_names, U_INT_4, IKE_SPI, +ENUM(encoding_type_names, U_INT_4, ENCRYPTED_DATA, "U_INT_4", "U_INT_8", "U_INT_16", @@ -38,4 +38,5 @@ ENUM(encoding_type_names, U_INT_4, IKE_SPI, "ADDRESS", "CHUNK_DATA", "IKE_SPI", + "ENCRYPTED", ); diff --git a/src/libcharon/encoding/payloads/encodings.h b/src/libcharon/encoding/payloads/encodings.h index dde495bc2..124814ff5 100644 --- a/src/libcharon/encoding/payloads/encodings.h +++ b/src/libcharon/encoding/payloads/encodings.h @@ -297,6 +297,11 @@ enum encoding_type_t { IKE_SPI, /** + * Representating an encrypted IKEv1 message. + */ + ENCRYPTED_DATA, + + /** * Reprensenting a field containing a set of wrapped payloads. * * This type is not used directly, but as an offset to the wrapped payloads. diff --git a/src/libcharon/encoding/payloads/encryption_payload.c b/src/libcharon/encoding/payloads/encryption_payload.c index bb9969d0b..425e58621 100644 --- a/src/libcharon/encoding/payloads/encryption_payload.c +++ b/src/libcharon/encoding/payloads/encryption_payload.c @@ -1,6 +1,7 @@ /* * 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 * @@ -71,6 +72,11 @@ struct private_encryption_payload_t { * Contained payloads */ linked_list_t *payloads; + + /** + * Type of payload, ENCRYPTED or ENCRYPTED_V1 + */ + payload_type_t type; }; /** @@ -79,7 +85,7 @@ struct private_encryption_payload_t { * The defined offsets are the positions in a object of type * private_encryption_payload_t. */ -static encoding_rule_t encodings[] = { +static encoding_rule_t encodings_v2[] = { /* 1 Byte next payload type, stored in the field next_payload */ { U_INT_8, offsetof(private_encryption_payload_t, next_payload) }, /* Critical and 7 reserved bits, all stored for reconstruction */ @@ -109,6 +115,29 @@ static encoding_rule_t encodings[] = { +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ +/** + * Encoding rules to parse or generate a complete encrypted IKEv1 message. + * + * The defined offsets are the positions in a object of type + * private_encryption_payload_t. + */ +static encoding_rule_t encodings_v1[] = { + /* encrypted data, stored in a chunk */ + { ENCRYPTED_DATA, offsetof(private_encryption_payload_t, encrypted) }, +}; + +/* + 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Message Length ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! Encrypted IKE Payloads ! + + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + ! ! Padding (0-255 octets) ! + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ + METHOD(payload_t, verify, status_t, private_encryption_payload_t *this) { @@ -118,20 +147,29 @@ METHOD(payload_t, verify, status_t, METHOD(payload_t, get_encoding_rules, int, private_encryption_payload_t *this, encoding_rule_t **rules) { - *rules = encodings; - return countof(encodings); + if (this->type == ENCRYPTED) + { + *rules = encodings_v2; + return countof(encodings_v2); + } + *rules = encodings_v1; + return countof(encodings_v1); } METHOD(payload_t, get_header_length, int, private_encryption_payload_t *this) { - return 4; + if (this->type == ENCRYPTED) + { + return 4; + } + return 0; } METHOD(payload_t, get_type, payload_type_t, private_encryption_payload_t *this) { - return ENCRYPTED; + return this->type; } METHOD(payload_t, get_next_type, payload_type_t, @@ -143,7 +181,8 @@ METHOD(payload_t, get_next_type, payload_type_t, METHOD(payload_t, set_next_type, void, private_encryption_payload_t *this, payload_type_t type) { - /* the next payload is set during add */ + /* the next payload is set during add, still allow this for IKEv1 */ + this->next_payload = type; } /** @@ -340,6 +379,47 @@ METHOD(encryption_payload_t, encrypt, bool, return TRUE; } +METHOD(encryption_payload_t, encrypt_v1, bool, + private_encryption_payload_t *this, chunk_t iv) +{ + generator_t *generator; + chunk_t plain, padding; + size_t bs; + + if (this->aead == NULL) + { + DBG1(DBG_ENC, "encryption failed, transform missing"); + chunk_free(&iv); + return FALSE; + } + + generator = generator_create(); + plain = generate(this, generator); + bs = this->aead->get_block_size(this->aead); + padding.len = bs - (plain.len % bs); + + /* prepare data to encrypt: + * | plain | padding | */ + free(this->encrypted.ptr); + this->encrypted = chunk_alloc(plain.len + padding.len); + memcpy(this->encrypted.ptr, plain.ptr, plain.len); + plain.ptr = this->encrypted.ptr; + padding.ptr = plain.ptr + plain.len; + memset(padding.ptr, 0, padding.len); + generator->destroy(generator); + + DBG3(DBG_ENC, "encrypting payloads:"); + DBG3(DBG_ENC, "plain %B", &plain); + DBG3(DBG_ENC, "padding %B", &padding); + + this->aead->encrypt(this->aead, this->encrypted, chunk_empty, iv, NULL); + chunk_free(&iv); + + DBG3(DBG_ENC, "encrypted %B", &this->encrypted); + + return TRUE; +} + /** * Parse the payloads after decryption. */ @@ -443,6 +523,36 @@ METHOD(encryption_payload_t, decrypt, status_t, return parse(this, plain); } +METHOD(encryption_payload_t, decrypt_v1, status_t, + private_encryption_payload_t *this, chunk_t iv) +{ + if (this->aead == NULL) + { + DBG1(DBG_ENC, "decryption failed, transform missing"); + chunk_free(&iv); + return INVALID_STATE; + } + + /* data must be a multiple of block size */ + if (iv.len != this->aead->get_block_size(this->aead) || + this->encrypted.len < iv.len || this->encrypted.len % iv.len) + { + DBG1(DBG_ENC, "decryption failed, invalid length"); + chunk_free(&iv); + return FAILED; + } + + DBG3(DBG_ENC, "decrypting payloads:"); + DBG3(DBG_ENC, "encrypted %B", &this->encrypted); + + this->aead->decrypt(this->aead, this->encrypted, chunk_empty, iv, NULL); + chunk_free(&iv); + + DBG3(DBG_ENC, "plain %B", &this->encrypted); + + return parse(this, this->encrypted); +} + METHOD(encryption_payload_t, set_transform, void, private_encryption_payload_t *this, aead_t* aead) { @@ -460,7 +570,7 @@ METHOD2(payload_t, encryption_payload_t, destroy, void, /* * Described in header */ -encryption_payload_t *encryption_payload_create() +encryption_payload_t *encryption_payload_create(payload_type_t type) { private_encryption_payload_t *this; @@ -487,7 +597,14 @@ encryption_payload_t *encryption_payload_create() .next_payload = NO_PAYLOAD, .payload_length = get_header_length(this), .payloads = linked_list_create(), + .type = type, ); + if (type == ENCRYPTED_V1) + { + this->public.encrypt = _encrypt_v1; + this->public.decrypt = _decrypt_v1; + } + return &this->public; } diff --git a/src/libcharon/encoding/payloads/encryption_payload.h b/src/libcharon/encoding/payloads/encryption_payload.h index 3cdc54b37..60774bde0 100644 --- a/src/libcharon/encoding/payloads/encryption_payload.h +++ b/src/libcharon/encoding/payloads/encryption_payload.h @@ -97,8 +97,9 @@ struct encryption_payload_t { /** * Creates an empty encryption_payload_t object. * + * @param type ENCRYPTED or ENCRYPTED_V1 * @return encryption_payload_t object */ -encryption_payload_t *encryption_payload_create(void); +encryption_payload_t *encryption_payload_create(payload_type_t type); #endif /** ENCRYPTION_PAYLOAD_H_ @}*/ diff --git a/src/libcharon/encoding/payloads/payload.c b/src/libcharon/encoding/payloads/payload.c index 9dc26773a..2f22503e6 100644 --- a/src/libcharon/encoding/payloads/payload.c +++ b/src/libcharon/encoding/payloads/payload.c @@ -220,7 +220,8 @@ payload_t *payload_create(payload_type_t type) case EXTENSIBLE_AUTHENTICATION: return (payload_t*)eap_payload_create(); case ENCRYPTED: - return (payload_t*)encryption_payload_create(); + case ENCRYPTED_V1: + return (payload_t*)encryption_payload_create(type); default: return (payload_t*)unknown_payload_create(type); } diff --git a/src/libcharon/encoding/payloads/payload.h b/src/libcharon/encoding/payloads/payload.h index 84871cfb6..e4ed76abf 100644 --- a/src/libcharon/encoding/payloads/payload.h +++ b/src/libcharon/encoding/payloads/payload.h @@ -247,6 +247,11 @@ enum payload_type_t { * CONFIGURATION_ATTRIBUTE, attribute in a configuration payload. */ CONFIGURATION_ATTRIBUTE, + + /** + * This is not really a payload, but rather the complete IKEv1 message. + */ + ENCRYPTED_V1, }; /** @@ -286,35 +291,35 @@ struct payload_t { /** * Get type of payload. * - * @return type of this payload + * @return type of this payload */ payload_type_t (*get_type) (payload_t *this); /** * Get type of next payload or NO_PAYLOAD (0) if this is the last one. * - * @return type of next payload + * @return type of next payload */ payload_type_t (*get_next_type) (payload_t *this); /** * Set type of next payload. * - * @param type type of next payload + * @param type type of next payload */ void (*set_next_type) (payload_t *this,payload_type_t type); /** * Get length of payload. * - * @return length of this payload + * @return length of this payload */ size_t (*get_length) (payload_t *this); /** * Verifies payload structure and makes consistence check. * - * @return SUCCESS, FAILED if consistence not given + * @return SUCCESS, FAILED if consistence not given */ status_t (*verify) (payload_t *this); |