1 /*
2 * Elliptic curve DSA sign and verify functions
3 *
4 * Copyright (C) 2006-2021, ARM Limited, All Rights Reserved
5 * Copyright (C) 2019, STMicroelectronics, All Rights Reserved
6 * SPDX-License-Identifier: Apache-2.0
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License"); you may
9 * not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 * This file implements ST ECDSA sign and verify HW services based on mbed TLS API
21 */
22
23 /* Includes ------------------------------------------------------------------*/
24 #include "mbedtls/ecdsa.h"
25
26 #if defined(MBEDTLS_ECDSA_C)
27 #include "mbedtls/platform.h"
28 #include "mbedtls/platform_util.h"
29 #include "mbedtls/error.h"
30 #include "stm32hal.h"
31
32 /* Private typedef -----------------------------------------------------------*/
33 /* Private define ------------------------------------------------------------*/
34 #define ST_ECDSA_TIMEOUT (5000U)
35
36 /* Private macro -------------------------------------------------------------*/
37 /* Parameter validation macros - mbedtls/platform_util.h has deprecated them */
38 #define ECDSA_VALIDATE_RET( cond ) do { } while(0)
39 #define ECDSA_VALIDATE( cond ) do { } while(0)
40
41 /* Private variables ---------------------------------------------------------*/
42 /* Private function prototypes -----------------------------------------------*/
43 /* Private functions ---------------------------------------------------------*/
44
45 #if defined(MBEDTLS_ECDSA_SIGN_ALT)
46
47 #if !defined(MBEDTLS_ECP_ALT)
48 #error "MBEDTLS_ECP_ALT must be defined, if MBEDTLS_ECDSA_SIGN_ALT is"
49 #endif
50
51 /*
52 * Compute ECDSA signature of a hashed message
53 */
mbedtls_ecdsa_sign(mbedtls_ecp_group * grp,mbedtls_mpi * r,mbedtls_mpi * s,const mbedtls_mpi * d,const unsigned char * buf,size_t blen,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)54 int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
55 const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
56 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
57 {
58 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
59 uint8_t *d_binary;
60 uint8_t *k_binary = NULL;
61
62 mbedtls_mpi k;
63 PKA_HandleTypeDef hpka = {0};
64 PKA_ECDSASignInTypeDef ECDSA_SignIn = {0};
65 PKA_ECDSASignOutTypeDef ECDSA_SignOut;
66
67 ECDSA_VALIDATE_RET( grp != NULL );
68 ECDSA_VALIDATE_RET( r != NULL );
69 ECDSA_VALIDATE_RET( s != NULL );
70 ECDSA_VALIDATE_RET( d != NULL );
71 ECDSA_VALIDATE_RET( f_rng != NULL );
72 ECDSA_VALIDATE_RET( buf != NULL || blen == 0 );
73
74 /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
75 if( ! mbedtls_ecdsa_can_do( grp->id ) || grp->G.MBEDTLS_PRIVATE(Y).MBEDTLS_PRIVATE(p) == NULL )
76 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
77
78 /* Make sure d is in range 1..n-1 */
79 if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 )
80 return ( MBEDTLS_ERR_ECP_INVALID_KEY);
81
82 /* Set HW peripheral Input parameter: curve coefs */
83 ECDSA_SignIn.primeOrderSize = grp->st_order_size;
84 ECDSA_SignIn.modulusSize = grp->st_modulus_size;
85 ECDSA_SignIn.modulus = grp->st_p;
86 ECDSA_SignIn.coefSign = grp->st_a_sign;
87 ECDSA_SignIn.coef = grp->st_a_abs;
88 #if defined(GENERATOR_HW_PKA_EXTENDED_API)
89 ECDSA_SignIn.coefB = grp->st_b;
90 #endif
91 ECDSA_SignIn.basePointX = grp->st_gx;
92 ECDSA_SignIn.basePointY = grp->st_gy;
93 ECDSA_SignIn.primeOrder = grp->st_n;
94
95 /* Set HW peripheral input parameter: hash content buffer to be signed */
96 ECDSA_SignIn.hash = buf;
97
98 /* Set HW peripheral input parameter: private signing key */
99 d_binary = mbedtls_calloc(grp->st_order_size, sizeof( uint8_t ));
100 MBEDTLS_MPI_CHK((d_binary == NULL) ? MBEDTLS_ERR_ECP_ALLOC_FAILED : 0);
101
102 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, d_binary, grp->st_order_size ) );
103
104 ECDSA_SignIn.privateKey = d_binary;
105
106 /* Set HW peripheral input parameter: random integer */
107 mbedtls_mpi_init( &k );
108
109 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &k, f_rng, p_rng ) );
110
111 k_binary = mbedtls_calloc(grp->st_order_size, sizeof( uint8_t ));
112 MBEDTLS_MPI_CHK((k_binary == NULL) ? MBEDTLS_ERR_ECP_ALLOC_FAILED : 0);
113
114 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &k, k_binary, grp->st_order_size ) );
115
116 ECDSA_SignIn.integer = k_binary;
117
118 /* Enable HW peripheral clock */
119 __HAL_RCC_PKA_CLK_ENABLE();
120
121 /* Initialize HW peripheral */
122 hpka.Instance = PKA;
123 MBEDTLS_MPI_CHK((HAL_PKA_Init(&hpka) != HAL_OK) ? MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED : 0);
124
125 HAL_PKA_RAMReset(&hpka);
126
127 /* Launch the signature */
128 MBEDTLS_MPI_CHK((HAL_PKA_ECDSASign(&hpka, &ECDSA_SignIn, ST_ECDSA_TIMEOUT) != HAL_OK) ? MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED : 0);
129
130 /* Allocate memory space for signature */
131 ECDSA_SignOut.RSign = mbedtls_calloc(grp->st_order_size, sizeof( uint8_t ));
132 MBEDTLS_MPI_CHK((ECDSA_SignOut.RSign == NULL) ? MBEDTLS_ERR_ECP_ALLOC_FAILED : 0);
133
134 ECDSA_SignOut.SSign = mbedtls_calloc(grp->st_order_size, sizeof( uint8_t ));
135 MBEDTLS_MPI_CHK((ECDSA_SignOut.SSign == NULL) ? MBEDTLS_ERR_ECP_ALLOC_FAILED : 0);
136
137 /* Get the signature into allocated space */
138 HAL_PKA_ECDSASign_GetResult(&hpka, &ECDSA_SignOut, NULL);
139
140 /* Convert the signature into mpi format */
141 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( r, ECDSA_SignOut.RSign, grp->st_order_size ) );
142
143 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( s, ECDSA_SignOut.SSign, grp->st_order_size ) );
144
145 cleanup:
146 /* De-initialize HW peripheral */
147 HAL_PKA_DeInit(&hpka);
148
149 /* Disable HW peripheral clock */
150 __HAL_RCC_PKA_CLK_DISABLE();
151
152 /* Free memory */
153 mbedtls_mpi_free( &k );
154
155 if (d_binary != NULL)
156 {
157 mbedtls_platform_zeroize(d_binary, grp->st_order_size);
158 mbedtls_free(d_binary);
159 }
160
161 if (k_binary != NULL)
162 {
163 mbedtls_platform_zeroize(k_binary, grp->st_order_size);
164 mbedtls_free(k_binary);
165 }
166
167 if (ECDSA_SignOut.RSign != NULL)
168 {
169 mbedtls_platform_zeroize(ECDSA_SignOut.RSign, grp->st_order_size);
170 mbedtls_free(ECDSA_SignOut.RSign);
171 }
172
173 if (ECDSA_SignOut.SSign != NULL)
174 {
175 mbedtls_platform_zeroize(ECDSA_SignOut.SSign, grp->st_order_size);
176 mbedtls_free(ECDSA_SignOut.SSign);
177 }
178
179 return ret;
180 }
181 #endif /* MBEDTLS_ECDSA_SIGN_ALT*/
182
183 #if defined(MBEDTLS_ECDSA_VERIFY_ALT)
184
185 #if !defined(MBEDTLS_ECP_ALT)
186 #error "MBEDTLS_ECP_ALT must be defined, if MBEDTLS_ECDSA_VERIFY_ALT is"
187 #endif
188
189
190 /*
191 * Verify ECDSA signature of hashed message
192 */
mbedtls_ecdsa_verify(mbedtls_ecp_group * grp,const unsigned char * buf,size_t blen,const mbedtls_ecp_point * Q,const mbedtls_mpi * r,const mbedtls_mpi * s)193 int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
194 const unsigned char *buf, size_t blen,
195 const mbedtls_ecp_point *Q,
196 const mbedtls_mpi *r,
197 const mbedtls_mpi *s)
198 {
199 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
200 size_t olen;
201 uint8_t *Q_binary;
202 uint8_t *r_binary = NULL;
203 uint8_t *s_binary = NULL;
204 PKA_HandleTypeDef hpka = {0};
205 PKA_ECDSAVerifInTypeDef ECDSA_VerifyIn;
206
207 /* Check parameters */
208 ECDSA_VALIDATE_RET( grp != NULL );
209 ECDSA_VALIDATE_RET( Q != NULL );
210 ECDSA_VALIDATE_RET( r != NULL );
211 ECDSA_VALIDATE_RET( s != NULL );
212 ECDSA_VALIDATE_RET( buf != NULL || blen == 0 );
213
214 /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
215 if( grp->G.MBEDTLS_PRIVATE(Y).MBEDTLS_PRIVATE(p) == NULL )
216 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
217
218 /* Make sure r and s are in range 1..n-1 */
219 if( mbedtls_mpi_cmp_int( r, 1 ) < 0 || mbedtls_mpi_cmp_mpi( r, &grp->N ) >= 0 ||
220 mbedtls_mpi_cmp_int( s, 1 ) < 0 || mbedtls_mpi_cmp_mpi( s, &grp->N ) >= 0 )
221 return( MBEDTLS_ERR_ECP_VERIFY_FAILED );
222
223 /* Set HW peripheral Input parameter: curve coefs */
224 ECDSA_VerifyIn.primeOrderSize = grp->st_order_size;
225 ECDSA_VerifyIn.modulusSize = grp->st_modulus_size;
226 ECDSA_VerifyIn.modulus = grp->st_p;
227 ECDSA_VerifyIn.coefSign = grp->st_a_sign;
228 ECDSA_VerifyIn.coef = grp->st_a_abs;
229 ECDSA_VerifyIn.basePointX = grp->st_gx;
230 ECDSA_VerifyIn.basePointY = grp->st_gy;
231 ECDSA_VerifyIn.primeOrder = grp->st_n;
232
233 /* Set HW peripheral input parameter: hash content buffer that was signed */
234 ECDSA_VerifyIn.hash = buf;
235
236 /* Set HW peripheral input parameter: public key */
237 Q_binary = mbedtls_calloc( ( 2U * grp->st_modulus_size ) + 1U, sizeof( uint8_t ) );
238 MBEDTLS_MPI_CHK((Q_binary == NULL) ? MBEDTLS_ERR_ECP_ALLOC_FAILED : 0);
239
240 MBEDTLS_MPI_CHK( mbedtls_ecp_point_write_binary( grp, Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &olen, Q_binary, ( 2U * grp->st_modulus_size ) + 1U ) );
241
242 ECDSA_VerifyIn.pPubKeyCurvePtX = Q_binary + 1U;
243 ECDSA_VerifyIn.pPubKeyCurvePtY = Q_binary + grp->st_modulus_size + 1U;
244
245 /* Set HW peripheral input parameter: signature to be verified */
246 r_binary = mbedtls_calloc(grp->st_order_size, sizeof( uint8_t ));
247 MBEDTLS_MPI_CHK((r_binary == NULL) ? MBEDTLS_ERR_ECP_ALLOC_FAILED : 0);
248
249 s_binary = mbedtls_calloc(grp->st_order_size, sizeof( uint8_t ));
250 MBEDTLS_MPI_CHK((s_binary == NULL) ? MBEDTLS_ERR_ECP_ALLOC_FAILED : 0);
251
252 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( r, r_binary, grp->st_order_size ) );
253 ECDSA_VerifyIn.RSign = r_binary;
254
255 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( s, s_binary, grp->st_order_size ) );
256 ECDSA_VerifyIn.SSign = s_binary;
257
258 /* Enable HW peripheral clock */
259 __HAL_RCC_PKA_CLK_ENABLE();
260
261 /* Initialize HW peripheral */
262 hpka.Instance = PKA;
263 MBEDTLS_MPI_CHK((HAL_PKA_Init(&hpka) != HAL_OK) ? MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED : 0);
264
265 HAL_PKA_RAMReset(&hpka);
266
267 /* Launch the signature verification */
268 MBEDTLS_MPI_CHK((HAL_PKA_ECDSAVerif(&hpka, &ECDSA_VerifyIn, ST_ECDSA_TIMEOUT) != HAL_OK) ? MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED : 0);
269
270 /* Check the result */
271 MBEDTLS_MPI_CHK((HAL_PKA_ECDSAVerif_IsValidSignature(&hpka) != 1U) ? MBEDTLS_ERR_ECP_VERIFY_FAILED : 0);
272
273 cleanup:
274 /* De-initialize HW peripheral */
275 HAL_PKA_DeInit(&hpka);
276
277 /* Disable HW peripheral clock */
278 __HAL_RCC_PKA_CLK_DISABLE();
279
280 /* Free memory */
281 if (Q_binary != NULL)
282 {
283 mbedtls_platform_zeroize(Q_binary, ( 2U * grp->st_modulus_size ) + 1U );
284 mbedtls_free(Q_binary);
285 }
286
287 if (r_binary != NULL)
288 {
289 mbedtls_platform_zeroize(r_binary, grp->st_order_size);
290 mbedtls_free(r_binary);
291 }
292
293 if (s_binary != NULL)
294 {
295 mbedtls_platform_zeroize(s_binary, grp->st_order_size);
296 mbedtls_free(s_binary);
297 }
298
299 return ret;
300 }
301
302 #endif /* MBEDTLS_ECDSA_VERIFY_ALT*/
303
304 #endif /* MBEDTLS_ECDSA_C */
305