kync 0.1.5

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 for key encapsulation plugins.

Key encapsulation is the process of encrypting an already existing key with another different key. This allows you to
separate your application from the key storage so that the user can specify how the key is stored – e.g.
password-encrypted in a file or in the OS' keychain.


== Plugin API
To achieve a simple and cross-platform compatible API, we use dynamic libraries that expose a C API/ABI.


=== General Rules
These general rules apply to all API functions and *MUST* be respected by any plugin that implement this API:

. Each function that may fail *MUST* return the error type
. No ownership is transferred
. An API-call *MUST NOT* take longer than 90 seconds before returning
. All functions *MUST* be threadsafe as long as their parameters are not shared


=== API Overview
These functions are defined by the API and *MUST* be implemented:

. `source_t` and `sink_t`: The data source/sink types
. `init`: Takes care of the library initialization and returns the implemented API version
. `capsule_format_uid`: Returns the capsule format UID for the implemented format
. `capsule_key_ids`: Gets all available capsule key IDs (for plugins that have their own key storage; e.g. GnuPG)
. `seal`: Seals some key bytes into a capsule
. `open`: Extracts the key bytes from a capsule
. `error_t`: The error type


=== source_t
[source,cpp]
----
typedef struct {
	uint8_t const* data(void* handle, size_t* len);
	void* handle;
} source_t;
----

A simple, callback based data-source.

_Important: If `data` returns `NULL`, this means the source is unavailable – which *MUST NOT* be confused with an empty
source!_

Fields:

. `data`: A function that returns the available bytes in `handle` and adjusts `len` accordingly. The returned pointer
  *MAY* be `NULL` in case this source is not available (*MUST NOT* be confused with an empty source!). This function
  *MAY* be called multiple times and *MUST* always return the same result.
. `handle`: An opaque pointer to the data-source handle


=== sink_t
[source,cpp]
----
typedef struct {
	uint8_t* data(void* handle, size_t len);
	void* handle;
} sink_t;
----

A simple, callback based data-sink.

. `data`: A function that returns a pointer to a `len` sized memory-area within `handle` which can be written. If the
  returned pointer is `NULL`, an `ENOBUF`-error *MUST* be returned. This function *MAY* be called multiple times to
  allow partial writes; on successive calls it *MUST* return new a pointer to an empty (not already written) slice of
  memory.
. `handle`: An opaque pointer to the data-sink handle


=== init
[source,cpp]
----
uint8_t init(uint8_t log_level);
----

This function initializes the library, sets the `log_level` and returns the API version. It *MUST NOT* fail.

Valid API versions are:

. `0x01`: The API version for this specification

Parameter `log_level`: The logging level the plugin should use (`0` means no logging). _Note: This only applies to
StdErr-logging_


=== capsule_format_uid
[source,cpp]
----
char const* capsule_format_uid();
----

This function returns a const static pointer the plugin's capsule format UID. It *MUST NOT* fail or return `NULL`.

The capsule format UID is a `'\0'`-terminated UTF-8 string which *MUST* map to one format only. To achieve this, we
append a random UUID; e.g. `AES-256-GCM-IETF.v1.B593CCDE-B5C3-433A-ABBA-9087FBF13E60`. If you write a fully compatible
drop-in replacement for an already existing plugin, you *MAY* use the original format UID.


=== capsule_key_ids
[source,cpp]
----
error_t capsule_key_ids(sink_t ids);
----

This function writes all available capsule key IDs as concatenated, `'\0'`-terminated UTF-8 strings into `ids`. It is
used if the plugin offers it's own key store that you can/must use (e.g. GnuPG).

If the plugin does not support a key store, it *MUST* return an `ENOKEY`-error.


=== seal
[source,cpp]
----
error_t seal(sink_t sink, source_t key, source_t capsule_key_id, source_t user_secret);
----

This function seals a `key` and writes the resulting data to `sink`.

Parameters:

. `sink`: The payload destination
. `key`: The slice containing the key bytes to seal
. `capsule_key_id`: The capsule key ID to use (see `capsule_key_ids`); *MUST* be unavailable if it is not necessary for
  the call – _if_ the plugin does not support a key store or the requested key is unavailable, it *MUST* return an
  `ENOKEY`-error.
. `user_secret`: A user-provided secret. This parameter may have multiple, plugin-dependent purposes; ranging from a
  hardware-token-PIN to the capsule key itself. *MAY* be unavailable if it is not necessary for the call – _if_ it is
  unavailable, a plugin *MUST NOT* perform any authentication attempts that could decrease a retry counter.


=== open
[source,cpp]
----
error_t open(sink_t sink, source_t capsule, source_t user_secret);
----

This function opens a `capsule` and writes the resulting key bytes into `sink`.

Parameters:

. `sink`: The plaintext-key destination
. `capsule`: The capsule data
. `user_secret`: A user-provided secret. This parameter may have multiple, plugin-dependent purposes; ranging from a
  hardware-token-PIN to the capsule key itself. *MAY* be unavailable if it is not necessary for the call – _if_ it is
  unavailable, a plugin *MUST NOT* perform any authentication attempts that could decrease a retry counter.


=== error_t
[source,cpp]
----
typedef struct {
	char const* error_type;
	char const* description;
	uint64_t info;
} error_t;
----

The error type.

Fields:

. `error_type`: The error type as `0`-terminated string or a `NULL`-pointer if no error occurred
. `info`: An error-specific info field
. `description`: An error description as `0`-terminated string; *MUST NOT* be `NULL`


==== EPERM
`"EPERM"` indicates that an operation is not permitted (at least without providing authentication data).

`info` indicates if the action requires authentication (`info != 0`) or if the action will always fail (`info == 0`).


==== EACCES
`"EACCES"` indicates an authentication error. `info` indicates the amount of retries left; if there is no retry-limit,
`info` is `UINT64_MAX`.


==== ENOBUF
`"ENOBUF"` indicates insufficient buffer space – this happens if the `sink_t` store the provided data. `info` indicates
the required size.


==== EIO
`"EIO"` indicates an I/O-related error. `info` is unused.


==== EILSEQ
`"EILSEQ"` indicates invalid capsule data. `info` is unused.


==== ENOKEY
`"ENOKEY"` indicates that there is no matching key available to decrypt the capsule. `info` is unused.


==== EINVAL
"`EINVAL`" indicates an invalid parameter. `info` is the `0`-based index of the parameter.


==== ECANCELED
`"ECANCELED"` indicates that the operation was canceled. `info` is unused.


==== ETIMEDOUT
`"ETIMEDOUT"` indicates that the operation timed out – either because it hit the 90s deadline or because something else
timed out (e.g. hardware token). `info` is unused.


==== EOTHER
`"EOTHER"` indicates that an unspecified fatal error occurred. `info` *MAY* be a plugin-specific error code and *MUST*
be ignored if it's meaning is unknown.