1 /***************************************************************************//**
2 * \file cy_cryptolite_hkdf.c
3 * \version 2.30
4 *
5 * \brief
6 *  This file provides the source code to the API for the HKDF method
7 *  in the CRYPTOLITE block driver.
8 *
9 ********************************************************************************
10 * \copyright
11 * Copyright (c) (2020-2023), Cypress Semiconductor Corporation (an Infineon company) or
12 * an affiliate of Cypress Semiconductor Corporation.
13 * SPDX-License-Identifier: Apache-2.0
14 *
15 * Licensed under the Apache License, Version 2.0 (the "License");
16 * you may not use this file except in compliance with the License.
17 * You may obtain a copy of the License at
18 *
19 *    http://www.apache.org/licenses/LICENSE-2.0
20 *
21 * Unless required by applicable law or agreed to in writing, software
22 * distributed under the License is distributed on an "AS IS" BASIS,
23 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
24 * See the License for the specific language governing permissions and
25 * limitations under the License.
26 *******************************************************************************/
27 
28 #include "cy_device.h"
29 
30 #if defined(CY_IP_MXCRYPTOLITE)
31 
32 #include "cy_cryptolite_hkdf.h"
33 
34 #if defined(__cplusplus)
35 extern "C" {
36 #endif
37 
38 #if (CRYPTOLITE_SHA_PRESENT == 1)
39 #if defined(CY_CRYPTOLITE_CFG_HKDF_C) && defined(CY_CRYPTOLITE_CFG_HMAC_C)
40 
41 #include "cy_cryptolite_utils.h"
42 #include "cy_cryptolite_vu.h"
43 
44 /*******************************************************************************
45 * Function Name: Cy_Cryptolite_Hkdf_Extract
46 ****************************************************************************//**
47 *
48 * Performs HKDF Extract calculation.
49 *
50 * \param base
51 * The pointer to the CRYPTOLITE instance.
52 *
53 * \param salt
54 * The pointer to salt.
55 *
56 * \param saltLength
57 * The size of a salt.
58 *
59 * \param ikm
60 * The pointer to the Input Key material.
61 *
62 * \param ikmLength
63 * The length of the IKM.
64 *
65 * \param prk
66 * The pointer to store the generated prk.
67 *
68 * \return
69 * \ref cy_en_cryptolite_status_t
70 *
71 *******************************************************************************/
Cy_Cryptolite_Hkdf_Extract(CRYPTOLITE_Type * base,uint8_t const * salt,uint32_t saltLength,uint8_t const * ikm,uint32_t ikmLength,uint8_t * prk)72 cy_en_cryptolite_status_t Cy_Cryptolite_Hkdf_Extract(CRYPTOLITE_Type *base,
73                                           uint8_t  const *salt,
74                                           uint32_t saltLength,
75                                           uint8_t  const *ikm,
76                                           uint32_t ikmLength,
77                                           uint8_t *prk)
78 {
79     cy_en_cryptolite_status_t status = CY_CRYPTOLITE_BAD_PARAMS;
80     CY_ALIGN(4) uint8_t nullSalt[CY_CRYPTOLITE_SHA256_HASH_SIZE] = {0u};
81     uint8_t *saltptr;
82     uint32_t  saltlen;
83     cy_stc_cryptolite_context_hmac_sha256_t hmac_ctx;
84 
85     /* Input parameters verification */
86     if ((NULL == base) || (NULL == prk) || ((NULL == salt) && (0UL != saltLength))
87         ||((NULL == ikm) && (0UL != ikmLength)))
88     {
89         return status;
90     }
91 
92     saltptr = (uint8_t  *)salt;
93     saltlen = saltLength;
94 
95     if(NULL == salt)
96     {
97         Cy_Cryptolite_Memset (nullSalt, 0u, CY_CRYPTOLITE_SHA256_HASH_SIZE);
98         saltlen = CY_CRYPTOLITE_SHA256_HASH_SIZE;
99         saltptr = nullSalt;
100     }
101 
102     return Cy_Cryptolite_Hmac_Sha256_Run(base, saltptr, saltlen, ikm, ikmLength, prk, &hmac_ctx);
103 }
104 
105 
106 /*******************************************************************************
107 * Function Name: Cy_Cryptolite_Hkdf_Expand
108 ****************************************************************************//**
109 *
110 * Performs HKDF Expand calculation.
111 *
112 * \param base
113 * The pointer to the CRYPTOLITE instance.
114 *
115 * \param prk
116 * The pointer to the pseudo random key.
117 *
118 * \param prkLength
119 * The length of the prk.
120 *
121 * \param info
122 * The pointer to info.
123 *
124 * \param infoLength
125 * The length of the info.
126 *
127 * \param okm
128 * The pointer to Output key material.
129 *
130 * \param okmLength
131 * The length of okm to be generated.
132 *
133 * \return
134 * \ref cy_en_cryptolite_status_t
135 *
136 *******************************************************************************/
Cy_Cryptolite_Hkdf_Expand(CRYPTOLITE_Type * base,uint8_t const * prk,uint32_t prkLength,uint8_t const * info,uint32_t infoLength,uint8_t * okm,uint32_t okmLength)137 cy_en_cryptolite_status_t Cy_Cryptolite_Hkdf_Expand(CRYPTOLITE_Type *base,
138                                           uint8_t  const *prk,
139                                           uint32_t prkLength,
140                                           uint8_t  const *info,
141                                           uint32_t infoLength,
142                                           uint8_t *okm,
143                                           uint32_t okmLength)
144 {
145     cy_en_cryptolite_status_t status = CY_CRYPTOLITE_BAD_PARAMS;
146     uint32_t  hashlen = CY_CRYPTOLITE_SHA256_HASH_SIZE;
147     uint32_t  n,i;
148     uint8_t  counter=0u;
149     uint32_t tLength=0u;
150     uint32_t bytesCopy=0u;
151     uint32_t offset=0u;
152     uint8_t t[CY_CRYPTOLITE_SHA256_HASH_SIZE]  = {0u};
153     cy_stc_cryptolite_context_hmac_sha256_t cfContext;
154 
155 
156     /* Input parameters verification */
157     if ((NULL == base) || ((NULL == prk) && (0UL != prkLength)) || ((NULL == info) && (0UL != infoLength))
158         ||((NULL == okm) && (0UL != okmLength)))
159     {
160         return status;
161     }
162 
163     n = (okmLength + (hashlen - 1u))/ hashlen;
164 
165     if( n > 255u)
166     {
167         return CY_CRYPTOLITE_BAD_PARAMS;
168     }
169 
170     for(i=1u; i<=n; i++)
171     {
172         counter++;
173 
174         status = Cy_Cryptolite_Hmac_Sha256_Init (base, &cfContext);
175         if(status != CY_CRYPTOLITE_SUCCESS)
176         {
177             break;
178         }
179 
180         status = Cy_Cryptolite_Hmac_Sha256_Start (base, prk, prkLength, &cfContext);
181         if(status != CY_CRYPTOLITE_SUCCESS)
182         {
183             break;
184         }
185 
186         status = Cy_Cryptolite_Hmac_Sha256_Update (base, t, tLength, &cfContext);
187         if(status != CY_CRYPTOLITE_SUCCESS)
188         {
189             break;
190         }
191 
192         status = Cy_Cryptolite_Hmac_Sha256_Update (base, info, infoLength, &cfContext);
193         if(status != CY_CRYPTOLITE_SUCCESS)
194         {
195             break;
196         }
197 
198         status = Cy_Cryptolite_Hmac_Sha256_Update (base, &counter, 1u, &cfContext);
199         if(status != CY_CRYPTOLITE_SUCCESS)
200         {
201             break;
202         }
203 
204         status = Cy_Cryptolite_Hmac_Sha256_Finish (base, t, &cfContext);
205         if(status != CY_CRYPTOLITE_SUCCESS)
206         {
207             break;
208         }
209 
210         status =  Cy_Cryptolite_Hmac_Sha256_Free(base, &cfContext);
211         if(status != CY_CRYPTOLITE_SUCCESS)
212         {
213             break;
214         }
215 
216         if(i != n)
217         {
218             bytesCopy = hashlen;
219         }
220         else
221         {
222             bytesCopy = okmLength - offset;
223         }
224 
225         status =  Cy_Cryptolite_Memcpy(base, (okm + offset), t, bytesCopy);
226         if(status != CY_CRYPTOLITE_SUCCESS)
227         {
228             break;
229         }
230 
231         offset += hashlen;
232         tLength = hashlen;
233     }
234 
235     return status;
236 }
237 
238 
239 
240 /*******************************************************************************
241 * Function Name: Cy_Cryptolite_Hkdf
242 ****************************************************************************//**
243 *
244 * Performs HKDF calculation.
245 *
246 * \param base
247 * The pointer to the CRYPTOLITE instance.
248 *
249 * \param salt
250 * The pointer to salt.
251 *
252 * \param saltLength
253 * The size of a salt.
254 *
255 * \param ikm
256 * The pointer to the Input Key material.
257 *
258 * \param ikmLength
259 * The length of the IKM.
260 *
261 * \param info
262 * The pointer to info.
263 *
264 * \param infoLength
265 * The length of the info.
266 *
267 * \param okm
268 * The pointer to Output key material.
269 *
270 * \param okmLength
271 * The length of okm to be generated.
272 *
273 * \return
274 * \ref cy_en_cryptolite_status_t
275 *
276 *******************************************************************************/
Cy_Cryptolite_Hkdf(CRYPTOLITE_Type * base,uint8_t const * salt,uint32_t saltLength,uint8_t const * ikm,uint32_t ikmLength,uint8_t const * info,uint32_t infoLength,uint8_t * okm,uint32_t okmLength)277 cy_en_cryptolite_status_t Cy_Cryptolite_Hkdf(CRYPTOLITE_Type *base,
278                                           uint8_t  const *salt,
279                                           uint32_t saltLength,
280                                           uint8_t  const *ikm,
281                                           uint32_t ikmLength,
282                                           uint8_t  const *info,
283                                           uint32_t infoLength,
284                                           uint8_t *okm,
285                                           uint32_t okmLength)
286 {
287     cy_en_cryptolite_status_t status = CY_CRYPTOLITE_BAD_PARAMS;
288     CY_ALIGN(4) uint8_t prk[CY_CRYPTOLITE_SHA256_HASH_SIZE]  = {0u};
289 
290     /* Input parameters verification */
291     if ((NULL == base) || ((NULL == salt) && (0UL != saltLength))
292         ||((NULL == ikm) && (0UL != ikmLength)) || ((NULL == info) && (0UL != infoLength))
293         ||((NULL == okm) && (0UL != okmLength)))
294     {
295         return status;
296     }
297 
298     Cy_Cryptolite_Memset (prk, 0u, CY_CRYPTOLITE_SHA256_HASH_SIZE);
299 
300     status = Cy_Cryptolite_Hkdf_Extract(base, salt, saltLength, ikm, ikmLength, prk);
301     if(status != CY_CRYPTOLITE_SUCCESS)
302     {
303         return status;
304     }
305 
306     status = Cy_Cryptolite_Hkdf_Expand(base, prk, CY_CRYPTOLITE_SHA256_HASH_SIZE, info, infoLength, okm, okmLength);
307 
308     Cy_Cryptolite_Memset ( prk, 0u, CY_CRYPTOLITE_SHA256_HASH_SIZE);
309 
310     return status;
311 }
312 
313 
314 #endif /* CRYPTOLITE_SHA_PRESENT */
315 #endif  /* defined(CY_CRYPTOLITE_CFG_HKDF_C) && defined(CY_CRYPTOLITE_CFG_HMAC_C) */
316 
317 #if defined(__cplusplus)
318 }
319 #endif
320 
321 
322 #endif /* defined(CY_IP_MXCRYPTOLITE) */
323 
324 
325 /* [] END OF FILE */
326