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