xdrbg.c
Go to the documentation of this file.
1 /**
2  * @file xdrbg.c
3  * @brief XDRBG pseudorandom number generator
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2025 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneCRYPTO Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.5.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/crypto.h"
36 #include "rng/xdrbg.h"
37 #include "debug.h"
38 
39 //Check crypto library configuration
40 #if (XDRBG_SUPPORT == ENABLED)
41 
42 //Common interface for PRNG algorithms
44 {
45  "XDRBG",
46  sizeof(XdrbgContext),
47  (PrngAlgoInit) NULL,
52 };
53 
54 
55 /**
56  * @brief Initialize PRNG context
57  * @param[in] context Pointer to the XDRBG context to initialize
58  * @param[in] xofAlgo XOF algorithm
59  * @return Error code
60  **/
61 
62 error_t xdrbgInit(XdrbgContext *context, const XofAlgo *xofAlgo)
63 {
64  //Check parameters
65  if(context == NULL || xofAlgo == NULL)
67 
68  //Clear the internal state
69  osMemset(context, 0, sizeof(XdrbgContext));
70 
71  //Create a mutex to prevent simultaneous access to the PRNG state
72  if(!osCreateMutex(&context->mutex))
73  {
74  //Failed to create mutex
76  }
77 
78 #if (SHAKE_SUPPORT == ENABLED)
79  //SHAKE128 XOF algorithm?
80  if(xofAlgo == SHAKE128_XOF_ALGO)
81  {
82  //Set parameters
83  context->xofAlgo = SHAKE128_XOF_ALGO;
84  context->securityStrength = 16;
85  context->maxOutputLen = 304;
86  }
87  else
88 #endif
89 #if (SHAKE_SUPPORT == ENABLED)
90  //SHAKE256 XOF algorithm?
91  if(xofAlgo == SHAKE256_XOF_ALGO)
92  {
93  //Set parameters
94  context->xofAlgo = SHAKE256_XOF_ALGO;
95  context->securityStrength = 32;
96  context->maxOutputLen = 344;
97  }
98  else
99 #endif
100 #if (ASCON_XOF128_SUPPORT == ENABLED)
101  //Ascon-XOF128 XOF algorithm?
102  if(xofAlgo == ASCON_XOF128_XOF_ALGO)
103  {
104  //Set parameters
105  context->xofAlgo = ASCON_XOF128_XOF_ALGO;
106  context->securityStrength = 16;
107  context->maxOutputLen = 256;
108  }
109  else
110 #endif
111  //Unknown XOF algorithm?
112  {
113  //Report an error
114  return ERROR_UNSUPPORTED_ALGO;
115  }
116 
117  //Successful initialization
118  return NO_ERROR;
119 }
120 
121 
122 /**
123  * @brief Seed the PRNG state
124  * @param[in] context Pointer to the XDRBG context
125  * @param[in] seed Seed material
126  * @param[in] seedLen Length of the seed material, in bytes
127  * @return Error code
128  **/
129 
130 error_t xdrbgSeed(XdrbgContext *context, const uint8_t *seed, size_t length)
131 {
132  //Seeding process
133  return xdrbgSeedEx(context, seed, length, NULL, 0);
134 }
135 
136 
137 /**
138  * @brief Seed the PRNG state (with nonce and personalization string)
139  * @param[in] context Pointer to the XDRBG context
140  * @param[in] seed Seed material
141  * @param[in] seedLen Length of the seed material, in bytes
142  * @param[in] alpha Optional data
143  * @param[in] alphaLen Length of the additional data, in bytes
144  * @return Error code
145  **/
146 
147 error_t xdrbgSeedEx(XdrbgContext *context, const uint8_t *seed, size_t seedLen,
148  const uint8_t *alpha, size_t alphaLen)
149 {
150  uint8_t encode;
151  const XofAlgo *xofAlgo;
152  XofContext *xofContext;
153 
154  //Check parameters
155  if(context == NULL || seed == NULL)
157 
158  //The alpha parameter is optional
159  if(alpha == NULL && alphaLen != 0)
161 
162  //XDRBG is a DRBG based on an underlying XOF
163  if(context->xofAlgo == NULL)
164  return ERROR_PRNG_NOT_READY;
165 
166  //Check the length of the seed
167  if(seedLen < (3 * context->securityStrength / 2))
169 
170  //The additional input string must not be longer than 84 bytes
171  if(alphaLen > XDRBG_MAX_ALPHA_LEN)
173 
174  //Acquire exclusive access to the PRNG state
175  osAcquireMutex(&context->mutex);
176 
177  //XDRBG is intended to be usable with any XOF
178  xofAlgo = context->xofAlgo;
179  //Point to the XOF context
180  xofContext = &context->xofContext;
181 
182  //The encoding adds a single byte of stretch
183  encode = XDRBG_ENCODE(alphaLen, 0);
184 
185  //Initialize internal state
186  xofAlgo->init(xofContext);
187  xofAlgo->absorb(xofContext, seed, seedLen);
188  xofAlgo->absorb(xofContext, alpha, alphaLen);
189  xofAlgo->absorb(xofContext, &encode, sizeof(encode));
190  xofAlgo->final(xofContext);
191  xofAlgo->squeeze(xofContext, context->v, context->securityStrength * 2);
192 
193  //Reset reseed_counter
194  context->reseedCounter = 1;
195 
196  //Release exclusive access to the PRNG state
197  osReleaseMutex(&context->mutex);
198 
199  //Successful processing
200  return NO_ERROR;
201 }
202 
203 
204 /**
205  * @brief Reseed the PRNG state
206  * @param[in] context Pointer to the XDRBG context
207  * @param[in] seed Seed material
208  * @param[in] seedLen Length of the seed material, in bytes
209  * @return Error code
210  **/
211 
212 error_t xdrbgReseed(XdrbgContext *context, const uint8_t *seed, size_t length)
213 {
214  //Reseeding process
215  return xdrbgReseedEx(context, seed, length, NULL, 0);
216 }
217 
218 
219 /**
220  * @brief Reseed the PRNG state (with additional input)
221  * @param[in] context Pointer to the XDRBG context
222  * @param[in] seed Seed material
223  * @param[in] seedLen Length of the seed material, in bytes
224  * @param[in] alpha Optional data
225  * @param[in] alphaLen Length of the additional data, in bytes
226  * @return Error code
227  **/
228 
229 error_t xdrbgReseedEx(XdrbgContext *context, const uint8_t *seed,
230  size_t seedLen, const uint8_t *alpha, size_t alphaLen)
231 {
232  uint8_t encode;
233  const XofAlgo *xofAlgo;
234  XofContext *xofContext;
235 
236  //Check parameters
237  if(context == NULL || seed == NULL)
239 
240  //The alpha parameter is optional
241  if(alpha == NULL && alphaLen != 0)
243 
244  //XDRBG is a DRBG based on an underlying XOF
245  if(context->xofAlgo == NULL)
246  return ERROR_PRNG_NOT_READY;
247 
248  //Check whether the DRBG has been properly instantiated
249  if(context->reseedCounter == 0)
250  return ERROR_PRNG_NOT_READY;
251 
252  //Check the length of the seed
253  if(seedLen < context->securityStrength)
255 
256  //The additional input string must not be longer than 84 bytes
257  if(alphaLen > XDRBG_MAX_ALPHA_LEN)
259 
260  //Acquire exclusive access to the PRNG state
261  osAcquireMutex(&context->mutex);
262 
263  //XDRBG is intended to be usable with any XOF
264  xofAlgo = context->xofAlgo;
265  //Point to the XOF context
266  xofContext = &context->xofContext;
267 
268  //The encoding adds a single byte of stretch
269  encode = XDRBG_ENCODE(alphaLen, 1);
270 
271  //Update internal state
272  xofAlgo->init(xofContext);
273  xofAlgo->absorb(xofContext, context->v, context->securityStrength * 2);
274  xofAlgo->absorb(xofContext, seed, seedLen);
275  xofAlgo->absorb(xofContext, alpha, alphaLen);
276  xofAlgo->absorb(xofContext, &encode, sizeof(encode));
277  xofAlgo->final(xofContext);
278  xofAlgo->squeeze(xofContext, context->v, context->securityStrength * 2);
279 
280  //Reset reseed_counter
281  context->reseedCounter = 1;
282 
283  //Release exclusive access to the PRNG state
284  osReleaseMutex(&context->mutex);
285 
286  //Successful processing
287  return NO_ERROR;
288 }
289 
290 
291 /**
292  * @brief Generate pseudorandom data
293  * @param[in] context Pointer to the XDRBG context
294  * @param[out] output Buffer where to store the pseudorandom bytes
295  * @param[in] length Requested number of bytes
296  * @return Error code
297  **/
298 
299 error_t xdrbgGenerate(XdrbgContext *context, uint8_t *output, size_t length)
300 {
301  //Generation process
302  return xdrbgGenerateEx(context, NULL, 0, output, length);
303 }
304 
305 
306 /**
307  * @brief Generate pseudorandom data (with additional input)
308  * @param[in] context Pointer to the XDRBG context
309  * @param[in] alpha Optional data
310  * @param[in] alphaLen Length of the additional data, in bytes
311  * @param[out] output Buffer where to store the pseudorandom bytes
312  * @param[in] outputLen Requested number of bytes
313  * @return Error code
314  **/
315 
316 error_t xdrbgGenerateEx(XdrbgContext *context, const uint8_t *alpha,
317  size_t alphaLen, uint8_t *output, size_t outputLen)
318 {
319  size_t n;
320  uint8_t encode;
321  const XofAlgo *xofAlgo;
322  XofContext *xofContext;
323 
324  //Check parameters
325  if(context == NULL)
327 
328  //The alpha parameter is optional
329  if(alpha == NULL && alphaLen != 0)
331 
332  //The additional input string must not be longer than 84 bytes
333  if(alphaLen > XDRBG_MAX_ALPHA_LEN)
335 
336  //XDRBG is a DRBG based on an underlying XOF
337  if(context->xofAlgo == NULL)
338  return ERROR_PRNG_NOT_READY;
339 
340  //A DRBG shall be instantiated prior to the generation of pseudorandom bits
341  if(context->reseedCounter == 0)
342  return ERROR_PRNG_NOT_READY;
343 
344  //Acquire exclusive access to the PRNG state
345  osAcquireMutex(&context->mutex);
346 
347  //XDRBG is intended to be usable with any XOF
348  xofAlgo = context->xofAlgo;
349  //Point to the XOF context
350  xofContext = &context->xofContext;
351 
352  //The encoding adds a single byte of stretch
353  encode = XDRBG_ENCODE(alphaLen, 2);
354 
355  //Generate the requested number of bytes
356  while(outputLen > 0)
357  {
358  //Number of bytes to generate at a time
359  n = MIN(outputLen, context->maxOutputLen);
360 
361  //Update internal state
362  xofAlgo->init(xofContext);
363  xofAlgo->absorb(xofContext, context->v, context->securityStrength * 2);
364  xofAlgo->absorb(xofContext, alpha, alphaLen);
365  xofAlgo->absorb(xofContext, &encode, sizeof(encode));
366  xofAlgo->final(xofContext);
367  xofAlgo->squeeze(xofContext, context->v, context->securityStrength * 2);
368 
369  //Generate output string
370  xofAlgo->squeeze(xofContext, output, n);
371 
372  //Advance data pointer
373  output += n;
374  outputLen -= n;
375  }
376 
377  //Increment reseed_counter
378  context->reseedCounter++;
379 
380  //Release exclusive access to the PRNG state
381  osReleaseMutex(&context->mutex);
382 
383  //Successful processing
384  return NO_ERROR;
385 }
386 
387 
388 /**
389  * @brief Release PRNG context
390  * @param[in] context Pointer to the XDRBG context
391  **/
392 
393 void xdrbgDeinit(XdrbgContext *context)
394 {
395  //Valid XDRBG context?
396  if(context != NULL)
397  {
398  //Free previously allocated resources
399  osDeleteMutex(&context->mutex);
400 
401  //Erase the contents of the internal state
402  osMemset(context, 0, sizeof(XdrbgContext));
403  }
404 }
405 
406 #endif
void xdrbgDeinit(XdrbgContext *context)
Release PRNG context.
Definition: xdrbg.c:393
error_t xdrbgSeed(XdrbgContext *context, const uint8_t *seed, size_t length)
Seed the PRNG state.
Definition: xdrbg.c:130
#define SHAKE128_XOF_ALGO
Definition: shake.h:39
error_t xdrbgSeedEx(XdrbgContext *context, const uint8_t *seed, size_t seedLen, const uint8_t *alpha, size_t alphaLen)
Seed the PRNG state (with nonce and personalization string)
Definition: xdrbg.c:147
bool_t osCreateMutex(OsMutex *mutex)
Create a mutex object.
#define PrngAlgo
Definition: crypto.h:1008
XDRBG PRNG context.
Definition: xdrbg.h:60
@ ERROR_OUT_OF_RESOURCES
Definition: error.h:64
error_t(* PrngAlgoSeed)(void *context, const uint8_t *seed, size_t length)
Definition: crypto.h:1107
error_t(* PrngAlgoReseed)(void *context, const uint8_t *seed, size_t length)
Definition: crypto.h:1110
error_t xdrbgReseedEx(XdrbgContext *context, const uint8_t *seed, size_t seedLen, const uint8_t *alpha, size_t alphaLen)
Reseed the PRNG state (with additional input)
Definition: xdrbg.c:229
XofAlgoInit init
Definition: crypto.h:1152
@ ERROR_PRNG_NOT_READY
Definition: error.h:252
XofAlgoSqueeze squeeze
Definition: crypto.h:1155
#define SHAKE256_XOF_ALGO
Definition: shake.h:40
error_t xdrbgGenerate(XdrbgContext *context, uint8_t *output, size_t length)
Generate pseudorandom data.
Definition: xdrbg.c:299
XofContext xofContext
XOF context.
Definition: xdrbg.h:63
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
XofAlgoAbsorb absorb
Definition: crypto.h:1153
error_t
Error codes.
Definition: error.h:43
size_t maxOutputLen
Maximum output length.
Definition: xdrbg.h:65
error_t xdrbgReseed(XdrbgContext *context, const uint8_t *seed, size_t length)
Reseed the PRNG state.
Definition: xdrbg.c:212
@ ERROR_UNSUPPORTED_ALGO
Definition: error.h:126
XofAlgoFinal final
Definition: crypto.h:1154
const PrngAlgo xdrbgPrngAlgo
Definition: xdrbg.c:43
error_t xdrbgInit(XdrbgContext *context, const XofAlgo *xofAlgo)
Initialize PRNG context.
Definition: xdrbg.c:62
General definitions for cryptographic algorithms.
#define XDRBG_ENCODE(alphaLen, n)
Definition: xdrbg.h:47
Generic XOF algorithm context.
uint8_t length
Definition: tcp.h:375
XDRBG pseudorandom number generator.
#define MIN(a, b)
Definition: os_port.h:63
Common interface for XOF algorithms.
Definition: crypto.h:1146
OsMutex mutex
Mutex preventing simultaneous access to the PRNG state.
Definition: xdrbg.h:61
void(* PrngAlgoDeinit)(void *context)
Definition: crypto.h:1116
void osDeleteMutex(OsMutex *mutex)
Delete a mutex object.
uint8_t n
void osAcquireMutex(OsMutex *mutex)
Acquire ownership of the specified mutex object.
void osReleaseMutex(OsMutex *mutex)
Release ownership of the specified mutex object.
error_t(* PrngAlgoGenerate)(void *context, uint8_t *output, size_t length)
Definition: crypto.h:1113
size_t securityStrength
Security strength.
Definition: xdrbg.h:64
error_t xdrbgGenerateEx(XdrbgContext *context, const uint8_t *alpha, size_t alphaLen, uint8_t *output, size_t outputLen)
Generate pseudorandom data (with additional input)
Definition: xdrbg.c:316
#define XDRBG_MAX_ALPHA_LEN
Definition: xdrbg.h:39
uint64_t reseedCounter
Reseed counter.
Definition: xdrbg.h:67
#define osMemset(p, value, length)
Definition: os_port.h:138
error_t(* PrngAlgoInit)(void *context)
Definition: crypto.h:1105
@ NO_ERROR
Success.
Definition: error.h:44
const XofAlgo * xofAlgo
XOF algorithm.
Definition: xdrbg.h:62
Debugging facilities.
#define ASCON_XOF128_XOF_ALGO
Definition: ascon_xof128.h:39
uint8_t v[XDRBG_MAX_V_SIZE]
Internal state V.
Definition: xdrbg.h:66