1 /***************************************************************************//**
2 * \file cy_cryptolite_hmac.c
3 * \version 2.50
4 *
5 * \brief
6 *  Provides API implementation of the Cryptolite HAMC-SHA256 PDL driver.
7 *
8 ********************************************************************************
9 * Copyright 2020 Cypress Semiconductor Corporation
10 * SPDX-License-Identifier: Apache-2.0
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 *    http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *******************************************************************************/
24 
25 #include "cy_device.h"
26 
27 #if defined (CY_IP_MXCRYPTOLITE)
28 
29 #include "cy_cryptolite_hmac.h"
30 
31 #if defined(__cplusplus)
32 extern "C" {
33 #endif
34 
35 #if (CRYPTOLITE_SHA_PRESENT == 1)
36 #if defined(CY_CRYPTOLITE_CFG_HMAC_C) && defined(CY_CRYPTOLITE_CFG_SHA2_256_ENABLED)
37 
38 CY_MISRA_DEVIATE_BLOCK_START('MISRA C-2012 Directive 4.7', 3, \
39 'Coverity does not seem to allow return of a error status without a check.')
40 
41 /*****************************************************************************
42 * Cy_Cryptolite_Hmac_Sha256_Init
43 ******************************************************************************
44 *
45 * The function to initialize the HMAC SHA256 operation.
46 *
47 *  base
48 * The pointer to the Cryptolite instance.
49 *
50 *  cfContext
51 * The pointer to the cy_stc_cryptolite_context_hmac_sha256_t structure that stores all
52 * internal variables for Cryptolite driver.
53 *
54 * return
55 * cy_en_cryptolite_status_t
56 *
57 *******************************************************************************/
Cy_Cryptolite_Hmac_Sha256_Init(CRYPTOLITE_Type * base,cy_stc_cryptolite_context_hmac_sha256_t * cfContext)58 cy_en_cryptolite_status_t Cy_Cryptolite_Hmac_Sha256_Init(CRYPTOLITE_Type *base,
59                                         cy_stc_cryptolite_context_hmac_sha256_t *cfContext)
60 {
61     cy_en_cryptolite_status_t status;
62 
63     /* Input parameters verification */
64     if ((NULL == base) || (NULL == cfContext))
65     {
66         return CY_CRYPTOLITE_BAD_PARAMS;
67     }
68 
69     cfContext->blocksize  = (uint16_t)CY_CRYPTOLITE_SHA256_BLOCK_SIZE;
70     cfContext->digestsize = (uint16_t)CY_CRYPTOLITE_SHA256_HASH_SIZE;
71     /*Init SHA 256*/
72     status = Cy_Cryptolite_Sha256_Init( base, &cfContext->ctx_sha256);
73 
74     return status;
75 }
76 
77 /*******************************************************************************
78 * Cy_Cryptolite_Hmac_Sha256_Start
79 ******************************************************************************
80 *
81 * Initializes the initial Hash vector.
82 *
83 *  base
84 * The pointer to the CRYPTOLITE instance.
85 *
86 *  key
87 * The pointer to the HMAC key.
88 *
89 *  keyLength
90 * The length of the HMAC key.
91 *
92 *  cfContext
93 * The pointer to the cy_stc_cryptolite_context_hmac_sha256_t structure that stores all
94 * internal variables for Cryptolite driver.
95 *
96 * return
97 * cy_en_cryptolite_status_t
98 *
99 *******************************************************************************/
Cy_Cryptolite_Hmac_Sha256_Start(CRYPTOLITE_Type * base,uint8_t const * key,uint32_t keyLength,cy_stc_cryptolite_context_hmac_sha256_t * cfContext)100 cy_en_cryptolite_status_t Cy_Cryptolite_Hmac_Sha256_Start(CRYPTOLITE_Type *base,
101                                         uint8_t const *key,
102                                         uint32_t keyLength,
103                                         cy_stc_cryptolite_context_hmac_sha256_t *cfContext)
104 {
105     uint32_t i;
106     uint32_t blockSizeTmp;
107     uint32_t digestSizeTmp;
108     uint8_t *ipadPtrTmp;
109     uint8_t *opadPtrTmp;
110     uint8_t *m0KeyPtrTmp;
111 
112     cy_en_cryptolite_status_t status = CY_CRYPTOLITE_SUCCESS;
113 
114     /* Input parameters verification */
115     if ((NULL == base) || (NULL == cfContext) || ((NULL == key) && (0UL != keyLength)) )
116     {
117         return CY_CRYPTOLITE_BAD_PARAMS;
118     }
119 
120     blockSizeTmp    = cfContext->blocksize;
121     digestSizeTmp   = cfContext->digestsize;
122     ipadPtrTmp      = (uint8_t*)cfContext->ipad;
123     opadPtrTmp      = (uint8_t*)cfContext->opad;
124     m0KeyPtrTmp     = (uint8_t*)cfContext->m0Key;
125 
126     /*check if IP is busy*/
127     if ((REG_CRYPTOLITE_STATUS(base) & CRYPTOLITE_STATUS_BUSY_Msk) != 0UL)
128     {
129         return CY_CRYPTOLITE_HW_BUSY;
130     }
131 
132     for (i=0U; i < CY_CRYPTOLITE_SHA256_BLOCK_SIZE; i++)
133     {
134         cfContext->ipad[i]  = 0;
135         cfContext->opad[i]  = 0;
136         cfContext->m0Key[i] = 0;
137     }
138 
139     /* Steps 1-3 according to FIPS 198-1 */
140     if (keyLength > blockSizeTmp)
141     {
142         /* The key is larger than the block size. Do a hash on the key. */
143         status = Cy_Cryptolite_Sha256_Start( base, &cfContext->ctx_sha256);
144 
145         if (CY_CRYPTOLITE_SUCCESS == status)
146         {
147             status = Cy_Cryptolite_Sha256_Update (base, key, keyLength, &cfContext->ctx_sha256);
148         }
149         if (CY_CRYPTOLITE_SUCCESS == status)
150         {
151             status = Cy_Cryptolite_Sha256_Finish (base, m0KeyPtrTmp, &cfContext->ctx_sha256);
152         }
153         /* Append zeros */
154         for (i=0U; i < (uint32_t)(blockSizeTmp - digestSizeTmp); i++)
155         {
156             m0KeyPtrTmp[digestSizeTmp + i] = 0x00u;
157         }
158     }
159     else /*(keyLength < blockSizeTmp)*/
160     {
161         /* If the key is shorter than the block, append zeros */
162         for (i=0U; i < keyLength; i++)
163         {
164             m0KeyPtrTmp[i] = key[i];
165         }
166         /* Append zeros */
167         for (i=0U; i < (uint32_t)(blockSizeTmp - keyLength); i++)
168         {
169             m0KeyPtrTmp[keyLength + i] = 0x00u;
170         }
171     }
172 
173     if (CY_CRYPTOLITE_SUCCESS == status)
174     {
175         /* Steps 4 and 7 according to FIPS 198-1 */
176         for (i=0U; i < blockSizeTmp; i++)
177         {
178             ipadPtrTmp[i] = CY_CRYPTOLITE_HMAC_IPAD ^ m0KeyPtrTmp[i];
179             opadPtrTmp[i] = CY_CRYPTOLITE_HMAC_0PAD ^ m0KeyPtrTmp[i];
180         }
181 
182         /* Step 6 according to FIPS 198-1 */
183         status = Cy_Cryptolite_Sha256_Start( base, &cfContext->ctx_sha256);
184 
185         if (CY_CRYPTOLITE_SUCCESS == status)
186         {
187             status = Cy_Cryptolite_Sha256_Update (base, ipadPtrTmp, blockSizeTmp, &cfContext->ctx_sha256);
188         }
189     }
190 
191     return status;
192 }
193 
194 /*******************************************************************************
195 * Cy_Cryptolite_Hmac_Sha256_Update
196 ********************************************************************************
197 *
198 * Performs the SHA256 calculation on one message.
199 *
200 *  base
201 * The pointer to the CRYPTOLITE instance.
202 *
203 *  cfContext
204 * The pointer to the cy_stc_cryptolite_context_hmac_sha256_t structure that stores all
205 * internal variables for Cryptolite driver.
206 *
207 *  message
208 * The pointer to the message whose Hash is being computed.
209 *
210 *  messageSize
211 * The size of the message whose Hash is being computed.
212 *
213 * return
214 * cy_en_cryptolite_status_t
215 *
216 *******************************************************************************/
Cy_Cryptolite_Hmac_Sha256_Update(CRYPTOLITE_Type * base,uint8_t const * message,uint32_t messageSize,cy_stc_cryptolite_context_hmac_sha256_t * cfContext)217 cy_en_cryptolite_status_t Cy_Cryptolite_Hmac_Sha256_Update(CRYPTOLITE_Type *base,
218                                         uint8_t const *message,
219                                         uint32_t  messageSize,
220                                         cy_stc_cryptolite_context_hmac_sha256_t *cfContext)
221 {
222     cy_en_cryptolite_status_t status = CY_CRYPTOLITE_BAD_PARAMS;
223 
224     if (0UL == messageSize)
225     {
226         return CY_CRYPTOLITE_SUCCESS;
227     }
228 
229     /* Input parameters verification */
230     if ((NULL == base) || (NULL == cfContext) || (NULL == message))
231     {
232         return status;
233     }
234 
235     /*check if IP is busy*/
236     if ((REG_CRYPTOLITE_STATUS(base) & CRYPTOLITE_STATUS_BUSY_Msk) != 0UL)
237     {
238         return CY_CRYPTOLITE_HW_BUSY;
239     }
240 
241     /* Append a message */
242     status = Cy_Cryptolite_Sha256_Update (base,  message, messageSize, &cfContext->ctx_sha256);
243 
244     return status;
245 }
246 
247 /*******************************************************************************
248 * Cy_Cryptolite_Hmac_Sha256_Finish
249 ******************************************************************************
250 *
251 * Completes the SHA256 calculation.
252 *
253 *  base
254 * The pointer to the CRYPTOLITE instance.
255 *
256 *  cfContext
257 * the pointer to the cy_stc_cryptolite_context_hmac_sha256_t structure that stores all
258 * internal variables for Cryptolite driver.
259 *
260 *  hmac
261 * The pointer to the calculated Hash hmac.
262 *
263 * return
264 * cy_en_cryptolite_status_t
265 *
266 *******************************************************************************/
Cy_Cryptolite_Hmac_Sha256_Finish(CRYPTOLITE_Type * base,uint8_t * hmac,cy_stc_cryptolite_context_hmac_sha256_t * cfContext)267 cy_en_cryptolite_status_t Cy_Cryptolite_Hmac_Sha256_Finish(CRYPTOLITE_Type *base,
268                                     uint8_t *hmac,
269                                     cy_stc_cryptolite_context_hmac_sha256_t *cfContext)
270 {
271     uint32_t blockSizeTmp;
272     uint32_t digestSizeTmp;
273     uint8_t *ipadPtrTmp;
274     uint8_t *opadPtrTmp;
275     cy_en_cryptolite_status_t status = CY_CRYPTOLITE_BAD_PARAMS;
276 
277     /* Input parameters verification */
278     if ((NULL == base) || (NULL == cfContext) || (NULL == hmac))
279     {
280         return status;
281     }
282 
283     blockSizeTmp   = cfContext->blocksize;
284     digestSizeTmp  = cfContext->digestsize;
285     ipadPtrTmp  = (uint8_t*)cfContext->ipad;
286     opadPtrTmp  = (uint8_t*)cfContext->opad;
287 
288     /*check if IP is busy*/
289     if ((REG_CRYPTOLITE_STATUS(base) & CRYPTOLITE_STATUS_BUSY_Msk) != 0UL)
290     {
291         return CY_CRYPTOLITE_HW_BUSY;
292     }
293 
294     /*Finish message hash and calculate hmac*/
295     status = Cy_Cryptolite_Sha256_Finish (base, ipadPtrTmp, &cfContext->ctx_sha256);
296 
297     /* Here is the ready part of HASH: Hash((Key^ipad)||text) */
298     if (CY_CRYPTOLITE_SUCCESS == status)
299     {
300         /* Steps 8, 9 according to FIPS 198-1 */
301         status = Cy_Cryptolite_Sha256_Start( base, &cfContext->ctx_sha256);
302 
303         if (CY_CRYPTOLITE_SUCCESS == status)
304         {
305             status = Cy_Cryptolite_Sha256_Update (base, opadPtrTmp, blockSizeTmp, &cfContext->ctx_sha256);
306         }
307         /* Append HASH from Step 6 */
308         if (CY_CRYPTOLITE_SUCCESS == status)
309         {
310             status = Cy_Cryptolite_Sha256_Update (base, ipadPtrTmp, digestSizeTmp, &cfContext->ctx_sha256);
311         }
312         if (CY_CRYPTOLITE_SUCCESS == status)
313         {
314             status = Cy_Cryptolite_Sha256_Finish (base, hmac, &cfContext->ctx_sha256);
315         }
316     }
317 
318     return status;
319 }
320 
321 /*******************************************************************************
322 * Cy_Cryptolite_Hmac_Sha256_Free
323 ******************************************************************************
324 *
325 * Clears the used memory and context data.
326 *
327 *  base
328 * The pointer to the CRYPTOLITE instance.
329 *
330 *  cfContext
331 * the pointer to the cy_stc_cryptolite_context_hmac_sha256_t structure that stores all
332 * internal variables for Cryptolite driver.
333 *
334 * return
335 * cy_en_cryptolite_status_t
336 *
337 *******************************************************************************/
Cy_Cryptolite_Hmac_Sha256_Free(CRYPTOLITE_Type * base,cy_stc_cryptolite_context_hmac_sha256_t * cfContext)338 cy_en_cryptolite_status_t Cy_Cryptolite_Hmac_Sha256_Free(CRYPTOLITE_Type *base,
339                                     cy_stc_cryptolite_context_hmac_sha256_t *cfContext)
340 {
341     uint32_t i;
342 
343     /* Input parameters verification */
344     if (NULL != cfContext)
345     {
346         /* Clear the context memory */
347         for (i=0U; i < CY_CRYPTOLITE_HMAC_MAX_PAD_SIZE; i++)
348         {
349             cfContext->ipad[i]  = 0;
350             cfContext->opad[i]  = 0;
351             cfContext->m0Key[i] = 0;
352         }
353         cfContext->blocksize = 0;
354         cfContext->digestsize = 0;
355 
356         /*Clear hash context*/
357         (void)Cy_Cryptolite_Sha256_Free (base, &cfContext->ctx_sha256);
358     }
359 
360     return CY_CRYPTOLITE_SUCCESS;
361 }
362 
363 /*******************************************************************************
364 * Cy_Cryptolite_Hmac_Sha256_Run
365 ******************************************************************************
366 *
367 * This function performs the HAMC SHA256 MAC function.
368 * Provide the required parameters and the pointer
369 * to the context structure when making this function call.
370 * It is independent of the previous Crypto state because it already contains
371 * preparation, calculation, and finalization steps.
372 *
373 *  base
374 * The pointer to the CRYPTOLITE instance.
375 *
376 *  cfContext
377 * the pointer to the cy_stc_cryptolite_context_hmac_sha256_t structure that stores all
378 * internal variables for Cryptolite driver.
379 *
380 *  message
381 * The pointer to a message whose HMAC is being computed.
382 *
383 *  messageSize
384 * The size of a message in bytes.
385 *
386 *  hmac
387 * The pointer to the hmac.
388 *
389 * return
390 * cy_en_cryptolite_status_t
391 *
392 *******************************************************************************/
Cy_Cryptolite_Hmac_Sha256_Run(CRYPTOLITE_Type * base,uint8_t const * key,uint32_t keyLength,uint8_t const * message,uint32_t messageSize,uint8_t * hmac,cy_stc_cryptolite_context_hmac_sha256_t * cfContext)393 cy_en_cryptolite_status_t Cy_Cryptolite_Hmac_Sha256_Run(CRYPTOLITE_Type *base,
394                                         uint8_t const *key,
395                                         uint32_t keyLength,
396                                         uint8_t const *message,
397                                         uint32_t  messageSize,
398                                         uint8_t *hmac,
399                                         cy_stc_cryptolite_context_hmac_sha256_t *cfContext)
400 {
401     cy_en_cryptolite_status_t status = CY_CRYPTOLITE_BAD_PARAMS;
402     /* Input parameters verification */
403     if ((NULL == base) || (NULL == cfContext) || (NULL == hmac) || ((NULL == message) && (0UL != messageSize))
404         || ((NULL == key) && (0UL != keyLength)))
405     {
406         return status;
407     }
408 
409     status = Cy_Cryptolite_Hmac_Sha256_Init (base, cfContext);
410 
411     if (CY_CRYPTOLITE_SUCCESS == status)
412     {
413         status = Cy_Cryptolite_Hmac_Sha256_Start (base, key, keyLength, cfContext);
414     }
415     if (CY_CRYPTOLITE_SUCCESS == status)
416     {
417         status = Cy_Cryptolite_Hmac_Sha256_Update (base, message, messageSize, cfContext);
418     }
419     if (CY_CRYPTOLITE_SUCCESS == status)
420     {
421         status = Cy_Cryptolite_Hmac_Sha256_Finish (base, hmac, cfContext);
422     }
423     if (CY_CRYPTOLITE_SUCCESS == status)
424     {
425         status = Cy_Cryptolite_Hmac_Sha256_Free (base, cfContext);
426     }
427 
428     return status;
429 }
430 CY_MISRA_BLOCK_END('MISRA C-2012 Directive 4.7')
431 
432 #endif
433 #endif /* CY_CRYPTOLITE_CFG_HMAC_C */
434 
435 #if defined(__cplusplus)
436 }
437 #endif
438 
439 
440 #endif /* CY_IP_MXCRYPTOLITE */
441 /* [] END OF FILE */
442