diff options
-rw-r--r-- | src/lib/ffi/ffi.cpp | 32 | ||||
-rw-r--r-- | src/lib/ffi/ffi.h | 23 | ||||
-rw-r--r-- | src/tests/test_ffi.cpp | 30 |
3 files changed, 82 insertions, 3 deletions
diff --git a/src/lib/ffi/ffi.cpp b/src/lib/ffi/ffi.cpp index 28eac401a..1cd8e4b90 100644 --- a/src/lib/ffi/ffi.cpp +++ b/src/lib/ffi/ffi.cpp @@ -9,6 +9,7 @@ #include <botan/version.h> #include <botan/mem_ops.h> #include <botan/hex.h> +#include <botan/base64.h> #include <cstdio> namespace Botan_FFI { @@ -74,5 +75,36 @@ int botan_hex_encode(const uint8_t* in, size_t len, char* out, uint32_t flags) }); } +int botan_hex_decode(const char* hex_str, size_t in_len, uint8_t* out, size_t* out_len) + { + return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() { + const std::vector<uint8_t> bin = Botan::hex_decode(hex_str, in_len); + return Botan_FFI::write_vec_output(out, out_len, bin); + }); + } + +int botan_base64_encode(const uint8_t* in, size_t len, char* out, size_t* out_len) + { + return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() { + const std::string base64 = Botan::base64_encode(in, len); + return Botan_FFI::write_str_output(out, out_len, base64); + }); + } + +int botan_base64_decode(const char* base64_str, size_t in_len, + uint8_t* out, size_t* out_len) + { + return ffi_guard_thunk(BOTAN_CURRENT_FUNCTION, [=]() { + if(*out_len < Botan::base64_decode_max_output(in_len)) + { + *out_len = Botan::base64_decode_max_output(in_len); + return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE; + } + + *out_len = Botan::base64_decode(out, std::string(base64_str, in_len)); + return BOTAN_FFI_SUCCESS; + }); + } + } diff --git a/src/lib/ffi/ffi.h b/src/lib/ffi/ffi.h index 37f38ae1b..6ee286ad3 100644 --- a/src/lib/ffi/ffi.h +++ b/src/lib/ffi/ffi.h @@ -173,9 +173,26 @@ BOTAN_DLL int botan_scrub_mem(uint8_t* mem, size_t bytes); */ BOTAN_DLL int botan_hex_encode(const uint8_t* x, size_t len, char* out, uint32_t flags); -// TODO: botan_hex_decode -// TODO: botan_base64_encode -// TODO: botan_base64_decode +/** +* Perform hex decoding +* @param hex_str a string of hex chars (whitespace is ignored) +* @param in_len the length of hex_str +* @param out the output buffer should be at least strlen(hex_str)/2 bytes +* @param out_len the size of out +*/ +BOTAN_DLL int botan_hex_decode(const char* hex_str, size_t in_len, uint8_t* out, size_t* out_len); + +/** +* Perform base64 encoding +*/ +BOTAN_DLL int botan_base64_encode(const uint8_t* x, size_t len, char* out, size_t* out_len); + + +/** +* Perform base64 decoding +*/ +BOTAN_DLL int botan_base64_decode(const char* base64_str, size_t in_len, + uint8_t* out, size_t* out_len); /** * RNG type diff --git a/src/tests/test_ffi.cpp b/src/tests/test_ffi.cpp index 3b825ad4e..34d832026 100644 --- a/src/tests/test_ffi.cpp +++ b/src/tests/test_ffi.cpp @@ -361,6 +361,7 @@ class FFI_Unit_Tests : public Test std::vector<Test::Result> results; results.push_back(ffi_test_errors()); + results.push_back(ffi_test_base64()); results.push_back(ffi_test_mp(rng)); results.push_back(ffi_test_block_ciphers()); results.push_back(ffi_test_ciphers_cbc()); @@ -697,6 +698,35 @@ class FFI_Unit_Tests : public Test return result; } + Test::Result ffi_test_base64() + { + Test::Result result("FFI base64"); + + const uint8_t bin[9] = { 0x16, 0x8a, 0x1f, 0x06, 0xe9, 0xe7, 0xcb, 0xdd, 0x34 }; + char out_buf[1024] = { 0 }; + + size_t out_len = sizeof(out_buf); + TEST_FFI_OK(botan_base64_encode, (bin, sizeof(bin), out_buf, &out_len)); + + result.test_eq("encoded string", out_buf, "FoofBunny900"); + + out_len -= 1; + TEST_FFI_RC(BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE, + botan_base64_encode, + (bin, sizeof(bin), out_buf, &out_len)); + + const char* base64 = "U3VjaCBiYXNlNjQgd293IQ=="; + uint8_t out_bin[1024] = { 0 }; + out_len = sizeof(out_bin); + TEST_FFI_OK(botan_base64_decode, (base64, strlen(base64), out_bin, &out_len)); + + result.test_eq("decoded string", + std::string(reinterpret_cast<const char*>(out_bin), out_len), + "Such base64 wow!"); + + return result; + } + Test::Result ffi_test_mp(botan_rng_t rng) { Test::Result result("FFI MP"); |