2 * Elliptic curve Diffie-Hellman
4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 * SPDX-License-Identifier: GPL-2.0
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 * This file is part of mbed TLS (https://tls.mbed.org)
27 * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
31 #if !defined(MBEDTLS_CONFIG_FILE)
32 #include "mbedtls/config.h"
34 #include MBEDTLS_CONFIG_FILE
37 #if defined(MBEDTLS_ECDH_C)
39 #include "mbedtls/ecdh.h"
43 #if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT)
45 * Generate public key: simple wrapper around mbedtls_ecp_gen_keypair
47 int mbedtls_ecdh_gen_public( mbedtls_ecp_group
*grp
, mbedtls_mpi
*d
, mbedtls_ecp_point
*Q
,
48 int (*f_rng
)(void *, unsigned char *, size_t),
51 return mbedtls_ecp_gen_keypair( grp
, d
, Q
, f_rng
, p_rng
);
53 #endif /* MBEDTLS_ECDH_GEN_PUBLIC_ALT */
55 #if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT)
57 * Compute shared secret (SEC1 3.3.1)
59 int mbedtls_ecdh_compute_shared( mbedtls_ecp_group
*grp
, mbedtls_mpi
*z
,
60 const mbedtls_ecp_point
*Q
, const mbedtls_mpi
*d
,
61 int (*f_rng
)(void *, unsigned char *, size_t),
67 mbedtls_ecp_point_init( &P
);
70 * Make sure Q is a valid pubkey before using it
72 MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp
, Q
) );
74 MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp
, &P
, d
, Q
, f_rng
, p_rng
) );
76 if( mbedtls_ecp_is_zero( &P
) )
78 ret
= MBEDTLS_ERR_ECP_BAD_INPUT_DATA
;
82 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z
, &P
.X
) );
85 mbedtls_ecp_point_free( &P
);
89 #endif /* MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
94 void mbedtls_ecdh_init( mbedtls_ecdh_context
*ctx
)
96 memset( ctx
, 0, sizeof( mbedtls_ecdh_context
) );
102 void mbedtls_ecdh_free( mbedtls_ecdh_context
*ctx
)
107 mbedtls_ecp_group_free( &ctx
->grp
);
108 mbedtls_ecp_point_free( &ctx
->Q
);
109 mbedtls_ecp_point_free( &ctx
->Qp
);
110 mbedtls_ecp_point_free( &ctx
->Vi
);
111 mbedtls_ecp_point_free( &ctx
->Vf
);
112 mbedtls_mpi_free( &ctx
->d
);
113 mbedtls_mpi_free( &ctx
->z
);
114 mbedtls_mpi_free( &ctx
->_d
);
118 * Setup and write the ServerKeyExhange parameters (RFC 4492)
120 * ECParameters curve_params;
122 * } ServerECDHParams;
124 int mbedtls_ecdh_make_params( mbedtls_ecdh_context
*ctx
, size_t *olen
,
125 unsigned char *buf
, size_t blen
,
126 int (*f_rng
)(void *, unsigned char *, size_t),
130 size_t grp_len
, pt_len
;
132 if( ctx
== NULL
|| ctx
->grp
.pbits
== 0 )
133 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA
);
135 if( ( ret
= mbedtls_ecdh_gen_public( &ctx
->grp
, &ctx
->d
, &ctx
->Q
, f_rng
, p_rng
) )
139 if( ( ret
= mbedtls_ecp_tls_write_group( &ctx
->grp
, &grp_len
, buf
, blen
) )
146 if( ( ret
= mbedtls_ecp_tls_write_point( &ctx
->grp
, &ctx
->Q
, ctx
->point_format
,
147 &pt_len
, buf
, blen
) ) != 0 )
150 *olen
= grp_len
+ pt_len
;
155 * Read the ServerKeyExhange parameters (RFC 4492)
157 * ECParameters curve_params;
159 * } ServerECDHParams;
161 int mbedtls_ecdh_read_params( mbedtls_ecdh_context
*ctx
,
162 const unsigned char **buf
, const unsigned char *end
)
166 if( ( ret
= mbedtls_ecp_tls_read_group( &ctx
->grp
, buf
, end
- *buf
) ) != 0 )
169 if( ( ret
= mbedtls_ecp_tls_read_point( &ctx
->grp
, &ctx
->Qp
, buf
, end
- *buf
) )
177 * Get parameters from a keypair
179 int mbedtls_ecdh_get_params( mbedtls_ecdh_context
*ctx
, const mbedtls_ecp_keypair
*key
,
180 mbedtls_ecdh_side side
)
184 if( ctx
->grp
.id
== MBEDTLS_ECP_DP_NONE
)
186 /* This is the first call to get_params(). Copy the group information
187 * into the context. */
188 if( ( ret
= mbedtls_ecp_group_copy( &ctx
->grp
, &key
->grp
) ) != 0 )
193 /* This is not the first call to get_params(). Check that the group
194 * is the same as the first time. */
195 if( ctx
->grp
.id
!= key
->grp
.id
)
196 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA
);
199 /* If it's not our key, just import the public part as Qp */
200 if( side
== MBEDTLS_ECDH_THEIRS
)
201 return( mbedtls_ecp_copy( &ctx
->Qp
, &key
->Q
) );
203 /* Our key: import public (as Q) and private parts */
204 if( side
!= MBEDTLS_ECDH_OURS
)
205 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA
);
207 if( ( ret
= mbedtls_ecp_copy( &ctx
->Q
, &key
->Q
) ) != 0 ||
208 ( ret
= mbedtls_mpi_copy( &ctx
->d
, &key
->d
) ) != 0 )
215 * Setup and export the client public value
217 int mbedtls_ecdh_make_public( mbedtls_ecdh_context
*ctx
, size_t *olen
,
218 unsigned char *buf
, size_t blen
,
219 int (*f_rng
)(void *, unsigned char *, size_t),
224 if( ctx
== NULL
|| ctx
->grp
.pbits
== 0 )
225 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA
);
227 if( ( ret
= mbedtls_ecdh_gen_public( &ctx
->grp
, &ctx
->d
, &ctx
->Q
, f_rng
, p_rng
) )
231 return mbedtls_ecp_tls_write_point( &ctx
->grp
, &ctx
->Q
, ctx
->point_format
,
236 * Parse and import the client's public value
238 int mbedtls_ecdh_read_public( mbedtls_ecdh_context
*ctx
,
239 const unsigned char *buf
, size_t blen
)
242 const unsigned char *p
= buf
;
245 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA
);
247 if( ( ret
= mbedtls_ecp_tls_read_point( &ctx
->grp
, &ctx
->Qp
, &p
, blen
) ) != 0 )
250 if( (size_t)( p
- buf
) != blen
)
251 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA
);
257 * Derive and export the shared secret
259 int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context
*ctx
, size_t *olen
,
260 unsigned char *buf
, size_t blen
,
261 int (*f_rng
)(void *, unsigned char *, size_t),
267 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA
);
269 if( ( ret
= mbedtls_ecdh_compute_shared( &ctx
->grp
, &ctx
->z
, &ctx
->Qp
, &ctx
->d
,
270 f_rng
, p_rng
) ) != 0 )
275 if( mbedtls_mpi_size( &ctx
->z
) > blen
)
276 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA
);
278 *olen
= ctx
->grp
.pbits
/ 8 + ( ( ctx
->grp
.pbits
% 8 ) != 0 );
279 return mbedtls_mpi_write_binary( &ctx
->z
, buf
, *olen
);
282 #endif /* MBEDTLS_ECDH_C */