xref: /aosp_15_r20/external/mbedtls/programs/pkey/dh_client.c (revision 62c56f9862f102b96d72393aff6076c951fb8148)
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