1 /* USER CODE BEGIN Header */
2 /**
3   ******************************************************************************
4   * @file    bpka.c
5   * @author  MCD Application Team
6   * @brief   This file implements the BLE PKA module.
7   ******************************************************************************
8   * @attention
9   *
10   * Copyright (c) 2022 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 #include "app_common.h"
22 #include "bpka.h"
23 
24 /*****************************************************************************/
25 
26 enum
27 {
28   BPKA_IDLE = 0,
29   BPKA_P256_KEY_GEN,
30   BPKA_RANGE_X_CHECK,
31   BPKA_RANGE_Y_CHECK,
32   BPKA_POINT_CHECK,
33   BPKA_DH_KEY_GEN,
34 };
35 
36 /*****************************************************************************/
37 
38 static uint8_t BPKA_state;
39 static uint8_t BPKA_error;
40 static uint32_t BPKA_buffer[24];
41 
42 /*****************************************************************************/
43 
BPKA_Reset(void)44 void BPKA_Reset( void )
45 {
46   /* Disable PKA hardware */
47   HW_PKA_Disable( );
48 
49   BPKA_state = BPKA_IDLE;
50 }
51 
52 /*****************************************************************************/
53 
BPKA_StartP256Key(const uint32_t * local_private_key)54 int BPKA_StartP256Key( const uint32_t* local_private_key )
55 {
56   /* Enable PKA hardware */
57   if ( ! HW_PKA_Enable( ) )
58     return BPKA_BUSY;
59 
60   /* Call the PKA scalar multiplication with the local private key
61      as k and the standard point as starting point,
62      in order to compute the local public key */
63   HW_PKA_P256_StartEccScalarMul( local_private_key, NULL, NULL );
64 
65   BPKA_state = BPKA_P256_KEY_GEN;
66 
67   BPKACB_Process( );
68 
69   return BPKA_OK;
70 }
71 
72 /*****************************************************************************/
73 
BPKA_ReadP256Key(uint32_t * local_public_key)74 void BPKA_ReadP256Key( uint32_t* local_public_key )
75 {
76   /* Get local public key from buffer */
77   memcpy( local_public_key, BPKA_buffer, 64 );
78 }
79 
80 /*****************************************************************************/
81 
BPKA_StartDhKey(const uint32_t * local_private_key,const uint32_t * remote_public_key)82 int BPKA_StartDhKey( const uint32_t* local_private_key,
83                      const uint32_t* remote_public_key )
84 {
85   /* Enable PKA hardware */
86   if ( ! HW_PKA_Enable( ) )
87     return BPKA_BUSY;
88 
89   /* Call the PKA range check operation for public key X coordinate */
90   HW_PKA_P256_StartRangeCheck( remote_public_key );
91 
92   /* Save input data */
93   memcpy( BPKA_buffer, local_private_key, 32 );
94   memcpy( BPKA_buffer + 8, remote_public_key, 64 );
95 
96   BPKA_state = BPKA_RANGE_X_CHECK;
97   BPKA_error = 1;
98 
99   BPKACB_Process( );
100 
101   return BPKA_OK;
102 }
103 
104 /*****************************************************************************/
105 
BPKA_ReadDhKey(uint32_t * dh_key)106 int BPKA_ReadDhKey( uint32_t* dh_key )
107 {
108   if ( BPKA_error )
109     return BPKA_EOF;
110 
111   /* Get DH key from buffer */
112   memcpy( dh_key, BPKA_buffer, 32 );
113 
114   return BPKA_OK;
115 }
116 
117 /*****************************************************************************/
118 
BPKACB_Complete(void)119 __WEAK void BPKACB_Complete( void )
120 {
121 }
122 
BPKACB_Process(void)123 __WEAK void BPKACB_Process( void )
124 {
125 }
126 
127 /*****************************************************************************/
128 
BPKA_Process(void)129 int BPKA_Process( void )
130 {
131   /* This function implements the offline key computation using the PKA
132    */
133   if ( BPKA_state == BPKA_IDLE )
134   {
135     return BPKA_OK;
136   }
137 
138   /* Check if the current operation is finished */
139   if ( ! HW_PKA_EndOfOperation( ) )
140     return BPKA_BUSY;
141 
142   switch ( BPKA_state )
143   {
144   case BPKA_P256_KEY_GEN:
145 
146     /* Read the PKA scalar multiplication result which is the local public
147        key */
148     HW_PKA_P256_ReadEccScalarMul( BPKA_buffer, BPKA_buffer + 8 );
149 
150     break;
151 
152   case BPKA_RANGE_X_CHECK:
153 
154     /* Test result of range check operation for public key X coordinate */
155     if ( ! HW_PKA_P256_IsRangeCheckOk( ) )
156       break;
157 
158     /* Call the PKA range check operation for public key Y coordinate */
159     HW_PKA_P256_StartRangeCheck( BPKA_buffer + 16 );
160 
161     BPKA_state = BPKA_RANGE_Y_CHECK;
162 
163     return BPKA_BUSY;
164 
165   case BPKA_RANGE_Y_CHECK:
166 
167     /* Test result of range check operation for public key Y coordinate */
168     if ( ! HW_PKA_P256_IsRangeCheckOk( ) )
169       break;
170 
171     /* Call the PKA point check operation for remote public key */
172     HW_PKA_P256_StartPointCheck( BPKA_buffer + 8,
173                                  BPKA_buffer + 16 );
174 
175     BPKA_state = BPKA_POINT_CHECK;
176 
177     return BPKA_BUSY;
178 
179   case BPKA_POINT_CHECK:
180 
181     /* Test result of point check operation for remote public key */
182     if ( ! HW_PKA_P256_IsPointCheckOk( ) )
183       break;
184 
185     /* Call the PKA scalar multiplication with the local private key
186        as k and the remote public key as starting point,
187        in order to compute the DH key */
188     HW_PKA_P256_StartEccScalarMul( BPKA_buffer,
189                                    BPKA_buffer + 8,
190                                    BPKA_buffer + 16 );
191 
192     BPKA_state = BPKA_DH_KEY_GEN;
193 
194     return BPKA_BUSY;
195 
196   case BPKA_DH_KEY_GEN:
197 
198     /* Read the PKA scalar multiplication result which is the DH key */
199     HW_PKA_P256_ReadEccScalarMul( BPKA_buffer, NULL );
200 
201     BPKA_error = 0;
202 
203     break;
204   }
205 
206   /* Callback to inform the BLE stack of the completion of PKA operation */
207   BPKACB_Complete( );
208 
209   /* End of process: reset the PKA module */
210   BPKA_Reset( );
211 
212   return BPKA_OK;
213 }
214 
BPKA_BG_Process(void)215 void BPKA_BG_Process( void )
216 {
217   if( BPKA_Process( ) != 0)
218   {
219     BPKACB_Process( );
220   }
221 }
222 
223 /*****************************************************************************/
224