aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2017-04-04 16:44:23 -0400
committerJack Lloyd <[email protected]>2017-04-04 16:44:23 -0400
commit542c6cb7338530b4a8f7d93f2410567815d993ef (patch)
tree76718dd137e433b6be08403cad6a6d72f7e6129b /src
parentf998cf9ae48ee5d4220fc6f5f54563e3c2cab6d1 (diff)
parent686371913aeb6ad823320dfc6caf3a8e7d24e01e (diff)
Merge GH #977 Add block cipher interface to C API
Diffstat (limited to 'src')
-rw-r--r--src/lib/ffi/ffi.cpp77
-rw-r--r--src/lib/ffi/ffi.h45
-rw-r--r--src/tests/test_ffi.cpp37
3 files changed, 159 insertions, 0 deletions
diff --git a/src/lib/ffi/ffi.cpp b/src/lib/ffi/ffi.cpp
index 945eacaf8..b4f0412d6 100644
--- a/src/lib/ffi/ffi.cpp
+++ b/src/lib/ffi/ffi.cpp
@@ -9,6 +9,7 @@
#include <botan/exceptn.h>
#include <botan/auto_rng.h>
#include <botan/aead.h>
+#include <botan/block_cipher.h>
#include <botan/hash.h>
#include <botan/mac.h>
#include <botan/pbkdf.h>
@@ -217,6 +218,7 @@ struct botan_cipher_struct : public botan_struct<Botan::Cipher_Mode, 0xB4A2BF9C>
BOTAN_FFI_DECLARE_STRUCT(botan_rng_struct, Botan::RandomNumberGenerator, 0x4901F9C1);
BOTAN_FFI_DECLARE_STRUCT(botan_mp_struct, Botan::BigInt, 0xC828B9D2);
+BOTAN_FFI_DECLARE_STRUCT(botan_block_cipher_struct, Botan::BlockCipher, 0x64C29716);
BOTAN_FFI_DECLARE_STRUCT(botan_hash_struct, Botan::HashFunction, 0x1F0A4F84);
BOTAN_FFI_DECLARE_STRUCT(botan_mac_struct, Botan::MessageAuthenticationCode, 0xA06E8FC1);
BOTAN_FFI_DECLARE_STRUCT(botan_pubkey_struct, Botan::Public_Key, 0x2C286519);
@@ -593,6 +595,81 @@ int botan_mp_num_bytes(const botan_mp_t mp, size_t* bytes)
return BOTAN_FFI_DO(Botan::BigInt, mp, n, { *bytes = n.bytes(); });
}
+int botan_block_cipher_init(botan_block_cipher_t* bc, const char* bc_name)
+ {
+ try
+ {
+ if(bc == nullptr || bc_name == nullptr || *bc_name == 0)
+ return BOTAN_FFI_ERROR_NULL_POINTER;
+
+ std::unique_ptr<Botan::BlockCipher> cipher(Botan::BlockCipher::create(bc_name));
+ if(cipher)
+ {
+ *bc = new botan_block_cipher_struct(cipher.release());
+ return 0;
+ }
+ }
+ catch(std::exception& e)
+ {
+ log_exception(BOTAN_CURRENT_FUNCTION, e.what());
+ }
+ catch(...)
+ {
+ log_exception(BOTAN_CURRENT_FUNCTION, "unknown");
+ }
+
+ return BOTAN_FFI_ERROR_EXCEPTION_THROWN;
+
+ }
+
+/**
+* Destroy a block cipher object
+*/
+int botan_block_cipher_destroy(botan_block_cipher_t bc)
+ {
+ delete bc;
+ return 0;
+ }
+
+int botan_block_cipher_clear(botan_block_cipher_t bc)
+ {
+ return BOTAN_FFI_DO(Botan::BlockCipher, bc, b, { b.clear(); });
+ }
+
+/**
+* Set the key for a block cipher instance
+*/
+int botan_block_cipher_set_key(botan_block_cipher_t bc,
+ const uint8_t key[], size_t len)
+ {
+ return BOTAN_FFI_DO(Botan::BlockCipher, bc, b, { b.set_key(key, len); });
+ }
+
+/**
+* Return the positive block size of this block cipher, or negative to
+* indicate an error
+*/
+int botan_block_cipher_block_size(botan_block_cipher_t bc)
+ {
+ return BOTAN_FFI_DO(Botan::BlockCipher, bc, b, { return b.block_size(); });
+ }
+
+int botan_block_cipher_encrypt_blocks(botan_block_cipher_t bc,
+ const uint8_t in[],
+ uint8_t out[],
+ size_t blocks)
+ {
+ return BOTAN_FFI_DO(Botan::BlockCipher, bc, b, { b.encrypt_n(in, out, blocks); });
+ }
+
+int botan_block_cipher_decrypt_blocks(botan_block_cipher_t bc,
+ const uint8_t in[],
+ uint8_t out[],
+ size_t blocks)
+ {
+ return BOTAN_FFI_DO(Botan::BlockCipher, bc, b, { b.decrypt_n(in, out, blocks); });
+ }
+
int botan_hash_init(botan_hash_t* hash, const char* hash_name, uint32_t flags)
{
try
diff --git a/src/lib/ffi/ffi.h b/src/lib/ffi/ffi.h
index 0901c4d4d..76cdaa145 100644
--- a/src/lib/ffi/ffi.h
+++ b/src/lib/ffi/ffi.h
@@ -456,6 +456,51 @@ BOTAN_DLL int botan_bcrypt_generate(uint8_t* out, size_t* out_len,
uint32_t flags);
/*
+* Raw Block Cipher (PRP) interface
+*/
+typedef struct botan_block_cipher_struct* botan_block_cipher_t;
+
+/**
+* Initialize a block cipher object
+*/
+BOTAN_DLL int botan_block_cipher_init(botan_block_cipher_t* bc,
+ const char* cipher_name);
+
+/**
+* Destroy a block cipher object
+*/
+BOTAN_DLL int botan_block_cipher_destroy(botan_block_cipher_t bc);
+
+/**
+* Reinitializes the block cipher
+* @return 0 on success, a negative value on failure
+*/
+BOTAN_DLL int botan_block_cipher_clear(botan_block_cipher_t bc);
+
+/**
+* Set the key for a block cipher instance
+*/
+BOTAN_DLL int botan_block_cipher_set_key(botan_block_cipher_t bc,
+ const uint8_t key[], size_t len);
+
+/**
+* Return the positive block size of this block cipher, or negative to
+* indicate an error
+*/
+BOTAN_DLL int botan_block_cipher_block_size(botan_block_cipher_t bc);
+
+BOTAN_DLL int botan_block_cipher_encrypt_blocks(botan_block_cipher_t bc,
+ const uint8_t in[],
+ uint8_t out[],
+ size_t blocks);
+
+BOTAN_DLL int botan_block_cipher_decrypt_blocks(botan_block_cipher_t bc,
+ const uint8_t in[],
+ uint8_t out[],
+ size_t blocks);
+
+
+/*
* Multiple precision integers
*/
typedef struct botan_mp_struct* botan_mp_t;
diff --git a/src/tests/test_ffi.cpp b/src/tests/test_ffi.cpp
index eee5fc39d..c84dfd224 100644
--- a/src/tests/test_ffi.cpp
+++ b/src/tests/test_ffi.cpp
@@ -387,6 +387,7 @@ class FFI_Unit_Tests : public Test
std::vector<Test::Result> results;
results.push_back(ffi_test_mp(rng));
+ results.push_back(ffi_test_block_ciphers());
#if defined(BOTAN_HAS_RSA)
results.push_back(ffi_test_rsa(rng));
@@ -415,6 +416,42 @@ class FFI_Unit_Tests : public Test
}
private:
+ Test::Result ffi_test_block_ciphers()
+ {
+ Test::Result result("FFI block ciphers");
+
+ botan_block_cipher_t cipher;
+
+ if(TEST_FFI_OK(botan_block_cipher_init, (&cipher, "AES-128")))
+ {
+ const std::vector<uint8_t> zero16(16, 0);
+ std::vector<uint8_t> block(16, 0);
+
+ TEST_FFI_OK(botan_block_cipher_clear, (cipher));
+
+ TEST_FFI_RC(16, botan_block_cipher_block_size, (cipher));
+
+ TEST_FFI_OK(botan_block_cipher_set_key, (cipher, zero16.data(), zero16.size()));
+
+ TEST_FFI_OK(botan_block_cipher_encrypt_blocks, (cipher, block.data(), block.data(), 1));
+ result.test_eq("AES-128 encryption works", block, "66E94BD4EF8A2C3B884CFA59CA342B2E");
+
+ TEST_FFI_OK(botan_block_cipher_encrypt_blocks, (cipher, block.data(), block.data(), 1));
+ result.test_eq("AES-128 encryption works", block, "F795BD4A52E29ED713D313FA20E98DBC");
+
+ TEST_FFI_OK(botan_block_cipher_decrypt_blocks, (cipher, block.data(), block.data(), 1));
+ result.test_eq("AES-128 decryption works", block, "66E94BD4EF8A2C3B884CFA59CA342B2E");
+
+ TEST_FFI_OK(botan_block_cipher_decrypt_blocks, (cipher, block.data(), block.data(), 1));
+ result.test_eq("AES-128 decryption works", block, "00000000000000000000000000000000");
+
+ TEST_FFI_OK(botan_block_cipher_clear, (cipher));
+ botan_block_cipher_destroy(cipher);
+ }
+
+ return result;
+ }
+
Test::Result ffi_test_mp(botan_rng_t rng)
{
Test::Result result("FFI MP");