diff options
Diffstat (limited to 'src/libstrongswan/plugins/botan/botan_crypter.c')
-rw-r--r-- | src/libstrongswan/plugins/botan/botan_crypter.c | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/src/libstrongswan/plugins/botan/botan_crypter.c b/src/libstrongswan/plugins/botan/botan_crypter.c new file mode 100644 index 000000000..002be6ea8 --- /dev/null +++ b/src/libstrongswan/plugins/botan/botan_crypter.c @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2018 René Korthaus + * Copyright (C) 2018 Konstantinos Kolelis + * Copyright (C) 2018 Tobias Hommel + * Rohde & Schwarz Cybersecurity GmbH + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "botan_crypter.h" + +#include <botan/ffi.h> + +typedef struct private_botan_crypter_t private_botan_crypter_t; + +/** + * Private data of botan_crypter_t + */ +struct private_botan_crypter_t { + + /** + * Public part of this class + */ + botan_crypter_t public; + + /** + * The key + */ + chunk_t key; + + /** + * The cipher name + */ + const char* cipher_name; +}; + +/** + * Do the actual en/decryption + */ +static bool crypt(private_botan_crypter_t *this, chunk_t data, chunk_t iv, + chunk_t *dst, uint32_t init_flag) +{ + botan_cipher_t cipher; + size_t output_written = 0; + size_t input_consumed = 0; + uint8_t *in, *out; + bool success = FALSE; + + in = data.ptr; + if (dst) + { + *dst = chunk_alloc(data.len); + out = dst->ptr; + } + else + { + out = data.ptr; + } + + if (botan_cipher_init(&cipher, this->cipher_name, init_flag)) + { + return FALSE; + } + + if (!botan_cipher_set_key(cipher, this->key.ptr, this->key.len) && + !botan_cipher_start(cipher, iv.ptr, iv.len) && + !botan_cipher_update(cipher, BOTAN_CIPHER_UPDATE_FLAG_FINAL, out, + data.len, &output_written, in, data.len, + &input_consumed) && + (output_written == input_consumed)) + { + success = TRUE; + } + + botan_cipher_destroy(cipher); + return success; +} + +METHOD(crypter_t, decrypt, bool, + private_botan_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst) +{ + return crypt(this, data, iv, dst, BOTAN_CIPHER_INIT_FLAG_DECRYPT); +} + + +METHOD(crypter_t, encrypt, bool, + private_botan_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst) +{ + return crypt(this, data, iv, dst, BOTAN_CIPHER_INIT_FLAG_ENCRYPT); +} + +METHOD(crypter_t, get_block_size, size_t, + private_botan_crypter_t *this) +{ + return AES_BLOCK_SIZE; +} + +METHOD(crypter_t, get_iv_size, size_t, + private_botan_crypter_t *this) +{ + return AES_BLOCK_SIZE; +} + +METHOD(crypter_t, get_key_size, size_t, + private_botan_crypter_t *this) +{ + return this->key.len; +} + +METHOD(crypter_t, set_key, bool, + private_botan_crypter_t *this, chunk_t key) +{ + memcpy(this->key.ptr, key.ptr, min(key.len, this->key.len)); + return TRUE; +} + +METHOD(crypter_t, destroy, void, + private_botan_crypter_t *this) +{ + chunk_clear(&this->key); + free(this); +} + +/* + * Described in header + */ +botan_crypter_t *botan_crypter_create(encryption_algorithm_t algo, + size_t key_size) +{ + private_botan_crypter_t *this; + + INIT(this, + .public = { + .crypter = { + .encrypt = _encrypt, + .decrypt = _decrypt, + .get_block_size = _get_block_size, + .get_iv_size = _get_iv_size, + .get_key_size = _get_key_size, + .set_key = _set_key, + .destroy = _destroy, + }, + }, + ); + + switch (algo) + { + case ENCR_AES_CBC: + switch (key_size) + { + case 16: + /* AES 128 */ + this->cipher_name = "AES-128/CBC/NoPadding"; + break; + case 24: + /* AES-192 */ + this->cipher_name = "AES-192/CBC/NoPadding"; + break; + case 32: + /* AES-256 */ + this->cipher_name = "AES-256/CBC/NoPadding"; + break; + default: + free(this); + return NULL; + } + break; + default: + free(this); + return NULL; + } + + this->key = chunk_alloc(key_size); + return &this->public; +} |