1 /**
2  * \file hmac_drbg.h
3  *
4  * \brief HMAC_DRBG (NIST SP 800-90A)
5  */
6 /*
7  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
8  *  SPDX-License-Identifier: Apache-2.0
9  *
10  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
11  *  not use this file except in compliance with the License.
12  *  You may obtain a copy of the License at
13  *
14  *  http://www.apache.org/licenses/LICENSE-2.0
15  *
16  *  Unless required by applicable law or agreed to in writing, software
17  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
18  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  *  See the License for the specific language governing permissions and
20  *  limitations under the License.
21  *
22  *  This file is part of mbed TLS (https://tls.mbed.org)
23  */
24 #ifndef MBEDTLS_HMAC_DRBG_H
25 #define MBEDTLS_HMAC_DRBG_H
26 
27 #include "md.h"
28 
29 #if defined(MBEDTLS_THREADING_C)
30 #include "threading.h"
31 #endif
32 
33 /*
34  * Error codes
35  */
36 #define MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG              -0x0003  /**< Too many random requested in single call. */
37 #define MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG                -0x0005  /**< Input too large (Entropy + additional). */
38 #define MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR                -0x0007  /**< Read/write error in file. */
39 #define MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED        -0x0009  /**< The entropy source failed. */
40 
41 /**
42  * \name SECTION: Module settings
43  *
44  * The configuration options you can set for this module are in this section.
45  * Either change them in config.h or define them on the compiler command line.
46  * \{
47  */
48 
49 #if !defined(MBEDTLS_HMAC_DRBG_RESEED_INTERVAL)
50 #define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL   10000   /**< Interval before reseed is performed by default */
51 #endif
52 
53 #if !defined(MBEDTLS_HMAC_DRBG_MAX_INPUT)
54 #define MBEDTLS_HMAC_DRBG_MAX_INPUT         256     /**< Maximum number of additional input bytes */
55 #endif
56 
57 #if !defined(MBEDTLS_HMAC_DRBG_MAX_REQUEST)
58 #define MBEDTLS_HMAC_DRBG_MAX_REQUEST       1024    /**< Maximum number of requested bytes per call */
59 #endif
60 
61 #if !defined(MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT)
62 #define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT    384     /**< Maximum size of (re)seed buffer */
63 #endif
64 
65 /* \} name SECTION: Module settings */
66 
67 #define MBEDTLS_HMAC_DRBG_PR_OFF   0   /**< No prediction resistance       */
68 #define MBEDTLS_HMAC_DRBG_PR_ON    1   /**< Prediction resistance enabled  */
69 
70 #ifdef __cplusplus
71 extern "C" {
72 #endif
73 
74 /**
75  * HMAC_DRBG context.
76  */
77 typedef struct mbedtls_hmac_drbg_context
78 {
79     /* Working state: the key K is not stored explicitely,
80      * but is implied by the HMAC context */
81     mbedtls_md_context_t md_ctx;                    /*!< HMAC context (inc. K)  */
82     unsigned char V[MBEDTLS_MD_MAX_SIZE];  /*!< V in the spec          */
83     int reseed_counter;                     /*!< reseed counter         */
84 
85     /* Administrative state */
86     size_t entropy_len;         /*!< entropy bytes grabbed on each (re)seed */
87     int prediction_resistance;  /*!< enable prediction resistance (Automatic
88                                      reseed before every random generation) */
89     int reseed_interval;        /*!< reseed interval   */
90 
91     /* Callbacks */
92     int (*f_entropy)(void *, unsigned char *, size_t); /*!< entropy function */
93     void *p_entropy;            /*!< context for the entropy function        */
94 
95 #if defined(MBEDTLS_THREADING_C)
96     mbedtls_threading_mutex_t mutex;
97 #endif
98 } mbedtls_hmac_drbg_context;
99 
100 /**
101  * \brief               HMAC_DRBG context initialization
102  *                      Makes the context ready for mbedtls_hmac_drbg_seed(),
103  *                      mbedtls_hmac_drbg_seed_buf() or
104  *                      mbedtls_hmac_drbg_free().
105  *
106  * \param ctx           HMAC_DRBG context to be initialized
107  */
108 void mbedtls_hmac_drbg_init( mbedtls_hmac_drbg_context *ctx );
109 
110 /**
111  * \brief               HMAC_DRBG initial seeding
112  *                      Seed and setup entropy source for future reseeds.
113  *
114  * \param ctx           HMAC_DRBG context to be seeded
115  * \param md_info       MD algorithm to use for HMAC_DRBG
116  * \param f_entropy     Entropy callback (p_entropy, buffer to fill, buffer
117  *                      length)
118  * \param p_entropy     Entropy context
119  * \param custom        Personalization data (Device specific identifiers)
120  *                      (Can be NULL)
121  * \param len           Length of personalization data
122  *
123  * \note                The "security strength" as defined by NIST is set to:
124  *                      128 bits if md_alg is SHA-1,
125  *                      192 bits if md_alg is SHA-224,
126  *                      256 bits if md_alg is SHA-256 or higher.
127  *                      Note that SHA-256 is just as efficient as SHA-224.
128  *
129  * \return              0 if successful, or
130  *                      MBEDTLS_ERR_MD_BAD_INPUT_DATA, or
131  *                      MBEDTLS_ERR_MD_ALLOC_FAILED, or
132  *                      MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED.
133  */
134 int mbedtls_hmac_drbg_seed( mbedtls_hmac_drbg_context *ctx,
135                     const mbedtls_md_info_t * md_info,
136                     int (*f_entropy)(void *, unsigned char *, size_t),
137                     void *p_entropy,
138                     const unsigned char *custom,
139                     size_t len );
140 
141 /**
142  * \brief               Initilisation of simpified HMAC_DRBG (never reseeds).
143  *                      (For use with deterministic ECDSA.)
144  *
145  * \param ctx           HMAC_DRBG context to be initialised
146  * \param md_info       MD algorithm to use for HMAC_DRBG
147  * \param data          Concatenation of entropy string and additional data
148  * \param data_len      Length of data in bytes
149  *
150  * \return              0 if successful, or
151  *                      MBEDTLS_ERR_MD_BAD_INPUT_DATA, or
152  *                      MBEDTLS_ERR_MD_ALLOC_FAILED.
153  */
154 int mbedtls_hmac_drbg_seed_buf( mbedtls_hmac_drbg_context *ctx,
155                         const mbedtls_md_info_t * md_info,
156                         const unsigned char *data, size_t data_len );
157 
158 /**
159  * \brief               Enable / disable prediction resistance (Default: Off)
160  *
161  * Note: If enabled, entropy is used for ctx->entropy_len before each call!
162  *       Only use this if you have ample supply of good entropy!
163  *
164  * \param ctx           HMAC_DRBG context
165  * \param resistance    MBEDTLS_HMAC_DRBG_PR_ON or MBEDTLS_HMAC_DRBG_PR_OFF
166  */
167 void mbedtls_hmac_drbg_set_prediction_resistance( mbedtls_hmac_drbg_context *ctx,
168                                           int resistance );
169 
170 /**
171  * \brief               Set the amount of entropy grabbed on each reseed
172  *                      (Default: given by the security strength, which
173  *                      depends on the hash used, see \c mbedtls_hmac_drbg_init() )
174  *
175  * \param ctx           HMAC_DRBG context
176  * \param len           Amount of entropy to grab, in bytes
177  */
178 void mbedtls_hmac_drbg_set_entropy_len( mbedtls_hmac_drbg_context *ctx,
179                                 size_t len );
180 
181 /**
182  * \brief               Set the reseed interval
183  *                      (Default: MBEDTLS_HMAC_DRBG_RESEED_INTERVAL)
184  *
185  * \param ctx           HMAC_DRBG context
186  * \param interval      Reseed interval
187  */
188 void mbedtls_hmac_drbg_set_reseed_interval( mbedtls_hmac_drbg_context *ctx,
189                                     int interval );
190 
191 /**
192  * \brief               HMAC_DRBG update state
193  *
194  * \param ctx           HMAC_DRBG context
195  * \param additional    Additional data to update state with, or NULL
196  * \param add_len       Length of additional data, or 0
197  *
198  * \return              \c 0 on success, or an error from the underlying
199  *                      hash calculation.
200  *
201  * \note                Additional data is optional, pass NULL and 0 as second
202  *                      third argument if no additional data is being used.
203  */
204 int mbedtls_hmac_drbg_update_ret( mbedtls_hmac_drbg_context *ctx,
205                        const unsigned char *additional, size_t add_len );
206 
207 /**
208  * \brief               HMAC_DRBG reseeding (extracts data from entropy source)
209  *
210  * \param ctx           HMAC_DRBG context
211  * \param additional    Additional data to add to state (Can be NULL)
212  * \param len           Length of additional data
213  *
214  * \return              0 if successful, or
215  *                      MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
216  */
217 int mbedtls_hmac_drbg_reseed( mbedtls_hmac_drbg_context *ctx,
218                       const unsigned char *additional, size_t len );
219 
220 /**
221  * \brief               HMAC_DRBG generate random with additional update input
222  *
223  * Note: Automatically reseeds if reseed_counter is reached or PR is enabled.
224  *
225  * \param p_rng         HMAC_DRBG context
226  * \param output        Buffer to fill
227  * \param output_len    Length of the buffer
228  * \param additional    Additional data to update with (can be NULL)
229  * \param add_len       Length of additional data (can be 0)
230  *
231  * \return              0 if successful, or
232  *                      MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or
233  *                      MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG, or
234  *                      MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG.
235  */
236 int mbedtls_hmac_drbg_random_with_add( void *p_rng,
237                                unsigned char *output, size_t output_len,
238                                const unsigned char *additional,
239                                size_t add_len );
240 
241 /**
242  * \brief               HMAC_DRBG generate random
243  *
244  * Note: Automatically reseeds if reseed_counter is reached or PR is enabled.
245  *
246  * \param p_rng         HMAC_DRBG context
247  * \param output        Buffer to fill
248  * \param out_len       Length of the buffer
249  *
250  * \return              0 if successful, or
251  *                      MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED, or
252  *                      MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG
253  */
254 int mbedtls_hmac_drbg_random( void *p_rng, unsigned char *output, size_t out_len );
255 
256 /**
257  * \brief               Free an HMAC_DRBG context
258  *
259  * \param ctx           HMAC_DRBG context to free.
260  */
261 void mbedtls_hmac_drbg_free( mbedtls_hmac_drbg_context *ctx );
262 
263 #if ! defined(MBEDTLS_DEPRECATED_REMOVED)
264 #if defined(MBEDTLS_DEPRECATED_WARNING)
265 #define MBEDTLS_DEPRECATED    __attribute__((deprecated))
266 #else
267 #define MBEDTLS_DEPRECATED
268 #endif
269 /**
270  * \brief               HMAC_DRBG update state
271  *
272  * \deprecated          Superseded by mbedtls_hmac_drbg_update_ret()
273  *                      in 2.16.0.
274  *
275  * \param ctx           HMAC_DRBG context
276  * \param additional    Additional data to update state with, or NULL
277  * \param add_len       Length of additional data, or 0
278  *
279  * \note                Additional data is optional, pass NULL and 0 as second
280  *                      third argument if no additional data is being used.
281  */
282 MBEDTLS_DEPRECATED void mbedtls_hmac_drbg_update(
283     mbedtls_hmac_drbg_context *ctx,
284     const unsigned char *additional, size_t add_len );
285 #undef MBEDTLS_DEPRECATED
286 #endif /* !MBEDTLS_DEPRECATED_REMOVED */
287 
288 #if defined(MBEDTLS_FS_IO)
289 /**
290  * \brief               Write a seed file
291  *
292  * \param ctx           HMAC_DRBG context
293  * \param path          Name of the file
294  *
295  * \return              0 if successful, 1 on file error, or
296  *                      MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED
297  */
298 int mbedtls_hmac_drbg_write_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path );
299 
300 /**
301  * \brief               Read and update a seed file. Seed is added to this
302  *                      instance
303  *
304  * \param ctx           HMAC_DRBG context
305  * \param path          Name of the file
306  *
307  * \return              0 if successful, 1 on file error,
308  *                      MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED or
309  *                      MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG
310  */
311 int mbedtls_hmac_drbg_update_seed_file( mbedtls_hmac_drbg_context *ctx, const char *path );
312 #endif /* MBEDTLS_FS_IO */
313 
314 
315 #if defined(MBEDTLS_SELF_TEST)
316 /**
317  * \brief               Checkup routine
318  *
319  * \return              0 if successful, or 1 if the test failed
320  */
321 int mbedtls_hmac_drbg_self_test( int verbose );
322 #endif
323 
324 #ifdef __cplusplus
325 }
326 #endif
327 
328 #endif /* hmac_drbg.h */
329