1*62c56f98SSadaf Ebrahimi /*
2*62c56f98SSadaf Ebrahimi * Diffie-Hellman-Merkle key exchange (client side)
3*62c56f98SSadaf Ebrahimi *
4*62c56f98SSadaf Ebrahimi * Copyright The Mbed TLS Contributors
5*62c56f98SSadaf Ebrahimi * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6*62c56f98SSadaf Ebrahimi */
7*62c56f98SSadaf Ebrahimi
8*62c56f98SSadaf Ebrahimi #include "mbedtls/build_info.h"
9*62c56f98SSadaf Ebrahimi
10*62c56f98SSadaf Ebrahimi #include "mbedtls/platform.h"
11*62c56f98SSadaf Ebrahimi /* md.h is included this early since MD_CAN_XXX macros are defined there. */
12*62c56f98SSadaf Ebrahimi #include "mbedtls/md.h"
13*62c56f98SSadaf Ebrahimi
14*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_AES_C) && defined(MBEDTLS_DHM_C) && \
15*62c56f98SSadaf Ebrahimi defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_NET_C) && \
16*62c56f98SSadaf Ebrahimi defined(MBEDTLS_RSA_C) && defined(MBEDTLS_MD_CAN_SHA256) && \
17*62c56f98SSadaf Ebrahimi defined(MBEDTLS_FS_IO) && defined(MBEDTLS_CTR_DRBG_C) && \
18*62c56f98SSadaf Ebrahimi defined(MBEDTLS_MD_CAN_SHA1)
19*62c56f98SSadaf Ebrahimi #include "mbedtls/net_sockets.h"
20*62c56f98SSadaf Ebrahimi #include "mbedtls/aes.h"
21*62c56f98SSadaf Ebrahimi #include "mbedtls/dhm.h"
22*62c56f98SSadaf Ebrahimi #include "mbedtls/rsa.h"
23*62c56f98SSadaf Ebrahimi #include "mbedtls/sha1.h"
24*62c56f98SSadaf Ebrahimi #include "mbedtls/entropy.h"
25*62c56f98SSadaf Ebrahimi #include "mbedtls/ctr_drbg.h"
26*62c56f98SSadaf Ebrahimi
27*62c56f98SSadaf Ebrahimi #include <stdio.h>
28*62c56f98SSadaf Ebrahimi #include <string.h>
29*62c56f98SSadaf Ebrahimi #endif
30*62c56f98SSadaf Ebrahimi
31*62c56f98SSadaf Ebrahimi #define SERVER_NAME "localhost"
32*62c56f98SSadaf Ebrahimi #define SERVER_PORT "11999"
33*62c56f98SSadaf Ebrahimi
34*62c56f98SSadaf Ebrahimi #if !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_DHM_C) || \
35*62c56f98SSadaf Ebrahimi !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NET_C) || \
36*62c56f98SSadaf Ebrahimi !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_MD_CAN_SHA256) || \
37*62c56f98SSadaf Ebrahimi !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_CTR_DRBG_C) || \
38*62c56f98SSadaf Ebrahimi !defined(MBEDTLS_SHA1_C)
main(void)39*62c56f98SSadaf Ebrahimi int main(void)
40*62c56f98SSadaf Ebrahimi {
41*62c56f98SSadaf Ebrahimi mbedtls_printf("MBEDTLS_AES_C and/or MBEDTLS_DHM_C and/or MBEDTLS_ENTROPY_C "
42*62c56f98SSadaf Ebrahimi "and/or MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or "
43*62c56f98SSadaf Ebrahimi "MBEDTLS_MD_CAN_SHA256 and/or MBEDTLS_FS_IO and/or "
44*62c56f98SSadaf Ebrahimi "MBEDTLS_CTR_DRBG_C and/or MBEDTLS_SHA1_C not defined.\n");
45*62c56f98SSadaf Ebrahimi mbedtls_exit(0);
46*62c56f98SSadaf Ebrahimi }
47*62c56f98SSadaf Ebrahimi #else
48*62c56f98SSadaf Ebrahimi
49*62c56f98SSadaf Ebrahimi
main(void)50*62c56f98SSadaf Ebrahimi int main(void)
51*62c56f98SSadaf Ebrahimi {
52*62c56f98SSadaf Ebrahimi FILE *f;
53*62c56f98SSadaf Ebrahimi
54*62c56f98SSadaf Ebrahimi int ret = 1;
55*62c56f98SSadaf Ebrahimi int exit_code = MBEDTLS_EXIT_FAILURE;
56*62c56f98SSadaf Ebrahimi size_t n, buflen;
57*62c56f98SSadaf Ebrahimi mbedtls_net_context server_fd;
58*62c56f98SSadaf Ebrahimi
59*62c56f98SSadaf Ebrahimi unsigned char *p, *end;
60*62c56f98SSadaf Ebrahimi unsigned char buf[2048];
61*62c56f98SSadaf Ebrahimi unsigned char hash[32];
62*62c56f98SSadaf Ebrahimi const char *pers = "dh_client";
63*62c56f98SSadaf Ebrahimi
64*62c56f98SSadaf Ebrahimi mbedtls_entropy_context entropy;
65*62c56f98SSadaf Ebrahimi mbedtls_ctr_drbg_context ctr_drbg;
66*62c56f98SSadaf Ebrahimi mbedtls_rsa_context rsa;
67*62c56f98SSadaf Ebrahimi mbedtls_dhm_context dhm;
68*62c56f98SSadaf Ebrahimi mbedtls_aes_context aes;
69*62c56f98SSadaf Ebrahimi
70*62c56f98SSadaf Ebrahimi mbedtls_net_init(&server_fd);
71*62c56f98SSadaf Ebrahimi mbedtls_dhm_init(&dhm);
72*62c56f98SSadaf Ebrahimi mbedtls_aes_init(&aes);
73*62c56f98SSadaf Ebrahimi mbedtls_ctr_drbg_init(&ctr_drbg);
74*62c56f98SSadaf Ebrahimi
75*62c56f98SSadaf Ebrahimi /*
76*62c56f98SSadaf Ebrahimi * 1. Setup the RNG
77*62c56f98SSadaf Ebrahimi */
78*62c56f98SSadaf Ebrahimi mbedtls_printf("\n . Seeding the random number generator");
79*62c56f98SSadaf Ebrahimi fflush(stdout);
80*62c56f98SSadaf Ebrahimi
81*62c56f98SSadaf Ebrahimi mbedtls_entropy_init(&entropy);
82*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
83*62c56f98SSadaf Ebrahimi (const unsigned char *) pers,
84*62c56f98SSadaf Ebrahimi strlen(pers))) != 0) {
85*62c56f98SSadaf Ebrahimi mbedtls_printf(" failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret);
86*62c56f98SSadaf Ebrahimi goto exit;
87*62c56f98SSadaf Ebrahimi }
88*62c56f98SSadaf Ebrahimi
89*62c56f98SSadaf Ebrahimi /*
90*62c56f98SSadaf Ebrahimi * 2. Read the server's public RSA key
91*62c56f98SSadaf Ebrahimi */
92*62c56f98SSadaf Ebrahimi mbedtls_printf("\n . Reading public key from rsa_pub.txt");
93*62c56f98SSadaf Ebrahimi fflush(stdout);
94*62c56f98SSadaf Ebrahimi
95*62c56f98SSadaf Ebrahimi if ((f = fopen("rsa_pub.txt", "rb")) == NULL) {
96*62c56f98SSadaf Ebrahimi mbedtls_printf(" failed\n ! Could not open rsa_pub.txt\n" \
97*62c56f98SSadaf Ebrahimi " ! Please run rsa_genkey first\n\n");
98*62c56f98SSadaf Ebrahimi goto exit;
99*62c56f98SSadaf Ebrahimi }
100*62c56f98SSadaf Ebrahimi
101*62c56f98SSadaf Ebrahimi mbedtls_rsa_init(&rsa);
102*62c56f98SSadaf Ebrahimi
103*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_mpi_read_file(&rsa.MBEDTLS_PRIVATE(N), 16, f)) != 0 ||
104*62c56f98SSadaf Ebrahimi (ret = mbedtls_mpi_read_file(&rsa.MBEDTLS_PRIVATE(E), 16, f)) != 0) {
105*62c56f98SSadaf Ebrahimi mbedtls_printf(" failed\n ! mbedtls_mpi_read_file returned %d\n\n", ret);
106*62c56f98SSadaf Ebrahimi fclose(f);
107*62c56f98SSadaf Ebrahimi goto exit;
108*62c56f98SSadaf Ebrahimi }
109*62c56f98SSadaf Ebrahimi
110*62c56f98SSadaf Ebrahimi rsa.MBEDTLS_PRIVATE(len) = (mbedtls_mpi_bitlen(&rsa.MBEDTLS_PRIVATE(N)) + 7) >> 3;
111*62c56f98SSadaf Ebrahimi
112*62c56f98SSadaf Ebrahimi fclose(f);
113*62c56f98SSadaf Ebrahimi
114*62c56f98SSadaf Ebrahimi /*
115*62c56f98SSadaf Ebrahimi * 3. Initiate the connection
116*62c56f98SSadaf Ebrahimi */
117*62c56f98SSadaf Ebrahimi mbedtls_printf("\n . Connecting to tcp/%s/%s", SERVER_NAME,
118*62c56f98SSadaf Ebrahimi SERVER_PORT);
119*62c56f98SSadaf Ebrahimi fflush(stdout);
120*62c56f98SSadaf Ebrahimi
121*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_net_connect(&server_fd, SERVER_NAME,
122*62c56f98SSadaf Ebrahimi SERVER_PORT, MBEDTLS_NET_PROTO_TCP)) != 0) {
123*62c56f98SSadaf Ebrahimi mbedtls_printf(" failed\n ! mbedtls_net_connect returned %d\n\n", ret);
124*62c56f98SSadaf Ebrahimi goto exit;
125*62c56f98SSadaf Ebrahimi }
126*62c56f98SSadaf Ebrahimi
127*62c56f98SSadaf Ebrahimi /*
128*62c56f98SSadaf Ebrahimi * 4a. First get the buffer length
129*62c56f98SSadaf Ebrahimi */
130*62c56f98SSadaf Ebrahimi mbedtls_printf("\n . Receiving the server's DH parameters");
131*62c56f98SSadaf Ebrahimi fflush(stdout);
132*62c56f98SSadaf Ebrahimi
133*62c56f98SSadaf Ebrahimi memset(buf, 0, sizeof(buf));
134*62c56f98SSadaf Ebrahimi
135*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_net_recv(&server_fd, buf, 2)) != 2) {
136*62c56f98SSadaf Ebrahimi mbedtls_printf(" failed\n ! mbedtls_net_recv returned %d\n\n", ret);
137*62c56f98SSadaf Ebrahimi goto exit;
138*62c56f98SSadaf Ebrahimi }
139*62c56f98SSadaf Ebrahimi
140*62c56f98SSadaf Ebrahimi n = buflen = (buf[0] << 8) | buf[1];
141*62c56f98SSadaf Ebrahimi if (buflen < 1 || buflen > sizeof(buf)) {
142*62c56f98SSadaf Ebrahimi mbedtls_printf(" failed\n ! Got an invalid buffer length\n\n");
143*62c56f98SSadaf Ebrahimi goto exit;
144*62c56f98SSadaf Ebrahimi }
145*62c56f98SSadaf Ebrahimi
146*62c56f98SSadaf Ebrahimi /*
147*62c56f98SSadaf Ebrahimi * 4b. Get the DHM parameters: P, G and Ys = G^Xs mod P
148*62c56f98SSadaf Ebrahimi */
149*62c56f98SSadaf Ebrahimi memset(buf, 0, sizeof(buf));
150*62c56f98SSadaf Ebrahimi
151*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_net_recv(&server_fd, buf, n)) != (int) n) {
152*62c56f98SSadaf Ebrahimi mbedtls_printf(" failed\n ! mbedtls_net_recv returned %d\n\n", ret);
153*62c56f98SSadaf Ebrahimi goto exit;
154*62c56f98SSadaf Ebrahimi }
155*62c56f98SSadaf Ebrahimi
156*62c56f98SSadaf Ebrahimi p = buf, end = buf + buflen;
157*62c56f98SSadaf Ebrahimi
158*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_dhm_read_params(&dhm, &p, end)) != 0) {
159*62c56f98SSadaf Ebrahimi mbedtls_printf(" failed\n ! mbedtls_dhm_read_params returned %d\n\n", ret);
160*62c56f98SSadaf Ebrahimi goto exit;
161*62c56f98SSadaf Ebrahimi }
162*62c56f98SSadaf Ebrahimi
163*62c56f98SSadaf Ebrahimi n = mbedtls_dhm_get_len(&dhm);
164*62c56f98SSadaf Ebrahimi if (n < 64 || n > 512) {
165*62c56f98SSadaf Ebrahimi mbedtls_printf(" failed\n ! Invalid DHM modulus size\n\n");
166*62c56f98SSadaf Ebrahimi goto exit;
167*62c56f98SSadaf Ebrahimi }
168*62c56f98SSadaf Ebrahimi
169*62c56f98SSadaf Ebrahimi /*
170*62c56f98SSadaf Ebrahimi * 5. Check that the server's RSA signature matches
171*62c56f98SSadaf Ebrahimi * the SHA-256 hash of (P,G,Ys)
172*62c56f98SSadaf Ebrahimi */
173*62c56f98SSadaf Ebrahimi mbedtls_printf("\n . Verifying the server's RSA signature");
174*62c56f98SSadaf Ebrahimi fflush(stdout);
175*62c56f98SSadaf Ebrahimi
176*62c56f98SSadaf Ebrahimi p += 2;
177*62c56f98SSadaf Ebrahimi
178*62c56f98SSadaf Ebrahimi if ((n = (size_t) (end - p)) != rsa.MBEDTLS_PRIVATE(len)) {
179*62c56f98SSadaf Ebrahimi mbedtls_printf(" failed\n ! Invalid RSA signature size\n\n");
180*62c56f98SSadaf Ebrahimi goto exit;
181*62c56f98SSadaf Ebrahimi }
182*62c56f98SSadaf Ebrahimi
183*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_sha1(buf, (int) (p - 2 - buf), hash)) != 0) {
184*62c56f98SSadaf Ebrahimi mbedtls_printf(" failed\n ! mbedtls_sha1 returned %d\n\n", ret);
185*62c56f98SSadaf Ebrahimi goto exit;
186*62c56f98SSadaf Ebrahimi }
187*62c56f98SSadaf Ebrahimi
188*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_rsa_pkcs1_verify(&rsa, MBEDTLS_MD_SHA256,
189*62c56f98SSadaf Ebrahimi 32, hash, p)) != 0) {
190*62c56f98SSadaf Ebrahimi mbedtls_printf(" failed\n ! mbedtls_rsa_pkcs1_verify returned %d\n\n", ret);
191*62c56f98SSadaf Ebrahimi goto exit;
192*62c56f98SSadaf Ebrahimi }
193*62c56f98SSadaf Ebrahimi
194*62c56f98SSadaf Ebrahimi /*
195*62c56f98SSadaf Ebrahimi * 6. Send our public value: Yc = G ^ Xc mod P
196*62c56f98SSadaf Ebrahimi */
197*62c56f98SSadaf Ebrahimi mbedtls_printf("\n . Sending own public value to server");
198*62c56f98SSadaf Ebrahimi fflush(stdout);
199*62c56f98SSadaf Ebrahimi
200*62c56f98SSadaf Ebrahimi n = mbedtls_dhm_get_len(&dhm);
201*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_dhm_make_public(&dhm, (int) n, buf, n,
202*62c56f98SSadaf Ebrahimi mbedtls_ctr_drbg_random, &ctr_drbg)) != 0) {
203*62c56f98SSadaf Ebrahimi mbedtls_printf(" failed\n ! mbedtls_dhm_make_public returned %d\n\n", ret);
204*62c56f98SSadaf Ebrahimi goto exit;
205*62c56f98SSadaf Ebrahimi }
206*62c56f98SSadaf Ebrahimi
207*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_net_send(&server_fd, buf, n)) != (int) n) {
208*62c56f98SSadaf Ebrahimi mbedtls_printf(" failed\n ! mbedtls_net_send returned %d\n\n", ret);
209*62c56f98SSadaf Ebrahimi goto exit;
210*62c56f98SSadaf Ebrahimi }
211*62c56f98SSadaf Ebrahimi
212*62c56f98SSadaf Ebrahimi /*
213*62c56f98SSadaf Ebrahimi * 7. Derive the shared secret: K = Ys ^ Xc mod P
214*62c56f98SSadaf Ebrahimi */
215*62c56f98SSadaf Ebrahimi mbedtls_printf("\n . Shared secret: ");
216*62c56f98SSadaf Ebrahimi fflush(stdout);
217*62c56f98SSadaf Ebrahimi
218*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_dhm_calc_secret(&dhm, buf, sizeof(buf), &n,
219*62c56f98SSadaf Ebrahimi mbedtls_ctr_drbg_random, &ctr_drbg)) != 0) {
220*62c56f98SSadaf Ebrahimi mbedtls_printf(" failed\n ! mbedtls_dhm_calc_secret returned %d\n\n", ret);
221*62c56f98SSadaf Ebrahimi goto exit;
222*62c56f98SSadaf Ebrahimi }
223*62c56f98SSadaf Ebrahimi
224*62c56f98SSadaf Ebrahimi for (n = 0; n < 16; n++) {
225*62c56f98SSadaf Ebrahimi mbedtls_printf("%02x", buf[n]);
226*62c56f98SSadaf Ebrahimi }
227*62c56f98SSadaf Ebrahimi
228*62c56f98SSadaf Ebrahimi /*
229*62c56f98SSadaf Ebrahimi * 8. Setup the AES-256 decryption key
230*62c56f98SSadaf Ebrahimi *
231*62c56f98SSadaf Ebrahimi * This is an overly simplified example; best practice is
232*62c56f98SSadaf Ebrahimi * to hash the shared secret with a random value to derive
233*62c56f98SSadaf Ebrahimi * the keying material for the encryption/decryption keys,
234*62c56f98SSadaf Ebrahimi * IVs and MACs.
235*62c56f98SSadaf Ebrahimi */
236*62c56f98SSadaf Ebrahimi mbedtls_printf("...\n . Receiving and decrypting the ciphertext");
237*62c56f98SSadaf Ebrahimi fflush(stdout);
238*62c56f98SSadaf Ebrahimi
239*62c56f98SSadaf Ebrahimi ret = mbedtls_aes_setkey_dec(&aes, buf, 256);
240*62c56f98SSadaf Ebrahimi if (ret != 0) {
241*62c56f98SSadaf Ebrahimi goto exit;
242*62c56f98SSadaf Ebrahimi }
243*62c56f98SSadaf Ebrahimi
244*62c56f98SSadaf Ebrahimi memset(buf, 0, sizeof(buf));
245*62c56f98SSadaf Ebrahimi
246*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_net_recv(&server_fd, buf, 16)) != 16) {
247*62c56f98SSadaf Ebrahimi mbedtls_printf(" failed\n ! mbedtls_net_recv returned %d\n\n", ret);
248*62c56f98SSadaf Ebrahimi goto exit;
249*62c56f98SSadaf Ebrahimi }
250*62c56f98SSadaf Ebrahimi
251*62c56f98SSadaf Ebrahimi ret = mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_DECRYPT, buf, buf);
252*62c56f98SSadaf Ebrahimi if (ret != 0) {
253*62c56f98SSadaf Ebrahimi goto exit;
254*62c56f98SSadaf Ebrahimi }
255*62c56f98SSadaf Ebrahimi buf[16] = '\0';
256*62c56f98SSadaf Ebrahimi mbedtls_printf("\n . Plaintext is \"%s\"\n\n", (char *) buf);
257*62c56f98SSadaf Ebrahimi
258*62c56f98SSadaf Ebrahimi exit_code = MBEDTLS_EXIT_SUCCESS;
259*62c56f98SSadaf Ebrahimi
260*62c56f98SSadaf Ebrahimi exit:
261*62c56f98SSadaf Ebrahimi
262*62c56f98SSadaf Ebrahimi mbedtls_net_free(&server_fd);
263*62c56f98SSadaf Ebrahimi
264*62c56f98SSadaf Ebrahimi mbedtls_aes_free(&aes);
265*62c56f98SSadaf Ebrahimi mbedtls_rsa_free(&rsa);
266*62c56f98SSadaf Ebrahimi mbedtls_dhm_free(&dhm);
267*62c56f98SSadaf Ebrahimi mbedtls_ctr_drbg_free(&ctr_drbg);
268*62c56f98SSadaf Ebrahimi mbedtls_entropy_free(&entropy);
269*62c56f98SSadaf Ebrahimi
270*62c56f98SSadaf Ebrahimi mbedtls_exit(exit_code);
271*62c56f98SSadaf Ebrahimi }
272*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_AES_C && MBEDTLS_DHM_C && MBEDTLS_ENTROPY_C &&
273*62c56f98SSadaf Ebrahimi MBEDTLS_NET_C && MBEDTLS_RSA_C && MBEDTLS_MD_CAN_SHA256 &&
274*62c56f98SSadaf Ebrahimi MBEDTLS_FS_IO && MBEDTLS_CTR_DRBG_C */
275