Interface BotanLibrary
This interface provides direct access to Botan's C FFI (Foreign Function Interface) through JNR-FFI. It defines Java method signatures that map to native Botan functions, handling type conversions and memory management for cross-language calls.
Purpose and Architecture
BotanLibrary serves as the low-level binding layer between Java and native Botan code:
- Interface, not Implementation: This is a JNR-FFI interface - JNR automatically generates the implementation by binding to the native library at runtime
- Direct Native Access: All methods directly correspond to Botan C FFI functions
- Memory Safety: Uses JNR-FFI annotations (@In, @Out) to manage native memory safely
- Singleton Access: Instances are created and managed by
BotanInstance
Function Categories
The library provides bindings for the following Botan operations:
Utility Functions
botan_version_string()- Get Botan library versionbotan_ffi_supports_api(long)- Check FFI API version supportbotan_error_description(int)- Convert error codes to descriptions
Encoding Functions
botan_hex_encode(byte[], long, byte[], long)- Binary to hexadecimalbotan_hex_decode(byte[], long, byte[], NativeLongByReference)- Hexadecimal to binarybotan_base64_encode(byte[], long, byte[], NativeLongByReference)- Binary to Base64botan_base64_decode(String, long, byte[], NativeLongByReference)- Base64 to binary
Hash Functions (Message Digests)
botan_hash_init(PointerByReference, String, long)- Initialize hash objectbotan_hash_update(Pointer, byte[], long)- Add data to hashbotan_hash_final(Pointer, byte[])- Finalize and get digestbotan_hash_copy_state(PointerByReference, Pointer)- Clone hash statebotan_hash_clear(Pointer)- Reset hash statebotan_hash_destroy(Pointer)- Free hash object
Message Authentication Codes (MACs)
botan_mac_init(PointerByReference, String, long)- Initialize MAC objectbotan_mac_set_key(Pointer, byte[], long)- Set MAC keybotan_mac_update(Pointer, byte[], long)- Add data to MACbotan_mac_final(Pointer, byte[])- Finalize and get MAC tagbotan_mac_clear(Pointer)- Reset MAC statebotan_mac_destroy(Pointer)- Free MAC object
Symmetric Ciphers
botan_cipher_init(PointerByReference, String, long)- Initialize cipher objectbotan_cipher_set_key(Pointer, byte[], long)- Set cipher keybotan_cipher_start(Pointer, byte[], long)- Start cipher with IV/noncebotan_cipher_update(Pointer, long, byte[], long, NativeLongByReference, byte[], long, NativeLongByReference)- Process data (encrypt/decrypt)botan_cipher_reset(Pointer)- Reset cipher statebotan_cipher_destroy(Pointer)- Free cipher object
Error Handling
All native functions return an integer error code:
- 0 indicates success
- Negative values indicate errors (e.g., -1 for invalid input, -20 for bad MAC)
- Use
botan_error_description(int)to convert error codes to human-readable messages BotanInstance.checkNativeCall(int, String)provides centralized error checking
Memory Management
Proper resource cleanup is critical when working with native objects:
- Initialization functions (e.g., botan_hash_init) allocate native memory
- Destroy functions (e.g., botan_hash_destroy) must be called to free memory
- Java wrappers use Cleaner API to ensure automatic cleanup on garbage collection
- PointerByReference is used for output parameters that receive native object handles
Usage Pattern
Direct usage of this interface is not recommended. Instead, use the high-level JCA wrapper classes:
// DON'T use BotanLibrary directly:
BotanLibrary lib = BotanInstance.singleton();
PointerByReference hashRef = new PointerByReference();
lib.botan_hash_init(hashRef, "SHA-256", 0);
// ... manual memory management required ...
lib.botan_hash_destroy(hashRef.getValue());
// DO use JCA wrappers instead:
MessageDigest sha256 = MessageDigest.getInstance("SHA-256", "Botan");
byte[] hash = sha256.digest(data);
// Automatic resource management via Cleaner
JNR-FFI Annotations
This interface uses JNR-FFI annotations to control parameter marshalling:
- @In - Input parameter (Java to native)
- @Out - Output parameter (native to Java)
- PointerByReference - Reference to a native pointer (for object handles)
- NativeLongByReference - Reference to a native long (for output sizes)
- Pointer - Opaque native pointer (for object handles)
Thread Safety
The native Botan library functions are NOT thread-safe for individual objects:
- Each native object (hash, MAC, cipher) must be accessed by only one thread
- Different threads can use different native objects concurrently
- Java wrapper classes inherit this thread-safety model
Native Library Requirements
This interface requires the Botan 3.x native library:
- Library name: "botan-3"
- Minimum version: Botan 3.0.0
- FFI API: Uses Botan's C FFI (stable ABI)
- Platform support: Linux, macOS, Windows
Implementation Notes
- Auto-generated Implementation: JNR-FFI generates the implementation at runtime by analyzing this interface and creating native bindings
- No Manual JNI: No need for hand-written JNI code - JNR handles everything
- Type Mapping: JNR automatically maps Java types to C types (int→int, byte[]→uint8_t*, etc.)
- Performance: Near-native performance due to efficient JNR code generation
- Since:
- 0.1.0
- Author:
- Yasser Aziza
- See Also:
-
BotanInstanceLibraryLoader
-
Method Summary
Modifier and TypeMethodDescriptionintbotan_base64_decode(String input, long inputLength, byte[] output, jnr.ffi.byref.NativeLongByReference outputLength) Performs base64 decoding.intbotan_base64_encode(byte[] input, long inputLength, byte[] output, jnr.ffi.byref.NativeLongByReference outputLength) Performs base64 encoding.intbotan_cipher_clear(jnr.ffi.Pointer cipher) Resets the key, nonce, AD and all other state on this cipher object.intbotan_cipher_destroy(jnr.ffi.Pointer cipher) Destroys the cipher object.intbotan_cipher_get_default_nonce_length(jnr.ffi.Pointer cipher, jnr.ffi.byref.NativeLongByReference nonceLength) Gets the default nonce length of this cipher.intbotan_cipher_get_keyspec(jnr.ffi.Pointer cipher, jnr.ffi.byref.NativeLongByReference minKeylen, jnr.ffi.byref.NativeLongByReference maxKeylen, jnr.ffi.byref.NativeLongByReference modKeylen) Gets information about the supported key lengths.intbotan_cipher_get_tag_length(jnr.ffi.Pointer cipher, jnr.ffi.byref.NativeLongByReference tagLength) Gets the tag length of the cipher (0 for non-AEAD modes).intbotan_cipher_get_update_granularity(jnr.ffi.Pointer cipher, jnr.ffi.byref.NativeLongByReference updateGranularity) Returns the update granularity of the cipher; botan_cipher_update must be called with blocks of this size, except for the final.intbotan_cipher_init(jnr.ffi.byref.PointerByReference cipher, String name, long flags) Initializes a cipher object.intbotan_cipher_output_length(jnr.ffi.Pointer cipher, long inputLength, jnr.ffi.byref.NativeLongByReference outputLength) Returns the output length of this cipher, for a particular input length.intbotan_cipher_reset(jnr.ffi.Pointer cipher) Resets the message specific state for this cipher.intbotan_cipher_set_associated_data(jnr.ffi.Pointer cipher, byte[] ad, long adLen) Sets the associated data.intbotan_cipher_set_key(jnr.ffi.Pointer cipher, byte[] key, long keyLength) Sets the key for this cipher object.intbotan_cipher_start(jnr.ffi.Pointer cipher, byte[] nonce, long nonceLength) Begin processing a new message using the provided nonce.intbotan_cipher_update(jnr.ffi.Pointer cipher, long flags, byte[] output, long outputSize, jnr.ffi.byref.NativeLongByReference outputWritten, byte[] input, long inputSize, jnr.ffi.byref.NativeLongByReference inputConsumed) Encrypts some data.intbotan_cipher_valid_nonce_length(jnr.ffi.Pointer cipher, long nonceLength) Returns if the specified nonce length is valid for this cipher.botan_error_description(int err) Converts an error code into a string.intbotan_ffi_supports_api(long apiVersion) Returns the version of the currently supported FFI API.intbotan_hash_block_size(jnr.ffi.Pointer hash, jnr.ffi.byref.NativeLongByReference size) Writes the block size of the hash function to the given reference.intbotan_hash_clear(jnr.ffi.Pointer hash) Reinitializes the state of the hash computation.intbotan_hash_copy_state(jnr.ffi.byref.PointerByReference dest, jnr.ffi.Pointer source) Copy the state of a hash function object.intbotan_hash_destroy(jnr.ffi.Pointer hash) Frees all resources of the hash object.intbotan_hash_final(jnr.ffi.Pointer hash, byte[] out) 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.intbotan_hash_init(jnr.ffi.byref.PointerByReference hash, String hashName, long flags) Initializes a hash function object.intbotan_hash_output_length(jnr.ffi.Pointer hash, jnr.ffi.byref.NativeLongByReference length) Writes the output length of the hash function to the given reference.intbotan_hash_update(jnr.ffi.Pointer hash, byte[] input, long length) Sends more input to the hash function.intbotan_hex_decode(byte[] input, long inputLength, byte[] output, jnr.ffi.byref.NativeLongByReference outputLength) Performs hex decoding.intbotan_hex_encode(byte[] input, long inputLength, byte[] output, long flags) Performs hex encoding.intbotan_mac_clear(jnr.ffi.Pointer mac) Reinitializes the state of the MAC computation.intbotan_mac_destroy(jnr.ffi.Pointer mac) Frees all resources of the MAC object.intbotan_mac_final(jnr.ffi.Pointer mac, byte[] out) Finalizes the MAC computation and writes the output to out[0:botan_mac_output_length()] then reinitializes for computing another MAC as if botan_mac_clear had been called.intbotan_mac_get_keyspec(jnr.ffi.Pointer mac, jnr.ffi.byref.NativeLongByReference minimumKeyLength, jnr.ffi.byref.NativeLongByReference maximumKeyLength, jnr.ffi.byref.NativeLongByReference keyLengthModulo) Gets the key length limits of this auth codeintbotan_mac_init(jnr.ffi.byref.PointerByReference mac, String name, long flags) Initializes a message authentication code object.intbotan_mac_output_length(jnr.ffi.Pointer mac, jnr.ffi.byref.NativeLongByReference length) Writes the output length of the message authentication code to the given reference.intbotan_mac_set_key(jnr.ffi.Pointer mac, byte[] key, long length) Sets the key on the MAC.intbotan_mac_update(jnr.ffi.Pointer mac, byte[] buffer, long length) Sends more input to the message authentication code.Returns a free-form version string, e.g., 2.0.0
-
Method Details
-
botan_error_description
Converts an error code into a string. Returns "Unknown error" if the error code is not a known one.- Parameters:
err- error code- Returns:
Stringdescription
-
botan_ffi_supports_api
int botan_ffi_supports_api(long apiVersion) Returns the version of the currently supported FFI API. This is expressed in the form YYYYMMDD of the release date of this version of the API.- Parameters:
apiVersion- supported API version- Returns:
- 0 if the given API version is supported
-
botan_version_string
String botan_version_string()Returns a free-form version string, e.g., 2.0.0- Returns:
Stringversion
-
botan_hex_encode
int botan_hex_encode(byte[] input, long inputLength, byte[] output, long flags) Performs hex encoding.- Parameters:
input- is some binary datainputLength- length of x in bytesoutput- an array of at least x*2 bytesflags- output be upper or lower case?- Returns:
- 0 on success, a negative value on failure
-
botan_hex_decode
int botan_hex_decode(byte[] input, long inputLength, byte[] output, jnr.ffi.byref.NativeLongByReference outputLength) Performs hex decoding.- Parameters:
input- a string of hex chars (whitespace is ignored)inputLength- the length of the inputoutput- the output buffer should be at least strlen(input)/2 bytesoutputLength- the size of the output- Returns:
- 0 on success, a negative value on failure
-
botan_base64_encode
int botan_base64_encode(byte[] input, long inputLength, byte[] output, jnr.ffi.byref.NativeLongByReference outputLength) Performs base64 encoding.- Parameters:
input- the input bufferinputLength- the length of the inputoutput- the output bufferoutputLength- the size of the output- Returns:
- 0 on success, a negative value on failure
-
botan_base64_decode
int botan_base64_decode(String input, long inputLength, byte[] output, jnr.ffi.byref.NativeLongByReference outputLength) Performs base64 decoding.- Parameters:
input- the input bufferinputLength- the length of the inputoutput- the output bufferoutputLength- the size of the output- Returns:
- 0 on success, a negative value on failure
-
botan_hash_init
Initializes a hash function object.- Parameters:
hash- hash objecthashName- name of the hash function, e.g., "SHA-384"flags- should be 0 in current API revision, all other uses are reserved and return BOTAN_FFI_ERROR_BAD_FLAG- Returns:
- 0 on success, a negative value on failure
-
botan_hash_copy_state
int botan_hash_copy_state(jnr.ffi.byref.PointerByReference dest, jnr.ffi.Pointer source) Copy the state of a hash function object.- Parameters:
dest- destination hash objectsource- source hash object- Returns:
- 0 on success, a negative value on failure
-
botan_hash_output_length
int botan_hash_output_length(jnr.ffi.Pointer hash, jnr.ffi.byref.NativeLongByReference length) Writes the output length of the hash function to the given reference.- Parameters:
hash- hash objectlength- output buffer to hold the hash function output length- Returns:
- 0 on success, a negative value on failure
-
botan_hash_block_size
int botan_hash_block_size(jnr.ffi.Pointer hash, jnr.ffi.byref.NativeLongByReference size) Writes the block size of the hash function to the given reference.- Parameters:
hash- hash objectsize- output buffer to hold the hash function output length- Returns:
- 0 on success, a negative value on failure
-
botan_hash_update
int botan_hash_update(jnr.ffi.Pointer hash, byte[] input, long length) Sends more input to the hash function.- Parameters:
hash- hash objectinput- input bufferlength- number of bytes to read from the input buffer- Returns:
- 0 on success, a negative value on failure
-
botan_hash_final
int botan_hash_final(jnr.ffi.Pointer hash, byte[] out) 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.- Parameters:
hash- hash objectout- output buffer- Returns:
- 0 on success, a negative value on failure
-
botan_hash_clear
int botan_hash_clear(jnr.ffi.Pointer hash) Reinitializes the state of the hash computation. A hash can be computed (with update/final) immediately.- Parameters:
hash- hash object- Returns:
- 0 on success, a negative value on failure
-
botan_hash_destroy
int botan_hash_destroy(jnr.ffi.Pointer hash) Frees all resources of the hash object.- Parameters:
hash- hash object- Returns:
- 0 if success, error if invalid object handle
-
botan_mac_init
Initializes a message authentication code object.- Parameters:
mac- MAC objectname- name of the hash function, e.g., "HMAC(SHA-384)"flags- should be 0 in current API revision, all other uses are reserved and return a negative value (error code)- Returns:
- 0 on success, a negative value on failure
-
botan_mac_output_length
int botan_mac_output_length(jnr.ffi.Pointer mac, jnr.ffi.byref.NativeLongByReference length) Writes the output length of the message authentication code to the given reference.- Parameters:
mac- MAC objectlength- output buffer to hold the MAC output length- Returns:
- 0 on success, a negative value on failure
-
botan_mac_set_key
int botan_mac_set_key(jnr.ffi.Pointer mac, byte[] key, long length) Sets the key on the MAC.- Parameters:
mac- MAC objectkey- buffer holding the keylength- size of the key buffer in bytes- Returns:
- 0 on success, a negative value on failure
-
botan_mac_update
int botan_mac_update(jnr.ffi.Pointer mac, byte[] buffer, long length) Sends more input to the message authentication code.- Parameters:
mac- MAC objectbuffer- input bufferlength- number of bytes to read from the input buffer- Returns:
- 0 on success, a negative value on failure
-
botan_mac_final
int botan_mac_final(jnr.ffi.Pointer mac, byte[] out) Finalizes the MAC computation and writes the output to out[0:botan_mac_output_length()] then reinitializes for computing another MAC as if botan_mac_clear had been called.- Parameters:
mac- MAC objectout- output buffer- Returns:
- 0 on success, a negative value on failure
-
botan_mac_clear
int botan_mac_clear(jnr.ffi.Pointer mac) Reinitializes the state of the MAC computation. A MAC can be computed (with update/final) immediately.- Parameters:
mac- MAC object- Returns:
- 0 on success, a negative value on failure
-
botan_mac_destroy
int botan_mac_destroy(jnr.ffi.Pointer mac) Frees all resources of the MAC object.- Parameters:
mac- MAC object- Returns:
- 0 if success, error if invalid object handle
-
botan_mac_get_keyspec
int botan_mac_get_keyspec(jnr.ffi.Pointer mac, jnr.ffi.byref.NativeLongByReference minimumKeyLength, jnr.ffi.byref.NativeLongByReference maximumKeyLength, jnr.ffi.byref.NativeLongByReference keyLengthModulo) Gets the key length limits of this auth code- Parameters:
mac- MAC objectminimumKeyLength- if non-NULL, will be set to minimum keylength of MACmaximumKeyLength- if non-NULL, will be set to maximum keylength of MACkeyLengthModulo- if non-NULL will be set to byte multiple of valid keys
-
botan_cipher_init
Initializes a cipher object.- Parameters:
cipher- cipher objectname- name of the cipher including operating mode and paddingflags-- Returns:
- 0 on success, a negative value on failure
-
botan_cipher_output_length
int botan_cipher_output_length(jnr.ffi.Pointer cipher, long inputLength, jnr.ffi.byref.NativeLongByReference outputLength) Returns the output length of this cipher, for a particular input length.- Parameters:
cipher- cipher objectinputLength- input lengthoutputLength- output length- Returns:
- 0 on success, a negative value on failure
-
botan_cipher_valid_nonce_length
int botan_cipher_valid_nonce_length(jnr.ffi.Pointer cipher, long nonceLength) Returns if the specified nonce length is valid for this cipher.- Parameters:
cipher- cipher objectnonceLength- nonce length- Returns:
- 0 on success, a negative value on failure
-
botan_cipher_get_tag_length
int botan_cipher_get_tag_length(jnr.ffi.Pointer cipher, jnr.ffi.byref.NativeLongByReference tagLength) Gets the tag length of the cipher (0 for non-AEAD modes).- Parameters:
cipher- cipher objecttagLength- tag length- Returns:
- 0 on success, a negative value on failure
-
botan_cipher_get_default_nonce_length
int botan_cipher_get_default_nonce_length(jnr.ffi.Pointer cipher, jnr.ffi.byref.NativeLongByReference nonceLength) Gets the default nonce length of this cipher.- Parameters:
cipher- cipher objectnonceLength- nonce length- Returns:
- 0 on success, a negative value on failure
-
botan_cipher_get_update_granularity
int botan_cipher_get_update_granularity(jnr.ffi.Pointer cipher, jnr.ffi.byref.NativeLongByReference updateGranularity) Returns the update granularity of the cipher; botan_cipher_update must be called with blocks of this size, except for the final.- Parameters:
cipher- cipher objectupdateGranularity- update granularity- Returns:
- 0 on success, a negative value on failure
-
botan_cipher_get_keyspec
int botan_cipher_get_keyspec(jnr.ffi.Pointer cipher, jnr.ffi.byref.NativeLongByReference minKeylen, jnr.ffi.byref.NativeLongByReference maxKeylen, jnr.ffi.byref.NativeLongByReference modKeylen) Gets information about the supported key lengths.- Parameters:
cipher- cipher objectminKeylen- minimal key lengthmaxKeylen- maximal key lengthmodKeylen- mod key length- Returns:
- 0 on success, a negative value on failure
-
botan_cipher_set_key
int botan_cipher_set_key(jnr.ffi.Pointer cipher, byte[] key, long keyLength) Sets the key for this cipher object.- Parameters:
cipher- cipher objectkey- keykeyLength- key length- Returns:
- 0 on success, a negative value on failure
-
botan_cipher_reset
int botan_cipher_reset(jnr.ffi.Pointer cipher) Resets the message specific state for this cipher. Without resetting the keys, this resets the nonce, and any state associated with any message bits that have been processed so far. It is conceptually equivalent to calling botan_cipher_clear followed by botan_cipher_set_key with the original key.- Parameters:
cipher- cipher object- Returns:
- 0 on success, a negative value on failure
-
botan_cipher_set_associated_data
int botan_cipher_set_associated_data(jnr.ffi.Pointer cipher, byte[] ad, long adLen) Sets the associated data. Will fail if cipher is not an AEAD.- Parameters:
cipher- cipher objectad- associated dataadLen- associated data length- Returns:
- 0 on success, a negative value on failure
-
botan_cipher_start
int botan_cipher_start(jnr.ffi.Pointer cipher, byte[] nonce, long nonceLength) Begin processing a new message using the provided nonce.- Parameters:
cipher- cipher objectnonce- nonce datanonceLength- nonce data length- Returns:
- 0 on success, a negative value on failure
-
botan_cipher_update
int botan_cipher_update(jnr.ffi.Pointer cipher, long flags, byte[] output, long outputSize, jnr.ffi.byref.NativeLongByReference outputWritten, byte[] input, long inputSize, jnr.ffi.byref.NativeLongByReference inputConsumed) Encrypts some data.- Parameters:
cipher- cipher objectflags-output- cipher output bytesoutputSize- cipher output sizeoutputWritten- written output sizeinput- cipher input bytesinputSize- cipher input sizeinputConsumed- cipher input consumed- Returns:
- 0 on success, a negative value on failure
-
botan_cipher_clear
int botan_cipher_clear(jnr.ffi.Pointer cipher) Resets the key, nonce, AD and all other state on this cipher object.- Parameters:
cipher- cipher object- Returns:
- 0 if success, error if invalid object handle
-
botan_cipher_destroy
int botan_cipher_destroy(jnr.ffi.Pointer cipher) Destroys the cipher object.- Parameters:
cipher- cipher object- Returns:
- 0 if success, error if invalid object handle
-