MPHELL  4.0.0
mphell-drbg.c
Go to the documentation of this file.
1 /*
2  MPHELL-4.0
3  Author(s): The MPHELL team
4 
5  (C) Copyright 2015-2018 - Institut Fourier / Univ. Grenoble Alpes (France)
6 
7  This file is part of the MPHELL Library.
8  MPHELL is free software: you can redistribute it and/or modify
9  it under the terms of the GNU Lesser General Public License as published by
10  the Free Software Foundation, version 3 of the License.
11 
12  MPHELL is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public License
18  along with MPHELL. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
26 #include "mphell-drbg.h"
27 
28 /* The DRBG internal state shall exist solely within the DRBG mechanism boundary.
29  * The internal state shall not be accessible by non-DRBG functions or other instantiations of that or other DRBGs
30  */
31 static drbg_internal_state drbg_internal_states[DRBG_MAX_INTERNAL_STATES];
32 
40 {
41  uint8_t i;
42 
43  for(i = 0; i < DRBG_MAX_INTERNAL_STATES; i++)
44  {
45  if(drbg_internal_states[i]->type == DRBG_UNSET)
46  {
47  return i;
48  }
49  }
50  return -1;
51 }
52 
53 
61 {
62  int16_t highest_supported_security_strength;
63 
64  switch(type)
65  {
66  case DRBG_SHA1 :
67  highest_supported_security_strength = 128;
68  break;
69 
70  case DRBG_SHA256 :
71  highest_supported_security_strength = 256;
72  break;
73 
74  case DRBG_AES128 :
75  highest_supported_security_strength = 128;
76  break;
77 
78  case DRBG_AES192 :
79  highest_supported_security_strength = 192;
80  break;
81 
82  case DRBG_AES256 :
83  highest_supported_security_strength = 256;
84  break;
85 
86  default :
87  highest_supported_security_strength = -1;
88 
89  }
90 
91  return highest_supported_security_strength;
92 }
93 
94 void
95 drbg_instantiate(mphell_status ret, int8_t *state_handle,
96  const uint16_t requested_instantiation_security_strength,
97  const drbg_type type, const entropy_type entropy_src, uint64_t reseed_interval,
98  const uint8_t * entropy, const uint16_t entropy_length,
99  const uint8_t * nonce, const uint16_t nonce_length,
100  const uint8_t* personalization_string, const uint64_t pers_length)
101 {
102  uint8_t security_strength;
103  int8_t handle = -1;
104  uint8_t *entropy_input = NULL;
105 
106  /* Check the validity of input parameters */
107 
108  if(type == DRBG_UNSET)
109  {
110  ret->flag = MPHELL_ERROR_RANDOM;
111  char *text = "drbg_instantiate : Invalid DRBG type specified";
112  ret->info = malloc(strlen(text));
113  memcpy(ret->info, text, strlen(text));
114  return;
115  }
116 
117  if(requested_instantiation_security_strength > (entropy_length * 8))
118  {
119  ret->flag = MPHELL_ERROR_RANDOM;
120  char *text = "drbg_instantiate : Requested security_strength is \
121  greater than the provided entropy";
122  ret->info = malloc(strlen(text));
123  memcpy(ret->info, text, strlen(text));
124  return;
125  }
126 
127  if(requested_instantiation_security_strength >
129  {
130  ret->flag = MPHELL_ERROR_RANDOM;
131  char *text = "drbg_instantiate : Requested security_strength is \
132  greater than the highest security strength supported \
133  by the drbg type specified";
134  ret->info = malloc(strlen(text));
135  memcpy(ret->info, text, strlen(text));
136  return;
137  }
138 
139  if(pers_length > DRBG_MAX_PERSONALIZATION_STRING_LENGTH)
140  {
141  ret->flag = MPHELL_ERROR_RANDOM;
142  char *text = "drbg_instantiate : The length of the personalization \
143  string is too big";
144  ret->info = malloc(strlen(text));
145  memcpy(ret->info, text, strlen(text));
146  return;
147  }
148 
149 
150  if((reseed_interval > DRBG_MAX_RESEED_INTERVAL) || (reseed_interval == 0))
151  {
152  ret->flag = MPHELL_ERROR_RANDOM;
153  char *text = "drbg_instantiate : The reseed interval must be 1 <= reseed_interval <= DRBG_MAX_RESEED_INTERVAL";
154  ret->info = malloc(strlen(text));
155  memcpy(ret->info, text, strlen(text));
156  return;
157  }
158 
159  /* Check the avialability of an empty internal state */
160 
161  handle = drbg_find_empty_state();
162  if(handle == -1)
163  {
164  ret->flag = MPHELL_ERROR_RANDOM;
165  char *text = "drbg_instantiate : There is no available empty \
166  internal state";
167  ret->info = malloc(strlen(text));
168  memcpy(ret->info, text, strlen(text));
169  return;
170  }
171 
172  /* Set security_strength to the lowest security_strength greater than equal
173  * to requested_instantiation_security_strength from the set
174  * {112, 128, 192, 256} */
175 
176  if(requested_instantiation_security_strength > 192)
177  {
178  security_strength = 256 / 8;
179  }
180  else if(requested_instantiation_security_strength > 128)
181  {
182  security_strength = 192 / 8;
183  }
184  else if(requested_instantiation_security_strength > 112)
185  {
186  security_strength = 128 / 8;
187  }
188  else
189  {
190  security_strength = 112 / 8;
191  }
192 
193  /* Set predefined entropy and nonce for drbg test. Never use for random application !!! */
194  entropy_input = malloc(entropy_length + nonce_length);
195 
196  memcpy(entropy_input, entropy, entropy_length);
197  memcpy(entropy_input + entropy_length, nonce, nonce_length);
198 
199  drbg_internal_states[handle]->entropy_src = entropy_src;
200 
201  /* Call appropriate instantiation algorithm */
202 
203  switch(type)
204  {
205  case DRBG_SHA1 :
206  case DRBG_SHA256 :
207  hash_drbg_instantiate(ret, drbg_internal_states[handle],
208  security_strength, entropy_input, entropy_length + nonce_length,
209  personalization_string, pers_length, type);
210  break;
211 
212  case DRBG_AES128 :
213  case DRBG_AES192 :
214  case DRBG_AES256 :
215  ctr_drbg_instantiate(ret, drbg_internal_states[handle],
216  security_strength, entropy_input, entropy_length + nonce_length,
217  personalization_string, pers_length, type);
218  break;
219  default :
220  ret->flag = MPHELL_ERROR_RANDOM;
221  char *text = "drbg_instantiate : Invalid drbg type, only \
222  supported DRBG_SHA1, DRBG_SHA256, DRBG_AES128, DRBG_AES192,\
223  DRBG_AES256";
224  ret->info = malloc(strlen(text));
225  memcpy(ret->info, text, strlen(text));
226  }
227  if(entropy_input != NULL)
228  {
229  free(entropy_input);
230  }
231  if(ret->flag == MPHELL_SUCCESS)
232  {
233  *state_handle = handle;
234  drbg_internal_states[handle]->type = type;
235  drbg_internal_states[handle]->info->security_strength =
236  security_strength;
237  drbg_internal_states[handle]->info->reseed_interval =
238  reseed_interval;
239  }
240 }
241 
242 void
243 drbg_reseed(mphell_status ret, const int8_t state_handle,
244  const uint8_t * entropy, const uint16_t entropy_length,
245  const uint8_t* additional_input, const uint64_t add_length)
246 {
247  /* Get the current internal state */
248 
249  if((state_handle < 0) || (state_handle > DRBG_MAX_INTERNAL_STATES) ||
250  ((drbg_internal_states[state_handle])->type == DRBG_UNSET))
251  {
252  ret->flag = MPHELL_ERROR_RANDOM;
253  char *text = "drbg_reseed : Invalid state handle specified";
254  ret->info = malloc(strlen(text));
255  memcpy(ret->info, text, strlen(text));
256  return;
257  }
258 
259  drbg_internal_state_t *internal_state = drbg_internal_states[state_handle];
260 
261  /* Check the input parameters */
262 
263  if(internal_state->info->security_strength > entropy_length)
264  {
265  ret->flag = MPHELL_ERROR_RANDOM;
266  char *text = "drbg_reseed : security_strength is \
267  greater than the provided entropy";
268  ret->info = malloc(strlen(text));
269  memcpy(ret->info, text, strlen(text));
270  return;
271  }
272 
273  if(additional_input != NULL &&
274  (add_length > DRBG_MAX_ADDITIONAL_INPUT_LENGTH))
275  {
276  ret->flag = MPHELL_ERROR_RANDOM;
277  char *text = "drbg_reseed : The length of the additional_input \
278  string is too big";
279  ret->info = malloc(strlen(text));
280  memcpy(ret->info, text, strlen(text));
281  return;
282  }
283 
284  /* Call appropriate reseed algorithm */
285 
286  switch(internal_state->type)
287  {
288  case DRBG_SHA1 :
289  case DRBG_SHA256 :
290  hash_drbg_reseed(ret, internal_state, entropy, entropy_length,
291  additional_input, add_length);
292  break;
293 
294  case DRBG_AES128 :
295  case DRBG_AES192 :
296  case DRBG_AES256 :
297  ctr_drbg_reseed(ret, internal_state, entropy, entropy_length,
298  additional_input, add_length);
299  break;
300 
301  default :
302  ret->flag = MPHELL_ERROR_RANDOM;
303  char *text = "drbg_reseed : Invalid drbg type, only \
304  supported DRBG_SHA1, DRBG_SHA256, DRBG_AES128, DRBG_AES192,\
305  DRBG_AES256";
306  ret->info = malloc(strlen(text));
307  memcpy(ret->info, text, strlen(text));
308  }
309 }
310 
311 void drbg_generate(mphell_status ret, uint8_t* returned_bytes,
312  const int8_t state_handle, const uint32_t requested_number_of_bytes,
313  const uint16_t requested_security_strength,
314  const uint8_t* additional_input, const uint64_t add_length)
315 {
316  /* Get the current internal state */
317 
318  if((state_handle < 0) || (state_handle > DRBG_MAX_INTERNAL_STATES) ||
319  ((drbg_internal_states[state_handle])->type == DRBG_UNSET))
320  {
321  ret->flag = MPHELL_ERROR_RANDOM;
322  char *text = "drbg_generate : Invalid state handle specified";
323  ret->info = malloc(strlen(text));
324  memcpy(ret->info, text, strlen(text));
325  return;
326  }
327 
328  drbg_internal_state_t *internal_state = drbg_internal_states[state_handle];
329 
330  /* Check the input parameters */
331 
332  if(requested_number_of_bytes > DRBG_MAX_NUMBER_OF_BYTES_PER_REQUEST)
333  {
334  ret->flag = MPHELL_ERROR_RANDOM;
335  char *text = "drbg_generate : requested_number_of bytes is greater \
336  than DRBG_MAX_NUMBER_OF_BYTES_PER_REQUEST";
337  ret->info = malloc(strlen(text));
338  memcpy(ret->info, text, strlen(text));
339  return;
340  }
341 
342  if((requested_security_strength / 8) >
343  internal_state->info->security_strength)
344  {
345  ret->flag = MPHELL_ERROR_RANDOM;
346  char *text = "drbg_generate : requested_security_strength is greater \
347  than security strength specified in internal state";
348  ret->info = malloc(strlen(text));
349  memcpy(ret->info, text, strlen(text));
350  return;
351  }
352 
353  if(additional_input != NULL &&
354  (add_length > DRBG_MAX_ADDITIONAL_INPUT_LENGTH))
355  {
356  ret->flag = MPHELL_ERROR_RANDOM;
357  char *text = "drbg_generate : The length of the additional_input \
358  string is too big";
359  ret->info = malloc(strlen(text));
360  memcpy(ret->info, text, strlen(text));
361  return;
362  }
363 
364  /* Call appropriate generate algorithm */
365 
366  switch(internal_state->type)
367  {
368  case DRBG_SHA1 :
369  case DRBG_SHA256 :
370  hash_drbg_generate(ret, returned_bytes, internal_state,
371  requested_number_of_bytes, additional_input, add_length);
372  break;
373 
374  case DRBG_AES128 :
375  case DRBG_AES192 :
376  case DRBG_AES256 :
377  ctr_drbg_generate(ret, returned_bytes, internal_state,
378  requested_number_of_bytes, additional_input, add_length);
379  break;
380 
381  default:
382  ret->flag = MPHELL_ERROR_RANDOM;
383  char *text = "drbg_generate : Invalid drbg type, only \
384  supported DRBG_SHA1, DRBG_SHA256, DRBG_AES128, DRBG_AES192,\
385  DRBG_AES256";
386  ret->info = malloc(strlen(text));
387  memcpy(ret->info, text, strlen(text));
388  }
389 
390  /* Call drbg_reseed if reseed is required, and generate random number */
391 
392  if(ret->flag == MPHELL_RESEED_REQUIRED)
393  {
394  /* Get entropy from the source */
395  drbg_internal_state_t *internal_state = drbg_internal_states[state_handle];
396  uint8_t* entropy_input = malloc(2 * internal_state->info->security_strength);
397  get_entropy_input(ret, entropy_input, internal_state->entropy_src, 2 * internal_state->info->security_strength);
398 
399  char *text;
400  if(ret->flag != MPHELL_SUCCESS)
401  {
402  if(entropy_input != NULL)
403  {
404  free(entropy_input);
405  }
406  ret->flag = MPHELL_ERROR_RANDOM;
407  text = "drbg_generate : get_entropy_input failed";
408  ret->info = malloc(strlen(text));
409  memcpy(ret->info, text, strlen(text));
410  return;
411  }
412  drbg_reseed(ret, state_handle, entropy_input, 2 * internal_state->info->security_strength, additional_input, add_length);
413  if(entropy_input != NULL)
414  {
415  free(entropy_input);
416  }
417  if(ret->flag != MPHELL_SUCCESS)
418  {
419  return;
420  }
421 
422  /* Call appropriate generate algorithm with additional_input = the Null string */
423 
424  switch(internal_state->type)
425  {
426  case DRBG_SHA1 :
427  case DRBG_SHA256 :
428  hash_drbg_generate(ret, returned_bytes, internal_state,
429  requested_number_of_bytes, NULL, 0);
430  break;
431 
432  case DRBG_AES128 :
433  case DRBG_AES192 :
434  case DRBG_AES256 :
435  ctr_drbg_generate(ret, returned_bytes, internal_state,
436  requested_number_of_bytes, NULL, 0);
437  break;
438 
439  default:
440  ret->flag = MPHELL_ERROR_RANDOM;
441  char *text = "drbg_generate : Invalid drbg type, only \
442  supported DRBG_SHA1, DRBG_SHA256, DRBG_AES128, DRBG_AES192,\
443  DRBG_AES256";
444  ret->info = malloc(strlen(text));
445  memcpy(ret->info, text, strlen(text));
446  }
447  }
448 }
449 
450 void
451 drbg_uninstantiate(mphell_status ret, const int8_t state_handle)
452 {
453  /* Get the current internal state */
454 
455  if((state_handle < 0) || (state_handle > DRBG_MAX_INTERNAL_STATES))
456  {
457  ret->flag = MPHELL_ERROR_RANDOM;
458  char *text = "drbg_unsinstantiate : Invalid state handle specified";
459  ret->info = malloc(strlen(text));
460  memcpy(ret->info, text, strlen(text));
461  return;
462  }
463 
464  if(drbg_internal_states[state_handle]->type == DRBG_UNSET)
465  {
466  return;
467  }
468  drbg_internal_state_t *internal_state = drbg_internal_states[state_handle];
469 
470  /* Erase the contents of the internal state indicated by state_handle */
471  memset(internal_state->state->V, 0, internal_state->info->outlen);
472  memset(internal_state->state->C_Key, 0, internal_state->info->seedlen - internal_state->info->outlen);
473  free(internal_state->state->V);
474  free(internal_state->state->C_Key);
475  internal_state->state->V = NULL;
476  internal_state->state->C_Key = NULL;
477  internal_state->state->reseed_counter = 0;
478 
479  internal_state->info->seedlen = 0;
480  internal_state->info->outlen = 0;
481  internal_state->info->security_strength = 0;
482 
483  internal_state->type = DRBG_UNSET;
484  ret->flag = MPHELL_SUCCESS;
485 }
void drbg_uninstantiate(mphell_status ret, const int8_t state_handle)
Uninstantiate a DRBG state.
Definition: mphell-drbg.c:451
Declaration of the Deterministic Random Bit Generator functions. Details can be found in "NIST Specia...
void ctr_drbg_reseed(mphell_status ret, drbg_internal_state working_state, const uint8_t *entropy_input, const uint16_t entropy_length, const uint8_t *additional_input, const uint64_t add_length)
Reseed the DRBG state (V, C_Key) using entropy_input and additional_input.
int8_t drbg_find_empty_state()
Find an empty DRBG state.
Definition: mphell-drbg.c:39
void ctr_drbg_generate(mphell_status ret, uint8_t *returned_bytes, drbg_internal_state working_state, const uint32_t requested_no_of_bytes, const uint8_t *additional_input, const uint64_t add_length)
"Generates pseudorandom bits upon request, using the current internal state, and generates a new inte...
void hash_drbg_instantiate(mphell_status ret, drbg_internal_state initial_state, const uint8_t security_strength, const uint8_t *entropy_input, const uint16_t entropy_length, const uint8_t *personalization_string, const uint64_t pers_length, const drbg_type type)
Instantiate the DRBG state (V, C_Key) using entropy_input and personalization_string.
void get_entropy_input(mphell_status ret, uint8_t *data, const entropy_type entropy_src, const uint16_t length)
Get length bit of entropy from the entropy source selected.
void drbg_generate(mphell_status ret, uint8_t *returned_bytes, const int8_t state_handle, const uint32_t requested_number_of_bytes, const uint16_t requested_security_strength, const uint8_t *additional_input, const uint64_t add_length)
"Generates pseudorandom bits upon request, using the current internal state, and generates a new inte...
Definition: mphell-drbg.c:311
int16_t drbg_find_highest_supported_security_strength(const drbg_type type)
Give the highest supported security strength according to the DRBG type.
Definition: mphell-drbg.c:60
enum drbg_algorithm drbg_type
Define the DRBG algorithm.
void drbg_reseed(mphell_status ret, const int8_t state_handle, const uint8_t *entropy, const uint16_t entropy_length, const uint8_t *additional_input, const uint64_t add_length)
Reseed the DRBG, "acquires new entropy input and combines it with the current internal state and any ...
Definition: mphell-drbg.c:243
mphell_status_t mphell_status[1]
The status is a couple (flag, information)
Definition: mphell-errors.h:94
void hash_drbg_reseed(mphell_status ret, drbg_internal_state working_state, const uint8_t *entropy_input, const uint16_t entropy_length, const uint8_t *additional_input, const uint64_t add_length)
Reseed the DRBG state (V, C_Key) using entropy_input and additional_input.
void ctr_drbg_instantiate(mphell_status ret, drbg_internal_state initial_state, const uint8_t security_strength, const uint8_t *entropy_input, const uint16_t entropy_length, const uint8_t *personalization_string, const uint64_t pers_length, const drbg_type type)
Instantiate the DRBG state (V, C_Key) using entropy_input and personalization_string.
enum entropy_source entropy_type
Define the entropy source.
drbg_internal_state_t drbg_internal_state[1]
Address of a drbg_internal_state_t structure.
void hash_drbg_generate(mphell_status ret, uint8_t *returned_bytes, drbg_internal_state working_state, const uint32_t requested_no_of_bytes, const uint8_t *additional_input, const uint64_t add_length)
"Generates pseudorandom bits upon request, using the current internal state, and generates a new inte...
The working state and administrative informations.
drbg_working_state state