diff --git a/include/cc20.h b/include/cc20.h index ec38702..a462d24 100644 --- a/include/cc20.h +++ b/include/cc20.h @@ -1,5 +1,11 @@ #ifndef _CC20_H #define _CC20_H + +#ifdef __cplusplus +extern "C" { +#define restrict __restrict__ +#endif + #include #include @@ -7,56 +13,99 @@ #define IV_SIZE 12 enum cc20_mode { + /// Encrypt the data written to this stream CC20_ENCRYPT, + /// Decrypt the data written to this stream CC20_DECRYPT, }; +/// Result from a `cc20_` internal operation. typedef enum cc20_error { + /// An internal fatal error CC20_ERR_PANIC = -1, + /// Operation succeeded CC20_ERR_NONE = 0, + /// If a `FILE*` stream is used that is invalid or `NULL`. CC20_ERR_INVALID_FILE, + /// If a pointer is `NULL` that should not be CC20_ERR_NULL_PTR, + /// An underlying `libssl` call fails CC20_ERR_SSL, + /// There is a generic I/O failure CC20_ERR_IO } cc20_result_t; #define CC20_OK(v) ((v)==CC20_ERR_NONE) #define CC20_ERR(v) ((v)!=CC20_ERR_NONE) +/// A chacha20_poly1305 key typedef uint8_t cc20_key_t[KEY_SIZE]; +/// A chacha20_poly1305 IV typedef uint8_t cc20_iv_t[IV_SIZE]; +/// Metadata used to construct an instance of `cc20_sink_t`. typedef struct cc20_metadata { + /// A valid, non-NULL, stream that the sink will write the transformed data to. FILE* backing; + /// The key used for the cipher cc20_key_t key; + /// The iv used to initialise the cipher. cc20_iv_t iv; + /// The transformation mode + /// + /// *MUST* be a valid `enum cc20_mode` disctiminant or UB. enum cc20_mode mode; } cc20_meta_t; +/// Configuration for a wrapper `FILE*` stream over a `cc20_sink_t`. struct cc20_wrap_cfg { - // default: false (0) + /// Keep the backing (`cc20_meta_t.backing`) stream alive (do not `fclose()` it) when the wrapper is closed. + /// # Default + /// * false (0) int keep_alive; }; +/// An opaque type containing the cipher transform and the backing stream. typedef struct cc20_sink cc20_sink_t; // Functions // + +/// Parameters tagged with this must be valid, non-NULL and non-aliased; but can point to uninitialised memory for this type. +/// They are guaranteed to be written to with a valid value if the function succeeds. If it fails, it is unspecified whether it will be written to. +//TODO: Attribute non-NULL how? #define _cc20_OUT *restrict +/// Generate a new securely random key and/or iv. +/// +/// # Possible errors +/// * `CC20_ERR_PANIC` - If the RNG fails. cc20_result_t cc20_keygen(cc20_key_t* restrict key, cc20_iv_t* restrict iv); +/// Write these parameters to `output` metadata. +/// * `key` and `iv` can be NULL, if one or both are, the field(s) will be initialised to secure random data in the `output` metadata (same as `cc20_keygen`. +/// * `file` must be non-NULL and valid. +/// # Possible errors +/// * `CC20_ERR_INVALID_FILE` - if `file` is NULL. +/// * `CC20_ERR_NULL_PTR` - if `output` is NULL. (see `_cc20_OUT`.) +/// ## Undefined behaviour +/// If `mode` is not a valid distriminant of `enum cc20_mdoe`. cc20_result_t cc20_gen_meta(FILE* file, const cc20_key_t* key, const cc20_iv_t* iv, enum cc20_mode mode, struct cc20_metadata _cc20_OUT output); +/// Create a sink from the specified metadata and write it to `output`. +/// +/// # Possible errors +/// * `CC20_ERR_NULL_PTR` - If `meta` or `output` is NULL. cc20_result_t cc20_gen_sink(const struct cc20_metadata* meta, cc20_sink_t* _cc20_OUT output); - +//TODO: Rework this entire API interface. Its clunky. +//TODO: Document the rest cc20_result_t cc20_gen_sink_full(FILE* file, const cc20_key_t* key, const cc20_iv_t* iv, @@ -79,4 +128,9 @@ cc20_result_t cc20_write(const void* ptr, size_t * restrict bytes, cc20_sink_t* FILE* cc20_wrap_sink(cc20_sink_t* sink, const struct cc20_wrap_cfg* cfg); +#ifdef __cplusplus +} +#undef restrict +#endif + #endif /* _CC20_H */