1 /*
2  * Copyright (c) 2001-2022, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include "mbedtls/build_info.h"
8 #include "mbedtls/ecdh.h"
9 
10 #include "cc_ecc_internal.h"
11 
12 
13 const mbedtls_ecp_curve_info curve_25519_data = { MBEDTLS_ECP_DP_CURVE25519,   29,     255,     "curve25519"};
14 
15 #if defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
16 /*
17  * Generate key pair, wrapper for conventional base point
18  */
cc_ecp_gen_keypair(mbedtls_ecp_group * grp,mbedtls_mpi * d,mbedtls_ecp_point * Q,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)19 int cc_ecp_gen_keypair( mbedtls_ecp_group *grp,
20                              mbedtls_mpi *d, mbedtls_ecp_point *Q,
21                              int (*f_rng)(void *, unsigned char *, size_t),
22                              void *p_rng )
23 {
24     return( cc_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) );
25 }
26 
27 /*
28  * Generate public key: simple wrapper around mbedtls_ecp_gen_keypair
29  */
mbedtls_ecdh_gen_public(mbedtls_ecp_group * grp,mbedtls_mpi * d,mbedtls_ecp_point * Q,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)30 int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
31                      int (*f_rng)(void *, unsigned char *, size_t),
32                      void *p_rng )
33 {
34     return cc_ecp_gen_keypair( grp, d, Q, f_rng, p_rng );
35 }
36 #endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */
37 
38 #if defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
39 /*
40  * Compute shared secret (SEC1 3.3.1)
41  */
mbedtls_ecdh_compute_shared(mbedtls_ecp_group * grp,mbedtls_mpi * z,const mbedtls_ecp_point * Q,const mbedtls_mpi * d,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)42 int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z,
43                          const mbedtls_ecp_point *Q, const mbedtls_mpi *d,
44                          int (*f_rng)(void *, unsigned char *, size_t),
45                          void *p_rng )
46 {
47     int ret;
48     mbedtls_ecp_point P;
49 
50     mbedtls_ecp_point_init( &P );
51 
52     if ( z == NULL || Q == NULL || grp == NULL || d == NULL)
53     {
54         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
55         goto cleanup;
56     }
57     /*
58      * Make sure Q is a valid pubkey before using it
59      */
60     MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) );
61 
62     MBEDTLS_MPI_CHK( cc_ecp_mul( grp, &P, d, Q, f_rng, p_rng ) );
63 
64     if( mbedtls_ecp_is_zero( &P ) )
65     {
66         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
67         goto cleanup;
68     }
69 
70     MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.MBEDTLS_PRIVATE(X) ) );
71 
72 cleanup:
73     mbedtls_ecp_point_free( &P );
74 
75     return( ret );
76 }
77 #endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
78 
79 /*
80  * Write the ECParameters record corresponding to a group (RFC 4492)
81  */
mbedtls_ecp_tls_write_group_edwards(const mbedtls_ecp_group * grp,size_t * olen,unsigned char * buf,size_t blen)82 static int mbedtls_ecp_tls_write_group_edwards( const mbedtls_ecp_group *grp, size_t *olen,
83                          unsigned char *buf, size_t blen )
84 {
85     const mbedtls_ecp_curve_info *curve_info = &curve_25519_data;
86 
87     if (grp->id != MBEDTLS_ECP_DP_CURVE25519){
88             return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
89     }
90     /*
91      * We are going to write 3 bytes (see below)
92      */
93     *olen = 3;
94     if( blen < *olen )
95         return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL );
96 
97     /*
98      * First byte is curve_type, always named_curve
99      */
100     *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE;
101 
102     /*
103      * Next two bytes are the namedcurve value
104      */
105     buf[0] = curve_info->tls_id >> 8;
106     buf[1] = curve_info->tls_id & 0xFF;
107 
108     return( 0 );
109 }
110 
111 /*
112  * Setup and write the ServerKeyExhange parameters (RFC 4492)
113  *      struct {
114  *          ECParameters    curve_params;
115  *          ECPoint         public;
116  *      } ServerECDHParams;
117  */
mbedtls_ecdh_make_params_edwards(mbedtls_ecdh_context * ctx,size_t * olen,unsigned char * buf,size_t blen,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)118 int mbedtls_ecdh_make_params_edwards( mbedtls_ecdh_context *ctx, size_t *olen,
119                       unsigned char *buf, size_t blen,
120                       int (*f_rng)(void *, unsigned char *, size_t),
121                       void *p_rng )
122 {
123     int ret;
124     size_t grp_len, pt_len;
125 
126     if( ctx == NULL || ctx->MBEDTLS_PRIVATE(ctx).MBEDTLS_PRIVATE(mbed_ecdh).MBEDTLS_PRIVATE(grp).pbits == 0 ||
127             olen == NULL || buf == NULL ||
128             blen <= 0 || (ctx->MBEDTLS_PRIVATE(ctx).MBEDTLS_PRIVATE(mbed_ecdh).MBEDTLS_PRIVATE(grp).id != MBEDTLS_ECP_DP_CURVE25519) ){
129         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
130     }
131 
132     if( ( ret = mbedtls_ecdh_gen_public( &ctx->MBEDTLS_PRIVATE(ctx).MBEDTLS_PRIVATE(mbed_ecdh).MBEDTLS_PRIVATE(grp), &ctx->MBEDTLS_PRIVATE(ctx).MBEDTLS_PRIVATE(mbed_ecdh).MBEDTLS_PRIVATE(d), &ctx->MBEDTLS_PRIVATE(ctx).MBEDTLS_PRIVATE(mbed_ecdh).MBEDTLS_PRIVATE(Q), f_rng, p_rng ) )
133                 != 0 )
134         return( ret );
135 
136     if( ( ret = mbedtls_ecp_tls_write_group_edwards( &ctx->MBEDTLS_PRIVATE(ctx).MBEDTLS_PRIVATE(mbed_ecdh).MBEDTLS_PRIVATE(grp), &grp_len, buf, blen ) )
137                 != 0 )
138         return( ret );
139 
140     buf += grp_len;
141     blen -= grp_len;
142 
143     if( ( ret = mbedtls_ecp_tls_write_point( &ctx->MBEDTLS_PRIVATE(ctx).MBEDTLS_PRIVATE(mbed_ecdh).MBEDTLS_PRIVATE(grp), &ctx->MBEDTLS_PRIVATE(ctx).MBEDTLS_PRIVATE(mbed_ecdh).MBEDTLS_PRIVATE(Q), ctx->MBEDTLS_PRIVATE(point_format),
144                                      &pt_len, buf, blen ) ) != 0 )
145         return( ret );
146 
147     *olen = grp_len + pt_len;
148     return( 0 );
149 }
150 
151 /*
152  * Set a group from an ECParameters record (RFC 4492)
153  */
mbedtls_ecp_tls_read_group_edwards(mbedtls_ecp_group * grp,const unsigned char ** buf,size_t len)154 static int mbedtls_ecp_tls_read_group_edwards( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len )
155 {
156     uint16_t tls_id;
157     const mbedtls_ecp_curve_info *curve_info = &curve_25519_data;
158 
159     /*
160      * We expect at least three bytes (see below)
161      */
162     if( len < 3 )
163         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
164 
165     /*
166      * First byte is curve_type; only named_curve is handled
167      */
168     if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE )
169         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
170 
171     /*
172      * Next two bytes are the namedcurve value
173      */
174     tls_id = *(*buf)++;
175     tls_id <<= 8;
176     tls_id |= *(*buf)++;
177 
178     if (curve_info->tls_id != tls_id){
179             return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
180     }
181     return mbedtls_ecp_group_load( grp, curve_info->grp_id );
182 }
183 
184 /*
185  * Read the ServerKeyExhange parameters (RFC 4492)
186  *      struct {
187  *          ECParameters    curve_params;
188  *          ECPoint         public;
189  *      } ServerECDHParams;
190  */
mbedtls_ecdh_read_params_edwards(mbedtls_ecdh_context * ctx,const unsigned char ** buf,const unsigned char * end)191 int mbedtls_ecdh_read_params_edwards( mbedtls_ecdh_context *ctx,
192                       const unsigned char **buf, const unsigned char *end )
193 {
194     int ret;
195 
196     if( ctx == NULL || buf == NULL || end == NULL){
197         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
198     }
199     if( ( ret = mbedtls_ecp_tls_read_group_edwards( &ctx->MBEDTLS_PRIVATE(ctx).MBEDTLS_PRIVATE(mbed_ecdh).MBEDTLS_PRIVATE(grp), buf, end - *buf ) ) != 0 )
200         return( ret );
201 
202     if( ( ret = mbedtls_ecp_tls_read_point( &ctx->MBEDTLS_PRIVATE(ctx).MBEDTLS_PRIVATE(mbed_ecdh).MBEDTLS_PRIVATE(grp), &ctx->MBEDTLS_PRIVATE(ctx).MBEDTLS_PRIVATE(mbed_ecdh).MBEDTLS_PRIVATE(Qp), buf, end - *buf ) )
203                 != 0 ){
204             return( ret );
205     }
206 
207     return( 0 );
208 }
209