1 /* USER CODE BEGIN Header */
2 /**
3 ******************************************************************************
4 * @file hw_pka.c
5 * @author GPM WBL Application Team
6 * @brief This file implements utility functions for PKA on stm32wb09
7 ******************************************************************************
8 * @attention
9 *
10 * Copyright (c) 2024 STMicroelectronics.
11 * All rights reserved.
12 *
13 * This software is licensed under terms that can be found in the LICENSE file
14 * in the root directory of this software component.
15 * If no LICENSE file comes with this software, it is provided AS-IS.
16 *
17 ******************************************************************************
18 */
19 /* USER CODE END Header */
20
21 /* Includes ------------------------------------------------------------------*/
22 #include "stm32wb0x.h"
23 #include "pka_manager.h"
24 #include "stm32wb0x_ll_pka.h"
25 #include "hw_pka.h"
26
27 /** @defgroup PKA_Manager PKA Manager
28 * @{
29 */
30
31 #if defined(STM32WB09) || defined(STM32WB05)
32 /** @defgroup PKA_Manager_TypesDefinitions Private Type Definitions
33 * @{
34 */
35 /* Internal state*/
36 typedef enum
37 {
38 HW_PKA_STEP_0 = 0x0,
39 HW_PKA_STEP_1,
40 HW_PKA_STEP_2,
41 HW_PKA_STEP_3,
42 HW_PKA_STEP_4,
43 HW_PKA_STEP_5,
44 HW_PKA_STEP_6,
45 HW_PKA_STEP_7,
46 HW_PKA_STEP_8,
47 HW_PKA_STEP_9,
48 HW_PKA_STEP_10,
49 HW_PKA_STEP_11,
50 HW_PKA_STEP_12,
51 HW_PKA_STEP_13,
52 HW_PKA_STEP_END_SUCCESS
53 } StateMachine_Step;
54
55 typedef enum
56 {
57 HW_PKA_OPERATION_NONE = 0,
58 HW_PKA_OPERATION_P256
59 } StateMachine_operation;
60
61 /**
62 * @}
63 */
64 #endif /* STM32WB09 STM32WB05 */
65
66 /** @defgroup PKA_Manager_Private_Macros Private Macros
67 * @{
68 */
69 static uint32_t ret[24] = {0};
70
71 #ifdef STM32WB05
72 static uint32_t T[4][8] = {0};
73 #endif /* STM32WB05 */
74
75 #if defined(STM32WB06) || defined(STM32WB07)
76 /* 0b0000 00XY. X: PKA_DATA_PCX error Y: PKA_DATA_PCY error */
77 static uint8_t PKA_SetDataError = 0x00;
78
79 #define HW_PKA_RAM_ECC_ADDR_KP_ERROR (PKA_RAM_BASE)
80 #define HW_PKA_RAM_ECC_ADDR_K (PKA_RAM_BASE + 0x6C)
81 #define HW_PKA_RAM_ECC_ADDR_PX (PKA_RAM_BASE + 0x90)
82 #define HW_PKA_RAM_ECC_ADDR_PY (PKA_RAM_BASE + 0xB4)
83
84 #define HW_PKA_DATA_SK 0x01 /* PKA select data for K value */
85 #define HW_PKA_DATA_PCX 0x02 /* PKA select data for Point X coordinate value */
86 #define HW_PKA_DATA_PCY 0x03 /* PKA select data for Point Y coordinate value */
87 #endif /* STM32WB06 STM32WB07 */
88
89 #if defined(STM32WB09) || defined(STM32WB05)
90 static volatile uint32_t internalStateMachine_Operation = HW_PKA_OPERATION_NONE;
91 static volatile uint32_t internalStateMachine_Step = 0;
92
93 static volatile uint32_t bufferSecretKey[8] = {0};
94 static volatile uint32_t bufferPublicKey[16] = {0};
95
96 #define VERIFY_ECC_SCALAR_MUL_RESULT 1
97
98 static const uint32_t HW_PKA_oplen[2] = {
99 0x100,
100 0x0
101 };
102
103 static const uint32_t HW_PKA_nbits_k[2] = {
104 0x100,
105 0x0
106 };
107
108 static const uint32_t HW_PKA_nbits_m[2] = {
109 0x100,
110 0x0
111 };
112
113 static const uint32_t HW_PKA_a_coeff_sign[2] = {
114 0x1,
115 0x0
116 };
117
118 static const uint32_t HW_PKA_P256_gfp[8] =
119 {
120 0xFFFFFFFF, /* LSB */
121 0xFFFFFFFF,
122 0xFFFFFFFF,
123 0x00000000,
124 0x00000000,
125 0x00000000,
126 0x00000001,
127 0xFFFFFFFF,
128 };
129
130 static const uint32_t HW_PKA_P256_r2[8] =
131 {
132 0x00000002, /* LSB */
133 0x00000005,
134 0x00000003,
135 0xFFFFFFFE,
136 0xFFFFFFF9,
137 0xFFFFFFFB,
138 0xFFFFFFFC,
139 0xFFFFFFFC,
140 };
141
142 static const uint32_t HW_PKA_P256_a[8] =
143 {
144 0x00000003, /* LSB */
145 0x00000000,
146 0x00000000,
147 0x00000000,
148 0x00000000,
149 0x00000000,
150 0x00000000,
151 0x00000000,
152 };
153
154 static const uint32_t HW_PKA_P256_b[8] =
155 {
156 0x27D2604B, /* LSB */
157 0x3BCE3C3E,
158 0xCC53B0F6,
159 0x651D06B0,
160 0x769886BC,
161 0xB3EBBD55,
162 0xAA3A93E7,
163 0x5AC635D8,
164 };
165
166 /**
167 * @}
168 */
169 #endif /* STM32WB09 STM32WB05 */
170
171 /** @defgroup PKA_Manager_External_Variables External Variables
172 * @{
173 */
174
175 extern PKA_HandleTypeDef hpka;
176
177 /**
178 * @}
179 */
180
181 /** @defgroup PKA_Manager_Private_FunctionPrototypes Private Function Prototypes
182 * @{
183 */
184 void HW_PKA_ExitWithError(uint32_t errorCode);
185 void HW_PKA_ProcEnd_StateMachine(void);
186 void (*HW_PKA_funcCB_LP)(PKAMGR_ResultStatus error_code, void *args_p);
187 #if defined(STM32WB09) || defined(STM32WB05)
188 void HW_PKA_Comparison( const uint32_t* opLen, const uint32_t* op1 , const uint32_t* op2 );
189 void HW_PKA_P256_StartPointCheck( const uint32_t* x, const uint32_t* y );
190 uint32_t HW_PKA_IsPointCheckOk(void);
191 uint32_t HW_PKA_IsRangeCheckOk(void);
192 void HW_PKA_P256_StartEccScalarMul( const uint32_t* k, const uint32_t* pX, const uint32_t* pY );
193 void HW_PKA_P256_ReadEccScalarMul(uint32_t* pX, uint32_t* pY);
194 uint32_t HW_PKA_isStartPoint(const uint32_t* p);
195 #endif /* STM32WB09 STM32WB05 */
196 #ifdef STM32WB05
197 void HW_PKA_MontgomeryMultiplication( uint32_t opLen, const uint32_t* op1, const uint32_t* op2, const uint32_t* p);
198 #endif /* STM32WB05 */
199 /**
200 * @}
201 */
202
203 /** @defgroup PKA_Manager_Private_Functions Private Functions
204 * @{
205 */
206
207 #if defined STM32WB09
208
HW_PKA_WriteSingleInput(uint32_t index,int size,const uint32_t * word)209 void HW_PKA_WriteSingleInput( uint32_t index, int size, const uint32_t* word )
210 {
211 /* Write the single word into PKA RAM */
212 for(int i=0; i<size; i++)
213 {
214 PKA->RAM[index++] = *word++;
215 }
216 }
217
218 #elif defined STM32WB05
219
HW_PKA_WriteSingleInput(uint32_t index,uint32_t word)220 void HW_PKA_WriteSingleInput( uint32_t index, uint32_t word )
221 {
222 /* Write the single word into PKA RAM */
223 PKA->RAM[index] = word;
224 }
225
226 #endif
227
228 #if defined STM32WB09
229
HW_PKA_WriteOperand(uint32_t index,int size,const uint32_t * in)230 void HW_PKA_WriteOperand( uint32_t index, int size, const uint32_t* in )
231 {
232 uint32_t* pka_ram = (uint32_t*)&PKA->RAM[index];
233 /* Write the input data into PKA RAM */
234 for ( ; size > 0; size-- )
235 {
236 *pka_ram++ = *in++;
237 }
238 /* Write extra zeros into PKA RAM */
239 *pka_ram++ = 0;
240 *pka_ram = 0;
241 }
242
243 #elif defined STM32WB05
244
HW_PKA_WriteOperand(uint32_t index,int size,const uint32_t * in)245 void HW_PKA_WriteOperand( uint32_t index, int size, const uint32_t* in )
246 {
247 uint32_t* pka_ram = (uint32_t*)&PKA->RAM[index];
248 /* Write the input data into PKA RAM */
249 for ( ; size > 0; size-- )
250 {
251 *pka_ram++ = *in++;
252 }
253 /* Write extra zeros into PKA RAM */
254 *pka_ram = 0;
255 }
256
257 #endif
258
259 #if defined(STM32WB05) || defined(STM32WB09)
HW_PKA_ReadResult(uint32_t index,int size,uint32_t * out)260 void HW_PKA_ReadResult( uint32_t index, int size, uint32_t* out )
261 {
262 uint32_t* pka_ram = (uint32_t*)&PKA->RAM[index];
263 /* Read from PKA RAM */
264 for ( ; size > 0; size-- )
265 {
266 *out++ = *pka_ram++;
267 }
268 }
269 #endif /* STM32WB05 STM32WB09 */
270
271 #if defined STM32WB09
272
273 /**
274 * @brief
275 * @param index PKA RAM index at 32 bit
276 * @param out must be 64bit
277 *
278 */
HW_PKA_ReadSingleOutput(uint32_t index,uint32_t * out)279 void HW_PKA_ReadSingleOutput( uint32_t index, uint32_t* out)
280 {
281 HW_PKA_ReadResult(index, 2, out);
282 }
283
284 #elif defined STM32WB05
285
286 /**
287 * @brief
288 * @param
289 * @param
290 *
291 */
HW_PKA_ReadSingleOutput(uint32_t index)292 uint32_t HW_PKA_ReadSingleOutput( uint32_t index )
293 {
294 /* Read a single word from PKA RAM */
295 return PKA_RAM->RAM[index];
296 }
297
298 #endif /* STM32WB09 elif STM32WB05 */
299
300 #if defined(STM32WB06) || defined(STM32WB07)
301
HAL_PKA_OperationCpltCallback(PKA_HandleTypeDef * hpka)302 void HAL_PKA_OperationCpltCallback(PKA_HandleTypeDef *hpka)
303 {
304 PKAMGR_Unlock();
305 HW_PKA_IRQHandler();
306 PKAMGR_IRQCallback();
307 }
308
HAL_PKA_ErrorCallback(PKA_HandleTypeDef * hpka)309 void HAL_PKA_ErrorCallback(PKA_HandleTypeDef *hpka)
310 {
311 PKAMGR_Unlock();
312 PKAMGR_IRQCallback();
313 }
314
315 /** @defgroup PKA_SELECT_DATA_VALUE Select Data for PKA operation
316 * @{
317 */
318 /**
319 * @}
320 */
321
322 /**
323 * @brief Internal Utility for PKA key range check
324 * @param a: pka key
325 * b: reference key
326 * bufferSize: key size
327 * @retval check result
328 */
rev_memcmp(uint8_t * a,const uint8_t * b,uint8_t bufferSize)329 static int rev_memcmp(uint8_t *a, const uint8_t *b, uint8_t bufferSize)
330 {
331 uint_fast8_t i = bufferSize;
332 int retval = 0;
333
334 do
335 {
336 i--;
337 retval = (int)a[i] - (int)b[i];
338 if (retval !=0)
339 {
340 break;
341 }
342 } while (i != 0U);
343
344 return retval;
345 }
346
347 /**
348 * @brief Write the PKA RAM with the input data.
349 * @param dataType: select the region of PKA RAM to write:
350 * @arg HW_PKA_DATA_SK is the K value
351 * @arg HW_PKA_DATA_PCX is the point X coordinate
352 * @arg HW_PKA_DATA_PCY is the point Y coordinate
353 * @param srcData Source Data
354 * @retval ErrorStatus
355 */
HW_PKA_SetData(uint8_t dataType,uint32_t * srcData)356 ErrorStatus HW_PKA_SetData(uint8_t dataType, uint32_t* srcData)
357 {
358 const uint8_t P256_P_LE[32] = {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0xff,0xff,0xff,0xff};
359 const uint8_t BLE_P256_ABELIAN_ORDER_R_LE[32] = {0x51,0x25,0x63,0xFC,0xC2,0xCA,0xB9,0xF3,0x84,0x9E,0x17,0xA7,0xAD,0xFA,0xE6,0xBC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF};
360 uint32_t StartAddress;
361 uint8_t idx;
362
363 /* Check the parameters */
364 assert_param(IS_LL_PKA_CMD(dataType));
365
366 if (dataType == HW_PKA_DATA_SK) {
367 if (rev_memcmp((uint8_t *) srcData, (uint8_t *)BLE_P256_ABELIAN_ORDER_R_LE, 32) >= 0) {
368 PKA_SetDataError |= 0x04;
369 return ERROR;
370 }
371 else {
372 PKA_SetDataError &= ~0x04;
373 }
374 StartAddress = HW_PKA_RAM_ECC_ADDR_K;
375 }
376
377 else if (dataType == HW_PKA_DATA_PCX) {
378 if (rev_memcmp((uint8_t *) srcData, (uint8_t *)P256_P_LE, 32) >= 0) {
379 PKA_SetDataError |= 0x01;
380 return ERROR;
381 }
382 else {
383 PKA_SetDataError &= ~0x01;
384 }
385 StartAddress = HW_PKA_RAM_ECC_ADDR_PX;
386
387 }
388
389 else if (dataType == HW_PKA_DATA_PCY) {
390 if (rev_memcmp((uint8_t *) srcData, (uint8_t *)P256_P_LE, 32) >= 0) {
391 PKA_SetDataError |= 0x02;
392 return ERROR;
393 }
394 else {
395 PKA_SetDataError &= ~0x02;
396 }
397 StartAddress = HW_PKA_RAM_ECC_ADDR_PY;
398 }
399 else
400 return ERROR;
401
402 /* Write the source data to target PKA RAM address. */
403 for (idx = 0; idx<8; idx++)
404 {
405 *(uint32_t *)(StartAddress + 4*idx) = srcData[idx];
406 }
407
408 /* A 9th word of zeros must be added */
409 *(uint32_t *)(StartAddress + 32UL) = 0x00000000;
410
411 return SUCCESS;
412 }
413
414 /**
415 * @brief Get from the PKA RAM the output data.
416 * @param dataType: select the region of PKA RAM to read:
417 * @arg HW_PKA_DATA_SK is the K value
418 * @arg HW_PKA_DATA_PCX is the point X coordinate
419 * @arg HW_PKA_DATA_PCY is the point Y coordinate
420 * @param dataTarget PKA RAM output data
421 * @retval ErrorStatus
422 */
HW_PKA_GetData(uint8_t dataType,uint8_t * dataTarget)423 ErrorStatus HW_PKA_GetData(uint8_t dataType, uint8_t* dataTarget)
424 {
425 uint32_t StartAddress;
426
427 /* Check the parameters */
428 assert_param(IS_LL_PKA_CMD(dataType));
429
430 if (dataType == HW_PKA_DATA_SK)
431 StartAddress = HW_PKA_RAM_ECC_ADDR_K;
432 else if (dataType == HW_PKA_DATA_PCX)
433 StartAddress = HW_PKA_RAM_ECC_ADDR_PX;
434 else if (dataType == HW_PKA_DATA_PCY)
435 StartAddress = HW_PKA_RAM_ECC_ADDR_PY;
436 else return ERROR;
437
438 /* Read the data to target PKA RAM address. */
439 for(uint8_t i=0;i<32;i++) {
440 dataTarget[i] = ((uint8_t *)StartAddress)[i];
441 }
442
443 return SUCCESS;
444 }
445
446 #endif /* STM32WB06 STM32WB07 */
447
HW_PKA_Init(void)448 void HW_PKA_Init(void)
449 {
450 PKAMGR_Init();
451 /* Activate interrupts */
452 LL_PKA_EnableIT_ADDRERR(PKA);
453 LL_PKA_EnableIT_RAMERR(PKA);
454 LL_PKA_EnableIT_PROCEND(PKA);
455 }
456
HW_PKA_PowerSaveLevelCheck(void)457 uint8_t HW_PKA_PowerSaveLevelCheck(void)
458 {
459 if(PKAMGR_SleepCheck()==PKAMGR_SUCCESS)
460 {
461 return POWER_SAVE_LEVEL_STOP;
462 }
463 else // PKA on going
464 {
465 return POWER_SAVE_LEVEL_CPU_HALT;
466 }
467 }
468
469 /**
470 * @brief
471 * @param
472 * @param
473 *
474 */
HW_PKA_StartP256DHkeyGeneration(const uint32_t * secretKey,const uint32_t * publicKey,PKAMGR_funcCB funcCB)475 PKAMGR_ResultStatus HW_PKA_StartP256DHkeyGeneration(const uint32_t* secretKey, const uint32_t* publicKey, PKAMGR_funcCB funcCB)
476 {
477 /* Set the PKA internal state to busy */
478 if(PKAMGR_Lock()!=PKAMGR_SUCCESS)
479 return PKAMGR_ERR_BUSY;
480
481 HW_PKA_funcCB_LP = funcCB;
482 #if defined(STM32WB09) || defined(STM32WB05)
483 /* Save input data */
484 for(int i=0;i<8;i++)
485 bufferSecretKey[i] = secretKey[i];
486 for(int i=0;i<16;i++)
487 bufferPublicKey[i] = publicKey[i];
488
489 if(HW_PKA_isStartPoint(publicKey))
490 {
491 /* p256 public key generation */
492 internalStateMachine_Step = HW_PKA_STEP_3;
493 internalStateMachine_Operation = HW_PKA_OPERATION_P256;
494 HW_PKA_P256_StartEccScalarMul( secretKey, (uint32_t *)&publicKey[0], (uint32_t *)&publicKey[8] );
495 }
496 else
497 {
498 /* p256 dhkey generation */
499 internalStateMachine_Step = HW_PKA_STEP_0;
500 internalStateMachine_Operation = HW_PKA_OPERATION_P256;
501 /* Call the PKA range check operation for public key X coordinate */
502 HW_PKA_Comparison(HW_PKA_oplen, (uint32_t *)&publicKey[0], HW_PKA_P256_gfp);
503
504 #if !defined(ASYNC_MODE)
505 // blocking mode (initial check steps interval time: 0.476ms)
506 while(internalStateMachine_Step!=HW_PKA_STEP_1);
507
508 /* Test result of range check operation for public key X coordinate */
509 if( !HW_PKA_IsRangeCheckOk() )
510 {
511 internalStateMachine_Operation = HW_PKA_OPERATION_NONE;
512 internalStateMachine_Step = HW_PKA_STEP_0;
513 PKAMGR_Unlock();
514 return PKAMGR_ERR_PARAM;
515 }
516 else
517 {
518 /* Call the PKA range check operation for public key Y coordinate */
519 HW_PKA_Comparison(HW_PKA_oplen, (uint32_t *)&bufferPublicKey[8], HW_PKA_P256_gfp);
520 }
521
522 while(internalStateMachine_Step!=HW_PKA_STEP_2);
523
524 /* Test result of range check operation for public key X coordinate */
525 if( !HW_PKA_IsRangeCheckOk() )
526 {
527 internalStateMachine_Operation = HW_PKA_OPERATION_NONE;
528 internalStateMachine_Step = HW_PKA_STEP_0;
529 PKAMGR_Unlock();
530 return PKAMGR_ERR_PARAM;
531 }
532 else
533 {
534 /* Call the PKA point check operation for remote public key */
535 HW_PKA_P256_StartPointCheck( (uint32_t *)&bufferPublicKey[0], (uint32_t *)&bufferPublicKey[8] );
536 }
537
538 while(internalStateMachine_Step!=HW_PKA_STEP_3);
539
540 /* Test result of point check operation for remote public key */
541 if ( !HW_PKA_IsPointCheckOk() )
542 {
543 internalStateMachine_Operation = HW_PKA_OPERATION_NONE;
544 internalStateMachine_Step = HW_PKA_STEP_0;
545 PKAMGR_Unlock();
546 return PKAMGR_ERR_PARAM;
547 }
548 else
549 {
550 /* Call the PKA scalar multiplication with the local private key
551 as k and the remote public key as starting point,
552 in order to compute the DH key */
553 HW_PKA_P256_StartEccScalarMul( (uint32_t *)&bufferSecretKey[0], (uint32_t *)&bufferPublicKey[0], (uint32_t *)&bufferPublicKey[8] );
554 }
555
556 #endif /* !defined(ASYNC_MODE) */
557 }
558 #endif /* STM32WB09 STM32WB05 */
559
560 #if defined(STM32WB06) || defined(STM32WB07)
561 /* ***** PROCEDURE FOR NewPoint ***** */
562
563 /* Insert the random K for NewPoint */
564 if(HW_PKA_SetData(HW_PKA_DATA_SK, (uint32_t*) secretKey) == ERROR)
565 {
566 PKAMGR_Unlock();
567 return PKAMGR_ERR_PARAM;
568 }
569
570 /* Insert the initial starting point coordinates */
571 if(HW_PKA_SetData(HW_PKA_DATA_PCX, (uint32_t *)&publicKey[0]) == ERROR)
572 {
573 PKAMGR_Unlock();
574 return PKAMGR_ERR_PARAM;
575 }
576
577 if( HW_PKA_SetData(HW_PKA_DATA_PCY, (uint32_t *)&publicKey[8]) == ERROR)
578 {
579 PKAMGR_Unlock();
580 return PKAMGR_ERR_PARAM;
581 }
582
583 /* Launch the computation in interrupt mode */
584 LL_PKA_Start(PKA);
585 #endif /* STM32WB06 STM32WB07 */
586
587 return PKAMGR_SUCCESS;
588 }
589
590 #if defined(STM32WB09) || defined(STM32WB05)
591 /**
592 * @brief
593 * @param
594 * @param
595 *
596 */
HW_PKA_ExitWithError(uint32_t errorCode)597 void HW_PKA_ExitWithError(uint32_t errorCode)
598 {
599 internalStateMachine_Operation = 0;
600 internalStateMachine_Step = 0;
601 PKAMGR_Unlock();
602 ret[0]=errorCode;
603 for(int i=0; i<8; i++)
604 {
605 ret[i+16] = bufferSecretKey[i];
606 }
607 HW_PKA_funcCB_LP(PKAMGR_ERROR, ret);
608 }
609
610 /**
611 * @brief
612 * @param
613 * @param
614 *
615 */
HW_PKA_ProcEnd_StateMachine(void)616 void HW_PKA_ProcEnd_StateMachine(void)
617 {
618 if(internalStateMachine_Operation == HW_PKA_OPERATION_P256)
619 {
620 switch(internalStateMachine_Step)
621 {
622 case HW_PKA_STEP_0:
623 internalStateMachine_Step = HW_PKA_STEP_1;
624
625 break;
626 case HW_PKA_STEP_1:
627 internalStateMachine_Step = HW_PKA_STEP_2;
628 break;
629 case HW_PKA_STEP_2:
630 internalStateMachine_Step = HW_PKA_STEP_3;
631 break;
632 case HW_PKA_STEP_3:
633 /* Read the PKA scalar multiplication result which is the DH key */
634 for(int i=0;i<8;i++)
635 ret[i] = bufferSecretKey[i];
636 HW_PKA_P256_ReadEccScalarMul( (uint32_t *)&ret[8], (uint32_t *)&ret[16] );
637 #ifdef STM32WB09
638 internalStateMachine_Step = HW_PKA_STEP_END_SUCCESS;
639 HW_PKA_ProcEnd_StateMachine();
640 #endif /* STM32WB09 */
641
642 #ifdef STM32WB05
643 if( VERIFY_ECC_SCALAR_MUL_RESULT )
644 {
645 internalStateMachine_Step = HW_PKA_STEP_4;
646 HW_PKA_ReadResult( 739, 8, &ret[0] );
647 HW_PKA_MontgomeryMultiplication( 256, &ret[0], &ret[0], HW_PKA_P256_gfp);
648 }
649 else
650 {
651 internalStateMachine_Step = HW_PKA_STEP_END_SUCCESS;
652 HW_PKA_ProcEnd_StateMachine();
653 }
654 break;
655 case HW_PKA_STEP_4:
656 HW_PKA_ReadResult( 500, 8, &T[0][0] );
657
658 internalStateMachine_Step = HW_PKA_STEP_5;
659
660 /* Set the point coordinate X1 */
661 HW_PKA_ReadResult( 634, 8, &ret[0]);
662 HW_PKA_MontgomeryMultiplication( 256, &ret[0], &T[0][0], HW_PKA_P256_gfp);
663
664 break;
665 case HW_PKA_STEP_5:
666 HW_PKA_ReadResult( 500, 8, &T[1][0] );
667
668 internalStateMachine_Step = HW_PKA_STEP_6;
669 /* Set the point coordinate Z1 */
670 HW_PKA_ReadResult( 676, 8, &ret[0] );
671 HW_PKA_MontgomeryMultiplication( 256, &ret[0], &ret[0], HW_PKA_P256_gfp);
672 break;
673 case HW_PKA_STEP_6:
674 HW_PKA_ReadResult( 500, 8, &T[2][0] );
675
676 internalStateMachine_Step = HW_PKA_STEP_7;
677 /* Set the point coordinate X2 */
678 HW_PKA_ReadResult( 697, 8, &ret[0] );
679 HW_PKA_MontgomeryMultiplication( 256, &ret[0], &T[2][0], HW_PKA_P256_gfp);
680 break;
681 case HW_PKA_STEP_7:
682 HW_PKA_ReadResult( 500, 8, &T[3][0] );
683
684 internalStateMachine_Step = HW_PKA_STEP_8;
685 HW_PKA_Comparison(HW_PKA_oplen, &T[1][0], &T[3][0]);
686 break;
687 case HW_PKA_STEP_8:
688 internalStateMachine_Step = HW_PKA_STEP_9;
689 if(HW_PKA_ReadSingleOutput(500)!=0)
690 {
691 HW_PKA_ExitWithError(0xFF00+HW_PKA_STEP_8);
692 }
693 else
694 {
695 /* Set the point coordinate Z2 */
696 HW_PKA_ReadResult( 739, 8, &ret[0] );
697 HW_PKA_MontgomeryMultiplication( 256, &ret[0], &T[0][0], HW_PKA_P256_gfp);
698 }
699 break;
700 case HW_PKA_STEP_9:
701 HW_PKA_ReadResult( 500, 8, &T[3][0] );
702
703 internalStateMachine_Step = HW_PKA_STEP_10;
704 /* Set the point coordinate Y1 */
705 HW_PKA_ReadResult( 655, 8, &ret[0] );
706 HW_PKA_MontgomeryMultiplication( 256, &ret[0], &T[3][0], HW_PKA_P256_gfp);
707 break;
708 case HW_PKA_STEP_10:
709 HW_PKA_ReadResult( 500, 8, &T[0][0] );
710
711 internalStateMachine_Step = HW_PKA_STEP_11;
712 /* Set the point coordinate Z1 */
713 HW_PKA_ReadResult( 676, 8, &ret[0] );
714 HW_PKA_MontgomeryMultiplication( 256, &ret[0], &T[2][0], HW_PKA_P256_gfp);
715 break;
716 case HW_PKA_STEP_11:
717 HW_PKA_ReadResult( 500, 8, &T[1][0] );
718
719 internalStateMachine_Step = HW_PKA_STEP_12;
720 /* Set the point coordinate Y2 */
721 HW_PKA_ReadResult( 718, 8, &ret[0] );
722 HW_PKA_MontgomeryMultiplication( 256, &ret[0], &T[1][0], HW_PKA_P256_gfp);
723 break;
724 case HW_PKA_STEP_12:
725 HW_PKA_ReadResult( 500, 8, &T[2][0] );
726
727 internalStateMachine_Step = HW_PKA_STEP_13;
728 HW_PKA_Comparison(HW_PKA_oplen, &T[0][0], &T[2][0]);
729 break;
730 case HW_PKA_STEP_13:
731 if(HW_PKA_ReadSingleOutput(500)!=0)
732 {
733 HW_PKA_ExitWithError(0xFF00+HW_PKA_STEP_13);
734 }
735 else
736 {
737 internalStateMachine_Step = HW_PKA_STEP_END_SUCCESS;
738 HW_PKA_ProcEnd_StateMachine();
739 }
740 #endif /* STM32WB05 */
741 break;
742 case HW_PKA_STEP_END_SUCCESS:
743 internalStateMachine_Operation = HW_PKA_OPERATION_NONE;
744 internalStateMachine_Step = HW_PKA_STEP_0;
745 PKAMGR_Unlock();
746 for(int i=0;i<8;i++)
747 ret[i] = bufferSecretKey[i];
748 HW_PKA_funcCB_LP(PKAMGR_SUCCESS, ret);
749 break;
750 default:
751 HW_PKA_ExitWithError(0xA0);
752 }
753 }
754 }
755
756 /**
757 * Brief This function handles PKA Instance interrupt request.
758 * Param None
759 * Retval None
760 */
HW_PKA_IRQHandler(void)761 void HW_PKA_IRQHandler(void)
762 {
763 /* Manage the PKA RAM error flag */
764 if(LL_PKA_IsActiveFlag_RAMERR(PKA) == 1)
765 {
766 LL_PKA_ClearFlag_RAMERR(PKA);
767 HW_PKA_ExitWithError(0xB1);
768 }
769
770 /* Manage the Address error flag */
771 if(LL_PKA_IsActiveFlag_ADDRERR(PKA) == 1)
772 {
773 LL_PKA_ClearFlag_ADDRERR(PKA);
774 HW_PKA_ExitWithError(0xB2);
775 }
776
777 /* Manage the PKA End of Operation flag */
778 if(LL_PKA_IsActiveFlag_PROCEND(PKA) == 1)
779 {
780 LL_PKA_ClearFlag_PROCEND(PKA);
781 HW_PKA_ProcEnd_StateMachine();
782 }
783 }
784
HAL_PKA_OperationCpltCallback(PKA_HandleTypeDef * hpka)785 void HAL_PKA_OperationCpltCallback(PKA_HandleTypeDef *hpka)
786 {
787 HW_PKA_ProcEnd_StateMachine();
788 PKAMGR_IRQCallback();
789 }
790
HAL_PKA_ErrorCallback(PKA_HandleTypeDef * hpka)791 void HAL_PKA_ErrorCallback(PKA_HandleTypeDef *hpka)
792 {
793 HW_PKA_ExitWithError(hpka->ErrorCode);
794 PKAMGR_IRQCallback();
795 }
796
797 /**
798 * @brief
799 * @param
800 * @param
801 *
802 */
HW_PKA_IsPointCheckOk(void)803 uint32_t HW_PKA_IsPointCheckOk(void)
804 {
805 #ifdef STM32WB09
806 uint32_t result[2] = {0};
807 HW_PKA_ReadResult( PKA_POINT_CHECK_OUT_ERROR, 2, &result[0] );
808 return ( result[0] == 0xD60D);
809 #endif /* STM32WB09 */
810
811 #ifdef STM32WB05
812 return (HW_PKA_ReadSingleOutput( 0 ) == 0);
813 #endif /* STM32WB05 */
814 }
815
816 /**
817 * @brief
818 * @param
819 * @param
820 *
821 */
HW_PKA_IsRangeCheckOk(void)822 uint32_t HW_PKA_IsRangeCheckOk(void)
823 {
824 #ifdef STM32WB09
825 uint32_t result[2] = {0};
826 HW_PKA_ReadResult( PKA_COMPARISON_OUT_RESULT, 2, &result[0] );
827 return ( result[0] == 0x916A);
828 #endif /* STM32WB09 */
829
830 #ifdef STM32WB05
831 return (HW_PKA_ReadSingleOutput( 500 ) == 2);
832 #endif /* STM32WB05 */
833 }
834
835 /**
836 * @brief
837 * @param
838 * @param
839 *
840 */
HW_PKA_P256_StartEccScalarMul(const uint32_t * k,const uint32_t * pX,const uint32_t * pY)841 void HW_PKA_P256_StartEccScalarMul( const uint32_t* k, const uint32_t* pX, const uint32_t* pY )
842 {
843 /* Set the configuration */
844 LL_PKA_Config( PKA, LL_PKA_MODE_ECC_KP_PRIMITIVE );
845
846 /* Enable the Security level */
847 LL_PKA_SetSecurityLevel(PKA, LL_PKA_SECURITY_LEVEL_ENABLE);
848
849 #ifdef STM32WB09
850 /* Set the scalar multiplier k length */
851 HW_PKA_WriteSingleInput( PKA_ECC_SCALAR_MUL_IN_EXP_NB_BITS, 2, HW_PKA_nbits_k);
852 /* Set the modulus length */
853 HW_PKA_WriteSingleInput( PKA_ECC_SCALAR_MUL_IN_OP_NB_BITS, 2, HW_PKA_nbits_m);
854 /* Set the coefficient a sign */
855 HW_PKA_WriteSingleInput( PKA_ECC_SCALAR_MUL_IN_A_COEFF_SIGN, 2, HW_PKA_a_coeff_sign);
856 /* Set the coefficient |a| */
857 HW_PKA_WriteOperand( PKA_ECC_SCALAR_MUL_IN_A_COEFF, 8, HW_PKA_P256_a );
858 /* Set the modulus value p */
859 HW_PKA_WriteOperand( PKA_ECC_SCALAR_MUL_IN_MOD_GF, 8, HW_PKA_P256_gfp );
860 /* Set the Montgomery parameter */
861 HW_PKA_WriteOperand( PKA_ECC_SCALAR_MUL_IN_MONTGOMERY_PARAM, 8, HW_PKA_P256_r2 );
862 /* Set the scalar multiplier k */
863 HW_PKA_WriteOperand( PKA_ECC_SCALAR_MUL_IN_K, 8, k );
864 /* Set the point P coordinate x */
865 HW_PKA_WriteOperand( PKA_ECC_SCALAR_MUL_IN_INITIAL_POINT_X, 8, pX );
866 /* Set the point P coordinate y */
867 HW_PKA_WriteOperand( PKA_ECC_SCALAR_MUL_IN_INITIAL_POINT_Y, 8, pY );
868 #endif /* STM32WB09 */
869
870 #ifdef STM32WB05
871 /* Set the scalar multiplier k length */
872 HW_PKA_WriteSingleInput( 0, HW_PKA_nbits_k[0] );
873 /* Set the modulus length */
874 HW_PKA_WriteSingleInput( 1, HW_PKA_nbits_m[0] );
875 /* Set the coefficient a sign */
876 HW_PKA_WriteSingleInput( 2, HW_PKA_a_coeff_sign[0] );
877 /* Set the coefficient |a| */
878 HW_PKA_WriteOperand( 3, 8, HW_PKA_P256_a );
879 /* Set the modulus value p */
880 HW_PKA_WriteOperand( 24, 8, HW_PKA_P256_gfp );
881 /* Set the Montgomery parameter */
882 HW_PKA_WriteOperand( 45, 8, HW_PKA_P256_r2 );
883 /* Set the scalar multiplier k */
884 HW_PKA_WriteOperand( 66, 8, k );
885 /* Set the point P coordinate x */
886 HW_PKA_WriteOperand( 87, 8, pX );
887 /* Set the point P coordinate y */
888 HW_PKA_WriteOperand( 108, 8, pY );
889 #endif /* STM32WB05 */
890
891 /* Wait for PKA busy flag equal to 0 */
892 while(LL_PKA_IsActiveFlag_BUSY(PKA));
893
894 /* Start the PKA processing */
895 LL_PKA_Start( PKA );
896 }
897
898 /**
899 * @brief
900 * @param
901 * @param
902 *
903 */
HW_PKA_Comparison(const uint32_t * opLen,const uint32_t * op1,const uint32_t * op2)904 void HW_PKA_Comparison( const uint32_t* opLen, const uint32_t* op1 , const uint32_t* op2 )
905 {
906 LL_PKA_SetMode(PKA, LL_PKA_MODE_COMPARISON );
907 #ifdef STM32WB09
908 /* Loads the input buffers to PKA RAM */
909 /* Set the muber of bits of P */
910 HW_PKA_WriteSingleInput( PKA_COMPARISON_NB_BITS, 2, opLen );
911 /* Set the op1 */
912 HW_PKA_WriteOperand( PKA_COMPARISON_IN_OP1, 8, op1 );
913 /* Set the op2 */
914 HW_PKA_WriteOperand( PKA_COMPARISON_IN_OP2, 8, op2 );
915 #endif /* STM32WB09 */
916
917 #ifdef STM32WB05
918 /* Loads the input buffers to PKA RAM */
919 /* Set the muber of bits of P */
920 HW_PKA_WriteSingleInput( 1, opLen[0] );
921 /* Set the op1 */
922 HW_PKA_WriteOperand( 301, 8, op1 );
923 /* Set the op2 */
924 HW_PKA_WriteOperand( 401, 8, op2 );
925 #endif /* STM32WB05 */
926 /* Wait for PKA busy flag equal to 0 */
927 while(LL_PKA_IsActiveFlag_BUSY(PKA));
928
929 /* Launch the computation in interrupt mode */
930 LL_PKA_Start(PKA);
931 }
932
HW_PKA_P256_StartPointCheck(const uint32_t * x,const uint32_t * y)933 void HW_PKA_P256_StartPointCheck( const uint32_t* x, const uint32_t* y )
934 {
935 /* Set the configuration */
936 LL_PKA_Config( PKA, LL_PKA_MODE_POINT_CHECK );
937 #ifdef STM32WB09
938 /* Set the muber of bits of p */
939 HW_PKA_WriteSingleInput( PKA_POINT_CHECK_IN_MOD_NB_BITS, 2, HW_PKA_nbits_m);
940 /* Set the coefficient a sign */
941 HW_PKA_WriteSingleInput( PKA_POINT_CHECK_IN_A_COEFF_SIGN, 2, HW_PKA_a_coeff_sign);
942 /* Set the coefficient |a| */
943 HW_PKA_WriteOperand( PKA_POINT_CHECK_IN_A_COEFF, 8, HW_PKA_P256_a );
944 /* Set the modulus value p */
945 HW_PKA_WriteOperand( PKA_POINT_CHECK_IN_MOD_GF, 8, HW_PKA_P256_gfp );
946 /* Set the point coordinate x */
947 HW_PKA_WriteOperand( PKA_POINT_CHECK_IN_INITIAL_POINT_X, 8, x );
948 /* Set the point coordinate y */
949 HW_PKA_WriteOperand( PKA_POINT_CHECK_IN_INITIAL_POINT_Y, 8, y );
950 /* Set the Montgomery parameter */
951 HW_PKA_WriteOperand( PKA_ECC_SCALAR_MUL_IN_MONTGOMERY_PARAM, 8, HW_PKA_P256_r2 );
952 /* Set the coefficient |b| */
953 HW_PKA_WriteOperand( PKA_POINT_CHECK_IN_B_COEFF, 8, HW_PKA_P256_b );
954 #endif /* STM32WB09 */
955
956 #ifdef STM32WB05
957 /* Set the muber of bits of p */
958 HW_PKA_WriteSingleInput( 1, 256 );
959 /* Set the coefficient a sign */
960 HW_PKA_WriteSingleInput( 2, 1 );
961 /* Set the coefficient |a| */
962 HW_PKA_WriteOperand( 3, 8, HW_PKA_P256_a );
963 /* Set the modulus value p */
964 HW_PKA_WriteOperand( 24, 8, HW_PKA_P256_gfp );
965 /* Set the point coordinate x */
966 HW_PKA_WriteOperand( 87, 8, x );
967 /* Set the point coordinate y */
968 HW_PKA_WriteOperand( 108, 8, y );
969 /* Set the coefficient |b| */
970 HW_PKA_WriteOperand( 255, 8, HW_PKA_P256_b );
971 #endif /* STM32WB05 */
972
973 /* Wait for PKA busy flag equal to 0 */
974 while(LL_PKA_IsActiveFlag_BUSY(PKA));
975
976 /* Start the PKA processing */
977 LL_PKA_Start( PKA );
978 }
979
980 #ifdef STM32WB05
HW_PKA_MontgomeryMultiplication(uint32_t opLen,const uint32_t * op1,const uint32_t * op2,const uint32_t * p)981 void HW_PKA_MontgomeryMultiplication( uint32_t opLen, const uint32_t* op1, const uint32_t* op2, const uint32_t* p)
982 {
983 /* Set the configuration */
984 LL_PKA_Config( PKA, LL_PKA_MODE_MONTGOMERY_MUL );
985
986 /* Loads the input buffers to PKA RAM */
987 /* Set the operand length */
988 HW_PKA_WriteSingleInput( 1, opLen);
989 /* Set the op1 */
990 HW_PKA_WriteOperand( 301, 8, op1);
991 /* Set the op2 */
992 HW_PKA_WriteOperand( 401, 8, op2);
993 /* Set the modulus value p */
994 HW_PKA_WriteOperand( 599, 8, p );
995
996 /* Wait for PKA busy flag equal to 0 */
997 while(LL_PKA_IsActiveFlag_BUSY(PKA));
998
999 /* Start the PKA processing */
1000 LL_PKA_Start( PKA );
1001 }
1002 #endif /* STM32WB05 */
1003
1004 /**
1005 * @brief
1006 * @param
1007 * @param
1008 *
1009 */
HW_PKA_P256_ReadEccScalarMul(uint32_t * pX,uint32_t * pY)1010 void HW_PKA_P256_ReadEccScalarMul( uint32_t* pX, uint32_t* pY )
1011 {
1012 #ifdef STM32WB09
1013 /* Read the output point X */
1014 if( pX )
1015 {
1016 HW_PKA_ReadResult( PKA_ECC_SCALAR_MUL_OUT_RESULT_X, 8, pX );
1017 }
1018 /* Read the output point Y as the second half of the result */
1019 if( pY )
1020 {
1021 HW_PKA_ReadResult( PKA_ECC_SCALAR_MUL_OUT_RESULT_Y, 8, pY );
1022 }
1023 #endif /* STM32WB09 */
1024
1025 #ifdef STM32WB05
1026 /* Read the output point X */
1027 if( pX )
1028 {
1029 HW_PKA_ReadResult( 87, 8, pX );
1030 }
1031 /* Read the output point Y as the second half of the result */
1032 if( pY )
1033 {
1034 HW_PKA_ReadResult( 108, 8, pY );
1035 }
1036 #endif /* STM32WB05 */
1037 }
1038
1039 /**
1040 * Brief This function checks if the param p is equal to the Start Point.
1041 * Param Publick key p
1042 * Retval 1 if p is equal to the Start Point. 0 in other cases.
1043 */
HW_PKA_isStartPoint(const uint32_t * p)1044 uint32_t HW_PKA_isStartPoint(const uint32_t* p)
1045 {
1046 for(int i=0; i<16; i++)
1047 {
1048 if(PKAStartPoint[i]!=p[i])
1049 return 0;
1050 }
1051 return 1;
1052 }
1053
1054 /**
1055 * @}
1056 */
1057
1058 #endif /* STM32WB09 STM32WB05 */
1059
1060 #if defined(STM32WB06) || defined(STM32WB07)
1061
1062 /**
1063 * @brief PKA verification of process command.
1064 * @param None
1065 * @retval ErrorStatus
1066 */
HW_PKA_VerifyProcess(void)1067 ErrorStatus HW_PKA_VerifyProcess(void)
1068 {
1069 uint32_t errorCode;
1070
1071 if(PKA_SetDataError != 0x00)
1072 return ERROR;
1073
1074 errorCode = *(uint32_t *)(HW_PKA_RAM_ECC_ADDR_KP_ERROR);
1075
1076 if (errorCode == 0) {
1077 return SUCCESS;
1078 }
1079 else {
1080 return ERROR;
1081 }
1082 }
1083
1084 /**
1085 * Brief This function handles PKA Instance interrupt request.
1086 * Param None
1087 * Retval None
1088 */
HW_PKA_IRQHandler(void)1089 void HW_PKA_IRQHandler(void)
1090 {
1091 /* Compare to expected results */
1092 if (HW_PKA_VerifyProcess() == ERROR)
1093 {
1094 PKAMGR_Unlock();
1095 ret[0] = 0x03;
1096 HW_PKA_funcCB_LP(PKAMGR_ERR_PROCESS, ret);
1097 }
1098 else
1099 {
1100 for(int i=0; i<24; i++)
1101 ret[i] = 0;
1102 /* | Secret Key | Public Key X-coord | Public Key Y-coord | */
1103 /* | (32 octets) | (32 octets) | (32 octets) | */
1104 /* Get the new calculated point NewPoint of the ellipse */
1105 HW_PKA_GetData(HW_PKA_DATA_SK, (uint8_t *)&ret[0]);
1106 HW_PKA_GetData(HW_PKA_DATA_PCX, (uint8_t *)&ret[8]);
1107 HW_PKA_GetData(HW_PKA_DATA_PCY, (uint8_t *)&ret[16]);
1108
1109 PKAMGR_Unlock();
1110 HW_PKA_funcCB_LP(PKAMGR_SUCCESS, ret);
1111 }
1112 }
1113
1114 #endif /* STM32WB06 STM32WB07 */
1115
1116 /**
1117 * @}
1118 */
1119