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