diff options
Diffstat (limited to 'src/charon/encoding/payloads/encryption_payload.c')
-rw-r--r-- | src/charon/encoding/payloads/encryption_payload.c | 367 |
1 files changed, 164 insertions, 203 deletions
diff --git a/src/charon/encoding/payloads/encryption_payload.c b/src/charon/encoding/payloads/encryption_payload.c index caf34fbaa..d32e6c902 100644 --- a/src/charon/encoding/payloads/encryption_payload.c +++ b/src/charon/encoding/payloads/encryption_payload.c @@ -29,7 +29,6 @@ #include <daemon.h> #include <encoding/payloads/encodings.h> #include <utils/linked_list.h> -#include <utils/logger.h> #include <encoding/generator.h> #include <encoding/parser.h> #include <utils/iterator.h> @@ -37,8 +36,6 @@ #include <crypto/signers/signer.h> - - typedef struct private_encryption_payload_t private_encryption_payload_t; /** @@ -95,32 +92,6 @@ struct private_encryption_payload_t { * Contained payloads of this encrpytion_payload. */ linked_list_t *payloads; - - /** - * logger for this payload, uses MESSAGE context - */ - logger_t *logger; - - /** - * @brief Computes the length of this payload. - * - * @param this calling private_encryption_payload_t object - */ - void (*compute_length) (private_encryption_payload_t *this); - - /** - * @brief Generate payloads (unencrypted) in chunk decrypted. - * - * @param this calling private_encryption_payload_t object - */ - void (*generate) (private_encryption_payload_t *this); - - /** - * @brief Parse payloads from a (unencrypted) chunk. - * - * @param this calling private_encryption_payload_t object - */ - status_t (*parse) (private_encryption_payload_t *this); }; /** @@ -212,11 +183,45 @@ static void set_next_type(private_encryption_payload_t *this, payload_type_t typ } /** + * (re-)compute the lenght of the whole payload + */ +static void compute_length(private_encryption_payload_t *this) +{ + iterator_t *iterator; + size_t block_size, length = 0; + iterator = this->payloads->create_iterator(this->payloads, TRUE); + + /* count payload length */ + while (iterator->has_next(iterator)) + { + payload_t *current_payload; + iterator->current(iterator, (void **) ¤t_payload); + length += current_payload->get_length(current_payload); + } + iterator->destroy(iterator); + + if (this->crypter && this->signer) + { + /* append one byte for padding length */ + length++; + /* append padding */ + block_size = this->crypter->get_block_size(this->crypter); + length += block_size - length % block_size; + /* add iv */ + length += block_size; + /* add signature */ + length += this->signer->get_block_size(this->signer); + } + length += ENCRYPTION_PAYLOAD_HEADER_LENGTH; + this->payload_length = length; +} + +/** * Implementation of payload_t.get_length. */ static size_t get_length(private_encryption_payload_t *this) { - this->compute_length(this); + compute_length(this); return this->payload_length; } @@ -245,7 +250,7 @@ static void add_payload(private_encryption_payload_t *this, payload_t *payload) } payload->set_next_type(payload, NO_PAYLOAD); this->payloads->insert_last(this->payloads, (void*)payload); - this->compute_length(this); + compute_length(this); } /** @@ -264,6 +269,60 @@ static size_t get_payload_count(private_encryption_payload_t *this) return this->payloads->get_count(this->payloads); } +/** + * Generate payload before encryption. + */ +static void generate(private_encryption_payload_t *this) +{ + payload_t *current_payload, *next_payload; + generator_t *generator; + iterator_t *iterator; + + /* recalculate length before generating */ + compute_length(this); + + /* create iterator */ + iterator = this->payloads->create_iterator(this->payloads, TRUE); + + /* get first payload */ + if (iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)¤t_payload); + this->next_payload = current_payload->get_type(current_payload); + } + else + { + /* no paylads? */ + DBG2(SIG_DBG_ENC, "generating contained payloads, but none available"); + free(this->decrypted.ptr); + this->decrypted = CHUNK_INITIALIZER; + iterator->destroy(iterator); + return; + } + + generator = generator_create(); + + /* build all payload, except last */ + while(iterator->has_next(iterator)) + { + iterator->current(iterator, (void**)&next_payload); + current_payload->set_next_type(current_payload, next_payload->get_type(next_payload)); + generator->generate_payload(generator, current_payload); + current_payload = next_payload; + } + iterator->destroy(iterator); + + /* build last payload */ + current_payload->set_next_type(current_payload, NO_PAYLOAD); + generator->generate_payload(generator, current_payload); + + /* free already generated data */ + free(this->decrypted.ptr); + + generator->write_to_chunk(generator, &(this->decrypted)); + generator->destroy(generator); + DBG2(SIG_DBG_ENC, "successfully generated content in encryption payload"); +} /** * Implementation of encryption_payload_t.encrypt. @@ -277,19 +336,18 @@ static status_t encrypt(private_encryption_payload_t *this) if (this->signer == NULL || this->crypter == NULL) { - this->logger->log(this->logger, ERROR, "could not encrypt, signer/crypter not set"); + DBG1(SIG_DBG_ENC, "could not encrypt, signer/crypter not set"); return INVALID_STATE; } /* for random data in iv and padding */ randomizer = randomizer_create(); - - + /* build payload chunk */ - this->generate(this); + generate(this); - this->logger->log(this->logger, CONTROL|LEVEL2, "encrypting payloads"); - this->logger->log_chunk(this->logger, RAW|LEVEL2, "data to encrypt", this->decrypted); + DBG2(SIG_DBG_ENC, "encrypting payloads"); + DBG3(SIG_DBG_ENC, "data to encrypt %B", &this->decrypted); /* build padding */ block_size = this->crypter->get_block_size(this->crypter); @@ -320,8 +378,8 @@ static status_t encrypt(private_encryption_payload_t *this) return status; } - this->logger->log_chunk(this->logger, RAW|LEVEL2, "data before encryption with padding", to_crypt); - + DBG3(SIG_DBG_ENC, "data before encryption with padding %B", &to_crypt); + /* encrypt to_crypt chunk */ free(this->encrypted.ptr); status = this->crypter->encrypt(this->crypter, to_crypt, iv, &result); @@ -329,12 +387,11 @@ static status_t encrypt(private_encryption_payload_t *this) free(to_crypt.ptr); if (status != SUCCESS) { - this->logger->log(this->logger, ERROR|LEVEL1, "encryption failed"); + DBG2(SIG_DBG_ENC, "encryption failed"); free(iv.ptr); return status; } - this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after encryption", result); - + DBG3(SIG_DBG_ENC, "data after encryption %B", &result); /* build encrypted result with iv and signature */ this->encrypted.len = iv.len + result.len + this->signer->get_block_size(this->signer); @@ -347,12 +404,58 @@ static status_t encrypt(private_encryption_payload_t *this) free(result.ptr); free(iv.ptr); - this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after encryption with IV and (invalid) signature", this->encrypted); + DBG3(SIG_DBG_ENC, "data after encryption with IV and (invalid) signature %B", + &this->encrypted); return SUCCESS; } /** + * Parse the payloads after decryption. + */ +static status_t parse(private_encryption_payload_t *this) +{ + parser_t *parser; + status_t status; + payload_type_t current_payload_type; + + /* build a parser on the decrypted data */ + parser = parser_create(this->decrypted); + + current_payload_type = this->next_payload; + /* parse all payloads */ + while (current_payload_type != NO_PAYLOAD) + { + payload_t *current_payload; + + status = parser->parse_payload(parser, current_payload_type, (payload_t**)¤t_payload); + if (status != SUCCESS) + { + parser->destroy(parser); + return PARSE_ERROR; + } + + status = current_payload->verify(current_payload); + if (status != SUCCESS) + { + DBG1(SIG_DBG_ENC, "%N verification failed", + payload_type_names, current_payload->get_type(current_payload)); + current_payload->destroy(current_payload); + parser->destroy(parser); + return VERIFY_ERROR; + } + + /* get next payload type */ + current_payload_type = current_payload->get_next_type(current_payload); + + this->payloads->insert_last(this->payloads,current_payload); + } + parser->destroy(parser); + DBG2(SIG_DBG_ENC, "succesfully parsed content of encryption payload"); + return SUCCESS; +} + +/** * Implementation of encryption_payload_t.encrypt. */ static status_t decrypt(private_encryption_payload_t *this) @@ -361,14 +464,13 @@ static status_t decrypt(private_encryption_payload_t *this) u_int8_t padding_length; status_t status; - - this->logger->log(this->logger, CONTROL|LEVEL2, "decrypting encryption payload"); - this->logger->log_chunk(this->logger, RAW|LEVEL2, "data before decryption with IV and (invalid) signature", this->encrypted); - + DBG2(SIG_DBG_ENC, "decrypting encryption payload"); + DBG3(SIG_DBG_ENC, "data before decryption with IV and (invalid) signature %B", + &this->encrypted); if (this->signer == NULL || this->crypter == NULL) { - this->logger->log(this->logger, ERROR, "could not decrypt, no crypter/signer set"); + DBG1(SIG_DBG_ENC, "could not decrypt, no crypter/signer set"); return INVALID_STATE; } @@ -386,22 +488,22 @@ static status_t decrypt(private_encryption_payload_t *this) */ if (concatenated.len < iv.len) { - this->logger->log(this->logger, ERROR, "could not decrypt, invalid input"); + DBG1(SIG_DBG_ENC, "could not decrypt, invalid input"); return FAILED; } /* free previus data, if any */ free(this->decrypted.ptr); - this->logger->log_chunk(this->logger, RAW|LEVEL2, "data before decryption", concatenated); + DBG3(SIG_DBG_ENC, "data before decryption %B", &concatenated); status = this->crypter->decrypt(this->crypter, concatenated, iv, &(this->decrypted)); if (status != SUCCESS) { - this->logger->log(this->logger, ERROR, "could not decrypt, decryption failed"); + DBG1(SIG_DBG_ENC, "could not decrypt, decryption failed"); return FAILED; } - this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after decryption with padding", this->decrypted); + DBG3(SIG_DBG_ENC, "data after decryption with padding %B", &this->decrypted); /* get padding length, sits just bevore signature */ @@ -413,16 +515,16 @@ static status_t decrypt(private_encryption_payload_t *this) /* check size again */ if (padding_length > concatenated.len || this->decrypted.len < 0) { - this->logger->log(this->logger, ERROR, "decryption failed, invalid padding length found. Invalid key?"); + DBG1(SIG_DBG_ENC, "decryption failed, invalid padding length found. Invalid key?"); /* decryption failed :-/ */ return FAILED; } /* free padding */ this->decrypted.ptr = realloc(this->decrypted.ptr, this->decrypted.len); - this->logger->log_chunk(this->logger, RAW|LEVEL2, "data after decryption without padding", this->decrypted); - this->logger->log(this->logger, CONTROL|LEVEL2, "decryption successful, trying to parse content"); - return (this->parse(this)); + DBG3(SIG_DBG_ENC, "data after decryption without padding %B", &this->decrypted); + DBG2(SIG_DBG_ENC, "decryption successful, trying to parse content"); + return parse(this); } /** @@ -444,14 +546,14 @@ static status_t build_signature(private_encryption_payload_t *this, chunk_t data if (this->signer == NULL) { - this->logger->log(this->logger, ERROR, "unable to build signature, no signer set"); + DBG1(SIG_DBG_ENC, "unable to build signature, no signer set"); return INVALID_STATE; } sig.len = this->signer->get_block_size(this->signer); data_without_sig.len -= sig.len; sig.ptr = data.ptr + data_without_sig.len; - this->logger->log(this->logger, CONTROL|LEVEL2, "building signature"); + DBG2(SIG_DBG_ENC, "building signature"); this->signer->get_signature(this->signer, data_without_sig, sig.ptr); return SUCCESS; } @@ -466,14 +568,14 @@ static status_t verify_signature(private_encryption_payload_t *this, chunk_t dat if (this->signer == NULL) { - this->logger->log(this->logger, ERROR, "unable to verify signature, no signer set"); + DBG1(SIG_DBG_ENC, "unable to verify signature, no signer set"); return INVALID_STATE; } /* find signature in data chunk */ sig.len = this->signer->get_block_size(this->signer); if (data.len <= sig.len) { - this->logger->log(this->logger, ERROR|LEVEL1, "unable to verify signature, invalid input"); + DBG1(SIG_DBG_ENC, "unable to verify signature, invalid input"); return FAILED; } sig.ptr = data.ptr + data.len - sig.len; @@ -485,150 +587,15 @@ static status_t verify_signature(private_encryption_payload_t *this, chunk_t dat if (!valid) { - this->logger->log(this->logger, ERROR|LEVEL1, "signature verification failed"); + DBG1(SIG_DBG_ENC, "signature verification failed"); return FAILED; } - this->logger->log(this->logger, CONTROL|LEVEL2, "signature verification successful"); - return SUCCESS; -} - -/** - * Implementation of private_encryption_payload_t.generate. - */ -static void generate(private_encryption_payload_t *this) -{ - payload_t *current_payload, *next_payload; - generator_t *generator; - iterator_t *iterator; - - /* recalculate length before generating */ - this->compute_length(this); - - /* create iterator */ - iterator = this->payloads->create_iterator(this->payloads, TRUE); - - /* get first payload */ - if (iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)¤t_payload); - this->next_payload = current_payload->get_type(current_payload); - } - else - { - /* no paylads? */ - this->logger->log(this->logger, CONTROL|LEVEL1, "generating contained payloads, but no available"); - free(this->decrypted.ptr); - this->decrypted = CHUNK_INITIALIZER; - iterator->destroy(iterator); - return; - } - - generator = generator_create(); - - /* build all payload, except last */ - while(iterator->has_next(iterator)) - { - iterator->current(iterator, (void**)&next_payload); - current_payload->set_next_type(current_payload, next_payload->get_type(next_payload)); - generator->generate_payload(generator, current_payload); - current_payload = next_payload; - } - iterator->destroy(iterator); - - /* build last payload */ - current_payload->set_next_type(current_payload, NO_PAYLOAD); - generator->generate_payload(generator, current_payload); - - /* free already generated data */ - free(this->decrypted.ptr); - - generator->write_to_chunk(generator, &(this->decrypted)); - generator->destroy(generator); - this->logger->log(this->logger, CONTROL|LEVEL1, "successfully generated content in encrpytion payload"); -} - -/** - * Implementation of private_encryption_payload_t.parse. - */ -static status_t parse(private_encryption_payload_t *this) -{ - parser_t *parser; - status_t status; - payload_type_t current_payload_type; - - /* build a parser on the decrypted data */ - parser = parser_create(this->decrypted); - - current_payload_type = this->next_payload; - /* parse all payloads */ - while (current_payload_type != NO_PAYLOAD) - { - payload_t *current_payload; - - status = parser->parse_payload(parser, current_payload_type, (payload_t**)¤t_payload); - if (status != SUCCESS) - { - parser->destroy(parser); - return PARSE_ERROR; - } - - status = current_payload->verify(current_payload); - if (status != SUCCESS) - { - this->logger->log(this->logger, ERROR, "%s verification failed", - mapping_find(payload_type_m,current_payload->get_type(current_payload))); - current_payload->destroy(current_payload); - parser->destroy(parser); - return VERIFY_ERROR; - } - - /* get next payload type */ - current_payload_type = current_payload->get_next_type(current_payload); - - this->payloads->insert_last(this->payloads,current_payload); - } - parser->destroy(parser); - this->logger->log(this->logger, CONTROL|LEVEL1, "succesfully parsed content of encryption payload"); + DBG2(SIG_DBG_ENC, "signature verification successful"); return SUCCESS; } /** - * Implementation of private_encryption_payload_t.compute_length. - */ -static void compute_length(private_encryption_payload_t *this) -{ - iterator_t *iterator; - size_t block_size, length = 0; - iterator = this->payloads->create_iterator(this->payloads, TRUE); - - /* count payload length */ - while (iterator->has_next(iterator)) - { - payload_t *current_payload; - iterator->current(iterator, (void **) ¤t_payload); - length += current_payload->get_length(current_payload); - } - iterator->destroy(iterator); - - if (this->crypter && this->signer) - { - /* append one byte for padding length */ - length++; - /* append padding */ - block_size = this->crypter->get_block_size(this->crypter); - length += block_size - length % block_size; - /* add iv */ - length += block_size; - /* add signature */ - length += this->signer->get_block_size(this->signer); - } - length += ENCRYPTION_PAYLOAD_HEADER_LENGTH; - this->payload_length = length; -} - - -/** * Implementation of payload_t.destroy. */ static void destroy(private_encryption_payload_t *this) @@ -675,12 +642,6 @@ encryption_payload_t *encryption_payload_create() this->public.verify_signature = (status_t (*) (encryption_payload_t*, chunk_t)) verify_signature; this->public.destroy = (void (*) (encryption_payload_t *)) destroy; - /* private functions */ - this->compute_length = compute_length; - this->generate = generate; - this->parse = parse; - this->logger = logger_manager->get_logger(logger_manager, ENCRYPTION_PAYLOAD); - /* set default values of the fields */ this->critical = FALSE; this->next_payload = NO_PAYLOAD; |