blob: 874cd3695185387882b0798cc05744d2301ec468 [file] [log] [blame]
/* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef APR_CRYPTO_H
#define APR_CRYPTO_H
#include "apu.h"
#include "apr_pools.h"
#include "apr_tables.h"
#include "apr_hash.h"
#include "apu_errno.h"
#include "apr_thread_proc.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file apr_crypto.h
* @brief APR-UTIL Crypto library
*/
/**
* @defgroup APR_Util_Crypto Crypto routines
* @ingroup APR
* @{
*/
#if APU_HAVE_CRYPTO || defined(DOXYGEN)
#ifndef APU_CRYPTO_RECOMMENDED_DRIVER
#if APU_HAVE_COMMONCRYPTO
/** Recommended driver for this platform */
#define APU_CRYPTO_RECOMMENDED_DRIVER "commoncrypto"
#else
#if APU_HAVE_OPENSSL
/** Recommended driver for this platform */
#define APU_CRYPTO_RECOMMENDED_DRIVER "openssl"
#else
#if APU_HAVE_NSS
/** Recommended driver for this platform */
#define APU_CRYPTO_RECOMMENDED_DRIVER "nss"
#else
#if APU_HAVE_MSCNG
/** Recommended driver for this platform */
#define APU_CRYPTO_RECOMMENDED_DRIVER "mscng"
#else
#if APU_HAVE_MSCAPI
/** Recommended driver for this platform */
#define APU_CRYPTO_RECOMMENDED_DRIVER "mscapi"
#else
#endif
#endif
#endif
#endif
#endif
#endif
/**
* Symmetric Key types understood by the library.
*
* NOTE: It is expected that this list will grow over time.
*
* Interoperability Matrix:
*
* The matrix is based on the testcrypto.c unit test, which attempts to
* test whether a simple encrypt/decrypt will succeed, as well as testing
* whether an encrypted string by one library can be decrypted by the
* others.
*
* Some libraries will successfully encrypt and decrypt their own data,
* but won't decrypt data from another library. It is hoped that over
* time these anomalies will be found and fixed, but until then it is
* recommended that ciphers are chosen that interoperate across platform.
*
* An X below means the test passes, it does not necessarily mean that
* encryption performed is correct or secure. Applications should stick
* to ciphers that pass the interoperablity tests on the right hand side
* of the table.
*
* Aligned data is data whose length is a multiple of the block size for
* the chosen cipher. Padded data is data that is not aligned by block
* size and must be padded by the crypto library.
*
* OpenSSL CommonCrypto NSS Interop
* Align Pad Align Pad Align Pad Align Pad
* 3DES_192/CBC X X X X X X X X
* 3DES_192/ECB X X X X
* AES_256/CBC X X X X X X X X
* AES_256/ECB X X X X X X
* AES_192/CBC X X X X X X
* AES_192/ECB X X X X X
* AES_128/CBC X X X X X X
* AES_128/ECB X X X X X
*
* Conclusion: for padded data, use 3DES_192/CBC or AES_256/CBC. For
* aligned data, use 3DES_192/CBC, AES_256/CBC or AES_256/ECB.
*/
/**
* Types of ciphers.
*/
typedef enum
{
APR_KEY_NONE, APR_KEY_3DES_192, /** 192 bit (3-Key) 3DES */
APR_KEY_AES_128, /** 128 bit AES */
APR_KEY_AES_192, /** 192 bit AES */
APR_KEY_AES_256
/** 256 bit AES */
} apr_crypto_block_key_type_e;
/**
* Types of modes supported by the ciphers.
*/
typedef enum
{
APR_MODE_NONE, /** An error condition */
APR_MODE_ECB, /** Electronic Code Book */
APR_MODE_CBC
/** Cipher Block Chaining */
} apr_crypto_block_key_mode_e;
/**
* Types of digests supported by the apr_crypto_key() function.
*/
typedef enum
{
APR_CRYPTO_DIGEST_NONE, /** An error condition */
APR_CRYPTO_DIGEST_MD5, /** MD5 */
APR_CRYPTO_DIGEST_SHA1, /** SHA1 */
APR_CRYPTO_DIGEST_SHA224, /** SHA224 */
APR_CRYPTO_DIGEST_SHA256, /** SHA256 */
APR_CRYPTO_DIGEST_SHA384, /** SHA384 */
APR_CRYPTO_DIGEST_SHA512, /** SHA512 */
} apr_crypto_block_key_digest_e;
/**
* Structure returned by the crypto_get_block_key_digests() function.
*/
typedef struct apr_crypto_block_key_digest_t {
/** The digest used with this crypto operation. */
apr_crypto_block_key_digest_e type;
/** The digest size used with this digest operation */
int digestsize;
/** The block size used with this digest operation */
int blocksize;
} apr_crypto_block_key_digest_t;
/**
* Types of ciphers supported by the apr_
*/
typedef enum
{
APR_CRYPTO_CIPHER_AUTO, /** Choose the recommended cipher / autodetect the cipher */
APR_CRYPTO_CIPHER_AES_256_CTR, /** AES 256 - CTR mode */
APR_CRYPTO_CIPHER_CHACHA20, /** ChaCha20 */
} apr_crypto_cipher_e;
/**
* Structure representing a backend crypto driver.
*
* This structure is created with apr_crypto_get_driver().
*/
typedef struct apr_crypto_driver_t apr_crypto_driver_t;
/**
* Structure to support a group of crypto operations.
*
* This structure is created with apr_crypto_make().
*/
typedef struct apr_crypto_t apr_crypto_t;
/**
* Structure representing the configuration of the given backend
* crypto library.
*/
typedef struct apr_crypto_config_t apr_crypto_config_t;
/**
* Structure representing a key prepared for encryption, decryption,
* signing or verifying.
*
* This structure is created using the apr_crypto_key() function.
*/
typedef struct apr_crypto_key_t apr_crypto_key_t;
/**
* Structure representing a block context for encryption, decryption,
* signing or verifying.
*
* This structure is created using the apr_crypto_block_encrypt_init()
* and apr_crypto_block_decrypt_init() functions.
*/
typedef struct apr_crypto_block_t apr_crypto_block_t;
/**
* Structure representing a digest context for signing or verifying.
*
* This structure is created using the apr_crypto_digest_init() function.
*/
typedef struct apr_crypto_digest_t apr_crypto_digest_t;
/**
* Structure returned by the crypto_get_block_key_types() function.
*/
typedef struct apr_crypto_block_key_type_t {
/** The cipher used with this crypto operation. */
apr_crypto_block_key_type_e type;
/** The key size used with this crypto operation */
int keysize;
/** The block size used with this crypto operation */
int blocksize;
/** The initialisation vector size used with this crypto operation */
int ivsize;
} apr_crypto_block_key_type_t;
/**
* Structure returned by the crypto_get_block_key_modes() function.
*/
typedef struct apr_crypto_block_key_mode_t {
/** The mode used with this crypto operation. */
apr_crypto_block_key_mode_e mode;
} apr_crypto_block_key_mode_t;
/**
* Structure describing a key to be derived from PBKDF2 to be passed by the
* apr_crypto_key() function.
*
* Derived keys are used for encryption and decryption.
*
* Implementations must use apr_crypto_key_rec_make() to allocate
* this structure.
*/
typedef struct apr_crypto_passphrase_t {
/** The passphrase used by the key generation algorithm */
const char *pass;
/** The length of the passphrase */
apr_size_t passLen;
/** The salt used by the key derivation algorithm */
const unsigned char * salt;
/** The length of the salt. */
apr_size_t saltLen;
/** The number of iterations used by the key derivation function */
int iterations;
} apr_crypto_passphrase_t;
/**
* Structure describing a raw key to be passed by the
* apr_crypto_key() function.
*
* Raw keys are used for encryption and decryption, and must match
* the correct sizes for each cipher.
*
* Implementations must use apr_crypto_key_rec_make() to allocate
* this structure.
*/
typedef struct apr_crypto_secret_t {
/** The raw secret key used for encrypt / decrypt. Must be
* the same size as the block size of the cipher being used.
*/
const unsigned char *secret;
/** The length of the secret key. */
apr_size_t secretLen;
} apr_crypto_secret_t;
/**
* Structure describing a simple digest hash to be generated by the
* apr_crypto_key() function.
*
* Implementations must use apr_crypto_key_rec_make() to allocate
* this structure.
*/
typedef struct apr_crypto_key_hash_t {
/** The digest used for the HMAC. */
apr_crypto_block_key_digest_e digest;
} apr_crypto_key_hash_t;
/**
* Structure describing a HMAC key and digest to be generated by the
* apr_crypto_key() function.
*
* Implementations must use apr_crypto_key_rec_make() to allocate
* this structure.
*/
typedef struct apr_crypto_key_hmac_t {
/** The secret used for the HMAC */
const unsigned char *secret;
/** The length of the secret used for the HMAC */
apr_size_t secretLen;
/** The digest used for the HMAC. */
apr_crypto_block_key_digest_e digest;
} apr_crypto_key_hmac_t;
/**
* Structure describing a CMAC key and digest to be generated by the
* apr_crypto_key() function.
*
* Implementations must use apr_crypto_key_rec_make() to allocate
* this structure.
*/
typedef struct apr_crypto_key_cmac_t {
/** The secret used for the CMAC */
const unsigned char *secret;
/** The length of the secret used for the CMAC */
apr_size_t secretLen;
/** The digest used for the CMAC. */
apr_crypto_block_key_digest_e digest;
} apr_crypto_key_cmac_t;
/**
* Structure used to create a hashed digest.
*
* Implementations must use apr_crypto_digest_rec_make() to allocate
* this structure.
*/
typedef struct apr_crypto_digest_hash_t {
/** The message digest */
unsigned char *s;
/** The length of the message digest */
apr_size_t slen;
/** The digest algorithm */
apr_crypto_block_key_digest_e digest;
} apr_crypto_digest_hash_t;
/**
* Structure used to create a signature.
*
* Implementations must use apr_crypto_digest_rec_make() to allocate
* this structure.
*/
typedef struct apr_crypto_digest_sign_t {
/** The message digest */
unsigned char *s;
/** The length of the message digest */
apr_size_t slen;
/** The digest algorithm */
apr_crypto_block_key_digest_e digest;
} apr_crypto_digest_sign_t;
/**
* Structure used to create a signature for verification.
*
* Implementations must use apr_crypto_digest_rec_make() to allocate
* this structure.
*/
typedef struct apr_crypto_digest_verify_t {
/** The message digest generated */
unsigned char *s;
/** The length of the message digest */
apr_size_t slen;
/** The message digest to be verified against */
const unsigned char *v;
/** The length of the message digest */
apr_size_t vlen;
/** The digest algorithm */
apr_crypto_block_key_digest_e digest;
} apr_crypto_digest_verify_t;
/**
* Types of keys supported by the apr_crypto_key() function and the
* apr_crypto_key_rec_t structure.
*/
typedef enum {
/**
* Key is derived from a passphrase.
*
* Used with the encrypt / decrypt functions.
*/
APR_CRYPTO_KTYPE_PASSPHRASE = 1,
/**
* Key is derived from a raw key.
*
* Used with the encrypt / decrypt functions.
*/
APR_CRYPTO_KTYPE_SECRET = 2,
/**
* Simple digest, no key.
*
* Used with the digest functions.
*/
APR_CRYPTO_KTYPE_HASH = 3,
/**
* HMAC Key is derived from a raw key.
*
* Used with the digest functions.
*/
APR_CRYPTO_KTYPE_HMAC = 4,
/**
* CMAC Key is derived from a raw key.
*
* Used with the digest functions.
*/
APR_CRYPTO_KTYPE_CMAC = 5,
} apr_crypto_key_type;
/**
* Types of digests supported by the apr_crypto_digest() functions and the
* apr_crypto_digest_rec_t structure.
*/
typedef enum {
/**
* Simple digest operation.
*
* Use with apr_crypto_key_rec_t APR_CRYPTO_KTYPE_HASH.
*/
APR_CRYPTO_DTYPE_HASH = 1,
/**
* Sign operation.
*
* Use with apr_crypto_key_rec_t APR_CRYPTO_KTYPE_HMAC or
* APR_CRYPTO_KTYPE_CMAC.
*/
APR_CRYPTO_DTYPE_SIGN = 2,
/**
* Verify operation.
*
* Use with apr_crypto_key_rec_t APR_CRYPTO_KTYPE_HMAC or
* APR_CRYPTO_KTYPE_CMAC.
*/
APR_CRYPTO_DTYPE_VERIFY = 3,
} apr_crypto_digest_type_e;
/**
* Structure describing a key to be generated by the
* apr_crypto_key() function.
*
* Implementations must use apr_crypto_key_rec_make() to allocate
* this structure.
*/
typedef struct apr_crypto_key_rec_t {
/** The type of the key. */
apr_crypto_key_type ktype;
/** The cipher used with this crypto operation. */
apr_crypto_block_key_type_e type;
/** The mode used with this crypto operation. */
apr_crypto_block_key_mode_e mode;
/** Non zero if padding should be used with this crypto operation. */
int pad;
/** Details of each key, based on the key type. */
union {
/**
* This key is generated using a PBE algorithm from a given
* passphrase, and can be used to encrypt / decrypt.
*
* Key type: APR_CRYPTO_KTYPE_PASSPHRASE
*/
apr_crypto_passphrase_t passphrase;
/**
* This is a raw key matching the block size of the given
* cipher, and can be used to encrypt / decrypt.
*
* Key type: APR_CRYPTO_KTYPE_SECRET
*/
apr_crypto_secret_t secret;
/**
* This represents a simple digest with no key.
*
* Key type: APR_CRYPTO_KTYPE_HASH
*/
apr_crypto_key_hash_t hash;
/**
* This is a key of arbitrary length used with an HMAC.
*
* Key type: APR_CRYPTO_KTYPE_HMAC
*/
apr_crypto_key_hmac_t hmac;
/**
* This is a key of arbitrary length used with a CMAC.
*
* Key type: APR_CRYPTO_KTYPE_CMAC
*/
apr_crypto_key_cmac_t cmac;
} k;
} apr_crypto_key_rec_t;
/**
* Structure describing a digest to be hashed, signed or verified.
*
* This structure is passed to the apr_crypto_digest_init() and
* apr_crypto_digest() functions.
*
* Implementations must use apr_crypto_digest_rec_make() to allocate
* this structure.
*/
typedef struct apr_crypto_digest_rec_t {
/** The type of the digest record. */
apr_crypto_digest_type_e dtype;
/** Details of each digest, based on the digest type. */
union {
apr_crypto_digest_hash_t hash;
apr_crypto_digest_sign_t sign;
apr_crypto_digest_verify_t verify;
} d;
} apr_crypto_digest_rec_t;
/**
* @brief Perform once-only initialisation. Call once only.
*
* @param pool - pool to register any shutdown cleanups, etc
* @return APR_ENOTIMPL in case of no crypto support.
*/
APR_DECLARE(apr_status_t) apr_crypto_init(apr_pool_t *pool);
/* TODO: doxygen */
APR_DECLARE(apr_status_t) apr_crypto_lib_version(const char *name,
const char **version);
APR_DECLARE(apr_status_t) apr_crypto_lib_init(const char *name,
const char *params,
const apu_err_t **result,
apr_pool_t *pool);
APR_DECLARE(apr_status_t) apr_crypto_lib_term(const char *name);
APR_DECLARE(int) apr_crypto_lib_is_active(const char *name);
/**
* @brief Zero out the buffer provided when the pool is cleaned up.
*
* @param pool - pool to register the cleanup
* @param buffer - buffer to zero out
* @param size - size of the buffer to zero out
*/
APR_DECLARE(apr_status_t) apr_crypto_clear(apr_pool_t *pool, void *buffer,
apr_size_t size);
/**
* @brief Always zero out the buffer provided, without being optimized out by
* the compiler.
*
* @param buffer - buffer to zero out
* @param size - size of the buffer to zero out
*/
APR_DECLARE(apr_status_t) apr_crypto_memzero(void *buffer, apr_size_t size);
/**
* @brief Timing attacks safe buffers comparison, where the executing time does
* not depend on the bytes compared but solely on the number of bytes.
*
* @param buf1 - first buffer to compare
* @param buf2 - second buffer to compare
* @param size - size of the buffers to compare
* @return 1 if the buffers are equals, 0 otherwise.
*/
APR_DECLARE(int) apr_crypto_equals(const void *buf1, const void *buf2,
apr_size_t size);
/**
* @brief Get the driver struct for a name
*
* @param driver - pointer to driver struct.
* @param name - driver name
* @param params - array of initialisation parameters
* @param result - result and error message on failure
* @param pool - (process) pool to register cleanup
* @return APR_SUCCESS for success
* @return APR_ENOTIMPL for no driver (when DSO not enabled)
* @return APR_EDSOOPEN if DSO driver file can't be opened
* @return APR_ESYMNOTFOUND if the driver file doesn't contain a driver
* @remarks NSS: the params can have "dir", "key3", "cert7" and "secmod"
* keys, each followed by an equal sign and a value. Such key/value pairs can
* be delimited by space or tab. If the value contains a space, surround the
* whole key value pair in quotes: "dir=My Directory".
* @remarks OpenSSL: currently no params are supported.
*/
APR_DECLARE(apr_status_t) apr_crypto_get_driver(
const apr_crypto_driver_t **driver,
const char *name, const char *params, const apu_err_t **result,
apr_pool_t *pool);
/**
* @brief Return the name of the driver.
*
* @param driver - The driver in use.
* @return The name of the driver.
*/
APR_DECLARE(const char *) apr_crypto_driver_name(
const apr_crypto_driver_t *driver);
/**
* @brief Get the result of the last operation on a context. If the result
* is NULL, the operation was successful.
* @param result - the result structure
* @param f - context pointer
* @return APR_SUCCESS for success
*/
APR_DECLARE(apr_status_t) apr_crypto_error(const apu_err_t **result,
const apr_crypto_t *f);
/**
* @brief Create a context for supporting encryption. Keys, certificates,
* algorithms and other parameters will be set per context. More than
* one context can be created at one time. A cleanup will be automatically
* registered with the given pool to guarantee a graceful shutdown.
* @param f - context pointer will be written here
* @param driver - driver to use
* @param params - array of key parameters
* @param pool - process pool
* @return APR_ENOENGINE when the engine specified does not exist. APR_EINITENGINE
* if the engine cannot be initialised.
* @remarks NSS: currently no params are supported.
* @remarks OpenSSL: the params can have "engine" as a key, followed by an equal
* sign and a value.
*/
APR_DECLARE(apr_status_t) apr_crypto_make(apr_crypto_t **f,
const apr_crypto_driver_t *driver, const char *params,
apr_pool_t *pool);
/**
* @brief Get a hash table of key digests, keyed by the name of the digest against
* a pointer to apr_crypto_block_key_digest_t, which in turn begins with an
* integer.
*
* @param digests - hashtable of key digests keyed to constants.
* @param f - encryption context
* @return APR_SUCCESS for success
*/
APR_DECLARE(apr_status_t) apr_crypto_get_block_key_digests(apr_hash_t **digests,
const apr_crypto_t *f);
/**
* @brief Get a hash table of key types, keyed by the name of the type against
* a pointer to apr_crypto_block_key_type_t, which in turn begins with an
* integer.
*
* @param types - hashtable of key types keyed to constants.
* @param f - encryption context
* @return APR_SUCCESS for success
*/
APR_DECLARE(apr_status_t) apr_crypto_get_block_key_types(apr_hash_t **types,
const apr_crypto_t *f);
/**
* @brief Get a hash table of key modes, keyed by the name of the mode against
* a pointer to apr_crypto_block_key_mode_t, which in turn begins with an
* integer.
*
* @param modes - hashtable of key modes keyed to constants.
* @param f - encryption context
* @return APR_SUCCESS for success
*/
APR_DECLARE(apr_status_t) apr_crypto_get_block_key_modes(apr_hash_t **modes,
const apr_crypto_t *f);
/**
* @brief Create a key record to be passed to apr_crypto_key().
* @param ktype The apr_crypto_key_type to use.
* @param p The pool to use.
* @return Returns a blank structure of the correct size.
*/
APR_DECLARE(apr_crypto_key_rec_t *) apr_crypto_key_rec_make(
apr_crypto_key_type ktype, apr_pool_t *p);
/**
* @brief Create a digest record to be passed to apr_crypto_digest_init().
* @param dtype The type of digest record to create.
* @param p The pool to use.
* @return Returns a blank structure of the correct size.
*/
APR_DECLARE(apr_crypto_digest_rec_t *) apr_crypto_digest_rec_make(
apr_crypto_digest_type_e dtype, apr_pool_t *p);
/**
* @brief Create a key from the provided secret or passphrase. The key is cleaned
* up when the context is cleaned, and may be reused with multiple
* encryption, decryption, signing or verifying operations. The choice of
* key type much match the intended operation.
* @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
* *key is not NULL, *key must point at a previously created structure.
* @param key The key returned, see note.
* @param rec The key record, from which the key will be derived.
* @param f The context to use.
* @param p The pool to use.
* @return APR_ENOKEY if the pass phrase is missing or empty, or if a backend
* error occurred while generating the key.
* @return APR_ENOCIPHER if the type or mode
* is not supported by the particular backend.
* @return APR_EKEYTYPE if the key type is
* not known.
* @return APR_EPADDING if padding was requested but is not supported.
* @return APR_ENOTIMPL if not implemented.
*/
APR_DECLARE(apr_status_t) apr_crypto_key(apr_crypto_key_t **key,
const apr_crypto_key_rec_t *rec, const apr_crypto_t *f, apr_pool_t *p);
/**
* @brief Create a key from the given passphrase. By default, the PBKDF2
* algorithm is used to generate the key from the passphrase. It is expected
* that the same pass phrase will generate the same key, regardless of the
* backend crypto platform used. The key is cleaned up when the context
* is cleaned, and may be reused with multiple encryption or decryption
* operations.
* @note If *key is NULL, a apr_crypto_key_t will be created from a pool. If
* *key is not NULL, *key must point at a previously created structure.
* @param key The key returned, see note.
* @param ivSize The size of the initialisation vector will be returned, based
* on whether an IV is relevant for this type of crypto.
* @param pass The passphrase to use.
* @param passLen The passphrase length in bytes
* @param salt The salt to use.
* @param saltLen The salt length in bytes
* @param type 3DES_192, AES_128, AES_192, AES_256.
* @param mode Electronic Code Book / Cipher Block Chaining.
* @param doPad Pad if necessary.
* @param iterations Number of iterations to use in algorithm
* @param f The context to use.
* @param p The pool to use.
* @return APR_ENOKEY if the pass phrase is missing or empty, or if a backend
* error occurred while generating the key.
* @return APR_ENOCIPHER if the type or mode
* is not supported by the particular backend.
* @return APR_EKEYTYPE if the key type is
* not known.
* @return APR_EPADDING if padding was requested but is not supported.
* @return APR_ENOTIMPL if not implemented.
* @deprecated Replaced by apr_crypto_key().
*/
APR_DECLARE(apr_status_t) apr_crypto_passphrase(apr_crypto_key_t **key,
apr_size_t *ivSize, const char *pass, apr_size_t passLen,
const unsigned char * salt, apr_size_t saltLen,
const apr_crypto_block_key_type_e type,
const apr_crypto_block_key_mode_e mode, const int doPad,
const int iterations, const apr_crypto_t *f, apr_pool_t *p);
/**
* @brief Initialise a context for encrypting arbitrary data using the given key.
* @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
* *ctx is not NULL, *ctx must point at a previously created structure.
* @param ctx The block context returned, see note.
* @param iv Optional initialisation vector. If the buffer pointed to is NULL,
* an IV will be created at random, in space allocated from the pool.
* If the buffer pointed to is not NULL, the IV in the buffer will be
* used.
* @param key The key structure to use.
* @param blockSize The block size of the cipher.
* @param p The pool to use.
* @return APR_ENOIV if an initialisation vector is required but not specified.
* @return APR_EINIT if the backend failed to initialise the context.
* @return APR_ENOTIMPL if not implemented.
* @return APR_EINVAL if the key type does not support the given operation.
*/
APR_DECLARE(apr_status_t) apr_crypto_block_encrypt_init(
apr_crypto_block_t **ctx, const unsigned char **iv,
const apr_crypto_key_t *key, apr_size_t *blockSize, apr_pool_t *p);
/**
* @brief Encrypt data provided by in, write it to out.
* @note The number of bytes written will be written to outlen. If
* out is NULL, outlen will contain the maximum size of the
* buffer needed to hold the data, including any data
* generated by apr_crypto_block_encrypt_finish below. If *out points
* to NULL, a buffer sufficiently large will be created from
* the pool provided. If *out points to a not-NULL value, this
* value will be used as a buffer instead.
* @param out Address of a buffer to which data will be written,
* see note.
* @param outlen Length of the output will be written here.
* @param in Address of the buffer to read.
* @param inlen Length of the buffer to read.
* @param ctx The block context to use.
* @return APR_ECRYPT if an error occurred.
* @return APR_ENOTIMPL if not implemented.
* @return APR_EINVAL if the key type does not support the given operation.
*/
APR_DECLARE(apr_status_t) apr_crypto_block_encrypt(unsigned char **out,
apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
apr_crypto_block_t *ctx);
/**
* @brief Encrypt final data block, write it to out.
* @note If necessary the final block will be written out after being
* padded. Typically the final block will be written to the
* same buffer used by apr_crypto_block_encrypt, offset by the
* number of bytes returned as actually written by the
* apr_crypto_block_encrypt() call. After this call, the context
* is cleaned and can be reused by apr_crypto_block_encrypt_init().
* @param out Address of a buffer to which data will be written. This
* buffer must already exist, and is usually the same
* buffer used by apr_crypto_block_encrypt(). See note.
* @param outlen Length of the output will be written here.
* @param ctx The block context to use.
* @return APR_ECRYPT if an error occurred.
* @return APR_EPADDING if padding was enabled and the block was incorrectly
* formatted.
* @return APR_ENOTIMPL if not implemented.
* @return APR_EINVAL if the key type does not support the given operation.
*/
APR_DECLARE(apr_status_t) apr_crypto_block_encrypt_finish(unsigned char *out,
apr_size_t *outlen, apr_crypto_block_t *ctx);
/**
* @brief Initialise a context for decrypting arbitrary data using the given key.
* @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
* *ctx is not NULL, *ctx must point at a previously created structure.
* @param ctx The block context returned, see note.
* @param blockSize The block size of the cipher.
* @param iv Optional initialisation vector.
* @param key The key structure to use.
* @param p The pool to use.
* @return APR_ENOIV if an initialisation vector is required but not specified.
* @return APR_EINIT if the backend failed to initialise the context.
* @return APR_ENOTIMPL if not implemented.
* @return APR_EINVAL if the key type does not support the given operation.
*/
APR_DECLARE(apr_status_t) apr_crypto_block_decrypt_init(
apr_crypto_block_t **ctx, apr_size_t *blockSize,
const unsigned char *iv, const apr_crypto_key_t *key, apr_pool_t *p);
/**
* @brief Decrypt data provided by in, write it to out.
* @note The number of bytes written will be written to outlen. If
* out is NULL, outlen will contain the maximum size of the
* buffer needed to hold the data, including any data
* generated by apr_crypto_block_decrypt_finish below. If *out points
* to NULL, a buffer sufficiently large will be created from
* the pool provided. If *out points to a not-NULL value, this
* value will be used as a buffer instead.
* @param out Address of a buffer to which data will be written,
* see note.
* @param outlen Length of the output will be written here.
* @param in Address of the buffer to read.
* @param inlen Length of the buffer to read.
* @param ctx The block context to use.
* @return APR_ECRYPT if an error occurred.
* @return APR_ENOTIMPL if not implemented.
* @return APR_EINVAL if the key type does not support the given operation.
*/
APR_DECLARE(apr_status_t) apr_crypto_block_decrypt(unsigned char **out,
apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
apr_crypto_block_t *ctx);
/**
* @brief Decrypt final data block, write it to out.
* @note If necessary the final block will be written out after being
* padded. Typically the final block will be written to the
* same buffer used by apr_crypto_block_decrypt, offset by the
* number of bytes returned as actually written by the
* apr_crypto_block_decrypt() call. After this call, the context
* is cleaned and can be reused by apr_crypto_block_decrypt_init().
* @param out Address of a buffer to which data will be written. This
* buffer must already exist, and is usually the same
* buffer used by apr_crypto_block_decrypt(). See note.
* @param outlen Length of the output will be written here.
* @param ctx The block context to use.
* @return APR_ECRYPT if an error occurred.
* @return APR_EPADDING if padding was enabled and the block was incorrectly
* formatted.
* @return APR_ENOTIMPL if not implemented.
* @return APR_EINVAL if the key type does not support the given operation.
*/
APR_DECLARE(apr_status_t) apr_crypto_block_decrypt_finish(unsigned char *out,
apr_size_t *outlen, apr_crypto_block_t *ctx);
/**
* @brief Clean encryption / decryption context.
* @note After cleanup, a context is free to be reused if necessary.
* @param ctx The block context to use.
* @return Returns APR_ENOTIMPL if not supported.
*/
APR_DECLARE(apr_status_t) apr_crypto_block_cleanup(apr_crypto_block_t *ctx);
/**
* @brief Initialise a context for hashing, signing or verifying arbitrary
* data.
*
* This function supports:
* - Simple hashing (MD5, SHA1, SHA224, SHA256, SHA384, SHA512).
* - HMAC (with a secret key)
* - CMAC (with a secret key)
*
* Details of the key and the type of digest to be performed are
* passed in the constant apr_crypto_key_t structure, which can be
* reused by many calls to apr_crypto_digest_init().
*
* Details of this particular operation are read from and written to
* the apr_crypto_digest_rec_t structure, which is expected to
* contain the message digest to be verified, as well as message
* digest generated during the hashing or signing process. This
* structure will be modified by each digest operation, and cannot be
* shared.
* @note If *d is NULL, a apr_crypto_digest_t will be created from a pool. If
* *d is not NULL, *d must point at a previously created structure.
* @param d The digest context returned, see note.
* @param key The key structure to use.
* @param rec The digest record indicating whether we want to sign or verify.
* This record contains digest we want to verify against, as well as
* the signature we have generated.
* @param p The pool to use.
* @return APR_SUCCESS if successful.
* @return APR_ENOIV if an initialisation vector is required but not specified.
* @return APR_EINIT if the backend failed to initialise the context.
* @return APR_ENOTIMPL if not implemented.
* @return APR_EINVAL if the key type does not support the given operation.
*/
APR_DECLARE(apr_status_t) apr_crypto_digest_init(apr_crypto_digest_t **d,
const apr_crypto_key_t *key, apr_crypto_digest_rec_t *rec, apr_pool_t *p);
/**
* @brief Update the digest with data provided by in.
* @param digest The block context to use.
* @param in Address of the buffer to digest.
* @param inlen Length of the buffer to digest.
* @return APR_SUCCESS if successful.
* @return APR_ECRYPT if an error occurred.
* @return APR_ENOTIMPL if not implemented.
* @return APR_EINVAL if the key type does not support the given operation.
*/
APR_DECLARE(apr_status_t) apr_crypto_digest_update(apr_crypto_digest_t *digest,
const unsigned char *in, apr_size_t inlen);
/**
* @brief Finalise the digest and write the result.
*
* The result is written to the apr_crypto_digest_rec_t structure
* passed into apr_crypto_digest_init().
*
* If verification is requested, this function will return the
* result of the verification.
* @note After this call, the context is cleaned and can be reused by
* apr_crypto_digest_init().
* @param digest The digest context to use.
* @return APR_SUCCESS if hash, signing or verification was successful.
* @return APR_ENOVERIFY if the verification failed.
* @return APR_ECRYPT if an error occurred.
* @return APR_EPADDING if padding was enabled and the block was incorrectly
* formatted.
* @return APR_ENOTIMPL if not implemented.
* @return APR_EINVAL if the key type does not support the given operation.
*/
APR_DECLARE(apr_status_t) apr_crypto_digest_final(apr_crypto_digest_t *digest);
/**
* @brief One shot digest on a single memory buffer.
* @param key The key structure to use.
* @param rec The digest record indicating whether we want to sign or verify.
* This record contains digest we want to verify against, as well as
* the signature we have generated. This record will contain the digest
* calculated.
* @param in Address of the buffer to digest.
* @param inlen Length of the buffer to digest.
* @param p The pool to use.
* @return APR_ENOIV if an initialisation vector is required but not specified.
* @return APR_EINIT if the backend failed to initialise the context.
* @return APR_ENOTIMPL if not implemented.
* @return APR_EINVAL if the key type does not support the given operation.
*/
APR_DECLARE(apr_status_t) apr_crypto_digest(const apr_crypto_key_t *key,
apr_crypto_digest_rec_t *rec, const unsigned char *in, apr_size_t inlen,
apr_pool_t *p);
/**
* @brief Clean digest context.
* @note After cleanup, a digest context is free to be reused if necessary.
* @param ctx The digest context to use.
* @return Returns APR_ENOTIMPL if not supported.
*/
APR_DECLARE(apr_status_t) apr_crypto_digest_cleanup(apr_crypto_digest_t *ctx);
/**
* @brief Clean encryption / decryption context.
* @note After cleanup, a context is free to be reused if necessary.
* @param f The context to use.
* @return Returns APR_ENOTIMPL if not supported.
*/
APR_DECLARE(apr_status_t) apr_crypto_cleanup(apr_crypto_t *f);
/**
* @brief Shutdown the crypto library.
* @note After shutdown, it is expected that the init function can be called again.
* @param driver - driver to use
* @return Returns APR_ENOTIMPL if not supported.
*/
APR_DECLARE(apr_status_t) apr_crypto_shutdown(
const apr_crypto_driver_t *driver);
#if APU_HAVE_CRYPTO_PRNG
/**
* Cryptographic Pseudo Random Number Generator (CPRNG).
*
* Allows to generate cryptographically secure random bytes indefinitely
* given an initial seed of \ref APR_CRYPTO_PRNG_SEED_SIZE bytes (32), which
* is either provided by the caller or automatically gathered from the system.
* The CPRNG can also be re-seeded at any time, or after a process is fork()ed.
*
* The internal key is renewed every \ref APR_CRYPTO_PRNG_SEED_SIZE random
* bytes produced and those data once returned to the caller are cleared from
* the internal state, which ensures forward secrecy.
*
* This CPRNG is fast, based on a stream cipher, and will never block besides
* the initial seed or any reseed if it depends on the system entropy.
*
* Finally, it can be used either globally (locked in multithread environment),
* per-thread (a lock free instance is automatically created for each thread on
* first use), or created as standalone instance (manageable independently).
*/
#define APR_CRYPTO_PRNG_SEED_SIZE 32
#define APR_CRYPTO_PRNG_LOCKED (0x1)
#define APR_CRYPTO_PRNG_PER_THREAD (0x2)
#define APR_CRYPTO_PRNG_MASK (0x3)
/** Opaque CPRNG state */
typedef struct apr_crypto_prng_t apr_crypto_prng_t;
/**
* @brief Perform global initialisation. Call once only.
*
* @param pool Used to allocate memory and register cleanups
* @param crypto The crypto context to use. If NULL, one will be created from
* the recommended crypto implementation.
* @param cipher The cipher to use.
* @param bufsize The size of the buffer used to cache upcoming random bytes.
* @param seed A custom seed of \ref APR_CRYPTO_PRNG_SEED_SIZE bytes,
* or NULL for the seed to be gathered from system entropy.
* @param flags \ref APR_CRYPTO_PRNG_PER_THREAD to allow for per-thread CPRNG,
* or zero.
* @return APR_EREINIT if called more than once,
* any system error (APR_ENOMEM, ...).
*/
APR_DECLARE(apr_status_t) apr_crypto_prng_init(apr_pool_t *pool, apr_crypto_t *crypto,
apr_crypto_cipher_e cipher, apr_size_t bufsize, const unsigned char seed[], int flags);
/**
* @brief Terminate global initialisation if needed, before automatic cleanups.
*
* @return APR_EINIT if \ref apr_crypto_prng_init() was not called.
*/
APR_DECLARE(apr_status_t) apr_crypto_prng_term(void);
/**
* @brief Generate cryptographically secure random bytes from the global CPRNG.
*
* @param buf The destination buffer
* @param len The destination length
* @return APR_EINIT if \ref apr_crypto_prng_init() was not called.
* any system error (APR_ENOMEM, ...).
*/
APR_DECLARE(apr_status_t) apr_crypto_random_bytes(void *buf, apr_size_t len);
#if APR_HAS_THREADS
/**
* @brief Generate cryptographically secure random bytes from the CPRNG of
* the current thread.
*
* @param buf The destination buffer
* @param len The destination length
* @return APR_EINIT if \ref apr_crypto_prng_init() was not called or
* called without \ref APR_CRYPTO_PRNG_PER_THREAD,
* any system error (APR_ENOMEM, ...).
*/
APR_DECLARE(apr_status_t) apr_crypto_random_thread_bytes(void *buf,
apr_size_t len);
#endif
/**
* @brief Create a standalone CPRNG.
*
* @param pcprng The CPRNG created.
* @param crypto The crypto context to use. If NULL, one will be created from
* the recommended crypto implementation.
* @param cipher The cipher to use.
* @param bufsize The size of the buffer used to cache upcoming random bytes.
* @param flags \ref APR_CRYPTO_PRNG_LOCKED to control concurrent accesses,
* or zero.
* @param seed A custom seed of \ref APR_CRYPTO_PRNG_SEED_SIZE bytes,
* or NULL for the seed to be gathered from system entropy.
* @param pool Used to allocate memory and register cleanups, or NULL
* if the memory should be managed outside (besides per-thread
* which has an automatic memory management with no pool, when
* NULL is given the caller is responsible for calling
* \ref apr_crypto_prng_destroy() or some memory would leak.
* @return APR_EINVAL if \ref bufsize is too large or flags are unknown,
* APR_ENOTIMPL if \ref APR_CRYPTO_PRNG_LOCKED with !APR_HAS_THREADS,
* APR_ENOCIPHER if neither Chacha20 nor AES-256-CTR are available,
* any system error (APR_ENOMEM, ...).
*/
APR_DECLARE(apr_status_t) apr_crypto_prng_create(apr_crypto_prng_t **pcprng,
apr_crypto_t *crypto, apr_crypto_cipher_e cipher, apr_size_t bufsize,
int flags, const unsigned char seed[], apr_pool_t *pool);
/**
* @brief Destroy a standalone CPRNG.
*
* @param cprng The CPRNG to destroy.
* @return APR_SUCCESS.
*/
APR_DECLARE(apr_status_t) apr_crypto_prng_destroy(apr_crypto_prng_t *cprng);
/**
* @brief Rekey a CPRNG.
*
* @param cprng The CPRNG, or NULL for all the created CPRNGs (but per-thread).
* @return Any system error (APR_ENOMEM, ...).
*/
APR_DECLARE(apr_status_t) apr_crypto_prng_rekey(apr_crypto_prng_t *cprng);
/**
* @brief Reseed a CPRNG.
*
* @param cprng The CPRNG to reseed, or NULL for the global CPRNG.
* @param seed A custom seed of \ref APR_CRYPTO_PRNG_SEED_SIZE bytes,
* or NULL for the seed to be gathered from system entropy.
* @return Any system error (APR_ENOMEM, ...).
*/
APR_DECLARE(apr_status_t) apr_crypto_prng_reseed(apr_crypto_prng_t *cprng,
const unsigned char seed[]);
#if APR_HAS_FORK
#define APR_CRYPTO_FORK_INPARENT 0
#define APR_CRYPTO_FORK_INCHILD 1
/**
* @brief Rekey a CPRNG in the parent and/or child process after a fork(),
* so that they don't share the same state.
*
* @param cprng The CPRNG, or NULL for all the created CPRNGs (but per-thread).
* @param in_child Whether in the child process (non zero), or in the parent
* process otherwise (zero).
*
* @return Any system error (APR_ENOMEM, ...).
*/
APR_DECLARE(apr_status_t) apr_crypto_prng_after_fork(apr_crypto_prng_t *cprng,
int flags);
#endif
/**
* @brief Generate cryptographically secure random bytes from a CPRNG.
*
* @param cprng The CPRNG, or NULL for the global CPRNG.
* @param buf The destination buffer
* @param len The destination length
* @return Any system error (APR_ENOMEM, ...).
*/
APR_DECLARE(apr_status_t) apr_crypto_prng_bytes(apr_crypto_prng_t *cprng,
void *buf, apr_size_t len);
#endif /* APU_HAVE_CRYPTO_PRNG */
#endif /* APU_HAVE_CRYPTO */
/** @} */
#ifdef __cplusplus
}
#endif
#endif