1 /***************************************************************************//**
2 * \file cy_crypto_core_cmac_v1.c
3 * \version 2.120
4 *
5 * \brief
6 *  This file provides the source code to the API for the CMAC method
7 *  in the Crypto 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_MXCRYPTO)
34 
35 #include "cy_crypto_core_cmac_v1.h"
36 
37 #if defined(CY_CRYPTO_CFG_HW_V1_ENABLE)
38 
39 #if defined(__cplusplus)
40 extern "C" {
41 #endif
42 
43 #if (CPUSS_CRYPTO_AES == 1) && defined(CY_CRYPTO_CFG_CMAC_C)
44 
45 #include "cy_crypto_core_aes_v1.h"
46 #include "cy_crypto_core_hw_v1.h"
47 #include "cy_crypto_core_mem_v1.h"
48 #include "cy_syslib.h"
49 
50 CY_MISRA_DEVIATE_BLOCK_START('MISRA C-2012 Rule 11.3', 2, \
51 'Pointer type conversion is intentional')
52 
53 static void Cy_Crypto_Core_V1_Cmac_CalcSubKey(uint8_t *srcDstPtr);
54 
55 /*******************************************************************************
56 * Function Name: Cy_Crypto_Core_V1_Cmac_CalcSubKey
57 ****************************************************************************//**
58 *
59 * Calculates the sub-key for the CMAC algorithm
60 * according to the NIST publication 800-38B, page 7.
61 *
62 * \param srcDstPtr
63 * The pointer to the source data for sub-key calculation, see 800-38B.
64 *
65 *******************************************************************************/
Cy_Crypto_Core_V1_Cmac_CalcSubKey(uint8_t * srcDstPtr)66 static void Cy_Crypto_Core_V1_Cmac_CalcSubKey(uint8_t *srcDstPtr)
67 {
68     int32_t i;
69     uint32_t c;
70     uint32_t msb = 0UL;
71 
72     for (i = (int32_t)((int32_t)CY_CRYPTO_AES_BLOCK_SIZE - 1); i >= 0; i--)
73     {
74         c = (uint32_t)srcDstPtr[i];
75         c = (c << 1U) | msb;
76         srcDstPtr[i] = (uint8_t) c;
77         msb = (c >> 8U) & 1UL;
78     }
79 
80     if (0UL != msb)
81     {
82         /* Just one byte is valuable, the rest are zeros */
83         srcDstPtr[(uint8_t)(CY_CRYPTO_AES_BLOCK_SIZE - 1U)] ^= CY_CRYPTO_CMAC_RB;
84     }
85 }
86 
87 /*******************************************************************************
88 * Function Name: Cy_Crypto_Core_V1_Cmac_Init
89 ****************************************************************************//**
90 *
91 * The function for initialization of CMAC operation.
92 *
93 * \param cmacState
94 * The pointer to the structure which stores the CMAC context.
95 *
96 * \param temp
97 * The pointer to the temporary memory needed for CMAC calculation,
98 * the max needed - 128 Bytes.
99 *
100 * \param block
101 * The pointer to the temporary storage for block, the max needed - 128 Bytes.
102 *
103 * \param k
104 * The pointer to the sub-key.
105 
106 *******************************************************************************/
Cy_Crypto_Core_V1_Cmac_Init(cy_stc_crypto_v1_cmac_state_t * cmacState,uint32_t * temp,uint32_t * block,uint32_t * k)107 void Cy_Crypto_Core_V1_Cmac_Init(cy_stc_crypto_v1_cmac_state_t* cmacState,
108                                 uint32_t* temp,
109                                 uint32_t* block,
110                                 uint32_t* k)
111 {
112     cmacState->block = block;
113     cmacState->temp  = temp;
114     cmacState->k     = k;
115 }
116 
117 /*******************************************************************************
118 * Function Name: Cy_Crypto_Core_V1_Cmac_Start
119 ****************************************************************************//**
120 *
121 * Starts CMAC calculation.
122 *
123 * \param base
124 * The pointer to the CRYPTO instance.
125 *
126 * \param aesState
127 * The pointer to the structure which stores the AES context.
128 *
129 * \param cmacState
130 * The pointer to the structure which stores the CMAC context.
131 *
132 *******************************************************************************/
Cy_Crypto_Core_V1_Cmac_Start(CRYPTO_Type * base,cy_stc_crypto_aes_state_t * aesState,cy_stc_crypto_v1_cmac_state_t * cmacState)133 void Cy_Crypto_Core_V1_Cmac_Start(CRYPTO_Type *base,
134                                cy_stc_crypto_aes_state_t  *aesState,
135                                cy_stc_crypto_v1_cmac_state_t *cmacState)
136 {
137     uint32_t *kTmp    = cmacState->k;
138     uint32_t *tempTmp = cmacState->temp;
139 
140     /* Calculate the K1 sub-key */
141     Cy_Crypto_Core_V1_MemSet(base, (void*)tempTmp, 0U, CY_CRYPTO_AES_BLOCK_SIZE);
142 
143     Cy_Crypto_Core_V1_Aes_ProcessBlock(base, aesState, CY_CRYPTO_ENCRYPT, kTmp, tempTmp);
144 
145     Cy_Crypto_Core_V1_Cmac_CalcSubKey((uint8_t*)kTmp);
146 }
147 
148 /*******************************************************************************
149 * Function Name: Cy_Crypto_Core_V1_Cmac_Update
150 ****************************************************************************//**
151 *
152 * Calculates CMAC on a message.
153 *
154 * \param base
155 * The pointer to the CRYPTO instance.
156 *
157 * \param aesState
158 * The pointer to the structure which stores the AES context.
159 *
160 * \param cmacState
161 * The pointer to the structure which stores the CMAC context.
162 *
163 * \param message
164 * The pointer to the message whose CMAC is being computed.
165 *
166 * \param messageSize
167 * The size of the message whose CMAC is being computed.
168 *
169 *******************************************************************************/
Cy_Crypto_Core_V1_Cmac_Update(CRYPTO_Type * base,cy_stc_crypto_aes_state_t * aesState,cy_stc_crypto_v1_cmac_state_t * cmacState,uint8_t const * message,uint32_t messageSize)170 void Cy_Crypto_Core_V1_Cmac_Update(CRYPTO_Type *base,
171                                 cy_stc_crypto_aes_state_t  *aesState,
172                                 cy_stc_crypto_v1_cmac_state_t *cmacState,
173                                 uint8_t  const *message,
174                                 uint32_t messageSize)
175 {
176     uint32_t *blockBuff = cmacState->block;
177     uint32_t *tempBuff  = cmacState->temp;
178 
179     /* Clear the argument for XOR for the first block */
180     Cy_Crypto_Core_V1_MemSet(base, (void* )tempBuff, 0x00U, CY_CRYPTO_AES_BLOCK_SIZE);
181 
182     /* Process all blocks except last */
183     while (messageSize > CY_CRYPTO_AES_BLOCK_SIZE)
184     {
185         /* Copy the source message block */
186         Cy_Crypto_Core_V1_MemCpy(base, blockBuff, message, CY_CRYPTO_AES_BLOCK_SIZE);
187 
188         Cy_Crypto_Core_V1_Aes_Xor(base, aesState, blockBuff, blockBuff, tempBuff);
189         Cy_Crypto_Core_V1_Aes_ProcessBlock(base,
190                                         aesState, CY_CRYPTO_ENCRYPT, tempBuff, blockBuff);
191 
192         /* in bytes */
193         message     += CY_CRYPTO_AES_BLOCK_SIZE;
194         messageSize -= CY_CRYPTO_AES_BLOCK_SIZE;
195     }
196 
197     /* The calculation size of the last block */
198     aesState->blockIdx = messageSize;
199 
200     /* Copy the last block to the block */
201     Cy_Crypto_Core_V1_MemCpy(base, (void*)blockBuff, (void*)message, (uint16_t)aesState->blockIdx);
202 }
203 
204 /*******************************************************************************
205 * Function Name: Cy_Crypto_Core_V1_Cmac_Finish
206 ****************************************************************************//**
207 *
208 * Completes CMAC calculation.
209 *
210 * \param base
211 * The pointer to the CRYPTO instance.
212 *
213 * \param aesState
214 * the pointer to the structure which stores the AES context.
215 *
216 * \param cmacState
217 * The pointer to the structure which stores the CMAC context.
218 *
219 * \param cmac
220 * The pointer to the computed CMAC value.
221 *
222 *******************************************************************************/
Cy_Crypto_Core_V1_Cmac_Finish(CRYPTO_Type * base,cy_stc_crypto_aes_state_t * aesState,cy_stc_crypto_v1_cmac_state_t * cmacState,uint8_t * cmac)223 void Cy_Crypto_Core_V1_Cmac_Finish(CRYPTO_Type *base,
224                                 cy_stc_crypto_aes_state_t  *aesState,
225                                 cy_stc_crypto_v1_cmac_state_t *cmacState,
226                                 uint8_t* cmac)
227 {
228     uint32_t *blockBuff   = cmacState->block;
229     uint32_t *tempBuff    = cmacState->temp;
230     uint32_t *kPtrTmp     = cmacState->k;
231     uint32_t  blockIdxTmp = aesState->blockIdx;
232     uint32_t  copySize;
233 
234     if (blockIdxTmp < CY_CRYPTO_AES_BLOCK_SIZE)
235     {
236         /* Calculate the K2 sub-key */
237         Cy_Crypto_Core_V1_Cmac_CalcSubKey((uint8_t* )kPtrTmp);
238 
239         /* Appended '1' bit to the end of message, followed by '0' */
240         *((uint8_t* )blockBuff + blockIdxTmp) = 0x80U;
241 
242         /* Write zeros into the rest of the message */
243         copySize = CY_CRYPTO_AES_BLOCK_SIZE - 1u - blockIdxTmp;
244         Cy_Crypto_Core_V1_MemSet(base, ((uint8_t* )blockBuff + blockIdxTmp + 1), 0x00U, (uint16_t)copySize);
245     }
246 
247     Cy_Crypto_Core_V1_Aes_Xor(base, aesState, blockBuff, blockBuff, tempBuff);
248     Cy_Crypto_Core_V1_Aes_Xor(base, aesState, blockBuff, blockBuff, kPtrTmp);
249 
250     Cy_Crypto_Core_V1_Aes_ProcessBlock(base, aesState, CY_CRYPTO_ENCRYPT, tempBuff, blockBuff);
251 
252     /* Copy the result to the cmac */
253     Cy_Crypto_Core_V1_MemCpy(base, cmac, tempBuff, CY_CRYPTO_AES_BLOCK_SIZE);
254 }
255 
256 /*******************************************************************************
257 * Function Name: Cy_Crypto_Core_V1_Cmac
258 ****************************************************************************//**
259 *
260 * Performs CMAC(Cipher-based Message Authentication Code) operation
261 * on a message to produce message authentication code using AES.
262 *
263 * \param base
264 * The pointer to the CRYPTO instance.
265 *
266 * \param message
267 * The pointer to a source plain text. Must be 4-byte aligned.
268 *
269 * \param messageSize
270 * The size of a source plain text.
271 *
272 * \param key
273 * The pointer to the encryption key. Must be 4-byte aligned.
274 *
275 * \param keyLength
276 * \ref cy_en_crypto_aes_key_length_t
277 *
278 * \param cmac
279 * The pointer to the calculated CMAC.
280 *
281 * \param aesState
282 * The pointer to the AES state structure allocated by the user. The user
283 * must not modify anything in this structure.
284 *
285 * \return
286 * \ref cy_en_crypto_status_t
287 *
288 *******************************************************************************/
Cy_Crypto_Core_V1_Cmac(CRYPTO_Type * base,uint8_t const * message,uint32_t messageSize,uint8_t const * key,cy_en_crypto_aes_key_length_t keyLength,uint8_t * cmac,cy_stc_crypto_aes_state_t * aesState)289 cy_en_crypto_status_t Cy_Crypto_Core_V1_Cmac(CRYPTO_Type *base,
290                                           uint8_t  const *message,
291                                           uint32_t messageSize,
292                                           uint8_t  const *key,
293                                           cy_en_crypto_aes_key_length_t keyLength,
294                                           uint8_t *cmac,
295                                           cy_stc_crypto_aes_state_t *aesState)
296 {
297     cy_stc_crypto_aes_buffers_t  *aesBuffers = (cy_stc_crypto_aes_buffers_t *)(Cy_Crypto_Core_GetVuMemoryAddress(base));
298     cy_stc_crypto_v1_cmac_buffers_t *cmacBuffers =
299         (cy_stc_crypto_v1_cmac_buffers_t *)((uint8_t*)aesBuffers + sizeof(cy_stc_crypto_aes_buffers_t));
300 
301     uint32_t *myBlock = (uint32_t*)(&cmacBuffers->block0);
302     uint32_t *myTemp  = (uint32_t*)(&cmacBuffers->block1);
303     uint32_t *myK     = (uint32_t*)(&cmacBuffers->k);
304     cy_stc_crypto_v1_cmac_state_t *myCmacState = &cmacBuffers->cmacState;
305 
306     (void)Cy_Crypto_Core_V1_Aes_Init(base, key, keyLength, aesState, aesBuffers);
307 
308     Cy_Crypto_Core_V1_Cmac_Init  (myCmacState, myTemp, myBlock, myK);
309     Cy_Crypto_Core_V1_Cmac_Start (base, aesState, myCmacState);
310     Cy_Crypto_Core_V1_Cmac_Update(base, aesState, myCmacState, message, messageSize);
311     Cy_Crypto_Core_V1_Cmac_Finish(base, aesState, myCmacState, cmac);
312 
313     return (CY_CRYPTO_SUCCESS);
314 }
315 
316 CY_MISRA_BLOCK_END('MISRA C-2012 Rule 11.3')
317 
318 #endif /* (CPUSS_CRYPTO_AES == 1) && defined(CY_CRYPTO_CFG_CMAC_C) */
319 
320 #if defined(__cplusplus)
321 }
322 #endif
323 
324 #endif /* defined(CY_CRYPTO_CFG_HW_V1_ENABLE) */
325 
326 #endif /* defined(CY_IP_MXCRYPTO) */
327 
328 
329 /* [] END OF FILE */
330