1 /*
2  * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <string.h>
8 #include "soc/hwcrypto_periph.h"
9 #include "ecc_impl.h"
10 
11 #include "mbedtls/ecp.h"
12 #include "mbedtls/platform_util.h"
13 
14 #if defined(MBEDTLS_ECP_MUL_ALT) || defined(MBEDTLS_ECP_MUL_ALT_SOFT_FALLBACK)
15 
16 #define MAX_SIZE            32     // 256 bits
17 
esp_mbedtls_ecp_point_multiply(const mbedtls_ecp_group * grp,mbedtls_ecp_point * R,const mbedtls_mpi * m,const mbedtls_ecp_point * P)18 static int esp_mbedtls_ecp_point_multiply(const mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
19         const mbedtls_mpi *m, const mbedtls_ecp_point *P)
20 {
21     int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
22     uint8_t x_tmp[MAX_SIZE] = {0};
23     uint8_t y_tmp[MAX_SIZE] = {0};
24 
25     uint8_t m_le[MAX_SIZE] = {0};
26     ecc_point_t p_pt = {0};
27     ecc_point_t r_pt = {0};
28 
29     p_pt.len = grp->pbits / 8;
30 
31     MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary_le(&P->MBEDTLS_PRIVATE(X), p_pt.x, MAX_SIZE));
32     MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary_le(&P->MBEDTLS_PRIVATE(Y), p_pt.y, MAX_SIZE));
33     MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary_le(m, m_le, MAX_SIZE));
34 
35     ret = esp_ecc_point_multiply(&p_pt, m_le, &r_pt, false);
36 
37     for (int i = 0; i < MAX_SIZE; i++) {
38         x_tmp[MAX_SIZE - i - 1] = r_pt.x[i];
39         y_tmp[MAX_SIZE - i - 1] = r_pt.y[i];
40     }
41 
42     MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&R->MBEDTLS_PRIVATE(X), x_tmp, MAX_SIZE));
43     MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&R->MBEDTLS_PRIVATE(Y), y_tmp, MAX_SIZE));
44     MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&R->MBEDTLS_PRIVATE(Z), 1));
45     return ret;
46 
47 cleanup:
48     return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
49 }
50 
ecp_mul_restartable_internal(mbedtls_ecp_group * grp,mbedtls_ecp_point * R,const mbedtls_mpi * m,const mbedtls_ecp_point * P,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng,mbedtls_ecp_restart_ctx * rs_ctx)51 int ecp_mul_restartable_internal( mbedtls_ecp_group *grp, mbedtls_ecp_point *R,
52              const mbedtls_mpi *m, const mbedtls_ecp_point *P,
53              int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
54              mbedtls_ecp_restart_ctx *rs_ctx )
55 {
56     int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
57     if (grp->id != MBEDTLS_ECP_DP_SECP192R1 && grp->id != MBEDTLS_ECP_DP_SECP256R1) {
58 #if defined(MBEDTLS_ECP_MUL_ALT_SOFT_FALLBACK)
59         return ecp_mul_restartable_internal_soft(grp, R, m, P, f_rng, p_rng, rs_ctx);
60 #else
61         return ret;
62 #endif
63     }
64 
65     /* Common sanity checks to conform with mbedTLS return values */
66     MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey(grp, m) );
67     MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey(grp, P) );
68 
69     MBEDTLS_MPI_CHK( esp_mbedtls_ecp_point_multiply(grp, R, m, P) );
70 cleanup:
71     return( ret );
72 }
73 
74 #endif /* defined(MBEDTLS_ECP_MUL_ALT) || defined(MBEDTLS_ECP_MUL_ALT_SOFT_FALLBACK) */
75 
76 #if defined(MBEDTLS_ECP_VERIFY_ALT) || defined(MBEDTLS_ECP_VERIFY_ALT_SOFT_FALLBACK)
77 
mbedtls_ecp_check_pubkey(const mbedtls_ecp_group * grp,const mbedtls_ecp_point * pt)78 int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp,
79                               const mbedtls_ecp_point *pt )
80 {
81     int res;
82     ecc_point_t point;
83 
84     if (grp->id != MBEDTLS_ECP_DP_SECP192R1 && grp->id != MBEDTLS_ECP_DP_SECP256R1) {
85 #if defined(MBEDTLS_ECP_VERIFY_ALT_SOFT_FALLBACK)
86         return mbedtls_ecp_check_pubkey_soft(grp, pt);
87 #else
88         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
89 #endif
90     }
91 
92     if (grp == NULL || pt == NULL) {
93         return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
94     }
95 
96     /* Must use affine coordinates */
97     if( mbedtls_mpi_cmp_int( &pt->MBEDTLS_PRIVATE(Z), 1 ) != 0 )
98         return( MBEDTLS_ERR_ECP_INVALID_KEY );
99 
100     mbedtls_platform_zeroize((void *)&point, sizeof(ecc_point_t));
101 
102     memcpy(&point.x, pt->MBEDTLS_PRIVATE(X).MBEDTLS_PRIVATE(p), mbedtls_mpi_size(&pt->MBEDTLS_PRIVATE(X)));
103     memcpy(&point.y, pt->MBEDTLS_PRIVATE(Y).MBEDTLS_PRIVATE(p), mbedtls_mpi_size(&pt->MBEDTLS_PRIVATE(Y)));
104 
105     point.len = grp->pbits / 8;
106 
107     res = esp_ecc_point_verify(&point);
108     if (res == 1) {
109         return 0;
110     } else {
111         return MBEDTLS_ERR_ECP_INVALID_KEY;
112     }
113 }
114 #endif /* defined(MBEDTLS_ECP_VERIFY_ALT) || defined(MBEDTLS_ECP_VERIFY_ALT_SOFT_FALLBACK) */
115