1 /* hmac_prng.h - TinyCrypt interface to an HMAC-PRNG implementation */
2 
3 /*
4  *  Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
5  *
6  *  Redistribution and use in source and binary forms, with or without
7  *  modification, are permitted provided that the following conditions are met:
8  *
9  *    - Redistributions of source code must retain the above copyright notice,
10  *     this list of conditions and the following disclaimer.
11  *
12  *    - Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  *    - Neither the name of Intel Corporation nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  *  POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 /**
34  * @file
35  * @brief Interface to an HMAC-PRNG implementation.
36  *
37  *  Overview:   A pseudo-random number generator (PRNG) generates a sequence
38  *              of numbers that have a distribution close to the one expected
39  *              for a sequence of truly random numbers. The NIST Special
40  *              Publication 800-90A specifies several mechanisms to generate
41  *              sequences of pseudo random numbers, including the HMAC-PRNG one
42  *              which is based on HMAC. TinyCrypt implements HMAC-PRNG with
43  *              certain modifications from the NIST SP 800-90A spec.
44  *
45  *  Security:   A cryptographically secure PRNG depends on the existence of an
46  *              entropy source to provide a truly random seed as well as the
47  *              security of the primitives used as the building blocks (HMAC and
48  *              SHA256, for TinyCrypt).
49  *
50  *              The NIST SP 800-90A standard tolerates a null personalization,
51  *              while TinyCrypt requires a non-null personalization. This is
52  *              because a personalization string (the host name concatenated
53  *              with a time stamp, for example) is easily computed and might be
54  *              the last line of defense against failure of the entropy source.
55  *
56  *  Requires:   - SHA-256
57  *              - HMAC
58  *
59  *  Usage:      1) call tc_hmac_prng_init to set the HMAC key and process the
60  *              personalization data.
61  *
62  *              2) call tc_hmac_prng_reseed to process the seed and additional
63  *              input.
64  *
65  *              3) call tc_hmac_prng_generate to out put the pseudo-random data.
66  */
67 
68 #ifndef __TC_HMAC_PRNG_H__
69 #define __TC_HMAC_PRNG_H__
70 
71 #include <tinycrypt/sha256.h>
72 #include <tinycrypt/hmac.h>
73 
74 #ifdef __cplusplus
75 extern "C" {
76 #endif
77 
78 #define TC_HMAC_PRNG_RESEED_REQ -1
79 
80 struct tc_hmac_prng_struct {
81 	/* the HMAC instance for this PRNG */
82 	struct tc_hmac_state_struct h;
83 	/* the PRNG key */
84 	uint8_t key[TC_SHA256_DIGEST_SIZE];
85 	/* PRNG state */
86 	uint8_t v[TC_SHA256_DIGEST_SIZE];
87 	/* calls to tc_hmac_prng_generate left before re-seed */
88 	unsigned int countdown;
89 };
90 
91 typedef struct tc_hmac_prng_struct *TCHmacPrng_t;
92 
93 /**
94  *  @brief HMAC-PRNG initialization procedure
95  *  Initializes prng with personalization, disables tc_hmac_prng_generate
96  *  @return returns TC_CRYPTO_SUCCESS (1)
97  *          returns TC_CRYPTO_FAIL (0) if:
98  *                prng == NULL,
99  *                personalization == NULL,
100  *                plen > MAX_PLEN
101  *  @note Assumes: - personalization != NULL.
102  *              The personalization is a platform unique string (e.g., the host
103  *              name) and is the last line of defense against failure of the
104  *              entropy source
105  *  @warning    NIST SP 800-90A specifies 3 items as seed material during
106  *              initialization: entropy seed, personalization, and an optional
107  *              nonce. TinyCrypts requires instead a non-null personalization
108  *              (which is easily computed) and indirectly requires an entropy
109  *              seed (since the reseed function is mandatorily called after
110  *              init)
111  *  @param prng IN/OUT -- the PRNG state to initialize
112  *  @param personalization IN -- personalization string
113  *  @param plen IN -- personalization length in bytes
114  */
115 int tc_hmac_prng_init(TCHmacPrng_t prng,
116 		      const uint8_t *personalization,
117 		      unsigned int plen);
118 
119 /**
120  *  @brief HMAC-PRNG reseed procedure
121  *  Mixes seed into prng, enables tc_hmac_prng_generate
122  *  @return returns  TC_CRYPTO_SUCCESS (1)
123  *  	    returns TC_CRYPTO_FAIL (0) if:
124  *          prng == NULL,
125  *          seed == NULL,
126  *          seedlen < MIN_SLEN,
127  *          seendlen > MAX_SLEN,
128  *          additional_input != (const uint8_t *) 0 && additionallen == 0,
129  *          additional_input != (const uint8_t *) 0 && additionallen > MAX_ALEN
130  *  @note Assumes:- tc_hmac_prng_init has been called for prng
131  *              - seed has sufficient entropy.
132  *
133  *  @param prng IN/OUT -- the PRNG state
134  *  @param seed IN -- entropy to mix into the prng
135  *  @param seedlen IN -- length of seed in bytes
136  *  @param additional_input IN -- additional input to the prng
137  *  @param additionallen IN -- additional input length in bytes
138  */
139 int tc_hmac_prng_reseed(TCHmacPrng_t prng, const uint8_t *seed,
140 			unsigned int seedlen, const uint8_t *additional_input,
141 			unsigned int additionallen);
142 
143 /**
144  *  @brief HMAC-PRNG generate procedure
145  *  Generates outlen pseudo-random bytes into out buffer, updates prng
146  *  @return returns TC_CRYPTO_SUCCESS (1)
147  *          returns TC_HMAC_PRNG_RESEED_REQ (-1) if a reseed is needed
148  *          returns TC_CRYPTO_FAIL (0) if:
149  *                out == NULL,
150  *                prng == NULL,
151  *                outlen == 0,
152  *                outlen >= MAX_OUT
153  *  @note Assumes tc_hmac_prng_init has been called for prng
154  *  @param out IN/OUT -- buffer to receive output
155  *  @param outlen IN -- size of out buffer in bytes
156  *  @param prng IN/OUT -- the PRNG state
157  */
158 int tc_hmac_prng_generate(uint8_t *out, unsigned int outlen, TCHmacPrng_t prng);
159 
160 #ifdef __cplusplus
161 }
162 #endif
163 
164 #endif /* __TC_HMAC_PRNG_H__ */
165