kync 0.2.0

KyNc – a generic API for key encapsulation and a Rust interface to KyNc-plugins
Documentation
= 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