Kync describes a KeYeNCapsulation plugin API – a KyNc plugin performs the task of protecting your app’s secret.
The advantage of separating the app and the key storage is that the secret can be stored in a context specific and user defined way by simply loading another plugin – how the secret is protected becomes completely opaque to your app.
To achieve a simple and cross-platform compatible API, we use dynamic libraries that expose a C API/ABI.
These rules apply to all functions:
-
All functions may fail. If they fail they return a pointer to a statically allocated,
\0
-terminated C string. Otherwise they returnNULL
. -
All structs, callbacks etc. are passed as pointers; no ownership is transferred
-
An API-call MUST NOT take longer than 90 seconds before returning
-
If a callback fails, the operation must be canceled and the callback error MUST be propagated
These functions are defined by the API and MUST be implemented:
-
init
: Initializes the library, sets the log level and checks if the requested API is supported -
id
: Queries the plugin/format ID -
configs
: Queries all possible plugin configurations (available algorithms, tokens etc.) -
auth_info
: Queries the authentication requirements for a specific configuration -
protect
: Protects a secret and generates the necessary public recovery information for it -
recover
: Recovers a secret using the public recovery information -
slice_t
: An immutable slice over some bytes -
write_t
: A write callback
const char* init(uint16_t api, uint8_t log_level);
This function initializes the library, sets the log_level
and checks if the requested api
version is implemented.
Parameters:
-
api
: The requested API version (this document defines the API0x01_00
) -
log_level
: The logging level the plugin should use (0
means no logging). Note: This applies to StdErr-logging only
const char* id(write_t* sink);
This function writes the capsule UID to sink
using a single sink.write
-call.
Parameters:
-
sink
: The sink to write the ID to
const char* configs(write_t* sink);
This function writes all available configs to sink
using a single sink.write
-call for each
config (e.g. three configs result in three sink.write
-calls).
Configs identify a specific algorithm/storage/token etc. There must at least be one config.
Parameters:
-
sink
: The sink to write the configs to
const char* set_context(const slice_t* context);
This functions sets an optional application specific context. This makes it possible for the plugin
to generate more meaningful names etc. Plugins may silently ignore a call to set_context
and
MUST NOT return an error unless they want to but cannot use the context.
Parameters:
-
context
: The application context (e.g. the application name and key usage)
const char* auth_info_protect(uint8_t* is_required, uint64_t* retries, const slice_t* config);
const char* auth_info_recover(uint8_t* is_required, uint64_t* retries, const slice_t* config);
These functions query the authentication requirements to protect/recover a secret for a specific config. The functions check if an authentication is necessary and get the number if retries left.
Parameters:
-
is_required
: Is set to1
if an authentication is required,0
otherwise -
retries
: Is set to the amount of retries left orUINT64_MAX
if there is no limit -
config
: The config to get the authentication information for
const char* protect(write_t* sink, const slice_t* data, const slice_t* config, const slice_t* auth);
This function protects data
and writes the public recovery information to sink
.
Parameters:
-
sink
: The sink to write the public recovery information to -
data
: The secret data to protect -
config
: The configuration to use -
auth
: The authentication information orNULL
if no authentication attempt should be performed
const char* recover(write_t* sink, const slice_t* data, const slice_t* auth);
This recovers a secret from the recovery data
and writes it to sink
.
Parameters:
-
sink
: The sink to write the public recovery information to -
data
: The secret data to protect -
auth
: The authentication information orNULL
if no authentication attempt should be performed
typedef struct slice_t slice_t;
/// A slice over some data
struct slice_t {
/// The data
const uint8_t* ptr;
/// The data length
const size_t len;
};
An immutable slice over some data.
Fields:
-
ptr
: A pointer to the data -
len
: The length of the data
typedef struct write_t write_t;
/// A write callback
struct write_t {
/// An opaque handle to the data sink
void* handle;
/// Pushes a segment to `handle` and returns `NULL` on success or a pointer to a static error
/// description
const char* (*write)(void* handle, const slice_t* data);
};
A write callback to write some data to an opaque handle. The write function may be called multiple
times – either to split the data into different logical segments (e.g. configs
) or just because
the data is not available at once (e.g. protect
and recover
).
Fields:
-
handle
: A pointer to an opaque handle -
write
: A pointer to a write implementation that writesdata
tohandle
and returnsNULL
on success or an error pointer on error