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