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