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#include "mbedtls/platform.h"
23
24#if !defined(MBEDTLS_ECDH_C) || \
25    !defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \
26    !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C)
27int main(void)
28{
29    mbedtls_printf("MBEDTLS_ECDH_C and/or "
30                   "MBEDTLS_ECP_DP_CURVE25519_ENABLED and/or "
31                   "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C "
32                   "not defined\n");
33    mbedtls_exit(0);
34}
35#else
36
37#include "mbedtls/entropy.h"
38#include "mbedtls/ctr_drbg.h"
39#include "mbedtls/ecdh.h"
40
41#include <string.h>
42
43
44int main(int argc, char *argv[])
45{
46    int ret = 1;
47    int exit_code = MBEDTLS_EXIT_FAILURE;
48    mbedtls_ecdh_context ctx_cli, ctx_srv;
49    mbedtls_entropy_context entropy;
50    mbedtls_ctr_drbg_context ctr_drbg;
51    unsigned char cli_to_srv[36], srv_to_cli[33];
52    const char pers[] = "ecdh";
53
54    size_t srv_olen;
55    size_t cli_olen;
56    unsigned char secret_cli[32] = { 0 };
57    unsigned char secret_srv[32] = { 0 };
58    const unsigned char *p_cli_to_srv = cli_to_srv;
59
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("  . Seed 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,
75                                     &entropy,
76                                     (const unsigned char *) pers,
77                                     sizeof(pers))) != 0) {
78        mbedtls_printf(" failed\n  ! mbedtls_ctr_drbg_seed returned %d\n",
79                       ret);
80        goto exit;
81    }
82
83    mbedtls_printf(" ok\n");
84
85    /*
86     * Client: initialize context and generate keypair
87     */
88    mbedtls_printf("  . Set up client context, generate EC key pair...");
89    fflush(stdout);
90
91    ret = mbedtls_ecdh_setup(&ctx_cli, MBEDTLS_ECP_DP_CURVE25519);
92    if (ret != 0) {
93        mbedtls_printf(" failed\n  ! mbedtls_ecdh_setup returned %d\n", ret);
94        goto exit;
95    }
96
97    ret = mbedtls_ecdh_make_params(&ctx_cli, &cli_olen, cli_to_srv,
98                                   sizeof(cli_to_srv),
99                                   mbedtls_ctr_drbg_random, &ctr_drbg);
100    if (ret != 0) {
101        mbedtls_printf(" failed\n  ! mbedtls_ecdh_make_params returned %d\n",
102                       ret);
103        goto exit;
104    }
105
106    mbedtls_printf(" ok\n");
107
108    /*
109     * Server: initialize context and generate keypair
110     */
111    mbedtls_printf("  . Server: read params, generate public key...");
112    fflush(stdout);
113
114    ret = mbedtls_ecdh_read_params(&ctx_srv, &p_cli_to_srv,
115                                   p_cli_to_srv + sizeof(cli_to_srv));
116    if (ret != 0) {
117        mbedtls_printf(" failed\n  ! mbedtls_ecdh_read_params returned %d\n",
118                       ret);
119        goto exit;
120    }
121
122    ret = mbedtls_ecdh_make_public(&ctx_srv, &srv_olen, srv_to_cli,
123                                   sizeof(srv_to_cli),
124                                   mbedtls_ctr_drbg_random, &ctr_drbg);
125    if (ret != 0) {
126        mbedtls_printf(" failed\n  ! mbedtls_ecdh_make_public returned %d\n",
127                       ret);
128        goto exit;
129    }
130
131    mbedtls_printf(" ok\n");
132
133    /*
134     * Client: read public key
135     */
136    mbedtls_printf("  . Client: read public key...");
137    fflush(stdout);
138
139    ret = mbedtls_ecdh_read_public(&ctx_cli, srv_to_cli,
140                                   sizeof(srv_to_cli));
141    if (ret != 0) {
142        mbedtls_printf(" failed\n  ! mbedtls_ecdh_read_public returned %d\n",
143                       ret);
144        goto exit;
145    }
146
147    mbedtls_printf(" ok\n");
148
149    /*
150     * Calculate secrets
151     */
152    mbedtls_printf("  . Calculate secrets...");
153    fflush(stdout);
154
155    ret = mbedtls_ecdh_calc_secret(&ctx_cli, &cli_olen, secret_cli,
156                                   sizeof(secret_cli),
157                                   mbedtls_ctr_drbg_random, &ctr_drbg);
158    if (ret != 0) {
159        mbedtls_printf(" failed\n  ! mbedtls_ecdh_calc_secret returned %d\n",
160                       ret);
161        goto exit;
162    }
163
164    ret = mbedtls_ecdh_calc_secret(&ctx_srv, &srv_olen, secret_srv,
165                                   sizeof(secret_srv),
166                                   mbedtls_ctr_drbg_random, &ctr_drbg);
167    if (ret != 0) {
168        mbedtls_printf(" failed\n  ! mbedtls_ecdh_calc_secret returned %d\n",
169                       ret);
170        goto exit;
171    }
172
173    mbedtls_printf(" ok\n");
174
175    /*
176     * Verification: are the computed secrets equal?
177     */
178    mbedtls_printf("  . Check if both calculated secrets are equal...");
179    fflush(stdout);
180
181    ret = memcmp(secret_srv, secret_cli, srv_olen);
182    if (ret != 0 || (cli_olen != srv_olen)) {
183        mbedtls_printf(" failed\n  ! Shared secrets not equal.\n");
184        goto exit;
185    }
186
187    mbedtls_printf(" ok\n");
188
189    exit_code = MBEDTLS_EXIT_SUCCESS;
190
191exit:
192
193    mbedtls_ecdh_free(&ctx_srv);
194    mbedtls_ecdh_free(&ctx_cli);
195    mbedtls_ctr_drbg_free(&ctr_drbg);
196    mbedtls_entropy_free(&entropy);
197
198    mbedtls_exit(exit_code);
199}
200#endif /* MBEDTLS_ECDH_C && MBEDTLS_ECP_DP_CURVE25519_ENABLED &&
201          MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C */
202