1 /***************************************************************************//**
2 * \file cy_cryptolite_cmac.c
3 * \version 2.30
4 *
5 * \brief
6 * This file provides the source code to the API for the CMAC method
7 * in the Cryptolite block driver.
8 *
9 * Implementation is done in accordance with information from this weblink:
10 * nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38b.pdf
11 *
12 ********************************************************************************
13 * \copyright
14 * Copyright (c) (2020-2022), Cypress Semiconductor Corporation (an Infineon company) or
15 * an affiliate of Cypress Semiconductor Corporation.
16 * SPDX-License-Identifier: Apache-2.0
17 *
18 * Licensed under the Apache License, Version 2.0 (the "License");
19 * you may not use this file except in compliance with the License.
20 * You may obtain a copy of the License at
21 *
22 * http://www.apache.org/licenses/LICENSE-2.0
23 *
24 * Unless required by applicable law or agreed to in writing, software
25 * distributed under the License is distributed on an "AS IS" BASIS,
26 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
27 * See the License for the specific language governing permissions and
28 * limitations under the License.
29 *******************************************************************************/
30
31 #include "cy_device.h"
32
33 #if defined(CY_IP_MXCRYPTOLITE)
34
35 #if defined(__cplusplus)
36 extern "C" {
37 #endif
38
39 #include "cy_cryptolite_cmac.h"
40
41 #if (CRYPTOLITE_AES_PRESENT == 1)
42 #if defined(CY_CRYPTOLITE_CFG_CMAC_C)
43
44 #include "cy_cryptolite_vu.h"
45
46 /* The bit string used to generate sub-keys */
47 #define CY_CRYPTOLITE_CMAC_RB (0x87u)
48
49 static void Cy_Cryptolite_Cmac_CalcSubKey(uint8_t *srcDstPtr);
50
51 /*******************************************************************************
52 * Function Name: Cy_Cryptolite_Cmac_CalcSubKey
53 ****************************************************************************//**
54 *
55 * Calculates the sub-key for the CMAC algorithm
56 * according to the NIST publication 800-38B, page 7.
57 *
58 * \param srcDstPtr
59 * The pointer to the source data for sub-key calculation, see 800-38B.
60 *
61 *******************************************************************************/
Cy_Cryptolite_Cmac_CalcSubKey(uint8_t * srcDstPtr)62 static void Cy_Cryptolite_Cmac_CalcSubKey(uint8_t *srcDstPtr)
63 {
64 int32_t i;
65 uint32_t c;
66 uint32_t msb = 0UL;
67
68 for (i = (int32_t)((int32_t)CY_CRYPTOLITE_AES_BLOCK_SIZE - 1); i >= 0; i--)
69 {
70 c = (uint32_t)srcDstPtr[i];
71 c = (c << 1U) | msb;
72 srcDstPtr[i] = (uint8_t) c;
73 msb = (c >> 8U) & 1UL;
74 }
75
76 if (0UL != msb)
77 {
78 /* Just one byte is valuable, the rest are zeros */
79 srcDstPtr[(uint8_t)(CY_CRYPTOLITE_AES_BLOCK_SIZE - 1U)] ^= CY_CRYPTOLITE_CMAC_RB;
80 }
81 }
82
83
84 /*******************************************************************************
85 * Function Name: Cy_Cryptolite_Cmac_Init
86 ****************************************************************************//*
87 *
88 * The function for initialization of CMAC operation.
89 *
90 * \param base
91 * The pointer to the CRYPTOLITE instance.
92 *
93 * \param key
94 * The pointer to the CMAC key.
95 *
96 * \param cmacState
97 * The pointer to the AES state structure allocated by the user. The user
98 * must not modify anything in this structure.
99 *
100 * \param aesBuffers The buffers should be a SAHB mapped addresses.
101 * The pointer to the memory buffers storage.
102 *
103 * \return
104 * \ref cy_en_cryptolite_status_t
105 *******************************************************************************/
Cy_Cryptolite_Cmac_Init(CRYPTOLITE_Type * base,uint8_t const * key,cy_stc_cryptolite_aes_state_t * cmacState,cy_stc_cryptolite_aes_buffers_t * aesBuffers)106 cy_en_cryptolite_status_t Cy_Cryptolite_Cmac_Init(CRYPTOLITE_Type *base,
107 uint8_t const *key,
108 cy_stc_cryptolite_aes_state_t *cmacState,
109 cy_stc_cryptolite_aes_buffers_t *aesBuffers)
110 {
111 cy_en_cryptolite_status_t status = CY_CRYPTOLITE_BAD_PARAMS;
112 uint8_t *keyRemap;
113
114 /* Input parameters verification */
115 if ((NULL == base) || (NULL == key) || (NULL == cmacState) || (NULL == aesBuffers))
116 {
117 return status;
118 }
119
120
121 keyRemap = (uint8_t *)CY_REMAP_ADDRESS_CRYPTOLITE(key);
122
123 status = Cy_Cryptolite_Aes_Init(base, keyRemap, cmacState, aesBuffers);
124 if(CY_CRYPTOLITE_SUCCESS != status)
125 {
126 return status;
127 }
128
129 return CY_CRYPTOLITE_SUCCESS;
130 }
131
132
133
134 /*******************************************************************************
135 * Function Name: Cy_Cryptolite_Cmac_Start
136 ****************************************************************************//*
137 *
138 * Starts CMAC calculation.
139 *
140 * \param base
141 * The pointer to the CRYPTOLITE instance.
142 *
143 * \param cmacState
144 * The pointer to the structure which stores the CMAC context.
145 *
146 * \return
147 * \ref cy_en_cryptolite_status_t
148 *******************************************************************************/
Cy_Cryptolite_Cmac_Start(CRYPTOLITE_Type * base,cy_stc_cryptolite_aes_state_t * cmacState)149 cy_en_cryptolite_status_t Cy_Cryptolite_Cmac_Start(CRYPTOLITE_Type *base, cy_stc_cryptolite_aes_state_t *cmacState)
150 {
151 /* Input parameters verification */
152 if ((NULL == base) || (NULL == cmacState))
153 {
154 return CY_CRYPTOLITE_BAD_PARAMS;
155 }
156
157 return Cy_Cryptolite_Aes_CbcMac_Setup(base, cmacState);
158 }
159
160
161 /*******************************************************************************
162 * Function Name: Cy_Cryptolite_Cmac_Update
163 ****************************************************************************//*
164 *
165 * Performs cmac update for multi stage operation.
166 *
167 * \param base
168 * The pointer to the CRYPTOLITE instance.
169 *
170 * \param message
171 * The pointer to the message whose CMAC is being computed.
172 *
173 * \param messageSize
174 * The size of the message whose CMAC is being computed.
175 *
176 * \param cmacState
177 * The pointer to the structure which stores the CMAC context.
178 *
179 * \return
180 * \ref cy_en_cryptolite_status_t
181 *******************************************************************************/
Cy_Cryptolite_Cmac_Update(CRYPTOLITE_Type * base,uint8_t const * message,uint32_t messageSize,cy_stc_cryptolite_aes_state_t * cmacState)182 cy_en_cryptolite_status_t Cy_Cryptolite_Cmac_Update(CRYPTOLITE_Type *base,
183 uint8_t const *message,
184 uint32_t messageSize,
185 cy_stc_cryptolite_aes_state_t *cmacState)
186 {
187 uint32_t count = 0u;
188 uint32_t cnt=0u;
189 cy_en_cryptolite_status_t status = CY_CRYPTOLITE_BAD_PARAMS;
190 uint8_t *messageRemap;
191
192 if(messageSize == 0u)
193 {
194 return CY_CRYPTOLITE_SUCCESS;
195 }
196
197 /* Input parameters verification */
198 if ((NULL == base) || (NULL == message) || (NULL == cmacState))
199 {
200 return CY_CRYPTOLITE_BAD_PARAMS;
201 }
202
203 messageRemap = (uint8_t *)CY_REMAP_ADDRESS_CRYPTOLITE(message);
204
205 if(cmacState->unProcessedBytes == 16u)
206 {
207 // The size passed here has no significance as it uses the unProcessedBytes size for processing the data
208 status = Cy_Cryptolite_Aes_CbcMac_Update(base, 1u, (uint8_t const *)cmacState->buffers->unProcessedData, cmacState);
209
210 if(CY_CRYPTOLITE_SUCCESS != status)
211 {
212 return status;
213 }
214 cmacState->unProcessedBytes = 0u;
215 }
216
217 if(cmacState->unProcessedBytes > 0u && messageSize > CY_CRYPTOLITE_AES_BLOCK_SIZE-cmacState->unProcessedBytes)
218 {
219 status = Cy_Cryptolite_Aes_CbcMac_Update(base, CY_CRYPTOLITE_AES_BLOCK_SIZE-cmacState->unProcessedBytes, messageRemap, cmacState);
220
221 if(CY_CRYPTOLITE_SUCCESS != status)
222 {
223 return status;
224 }
225
226 messageSize -= CY_CRYPTOLITE_AES_BLOCK_SIZE-cmacState->unProcessedBytes;
227 messageRemap += CY_CRYPTOLITE_AES_BLOCK_SIZE-cmacState->unProcessedBytes;
228 }
229
230 cnt = (uint32_t)((messageSize + CY_CRYPTOLITE_AES_BLOCK_SIZE -1u) / CY_CRYPTOLITE_AES_BLOCK_SIZE);
231
232 if(cnt > 1u)
233 {
234 --cnt;
235 count = cnt*CY_CRYPTOLITE_AES_BLOCK_SIZE;
236
237 status = Cy_Cryptolite_Aes_CbcMac_Update(base, count, messageRemap, cmacState);
238
239 if(CY_CRYPTOLITE_SUCCESS != status)
240 {
241 return status;
242 }
243
244 messageSize -= cnt*CY_CRYPTOLITE_AES_BLOCK_SIZE;
245 messageRemap += cnt*CY_CRYPTOLITE_AES_BLOCK_SIZE;
246 }
247
248 if(messageSize > 0u)
249 {
250 status = CY_CRYPTOLITE_SUCCESS;
251 Cy_Cryptolite_Vu_memcpy((void*)&cmacState->buffers->unProcessedData[cmacState->unProcessedBytes], messageRemap, messageSize);
252 cmacState->unProcessedBytes += messageSize;
253 }
254
255 return status;
256 }
257
258
259
260 /*******************************************************************************
261 * Function Name: Cy_Cryptolite_Cmac_Finish
262 ****************************************************************************//*
263 *
264 * Completes CMAC calculation.
265 *
266 * \param base
267 * The pointer to the CRYPTOLITE instance.
268 *
269 * \param cmac
270 * The pointer to the computed CMAC value.
271 *
272 * \param cmacState
273 * The pointer to the structure which stores the CMAC context.
274 *
275 * \return
276 * \ref cy_en_cryptolite_status_t
277 *******************************************************************************/
Cy_Cryptolite_Cmac_Finish(CRYPTOLITE_Type * base,uint8_t * cmac,cy_stc_cryptolite_aes_state_t * cmacState)278 cy_en_cryptolite_status_t Cy_Cryptolite_Cmac_Finish(CRYPTOLITE_Type *base, uint8_t* cmac, cy_stc_cryptolite_aes_state_t *cmacState)
279 {
280 CY_ALIGN(4) uint8_t subkey[16];
281 CY_ALIGN(4) uint8_t zeromsg[16];
282 uint32_t *keyPtr = NULL;
283 uint32_t *finalMsgPtr = NULL;
284 uint32_t *tempBuff = NULL;
285 uint8_t *paddingRemap;
286
287 /* Input parameters verification */
288 if ((NULL == base) || (NULL == cmac) || (NULL == cmacState))
289 {
290 return CY_CRYPTOLITE_BAD_PARAMS;
291 }
292
293 uint8_t const p_padding[16] =
294 {
295 0x80u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u,
296 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u
297 };
298
299
300 paddingRemap = (uint8_t *)CY_REMAP_ADDRESS_CRYPTOLITE(p_padding);
301
302 cy_en_cryptolite_status_t status = CY_CRYPTOLITE_BAD_PARAMS;
303
304 Cy_Cryptolite_Vu_memset((void *)zeromsg, 0u, sizeof(zeromsg));
305
306 keyPtr = (uint32_t*)((void *)subkey);
307 tempBuff = (uint32_t*)((void *)cmacState->buffers->iv);
308 finalMsgPtr = (uint32_t*)((void *)cmacState->buffers->unProcessedData);
309
310 if(cmacState->unProcessedBytes != 16u)
311 {
312 Cy_Cryptolite_Vu_memcpy((void*)&cmacState->buffers->unProcessedData[cmacState->unProcessedBytes], paddingRemap, CY_CRYPTOLITE_AES_BLOCK_SIZE - cmacState->unProcessedBytes);
313 }
314
315 status = Cy_Cryptolite_Aes_Ecb(base, subkey, zeromsg, cmacState);
316 if(CY_CRYPTOLITE_SUCCESS != status)
317 {
318 return status;
319 }
320
321 // Calculate subkey k1
322 Cy_Cryptolite_Cmac_CalcSubKey(subkey);
323
324 if(cmacState->unProcessedBytes < 16u)
325 {
326 // Calculate subkey k2
327 Cy_Cryptolite_Cmac_CalcSubKey(subkey);
328 }
329
330 tempBuff[0] = tempBuff[0] ^ keyPtr[0] ^ finalMsgPtr[0];
331 tempBuff[1] = tempBuff[1] ^ keyPtr[1] ^ finalMsgPtr[1];
332 tempBuff[2] = tempBuff[2] ^ keyPtr[2] ^ finalMsgPtr[2];
333 tempBuff[3] = tempBuff[3] ^ keyPtr[3] ^ finalMsgPtr[3];
334
335 status = Cy_Cryptolite_Aes_Ecb(base, cmac, (uint8_t *)tempBuff, cmacState);
336
337 return status;
338 }
339
340
341
342 /*******************************************************************************
343 * Function Name: Cy_Cryptolite_Cmac_Free
344 ****************************************************************************//*
345 *
346 * Clears CMAC operation context.
347 *
348 * \param base
349 * The pointer to the CRYPTOLITE instance.
350 *
351 * \param cmacState
352 * The pointer to the AES state structure allocated by the user. The user
353 * must not modify anything in this structure.
354 *
355 * \return
356 * \ref cy_en_cryptolite_status_t
357 *******************************************************************************/
Cy_Cryptolite_Cmac_Free(CRYPTOLITE_Type * base,cy_stc_cryptolite_aes_state_t * cmacState)358 cy_en_cryptolite_status_t Cy_Cryptolite_Cmac_Free(CRYPTOLITE_Type *base, cy_stc_cryptolite_aes_state_t *cmacState)
359
360 {
361 return Cy_Cryptolite_Aes_Free(base, cmacState);
362
363 }
364
365
366 /*******************************************************************************
367 * Function Name: Cy_Cryptolite_Cmac
368 ****************************************************************************//*
369 *
370 * Performs CMAC(Cipher-based Message Authentication Code) operation
371 * on a message to produce message authentication code using AES.
372 **
373 * \param base
374 * The pointer to the CRYPTOLITE instance.
375 *
376 * \param message
377 * The pointer to a source plain text.
378 *
379 * \param messageSize
380 * The size of a source plain text.
381 *
382 * \param key
383 * The pointer to the encryption key.
384 *
385 * \param cmac
386 * The pointer to the calculated CMAC.
387 *
388 * \param aesState
389 * The pointer to the AES state structure allocated by the user. The user
390 * must not modify anything in this structure.
391 *
392 * \return
393 * \ref cy_en_cryptolite_status_t
394 *
395 *******************************************************************************/
Cy_Cryptolite_Cmac(CRYPTOLITE_Type * base,uint8_t const * key,uint8_t const * message,uint32_t messageSize,uint8_t * cmac,cy_stc_cryptolite_aes_state_t * cmacState)396 cy_en_cryptolite_status_t Cy_Cryptolite_Cmac(CRYPTOLITE_Type *base,
397 uint8_t const *key,
398 uint8_t const *message,
399 uint32_t messageSize,
400 uint8_t *cmac,
401 cy_stc_cryptolite_aes_state_t *cmacState)
402 {
403
404 cy_en_cryptolite_status_t status = CY_CRYPTOLITE_BAD_PARAMS;
405 cy_stc_cryptolite_aes_buffers_t cmacBuffersData;
406 uint8_t *keyRemap;
407 uint8_t *messageRemap;
408
409 /* Input parameters verification */
410 if ((NULL == base) || (NULL == key) || ((NULL == message) && (messageSize>0u)) || (NULL == cmac) || (NULL == cmacState))
411 {
412 return CY_CRYPTOLITE_BAD_PARAMS;
413 }
414
415 keyRemap = (uint8_t *)CY_REMAP_ADDRESS_CRYPTOLITE(key);
416 messageRemap = (uint8_t *)CY_REMAP_ADDRESS_CRYPTOLITE(message);
417
418 status = Cy_Cryptolite_Cmac_Init (base, keyRemap, cmacState, &cmacBuffersData);
419
420 if(CY_CRYPTOLITE_SUCCESS == status)
421 {
422 status = Cy_Cryptolite_Cmac_Start (base, cmacState);
423 }
424
425 if(CY_CRYPTOLITE_SUCCESS == status)
426 {
427 status = Cy_Cryptolite_Cmac_Update(base, messageRemap, messageSize, cmacState);
428 }
429
430 if(CY_CRYPTOLITE_SUCCESS == status)
431 {
432 status = Cy_Cryptolite_Cmac_Finish(base, cmac, cmacState);
433 }
434
435 if(CY_CRYPTOLITE_SUCCESS == status)
436 {
437 status = Cy_Cryptolite_Cmac_Free(base, cmacState);
438 }
439
440 return (CY_CRYPTOLITE_SUCCESS);
441 }
442
443 #endif /* defined(CY_CRYPTOLITE_CFG_CMAC_C) */
444 #endif /* (CRYPTOLITE_AES_PRESENT == 1) */
445
446 #if defined(__cplusplus)
447 }
448 #endif
449
450
451 #endif /* defined(CY_IP_MXCRYPTOLITE) */
452
453
454 /* [] END OF FILE */
455