1 /*
2  *  Example ECDHE with Curve25519 program
3  *
4  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5  *  SPDX-License-Identifier: GPL-2.0
6  *
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.
11  *
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.
16  *
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.
20  *
21  *  This file is part of mbed TLS (https://tls.mbed.org)
22  */
23 
24 #if !defined(MBEDTLS_CONFIG_FILE)
25 #include "mbedtls/config.h"
26 #else
27 #include MBEDTLS_CONFIG_FILE
28 #endif
29 
30 #if defined(MBEDTLS_PLATFORM_C)
31 #include "mbedtls/platform.h"
32 #else
33 #include <stdio.h>
34 #include <stdlib.h>
35 #define mbedtls_printf          printf
36 #define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
37 #define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
38 #endif /* MBEDTLS_PLATFORM_C */
39 
40 #if !defined(MBEDTLS_ECDH_C) || \
41     !defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \
42     !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C)
main(void)43 int main( void )
44 {
45     mbedtls_printf( "MBEDTLS_ECDH_C and/or "
46                     "MBEDTLS_ECP_DP_CURVE25519_ENABLED and/or "
47                     "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C "
48                     "not defined\n" );
49     return( 0 );
50 }
51 #else
52 
53 #include "mbedtls/entropy.h"
54 #include "mbedtls/ctr_drbg.h"
55 #include "mbedtls/ecdh.h"
56 
main(int argc,char * argv[])57 int main( int argc, char *argv[] )
58 {
59     int ret = 1;
60     int exit_code = MBEDTLS_EXIT_FAILURE;
61     mbedtls_ecdh_context ctx_cli, ctx_srv;
62     mbedtls_entropy_context entropy;
63     mbedtls_ctr_drbg_context ctr_drbg;
64     unsigned char cli_to_srv[32], srv_to_cli[32];
65     const char pers[] = "ecdh";
66     ((void) argc);
67     ((void) argv);
68 
69     mbedtls_ecdh_init( &ctx_cli );
70     mbedtls_ecdh_init( &ctx_srv );
71     mbedtls_ctr_drbg_init( &ctr_drbg );
72 
73     /*
74      * Initialize random number generation
75      */
76     mbedtls_printf( "  . Seeding the random number generator..." );
77     fflush( stdout );
78 
79     mbedtls_entropy_init( &entropy );
80     if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
81                                (const unsigned char *) pers,
82                                sizeof pers ) ) != 0 )
83     {
84         mbedtls_printf( " failed\n  ! mbedtls_ctr_drbg_seed returned %d\n", ret );
85         goto exit;
86     }
87 
88     mbedtls_printf( " ok\n" );
89 
90     /*
91      * Client: inialize context and generate keypair
92      */
93     mbedtls_printf( "  . Setting up client context..." );
94     fflush( stdout );
95 
96     ret = mbedtls_ecp_group_load( &ctx_cli.grp, MBEDTLS_ECP_DP_CURVE25519 );
97     if( ret != 0 )
98     {
99         mbedtls_printf( " failed\n  ! mbedtls_ecp_group_load returned %d\n", ret );
100         goto exit;
101     }
102 
103     ret = mbedtls_ecdh_gen_public( &ctx_cli.grp, &ctx_cli.d, &ctx_cli.Q,
104                                    mbedtls_ctr_drbg_random, &ctr_drbg );
105     if( ret != 0 )
106     {
107         mbedtls_printf( " failed\n  ! mbedtls_ecdh_gen_public returned %d\n", ret );
108         goto exit;
109     }
110 
111     ret = mbedtls_mpi_write_binary( &ctx_cli.Q.X, cli_to_srv, 32 );
112     if( ret != 0 )
113     {
114         mbedtls_printf( " failed\n  ! mbedtls_mpi_write_binary returned %d\n", ret );
115         goto exit;
116     }
117 
118     mbedtls_printf( " ok\n" );
119 
120     /*
121      * Server: initialize context and generate keypair
122      */
123     mbedtls_printf( "  . Setting up server context..." );
124     fflush( stdout );
125 
126     ret = mbedtls_ecp_group_load( &ctx_srv.grp, MBEDTLS_ECP_DP_CURVE25519 );
127     if( ret != 0 )
128     {
129         mbedtls_printf( " failed\n  ! mbedtls_ecp_group_load returned %d\n", ret );
130         goto exit;
131     }
132 
133     ret = mbedtls_ecdh_gen_public( &ctx_srv.grp, &ctx_srv.d, &ctx_srv.Q,
134                                    mbedtls_ctr_drbg_random, &ctr_drbg );
135     if( ret != 0 )
136     {
137         mbedtls_printf( " failed\n  ! mbedtls_ecdh_gen_public returned %d\n", ret );
138         goto exit;
139     }
140 
141     ret = mbedtls_mpi_write_binary( &ctx_srv.Q.X, srv_to_cli, 32 );
142     if( ret != 0 )
143     {
144         mbedtls_printf( " failed\n  ! mbedtls_mpi_write_binary returned %d\n", ret );
145         goto exit;
146     }
147 
148     mbedtls_printf( " ok\n" );
149 
150     /*
151      * Server: read peer's key and generate shared secret
152      */
153     mbedtls_printf( "  . Server reading client key and computing secret..." );
154     fflush( stdout );
155 
156     ret = mbedtls_mpi_lset( &ctx_srv.Qp.Z, 1 );
157     if( ret != 0 )
158     {
159         mbedtls_printf( " failed\n  ! mbedtls_mpi_lset returned %d\n", ret );
160         goto exit;
161     }
162 
163     ret = mbedtls_mpi_read_binary( &ctx_srv.Qp.X, cli_to_srv, 32 );
164     if( ret != 0 )
165     {
166         mbedtls_printf( " failed\n  ! mbedtls_mpi_read_binary returned %d\n", ret );
167         goto exit;
168     }
169 
170     ret = mbedtls_ecdh_compute_shared( &ctx_srv.grp, &ctx_srv.z,
171                                        &ctx_srv.Qp, &ctx_srv.d,
172                                        mbedtls_ctr_drbg_random, &ctr_drbg );
173     if( ret != 0 )
174     {
175         mbedtls_printf( " failed\n  ! mbedtls_ecdh_compute_shared returned %d\n", ret );
176         goto exit;
177     }
178 
179     mbedtls_printf( " ok\n" );
180 
181     /*
182      * Client: read peer's key and generate shared secret
183      */
184     mbedtls_printf( "  . Client reading server key and computing secret..." );
185     fflush( stdout );
186 
187     ret = mbedtls_mpi_lset( &ctx_cli.Qp.Z, 1 );
188     if( ret != 0 )
189     {
190         mbedtls_printf( " failed\n  ! mbedtls_mpi_lset returned %d\n", ret );
191         goto exit;
192     }
193 
194     ret = mbedtls_mpi_read_binary( &ctx_cli.Qp.X, srv_to_cli, 32 );
195     if( ret != 0 )
196     {
197         mbedtls_printf( " failed\n  ! mbedtls_mpi_read_binary returned %d\n", ret );
198         goto exit;
199     }
200 
201     ret = mbedtls_ecdh_compute_shared( &ctx_cli.grp, &ctx_cli.z,
202                                        &ctx_cli.Qp, &ctx_cli.d,
203                                        mbedtls_ctr_drbg_random, &ctr_drbg );
204     if( ret != 0 )
205     {
206         mbedtls_printf( " failed\n  ! mbedtls_ecdh_compute_shared returned %d\n", ret );
207         goto exit;
208     }
209 
210     mbedtls_printf( " ok\n" );
211 
212     /*
213      * Verification: are the computed secrets equal?
214      */
215     mbedtls_printf( "  . Checking if both computed secrets are equal..." );
216     fflush( stdout );
217 
218     ret = mbedtls_mpi_cmp_mpi( &ctx_cli.z, &ctx_srv.z );
219     if( ret != 0 )
220     {
221         mbedtls_printf( " failed\n  ! mbedtls_ecdh_compute_shared returned %d\n", ret );
222         goto exit;
223     }
224 
225     mbedtls_printf( " ok\n" );
226 
227     exit_code = MBEDTLS_EXIT_SUCCESS;
228 
229 exit:
230 
231 #if defined(_WIN32)
232     mbedtls_printf( "  + Press Enter to exit this program.\n" );
233     fflush( stdout ); getchar();
234 #endif
235 
236     mbedtls_ecdh_free( &ctx_srv );
237     mbedtls_ecdh_free( &ctx_cli );
238     mbedtls_ctr_drbg_free( &ctr_drbg );
239     mbedtls_entropy_free( &entropy );
240 
241     return( exit_code );
242 }
243 #endif /* MBEDTLS_ECDH_C && MBEDTLS_ECP_DP_CURVE25519_ENABLED &&
244           MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
245