one_step_kdf.c
Go to the documentation of this file.
1 /**
2  * @file one_step_kdf.c
3  * @brief One-Step KDF
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2026 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  * @section Description
28  *
29  * One-Step KDF is a key derivation function defined by NIST SP 800-56C
30  * revision 1, section 4
31  *
32  * @author Oryx Embedded SARL (www.oryx-embedded.com)
33  * @version 2.6.6
34  **/
35 
36 //Switch to the appropriate trace level
37 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
38 
39 //Dependencies
40 #include "core/crypto.h"
41 #include "kdf/one_step_kdf.h"
42 #include "mac/mac_algorithms.h"
43 
44 //Check crypto library configuration
45 #if (ONE_STEP_KDF_SUPPORT == ENABLED)
46 
47 //Default salt value for HMAC and KMAC auxiliary functions
48 static const uint8_t defaultSalt[164] =
49 {
50  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
53  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
54  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
55  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60  0x00, 0x00, 0x00, 0x00
61 };
62 
63 
64 /**
65  * @brief One-Step KDF function
66  * @param[in] type Auxiliary function H (hash, HMAC or KMAC)
67  * @param[in] hashAlgo Underlying hash function (for hash and HMAC-based
68  * auxiliary functions only)
69  * @param[in] z Shared secret Z
70  * @param[in] zLen Length of the shared secret Z, in bytes
71  * @param[in] salt Salt value (for HMAC and KMAC-based auxiliary functions only)
72  * @param[in] saltLen Length of the salt value, in bytes
73  * @param[in] otherInfo Context-specific information (optional parameter)
74  * @param[in] otherInfoLen Length of the context-specific information, in bytes
75  * @param[out] dk Derived keying material
76  * @param[in] dkLen Length of the keying material to be generated, in bytes
77  * @return Error code
78  **/
79 
81  const uint8_t *z, size_t zLen, const uint8_t *salt, size_t saltLen,
82  const uint8_t *otherInfo, size_t otherInfoLen, uint8_t *dk, size_t dkLen)
83 {
84  error_t error;
85 
86  //The One-Step KDF uses an auxiliary function H, which can be either an
87  //approved hash function, an HMAC with an approved hash function or a KMAC
88  //variant
90  {
91  error = oneStepKdfHash(hashAlgo, z, zLen, otherInfo, otherInfoLen,
92  dk, dkLen);
93  }
94  else if(type == ONE_STEP_KDF_TYPE_HMAC)
95  {
96  error = oneStepKdfHmac(hashAlgo, z, zLen, salt, saltLen, otherInfo,
97  otherInfoLen, dk, dkLen);
98  }
100  {
101  error = oneStepKdfKmac(128, dkLen, z, zLen, salt, saltLen, otherInfo,
102  otherInfoLen, dk, dkLen);
103  }
104  else if(type == ONE_STEP_KDF_TYPE_KMAC256)
105  {
106  error = oneStepKdfKmac(256, dkLen, z, zLen, salt, saltLen, otherInfo,
107  otherInfoLen, dk, dkLen);
108  }
109  else
110  {
111  error = ERROR_INVALID_PARAMETER;
112  }
113 
114  //Return status code
115  return error;
116 }
117 
118 
119 /**
120  * @brief One-Step KDF function (with hash-based auxiliary function)
121  * @param[in] hashAlgo Underlying hash function
122  * @param[in] z Shared secret Z
123  * @param[in] zLen Length of the shared secret Z, in bytes
124  * @param[in] otherInfo Context-specific information (optional parameter)
125  * @param[in] otherInfoLen Length of the context-specific information, in bytes
126  * @param[out] dk Derived keying material
127  * @param[in] dkLen Length of the keying material to be generated, in bytes
128  * @return Error code
129  **/
130 
131 error_t oneStepKdfHash(const HashAlgo *hashAlgo, const uint8_t *z,
132  size_t zLen, const uint8_t *otherInfo, size_t otherInfoLen, uint8_t *dk,
133  size_t dkLen)
134 {
135  size_t n;
136  uint32_t i;
137  uint8_t counter[4];
138  uint8_t digest[MAX_HASH_DIGEST_SIZE];
139 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
140  HashContext *hashContext;
141 #else
142  HashContext hashContext[1];
143 #endif
144 
145  //Check parameters
146  if(hashAlgo == NULL || z == NULL || dk == NULL)
148 
149  //The OtherInfo parameter is optional
150  if(otherInfo == NULL && otherInfoLen != 0)
152 
153  //The length of the derived keying material (L) must be a positive integer
154  if(dkLen == 0)
156 
157 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
158  //Allocate a memory buffer to hold the hash context
159  hashContext = cryptoAllocMem(hashAlgo->contextSize);
160  //Failed to allocate memory?
161  if(hashContext == NULL)
162  return ERROR_OUT_OF_MEMORY;
163 #endif
164 
165  //Derive the keying material
166  for(i = 1; dkLen > 0; i++)
167  {
168  //Encode the counter as a 32-bit big-endian string
169  STORE32BE(i, counter);
170 
171  //Compute H(counter || Z || OtherInfo)
172  hashAlgo->init(hashContext);
173  hashAlgo->update(hashContext, counter, sizeof(uint32_t));
174  hashAlgo->update(hashContext, z, zLen);
175  hashAlgo->update(hashContext, otherInfo, otherInfoLen);
176  hashAlgo->final(hashContext, digest);
177 
178  //Number of octets in the current block
179  n = MIN(dkLen, hashAlgo->digestSize);
180  //Save the resulting block
181  osMemcpy(dk, digest, n);
182 
183  //Point to the next block
184  dk += n;
185  dkLen -= n;
186  }
187 
188 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
189  //Free previously allocated memory
190  cryptoFreeMem(hashContext);
191 #endif
192 
193  //Successful processing
194  return NO_ERROR;
195 }
196 
197 
198 /**
199  * @brief One-Step KDF function (with HMAC-based auxiliary function)
200  * @param[in] hashAlgo Underlying hash function
201  * @param[in] z Shared secret Z
202  * @param[in] zLen Length of the shared secret Z, in bytes
203  * @param[in] salt Salt value
204  * @param[in] saltLen Length of the salt, in bytes
205  * @param[in] otherInfo Context-specific information (optional parameter)
206  * @param[in] otherInfoLen Length of the context-specific information, in bytes
207  * @param[out] dk Derived keying material
208  * @param[in] dkLen Length of the keying material to be generated, in bytes
209  * @return Error code
210  **/
211 
212 error_t oneStepKdfHmac(const HashAlgo *hashAlgo, const uint8_t *z,
213  size_t zLen, const uint8_t *salt, size_t saltLen, const uint8_t *otherInfo,
214  size_t otherInfoLen, uint8_t *dk, size_t dkLen)
215 {
216 #if (HMAC_SUPPORT == ENABLED)
217  size_t n;
218  uint32_t i;
219  uint8_t counter[4];
220  uint8_t digest[MAX_HASH_DIGEST_SIZE];
221 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
222  HmacContext *hmacContext;
223 #else
224  HmacContext hmacContext[1];
225 #endif
226 
227  //Check parameters
228  if(hashAlgo == NULL || z == NULL || dk == NULL)
230 
231  //The salt parameter is optional
232  if(salt == NULL && saltLen != 0)
234 
235  //The OtherInfo parameter is optional
236  if(otherInfo == NULL && otherInfoLen != 0)
238 
239  //The length of the derived keying material (L) must be a positive integer
240  if(dkLen == 0)
242 
243 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
244  //Allocate a memory buffer to hold the HMAC context
245  hmacContext = cryptoAllocMem(sizeof(HmacContext));
246  //Failed to allocate memory?
247  if(hmacContext == NULL)
248  return ERROR_OUT_OF_MEMORY;
249 #endif
250 
251  //If the salt value is omitted, then the default salt shall be used
252  if(salt == NULL)
253  {
254  //The default salt shall be an all-zero byte string whose bit length
255  //equals that specified as the bit length of an input block for the hash
256  //function
257  salt = defaultSalt;
258  saltLen = hashAlgo->blockSize;
259  }
260 
261  //Derive the keying material
262  for(i = 1; dkLen > 0; i++)
263  {
264  //Encode the counter as a 32-bit big-endian string
265  STORE32BE(i, counter);
266 
267  //Compute H(counter || Z || OtherInfo)
268  hmacInit(hmacContext, hashAlgo, salt, saltLen);
269  hmacUpdate(hmacContext, counter, sizeof(uint32_t));
270  hmacUpdate(hmacContext, z, zLen);
271  hmacUpdate(hmacContext, otherInfo, otherInfoLen);
272  hmacFinal(hmacContext, digest);
273 
274  //Number of octets in the current block
275  n = MIN(dkLen, hashAlgo->digestSize);
276  //Save the resulting block
277  osMemcpy(dk, digest, n);
278 
279  //Point to the next block
280  dk += n;
281  dkLen -= n;
282  }
283 
284 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
285  //Free previously allocated memory
286  cryptoFreeMem(hmacContext);
287 #endif
288 
289  //Successful processing
290  return NO_ERROR;
291 #else
292  //HMAC-based auxiliary function is not implemented
293  return ERROR_NOT_IMPLEMENTED;
294 #endif
295 }
296 
297 
298 /**
299  * @brief One-Step KDF function (with KMAC-based auxiliary function)
300  * @param[in] strength Number of bits of security (128 for KMAC128 and
301  * 256 for KMAC256)
302  * @param[in] hLen Length of of the auxiliary function output, in bytes
303  * @param[in] z Shared secret Z
304  * @param[in] zLen Length of the shared secret Z, in bytes
305  * @param[in] salt Salt value
306  * @param[in] saltLen Length of the salt, in bytes
307  * @param[in] otherInfo Context-specific information (optional parameter)
308  * @param[in] otherInfoLen Length of the context-specific information, in bytes
309  * @param[out] dk Derived keying material
310  * @param[in] dkLen Length of the keying material to be generated, in bytes
311  * @return Error code
312  **/
313 
314 error_t oneStepKdfKmac(uint_t strength, size_t hLen, const uint8_t *z,
315  size_t zLen, const uint8_t *salt, size_t saltLen, const uint8_t *otherInfo,
316  size_t otherInfoLen, uint8_t *dk, size_t dkLen)
317 {
318 #if (KMAC_SUPPORT == ENABLED)
319  error_t error;
320  size_t n;
321  uint32_t i;
322  uint8_t counter[4];
323 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
324  KmacContext *kmacContext;
325 #else
326  KmacContext kmacContext[1];
327 #endif
328 
329  //The KMAC variant must be either KMAC128 or KMAC256
330  if(strength != 128 && strength != 256)
332 
333  //H_outputBits shall either be set equal to the length (in bits) of the
334  //secret keying material to be derived (L) or selected from the set {160,
335  //224, 256, 384, 512}
336  if(hLen != 20 && hLen != 28 && hLen != 32 && hLen != 48 && hLen != 64 &&
337  hLen != dkLen)
338  {
340  }
341 
342  //Check parameters
343  if(z == NULL || dk == NULL)
345 
346  //The salt parameter is optional
347  if(salt == NULL && saltLen != 0)
349 
350  //The OtherInfo parameter is optional
351  if(otherInfo == NULL && otherInfoLen != 0)
353 
354  //The length of the derived keying material (L) must be a positive integer
355  if(dkLen == 0)
357 
358 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
359  //Allocate a memory buffer to hold the KMAC context
360  kmacContext = cryptoAllocMem(sizeof(KmacContext));
361  //Failed to allocate memory?
362  if(kmacContext == NULL)
363  return ERROR_OUT_OF_MEMORY;
364 #endif
365 
366  //If the salt value is omitted, then the default salt shall be used
367  if(salt == NULL)
368  {
369  //Point to the default salt
370  salt = defaultSalt;
371 
372  //The default salt shall be an all-zero string of 164 bytes for KMAC128,
373  //and 132 bytes for KMAC256
374  if(strength == 128)
375  {
377  }
378  else
379  {
381  }
382  }
383 
384  //Initialize status code
385  error = NO_ERROR;
386 
387  //Derive the keying material
388  for(i = 1; dkLen > 0 && !error; i++)
389  {
390  //Number of octets in the current block
391  n = MIN(dkLen, hLen);
392 
393  //Encode the counter as a 32-bit big-endian string
394  STORE32BE(i, counter);
395 
396  //Initialize KMAC calculation
397  error = kmacInit(kmacContext, strength, salt, saltLen, "KDF", 3);
398 
399  //Check status code
400  if(!error)
401  {
402  //Compute H(counter || Z || OtherInfo)
403  kmacUpdate(kmacContext, counter, sizeof(uint32_t));
404  kmacUpdate(kmacContext, z, zLen);
405  kmacUpdate(kmacContext, otherInfo, otherInfoLen);
406 
407  //Finalize KMAC calculation
408  kmacFinal(kmacContext, dk, n);
409  }
410 
411  //Point to the next block
412  dk += n;
413  dkLen -= n;
414  }
415 
416 #if (CRYPTO_STATIC_MEM_SUPPORT == DISABLED)
417  //Free previously allocated memory
418  cryptoFreeMem(kmacContext);
419 #endif
420 
421  //Return status code
422  return error;
423 #else
424  //KMAC-based auxiliary function is not implemented
425  return ERROR_NOT_IMPLEMENTED;
426 #endif
427 }
428 
429 #endif
HashAlgoInit init
Definition: crypto.h:1253
Generic hash algorithm context.
HMAC algorithm context.
Definition: hmac.h:59
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
error_t kmacInit(KmacContext *context, uint_t strength, const void *key, size_t keyLen, const char_t *custom, size_t customLen)
Initialize KMAC calculation.
Definition: kmac.c:125
size_t digestSize
Definition: crypto.h:1249
HashAlgoUpdate update
Definition: crypto.h:1254
uint8_t type
Definition: coap_common.h:176
@ ONE_STEP_KDF_TYPE_HASH
Definition: one_step_kdf.h:54
size_t blockSize
Definition: crypto.h:1248
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
#define ONE_STEP_KDF_KMAC128_DEFAULT_SALT_LEN
Definition: one_step_kdf.h:38
error_t oneStepKdfKmac(uint_t strength, size_t hLen, const uint8_t *z, size_t zLen, const uint8_t *salt, size_t saltLen, const uint8_t *otherInfo, size_t otherInfoLen, uint8_t *dk, size_t dkLen)
One-Step KDF function (with KMAC-based auxiliary function)
Definition: one_step_kdf.c:314
size_t contextSize
Definition: crypto.h:1247
#define MAX_HASH_DIGEST_SIZE
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
@ ONE_STEP_KDF_TYPE_HMAC
Definition: one_step_kdf.h:55
#define osMemcpy(dest, src, length)
Definition: os_port.h:147
One-Step KDF.
error_t
Error codes.
Definition: error.h:43
@ ONE_STEP_KDF_TYPE_KMAC256
Definition: one_step_kdf.h:57
General definitions for cryptographic algorithms.
#define MIN(a, b)
Definition: os_port.h:63
error_t oneStepKdf(OneStepKdfType type, const HashAlgo *hashAlgo, const uint8_t *z, size_t zLen, const uint8_t *salt, size_t saltLen, const uint8_t *otherInfo, size_t otherInfoLen, uint8_t *dk, size_t dkLen)
One-Step KDF function.
Definition: one_step_kdf.c:80
uint8_t z
Definition: dns_common.h:196
HashAlgoFinal final
Definition: crypto.h:1255
__weak_func void hmacUpdate(HmacContext *context, const void *data, size_t length)
Update the HMAC context with a portion of the message being hashed.
Definition: hmac.c:201
error_t oneStepKdfHmac(const HashAlgo *hashAlgo, const uint8_t *z, size_t zLen, const uint8_t *salt, size_t saltLen, const uint8_t *otherInfo, size_t otherInfoLen, uint8_t *dk, size_t dkLen)
One-Step KDF function (with HMAC-based auxiliary function)
Definition: one_step_kdf.c:212
#define ONE_STEP_KDF_KMAC256_DEFAULT_SALT_LEN
Definition: one_step_kdf.h:40
void kmacUpdate(KmacContext *context, const void *data, size_t dataLen)
Update the KMAC context with a portion of the message being hashed.
Definition: kmac.c:188
uint8_t n
__weak_func void hmacFinal(HmacContext *context, uint8_t *digest)
Finish the HMAC calculation.
Definition: hmac.c:218
#define cryptoFreeMem(p)
Definition: crypto.h:966
error_t oneStepKdfHash(const HashAlgo *hashAlgo, const uint8_t *z, size_t zLen, const uint8_t *otherInfo, size_t otherInfoLen, uint8_t *dk, size_t dkLen)
One-Step KDF function (with hash-based auxiliary function)
Definition: one_step_kdf.c:131
#define cryptoAllocMem(size)
Definition: crypto.h:961
Collection of MAC algorithms.
error_t kmacFinal(KmacContext *context, uint8_t *mac, size_t macLen)
Finish the KMAC calculation.
Definition: kmac.c:203
Common interface for hash algorithms.
Definition: crypto.h:1243
unsigned int uint_t
Definition: compiler_port.h:57
@ ONE_STEP_KDF_TYPE_KMAC128
Definition: one_step_kdf.h:56
__weak_func error_t hmacInit(HmacContext *context, const HashAlgo *hash, const void *key, size_t keyLen)
Initialize HMAC calculation.
Definition: hmac.c:140
KMAC algorithm context.
Definition: kmac.h:54
OneStepKdfType
One-Step KDF auxiliary functions.
Definition: one_step_kdf.h:53
#define STORE32BE(a, p)
Definition: cpu_endian.h:286
@ NO_ERROR
Success.
Definition: error.h:44