blob: 18a107041e865a2fdbe16a02afc347ac07ae0abd [file] [log] [blame]
/*
* cifra - embedded cryptography library
* Written in 2016 by Joseph Birr-Pixton <jpixton@gmail.com>
*
* To the extent possible under law, the author(s) have dedicated all
* copyright and related and neighboring rights to this software to the
* public domain worldwide. This software is distributed without any
* warranty.
*
* You should have received a copy of the CC0 Public Domain Dedication
* along with this software. If not, see
* <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
#ifndef DRBG_H
#define DRBG_H
#include <stddef.h>
#include <stdint.h>
#include "chash.h"
#include "hmac.h"
/**
* Hash_DRBG
* =========
* This is Hash_DRBG from SP800-90A rev 1, with SHA256 as
* the underlying hash function.
*
* This generator enforces a `reseed_interval` of 2^32-1:
* use :c:func:`cf_hash_drbg_sha256_needs_reseed` to check
* whether you need to reseed before use, and reseed using
* :c:func:`cf_hash_drbg_sha256_reseed`. If you try to use
* the generator when it thinks it needs reseeding, it will
* call `abort`.
*
* Internally it enforces a `max_number_of_bits_per_request`
* of 2^19 bits. It sorts out chunking up multiple requests
* for you though, so feel free to ask for more than 2^16 bytes
* at a time. If you provide additional input when doing that,
* it is added only once, on the first subrequest.
*
* It does not enforce any `max_length` or
* `max_personalization_string_length`.
*/
/* .. c:type:: cf_hash_drbg_sha256
* Hash_DRBG with SHA256 context.
*
* .. c:member:: cf_hash_drbg_sha256.V
* Current internal state.
*
* .. c:member:: cf_hash_drbg_sha256.C
* Current update offset.
*
* .. c:member:: cf_hash_drbg_sha256.reseed_counter
* Current number of times entropy has been extracted from
* generator.
*/
typedef struct
{
uint8_t V[440/8];
uint8_t C[440/8];
uint32_t reseed_counter;
} cf_hash_drbg_sha256;
/* .. c:function:: $DECL
* Initialises the generator state `ctx`, using the provided `entropy`,
* `nonce` and personalisation string `persn`.
*/
extern void cf_hash_drbg_sha256_init(cf_hash_drbg_sha256 *ctx,
const void *entropy, size_t nentropy,
const void *nonce, size_t nnonce,
const void *persn, size_t npersn);
/* .. c:function:: $DECL
* Returns non-zero if the generator needs reseeding. If
* this function returns non-zero, the next :c:func:`cf_hash_drbg_sha256_gen`
* or :c:func:`cf_hash_drbg_sha256_gen_additional` call will call `abort`.
*/
extern uint32_t cf_hash_drbg_sha256_needs_reseed(const cf_hash_drbg_sha256 *ctx);
/* .. c:function:: $DECL
* Reseeds the generator with the given `entropy` and additional data `addnl`.
*/
extern void cf_hash_drbg_sha256_reseed(cf_hash_drbg_sha256 *ctx,
const void *entropy, size_t nentropy,
const void *addnl, size_t naddnl);
/* .. c:function:: $DECL
* Generates pseudo-random output, writing `nout` bytes at `out`.
* This function aborts if the generator needs seeding.
*/
extern void cf_hash_drbg_sha256_gen(cf_hash_drbg_sha256 *ctx,
void *out, size_t nout);
/* .. c:function:: $DECL
* Generates pseudo-random output, writing `nout` bytes at `out`.
* At the same time, `addnl` is input to the generator as further
* entropy.
* This function aborts if the generator needs seeding.
*/
extern void cf_hash_drbg_sha256_gen_additional(cf_hash_drbg_sha256 *ctx,
const void *addnl, size_t naddnl,
void *out, size_t nout);
/**
* HMAC_DRBG
* =========
* This is HMAC_DRBG from SP800-90a r1 with any hash function.
*
* This generator enforces a `reseed_interval` of 2^32-1:
* use :c:func:`cf_hmac_drbg_needs_reseed` to check whether
* you need to reseed before use, and reseed using
* :c:func:`cf_hmac_drbg_reseed`. If you try to use the
* generator when it thinks it needs reseeding, it will
* call `abort`.
*
* Internally it enforces a `max_number_of_bits_per_request`
* of 2^19 bits. It sorts out chunking up multiple requests
* for you though, so feel free to ask for more than 2^16 bytes
* at a time. If you provide additional input when doing that,
* it is added only once, on the first subrequest.
*
* It does not enforce any `max_length` or
* `max_personalization_string_length`.
*/
/* .. c:type:: cf_hmac_drbg
* HMAC_DRBG context.
*
* .. c:member:: cf_hmac_drbg.V
* Current internal state.
*
* .. c:member:: cf_hmac_drbg.hmac
* Current HMAC context, with key scheduled in it.
*
* .. c:member:: cf_hmac_drbg.reseed_counter
* Current number of times entropy has been extracted from
* generator.
*/
typedef struct
{
uint8_t V[CF_MAXHASH];
cf_hmac_ctx hmac; /* pristine context with key scheduled */
uint32_t reseed_counter;
} cf_hmac_drbg;
/* .. c:function:: $DECL
* Initialises the generator state `ctx`, using the provided `entropy`,
* `nonce` and personalisation string `persn`.
*/
extern void cf_hmac_drbg_init(cf_hmac_drbg *ctx,
const cf_chash *hash,
const void *entropy, size_t nentropy,
const void *nonce, size_t nnonce,
const void *persn, size_t npersn);
/* .. c:function:: $DECL
* Returns non-zero if the generator needs reseeding. If
* this function returns non-zero, the next :c:func:`cf_hmac_drbg_gen`
* or :c:func:`cf_hmac_drbg_gen_additional` call will call `abort`.
*/
extern uint32_t cf_hmac_drbg_needs_reseed(const cf_hmac_drbg *ctx);
/* .. c:function:: $DECL
* Reseeds the generator with the given `entropy` and additional data
* `addnl`.
*/
extern void cf_hmac_drbg_reseed(cf_hmac_drbg *ctx,
const void *entropy, size_t nentropy,
const void *addnl, size_t naddnl);
/* .. c:function:: $DECL
* Generates pseudo-random output, writing `nout` bytes at `out`.
* This function aborts if the generator needs seeding.
*/
extern void cf_hmac_drbg_gen(cf_hmac_drbg *ctx,
void *out, size_t nout);
/* .. c:function:: $DECL
* Generates pseudo-random output, writing `nout` bytes at `out`.
* At the same time, `addnl` is input to the generator as further
* entropy.
* This function aborts if the generator needs seeding.
*/
extern void cf_hmac_drbg_gen_additional(cf_hmac_drbg *ctx,
const void *addnl, size_t naddnl,
void *out, size_t nout);
#endif