1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/sys/include/crypto/chacha.h

147 lines
4.7 KiB
C

/*
* Copyright (C) 2008 D. J. Bernstein (dedicated to the public domain)
* Copyright (C) 2015 René Kijewski <rene.kijewski@fu-berlin.de>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/**
* @ingroup sys_crypto
* @{
*
* @file
* @brief ChaCha stream cipher
*
* @author René Kijewski <rene.kijewski@fu-berlin.de>
*/
#ifndef CRYPTO_CHACHA_H
#define CRYPTO_CHACHA_H
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief A ChaCha cipher stream context.
* @details Initialize with chacha_init().
*/
typedef struct {
uint32_t state[16]; /**< The current state of the stream. */
uint8_t rounds; /**< Number of iterations. */
} chacha_ctx;
/**
* @brief Initialize a ChaCha context
*
* @param[out] ctx The context to initialize
* @param[in] rounds Number of rounds. Recommended: 20. Also in use: 8 and 12.
* @param[in] key The key to use.
* @param[in] keylen Length (in bytes) of @p key. Must be 16 or 32.
* @param[in] nonce IV / nonce to use.
*
* @return `== 0` on success.
* @return `< 0` if an illegal value for @p rounds or @p keylen was supplied.
*/
int chacha_init(chacha_ctx *ctx,
unsigned rounds,
const uint8_t *key, uint32_t keylen,
const uint8_t nonce[8]);
/**
* @brief Generate next block in the keystream.
*
* @details If you want to seek inside the cipher steam, then you have to
* update the clock in `ctx->state[13]:ctx->state[12]` manually.
*
* @warning You need to re-initialize the context with a new nonce after 2^64
* encrypted blocks, or the keystream will repeat!
*
* @param[in,out] ctx The ChaCha context
* @param[out] x The block of the keystream (`sizeof(x) == 64`).
*/
void chacha_keystream_bytes(chacha_ctx *ctx, void *x);
/**
* @brief Encode or decode a block of data.
*
* @details @p m is always the input regardless if it is the plaintext or ciphertext,
* and @p c vice verse.
*
* @warning You need to re-initialize the context with a new nonce after 2^64
* encrypted blocks, or the keystream will repeat!
*
* @param[in,out] ctx The ChaCha context.
* @param[in] m The input.
* @param[out] c The output.
*/
void chacha_encrypt_bytes(chacha_ctx *ctx, const uint8_t *m, uint8_t *c);
/**
* @copydoc chacha_encrypt_bytes()
*/
static inline void chacha_decrypt_bytes(chacha_ctx *ctx, const uint8_t *m,
uint8_t *c)
{
chacha_encrypt_bytes(ctx, m, c);
}
/**
* @brief Seed the pseudo-random number generator.
*
* @details You can seed the random number generator with up to 64 bytes of data.
* If you feed less than 64 bytes of data, then the privous state gets
* only partially overwritten.
*
* If you want to supply multiple information, then you have to concatenate
* them manually before invoking the function.
*
* The PRNG gets a random seed in the build process.
* You can set a deterministic value by supplying a comma separated
* argument to `make` like
* `RIOT_CHACHA_PRNG_DEFAULT="0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15"`.
*
* @param[in] data Some random data.
* @param[in] bytes Length of @p data in bytes where `0 < bytes <= 64`.
*/
void chacha_prng_seed(const void *data, size_t bytes);
/**
* @brief Extract a number from the pseudo-random number generator.
*
* @warning After you have read 2^68 numbers you have to re-seed the PRNG.
* Otherwise the sequence will repeat.
*
* @return The random value
*/
uint32_t chacha_prng_next(void);
#ifdef __cplusplus
}
#endif
#endif /* CRYPTO_CHACHA_H */
/**
* @}
*/