aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/ffi/ffi.cpp22
-rw-r--r--src/lib/ffi/ffi.h47
-rw-r--r--src/ocaml/botan.ml161
-rw-r--r--src/ocaml/botan.mli35
-rwxr-xr-xsrc/ocaml/build.sh3
5 files changed, 268 insertions, 0 deletions
diff --git a/src/lib/ffi/ffi.cpp b/src/lib/ffi/ffi.cpp
index 2151c33a9..4fcdb63c1 100644
--- a/src/lib/ffi/ffi.cpp
+++ b/src/lib/ffi/ffi.cpp
@@ -15,6 +15,7 @@
#include <botan/version.h>
#include <botan/pubkey.h>
#include <botan/data_src.h>
+#include <botan/hex.h>
#include <botan/mem_ops.h>
#include <cstring>
#include <memory>
@@ -177,6 +178,27 @@ uint32_t botan_version_minor() { return Botan::version_minor(); }
uint32_t botan_version_patch() { return Botan::version_patch(); }
uint32_t botan_version_datestamp() { return Botan::version_datestamp(); }
+int botan_same_mem(const uint8_t* x, const uint8_t* y, size_t len)
+ {
+ return Botan::same_mem(x, y, len) ? 0 : 1;
+ }
+
+int botan_hex_encode(const uint8_t* in, size_t len, char* out, uint32_t flags)
+ {
+ try
+ {
+ const bool uppercase = (flags & BOTAN_FFI_HEX_LOWER_CASE) == 0;
+ Botan::hex_encode(out, in, len, uppercase);
+ return 0;
+ }
+ catch(std::exception& e)
+ {
+ log_exception(BOTAN_CURRENT_FUNCTION, e.what());
+ }
+
+ return 1;
+ }
+
int botan_rng_init(botan_rng_t* rng_out, const char* rng_type)
{
// Just gives unique_ptr something to delete, really
diff --git a/src/lib/ffi/ffi.h b/src/lib/ffi/ffi.h
index ca92977f4..a516529b4 100644
--- a/src/lib/ffi/ffi.h
+++ b/src/lib/ffi/ffi.h
@@ -50,12 +50,23 @@ BOTAN_DLL uint32_t botan_version_datestamp();
*/
BOTAN_DLL int botan_same_mem(const uint8_t* x, const uint8_t* y, size_t len);
+#define BOTAN_FFI_HEX_LOWER_CASE 1
+
+BOTAN_DLL int botan_hex_encode(const uint8_t* x, size_t len, char* out, uint32_t flags);
+
/*
* RNG
*/
typedef struct botan_rng_struct* botan_rng_t;
+/**
+* TODO: replace rng_type with simple flags?
+*/
BOTAN_DLL int botan_rng_init(botan_rng_t* rng, const char* rng_type);
+
+/**
+* TODO: better name
+*/
BOTAN_DLL int botan_rng_get(botan_rng_t rng, uint8_t* out, size_t out_len);
BOTAN_DLL int botan_rng_reseed(botan_rng_t rng, size_t bits);
BOTAN_DLL int botan_rng_destroy(botan_rng_t rng);
@@ -65,13 +76,49 @@ BOTAN_DLL int botan_rng_destroy(botan_rng_t rng);
*/
typedef struct botan_hash_struct* botan_hash_t;
+/**
+* Initialize a hash object:
+* botan_hash_t hash
+* botan_hash_init(&hash, "SHA-384", 0);
+*
+* Flags should be 0 in current API revision, all other uses are reserved.
+* and return BOTAN_FFI_ERROR_BAD_FLAG.
+
+* TODO: since output_length is effectively required to use this API,
+* return it from init as an output parameter
+*/
BOTAN_DLL int botan_hash_init(botan_hash_t* hash, const char* hash_name, uint32_t flags);
+
+/**
+* Writes the output length of the hash object to *output_length
+*/
BOTAN_DLL int botan_hash_output_length(botan_hash_t hash, size_t* output_length);
+
+/**
+* Send more input to the hash function.
+*/
BOTAN_DLL int botan_hash_update(botan_hash_t hash, const uint8_t* in, size_t in_len);
+
+/**
+* Finalizes the hash computation and writes the output to
+* out[0:botan_hash_output_length()] then reinitializes for computing
+* another digest as if botan_hash_clear had been called.
+*/
BOTAN_DLL int botan_hash_final(botan_hash_t hash, uint8_t out[]);
+
+/**
+* Reinitializes the state of the hash computation. A hash can
+* be computed (with update/final) immediately.
+*/
BOTAN_DLL int botan_hash_clear(botan_hash_t hash);
+
+/**
+* Frees all resources of this object
+*/
BOTAN_DLL int botan_hash_destroy(botan_hash_t hash);
+BOTAN_DLL int botan_hash_name(botan_hash_t hash, char* name, size_t name_len);
+
/*
* Message Authentication
*/
diff --git a/src/ocaml/botan.ml b/src/ocaml/botan.ml
new file mode 100644
index 000000000..8abdd04dc
--- /dev/null
+++ b/src/ocaml/botan.ml
@@ -0,0 +1,161 @@
+(*
+* OCaml binding for botan (http://botan.randombit.net)
+* (C) 2015 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*)
+
+open Ctypes
+open Foreign
+
+exception Botan_Error of int
+
+(* TODO: translate error code to string *)
+let result_or_exn rc res =
+ match rc with
+ | 0 -> res
+ | _ as ec -> raise (Botan_Error ec)
+
+
+module Botan = struct
+
+ let version =
+ let version_major =
+ foreign "botan_version_major" (void @-> returning int32_t) in
+ let version_minor =
+ foreign "botan_version_minor" (void @-> returning int32_t) in
+ let version_patch =
+ foreign "botan_version_patch" (void @-> returning int32_t) in
+ let major = Int32.to_int (version_major ()) in
+ let minor = Int32.to_int (version_minor ()) in
+ let patch = Int32.to_int (version_patch ()) in
+ (major, minor, patch)
+
+ let version_string =
+ let version_string =
+ foreign "botan_version_string" (void @-> returning string) in
+ version_string ()
+
+ let version_date =
+ let version_datestamp =
+ foreign "botan_version_datestamp" (void @-> returning int32_t) in
+ Int32.to_int (version_datestamp ())
+
+ let ffi_version =
+ let ffi_version =
+ foreign "botan_ffi_api_version" (void @-> returning int32_t) in
+ Int32.to_int (ffi_version ())
+
+ let hex_encode bin =
+ let hex_encode =
+ foreign "botan_hex_encode" (string @-> size_t @-> ptr char @-> uint32_t @-> returning int) in
+ let bin_len = String.length bin in
+ let hex_len = 2*bin_len in
+ let hex = allocate_n char hex_len in
+ let rc = hex_encode bin (Unsigned.Size_t.of_int bin_len) hex (Unsigned.UInt32.of_int 0) in
+ result_or_exn rc (string_from_ptr hex hex_len)
+
+ module Hash = struct
+ type t = unit ptr
+ let hash_t : t typ = ptr void
+
+ let create name =
+ let hash_init =
+ foreign "botan_hash_init" (ptr hash_t @-> string @-> uint32_t @-> returning int) in
+ let o = allocate_n ~count:1 hash_t in
+ let rc = hash_init o name (Unsigned.UInt32.of_int 0) in
+ result_or_exn rc (!@ o)
+
+ let destroy hash =
+ let hash_destroy =
+ foreign "botan_hash_destroy" (hash_t @-> returning int) in
+ let rc = hash_destroy hash in
+ result_or_exn rc ()
+
+ let output_length hash =
+ let hash_output_length =
+ foreign "botan_hash_output_length" (hash_t @-> ptr size_t @-> returning int) in
+ let ol = allocate_n ~count:1 size_t in
+ let rc = hash_output_length hash ol in
+ result_or_exn rc (Unsigned.Size_t.to_int (!@ ol))
+
+ let clear hash =
+ let hash_clear =
+ foreign "botan_hash_clear" (hash_t @-> returning int) in
+ let rc = hash_clear hash in
+ result_or_exn rc ()
+
+ let update hash input =
+ let hash_update =
+ foreign "botan_hash_update" (hash_t @-> string @-> size_t @-> returning int) in
+ let input_len = (String.length input) in
+ let rc = hash_update hash input (Unsigned.Size_t.of_int input_len) in
+ result_or_exn rc ()
+
+ let final hash =
+ let hash_final =
+ foreign "botan_hash_final" (hash_t @-> ptr char @-> returning int) in
+ let ol = output_length hash in
+ let res = allocate_n ~count:ol char in
+ let rc = hash_final hash res in
+ result_or_exn rc (string_from_ptr res ol)
+
+ end (* Hash *)
+
+ module RNG = struct
+ type t = unit ptr
+ let rng_t : t typ = ptr void
+
+ let create name =
+ let rng_init =
+ foreign "botan_rng_init" (ptr rng_t @-> string @-> uint32_t @-> returning int) in
+ let o = allocate_n ~count:1 rng_t in
+ let rc = rng_init o name (Unsigned.UInt32.of_int 0) in
+ result_or_exn rc (!@ o)
+
+ let destroy rng =
+ let rng_destroy =
+ foreign "botan_rng_destroy" (rng_t @-> returning int) in
+ let rc = rng_destroy rng in
+ result_or_exn rc ()
+
+ let generate rng out_len =
+ let rng_generate =
+ foreign "botan_rng_get" (rng_t @-> ptr char @-> size_t @-> returning int) in
+ let res = allocate_n ~count:out_len char in
+ let rc = rng_generate rng res (Unsigned.Size_t.of_int out_len) in
+ result_or_exn rc (string_from_ptr res out_len)
+
+ let reseed rng bits =
+ let rng_reseed =
+ foreign "botan_rng_reseed" (rng_t @-> size_t @-> returning int) in
+ let rc = rng_reseed rng (Unsigned.Size_t.of_int bits) in
+ result_or_exn rc ()
+
+ let update rng input =
+ let rng_update =
+ foreign "botan_rng_update" (rng_t @-> string @-> size_t @-> returning int) in
+ let input_len = (String.length input) in
+ let rc = rng_update rng input (Unsigned.Size_t.of_int input_len) in
+ result_or_exn rc ()
+
+ end (* RNG *)
+
+end (* Botan *)
+
+let () =
+ let rng = Botan.RNG.create "user" in
+ print_string (Botan.hex_encode (Botan.RNG.generate rng 11) ^ "\n")
+
+let () =
+ let (maj,min,patch) = Botan.version in
+ let ver_str = Botan.version_string in
+ print_string (Printf.sprintf "%d.%d.%d\n%s\n" maj min patch ver_str)
+
+let () =
+ let h = Botan.Hash.create "SHA-384" in
+ begin
+ Botan.Hash.update h "hi";
+ print_string (Botan.hex_encode (Botan.Hash.final h) ^ "\n");
+ Botan.Hash.destroy h
+ end
diff --git a/src/ocaml/botan.mli b/src/ocaml/botan.mli
new file mode 100644
index 000000000..ec7e71dfe
--- /dev/null
+++ b/src/ocaml/botan.mli
@@ -0,0 +1,35 @@
+(*
+* OCaml binding for botan (http://botan.randombit.net)
+* (C) 2015 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*)
+
+
+module Botan : sig
+ val version : (int * int * int)
+ val version_string : string
+ val version_date : int
+ val ffi_version : int
+
+ val hex_encode : string -> string
+
+ module RNG : sig
+ type t
+ val create : string -> t
+ val destroy: t -> unit (* TODO: GC finalize instead *)
+ val generate : t -> int -> string
+ val reseed : t -> int -> unit
+ end
+
+ module Hash : sig
+ type t
+ val create : string -> t
+ val destroy: t -> unit (* TODO: GC finalize instead *)
+ val output_length : t -> int
+ val clear : t -> unit
+ val update : t -> string -> unit
+ val final: t -> string
+ end
+
+end
diff --git a/src/ocaml/build.sh b/src/ocaml/build.sh
new file mode 100755
index 000000000..8b1c0825d
--- /dev/null
+++ b/src/ocaml/build.sh
@@ -0,0 +1,3 @@
+
+# extra ../ is needed due to ocamlbuild chdiring into _build
+ocamlbuild -pkg ctypes.foreign -lflags -cclib,-L../../.. -lflags -cclib,-lbotan-1.11 botan.native