dh_client.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. /*
  2. * Diffie-Hellman-Merkle key exchange (client 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_NAME "localhost"
  78. #define SERVER_PORT "11999"
  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 server_fd;
  100. unsigned char *p, *end;
  101. unsigned char buf[2048];
  102. unsigned char hash[32];
  103. const char *pers = "dh_client";
  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_net_init( &server_fd );
  110. mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, MBEDTLS_MD_SHA256 );
  111. mbedtls_dhm_init( &dhm );
  112. mbedtls_aes_init( &aes );
  113. mbedtls_ctr_drbg_init( &ctr_drbg );
  114. /*
  115. * 1. Setup the RNG
  116. */
  117. mbedtls_printf( "\n . Seeding the random number generator" );
  118. fflush( stdout );
  119. mbedtls_entropy_init( &entropy );
  120. if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
  121. (const unsigned char *) pers,
  122. strlen( pers ) ) ) != 0 )
  123. {
  124. mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret );
  125. goto exit;
  126. }
  127. /*
  128. * 2. Read the server's public RSA key
  129. */
  130. mbedtls_printf( "\n . Reading public key from rsa_pub.txt" );
  131. fflush( stdout );
  132. if( ( f = fopen( "rsa_pub.txt", "rb" ) ) == NULL )
  133. {
  134. mbedtls_printf( " failed\n ! Could not open rsa_pub.txt\n" \
  135. " ! Please run rsa_genkey first\n\n" );
  136. goto exit;
  137. }
  138. mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 );
  139. if( ( ret = mbedtls_mpi_read_file( &rsa.N, 16, f ) ) != 0 ||
  140. ( ret = mbedtls_mpi_read_file( &rsa.E, 16, f ) ) != 0 )
  141. {
  142. mbedtls_printf( " failed\n ! mbedtls_mpi_read_file returned %d\n\n", ret );
  143. fclose( f );
  144. goto exit;
  145. }
  146. rsa.len = ( mbedtls_mpi_bitlen( &rsa.N ) + 7 ) >> 3;
  147. fclose( f );
  148. /*
  149. * 3. Initiate the connection
  150. */
  151. mbedtls_printf( "\n . Connecting to tcp/%s/%s", SERVER_NAME,
  152. SERVER_PORT );
  153. fflush( stdout );
  154. if( ( ret = mbedtls_net_connect( &server_fd, SERVER_NAME,
  155. SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 )
  156. {
  157. mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret );
  158. goto exit;
  159. }
  160. /*
  161. * 4a. First get the buffer length
  162. */
  163. mbedtls_printf( "\n . Receiving the server's DH parameters" );
  164. fflush( stdout );
  165. memset( buf, 0, sizeof( buf ) );
  166. if( ( ret = mbedtls_net_recv( &server_fd, buf, 2 ) ) != 2 )
  167. {
  168. mbedtls_printf( " failed\n ! mbedtls_net_recv returned %d\n\n", ret );
  169. goto exit;
  170. }
  171. n = buflen = ( buf[0] << 8 ) | buf[1];
  172. if( buflen < 1 || buflen > sizeof( buf ) )
  173. {
  174. mbedtls_printf( " failed\n ! Got an invalid buffer length\n\n" );
  175. goto exit;
  176. }
  177. /*
  178. * 4b. Get the DHM parameters: P, G and Ys = G^Xs mod P
  179. */
  180. memset( buf, 0, sizeof( buf ) );
  181. if( ( ret = mbedtls_net_recv( &server_fd, buf, n ) ) != (int) n )
  182. {
  183. mbedtls_printf( " failed\n ! mbedtls_net_recv returned %d\n\n", ret );
  184. goto exit;
  185. }
  186. p = buf, end = buf + buflen;
  187. if( ( ret = mbedtls_dhm_read_params( &dhm, &p, end ) ) != 0 )
  188. {
  189. mbedtls_printf( " failed\n ! mbedtls_dhm_read_params returned %d\n\n", ret );
  190. goto exit;
  191. }
  192. if( dhm.len < 64 || dhm.len > 512 )
  193. {
  194. mbedtls_printf( " failed\n ! Invalid DHM modulus size\n\n" );
  195. goto exit;
  196. }
  197. /*
  198. * 5. Check that the server's RSA signature matches
  199. * the SHA-256 hash of (P,G,Ys)
  200. */
  201. mbedtls_printf( "\n . Verifying the server's RSA signature" );
  202. fflush( stdout );
  203. p += 2;
  204. if( ( n = (size_t) ( end - p ) ) != rsa.len )
  205. {
  206. mbedtls_printf( " failed\n ! Invalid RSA signature size\n\n" );
  207. goto exit;
  208. }
  209. if( ( ret = mbedtls_sha1_ret( buf, (int)( p - 2 - buf ), hash ) ) != 0 )
  210. {
  211. mbedtls_printf( " failed\n ! mbedtls_sha1_ret returned %d\n\n", ret );
  212. goto exit;
  213. }
  214. if( ( ret = mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC,
  215. MBEDTLS_MD_SHA256, 0, hash, p ) ) != 0 )
  216. {
  217. mbedtls_printf( " failed\n ! mbedtls_rsa_pkcs1_verify returned %d\n\n", ret );
  218. goto exit;
  219. }
  220. /*
  221. * 6. Send our public value: Yc = G ^ Xc mod P
  222. */
  223. mbedtls_printf( "\n . Sending own public value to server" );
  224. fflush( stdout );
  225. n = dhm.len;
  226. if( ( ret = mbedtls_dhm_make_public( &dhm, (int) dhm.len, buf, n,
  227. mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
  228. {
  229. mbedtls_printf( " failed\n ! mbedtls_dhm_make_public returned %d\n\n", ret );
  230. goto exit;
  231. }
  232. if( ( ret = mbedtls_net_send( &server_fd, buf, n ) ) != (int) n )
  233. {
  234. mbedtls_printf( " failed\n ! mbedtls_net_send returned %d\n\n", ret );
  235. goto exit;
  236. }
  237. /*
  238. * 7. Derive the shared secret: K = Ys ^ Xc mod P
  239. */
  240. mbedtls_printf( "\n . Shared secret: " );
  241. fflush( stdout );
  242. if( ( ret = mbedtls_dhm_calc_secret( &dhm, buf, sizeof( buf ), &n,
  243. mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
  244. {
  245. mbedtls_printf( " failed\n ! mbedtls_dhm_calc_secret returned %d\n\n", ret );
  246. goto exit;
  247. }
  248. for( n = 0; n < 16; n++ )
  249. mbedtls_printf( "%02x", buf[n] );
  250. /*
  251. * 8. Setup the AES-256 decryption key
  252. *
  253. * This is an overly simplified example; best practice is
  254. * to hash the shared secret with a random value to derive
  255. * the keying material for the encryption/decryption keys,
  256. * IVs and MACs.
  257. */
  258. mbedtls_printf( "...\n . Receiving and decrypting the ciphertext" );
  259. fflush( stdout );
  260. mbedtls_aes_setkey_dec( &aes, buf, 256 );
  261. memset( buf, 0, sizeof( buf ) );
  262. if( ( ret = mbedtls_net_recv( &server_fd, buf, 16 ) ) != 16 )
  263. {
  264. mbedtls_printf( " failed\n ! mbedtls_net_recv returned %d\n\n", ret );
  265. goto exit;
  266. }
  267. mbedtls_aes_crypt_ecb( &aes, MBEDTLS_AES_DECRYPT, buf, buf );
  268. buf[16] = '\0';
  269. mbedtls_printf( "\n . Plaintext is \"%s\"\n\n", (char *) buf );
  270. exit_code = MBEDTLS_EXIT_SUCCESS;
  271. exit:
  272. mbedtls_net_free( &server_fd );
  273. mbedtls_aes_free( &aes );
  274. mbedtls_rsa_free( &rsa );
  275. mbedtls_dhm_free( &dhm );
  276. mbedtls_ctr_drbg_free( &ctr_drbg );
  277. mbedtls_entropy_free( &entropy );
  278. #if defined(_WIN32)
  279. mbedtls_printf( " + Press Enter to exit this program.\n" );
  280. fflush( stdout ); getchar();
  281. #endif
  282. mbedtls_exit( exit_code );
  283. }
  284. #endif /* MBEDTLS_AES_C && MBEDTLS_DHM_C && MBEDTLS_ENTROPY_C &&
  285. MBEDTLS_NET_C && MBEDTLS_RSA_C && MBEDTLS_SHA256_C &&
  286. MBEDTLS_FS_IO && MBEDTLS_CTR_DRBG_C */