= Kync v1
:toc:
== General
Kync describes a **K**e**Y**e**NC**apsulation 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.
== Plugin API
To achieve a simple and cross-platform compatible API, we use dynamic libraries that expose a C
API/ABI.
=== General Rules
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 return `NULL`.
. 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
=== API Overview
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
=== `init`
[source,cpp]
----
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 API `0x01_00`)
. `log_level`: The logging level the plugin should use (`0` means no logging). _Note: This applies
to StdErr-logging only_
=== `id`
[source,cpp]
----
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
=== `configs`
[source,cpp]
----
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
=== `set_context`
[source,cpp]
----
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)
=== `auth_info_protect`, `auth_info_recover`
[source,cpp]
----
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 to `1` if an authentication is required, `0` otherwise
. `retries`: Is set to the amount of retries left or `UINT64_MAX` if there is no limit
. `config`: The config to get the authentication information for
=== `protect`
[source,cpp]
----
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 or `NULL` if no authentication attempt should be performed
=== `recover`
[source,cpp]
----
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 or `NULL` if no authentication attempt should be performed
=== `slice_t`
[source,cpp]
----
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
=== `write_t`
[source,cpp]
----
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 writes `data` to `handle` and returns `NULL` on
success or an error pointer on error