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