1 /***************************************************************************//**
2 * \file cy_crypto_core_hmac_v1.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_v1.h"
33 
34 #if defined(CY_CRYPTO_CFG_HW_V1_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_v1.h"
43 #include "cy_crypto_core_hw_v1.h"
44 #include "cy_crypto_core_mem_v1.h"
45 #include "cy_syslib.h"
46 
47 #define CY_CRYPTO_HMAC_IPAD               (0x36u)
48 #define CY_CRYPTO_HMAC_0PAD               (0x5Cu)
49 #define CY_CRYPTO_HMAC_MAX_PAD_SIZE       (128u)
50 #define CY_CRYPTO_HMAC_MAX_M0_KEY_SIZE    (128u)
51 
52 typedef struct
53 {
54     uint8_t *ipad;
55     uint8_t *opad;
56     uint8_t *m0Key;
57 } cy_stc_crypto_v1_hmac_state_t;
58 
59 /* Allocating internal variables into the CRYPTO SRAM Buffer */
60 typedef struct
61 {
62     uint32_t ipad[CY_CRYPTO_HMAC_MAX_PAD_SIZE / 4u];
63     uint32_t opad[CY_CRYPTO_HMAC_MAX_PAD_SIZE / 4u];
64     uint32_t m0Key[CY_CRYPTO_SHA_MAX_BLOCK_SIZE / 4u];
65     cy_stc_crypto_v1_sha_buffers_t shaBuffers;
66     cy_stc_crypto_v1_hmac_state_t hmacState;
67 } cy_stc_crypto_hmac_buffers_t;
68 
69 /* Functions declarations */
70 static void Cy_Crypto_Core_V1_Hmac_Init(cy_stc_crypto_v1_hmac_state_t *hmacState,
71                                 uint8_t *ipad,
72                                 uint8_t *opad,
73                                 uint8_t *m0Key);
74 
75 static cy_en_crypto_status_t Cy_Crypto_Core_V1_Hmac_Calculate(CRYPTO_Type *base,
76                                    cy_stc_crypto_v1_hmac_state_t *hmacState,
77                                    cy_stc_crypto_sha_state_t *hashState,
78                                    uint8_t const *key,
79                                    uint32_t keyLength,
80                                    uint8_t const *message,
81                                    uint32_t messageSize,
82                                    uint8_t *hmac);
83 
84 static void Cy_Crypto_Core_V1_Hmac_Free(CRYPTO_Type *base,
85                                    cy_stc_crypto_v1_hmac_state_t *hmacState);
86 
87 /*******************************************************************************
88 * Function Name: Cy_Crypto_Core_V1_Hmac_Init
89 ****************************************************************************//**
90 *
91 * Initializes HMAC (Hash-based Message Authentication Code) calculation.
92 * User should allocate two buffers (ipad and opad) for HMAC calculation.
93 *
94 * \param hmacState
95 * the pointer to the hmacState structure which stores internal variables
96 * for HMAC calculation.
97 *
98 * \param ipad
99 * The memory buffer for HMAC calculation,
100 * the max used size = CRYPTO_HMAC_MAX_PAD_SIZE.
101 *
102 * \param opad
103 * The memory buffer for HMAC calculation,
104 * the max used size = CRYPTO_HMAC_MAX_PAD_SIZE.
105 *
106 * \param m0Key
107 * The memory buffer for HMAC calculation,
108 * the max used size = CRYPTO_HMAC_MAX_M0_KEY_SIZE.
109 *
110 *******************************************************************************/
Cy_Crypto_Core_V1_Hmac_Init(cy_stc_crypto_v1_hmac_state_t * hmacState,uint8_t * ipad,uint8_t * opad,uint8_t * m0Key)111 static void Cy_Crypto_Core_V1_Hmac_Init(cy_stc_crypto_v1_hmac_state_t *hmacState,
112                                 uint8_t *ipad,
113                                 uint8_t *opad,
114                                 uint8_t *m0Key)
115 {
116     hmacState->ipad  = ipad;
117     hmacState->opad  = opad;
118     hmacState->m0Key = m0Key;
119 }
120 
121 /*******************************************************************************
122 * Function Name: Cy_Crypto_Core_V1_Hmac_Calculate
123 ****************************************************************************//**
124 *
125 * Starts HMAC (Hash-based Message Authentication Code) calculation.
126 *
127 * \param base
128 * The pointer to the CRYPTO instance.
129 *
130 * \param hmacState
131 * The pointer to the hmacState structure which stores internal variables
132 * for HMAC calculation.
133 *
134 * \param hashState
135 * The pointer to the hashState structure which stores internal variables
136 * of the SHA algorithm because it is used for HMAC calculation.
137 *
138 * \param key
139 * The pointer to the key used in computing SHA.
140 *
141 * \param keyLength
142 * The size of the key.
143 *
144 * \param message
145 * The pointer to the input message.
146 *
147 * \param messageSize
148 * The size of the input message.
149 *
150 * \param hmac
151 * The pointer to the calculated HMAC.
152 *
153 *******************************************************************************/
Cy_Crypto_Core_V1_Hmac_Calculate(CRYPTO_Type * base,cy_stc_crypto_v1_hmac_state_t * hmacState,cy_stc_crypto_sha_state_t * hashState,uint8_t const * key,uint32_t keyLength,uint8_t const * message,uint32_t messageSize,uint8_t * hmac)154 static cy_en_crypto_status_t Cy_Crypto_Core_V1_Hmac_Calculate(CRYPTO_Type *base,
155                                    cy_stc_crypto_v1_hmac_state_t *hmacState,
156                                    cy_stc_crypto_sha_state_t *hashState,
157                                    uint8_t const *key,
158                                    uint32_t keyLength,
159                                    uint8_t const *message,
160                                    uint32_t messageSize,
161                                    uint8_t *hmac)
162 {
163     cy_en_crypto_status_t tmpResult = CY_CRYPTO_SUCCESS;
164 
165     uint32_t i = 0uL;
166     uint8_t *ipadPtrTmp  = (uint8_t*)hmacState->ipad;
167     uint8_t *opadPtrTmp  = (uint8_t*)hmacState->opad;
168     uint8_t *m0KeyPtrTmp = (uint8_t*)hmacState->m0Key;
169 
170     /* Steps 1-3 according to FIPS 198-1 */
171     if (keyLength > hashState->blockSize)
172     {
173         /* The key is larger than the block size. Do a hash on the key. */
174         tmpResult = Cy_Crypto_Core_V1_Sha_Start(base, hashState);
175         if (CY_CRYPTO_SUCCESS == tmpResult)
176         {
177             tmpResult = Cy_Crypto_Core_V1_Sha_Update(base, hashState, key, keyLength);
178         }
179         if (CY_CRYPTO_SUCCESS == tmpResult)
180         {
181             tmpResult = Cy_Crypto_Core_V1_Sha_Finish(base, hashState, (uint8_t*)m0KeyPtrTmp);
182         }
183 
184         if (CY_CRYPTO_SUCCESS == tmpResult)
185         {
186             /* Append zeros */
187             Cy_Crypto_Core_V1_MemSet(base, (m0KeyPtrTmp + hashState->digestSize), 0x00u,
188                    (uint16_t)(hashState->blockSize - hashState->digestSize));
189         }
190     }
191     else if (keyLength < hashState->blockSize)
192     {
193         /* If the key is shorter than the block, append zeros */
194         Cy_Crypto_Core_V1_MemCpy(base, m0KeyPtrTmp, key, (uint16_t)keyLength);
195         Cy_Crypto_Core_V1_MemSet(base, (m0KeyPtrTmp + keyLength), 0x00u, (uint16_t)(hashState->blockSize - keyLength));
196     }
197     else
198     {
199         Cy_Crypto_Core_V1_MemCpy(base, m0KeyPtrTmp, key, (uint16_t)keyLength);
200     }
201 
202     if (CY_CRYPTO_SUCCESS == tmpResult)
203     {
204         /* Steps 4 and 7 according to FIPS 198-1 */
205         while (i < hashState->blockSize)
206         {
207             ipadPtrTmp[i] = CY_CRYPTO_HMAC_IPAD ^ m0KeyPtrTmp[i];
208             opadPtrTmp[i] = CY_CRYPTO_HMAC_0PAD ^ m0KeyPtrTmp[i];
209             i++;
210         }
211 
212         /* Step 6 according to FIPS 198-1 */
213         tmpResult = Cy_Crypto_Core_V1_Sha_Start(base, hashState);
214 
215         if (CY_CRYPTO_SUCCESS == tmpResult)
216         {
217             tmpResult = Cy_Crypto_Core_V1_Sha_Update(base, hashState, ipadPtrTmp, hashState->blockSize);
218         }
219 
220         if (CY_CRYPTO_SUCCESS == tmpResult)
221         {
222             /* Append a message */
223             tmpResult = Cy_Crypto_Core_V1_Sha_Update (base, hashState, message, messageSize);
224         }
225         if (CY_CRYPTO_SUCCESS == tmpResult)
226         {
227             tmpResult = Cy_Crypto_Core_V1_Sha_Finish (base, hashState, ipadPtrTmp);
228         }
229 
230         /* Here is the ready part of HASH: Hash((Key^ipad)||text) */
231 
232         if (CY_CRYPTO_SUCCESS == tmpResult)
233         {
234             /* Steps 8, 9 according to FIPS 198-1 */
235             tmpResult = Cy_Crypto_Core_V1_Sha_Start(base, hashState);
236 
237             if (CY_CRYPTO_SUCCESS == tmpResult)
238             {
239                 tmpResult = Cy_Crypto_Core_V1_Sha_Update(base, hashState, opadPtrTmp, hashState->blockSize);
240             }
241 
242             /* Append HASH from Step 6 */
243             if (CY_CRYPTO_SUCCESS == tmpResult)
244             {
245                 tmpResult = Cy_Crypto_Core_V1_Sha_Update(base, hashState, (uint8_t*)ipadPtrTmp, hashState->digestSize);
246             }
247             if (CY_CRYPTO_SUCCESS == tmpResult)
248             {
249                 tmpResult = Cy_Crypto_Core_V1_Sha_Finish(base, hashState, hmac);
250             }
251         }
252     }
253 
254     return (tmpResult);
255 }
256 
257 /*******************************************************************************
258 * Function Name: Cy_Crypto_Core_V1_Hmac_Free
259 ****************************************************************************//**
260 *
261 * Clears the used memory buffers.
262 *
263 * \param base
264 * The pointer to the CRYPTO instance.
265 *
266 * \param hmacState
267 * The pointer to the HMAC context.
268 *
269 *******************************************************************************/
Cy_Crypto_Core_V1_Hmac_Free(CRYPTO_Type * base,cy_stc_crypto_v1_hmac_state_t * hmacState)270 static void Cy_Crypto_Core_V1_Hmac_Free(CRYPTO_Type *base, cy_stc_crypto_v1_hmac_state_t *hmacState)
271 {
272     /* Clear the memory buffer. */
273     Cy_Crypto_Core_V1_MemSet(base, hmacState->ipad,  0x00u, CY_CRYPTO_HMAC_MAX_PAD_SIZE);
274     Cy_Crypto_Core_V1_MemSet(base, hmacState->opad,  0x00u, CY_CRYPTO_HMAC_MAX_PAD_SIZE);
275     Cy_Crypto_Core_V1_MemSet(base, hmacState->m0Key, 0x00u, CY_CRYPTO_HMAC_MAX_M0_KEY_SIZE);
276 }
277 
278 /*******************************************************************************
279 * Function Name: Cy_Crypto_Core_V1_Hmac
280 ****************************************************************************//**
281 *
282 * Performs HMAC calculation.
283 *
284 * \param base
285 * The pointer to the CRYPTO instance.
286 *
287 * \param hmac
288 * The pointer to the calculated HMAC. Must be 4-byte aligned.
289 *
290 * \param message
291 * The pointer to a message whose hash value is being computed.
292 *
293 * \param messageSize
294 * The size of a message.
295 *
296 * \param key
297 * The pointer to the key.
298 *
299 * \param keyLength
300 * The length of the key.
301 *
302 * \param mode
303 * \ref cy_en_crypto_sha_mode_t
304 *
305 * \return
306 * \ref cy_en_crypto_status_t
307 *
308 *******************************************************************************/
Cy_Crypto_Core_V1_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)309 cy_en_crypto_status_t Cy_Crypto_Core_V1_Hmac(CRYPTO_Type *base,
310                                           uint8_t *hmac,
311                                           uint8_t const *message,
312                                           uint32_t messageSize,
313                                           uint8_t const *key,
314                                           uint32_t keyLength,
315                                           cy_en_crypto_sha_mode_t mode)
316 {
317     cy_en_crypto_status_t tmpResult = CY_CRYPTO_SUCCESS;
318 
319     /* Allocating internal variables into the CRYPTO SRAM Buffer */
320     cy_stc_crypto_hmac_buffers_t  *hmacBuffers = (cy_stc_crypto_hmac_buffers_t *)((void *)Cy_Crypto_Core_GetVuMemoryAddress(base));
321 
322     cy_stc_crypto_v1_hmac_state_t *hmacStateTmp = &hmacBuffers->hmacState;
323     cy_stc_crypto_sha_state_t      hashStateLoc = { 0 };
324 
325     uint8_t *ipadTmp      = (uint8_t*)(&hmacBuffers->ipad);
326     uint8_t *opadTmp      = (uint8_t*)(&hmacBuffers->opad);
327     uint8_t *m0KeyTmp     = (uint8_t*)(&hmacBuffers->m0Key);
328 
329     tmpResult = Cy_Crypto_Core_V1_Sha_Init(base, &hashStateLoc, mode, &hmacBuffers->shaBuffers);
330 
331     if (CY_CRYPTO_SUCCESS == tmpResult)
332     {
333         Cy_Crypto_Core_V1_Hmac_Init(hmacStateTmp, ipadTmp, opadTmp, m0KeyTmp);
334         tmpResult = Cy_Crypto_Core_V1_Hmac_Calculate (base, hmacStateTmp, &hashStateLoc, key, keyLength, message, messageSize, hmac);
335         Cy_Crypto_Core_V1_Hmac_Free(base, hmacStateTmp);
336     }
337 
338     (void)Cy_Crypto_Core_V1_Sha_Free(base, &hashStateLoc);
339 
340     return (tmpResult);
341 }
342 
343 #endif /* (CPUSS_CRYPTO_SHA == 1) && defined(CY_CRYPTO_CFG_HMAC_C) */
344 
345 #if defined(__cplusplus)
346 }
347 #endif
348 
349 #endif /* defined(CY_CRYPTO_CFG_HW_V1_ENABLE) */
350 
351 #endif /* defined(CY_IP_MXCRYPTO) */
352 
353 
354 /* [] END OF FILE */
355