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