1 /***************************************************************************//**
2 * \file cy_crypto_core_hmac_v2.c
3 * \version 2.120
4 *
5 * \brief
6 *  This file provides the source code to the API for the HMAC method
7 *  in the Crypto block driver.
8 *
9 ********************************************************************************
10 * \copyright
11 * Copyright (c) (2020-2022), 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_MXCRYPTO)
31 
32 #include "cy_crypto_core_hmac_v2.h"
33 
34 #if defined(CY_CRYPTO_CFG_HW_V2_ENABLE)
35 
36 #if defined(__cplusplus)
37 extern "C" {
38 #endif
39 
40 #if (CPUSS_CRYPTO_SHA == 1) && defined(CY_CRYPTO_CFG_HMAC_C)
41 
42 #include "cy_crypto_core_sha_v2.h"
43 #include "cy_crypto_core_mem_v2.h"
44 #include "cy_syslib.h"
45 
46 /*****************************************************************************
47 * Cy_Crypto_Core_V2_Hmac_Init
48 ******************************************************************************
49 *
50 * The function to initialize the HMAC operation.
51 *
52 * For CAT1C & CAT1D(CM55) devices when D-Cache is enabled parameters hmacState and hmacBuffer must align and end in 32 byte boundary.
53 *
54 * \param base
55 * The pointer to the CRYPTO instance.
56 *
57 * \param hmacState
58 * The pointer to the cy_stc_crypto_hmac_state_t structure that stores all
59 * internal state for mxcrypto driver.
60 *
61 * \param mode
62 * The hash mode for HMAC.
63 *
64 * \param hmacBuffer
65 * The pointer to the cy_stc_crypto_v2_hmac_buffers_t structure that stores all
66 * buffers for HMAC operation.
67 *
68 * \return
69 * cy_en_crypto_status_t
70 *
71 *******************************************************************************/
72 
Cy_Crypto_Core_V2_Hmac_Init(CRYPTO_Type * base,cy_stc_crypto_hmac_state_t * hmacState,cy_en_crypto_sha_mode_t mode,cy_stc_crypto_v2_hmac_buffers_t * hmacBuffer)73 cy_en_crypto_status_t Cy_Crypto_Core_V2_Hmac_Init(CRYPTO_Type *base, cy_stc_crypto_hmac_state_t *hmacState, cy_en_crypto_sha_mode_t mode, cy_stc_crypto_v2_hmac_buffers_t *hmacBuffer)
74 {
75 
76 
77     /* Input parameters verification */
78     if ((NULL == base) || (NULL == hmacState) || (NULL == hmacBuffer))
79     {
80         return CY_CRYPTO_BAD_PARAMS;
81     }
82 
83     hmacState->ipad = hmacBuffer->ipad;
84     hmacState->opad = hmacBuffer->opad;
85     hmacState->m0Key = hmacBuffer->m0Key;
86     hmacState->sha_buffer = &hmacBuffer->shaBuffers;
87 
88 
89     return Cy_Crypto_Core_V2_Sha_Init(base, &hmacState->hashState, mode, hmacState->sha_buffer);
90 
91 }
92 
93 
94 
95 /*******************************************************************************
96 * Cy_Crypto_Core_V2_Hmac_Start
97 ******************************************************************************
98 *
99 * Initializes the initial Hash vector.
100 *
101 * For CAT1C & CAT1D(CM55) devices when D-Cache is enabled parameters key & hmacState (m0Key) must align and end in 32 byte boundary.
102 *
103 * \param base
104 * The pointer to the CRYPTO instance.
105 *
106 * \param hmacState
107 * The pointer to the cy_stc_crypto_hmac_state_t structure that stores all
108 * internal state for mxcrypto driver.
109 *
110 * \param key
111 * The pointer to the HMAC key.
112 *
113 * \param keyLength
114 * The size of the input key
115 *
116 * \return
117 * cy_en_crypto_status_t
118 *
119 *******************************************************************************/
120 
Cy_Crypto_Core_V2_Hmac_Start(CRYPTO_Type * base,cy_stc_crypto_hmac_state_t * hmacState,uint8_t const * key,uint32_t keyLength)121 cy_en_crypto_status_t Cy_Crypto_Core_V2_Hmac_Start(CRYPTO_Type *base, cy_stc_crypto_hmac_state_t *hmacState,
122                                         uint8_t const *key,
123                                         uint32_t keyLength
124                                         )
125 
126 {
127 
128     uint32_t i = 0uL;
129     uint32_t blockSizeTmp;
130     uint32_t digestSizeTmp;
131     uint8_t *ipadRemap;
132     uint8_t *opadRemap;
133     uint8_t *m0KeyRemap;
134     cy_en_crypto_status_t status = CY_CRYPTO_SUCCESS;
135     uint8_t *ipadPtr;
136     uint8_t *opadPtr;
137     uint8_t *m0KeyPtr;
138 
139     /* Input parameters verification */
140     if ((NULL == base) || (NULL == hmacState) || ((NULL == key) && (0UL != keyLength)) )
141     {
142         return CY_CRYPTO_BAD_PARAMS;
143     }
144 
145     blockSizeTmp   = hmacState->hashState.blockSize;
146     digestSizeTmp  = hmacState->hashState.digestSize;
147     ipadRemap  = (uint8_t*)CY_REMAP_ADDRESS_FOR_CRYPTO(hmacState->ipad);
148     opadRemap  = (uint8_t*)CY_REMAP_ADDRESS_FOR_CRYPTO(hmacState->opad);
149     m0KeyRemap = (uint8_t*)CY_REMAP_ADDRESS_FOR_CRYPTO(hmacState->m0Key);
150 
151     ipadPtr = hmacState->ipad;
152     opadPtr = hmacState->opad;
153     m0KeyPtr = hmacState->m0Key;
154 
155 #if (((CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)) || CY_CPU_CORTEX_M55)
156         /* Flush the cache */
157         SCB_CleanDCache_by_Addr((volatile void *)key,(int32_t)keyLength);
158 #endif
159     Cy_Crypto_Core_V2_MemSet(base, m0KeyRemap, 0x00u, (uint16_t)blockSizeTmp);
160     Cy_Crypto_Core_V2_MemSet(base, ipadRemap, 0x00u, (uint16_t)blockSizeTmp);
161     Cy_Crypto_Core_V2_MemSet(base, opadRemap, 0x00u, (uint16_t)blockSizeTmp);
162 
163     /* Steps 1-3 according to FIPS 198-1 */
164     if (keyLength > blockSizeTmp)
165     {
166         /* The key is larger than the block size. Do a hash on the key. */
167         status = Cy_Crypto_Core_V2_Sha_Start  (base, &hmacState->hashState);
168 
169         if (CY_CRYPTO_SUCCESS == status)
170         {
171             status = Cy_Crypto_Core_V2_Sha_Update (base, &hmacState->hashState, key, keyLength);
172         }
173         if (CY_CRYPTO_SUCCESS == status)
174         {
175             status = Cy_Crypto_Core_V2_Sha_Finish (base, &hmacState->hashState, m0KeyRemap);
176         }
177 
178         /* Append zeros */
179         Cy_Crypto_Core_V2_MemSet(base, (m0KeyRemap + digestSizeTmp), 0x00u, (uint16_t)(blockSizeTmp - digestSizeTmp));
180     }
181     else if (keyLength < blockSizeTmp)
182     {
183         /* If the key is shorter than the block, append zeros */
184         Cy_Crypto_Core_V2_MemCpy(base, m0KeyRemap, key, (uint16_t)keyLength);
185         Cy_Crypto_Core_V2_MemSet(base, m0KeyRemap + keyLength, 0x00u, (uint16_t)(blockSizeTmp - keyLength));
186     }
187     else
188     {
189         Cy_Crypto_Core_V2_MemCpy(base, m0KeyRemap, key, (uint16_t)keyLength);
190     }
191 #if (((CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)) || CY_CPU_CORTEX_M55)
192     SCB_InvalidateDCache_by_Addr(hmacState->m0Key, (int32_t)blockSizeTmp);
193 #endif
194 
195     if (CY_CRYPTO_SUCCESS == status)
196     {
197         /* Steps 4 and 7 according to FIPS 198-1 */
198         while (i < blockSizeTmp)
199         {
200             ipadPtr[i] = CY_CRYPTO_HMAC_IPAD ^ m0KeyPtr[i];
201             opadPtr[i] = CY_CRYPTO_HMAC_0PAD ^ m0KeyPtr[i];
202             i++;
203         }
204 
205 #if (((CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)) || CY_CPU_CORTEX_M55)
206         SCB_CleanDCache_by_Addr((volatile void *)hmacState->ipad,(int32_t)CY_CRYPTO_HMAC_MAX_PAD_SIZE);
207         SCB_CleanDCache_by_Addr((volatile void *)hmacState->opad,(int32_t)CY_CRYPTO_HMAC_MAX_PAD_SIZE);
208 #endif
209 
210 
211         /* Step 6 according to FIPS 198-1 */
212         status = Cy_Crypto_Core_V2_Sha_Start (base, &hmacState->hashState);
213 
214         if (CY_CRYPTO_SUCCESS == status)
215         {
216             status = Cy_Crypto_Core_V2_Sha_Update(base, &hmacState->hashState, ipadRemap, blockSizeTmp);
217         }
218 
219 #if (((CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)) || CY_CPU_CORTEX_M55)
220         SCB_InvalidateDCache_by_Addr((volatile void *)hmacState->ipad,(int32_t)CY_CRYPTO_HMAC_MAX_PAD_SIZE);
221         SCB_InvalidateDCache_by_Addr((volatile void *)hmacState->opad,(int32_t)CY_CRYPTO_HMAC_MAX_PAD_SIZE);
222 #endif
223     }
224 
225     return status;
226 
227 }
228 
229 
230 /*******************************************************************************
231 * Cy_Crypto_Core_V2_Hmac_Update
232 ******************************************************************************
233 *
234 * Performs the multipart hmac operation.
235 *
236 * \param base
237 * The pointer to the CRYPTO instance.
238 *
239 * \param hmacState
240 * The pointer to the cy_stc_crypto_hmac_state_t structure that stores all
241 * internal state for mxcrypto driver.
242 *
243 * \param message
244 * The pointer to the message.
245 *
246 * \param messageSize
247 * The size of the message
248 *
249 * \return
250 * cy_en_crypto_status_t
251 *
252 *******************************************************************************/
253 
Cy_Crypto_Core_V2_Hmac_Update(CRYPTO_Type * base,cy_stc_crypto_hmac_state_t * hmacState,uint8_t const * message,uint32_t messageSize)254  cy_en_crypto_status_t Cy_Crypto_Core_V2_Hmac_Update(CRYPTO_Type *base, cy_stc_crypto_hmac_state_t  *hmacState,
255                                    uint8_t const  *message,
256                                    uint32_t  messageSize
257                                    )
258 {
259 
260     if (0UL == messageSize)
261     {
262         return CY_CRYPTO_SUCCESS;
263     }
264 
265     /* Input parameters verification */
266     if ((NULL == base) || (NULL == hmacState) || (NULL == message))
267     {
268         return CY_CRYPTO_BAD_PARAMS;
269     }
270 
271     return Cy_Crypto_Core_V2_Sha_Update(base, &hmacState->hashState, message, messageSize);
272 
273 }
274 
275 
276 
277 /*******************************************************************************
278 * Cy_Crypto_Core_V2_Hmac_Finish
279 ******************************************************************************
280 *
281 * Finishes the hmac operation.
282 *
283 * \param base
284 * The pointer to the CRYPTO instance.
285 *
286 * \param hmacState
287 * The pointer to the cy_stc_crypto_hmac_state_t structure that stores all
288 * internal state for mxcrypto driver.
289 *
290 * \param hmac
291 * The pointer to store the hmac value.
292 *
293 * \return
294 * cy_en_crypto_status_t
295 *
296 *******************************************************************************/
297 
Cy_Crypto_Core_V2_Hmac_Finish(CRYPTO_Type * base,cy_stc_crypto_hmac_state_t * hmacState,uint8_t * hmac)298 cy_en_crypto_status_t Cy_Crypto_Core_V2_Hmac_Finish(CRYPTO_Type *base, cy_stc_crypto_hmac_state_t *hmacState,
299                                                     uint8_t *hmac)
300 
301 {
302     uint32_t blockSizeTmp;
303     uint32_t digestSizeTmp;
304     uint8_t *ipadPtrTmp;
305     uint8_t *opadPtrTmp;
306     cy_en_crypto_status_t status = CY_CRYPTO_BAD_PARAMS;
307 
308     /* Input parameters verification */
309     if ((NULL == base) || (NULL == hmacState) || (NULL == hmac))
310     {
311         return status;
312     }
313 
314     blockSizeTmp  = hmacState->hashState.blockSize;
315     digestSizeTmp = hmacState->hashState.digestSize;
316     ipadPtrTmp = (uint8_t*)hmacState->ipad;
317     opadPtrTmp = (uint8_t*)hmacState->opad;
318 
319     status = Cy_Crypto_Core_V2_Sha_Finish(base, &hmacState->hashState, ipadPtrTmp);
320 
321     /* Here is the ready part of HASH: Hash((Key^ipad)||text) */
322 
323     if (CY_CRYPTO_SUCCESS == status)
324     {
325         /* Steps 8, 9 according to FIPS 198-1 */
326         status = Cy_Crypto_Core_V2_Sha_Start(base, &hmacState->hashState);
327 
328         if (CY_CRYPTO_SUCCESS == status)
329         {
330             status = Cy_Crypto_Core_V2_Sha_Update(base, &hmacState->hashState, opadPtrTmp, blockSizeTmp);
331         }
332 
333         /* Append HASH from Step 6 */
334         if (CY_CRYPTO_SUCCESS == status)
335         {
336             status = Cy_Crypto_Core_V2_Sha_Update(base, &hmacState->hashState, ipadPtrTmp, digestSizeTmp);
337         }
338 
339         if (CY_CRYPTO_SUCCESS == status)
340         {
341             status = Cy_Crypto_Core_V2_Sha_Finish(base, &hmacState->hashState, hmac);
342         }
343 
344         if (CY_CRYPTO_SUCCESS == status)
345         {
346             status = Cy_Crypto_Core_V2_Sha_Free(base, &hmacState->hashState);
347         }
348     }
349 
350     return status;
351 
352 }
353 
354 
355 /*******************************************************************************
356 * Cy_Crypto_Core_V2_Hmac_Free
357 ******************************************************************************
358 *
359 * Frees the internally stored buffers in hmac context.
360 *
361 * For CAT1C & CAT1D(CM55) devices when D-Cache is enabled parameters hmacState must align and end in 32 byte boundary.
362 *
363 * \param base
364 * The pointer to the CRYPTO instance.
365 *
366 * \param hmacState
367 * The pointer to the cy_stc_crypto_hmac_state_t structure that stores all
368 * internal state for mxcrypto driver.
369 *
370 *
371 * \return
372 * cy_en_crypto_status_t
373 *
374 *******************************************************************************/
Cy_Crypto_Core_V2_Hmac_Free(CRYPTO_Type * base,cy_stc_crypto_hmac_state_t * hmacState)375 cy_en_crypto_status_t Cy_Crypto_Core_V2_Hmac_Free(CRYPTO_Type *base, cy_stc_crypto_hmac_state_t *hmacState)
376 {
377     /* Input parameters verification */
378     if ( (NULL != base) && (NULL != hmacState))
379     {
380         /* Clear the memory buffer. */
381 
382         if (NULL != hmacState->ipad)
383         {
384             Cy_Crypto_Core_V2_MemSet(base, hmacState->ipad, 0u, CY_CRYPTO_HMAC_MAX_PAD_SIZE);
385         }
386 
387         if (NULL != hmacState->opad)
388         {
389             Cy_Crypto_Core_V2_MemSet(base, hmacState->opad, 0u, CY_CRYPTO_HMAC_MAX_PAD_SIZE);
390         }
391 
392         if (NULL != hmacState->m0Key)
393         {
394             Cy_Crypto_Core_V2_MemSet(base, hmacState->m0Key, 0u, CY_CRYPTO_SHA_MAX_BLOCK_SIZE);
395         }
396 
397         Cy_Crypto_Core_V2_MemSet(base, hmacState, 0u, ((uint16_t)sizeof(cy_stc_crypto_hmac_state_t)));
398     #if (((CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)) || CY_CPU_CORTEX_M55)
399         SCB_InvalidateDCache_by_Addr(hmacState->ipad, (int32_t)CY_CRYPTO_HMAC_MAX_PAD_SIZE);
400         SCB_InvalidateDCache_by_Addr(hmacState->opad, (int32_t)CY_CRYPTO_HMAC_MAX_PAD_SIZE);
401         SCB_InvalidateDCache_by_Addr(hmacState->m0Key, (int32_t)CY_CRYPTO_SHA_MAX_BLOCK_SIZE);
402         SCB_InvalidateDCache_by_Addr(hmacState, (int32_t)sizeof(cy_stc_crypto_hmac_state_t));
403     #endif
404 
405     }
406 
407 
408     return CY_CRYPTO_SUCCESS;
409 
410 }
411 
412 /*******************************************************************************
413 * Function Name: Cy_Crypto_Core_V2_Hmac
414 ****************************************************************************//**
415 *
416 * Performs HMAC calculation.
417 *
418 * For CAT1A and CAT1C devices with DCache disabled, hmac must be 4-byte aligned.
419 *
420 * \param base
421 * The pointer to the CRYPTO instance.
422 *
423 * \param hmac
424 * The pointer to the calculated HMAC.
425 *
426 * \param message
427 * The pointer to a message whose hash value is being computed.
428 *
429 * \param messageSize
430 * The size of a message.
431 *
432 * \param key
433 * The pointer to the key.
434 *
435 * \param keyLength
436 * The length of the key.
437 *
438 * \param mode
439 * \ref cy_en_crypto_sha_mode_t
440 *
441 * \return
442 * \ref cy_en_crypto_status_t
443 *
444 *******************************************************************************/
Cy_Crypto_Core_V2_Hmac(CRYPTO_Type * base,uint8_t * hmac,uint8_t const * message,uint32_t messageSize,uint8_t const * key,uint32_t keyLength,cy_en_crypto_sha_mode_t mode)445 cy_en_crypto_status_t Cy_Crypto_Core_V2_Hmac(CRYPTO_Type *base,
446                                           uint8_t *hmac,
447                                           uint8_t const *message,
448                                           uint32_t messageSize,
449                                           uint8_t const *key,
450                                           uint32_t keyLength,
451                                           cy_en_crypto_sha_mode_t mode)
452 {
453     cy_en_crypto_status_t status = CY_CRYPTO_BAD_PARAMS;
454     /* Allocating internal variables into the RAM */
455 #if (((CY_CPU_CORTEX_M7) && defined (ENABLE_CM7_DATA_CACHE)) || CY_CPU_CORTEX_M55)
456     CY_ALIGN(__SCB_DCACHE_LINE_SIZE) static cy_stc_crypto_hmac_state_t  hmacState;
457     CY_ALIGN(__SCB_DCACHE_LINE_SIZE) static cy_stc_crypto_v2_hmac_buffers_t hmacBuffer;
458 #else
459     cy_stc_crypto_hmac_state_t  hmacState = {0};
460     cy_stc_crypto_v2_hmac_buffers_t hmacBuffer = {0};
461 #endif
462 
463     /* Input parameters verification */
464     if ((NULL == base) || (NULL == hmac) || ((NULL == message) && (0UL != messageSize))
465         ||((NULL == key) && (0UL != keyLength)))
466     {
467         return status;
468     }
469 
470     Cy_Crypto_Core_V2_MemSet(base, (void*)&hmacState, 0x00U, (uint16_t)sizeof(cy_stc_crypto_hmac_state_t));
471     Cy_Crypto_Core_V2_MemSet(base, (void*)&hmacBuffer, 0x00U, (uint16_t)sizeof(cy_stc_crypto_v2_hmac_buffers_t));
472 
473     status = Cy_Crypto_Core_V2_Hmac_Init(base, &hmacState, mode, &hmacBuffer);
474 
475     if (CY_CRYPTO_SUCCESS == status)
476     {
477         status = Cy_Crypto_Core_V2_Hmac_Start(base, &hmacState, key, keyLength);
478     }
479 
480     if (CY_CRYPTO_SUCCESS == status)
481     {
482         status = Cy_Crypto_Core_V2_Hmac_Update(base, &hmacState, message, messageSize);
483     }
484 
485     if (CY_CRYPTO_SUCCESS == status)
486     {
487         status =  Cy_Crypto_Core_V2_Hmac_Finish(base, &hmacState, hmac);
488     }
489 
490     if (CY_CRYPTO_SUCCESS == status)
491     {
492         status =  Cy_Crypto_Core_V2_Hmac_Free(base, &hmacState);
493     }
494 
495     return (status);
496 }
497 
498 #endif /* (CPUSS_CRYPTO_SHA == 1) && defined(CY_CRYPTO_CFG_HMAC_C) */
499 
500 #if defined(__cplusplus)
501 }
502 #endif
503 
504 #endif /* defined(CY_CRYPTO_CFG_HW_V2_ENABLE) */
505 
506 #endif /* defined(CY_IP_MXCRYPTO) */
507 
508 
509 /* [] END OF FILE */
510