cert_app.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. /*
  2. * Certificate reading application
  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_time time
  57. #define mbedtls_time_t time_t
  58. #define mbedtls_fprintf fprintf
  59. #define mbedtls_printf printf
  60. #define mbedtls_exit exit
  61. #define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
  62. #define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
  63. #endif /* MBEDTLS_PLATFORM_C */
  64. #if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) || \
  65. !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_CLI_C) || \
  66. !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_RSA_C) || \
  67. !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO) || \
  68. !defined(MBEDTLS_CTR_DRBG_C)
  69. int main( void )
  70. {
  71. mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C and/or "
  72. "MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_CLI_C and/or "
  73. "MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or "
  74. "MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_FS_IO and/or "
  75. "MBEDTLS_CTR_DRBG_C not defined.\n");
  76. mbedtls_exit( 0 );
  77. }
  78. #else
  79. #include "mbedtls/entropy.h"
  80. #include "mbedtls/ctr_drbg.h"
  81. #include "mbedtls/net_sockets.h"
  82. #include "mbedtls/ssl.h"
  83. #include "mbedtls/x509.h"
  84. #include "mbedtls/debug.h"
  85. #include <stdio.h>
  86. #include <stdlib.h>
  87. #include <string.h>
  88. #define MODE_NONE 0
  89. #define MODE_FILE 1
  90. #define MODE_SSL 2
  91. #define DFL_MODE MODE_NONE
  92. #define DFL_FILENAME "cert.crt"
  93. #define DFL_CA_FILE ""
  94. #define DFL_CRL_FILE ""
  95. #define DFL_CA_PATH ""
  96. #define DFL_SERVER_NAME "localhost"
  97. #define DFL_SERVER_PORT "4433"
  98. #define DFL_DEBUG_LEVEL 0
  99. #define DFL_PERMISSIVE 0
  100. #define USAGE_IO \
  101. " ca_file=%%s The single file containing the top-level CA(s) you fully trust\n" \
  102. " default: \"\" (none)\n" \
  103. " crl_file=%%s The single CRL file you want to use\n" \
  104. " default: \"\" (none)\n" \
  105. " ca_path=%%s The path containing the top-level CA(s) you fully trust\n" \
  106. " default: \"\" (none) (overrides ca_file)\n"
  107. #define USAGE \
  108. "\n usage: cert_app param=<>...\n" \
  109. "\n acceptable parameters:\n" \
  110. " mode=file|ssl default: none\n" \
  111. " filename=%%s default: cert.crt\n" \
  112. USAGE_IO \
  113. " server_name=%%s default: localhost\n" \
  114. " server_port=%%d default: 4433\n" \
  115. " debug_level=%%d default: 0 (disabled)\n" \
  116. " permissive=%%d default: 0 (disabled)\n" \
  117. "\n"
  118. /*
  119. * global options
  120. */
  121. struct options
  122. {
  123. int mode; /* the mode to run the application in */
  124. const char *filename; /* filename of the certificate file */
  125. const char *ca_file; /* the file with the CA certificate(s) */
  126. const char *crl_file; /* the file with the CRL to use */
  127. const char *ca_path; /* the path with the CA certificate(s) reside */
  128. const char *server_name; /* hostname of the server (client only) */
  129. const char *server_port; /* port on which the ssl service runs */
  130. int debug_level; /* level of debugging */
  131. int permissive; /* permissive parsing */
  132. } opt;
  133. static void my_debug( void *ctx, int level,
  134. const char *file, int line,
  135. const char *str )
  136. {
  137. ((void) level);
  138. mbedtls_fprintf( (FILE *) ctx, "%s:%04d: %s", file, line, str );
  139. fflush( (FILE *) ctx );
  140. }
  141. static int my_verify( void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags )
  142. {
  143. char buf[1024];
  144. ((void) data);
  145. mbedtls_printf( "\nVerify requested for (Depth %d):\n", depth );
  146. mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt );
  147. mbedtls_printf( "%s", buf );
  148. if ( ( *flags ) == 0 )
  149. mbedtls_printf( " This certificate has no flags\n" );
  150. else
  151. {
  152. mbedtls_x509_crt_verify_info( buf, sizeof( buf ), " ! ", *flags );
  153. mbedtls_printf( "%s\n", buf );
  154. }
  155. return( 0 );
  156. }
  157. int main( int argc, char *argv[] )
  158. {
  159. int ret = 1;
  160. int exit_code = MBEDTLS_EXIT_FAILURE;
  161. mbedtls_net_context server_fd;
  162. unsigned char buf[1024];
  163. mbedtls_entropy_context entropy;
  164. mbedtls_ctr_drbg_context ctr_drbg;
  165. mbedtls_ssl_context ssl;
  166. mbedtls_ssl_config conf;
  167. mbedtls_x509_crt cacert;
  168. mbedtls_x509_crl cacrl;
  169. int i, j;
  170. uint32_t flags;
  171. int verify = 0;
  172. char *p, *q;
  173. const char *pers = "cert_app";
  174. /*
  175. * Set to sane values
  176. */
  177. mbedtls_net_init( &server_fd );
  178. mbedtls_ctr_drbg_init( &ctr_drbg );
  179. mbedtls_ssl_init( &ssl );
  180. mbedtls_ssl_config_init( &conf );
  181. mbedtls_x509_crt_init( &cacert );
  182. #if defined(MBEDTLS_X509_CRL_PARSE_C)
  183. mbedtls_x509_crl_init( &cacrl );
  184. #else
  185. /* Zeroize structure as CRL parsing is not supported and we have to pass
  186. it to the verify function */
  187. memset( &cacrl, 0, sizeof(mbedtls_x509_crl) );
  188. #endif
  189. if( argc == 0 )
  190. {
  191. usage:
  192. mbedtls_printf( USAGE );
  193. goto exit;
  194. }
  195. opt.mode = DFL_MODE;
  196. opt.filename = DFL_FILENAME;
  197. opt.ca_file = DFL_CA_FILE;
  198. opt.crl_file = DFL_CRL_FILE;
  199. opt.ca_path = DFL_CA_PATH;
  200. opt.server_name = DFL_SERVER_NAME;
  201. opt.server_port = DFL_SERVER_PORT;
  202. opt.debug_level = DFL_DEBUG_LEVEL;
  203. opt.permissive = DFL_PERMISSIVE;
  204. for( i = 1; i < argc; i++ )
  205. {
  206. p = argv[i];
  207. if( ( q = strchr( p, '=' ) ) == NULL )
  208. goto usage;
  209. *q++ = '\0';
  210. for( j = 0; p + j < q; j++ )
  211. {
  212. if( argv[i][j] >= 'A' && argv[i][j] <= 'Z' )
  213. argv[i][j] |= 0x20;
  214. }
  215. if( strcmp( p, "mode" ) == 0 )
  216. {
  217. if( strcmp( q, "file" ) == 0 )
  218. opt.mode = MODE_FILE;
  219. else if( strcmp( q, "ssl" ) == 0 )
  220. opt.mode = MODE_SSL;
  221. else
  222. goto usage;
  223. }
  224. else if( strcmp( p, "filename" ) == 0 )
  225. opt.filename = q;
  226. else if( strcmp( p, "ca_file" ) == 0 )
  227. opt.ca_file = q;
  228. else if( strcmp( p, "crl_file" ) == 0 )
  229. opt.crl_file = q;
  230. else if( strcmp( p, "ca_path" ) == 0 )
  231. opt.ca_path = q;
  232. else if( strcmp( p, "server_name" ) == 0 )
  233. opt.server_name = q;
  234. else if( strcmp( p, "server_port" ) == 0 )
  235. opt.server_port = q;
  236. else if( strcmp( p, "debug_level" ) == 0 )
  237. {
  238. opt.debug_level = atoi( q );
  239. if( opt.debug_level < 0 || opt.debug_level > 65535 )
  240. goto usage;
  241. }
  242. else if( strcmp( p, "permissive" ) == 0 )
  243. {
  244. opt.permissive = atoi( q );
  245. if( opt.permissive < 0 || opt.permissive > 1 )
  246. goto usage;
  247. }
  248. else
  249. goto usage;
  250. }
  251. /*
  252. * 1.1. Load the trusted CA
  253. */
  254. mbedtls_printf( " . Loading the CA root certificate ..." );
  255. fflush( stdout );
  256. if( strlen( opt.ca_path ) )
  257. {
  258. if( ( ret = mbedtls_x509_crt_parse_path( &cacert, opt.ca_path ) ) < 0 )
  259. {
  260. mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse_path returned -0x%x\n\n", -ret );
  261. goto exit;
  262. }
  263. verify = 1;
  264. }
  265. else if( strlen( opt.ca_file ) )
  266. {
  267. if( ( ret = mbedtls_x509_crt_parse_file( &cacert, opt.ca_file ) ) < 0 )
  268. {
  269. mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse_file returned -0x%x\n\n", -ret );
  270. goto exit;
  271. }
  272. verify = 1;
  273. }
  274. mbedtls_printf( " ok (%d skipped)\n", ret );
  275. #if defined(MBEDTLS_X509_CRL_PARSE_C)
  276. if( strlen( opt.crl_file ) )
  277. {
  278. if( ( ret = mbedtls_x509_crl_parse_file( &cacrl, opt.crl_file ) ) != 0 )
  279. {
  280. mbedtls_printf( " failed\n ! mbedtls_x509_crl_parse returned -0x%x\n\n", -ret );
  281. goto exit;
  282. }
  283. verify = 1;
  284. }
  285. #endif
  286. if( opt.mode == MODE_FILE )
  287. {
  288. mbedtls_x509_crt crt;
  289. mbedtls_x509_crt *cur = &crt;
  290. mbedtls_x509_crt_init( &crt );
  291. /*
  292. * 1.1. Load the certificate(s)
  293. */
  294. mbedtls_printf( "\n . Loading the certificate(s) ..." );
  295. fflush( stdout );
  296. ret = mbedtls_x509_crt_parse_file( &crt, opt.filename );
  297. if( ret < 0 )
  298. {
  299. mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse_file returned %d\n\n", ret );
  300. mbedtls_x509_crt_free( &crt );
  301. goto exit;
  302. }
  303. if( opt.permissive == 0 && ret > 0 )
  304. {
  305. mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse failed to parse %d certificates\n\n", ret );
  306. mbedtls_x509_crt_free( &crt );
  307. goto exit;
  308. }
  309. mbedtls_printf( " ok\n" );
  310. /*
  311. * 1.2 Print the certificate(s)
  312. */
  313. while( cur != NULL )
  314. {
  315. mbedtls_printf( " . Peer certificate information ...\n" );
  316. ret = mbedtls_x509_crt_info( (char *) buf, sizeof( buf ) - 1, " ",
  317. cur );
  318. if( ret == -1 )
  319. {
  320. mbedtls_printf( " failed\n ! mbedtls_x509_crt_info returned %d\n\n", ret );
  321. mbedtls_x509_crt_free( &crt );
  322. goto exit;
  323. }
  324. mbedtls_printf( "%s\n", buf );
  325. cur = cur->next;
  326. }
  327. /*
  328. * 1.3 Verify the certificate
  329. */
  330. if( verify )
  331. {
  332. mbedtls_printf( " . Verifying X.509 certificate..." );
  333. if( ( ret = mbedtls_x509_crt_verify( &crt, &cacert, &cacrl, NULL, &flags,
  334. my_verify, NULL ) ) != 0 )
  335. {
  336. char vrfy_buf[512];
  337. mbedtls_printf( " failed\n" );
  338. mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags );
  339. mbedtls_printf( "%s\n", vrfy_buf );
  340. }
  341. else
  342. mbedtls_printf( " ok\n" );
  343. }
  344. mbedtls_x509_crt_free( &crt );
  345. }
  346. else if( opt.mode == MODE_SSL )
  347. {
  348. /*
  349. * 1. Initialize the RNG and the session data
  350. */
  351. mbedtls_printf( "\n . Seeding the random number generator..." );
  352. fflush( stdout );
  353. mbedtls_entropy_init( &entropy );
  354. if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
  355. (const unsigned char *) pers,
  356. strlen( pers ) ) ) != 0 )
  357. {
  358. mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret );
  359. goto ssl_exit;
  360. }
  361. mbedtls_printf( " ok\n" );
  362. #if defined(MBEDTLS_DEBUG_C)
  363. mbedtls_debug_set_threshold( opt.debug_level );
  364. #endif
  365. /*
  366. * 2. Start the connection
  367. */
  368. mbedtls_printf( " . SSL connection to tcp/%s/%s...", opt.server_name,
  369. opt.server_port );
  370. fflush( stdout );
  371. if( ( ret = mbedtls_net_connect( &server_fd, opt.server_name,
  372. opt.server_port, MBEDTLS_NET_PROTO_TCP ) ) != 0 )
  373. {
  374. mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret );
  375. goto ssl_exit;
  376. }
  377. /*
  378. * 3. Setup stuff
  379. */
  380. if( ( ret = mbedtls_ssl_config_defaults( &conf,
  381. MBEDTLS_SSL_IS_CLIENT,
  382. MBEDTLS_SSL_TRANSPORT_STREAM,
  383. MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
  384. {
  385. mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret );
  386. goto exit;
  387. }
  388. if( verify )
  389. {
  390. mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_REQUIRED );
  391. mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL );
  392. mbedtls_ssl_conf_verify( &conf, my_verify, NULL );
  393. }
  394. else
  395. mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_NONE );
  396. mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
  397. mbedtls_ssl_conf_dbg( &conf, my_debug, stdout );
  398. if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 )
  399. {
  400. mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret );
  401. goto ssl_exit;
  402. }
  403. if( ( ret = mbedtls_ssl_set_hostname( &ssl, opt.server_name ) ) != 0 )
  404. {
  405. mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret );
  406. goto ssl_exit;
  407. }
  408. mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL );
  409. /*
  410. * 4. Handshake
  411. */
  412. while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 )
  413. {
  414. if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
  415. {
  416. mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned %d\n\n", ret );
  417. goto ssl_exit;
  418. }
  419. }
  420. mbedtls_printf( " ok\n" );
  421. /*
  422. * 5. Print the certificate
  423. */
  424. mbedtls_printf( " . Peer certificate information ...\n" );
  425. ret = mbedtls_x509_crt_info( (char *) buf, sizeof( buf ) - 1, " ",
  426. ssl.session->peer_cert );
  427. if( ret == -1 )
  428. {
  429. mbedtls_printf( " failed\n ! mbedtls_x509_crt_info returned %d\n\n", ret );
  430. goto ssl_exit;
  431. }
  432. mbedtls_printf( "%s\n", buf );
  433. mbedtls_ssl_close_notify( &ssl );
  434. ssl_exit:
  435. mbedtls_ssl_free( &ssl );
  436. mbedtls_ssl_config_free( &conf );
  437. }
  438. else
  439. goto usage;
  440. exit_code = MBEDTLS_EXIT_SUCCESS;
  441. exit:
  442. mbedtls_net_free( &server_fd );
  443. mbedtls_x509_crt_free( &cacert );
  444. #if defined(MBEDTLS_X509_CRL_PARSE_C)
  445. mbedtls_x509_crl_free( &cacrl );
  446. #endif
  447. mbedtls_ctr_drbg_free( &ctr_drbg );
  448. mbedtls_entropy_free( &entropy );
  449. #if defined(_WIN32)
  450. mbedtls_printf( " + Press Enter to exit this program.\n" );
  451. fflush( stdout ); getchar();
  452. #endif
  453. mbedtls_exit( exit_code );
  454. }
  455. #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C &&
  456. MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C &&
  457. MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_FS_IO && MBEDTLS_CTR_DRBG_C */