dh_server.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. /*
  2. * Diffie-Hellman-Merkle key exchange (server side)
  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. #include "mbedtls/build_info.h"
  20. #include "mbedtls/platform.h"
  21. #if defined(MBEDTLS_AES_C) && defined(MBEDTLS_DHM_C) && \
  22. defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_NET_C) && \
  23. defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA256_C) && \
  24. defined(MBEDTLS_FS_IO) && defined(MBEDTLS_CTR_DRBG_C) && \
  25. defined(MBEDTLS_SHA1_C)
  26. #include "mbedtls/net_sockets.h"
  27. #include "mbedtls/aes.h"
  28. #include "mbedtls/dhm.h"
  29. #include "mbedtls/rsa.h"
  30. #include "mbedtls/sha1.h"
  31. #include "mbedtls/entropy.h"
  32. #include "mbedtls/ctr_drbg.h"
  33. #include <stdio.h>
  34. #include <string.h>
  35. #endif
  36. #define SERVER_PORT "11999"
  37. #define PLAINTEXT "==Hello there!=="
  38. #if !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_DHM_C) || \
  39. !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NET_C) || \
  40. !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_SHA256_C) || \
  41. !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_CTR_DRBG_C) || \
  42. !defined(MBEDTLS_SHA1_C)
  43. int main(void)
  44. {
  45. mbedtls_printf("MBEDTLS_AES_C and/or MBEDTLS_DHM_C and/or MBEDTLS_ENTROPY_C "
  46. "and/or MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or "
  47. "MBEDTLS_SHA256_C and/or MBEDTLS_FS_IO and/or "
  48. "MBEDTLS_CTR_DRBG_C not defined.\n");
  49. mbedtls_exit(0);
  50. }
  51. #else
  52. int main(void)
  53. {
  54. FILE *f;
  55. int ret = 1;
  56. int exit_code = MBEDTLS_EXIT_FAILURE;
  57. size_t n, buflen;
  58. mbedtls_net_context listen_fd, client_fd;
  59. unsigned char buf[2048];
  60. unsigned char hash[32];
  61. unsigned char buf2[2];
  62. const char *pers = "dh_server";
  63. mbedtls_entropy_context entropy;
  64. mbedtls_ctr_drbg_context ctr_drbg;
  65. mbedtls_rsa_context rsa;
  66. mbedtls_dhm_context dhm;
  67. mbedtls_aes_context aes;
  68. mbedtls_mpi N, P, Q, D, E;
  69. mbedtls_net_init(&listen_fd);
  70. mbedtls_net_init(&client_fd);
  71. mbedtls_dhm_init(&dhm);
  72. mbedtls_aes_init(&aes);
  73. mbedtls_ctr_drbg_init(&ctr_drbg);
  74. mbedtls_mpi_init(&N); mbedtls_mpi_init(&P); mbedtls_mpi_init(&Q);
  75. mbedtls_mpi_init(&D); mbedtls_mpi_init(&E);
  76. /*
  77. * 1. Setup the RNG
  78. */
  79. mbedtls_printf("\n . Seeding the random number generator");
  80. fflush(stdout);
  81. mbedtls_entropy_init(&entropy);
  82. if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
  83. (const unsigned char *) pers,
  84. strlen(pers))) != 0) {
  85. mbedtls_printf(" failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret);
  86. goto exit;
  87. }
  88. /*
  89. * 2a. Read the server's private RSA key
  90. */
  91. mbedtls_printf("\n . Reading private key from rsa_priv.txt");
  92. fflush(stdout);
  93. if ((f = fopen("rsa_priv.txt", "rb")) == NULL) {
  94. mbedtls_printf(" failed\n ! Could not open rsa_priv.txt\n" \
  95. " ! Please run rsa_genkey first\n\n");
  96. goto exit;
  97. }
  98. mbedtls_rsa_init(&rsa);
  99. if ((ret = mbedtls_mpi_read_file(&N, 16, f)) != 0 ||
  100. (ret = mbedtls_mpi_read_file(&E, 16, f)) != 0 ||
  101. (ret = mbedtls_mpi_read_file(&D, 16, f)) != 0 ||
  102. (ret = mbedtls_mpi_read_file(&P, 16, f)) != 0 ||
  103. (ret = mbedtls_mpi_read_file(&Q, 16, f)) != 0) {
  104. mbedtls_printf(" failed\n ! mbedtls_mpi_read_file returned %d\n\n",
  105. ret);
  106. fclose(f);
  107. goto exit;
  108. }
  109. fclose(f);
  110. if ((ret = mbedtls_rsa_import(&rsa, &N, &P, &Q, &D, &E)) != 0) {
  111. mbedtls_printf(" failed\n ! mbedtls_rsa_import returned %d\n\n",
  112. ret);
  113. goto exit;
  114. }
  115. if ((ret = mbedtls_rsa_complete(&rsa)) != 0) {
  116. mbedtls_printf(" failed\n ! mbedtls_rsa_complete returned %d\n\n",
  117. ret);
  118. goto exit;
  119. }
  120. /*
  121. * 2b. Get the DHM modulus and generator
  122. */
  123. mbedtls_printf("\n . Reading DH parameters from dh_prime.txt");
  124. fflush(stdout);
  125. if ((f = fopen("dh_prime.txt", "rb")) == NULL) {
  126. mbedtls_printf(" failed\n ! Could not open dh_prime.txt\n" \
  127. " ! Please run dh_genprime first\n\n");
  128. goto exit;
  129. }
  130. if (mbedtls_mpi_read_file(&dhm.MBEDTLS_PRIVATE(P), 16, f) != 0 ||
  131. mbedtls_mpi_read_file(&dhm.MBEDTLS_PRIVATE(G), 16, f) != 0) {
  132. mbedtls_printf(" failed\n ! Invalid DH parameter file\n\n");
  133. fclose(f);
  134. goto exit;
  135. }
  136. fclose(f);
  137. /*
  138. * 3. Wait for a client to connect
  139. */
  140. mbedtls_printf("\n . Waiting for a remote connection");
  141. fflush(stdout);
  142. if ((ret = mbedtls_net_bind(&listen_fd, NULL, SERVER_PORT, MBEDTLS_NET_PROTO_TCP)) != 0) {
  143. mbedtls_printf(" failed\n ! mbedtls_net_bind returned %d\n\n", ret);
  144. goto exit;
  145. }
  146. if ((ret = mbedtls_net_accept(&listen_fd, &client_fd,
  147. NULL, 0, NULL)) != 0) {
  148. mbedtls_printf(" failed\n ! mbedtls_net_accept returned %d\n\n", ret);
  149. goto exit;
  150. }
  151. /*
  152. * 4. Setup the DH parameters (P,G,Ys)
  153. */
  154. mbedtls_printf("\n . Sending the server's DH parameters");
  155. fflush(stdout);
  156. memset(buf, 0, sizeof(buf));
  157. if ((ret =
  158. mbedtls_dhm_make_params(&dhm, (int) mbedtls_mpi_size(&dhm.MBEDTLS_PRIVATE(P)), buf, &n,
  159. mbedtls_ctr_drbg_random, &ctr_drbg)) != 0) {
  160. mbedtls_printf(" failed\n ! mbedtls_dhm_make_params returned %d\n\n", ret);
  161. goto exit;
  162. }
  163. /*
  164. * 5. Sign the parameters and send them
  165. */
  166. if ((ret = mbedtls_sha1(buf, n, hash)) != 0) {
  167. mbedtls_printf(" failed\n ! mbedtls_sha1 returned %d\n\n", ret);
  168. goto exit;
  169. }
  170. buf[n] = (unsigned char) (rsa.MBEDTLS_PRIVATE(len) >> 8);
  171. buf[n + 1] = (unsigned char) (rsa.MBEDTLS_PRIVATE(len));
  172. if ((ret = mbedtls_rsa_pkcs1_sign(&rsa, NULL, NULL, MBEDTLS_MD_SHA256,
  173. 32, hash, buf + n + 2)) != 0) {
  174. mbedtls_printf(" failed\n ! mbedtls_rsa_pkcs1_sign returned %d\n\n", ret);
  175. goto exit;
  176. }
  177. buflen = n + 2 + rsa.MBEDTLS_PRIVATE(len);
  178. buf2[0] = (unsigned char) (buflen >> 8);
  179. buf2[1] = (unsigned char) (buflen);
  180. if ((ret = mbedtls_net_send(&client_fd, buf2, 2)) != 2 ||
  181. (ret = mbedtls_net_send(&client_fd, buf, buflen)) != (int) buflen) {
  182. mbedtls_printf(" failed\n ! mbedtls_net_send returned %d\n\n", ret);
  183. goto exit;
  184. }
  185. /*
  186. * 6. Get the client's public value: Yc = G ^ Xc mod P
  187. */
  188. mbedtls_printf("\n . Receiving the client's public value");
  189. fflush(stdout);
  190. memset(buf, 0, sizeof(buf));
  191. n = mbedtls_dhm_get_len(&dhm);
  192. if ((ret = mbedtls_net_recv(&client_fd, buf, n)) != (int) n) {
  193. mbedtls_printf(" failed\n ! mbedtls_net_recv returned %d\n\n", ret);
  194. goto exit;
  195. }
  196. if ((ret = mbedtls_dhm_read_public(&dhm, buf, n)) != 0) {
  197. mbedtls_printf(" failed\n ! mbedtls_dhm_read_public returned %d\n\n", ret);
  198. goto exit;
  199. }
  200. /*
  201. * 7. Derive the shared secret: K = Ys ^ Xc mod P
  202. */
  203. mbedtls_printf("\n . Shared secret: ");
  204. fflush(stdout);
  205. if ((ret = mbedtls_dhm_calc_secret(&dhm, buf, sizeof(buf), &n,
  206. mbedtls_ctr_drbg_random, &ctr_drbg)) != 0) {
  207. mbedtls_printf(" failed\n ! mbedtls_dhm_calc_secret returned %d\n\n", ret);
  208. goto exit;
  209. }
  210. for (n = 0; n < 16; n++) {
  211. mbedtls_printf("%02x", buf[n]);
  212. }
  213. /*
  214. * 8. Setup the AES-256 encryption key
  215. *
  216. * This is an overly simplified example; best practice is
  217. * to hash the shared secret with a random value to derive
  218. * the keying material for the encryption/decryption keys
  219. * and MACs.
  220. */
  221. mbedtls_printf("...\n . Encrypting and sending the ciphertext");
  222. fflush(stdout);
  223. ret = mbedtls_aes_setkey_enc(&aes, buf, 256);
  224. if (ret != 0) {
  225. goto exit;
  226. }
  227. memcpy(buf, PLAINTEXT, 16);
  228. ret = mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_ENCRYPT, buf, buf);
  229. if (ret != 0) {
  230. goto exit;
  231. }
  232. if ((ret = mbedtls_net_send(&client_fd, buf, 16)) != 16) {
  233. mbedtls_printf(" failed\n ! mbedtls_net_send returned %d\n\n", ret);
  234. goto exit;
  235. }
  236. mbedtls_printf("\n\n");
  237. exit_code = MBEDTLS_EXIT_SUCCESS;
  238. exit:
  239. mbedtls_mpi_free(&N); mbedtls_mpi_free(&P); mbedtls_mpi_free(&Q);
  240. mbedtls_mpi_free(&D); mbedtls_mpi_free(&E);
  241. mbedtls_net_free(&client_fd);
  242. mbedtls_net_free(&listen_fd);
  243. mbedtls_aes_free(&aes);
  244. mbedtls_rsa_free(&rsa);
  245. mbedtls_dhm_free(&dhm);
  246. mbedtls_ctr_drbg_free(&ctr_drbg);
  247. mbedtls_entropy_free(&entropy);
  248. mbedtls_exit(exit_code);
  249. }
  250. #endif /* MBEDTLS_AES_C && MBEDTLS_DHM_C && MBEDTLS_ENTROPY_C &&
  251. MBEDTLS_NET_C && MBEDTLS_RSA_C && MBEDTLS_SHA256_C &&
  252. MBEDTLS_FS_IO && MBEDTLS_CTR_DRBG_C */