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