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