aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2018-08-10 15:18:44 -0400
committerJack Lloyd <[email protected]>2018-08-10 15:18:44 -0400
commitf868b8d31e91a0ae4fbc065621c2136ba898b538 (patch)
tree8e60fdd96f1c3ed31e75b6bb22a38e0b434fac3e
parent36a7ec51b23b5d30e42480ef8a8a16468804065f (diff)
Add a function to query output length of symmetric cipher
-rw-r--r--src/lib/ffi/ffi.h2
-rw-r--r--src/lib/ffi/ffi_cipher.cpp8
-rw-r--r--src/lib/ffi/ffi_pk_op.cpp4
-rw-r--r--src/lib/ffi/ffi_util.h5
-rw-r--r--src/lib/modes/cipher_mode.h5
-rw-r--r--src/tests/test_ffi.cpp13
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));