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