dh_server.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. /*
  2. * Diffie-Hellman-Merkle key exchange (server side)
  3. *
  4. * Copyright The Mbed TLS Contributors
  5. * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  6. *
  7. * This file is provided under the Apache License 2.0, or the
  8. * GNU General Public License v2.0 or later.
  9. *
  10. * **********
  11. * Apache License 2.0:
  12. *
  13. * Licensed under the Apache License, Version 2.0 (the "License"); you may
  14. * not use this file except in compliance with the License.
  15. * You may obtain a copy of the License at
  16. *
  17. * http://www.apache.org/licenses/LICENSE-2.0
  18. *
  19. * Unless required by applicable law or agreed to in writing, software
  20. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  21. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  22. * See the License for the specific language governing permissions and
  23. * limitations under the License.
  24. *
  25. * **********
  26. *
  27. * **********
  28. * GNU General Public License v2.0 or later:
  29. *
  30. * This program is free software; you can redistribute it and/or modify
  31. * it under the terms of the GNU General Public License as published by
  32. * the Free Software Foundation; either version 2 of the License, or
  33. * (at your option) any later version.
  34. *
  35. * This program is distributed in the hope that it will be useful,
  36. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  37. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  38. * GNU General Public License for more details.
  39. *
  40. * You should have received a copy of the GNU General Public License along
  41. * with this program; if not, write to the Free Software Foundation, Inc.,
  42. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  43. *
  44. * **********
  45. */
  46. #if !defined(MBEDTLS_CONFIG_FILE)
  47. #include "mbedtls/config.h"
  48. #else
  49. #include MBEDTLS_CONFIG_FILE
  50. #endif
  51. #if defined(MBEDTLS_PLATFORM_C)
  52. #include "mbedtls/platform.h"
  53. #else
  54. #include <stdio.h>
  55. #include <stdlib.h>
  56. #define mbedtls_printf printf
  57. #define mbedtls_time_t time_t
  58. #define mbedtls_exit exit
  59. #define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
  60. #define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
  61. #endif /* MBEDTLS_PLATFORM_C */
  62. #if defined(MBEDTLS_AES_C) && defined(MBEDTLS_DHM_C) && \
  63. defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_NET_C) && \
  64. defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA256_C) && \
  65. defined(MBEDTLS_FS_IO) && defined(MBEDTLS_CTR_DRBG_C) && \
  66. defined(MBEDTLS_SHA1_C)
  67. #include "mbedtls/net_sockets.h"
  68. #include "mbedtls/aes.h"
  69. #include "mbedtls/dhm.h"
  70. #include "mbedtls/rsa.h"
  71. #include "mbedtls/sha1.h"
  72. #include "mbedtls/entropy.h"
  73. #include "mbedtls/ctr_drbg.h"
  74. #include <stdio.h>
  75. #include <string.h>
  76. #endif
  77. #define SERVER_PORT "11999"
  78. #define PLAINTEXT "==Hello there!=="
  79. #if !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_DHM_C) || \
  80. !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NET_C) || \
  81. !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_SHA256_C) || \
  82. !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_CTR_DRBG_C) || \
  83. !defined(MBEDTLS_SHA1_C)
  84. int main( void )
  85. {
  86. mbedtls_printf("MBEDTLS_AES_C and/or MBEDTLS_DHM_C and/or MBEDTLS_ENTROPY_C "
  87. "and/or MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or "
  88. "MBEDTLS_SHA256_C and/or MBEDTLS_FS_IO and/or "
  89. "MBEDTLS_CTR_DRBG_C not defined.\n");
  90. mbedtls_exit( 0 );
  91. }
  92. #else
  93. int main( void )
  94. {
  95. FILE *f;
  96. int ret = 1;
  97. int exit_code = MBEDTLS_EXIT_FAILURE;
  98. size_t n, buflen;
  99. mbedtls_net_context listen_fd, client_fd;
  100. unsigned char buf[2048];
  101. unsigned char hash[32];
  102. unsigned char buf2[2];
  103. const char *pers = "dh_server";
  104. mbedtls_entropy_context entropy;
  105. mbedtls_ctr_drbg_context ctr_drbg;
  106. mbedtls_rsa_context rsa;
  107. mbedtls_dhm_context dhm;
  108. mbedtls_aes_context aes;
  109. mbedtls_mpi N, P, Q, D, E;
  110. mbedtls_net_init( &listen_fd );
  111. mbedtls_net_init( &client_fd );
  112. mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_SHA256 );
  113. mbedtls_dhm_init( &dhm );
  114. mbedtls_aes_init( &aes );
  115. mbedtls_ctr_drbg_init( &ctr_drbg );
  116. mbedtls_mpi_init( &N ); mbedtls_mpi_init( &P ); mbedtls_mpi_init( &Q );
  117. mbedtls_mpi_init( &D ); mbedtls_mpi_init( &E );
  118. /*
  119. * 1. Setup the RNG
  120. */
  121. mbedtls_printf( "\n . Seeding the random number generator" );
  122. fflush( stdout );
  123. mbedtls_entropy_init( &entropy );
  124. if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
  125. (const unsigned char *) pers,
  126. strlen( pers ) ) ) != 0 )
  127. {
  128. mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret );
  129. goto exit;
  130. }
  131. /*
  132. * 2a. Read the server's private RSA key
  133. */
  134. mbedtls_printf( "\n . Reading private key from rsa_priv.txt" );
  135. fflush( stdout );
  136. if( ( f = fopen( "rsa_priv.txt", "rb" ) ) == NULL )
  137. {
  138. mbedtls_printf( " failed\n ! Could not open rsa_priv.txt\n" \
  139. " ! Please run rsa_genkey first\n\n" );
  140. goto exit;
  141. }
  142. mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 );
  143. if( ( ret = mbedtls_mpi_read_file( &N , 16, f ) ) != 0 ||
  144. ( ret = mbedtls_mpi_read_file( &E , 16, f ) ) != 0 ||
  145. ( ret = mbedtls_mpi_read_file( &D , 16, f ) ) != 0 ||
  146. ( ret = mbedtls_mpi_read_file( &P , 16, f ) ) != 0 ||
  147. ( ret = mbedtls_mpi_read_file( &Q , 16, f ) ) != 0 )
  148. {
  149. mbedtls_printf( " failed\n ! mbedtls_mpi_read_file returned %d\n\n",
  150. ret );
  151. fclose( f );
  152. goto exit;
  153. }
  154. fclose( f );
  155. if( ( ret = mbedtls_rsa_import( &rsa, &N, &P, &Q, &D, &E ) ) != 0 )
  156. {
  157. mbedtls_printf( " failed\n ! mbedtls_rsa_import returned %d\n\n",
  158. ret );
  159. goto exit;
  160. }
  161. if( ( ret = mbedtls_rsa_complete( &rsa ) ) != 0 )
  162. {
  163. mbedtls_printf( " failed\n ! mbedtls_rsa_complete returned %d\n\n",
  164. ret );
  165. goto exit;
  166. }
  167. /*
  168. * 2b. Get the DHM modulus and generator
  169. */
  170. mbedtls_printf( "\n . Reading DH parameters from dh_prime.txt" );
  171. fflush( stdout );
  172. if( ( f = fopen( "dh_prime.txt", "rb" ) ) == NULL )
  173. {
  174. mbedtls_printf( " failed\n ! Could not open dh_prime.txt\n" \
  175. " ! Please run dh_genprime first\n\n" );
  176. goto exit;
  177. }
  178. if( mbedtls_mpi_read_file( &dhm.P, 16, f ) != 0 ||
  179. mbedtls_mpi_read_file( &dhm.G, 16, f ) != 0 )
  180. {
  181. mbedtls_printf( " failed\n ! Invalid DH parameter file\n\n" );
  182. fclose( f );
  183. goto exit;
  184. }
  185. fclose( f );
  186. /*
  187. * 3. Wait for a client to connect
  188. */
  189. mbedtls_printf( "\n . Waiting for a remote connection" );
  190. fflush( stdout );
  191. if( ( ret = mbedtls_net_bind( &listen_fd, NULL, SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 )
  192. {
  193. mbedtls_printf( " failed\n ! mbedtls_net_bind returned %d\n\n", ret );
  194. goto exit;
  195. }
  196. if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd,
  197. NULL, 0, NULL ) ) != 0 )
  198. {
  199. mbedtls_printf( " failed\n ! mbedtls_net_accept returned %d\n\n", ret );
  200. goto exit;
  201. }
  202. /*
  203. * 4. Setup the DH parameters (P,G,Ys)
  204. */
  205. mbedtls_printf( "\n . Sending the server's DH parameters" );
  206. fflush( stdout );
  207. memset( buf, 0, sizeof( buf ) );
  208. if( ( ret = mbedtls_dhm_make_params( &dhm, (int) mbedtls_mpi_size( &dhm.P ), buf, &n,
  209. mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
  210. {
  211. mbedtls_printf( " failed\n ! mbedtls_dhm_make_params returned %d\n\n", ret );
  212. goto exit;
  213. }
  214. /*
  215. * 5. Sign the parameters and send them
  216. */
  217. if( ( ret = mbedtls_sha1_ret( buf, n, hash ) ) != 0 )
  218. {
  219. mbedtls_printf( " failed\n ! mbedtls_sha1_ret returned %d\n\n", ret );
  220. goto exit;
  221. }
  222. buf[n ] = (unsigned char)( rsa.len >> 8 );
  223. buf[n + 1] = (unsigned char)( rsa.len );
  224. if( ( ret = mbedtls_rsa_pkcs1_sign( &rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA256,
  225. 0, hash, buf + n + 2 ) ) != 0 )
  226. {
  227. mbedtls_printf( " failed\n ! mbedtls_rsa_pkcs1_sign returned %d\n\n", ret );
  228. goto exit;
  229. }
  230. buflen = n + 2 + rsa.len;
  231. buf2[0] = (unsigned char)( buflen >> 8 );
  232. buf2[1] = (unsigned char)( buflen );
  233. if( ( ret = mbedtls_net_send( &client_fd, buf2, 2 ) ) != 2 ||
  234. ( ret = mbedtls_net_send( &client_fd, buf, buflen ) ) != (int) buflen )
  235. {
  236. mbedtls_printf( " failed\n ! mbedtls_net_send returned %d\n\n", ret );
  237. goto exit;
  238. }
  239. /*
  240. * 6. Get the client's public value: Yc = G ^ Xc mod P
  241. */
  242. mbedtls_printf( "\n . Receiving the client's public value" );
  243. fflush( stdout );
  244. memset( buf, 0, sizeof( buf ) );
  245. n = dhm.len;
  246. if( ( ret = mbedtls_net_recv( &client_fd, buf, n ) ) != (int) n )
  247. {
  248. mbedtls_printf( " failed\n ! mbedtls_net_recv returned %d\n\n", ret );
  249. goto exit;
  250. }
  251. if( ( ret = mbedtls_dhm_read_public( &dhm, buf, dhm.len ) ) != 0 )
  252. {
  253. mbedtls_printf( " failed\n ! mbedtls_dhm_read_public returned %d\n\n", ret );
  254. goto exit;
  255. }
  256. /*
  257. * 7. Derive the shared secret: K = Ys ^ Xc mod P
  258. */
  259. mbedtls_printf( "\n . Shared secret: " );
  260. fflush( stdout );
  261. if( ( ret = mbedtls_dhm_calc_secret( &dhm, buf, sizeof( buf ), &n,
  262. mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
  263. {
  264. mbedtls_printf( " failed\n ! mbedtls_dhm_calc_secret returned %d\n\n", ret );
  265. goto exit;
  266. }
  267. for( n = 0; n < 16; n++ )
  268. mbedtls_printf( "%02x", buf[n] );
  269. /*
  270. * 8. Setup the AES-256 encryption key
  271. *
  272. * This is an overly simplified example; best practice is
  273. * to hash the shared secret with a random value to derive
  274. * the keying material for the encryption/decryption keys
  275. * and MACs.
  276. */
  277. mbedtls_printf( "...\n . Encrypting and sending the ciphertext" );
  278. fflush( stdout );
  279. mbedtls_aes_setkey_enc( &aes, buf, 256 );
  280. memcpy( buf, PLAINTEXT, 16 );
  281. mbedtls_aes_crypt_ecb( &aes, MBEDTLS_AES_ENCRYPT, buf, buf );
  282. if( ( ret = mbedtls_net_send( &client_fd, buf, 16 ) ) != 16 )
  283. {
  284. mbedtls_printf( " failed\n ! mbedtls_net_send returned %d\n\n", ret );
  285. goto exit;
  286. }
  287. mbedtls_printf( "\n\n" );
  288. exit_code = MBEDTLS_EXIT_SUCCESS;
  289. exit:
  290. mbedtls_mpi_free( &N ); mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q );
  291. mbedtls_mpi_free( &D ); mbedtls_mpi_free( &E );
  292. mbedtls_net_free( &client_fd );
  293. mbedtls_net_free( &listen_fd );
  294. mbedtls_aes_free( &aes );
  295. mbedtls_rsa_free( &rsa );
  296. mbedtls_dhm_free( &dhm );
  297. mbedtls_ctr_drbg_free( &ctr_drbg );
  298. mbedtls_entropy_free( &entropy );
  299. #if defined(_WIN32)
  300. mbedtls_printf( " + Press Enter to exit this program.\n" );
  301. fflush( stdout ); getchar();
  302. #endif
  303. mbedtls_exit( exit_code );
  304. }
  305. #endif /* MBEDTLS_AES_C && MBEDTLS_DHM_C && MBEDTLS_ENTROPY_C &&
  306. MBEDTLS_NET_C && MBEDTLS_RSA_C && MBEDTLS_SHA256_C &&
  307. MBEDTLS_FS_IO && MBEDTLS_CTR_DRBG_C */