hkdf.c
Go to the documentation of this file.
1 /**
2  * @file hkdf.c
3  * @brief HKDF (HMAC-based Key Derivation Function)
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneCrypto Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @section Description
26  *
27  * HKDF is a simple HMAC-based key derivation function which can be used as a
28  * building block in various protocols and applications. Refer to RFC 5869 for
29  * more details
30  *
31  * @author Oryx Embedded SARL (www.oryx-embedded.com)
32  * @version 1.9.0
33  **/
34 
35 //Switch to the appropriate trace level
36 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
37 
38 //Dependencies
39 #include "core/crypto.h"
40 #include "kdf/hkdf.h"
41 #include "mac/hmac.h"
42 
43 //Check crypto library configuration
44 #if (HKDF_SUPPORT == ENABLED)
45 
46 
47 /**
48  * @brief HKDF key derivation function
49  * @param[in] hash Underlying hash function
50  * @param[in] ikm input keying material
51  * @param[in] ikmLen Length in the input keying material
52  * @param[in] salt Optional salt value (a non-secret random value)
53  * @param[in] saltLen Length of the salt
54  * @param[in] info Optional application specific information
55  * @param[in] infoLen Length of the application specific information
56  * @param[out] okm output keying material
57  * @param[in] okmLen Length of the output keying material
58  * @return Error code
59  **/
60 
61 error_t hkdf(const HashAlgo *hash, const uint8_t *ikm, size_t ikmLen,
62  const uint8_t *salt, size_t saltLen, const uint8_t *info, size_t infoLen,
63  uint8_t *okm, size_t okmLen)
64 {
65  error_t error;
66  uint8_t prk[MAX_HASH_DIGEST_SIZE];
67 
68  //Perform HKDF extract step
69  error = hkdfExtract(hash, ikm, ikmLen, salt, saltLen, prk);
70 
71  //Check status code
72  if(!error)
73  {
74  //Perform HKDF expand step
75  error = hkdfExpand(hash, prk, hash->digestSize, info, infoLen,
76  okm, okmLen);
77  }
78 
79  //Return status code
80  return error;
81 }
82 
83 
84 /**
85  * @brief HKDF extract step
86  * @param[in] hash Underlying hash function
87  * @param[in] ikm input keying material
88  * @param[in] ikmLen Length in the input keying material
89  * @param[in] salt Optional salt value (a non-secret random value)
90  * @param[in] saltLen Length of the salt
91  * @param[out] prk Pseudorandom key
92  * @return Error code
93  **/
94 
95 error_t hkdfExtract(const HashAlgo *hash, const uint8_t *ikm, size_t ikmLen,
96  const uint8_t *salt, size_t saltLen, uint8_t *prk)
97 {
98  HmacContext *hmacContext;
99 
100  //Check parameters
101  if(hash == NULL || ikm == NULL || prk == NULL)
103 
104  //The salt parameter is optional
105  if(salt == NULL && saltLen != 0)
107 
108  //Allocate a memory buffer to hold the HMAC context
109  hmacContext = cryptoAllocMem(sizeof(HmacContext));
110  //Failed to allocate memory?
111  if(hmacContext == NULL)
112  return ERROR_OUT_OF_MEMORY;
113 
114  //The salt parameter is optional
115  if(salt == NULL)
116  {
117  //If the salt is not provided, it is set to a string of HashLen zeros
118  cryptoMemset(hmacContext->digest, 0, hash->digestSize);
119  salt = hmacContext->digest;
120  saltLen = hash->digestSize;
121  }
122 
123  //Compute PRK = HMAC-Hash(salt, IKM)
124  hmacInit(hmacContext, hash, salt, saltLen);
125  hmacUpdate(hmacContext, ikm, ikmLen);
126  hmacFinal(hmacContext, prk);
127 
128  //Free previously allocated memory
129  cryptoFreeMem(hmacContext);
130 
131  //Successful processing
132  return NO_ERROR;
133 }
134 
135 
136 /**
137  * @brief HKDF expand step
138  * @param[in] hash Underlying hash function
139  * @param[in] prk Pseudorandom key
140  * @param[in] prkLen Length of the pseudorandom key
141  * @param[in] info Optional application specific information
142  * @param[in] infoLen Length of the application specific information
143  * @param[out] okm output keying material
144  * @param[in] okmLen Length of the output keying material
145  * @return Error code
146  **/
147 
148 error_t hkdfExpand(const HashAlgo *hash, const uint8_t *prk, size_t prkLen,
149  const uint8_t *info, size_t infoLen, uint8_t *okm, size_t okmLen)
150 {
151  uint8_t i;
152  size_t tLen;
153  HmacContext *hmacContext;
154  uint8_t t[MAX_HASH_DIGEST_SIZE];
155 
156  //Check parameters
157  if(hash == NULL || prk == NULL || okm == NULL)
159 
160  //The application specific information parameter is optional
161  if(info == NULL && infoLen != 0)
163 
164  //PRK must be at least HashLen octets
165  if(prkLen < hash->digestSize)
166  return ERROR_INVALID_LENGTH;
167 
168  //Check the length of the output keying material
169  if(okmLen > (255 * hash->digestSize))
170  return ERROR_INVALID_LENGTH;
171 
172  //Allocate a memory buffer to hold the HMAC context
173  hmacContext = cryptoAllocMem(sizeof(HmacContext));
174  //Failed to allocate memory?
175  if(hmacContext == NULL)
176  return ERROR_OUT_OF_MEMORY;
177 
178  //T(0) is an empty string (zero length)
179  tLen = 0;
180 
181  //Iterate as many times as required
182  for(i = 1; okmLen > 0; i++)
183  {
184  //Compute T(i) = HMAC-Hash(PRK, T(i-1) | info | i)
185  hmacInit(hmacContext, hash, prk, prkLen);
186  hmacUpdate(hmacContext, t, tLen);
187  hmacUpdate(hmacContext, info, infoLen);
188  hmacUpdate(hmacContext, &i, sizeof(i));
189  hmacFinal(hmacContext, t);
190 
191  //Number of octets in the current block
192  tLen = MIN(okmLen, hash->digestSize);
193  //Save the resulting block
194  cryptoMemcpy(okm, t, tLen);
195 
196  //Point to the next block
197  okm += tLen;
198  okmLen -= tLen;
199  }
200 
201  //Free previously allocated memory
202  cryptoFreeMem(hmacContext);
203 
204  //Successful processing
205  return NO_ERROR;
206 }
207 
208 #endif
#define cryptoMemcpy(dest, src, length)
Definition: crypto.h:590
#define cryptoFreeMem(p)
Definition: crypto.h:578
uint8_t hash
Definition: tls.h:1363
HKDF (HMAC-based Key Derivation Function)
#define cryptoAllocMem(size)
Definition: crypto.h:573
General definitions for cryptographic algorithms.
void hmacFinal(HmacContext *context, uint8_t *digest)
Finish the HMAC calculation.
Definition: hmac.c:183
Invalid parameter.
Definition: error.h:45
#define MAX_HASH_DIGEST_SIZE
Definition: crypto.h:747
error_t hkdfExpand(const HashAlgo *hash, const uint8_t *prk, size_t prkLen, const uint8_t *info, size_t infoLen, uint8_t *okm, size_t okmLen)
HKDF expand step.
Definition: hkdf.c:148
HMAC algorithm context.
Definition: hmac.h:180
HMAC (Keyed-Hashing for Message Authentication)
error_t hkdfExtract(const HashAlgo *hash, const uint8_t *ikm, size_t ikmLen, const uint8_t *salt, size_t saltLen, uint8_t *prk)
HKDF extract step.
Definition: hkdf.c:95
#define MIN(a, b)
Definition: os_port.h:60
uint8_t digest[MAX_HASH_DIGEST_SIZE]
Definition: hmac.h:185
Success.
Definition: error.h:42
error_t
Error codes.
Definition: error.h:40
void hmacInit(HmacContext *context, const HashAlgo *hash, const void *key, size_t keyLen)
Initialize HMAC calculation.
Definition: hmac.c:116
error_t hkdf(const HashAlgo *hash, const uint8_t *ikm, size_t ikmLen, const uint8_t *salt, size_t saltLen, const uint8_t *info, size_t infoLen, uint8_t *okm, size_t okmLen)
HKDF key derivation function.
Definition: hkdf.c:61
#define cryptoMemset(p, value, length)
Definition: crypto.h:584
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:166
Common interface for hash algorithms.
Definition: crypto.h:1054