blob: 0645ce798ba5a82289eabc06f3dd61d2f768876c [file] [log] [blame]
Paul Bakker33b43f12013-08-20 11:48:36 +02001/* BEGIN_HEADER */
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +00002#include "mbedtls/ecdh.h"
Gilles Peskine390bbd02018-11-07 22:07:58 +01003
4static int load_public_key( int grp_id, const char *point_str,
5 mbedtls_ecp_keypair *ecp )
6{
7 int ok = 0;
Gilles Peskineb46f1bd2019-02-22 11:30:14 +01008 unsigned char point_buf[MBEDTLS_ECP_MAX_PT_LEN];
Gilles Peskine390bbd02018-11-07 22:07:58 +01009 size_t point_len = unhexify( point_buf, point_str );
10
11 TEST_ASSERT( mbedtls_ecp_group_load( &ecp->grp, grp_id ) == 0 );
12 TEST_ASSERT( mbedtls_ecp_point_read_binary( &ecp->grp,
13 &ecp->Q,
14 point_buf,
15 point_len ) == 0 );
16 TEST_ASSERT( mbedtls_ecp_check_pubkey( &ecp->grp,
17 &ecp->Q ) == 0 );
18 ok = 1;
19exit:
20 return( ok );
21}
22
23static int load_private_key( int grp_id, const char *private_key_str,
24 mbedtls_ecp_keypair *ecp,
25 rnd_pseudo_info *rnd_info )
26{
27 int ok = 0;
28 unsigned char private_key_buf[MBEDTLS_ECP_MAX_BYTES];
29 size_t private_key_len = unhexify( private_key_buf, private_key_str );
30
31 TEST_ASSERT( mbedtls_ecp_group_load( &ecp->grp, grp_id ) == 0 );
32 TEST_ASSERT( mbedtls_mpi_read_binary( &ecp->d,
33 private_key_buf,
34 private_key_len ) == 0 );
35 TEST_ASSERT( mbedtls_ecp_check_privkey( &ecp->grp, &ecp->d ) == 0 );
36 /* Calculate the public key from the private key. */
37 TEST_ASSERT( mbedtls_ecp_mul( &ecp->grp, &ecp->Q, &ecp->d,
38 &ecp->grp.G,
39 &rnd_pseudo_rand, rnd_info ) == 0 );
40 ok = 1;
41exit:
42 return( ok );
43}
44
Paul Bakker33b43f12013-08-20 11:48:36 +020045/* END_HEADER */
Manuel Pégourié-Gonnard61ce13b2013-01-26 16:20:32 +010046
Paul Bakker33b43f12013-08-20 11:48:36 +020047/* BEGIN_DEPENDENCIES
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020048 * depends_on:MBEDTLS_ECDH_C
Paul Bakker33b43f12013-08-20 11:48:36 +020049 * END_DEPENDENCIES
50 */
Manuel Pégourié-Gonnard61ce13b2013-01-26 16:20:32 +010051
Paul Bakker33b43f12013-08-20 11:48:36 +020052/* BEGIN_CASE */
53void ecdh_primitive_random( int id )
Manuel Pégourié-Gonnard61ce13b2013-01-26 16:20:32 +010054{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020055 mbedtls_ecp_group grp;
56 mbedtls_ecp_point qA, qB;
57 mbedtls_mpi dA, dB, zA, zB;
Manuel Pégourié-Gonnard61ce13b2013-01-26 16:20:32 +010058 rnd_pseudo_info rnd_info;
59
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020060 mbedtls_ecp_group_init( &grp );
61 mbedtls_ecp_point_init( &qA ); mbedtls_ecp_point_init( &qB );
62 mbedtls_mpi_init( &dA ); mbedtls_mpi_init( &dB );
63 mbedtls_mpi_init( &zA ); mbedtls_mpi_init( &zB );
Manuel Pégourié-Gonnard61ce13b2013-01-26 16:20:32 +010064 memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) );
65
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +020066 TEST_ASSERT( mbedtls_ecp_group_load( &grp, id ) == 0 );
Manuel Pégourié-Gonnard61ce13b2013-01-26 16:20:32 +010067
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020068 TEST_ASSERT( mbedtls_ecdh_gen_public( &grp, &dA, &qA, &rnd_pseudo_rand, &rnd_info )
Manuel Pégourié-Gonnard61ce13b2013-01-26 16:20:32 +010069 == 0 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020070 TEST_ASSERT( mbedtls_ecdh_gen_public( &grp, &dB, &qB, &rnd_pseudo_rand, &rnd_info )
Manuel Pégourié-Gonnard61ce13b2013-01-26 16:20:32 +010071 == 0 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020072 TEST_ASSERT( mbedtls_ecdh_compute_shared( &grp, &zA, &qB, &dA,
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +020073 &rnd_pseudo_rand, &rnd_info ) == 0 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020074 TEST_ASSERT( mbedtls_ecdh_compute_shared( &grp, &zB, &qA, &dB,
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +020075 NULL, NULL ) == 0 );
Manuel Pégourié-Gonnard61ce13b2013-01-26 16:20:32 +010076
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020077 TEST_ASSERT( mbedtls_mpi_cmp_mpi( &zA, &zB ) == 0 );
Manuel Pégourié-Gonnard61ce13b2013-01-26 16:20:32 +010078
Paul Bakkerbd51b262014-07-10 15:26:12 +020079exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020080 mbedtls_ecp_group_free( &grp );
81 mbedtls_ecp_point_free( &qA ); mbedtls_ecp_point_free( &qB );
82 mbedtls_mpi_free( &dA ); mbedtls_mpi_free( &dB );
83 mbedtls_mpi_free( &zA ); mbedtls_mpi_free( &zB );
Manuel Pégourié-Gonnard61ce13b2013-01-26 16:20:32 +010084}
Paul Bakker33b43f12013-08-20 11:48:36 +020085/* END_CASE */
Manuel Pégourié-Gonnard007b7172013-01-27 08:56:21 +010086
Paul Bakker33b43f12013-08-20 11:48:36 +020087/* BEGIN_CASE */
88void ecdh_primitive_testvec( int id, char *dA_str, char *xA_str, char *yA_str,
89 char *dB_str, char *xB_str, char *yB_str,
90 char *z_str )
Manuel Pégourié-Gonnard007b7172013-01-27 08:56:21 +010091{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020092 mbedtls_ecp_group grp;
93 mbedtls_ecp_point qA, qB;
94 mbedtls_mpi dA, dB, zA, zB, check;
95 unsigned char rnd_buf_A[MBEDTLS_ECP_MAX_BYTES];
96 unsigned char rnd_buf_B[MBEDTLS_ECP_MAX_BYTES];
Manuel Pégourié-Gonnard544416a2014-01-23 16:55:18 +010097 rnd_buf_info rnd_info_A, rnd_info_B;
Manuel Pégourié-Gonnard007b7172013-01-27 08:56:21 +010098
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020099 mbedtls_ecp_group_init( &grp );
100 mbedtls_ecp_point_init( &qA ); mbedtls_ecp_point_init( &qB );
101 mbedtls_mpi_init( &dA ); mbedtls_mpi_init( &dB );
102 mbedtls_mpi_init( &zA ); mbedtls_mpi_init( &zB ); mbedtls_mpi_init( &check );
Manuel Pégourié-Gonnard007b7172013-01-27 08:56:21 +0100103
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +0200104 TEST_ASSERT( mbedtls_ecp_group_load( &grp, id ) == 0 );
Manuel Pégourié-Gonnard007b7172013-01-27 08:56:21 +0100105
Manuel Pégourié-Gonnard544416a2014-01-23 16:55:18 +0100106 rnd_info_A.buf = rnd_buf_A;
107 rnd_info_A.length = unhexify( rnd_buf_A, dA_str );
108
109 /* Fix rnd_buf_A by shifting it left if necessary */
110 if( grp.nbits % 8 != 0 )
111 {
112 unsigned char shift = 8 - ( grp.nbits % 8 );
113 size_t i;
114
115 for( i = 0; i < rnd_info_A.length - 1; i++ )
116 rnd_buf_A[i] = rnd_buf_A[i] << shift
117 | rnd_buf_A[i+1] >> ( 8 - shift );
118
119 rnd_buf_A[rnd_info_A.length-1] <<= shift;
120 }
121
122 rnd_info_B.buf = rnd_buf_B;
123 rnd_info_B.length = unhexify( rnd_buf_B, dB_str );
124
125 /* Fix rnd_buf_B by shifting it left if necessary */
126 if( grp.nbits % 8 != 0 )
127 {
128 unsigned char shift = 8 - ( grp.nbits % 8 );
129 size_t i;
130
131 for( i = 0; i < rnd_info_B.length - 1; i++ )
132 rnd_buf_B[i] = rnd_buf_B[i] << shift
133 | rnd_buf_B[i+1] >> ( 8 - shift );
134
135 rnd_buf_B[rnd_info_B.length-1] <<= shift;
136 }
137
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200138 TEST_ASSERT( mbedtls_ecdh_gen_public( &grp, &dA, &qA,
Manuel Pégourié-Gonnard544416a2014-01-23 16:55:18 +0100139 rnd_buffer_rand, &rnd_info_A ) == 0 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200140 TEST_ASSERT( ! mbedtls_ecp_is_zero( &qA ) );
141 TEST_ASSERT( mbedtls_mpi_read_string( &check, 16, xA_str ) == 0 );
142 TEST_ASSERT( mbedtls_mpi_cmp_mpi( &qA.X, &check ) == 0 );
143 TEST_ASSERT( mbedtls_mpi_read_string( &check, 16, yA_str ) == 0 );
144 TEST_ASSERT( mbedtls_mpi_cmp_mpi( &qA.Y, &check ) == 0 );
Manuel Pégourié-Gonnard007b7172013-01-27 08:56:21 +0100145
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200146 TEST_ASSERT( mbedtls_ecdh_gen_public( &grp, &dB, &qB,
Manuel Pégourié-Gonnard544416a2014-01-23 16:55:18 +0100147 rnd_buffer_rand, &rnd_info_B ) == 0 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200148 TEST_ASSERT( ! mbedtls_ecp_is_zero( &qB ) );
149 TEST_ASSERT( mbedtls_mpi_read_string( &check, 16, xB_str ) == 0 );
150 TEST_ASSERT( mbedtls_mpi_cmp_mpi( &qB.X, &check ) == 0 );
151 TEST_ASSERT( mbedtls_mpi_read_string( &check, 16, yB_str ) == 0 );
152 TEST_ASSERT( mbedtls_mpi_cmp_mpi( &qB.Y, &check ) == 0 );
Manuel Pégourié-Gonnard007b7172013-01-27 08:56:21 +0100153
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200154 TEST_ASSERT( mbedtls_mpi_read_string( &check, 16, z_str ) == 0 );
155 TEST_ASSERT( mbedtls_ecdh_compute_shared( &grp, &zA, &qB, &dA, NULL, NULL ) == 0 );
156 TEST_ASSERT( mbedtls_mpi_cmp_mpi( &zA, &check ) == 0 );
157 TEST_ASSERT( mbedtls_ecdh_compute_shared( &grp, &zB, &qA, &dB, NULL, NULL ) == 0 );
158 TEST_ASSERT( mbedtls_mpi_cmp_mpi( &zB, &check ) == 0 );
Manuel Pégourié-Gonnard007b7172013-01-27 08:56:21 +0100159
Paul Bakkerbd51b262014-07-10 15:26:12 +0200160exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200161 mbedtls_ecp_group_free( &grp );
162 mbedtls_ecp_point_free( &qA ); mbedtls_ecp_point_free( &qB );
163 mbedtls_mpi_free( &dA ); mbedtls_mpi_free( &dB );
164 mbedtls_mpi_free( &zA ); mbedtls_mpi_free( &zB ); mbedtls_mpi_free( &check );
Manuel Pégourié-Gonnard007b7172013-01-27 08:56:21 +0100165}
Paul Bakker33b43f12013-08-20 11:48:36 +0200166/* END_CASE */
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100167
Paul Bakker33b43f12013-08-20 11:48:36 +0200168/* BEGIN_CASE */
169void ecdh_exchange( int id )
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100170{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200171 mbedtls_ecdh_context srv, cli;
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100172 unsigned char buf[1000];
173 const unsigned char *vbuf;
174 size_t len;
175 rnd_pseudo_info rnd_info;
176
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200177 mbedtls_ecdh_init( &srv );
178 mbedtls_ecdh_init( &cli );
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100179 memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) );
180
Manuel Pégourié-Gonnarde3a062b2015-05-11 18:46:47 +0200181 TEST_ASSERT( mbedtls_ecp_group_load( &srv.grp, id ) == 0 );
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100182
183 memset( buf, 0x00, sizeof( buf ) ); vbuf = buf;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200184 TEST_ASSERT( mbedtls_ecdh_make_params( &srv, &len, buf, 1000,
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100185 &rnd_pseudo_rand, &rnd_info ) == 0 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200186 TEST_ASSERT( mbedtls_ecdh_read_params( &cli, &vbuf, buf + len ) == 0 );
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100187
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100188 memset( buf, 0x00, sizeof( buf ) );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200189 TEST_ASSERT( mbedtls_ecdh_make_public( &cli, &len, buf, 1000,
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100190 &rnd_pseudo_rand, &rnd_info ) == 0 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200191 TEST_ASSERT( mbedtls_ecdh_read_public( &srv, buf, len ) == 0 );
Manuel Pégourié-Gonnard5cceb412013-02-11 21:51:45 +0100192
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200193 TEST_ASSERT( mbedtls_ecdh_calc_secret( &srv, &len, buf, 1000,
Manuel Pégourié-Gonnarde09d2f82013-09-02 14:29:09 +0200194 &rnd_pseudo_rand, &rnd_info ) == 0 );
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200195 TEST_ASSERT( mbedtls_ecdh_calc_secret( &cli, &len, buf, 1000, NULL, NULL ) == 0 );
196 TEST_ASSERT( mbedtls_mpi_cmp_mpi( &srv.z, &cli.z ) == 0 );
Manuel Pégourié-Gonnard424fda52013-02-11 22:05:42 +0100197
Paul Bakkerbd51b262014-07-10 15:26:12 +0200198exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200199 mbedtls_ecdh_free( &srv );
200 mbedtls_ecdh_free( &cli );
Manuel Pégourié-Gonnard854fbd72013-02-11 20:28:55 +0100201}
Paul Bakker33b43f12013-08-20 11:48:36 +0200202/* END_CASE */
Gilles Peskine390bbd02018-11-07 22:07:58 +0100203
204/* BEGIN_CASE */
205void ecdh_exchange_calc_secret( int grp_id,
206 char *our_private_key,
207 char *their_point,
208 int ours_first,
209 char *expected_str )
210{
211 rnd_pseudo_info rnd_info;
212 unsigned char expected_buf[MBEDTLS_ECP_MAX_BYTES];
213 size_t expected_len;
214 mbedtls_ecp_keypair our_key;
215 mbedtls_ecp_keypair their_key;
216 mbedtls_ecdh_context ecdh;
217 unsigned char shared_secret[MBEDTLS_ECP_MAX_BYTES];
218 size_t shared_secret_length = 0;
219
220 memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) );
221 mbedtls_ecdh_init( &ecdh );
222 mbedtls_ecp_keypair_init( &our_key );
223 mbedtls_ecp_keypair_init( &their_key );
224
225 expected_len = unhexify( expected_buf, expected_str );
226
227 if( ! load_private_key( grp_id, our_private_key, &our_key, &rnd_info ) )
228 goto exit;
229 if( ! load_public_key( grp_id, their_point, &their_key ) )
230 goto exit;
231
232 /* Import the keys to the ECDH calculation. */
233 if( ours_first )
234 {
235 TEST_ASSERT( mbedtls_ecdh_get_params(
236 &ecdh, &our_key, MBEDTLS_ECDH_OURS ) == 0 );
237 TEST_ASSERT( mbedtls_ecdh_get_params(
238 &ecdh, &their_key, MBEDTLS_ECDH_THEIRS ) == 0 );
239 }
240 else
241 {
242 TEST_ASSERT( mbedtls_ecdh_get_params(
243 &ecdh, &their_key, MBEDTLS_ECDH_THEIRS ) == 0 );
244 TEST_ASSERT( mbedtls_ecdh_get_params(
245 &ecdh, &our_key, MBEDTLS_ECDH_OURS ) == 0 );
246 }
247
248 /* Perform the ECDH calculation. */
249 TEST_ASSERT( mbedtls_ecdh_calc_secret(
250 &ecdh,
251 &shared_secret_length,
252 shared_secret, sizeof( shared_secret ),
253 &rnd_pseudo_rand, &rnd_info ) == 0 );
254 TEST_ASSERT( shared_secret_length == expected_len );
255 TEST_ASSERT( memcmp( expected_buf, shared_secret,
256 shared_secret_length ) == 0 );
257
258exit:
259 mbedtls_ecdh_free( &ecdh );
260 mbedtls_ecp_keypair_free( &our_key );
261 mbedtls_ecp_keypair_free( &their_key );
262}
263/* END_CASE */
Gilles Peskine496c9e02018-11-07 22:09:29 +0100264
265/* BEGIN_CASE */
266void ecdh_exchange_get_params_fail( int our_grp_id,
267 char *our_private_key,
268 int their_grp_id,
269 char *their_point,
270 int ours_first,
271 int expected_ret )
272{
273 rnd_pseudo_info rnd_info;
274 mbedtls_ecp_keypair our_key;
275 mbedtls_ecp_keypair their_key;
276 mbedtls_ecdh_context ecdh;
277
278 memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) );
279 mbedtls_ecdh_init( &ecdh );
280 mbedtls_ecp_keypair_init( &our_key );
281 mbedtls_ecp_keypair_init( &their_key );
282
283 if( ! load_private_key( our_grp_id, our_private_key, &our_key, &rnd_info ) )
284 goto exit;
285 if( ! load_public_key( their_grp_id, their_point, &their_key ) )
286 goto exit;
287
288 if( ours_first )
289 {
290 TEST_ASSERT( mbedtls_ecdh_get_params(
291 &ecdh, &our_key, MBEDTLS_ECDH_OURS ) == 0 );
292 TEST_ASSERT( mbedtls_ecdh_get_params(
293 &ecdh, &their_key, MBEDTLS_ECDH_THEIRS ) ==
294 expected_ret );
295 }
296 else
297 {
298 TEST_ASSERT( mbedtls_ecdh_get_params(
299 &ecdh, &their_key, MBEDTLS_ECDH_THEIRS ) == 0 );
300 TEST_ASSERT( mbedtls_ecdh_get_params(
301 &ecdh, &our_key, MBEDTLS_ECDH_OURS ) ==
302 expected_ret );
303 }
304
305exit:
306 mbedtls_ecdh_free( &ecdh );
307 mbedtls_ecp_keypair_free( &our_key );
308 mbedtls_ecp_keypair_free( &their_key );
309}
310/* END_CASE */