1 /***************************************************************************//**
2 * \file cy_cryptolite_sha256.c
3 * \version 2.50
4 *
5 * \brief
6 *  Provides API implementation of the Cryptolite SHA256 PDL driver.
7 *
8 ********************************************************************************
9 * \copyright
10 * Copyright (c) (2020-2022), Cypress Semiconductor Corporation (an Infineon company) or
11 * an affiliate of Cypress Semiconductor Corporation.
12 * SPDX-License-Identifier: Apache-2.0
13 *
14 * Licensed under the Apache License, Version 2.0 (the "License");
15 * you may not use this file except in compliance with the License.
16 * You may obtain a copy of the License at
17 *
18 *    http://www.apache.org/licenses/LICENSE-2.0
19 *
20 * Unless required by applicable law or agreed to in writing, software
21 * distributed under the License is distributed on an "AS IS" BASIS,
22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 * See the License for the specific language governing permissions and
24 * limitations under the License.
25 *******************************************************************************/
26 
27 #include "cy_device.h"
28 
29 #if defined (CY_IP_MXCRYPTOLITE)
30 
31 #include "cy_cryptolite_sha256.h"
32 #include "cy_cryptolite_utils.h"
33 
34 #if defined(__cplusplus)
35 extern "C" {
36 #endif
37 
38 #if (CRYPTOLITE_SHA_PRESENT == 1)
39 #if defined(CY_CRYPTOLITE_CFG_SHA_C) && defined(CY_CRYPTOLITE_CFG_SHA2_256_ENABLED)
40 
41 /*Initial Hash*/
42 static const uint32_t sha256InitHash[] =
43 {
44     0x6A09E667uL, 0xBB67AE85uL, 0x3C6EF372uL, 0xA54FF53AuL,
45     0x510E527FuL, 0x9B05688CuL, 0x1F83D9ABuL, 0x5BE0CD19uL
46 };
47 
48 /*****************************************************************************
49 * Cy_Cryptolite_Sha256_Process (for internal use)
50 ******************************************************************************
51 *
52 * The function starts the hash calculation, blocks until finished.
53 *
54 *  base
55 * The pointer to the Cryptolite instance.
56 *
57 *  cfContext
58 * The pointer to the cy_stc_cryptolite_context_sha256_t structure that stores all
59 * internal variables for Cryptolite driver.
60 *
61 * return
62 * cy_en_cryptolite_status_t
63 *
64 *******************************************************************************/
Cy_Cryptolite_Sha256_Process(CRYPTOLITE_Type * base,cy_stc_cryptolite_context_sha256_t * cfContext)65 static cy_en_cryptolite_status_t Cy_Cryptolite_Sha256_Process(CRYPTOLITE_Type *base,
66                                         cy_stc_cryptolite_context_sha256_t *cfContext)
67 {
68     if((REG_CRYPTOLITE_STATUS(base) & CRYPTOLITE_STATUS_BUSY_Msk) != 0UL)
69     {
70         return CY_CRYPTOLITE_HW_BUSY;
71     }
72 
73     /*write to SHA DESCR REG starts process
74       IP will block another write to SHA DESCR REG until its busy
75       We poll for busy state and check for error before posting next
76       descriptor */
77 
78     /*start message schedule*/
79     REG_CRYPTOLITE_SHA_DESCR(base) = (uint32_t)&(cfContext->message_schedule_struct);
80     while((REG_CRYPTOLITE_STATUS(base) & CRYPTOLITE_STATUS_BUSY_Msk) != 0UL){};
81     if((REG_CRYPTOLITE_SHA_INTR_ERROR(base) & CRYPTOLITE_INTR_ERROR_BUS_ERROR_Msk) != 0UL)
82     {
83         REG_CRYPTOLITE_SHA_INTR_ERROR(base) = CRYPTOLITE_INTR_ERROR_BUS_ERROR_Msk;
84         return CY_CRYPTOLITE_BUS_ERROR;
85     }
86 
87     /*start process*/
88     REG_CRYPTOLITE_SHA_DESCR(base) = (uint32_t)&(cfContext->message_process_struct);
89     while((REG_CRYPTOLITE_STATUS(base) & CRYPTOLITE_STATUS_BUSY_Msk) != 0UL){};
90     if((REG_CRYPTOLITE_SHA_INTR_ERROR(base) & CRYPTOLITE_INTR_ERROR_BUS_ERROR_Msk) != 0UL)
91     {
92         REG_CRYPTOLITE_SHA_INTR_ERROR(base) = CRYPTOLITE_INTR_ERROR_BUS_ERROR_Msk;
93         return CY_CRYPTOLITE_BUS_ERROR;
94     }
95 
96     return CY_CRYPTOLITE_SUCCESS;
97 }
98 
99 /*****************************************************************************
100 * Cy_Cryptolite_Sha256_Process_aligned (for internal use)
101 ******************************************************************************
102 *
103 * The function starts the hash calculation for 4 byte aligned data blocks
104 * until finished.
105 *
106 *  base
107 * The pointer to the Cryptolite instance.
108 *
109 *  cfContext
110 * The pointer to the cy_stc_cryptolite_context_sha256_t structure that stores all
111 * internal variables for Cryptolite driver.
112 *
113 *  message
114 * The pointer to the message whose Hash is being computed.
115 *
116 *  messageSize
117 * The pointer to size of the message whose Hash is being computed.
118 * returns the remaining message size after process
119 *
120 * return
121 * cy_en_cryptolite_status_t
122 *
123 *******************************************************************************/
Cy_Cryptolite_Sha256_Process_aligned(CRYPTOLITE_Type * base,cy_stc_cryptolite_context_sha256_t * cfContext,uint8_t const * message,uint32_t * messageSize)124 static cy_en_cryptolite_status_t Cy_Cryptolite_Sha256_Process_aligned(CRYPTOLITE_Type *base,
125                                         cy_stc_cryptolite_context_sha256_t *cfContext,
126                                         uint8_t const *message,
127                                         uint32_t  *messageSize)
128 {
129     cy_en_cryptolite_status_t err;
130 
131     /*point descriptor to message buffer*/
132     cfContext->message_schedule_struct.data1 = (uint32_t)message;
133 
134     while(*messageSize >= CY_CRYPTOLITE_SHA256_BLOCK_SIZE)
135     {
136         err = Cy_Cryptolite_Sha256_Process(base, cfContext);
137         if(CY_CRYPTOLITE_SUCCESS != err)
138         {
139             cfContext->message_schedule_struct.data1 = (uint32_t)cfContext->message;
140             return err;
141         }
142         *messageSize-=CY_CRYPTOLITE_SHA256_BLOCK_SIZE;
143         cfContext->messageSize+= CY_CRYPTOLITE_SHA256_BLOCK_SIZE;
144         cfContext->message_schedule_struct.data1+= CY_CRYPTOLITE_SHA256_BLOCK_SIZE;
145     }
146     /*restore descriptor to context buffer*/
147     cfContext->message_schedule_struct.data1 = (uint32_t)cfContext->message;
148 
149     return CY_CRYPTOLITE_SUCCESS;
150 }
151 
152 /*****************************************************************************
153 * Cy_Cryptolite_Sha256_Init
154 ******************************************************************************
155 *
156 * The function to initialize the SHA256 operation.
157 *
158 *  base
159 * The pointer to the Cryptolite instance.
160 *
161 *  cfContext
162 * The pointer to the cy_stc_cryptolite_context_sha256_t structure that stores all
163 * internal variables for Cryptolite driver.
164 *
165 * return
166 * cy_en_cryptolite_status_t
167 *
168 *******************************************************************************/
Cy_Cryptolite_Sha256_Init(CRYPTOLITE_Type * base,cy_stc_cryptolite_context_sha256_t * cfContext)169 cy_en_cryptolite_status_t Cy_Cryptolite_Sha256_Init(CRYPTOLITE_Type *base,
170                                         cy_stc_cryptolite_context_sha256_t *cfContext)
171 {
172     /* Input parameters verification */
173     if ((NULL == base) || (NULL == cfContext))
174     {
175         return CY_CRYPTOLITE_BAD_PARAMS;
176     }
177 
178     cfContext->message = (uint8_t*)cfContext->msgblock;
179     cfContext->message_schedule_struct.data0 = (uint32_t)CY_CRYPTOLITE_MSG_SCH_CTLWD;
180     cfContext->message_schedule_struct.data1 = (uint32_t)cfContext->message;
181     cfContext->message_schedule_struct.data2 = (uint32_t)cfContext->message_schedule;
182 
183     cfContext->message_process_struct.data0 = (uint32_t)CY_CRYPTOLITE_PROCESS_CTLWD;
184     cfContext->message_process_struct.data1 = (uint32_t)cfContext->hash;
185     cfContext->message_process_struct.data2 = (uint32_t)cfContext->message_schedule;
186 
187     return (CY_CRYPTOLITE_SUCCESS);
188 }
189 
190 /*******************************************************************************
191 * Cy_Cryptolite_Sha256_Start
192 ******************************************************************************
193 *
194 * Initializes the initial Hash vector.
195 *
196 *  base
197 * The pointer to the CRYPTOLITE instance.
198 *
199 *  cfContext
200 * The pointer to the cy_stc_cryptolite_context_sha256_t structure that stores all
201 * internal variables for Cryptolite driver.
202 *
203 * return
204 * cy_en_cryptolite_status_t
205 *
206 *******************************************************************************/
Cy_Cryptolite_Sha256_Start(CRYPTOLITE_Type * base,cy_stc_cryptolite_context_sha256_t * cfContext)207 cy_en_cryptolite_status_t Cy_Cryptolite_Sha256_Start(CRYPTOLITE_Type *base,
208                                         cy_stc_cryptolite_context_sha256_t *cfContext)
209 {
210     uint32_t i;
211     /* Input parameters verification */
212     if ((NULL == base) || (NULL == cfContext))
213     {
214         return CY_CRYPTOLITE_BAD_PARAMS;
215     }
216 
217     /*check if IP is busy*/
218     if ((REG_CRYPTOLITE_STATUS(base) & CRYPTOLITE_STATUS_BUSY_Msk) != 0UL)
219     {
220         return CY_CRYPTOLITE_HW_BUSY;
221     }
222 
223     cfContext->msgIdx = 0U;
224     cfContext->messageSize = 0U;
225 
226     /*copy initial hash*/
227     for (i=0U; i < CY_CRYPTOLITE_SHA256_HASH_SIZE/4U; i++)
228     {
229         cfContext->hash[i] = sha256InitHash[i];
230     }
231 
232     return CY_CRYPTOLITE_SUCCESS;
233 }
234 
235 
236 /*******************************************************************************
237 * Cy_Cryptolite_Sha256_Update
238 ********************************************************************************
239 *
240 * Performs the SHA256 calculation on one message.
241 *
242 *  base
243 * The pointer to the CRYPTOLITE instance.
244 *
245 *  cfContext
246 * The pointer to the cy_stc_cryptolite_context_sha256_t structure that stores all
247 * internal variables for Cryptolite driver.
248 *
249 *  message
250 * The pointer to the message whose Hash is being computed.
251 *
252 *  messageSize
253 * The size of the message whose Hash is being computed.
254 *
255 * return
256 * cy_en_cryptolite_status_t
257 *
258 *******************************************************************************/
Cy_Cryptolite_Sha256_Update(CRYPTOLITE_Type * base,uint8_t const * message,uint32_t messageSize,cy_stc_cryptolite_context_sha256_t * cfContext)259 cy_en_cryptolite_status_t Cy_Cryptolite_Sha256_Update(CRYPTOLITE_Type *base,
260                                         uint8_t const *message,
261                                         uint32_t  messageSize,
262                                         cy_stc_cryptolite_context_sha256_t *cfContext)
263 {
264     cy_en_cryptolite_status_t err = CY_CRYPTOLITE_BAD_PARAMS;
265     uint32_t readIdx = 0U;
266     uint32_t msg_add = (uint32)message;
267     uint32_t lmessageSize;
268     uint8_t *messageRemap;
269 
270     if (0UL == messageSize)
271     {
272         return CY_CRYPTOLITE_SUCCESS;
273     }
274 
275     /* Input parameters verification */
276     if ((NULL == base) || (NULL == cfContext) || (NULL == message))
277     {
278         return err;
279     }
280 
281     /*check if IP is busy*/
282     if ((REG_CRYPTOLITE_STATUS(base) & CRYPTOLITE_STATUS_BUSY_Msk) != 0UL)
283     {
284         return CY_CRYPTOLITE_HW_BUSY;
285     }
286 
287     messageRemap =  (uint8_t *)CY_REMAP_ADDRESS_CRYPTOLITE(message);
288     lmessageSize = messageSize;
289 
290     /*Check for 4 byte aligned buffer and process*/
291     if((msg_add & 0x3UL) == 0UL)
292     {
293         /*Check for fragmented message and size*/
294         if (cfContext->msgIdx == 0UL && messageSize >= CY_CRYPTOLITE_SHA256_BLOCK_SIZE)
295         {
296             err = Cy_Cryptolite_Sha256_Process_aligned(base, cfContext, messageRemap, &lmessageSize);
297             if(CY_CRYPTOLITE_SUCCESS != err)
298             {
299                 return err;
300             }
301             readIdx = messageSize - lmessageSize;
302         }
303     }
304 
305     while((cfContext->msgIdx + lmessageSize) >= CY_CRYPTOLITE_SHA256_BLOCK_SIZE)
306     {
307         uint32_t tocopy = CY_CRYPTOLITE_SHA256_BLOCK_SIZE - cfContext->msgIdx;
308 
309         err = Cy_Cryptolite_Memcpy(base, &cfContext->message[cfContext->msgIdx], (uint8_t *)&messageRemap[readIdx], tocopy);
310 
311         if(CY_CRYPTOLITE_SUCCESS != err)
312         {
313             return err;
314         }
315         readIdx += tocopy;
316         cfContext->msgIdx += tocopy;
317 
318         /* calculate message schedule and process */
319         err = Cy_Cryptolite_Sha256_Process(base, cfContext);
320         if(CY_CRYPTOLITE_SUCCESS != err)
321         {
322             return err;
323         }
324         lmessageSize-= tocopy;
325         cfContext->messageSize+= CY_CRYPTOLITE_SHA256_BLOCK_SIZE;
326         cfContext->msgIdx = 0U;
327     }
328 
329     err = Cy_Cryptolite_Memcpy(base, &cfContext->message[cfContext->msgIdx], (uint8_t *)&messageRemap[readIdx], lmessageSize);
330 
331     if(CY_CRYPTOLITE_SUCCESS != err)
332     {
333         return err;
334     }
335     cfContext->msgIdx += lmessageSize;
336 
337     return CY_CRYPTOLITE_SUCCESS;
338 }
339 
340 /*******************************************************************************
341 * Cy_Cryptolite_Sha256_Finish
342 ******************************************************************************
343 *
344 * Completes the SHA256 calculation.
345 *
346 *  base
347 * The pointer to the CRYPTOLITE instance.
348 *
349 *  cfContext
350 * the pointer to the cy_stc_cryptolite_context_sha256_t structure that stores all
351 * internal variables for Cryptolite driver.
352 *
353 *  digest
354 * The pointer to the calculated Hash digest.
355 *
356 * return
357 * cy_en_cryptolite_status_t
358 *
359 *******************************************************************************/
Cy_Cryptolite_Sha256_Finish(CRYPTOLITE_Type * base,uint8_t * digest,cy_stc_cryptolite_context_sha256_t * cfContext)360 cy_en_cryptolite_status_t Cy_Cryptolite_Sha256_Finish(CRYPTOLITE_Type *base,
361                                     uint8_t *digest,
362                                     cy_stc_cryptolite_context_sha256_t *cfContext)
363 {
364     cy_en_cryptolite_status_t err = CY_CRYPTOLITE_BAD_PARAMS;
365     uint8_t *hashptr;
366     uint32_t idx;
367     uint64_t totalMessageSizeInBits;
368 
369     /* Input parameters verification */
370     if ((NULL == base) || (NULL == cfContext) || (NULL == digest))
371     {
372         return err;
373     }
374 
375     /*check if IP is busy*/
376     if ((REG_CRYPTOLITE_STATUS(base) & CRYPTOLITE_STATUS_BUSY_Msk) != 0UL)
377     {
378         return CY_CRYPTOLITE_HW_BUSY;
379     }
380 
381     totalMessageSizeInBits = (cfContext->messageSize + (uint64_t)(cfContext->msgIdx)) * 8U;
382     /*Append one bit to end and clear rest of block*/
383     cfContext->message[cfContext->msgIdx] = 0x80U;
384     idx = cfContext->msgIdx + 1U;
385 
386     for ( ; idx < CY_CRYPTOLITE_SHA256_BLOCK_SIZE; idx++ )
387     {
388         cfContext->message[idx] = 0U;
389     }
390 
391     /*if message size is more than pad size process the block*/
392     if (cfContext->msgIdx >= CY_CRYPTOLITE_SHA256_PAD_SIZE)
393     {
394         err = Cy_Cryptolite_Sha256_Process(base, cfContext);
395         if(CY_CRYPTOLITE_SUCCESS != err)
396         {
397             return err;
398         }
399         /*clear the message block to finish*/
400         for ( idx = 0; idx < CY_CRYPTOLITE_SHA256_PAD_SIZE; idx++ )
401         {
402             cfContext->message[idx] = 0U;
403         }
404     }
405 
406     /*append total message size in bits from 57 to 64 bytes */
407     cfContext->message[CY_CRYPTOLITE_SHA256_BLOCK_SIZE - 1UL] = (uint8_t)totalMessageSizeInBits;
408     cfContext->message[CY_CRYPTOLITE_SHA256_BLOCK_SIZE - 2UL] = (uint8_t)(totalMessageSizeInBits >> 8);
409     cfContext->message[CY_CRYPTOLITE_SHA256_BLOCK_SIZE - 3UL] = (uint8_t)(totalMessageSizeInBits >> 16);
410     cfContext->message[CY_CRYPTOLITE_SHA256_BLOCK_SIZE - 4UL] = (uint8_t)(totalMessageSizeInBits >> 24);
411     cfContext->message[CY_CRYPTOLITE_SHA256_BLOCK_SIZE - 5UL] = (uint8_t)(totalMessageSizeInBits >> 32);
412     cfContext->message[CY_CRYPTOLITE_SHA256_BLOCK_SIZE - 6UL] = (uint8_t)(totalMessageSizeInBits >> 40);
413     cfContext->message[CY_CRYPTOLITE_SHA256_BLOCK_SIZE - 7UL] = (uint8_t)(totalMessageSizeInBits >> 48);
414     cfContext->message[CY_CRYPTOLITE_SHA256_BLOCK_SIZE - 8UL] = (uint8_t)(totalMessageSizeInBits >> 56);
415 
416     /*Process the last block*/
417     err = Cy_Cryptolite_Sha256_Process(base, cfContext);
418     if(CY_CRYPTOLITE_SUCCESS != err)
419     {
420         return err;
421     }
422 
423     /* This implementation uses little endian ordering and SHA uses big endian,
424        reverse all the bytes in 32bit word when copying the final output hash.*/
425     idx = (uint32_t)(CY_CRYPTOLITE_SHA256_HASH_SIZE / 4UL);
426     hashptr = (uint8_t*)cfContext->hash;
427 
428     for( ; idx != 0U; idx--)
429     {
430         *(digest)   = *(hashptr+3);
431         *(digest+1) = *(hashptr+2);
432         *(digest+2) = *(hashptr+1);
433         *(digest+3) = *(hashptr);
434 
435         digest  += 4U;
436         hashptr += 4U;
437     }
438 
439     return CY_CRYPTOLITE_SUCCESS;
440 }
441 
442 /*******************************************************************************
443 * Cy_Cryptolite_Sha256_Free
444 ******************************************************************************
445 *
446 * Clears the used memory and context data.
447 *
448 *  base
449 * The pointer to the CRYPTOLITE instance.
450 *
451 *  cfContext
452 * the pointer to the cy_stc_cryptolite_context_sha256_t structure that stores all
453 * internal variables for Cryptolite driver.
454 *
455 * return
456 * cy_en_cryptolite_status_t
457 *
458 *******************************************************************************/
Cy_Cryptolite_Sha256_Free(CRYPTOLITE_Type * base,cy_stc_cryptolite_context_sha256_t * cfContext)459 cy_en_cryptolite_status_t Cy_Cryptolite_Sha256_Free(CRYPTOLITE_Type *base,
460                                     cy_stc_cryptolite_context_sha256_t *cfContext)
461 {
462     uint32_t idx;
463     (void)base;
464 
465     /* Input parameters verification */
466     if (NULL != cfContext)
467     {
468         /* Clear the context memory */
469         for ( idx = 0; idx < CY_CRYPTOLITE_SHA256_BLOCK_SIZE; idx++ )
470         {
471             cfContext->message_schedule[idx] = 0U;
472         }
473 
474         for ( idx = 0; idx < (CY_CRYPTOLITE_SHA256_BLOCK_SIZE / 4u) + 1u ; idx++ )
475         {
476             cfContext->msgblock[idx] = 0U;
477         }
478 
479         for ( idx = 0; idx < CY_CRYPTOLITE_SHA256_HASH_SIZE/4U ; idx++ )
480         {
481             cfContext->hash[idx] = 0U;
482         }
483     }
484 
485     return CY_CRYPTOLITE_SUCCESS;
486 }
487 
488 /*******************************************************************************
489 * Cy_Cryptolite_Sha256_Run
490 ******************************************************************************
491 *
492 * This function performs the SHA256 Hash function.
493 * Provide the required parameters and the pointer
494 * to the context structure when making this function call.
495 * It is independent of the previous Crypto state because it already contains
496 * preparation, calculation, and finalization steps.
497 *
498 *  base
499 * The pointer to the CRYPTOLITE instance.
500 *
501 *  cfContext
502 * the pointer to the cy_stc_cryptolite_context_sha256_t structure that stores all
503 * internal variables for Cryptolite driver.
504 *
505 *  message
506 * The pointer to a message whose hash value is being computed.
507 *
508 *  messageSize
509 * The size of a message in bytes.
510 *
511 *  digest
512 * The pointer to the hash digest.
513 *
514 * return
515 * cy_en_cryptolite_status_t
516 *
517 *******************************************************************************/
Cy_Cryptolite_Sha256_Run(CRYPTOLITE_Type * base,uint8_t const * message,uint32_t messageSize,uint8_t * digest,cy_stc_cryptolite_context_sha256_t * cfContext)518 cy_en_cryptolite_status_t Cy_Cryptolite_Sha256_Run(CRYPTOLITE_Type *base,
519                                         uint8_t const *message,
520                                         uint32_t  messageSize,
521                                         uint8_t *digest,
522                                         cy_stc_cryptolite_context_sha256_t *cfContext)
523 {
524     cy_en_cryptolite_status_t err = CY_CRYPTOLITE_BAD_PARAMS;
525     /* Input parameters verification */
526     if ((NULL == base) || (NULL == cfContext) || (NULL == digest) || ((NULL == message) && (0UL != messageSize)))
527     {
528         return err;
529     }
530 
531     err = Cy_Cryptolite_Sha256_Init (base, cfContext);
532 
533     if (CY_CRYPTOLITE_SUCCESS == err)
534     {
535         err = Cy_Cryptolite_Sha256_Start (base, cfContext);
536     }
537     if (CY_CRYPTOLITE_SUCCESS == err)
538     {
539         err = Cy_Cryptolite_Sha256_Update (base, message, messageSize, cfContext);
540     }
541     if (CY_CRYPTOLITE_SUCCESS == err)
542     {
543         err = Cy_Cryptolite_Sha256_Finish (base, digest, cfContext);
544     }
545     if (CY_CRYPTOLITE_SUCCESS == err)
546     {
547         err = Cy_Cryptolite_Sha256_Free (base, cfContext);
548     }
549 
550     return (err);
551 }
552 
553 #endif
554 #endif
555 
556 #if defined(__cplusplus)
557 }
558 #endif
559 
560 
561 #endif /* CY_IP_MXCRYPTOLITE */
562 
563 
564 /* [] END OF FILE */
565