162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * DRBG based on NIST SP800-90A 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright Stephan Mueller <smueller@chronox.de>, 2014 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 762306a36Sopenharmony_ci * modification, are permitted provided that the following conditions 862306a36Sopenharmony_ci * are met: 962306a36Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 1062306a36Sopenharmony_ci * notice, and the entire permission notice in its entirety, 1162306a36Sopenharmony_ci * including the disclaimer of warranties. 1262306a36Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright 1362306a36Sopenharmony_ci * notice, this list of conditions and the following disclaimer in the 1462306a36Sopenharmony_ci * documentation and/or other materials provided with the distribution. 1562306a36Sopenharmony_ci * 3. The name of the author may not be used to endorse or promote 1662306a36Sopenharmony_ci * products derived from this software without specific prior 1762306a36Sopenharmony_ci * written permission. 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * ALTERNATIVELY, this product may be distributed under the terms of 2062306a36Sopenharmony_ci * the GNU General Public License, in which case the provisions of the GPL are 2162306a36Sopenharmony_ci * required INSTEAD OF the above restrictions. (This clause is 2262306a36Sopenharmony_ci * necessary due to a potential bad interaction between the GPL and 2362306a36Sopenharmony_ci * the restrictions contained in a BSD-style copyright.) 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 2662306a36Sopenharmony_ci * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2762306a36Sopenharmony_ci * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF 2862306a36Sopenharmony_ci * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 2962306a36Sopenharmony_ci * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 3062306a36Sopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 3162306a36Sopenharmony_ci * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 3262306a36Sopenharmony_ci * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 3362306a36Sopenharmony_ci * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3462306a36Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 3562306a36Sopenharmony_ci * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH 3662306a36Sopenharmony_ci * DAMAGE. 3762306a36Sopenharmony_ci */ 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#ifndef _DRBG_H 4062306a36Sopenharmony_ci#define _DRBG_H 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci#include <linux/random.h> 4462306a36Sopenharmony_ci#include <linux/scatterlist.h> 4562306a36Sopenharmony_ci#include <crypto/hash.h> 4662306a36Sopenharmony_ci#include <crypto/skcipher.h> 4762306a36Sopenharmony_ci#include <linux/module.h> 4862306a36Sopenharmony_ci#include <linux/crypto.h> 4962306a36Sopenharmony_ci#include <linux/slab.h> 5062306a36Sopenharmony_ci#include <crypto/internal/rng.h> 5162306a36Sopenharmony_ci#include <crypto/rng.h> 5262306a36Sopenharmony_ci#include <linux/fips.h> 5362306a36Sopenharmony_ci#include <linux/mutex.h> 5462306a36Sopenharmony_ci#include <linux/list.h> 5562306a36Sopenharmony_ci#include <linux/workqueue.h> 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci/* 5862306a36Sopenharmony_ci * Concatenation Helper and string operation helper 5962306a36Sopenharmony_ci * 6062306a36Sopenharmony_ci * SP800-90A requires the concatenation of different data. To avoid copying 6162306a36Sopenharmony_ci * buffers around or allocate additional memory, the following data structure 6262306a36Sopenharmony_ci * is used to point to the original memory with its size. In addition, it 6362306a36Sopenharmony_ci * is used to build a linked list. The linked list defines the concatenation 6462306a36Sopenharmony_ci * of individual buffers. The order of memory block referenced in that 6562306a36Sopenharmony_ci * linked list determines the order of concatenation. 6662306a36Sopenharmony_ci */ 6762306a36Sopenharmony_cistruct drbg_string { 6862306a36Sopenharmony_ci const unsigned char *buf; 6962306a36Sopenharmony_ci size_t len; 7062306a36Sopenharmony_ci struct list_head list; 7162306a36Sopenharmony_ci}; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_cistatic inline void drbg_string_fill(struct drbg_string *string, 7462306a36Sopenharmony_ci const unsigned char *buf, size_t len) 7562306a36Sopenharmony_ci{ 7662306a36Sopenharmony_ci string->buf = buf; 7762306a36Sopenharmony_ci string->len = len; 7862306a36Sopenharmony_ci INIT_LIST_HEAD(&string->list); 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistruct drbg_state; 8262306a36Sopenharmony_citypedef uint32_t drbg_flag_t; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cistruct drbg_core { 8562306a36Sopenharmony_ci drbg_flag_t flags; /* flags for the cipher */ 8662306a36Sopenharmony_ci __u8 statelen; /* maximum state length */ 8762306a36Sopenharmony_ci __u8 blocklen_bytes; /* block size of output in bytes */ 8862306a36Sopenharmony_ci char cra_name[CRYPTO_MAX_ALG_NAME]; /* mapping to kernel crypto API */ 8962306a36Sopenharmony_ci /* kernel crypto API backend cipher name */ 9062306a36Sopenharmony_ci char backend_cra_name[CRYPTO_MAX_ALG_NAME]; 9162306a36Sopenharmony_ci}; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistruct drbg_state_ops { 9462306a36Sopenharmony_ci int (*update)(struct drbg_state *drbg, struct list_head *seed, 9562306a36Sopenharmony_ci int reseed); 9662306a36Sopenharmony_ci int (*generate)(struct drbg_state *drbg, 9762306a36Sopenharmony_ci unsigned char *buf, unsigned int buflen, 9862306a36Sopenharmony_ci struct list_head *addtl); 9962306a36Sopenharmony_ci int (*crypto_init)(struct drbg_state *drbg); 10062306a36Sopenharmony_ci int (*crypto_fini)(struct drbg_state *drbg); 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci}; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistruct drbg_test_data { 10562306a36Sopenharmony_ci struct drbg_string *testentropy; /* TEST PARAMETER: test entropy */ 10662306a36Sopenharmony_ci}; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_cienum drbg_seed_state { 10962306a36Sopenharmony_ci DRBG_SEED_STATE_UNSEEDED, 11062306a36Sopenharmony_ci DRBG_SEED_STATE_PARTIAL, /* Seeded with !rng_is_initialized() */ 11162306a36Sopenharmony_ci DRBG_SEED_STATE_FULL, 11262306a36Sopenharmony_ci}; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_cistruct drbg_state { 11562306a36Sopenharmony_ci struct mutex drbg_mutex; /* lock around DRBG */ 11662306a36Sopenharmony_ci unsigned char *V; /* internal state 10.1.1.1 1a) */ 11762306a36Sopenharmony_ci unsigned char *Vbuf; 11862306a36Sopenharmony_ci /* hash: static value 10.1.1.1 1b) hmac / ctr: key */ 11962306a36Sopenharmony_ci unsigned char *C; 12062306a36Sopenharmony_ci unsigned char *Cbuf; 12162306a36Sopenharmony_ci /* Number of RNG requests since last reseed -- 10.1.1.1 1c) */ 12262306a36Sopenharmony_ci size_t reseed_ctr; 12362306a36Sopenharmony_ci size_t reseed_threshold; 12462306a36Sopenharmony_ci /* some memory the DRBG can use for its operation */ 12562306a36Sopenharmony_ci unsigned char *scratchpad; 12662306a36Sopenharmony_ci unsigned char *scratchpadbuf; 12762306a36Sopenharmony_ci void *priv_data; /* Cipher handle */ 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci struct crypto_skcipher *ctr_handle; /* CTR mode cipher handle */ 13062306a36Sopenharmony_ci struct skcipher_request *ctr_req; /* CTR mode request handle */ 13162306a36Sopenharmony_ci __u8 *outscratchpadbuf; /* CTR mode output scratchpad */ 13262306a36Sopenharmony_ci __u8 *outscratchpad; /* CTR mode aligned outbuf */ 13362306a36Sopenharmony_ci struct crypto_wait ctr_wait; /* CTR mode async wait obj */ 13462306a36Sopenharmony_ci struct scatterlist sg_in, sg_out; /* CTR mode SGLs */ 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci enum drbg_seed_state seeded; /* DRBG fully seeded? */ 13762306a36Sopenharmony_ci unsigned long last_seed_time; 13862306a36Sopenharmony_ci bool pr; /* Prediction resistance enabled? */ 13962306a36Sopenharmony_ci bool fips_primed; /* Continuous test primed? */ 14062306a36Sopenharmony_ci unsigned char *prev; /* FIPS 140-2 continuous test value */ 14162306a36Sopenharmony_ci struct crypto_rng *jent; 14262306a36Sopenharmony_ci const struct drbg_state_ops *d_ops; 14362306a36Sopenharmony_ci const struct drbg_core *core; 14462306a36Sopenharmony_ci struct drbg_string test_data; 14562306a36Sopenharmony_ci}; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic inline __u8 drbg_statelen(struct drbg_state *drbg) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci if (drbg && drbg->core) 15062306a36Sopenharmony_ci return drbg->core->statelen; 15162306a36Sopenharmony_ci return 0; 15262306a36Sopenharmony_ci} 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_cistatic inline __u8 drbg_blocklen(struct drbg_state *drbg) 15562306a36Sopenharmony_ci{ 15662306a36Sopenharmony_ci if (drbg && drbg->core) 15762306a36Sopenharmony_ci return drbg->core->blocklen_bytes; 15862306a36Sopenharmony_ci return 0; 15962306a36Sopenharmony_ci} 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_cistatic inline __u8 drbg_keylen(struct drbg_state *drbg) 16262306a36Sopenharmony_ci{ 16362306a36Sopenharmony_ci if (drbg && drbg->core) 16462306a36Sopenharmony_ci return (drbg->core->statelen - drbg->core->blocklen_bytes); 16562306a36Sopenharmony_ci return 0; 16662306a36Sopenharmony_ci} 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic inline size_t drbg_max_request_bytes(struct drbg_state *drbg) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci /* SP800-90A requires the limit 2**19 bits, but we return bytes */ 17162306a36Sopenharmony_ci return (1 << 16); 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_cistatic inline size_t drbg_max_addtl(struct drbg_state *drbg) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci /* SP800-90A requires 2**35 bytes additional info str / pers str */ 17762306a36Sopenharmony_ci#if (__BITS_PER_LONG == 32) 17862306a36Sopenharmony_ci /* 17962306a36Sopenharmony_ci * SP800-90A allows smaller maximum numbers to be returned -- we 18062306a36Sopenharmony_ci * return SIZE_MAX - 1 to allow the verification of the enforcement 18162306a36Sopenharmony_ci * of this value in drbg_healthcheck_sanity. 18262306a36Sopenharmony_ci */ 18362306a36Sopenharmony_ci return (SIZE_MAX - 1); 18462306a36Sopenharmony_ci#else 18562306a36Sopenharmony_ci return (1UL<<35); 18662306a36Sopenharmony_ci#endif 18762306a36Sopenharmony_ci} 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_cistatic inline size_t drbg_max_requests(struct drbg_state *drbg) 19062306a36Sopenharmony_ci{ 19162306a36Sopenharmony_ci /* SP800-90A requires 2**48 maximum requests before reseeding */ 19262306a36Sopenharmony_ci return (1<<20); 19362306a36Sopenharmony_ci} 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci/* 19662306a36Sopenharmony_ci * This is a wrapper to the kernel crypto API function of 19762306a36Sopenharmony_ci * crypto_rng_generate() to allow the caller to provide additional data. 19862306a36Sopenharmony_ci * 19962306a36Sopenharmony_ci * @drng DRBG handle -- see crypto_rng_get_bytes 20062306a36Sopenharmony_ci * @outbuf output buffer -- see crypto_rng_get_bytes 20162306a36Sopenharmony_ci * @outlen length of output buffer -- see crypto_rng_get_bytes 20262306a36Sopenharmony_ci * @addtl_input additional information string input buffer 20362306a36Sopenharmony_ci * @addtllen length of additional information string buffer 20462306a36Sopenharmony_ci * 20562306a36Sopenharmony_ci * return 20662306a36Sopenharmony_ci * see crypto_rng_get_bytes 20762306a36Sopenharmony_ci */ 20862306a36Sopenharmony_cistatic inline int crypto_drbg_get_bytes_addtl(struct crypto_rng *drng, 20962306a36Sopenharmony_ci unsigned char *outbuf, unsigned int outlen, 21062306a36Sopenharmony_ci struct drbg_string *addtl) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci return crypto_rng_generate(drng, addtl->buf, addtl->len, 21362306a36Sopenharmony_ci outbuf, outlen); 21462306a36Sopenharmony_ci} 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci/* 21762306a36Sopenharmony_ci * TEST code 21862306a36Sopenharmony_ci * 21962306a36Sopenharmony_ci * This is a wrapper to the kernel crypto API function of 22062306a36Sopenharmony_ci * crypto_rng_generate() to allow the caller to provide additional data and 22162306a36Sopenharmony_ci * allow furnishing of test_data 22262306a36Sopenharmony_ci * 22362306a36Sopenharmony_ci * @drng DRBG handle -- see crypto_rng_get_bytes 22462306a36Sopenharmony_ci * @outbuf output buffer -- see crypto_rng_get_bytes 22562306a36Sopenharmony_ci * @outlen length of output buffer -- see crypto_rng_get_bytes 22662306a36Sopenharmony_ci * @addtl_input additional information string input buffer 22762306a36Sopenharmony_ci * @addtllen length of additional information string buffer 22862306a36Sopenharmony_ci * @test_data filled test data 22962306a36Sopenharmony_ci * 23062306a36Sopenharmony_ci * return 23162306a36Sopenharmony_ci * see crypto_rng_get_bytes 23262306a36Sopenharmony_ci */ 23362306a36Sopenharmony_cistatic inline int crypto_drbg_get_bytes_addtl_test(struct crypto_rng *drng, 23462306a36Sopenharmony_ci unsigned char *outbuf, unsigned int outlen, 23562306a36Sopenharmony_ci struct drbg_string *addtl, 23662306a36Sopenharmony_ci struct drbg_test_data *test_data) 23762306a36Sopenharmony_ci{ 23862306a36Sopenharmony_ci crypto_rng_set_entropy(drng, test_data->testentropy->buf, 23962306a36Sopenharmony_ci test_data->testentropy->len); 24062306a36Sopenharmony_ci return crypto_rng_generate(drng, addtl->buf, addtl->len, 24162306a36Sopenharmony_ci outbuf, outlen); 24262306a36Sopenharmony_ci} 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci/* 24562306a36Sopenharmony_ci * TEST code 24662306a36Sopenharmony_ci * 24762306a36Sopenharmony_ci * This is a wrapper to the kernel crypto API function of 24862306a36Sopenharmony_ci * crypto_rng_reset() to allow the caller to provide test_data 24962306a36Sopenharmony_ci * 25062306a36Sopenharmony_ci * @drng DRBG handle -- see crypto_rng_reset 25162306a36Sopenharmony_ci * @pers personalization string input buffer 25262306a36Sopenharmony_ci * @perslen length of additional information string buffer 25362306a36Sopenharmony_ci * @test_data filled test data 25462306a36Sopenharmony_ci * 25562306a36Sopenharmony_ci * return 25662306a36Sopenharmony_ci * see crypto_rng_reset 25762306a36Sopenharmony_ci */ 25862306a36Sopenharmony_cistatic inline int crypto_drbg_reset_test(struct crypto_rng *drng, 25962306a36Sopenharmony_ci struct drbg_string *pers, 26062306a36Sopenharmony_ci struct drbg_test_data *test_data) 26162306a36Sopenharmony_ci{ 26262306a36Sopenharmony_ci crypto_rng_set_entropy(drng, test_data->testentropy->buf, 26362306a36Sopenharmony_ci test_data->testentropy->len); 26462306a36Sopenharmony_ci return crypto_rng_reset(drng, pers->buf, pers->len); 26562306a36Sopenharmony_ci} 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci/* DRBG type flags */ 26862306a36Sopenharmony_ci#define DRBG_CTR ((drbg_flag_t)1<<0) 26962306a36Sopenharmony_ci#define DRBG_HMAC ((drbg_flag_t)1<<1) 27062306a36Sopenharmony_ci#define DRBG_HASH ((drbg_flag_t)1<<2) 27162306a36Sopenharmony_ci#define DRBG_TYPE_MASK (DRBG_CTR | DRBG_HMAC | DRBG_HASH) 27262306a36Sopenharmony_ci/* DRBG strength flags */ 27362306a36Sopenharmony_ci#define DRBG_STRENGTH128 ((drbg_flag_t)1<<3) 27462306a36Sopenharmony_ci#define DRBG_STRENGTH192 ((drbg_flag_t)1<<4) 27562306a36Sopenharmony_ci#define DRBG_STRENGTH256 ((drbg_flag_t)1<<5) 27662306a36Sopenharmony_ci#define DRBG_STRENGTH_MASK (DRBG_STRENGTH128 | DRBG_STRENGTH192 | \ 27762306a36Sopenharmony_ci DRBG_STRENGTH256) 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_cienum drbg_prefixes { 28062306a36Sopenharmony_ci DRBG_PREFIX0 = 0x00, 28162306a36Sopenharmony_ci DRBG_PREFIX1, 28262306a36Sopenharmony_ci DRBG_PREFIX2, 28362306a36Sopenharmony_ci DRBG_PREFIX3 28462306a36Sopenharmony_ci}; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci#endif /* _DRBG_H */ 287