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 #define mbedtls_printf     printf
33 #endif
34 
35 #if !defined(MBEDTLS_ECDH_C) || \
36     !defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \
37     !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C)
main(void)38 int main( void )
39 {
40     mbedtls_printf( "MBEDTLS_ECDH_C and/or "
41                     "MBEDTLS_ECP_DP_CURVE25519_ENABLED and/or "
42                     "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C "
43                     "not defined\n" );
44     return( 0 );
45 }
46 #else
47 
48 #include "mbedtls/entropy.h"
49 #include "mbedtls/ctr_drbg.h"
50 #include "mbedtls/ecdh.h"
51 
main(int argc,char * argv[])52 int main( int argc, char *argv[] )
53 {
54     int ret;
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: inialize context and generate keypair
86      */
87     mbedtls_printf( "  . Setting up client context..." );
88     fflush( stdout );
89 
90     ret = mbedtls_ecp_group_load( &ctx_cli.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.grp, &ctx_cli.d, &ctx_cli.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.Q.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.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.grp, &ctx_srv.d, &ctx_srv.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.Q.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.Qp.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.Qp.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.grp, &ctx_srv.z,
165                                        &ctx_srv.Qp, &ctx_srv.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.Qp.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.Qp.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.grp, &ctx_cli.z,
196                                        &ctx_cli.Qp, &ctx_cli.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 secret equal?
208      */
209     mbedtls_printf( "  . Checking if both computed secrets are equal..." );
210     fflush( stdout );
211 
212     ret = mbedtls_mpi_cmp_mpi( &ctx_cli.z, &ctx_srv.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 
222 exit:
223 
224 #if defined(_WIN32)
225     mbedtls_printf( "  + Press Enter to exit this program.\n" );
226     fflush( stdout ); getchar();
227 #endif
228 
229     mbedtls_ecdh_free( &ctx_srv );
230     mbedtls_ecdh_free( &ctx_cli );
231     mbedtls_ctr_drbg_free( &ctr_drbg );
232     mbedtls_entropy_free( &entropy );
233 
234     return( ret != 0 );
235 }
236 #endif /* MBEDTLS_ECDH_C && MBEDTLS_ECP_DP_CURVE25519_ENABLED &&
237           MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
238