2 * Diffie-Hellman-Merkle key exchange (server side)
4 * Based on XySSL: Copyright (C) 2006-2008 Christophe Devine
6 * Copyright (C) 2009 Paul Bakker <polarssl_maintainer at polarssl dot org>
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
14 * * Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * * Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * * Neither the names of PolarSSL or XySSL nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #ifndef _CRT_SECURE_NO_DEPRECATE
37 #define _CRT_SECURE_NO_DEPRECATE 1
43 #include "tropicssl/net.h"
44 #include "tropicssl/aes.h"
45 #include "tropicssl/dhm.h"
46 #include "tropicssl/rsa.h"
47 #include "tropicssl/sha1.h"
48 #include "tropicssl/havege.h"
50 #define SERVER_PORT 11999
51 #define PLAINTEXT "==Hello there!=="
61 unsigned char buf
[1024];
62 unsigned char hash
[20];
63 unsigned char buf2
[2];
70 memset(&rsa
, 0, sizeof(rsa
));
71 memset(&dhm
, 0, sizeof(dhm
));
76 printf("\n . Seeding the random number generator");
82 * 2a. Read the server's private RSA key
84 printf("\n . Reading private key from rsa_priv.txt");
87 if ((f
= fopen("rsa_priv.txt", "rb")) == NULL
) {
89 printf(" failed\n ! Could not open rsa_priv.txt\n"
90 " ! Please run rsa_genkey first\n\n");
94 rsa_init(&rsa
, RSA_PKCS_V15
, 0, NULL
, NULL
);
96 if ((ret
= mpi_read_file(&rsa
.N
, 16, f
)) != 0 ||
97 (ret
= mpi_read_file(&rsa
.E
, 16, f
)) != 0 ||
98 (ret
= mpi_read_file(&rsa
.D
, 16, f
)) != 0 ||
99 (ret
= mpi_read_file(&rsa
.P
, 16, f
)) != 0 ||
100 (ret
= mpi_read_file(&rsa
.Q
, 16, f
)) != 0 ||
101 (ret
= mpi_read_file(&rsa
.DP
, 16, f
)) != 0 ||
102 (ret
= mpi_read_file(&rsa
.DQ
, 16, f
)) != 0 ||
103 (ret
= mpi_read_file(&rsa
.QP
, 16, f
)) != 0) {
104 printf(" failed\n ! mpi_read_file returned %d\n\n", ret
);
108 rsa
.len
= (mpi_msb(&rsa
.N
) + 7) >> 3;
113 * 2b. Get the DHM modulus and generator
115 printf("\n . Reading DH parameters from dh_prime.txt");
118 if ((f
= fopen("dh_prime.txt", "rb")) == NULL
) {
120 printf(" failed\n ! Could not open dh_prime.txt\n"
121 " ! Please run dh_genprime first\n\n");
125 if (mpi_read_file(&dhm
.P
, 16, f
) != 0 ||
126 mpi_read_file(&dhm
.G
, 16, f
) != 0) {
127 printf(" failed\n ! Invalid DH parameter file\n\n");
134 * 3. Wait for a client to connect
136 printf("\n . Waiting for a remote connection");
139 if ((ret
= net_bind(&listen_fd
, NULL
, SERVER_PORT
)) != 0) {
140 printf(" failed\n ! net_bind returned %d\n\n", ret
);
144 if ((ret
= net_accept(listen_fd
, &client_fd
, NULL
)) != 0) {
145 printf(" failed\n ! net_accept returned %d\n\n", ret
);
150 * 4. Setup the DH parameters (P,G,Ys)
152 printf("\n . Sending the server's DH parameters");
155 memset(buf
, 0, sizeof(buf
));
157 if ((ret
= dhm_make_params(&dhm
, 256, buf
, &n
, havege_rand
, &hs
)) != 0) {
158 printf(" failed\n ! dhm_make_params returned %d\n\n", ret
);
163 * 5. Sign the parameters and send them
167 buf
[n
] = (unsigned char)(rsa
.len
>> 8);
168 buf
[n
+ 1] = (unsigned char)(rsa
.len
);
170 if ((ret
= rsa_pkcs1_sign(&rsa
, RSA_PRIVATE
, RSA_SHA1
,
171 0, hash
, buf
+ n
+ 2)) != 0) {
172 printf(" failed\n ! rsa_pkcs1_sign returned %d\n\n", ret
);
176 buflen
= n
+ 2 + rsa
.len
;
177 buf2
[0] = (unsigned char)(buflen
>> 8);
178 buf2
[1] = (unsigned char)(buflen
);
180 if ((ret
= net_send(&client_fd
, buf2
, 2)) != 2 ||
181 (ret
= net_send(&client_fd
, buf
, buflen
)) != buflen
) {
182 printf(" failed\n ! net_send returned %d\n\n", ret
);
187 * 6. Get the client's public value: Yc = G ^ Xc mod P
189 printf("\n . Receiving the client's public value");
192 memset(buf
, 0, sizeof(buf
));
195 if ((ret
= net_recv(&client_fd
, buf
, n
)) != n
) {
196 printf(" failed\n ! net_recv returned %d\n\n", ret
);
200 if ((ret
= dhm_read_public(&dhm
, buf
, dhm
.len
)) != 0) {
201 printf(" failed\n ! dhm_read_public returned %d\n\n", ret
);
206 * 7. Derive the shared secret: K = Ys ^ Xc mod P
208 printf("\n . Shared secret: ");
211 if ((ret
= dhm_calc_secret(&dhm
, buf
, &n
)) != 0) {
212 printf(" failed\n ! dhm_calc_secret returned %d\n\n", ret
);
216 for (n
= 0; n
< 16; n
++)
217 printf("%02x", buf
[n
]);
220 * 8. Setup the AES-256 encryption key
222 * This is an overly simplified example; best practice is
223 * to hash the shared secret with a random value to derive
224 * the keying material for the encryption/decryption keys
227 printf("...\n . Encrypting and sending the ciphertext");
230 aes_setkey_enc(&aes
, buf
, 256);
231 memcpy(buf
, PLAINTEXT
, 16);
232 aes_crypt_ecb(&aes
, AES_ENCRYPT
, buf
, buf
);
234 if ((ret
= net_send(&client_fd
, buf
, 16)) != 16) {
235 printf(" failed\n ! net_send returned %d\n\n", ret
);
243 net_close(client_fd
);
248 printf(" + Press Enter to exit this program.\n");