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