diff options
author | Jack Lloyd <[email protected]> | 2018-08-10 15:18:44 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2018-08-10 15:18:44 -0400 |
commit | f868b8d31e91a0ae4fbc065621c2136ba898b538 (patch) | |
tree | 8e60fdd96f1c3ed31e75b6bb22a38e0b434fac3e | |
parent | 36a7ec51b23b5d30e42480ef8a8a16468804065f (diff) |
Add a function to query output length of symmetric cipher
-rw-r--r-- | src/lib/ffi/ffi.h | 2 | ||||
-rw-r--r-- | src/lib/ffi/ffi_cipher.cpp | 8 | ||||
-rw-r--r-- | src/lib/ffi/ffi_pk_op.cpp | 4 | ||||
-rw-r--r-- | src/lib/ffi/ffi_util.h | 5 | ||||
-rw-r--r-- | src/lib/modes/cipher_mode.h | 5 | ||||
-rw-r--r-- | src/tests/test_ffi.cpp | 13 |
6 files changed, 31 insertions, 6 deletions
diff --git a/src/lib/ffi/ffi.h b/src/lib/ffi/ffi.h index 19a65f946..89ac30e27 100644 --- a/src/lib/ffi/ffi.h +++ b/src/lib/ffi/ffi.h @@ -416,6 +416,8 @@ BOTAN_PUBLIC_API(2,0) int botan_cipher_init(botan_cipher_t* cipher, const char* BOTAN_PUBLIC_API(2,8) int botan_cipher_name(botan_cipher_t cipher, char* name, size_t* name_len); +BOTAN_PUBLIC_API(2,8) int botan_cipher_output_length(botan_cipher_t cipher, size_t in_len, size_t* out_len); + BOTAN_PUBLIC_API(2,0) int botan_cipher_valid_nonce_length(botan_cipher_t cipher, size_t nl); BOTAN_PUBLIC_API(2,0) int botan_cipher_get_tag_length(botan_cipher_t cipher, size_t* tag_size); BOTAN_PUBLIC_API(2,0) int botan_cipher_get_default_nonce_length(botan_cipher_t cipher, size_t* nl); diff --git a/src/lib/ffi/ffi_cipher.cpp b/src/lib/ffi/ffi_cipher.cpp index 094656fd2..8dee35a81 100644 --- a/src/lib/ffi/ffi_cipher.cpp +++ b/src/lib/ffi/ffi_cipher.cpp @@ -41,6 +41,14 @@ int botan_cipher_clear(botan_cipher_t cipher) return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { c.clear(); }); } +int botan_cipher_output_length(botan_cipher_t cipher, size_t in_len, size_t* out_len) + { + if(out_len == nullptr) + return BOTAN_FFI_ERROR_NULL_POINTER; + + return BOTAN_FFI_DO(Botan::Cipher_Mode, cipher, c, { *out_len = c.output_length(in_len); }); + } + int botan_cipher_query_keylen(botan_cipher_t cipher, size_t* out_minimum_keylength, size_t* out_maximum_keylength) diff --git a/src/lib/ffi/ffi_pk_op.cpp b/src/lib/ffi/ffi_pk_op.cpp index 0f18fca3e..5f2437a10 100644 --- a/src/lib/ffi/ffi_pk_op.cpp +++ b/src/lib/ffi/ffi_pk_op.cpp @@ -46,6 +46,8 @@ int botan_pk_op_encrypt_destroy(botan_pk_op_encrypt_t op) int botan_pk_op_encrypt_output_length(botan_pk_op_encrypt_t op, size_t ptext_len, size_t* ctext_len) { + if(ctext_len == nullptr) + return BOTAN_FFI_ERROR_NULL_POINTER; return BOTAN_FFI_DO(Botan::PK_Encryptor, op, o, { *ctext_len = o.ciphertext_length(ptext_len); }); } @@ -88,6 +90,8 @@ int botan_pk_op_decrypt_destroy(botan_pk_op_decrypt_t op) int botan_pk_op_decrypt_output_length(botan_pk_op_decrypt_t op, size_t ctext_len, size_t* ptext_len) { + if(ptext_len == nullptr) + return BOTAN_FFI_ERROR_NULL_POINTER; return BOTAN_FFI_DO(Botan::PK_Decryptor, op, o, { *ptext_len = o.plaintext_length(ctext_len); }); } diff --git a/src/lib/ffi/ffi_util.h b/src/lib/ffi/ffi_util.h index afd359dbb..2aa0edd83 100644 --- a/src/lib/ffi/ffi_util.h +++ b/src/lib/ffi/ffi_util.h @@ -136,10 +136,13 @@ int ffi_delete_object(botan_struct<T, M>* obj, const char* func_name) inline int write_output(uint8_t out[], size_t* out_len, const uint8_t buf[], size_t buf_len) { + if(out_len == nullptr) + return BOTAN_FFI_ERROR_NULL_POINTER; + const size_t avail = *out_len; *out_len = buf_len; - if(avail >= buf_len) + if((avail >= buf_len) && (out != nullptr)) { Botan::copy_mem(out, buf, buf_len); return BOTAN_FFI_SUCCESS; diff --git a/src/lib/modes/cipher_mode.h b/src/lib/modes/cipher_mode.h index eb5ce8a7c..9bf0b6811 100644 --- a/src/lib/modes/cipher_mode.h +++ b/src/lib/modes/cipher_mode.h @@ -130,8 +130,9 @@ class BOTAN_PUBLIC_API(2,0) Cipher_Mode : public SymmetricAlgorithm /** * Returns the size of the output if this transform is used to process a - * message with input_length bytes. Will throw if unable to give a precise - * answer. + * message with input_length bytes. In most cases the answer is precise. + * If it is not possible to precise (namely for CBC decryption) instead a + * lower bound is returned. */ virtual size_t output_length(size_t input_length) const = 0; diff --git a/src/tests/test_ffi.cpp b/src/tests/test_ffi.cpp index 76f8635f1..9739d725c 100644 --- a/src/tests/test_ffi.cpp +++ b/src/tests/test_ffi.cpp @@ -372,14 +372,17 @@ class FFI_Unit_Tests final : public Test const std::vector<uint8_t> exp_ciphertext = Botan::hex_decode("e232cd6ef50047801ee681ec30f61d53cfd6b0bca02fd03c1b234baa10ea82ac9dab8b960926433a19ce6dea08677e34"); - std::vector<uint8_t> ciphertext(16 + plaintext.size()); // TODO: no way to know this size from API - size_t output_written = 0; size_t input_consumed = 0; // Test that after clear or final the object can be reused for(size_t r = 0; r != 2; ++r) { + size_t ctext_len; + TEST_FFI_OK(botan_cipher_output_length, (cipher_encrypt, plaintext.size(), &ctext_len)); + result.test_eq("Expected size of padded message", ctext_len, plaintext.size() + 15); + std::vector<uint8_t> ciphertext(ctext_len); + TEST_FFI_OK(botan_cipher_set_key, (cipher_encrypt, symkey.data(), symkey.size())); TEST_FFI_OK(botan_cipher_start, (cipher_encrypt, nonce.data(), nonce.size())); TEST_FFI_OK(botan_cipher_update, (cipher_encrypt, 0, ciphertext.data(), ciphertext.size(), &output_written, @@ -397,7 +400,9 @@ class FFI_Unit_Tests final : public Test if(TEST_FFI_OK(botan_cipher_init, (&cipher_decrypt, "AES-128/CBC", BOTAN_CIPHER_INIT_FLAG_DECRYPT))) { - std::vector<uint8_t> decrypted(plaintext.size()); + size_t ptext_len; + TEST_FFI_OK(botan_cipher_output_length, (cipher_decrypt, ciphertext.size(), &ptext_len)); + std::vector<uint8_t> decrypted(ptext_len); TEST_FFI_OK(botan_cipher_set_key, (cipher_decrypt, symkey.data(), symkey.size())); TEST_FFI_OK(botan_cipher_start, (cipher_decrypt, nonce.data(), nonce.size())); @@ -405,6 +410,8 @@ class FFI_Unit_Tests final : public Test decrypted.data(), decrypted.size(), &output_written, ciphertext.data(), ciphertext.size(), &input_consumed)); + decrypted.resize(output_written); + result.test_eq("AES/CBC plaintext", decrypted, plaintext); TEST_FFI_OK(botan_cipher_destroy, (cipher_decrypt)); |