1a8e1175bSopenharmony_ci/* 2a8e1175bSopenharmony_ci * SSL client demonstration program 3a8e1175bSopenharmony_ci * 4a8e1175bSopenharmony_ci * Copyright The Mbed TLS Contributors 5a8e1175bSopenharmony_ci * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6a8e1175bSopenharmony_ci */ 7a8e1175bSopenharmony_ci 8a8e1175bSopenharmony_ci#include "mbedtls/build_info.h" 9a8e1175bSopenharmony_ci 10a8e1175bSopenharmony_ci#include "mbedtls/platform.h" 11a8e1175bSopenharmony_ci 12a8e1175bSopenharmony_ci#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) || \ 13a8e1175bSopenharmony_ci !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_CLI_C) || \ 14a8e1175bSopenharmony_ci !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_RSA_C) || \ 15a8e1175bSopenharmony_ci !defined(MBEDTLS_PEM_PARSE_C) || !defined(MBEDTLS_CTR_DRBG_C) || \ 16a8e1175bSopenharmony_ci !defined(MBEDTLS_X509_CRT_PARSE_C) 17a8e1175bSopenharmony_ciint main(void) 18a8e1175bSopenharmony_ci{ 19a8e1175bSopenharmony_ci mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C and/or " 20a8e1175bSopenharmony_ci "MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_CLI_C and/or " 21a8e1175bSopenharmony_ci "MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or " 22a8e1175bSopenharmony_ci "MBEDTLS_CTR_DRBG_C and/or MBEDTLS_X509_CRT_PARSE_C " 23a8e1175bSopenharmony_ci "not defined.\n"); 24a8e1175bSopenharmony_ci mbedtls_exit(0); 25a8e1175bSopenharmony_ci} 26a8e1175bSopenharmony_ci#else 27a8e1175bSopenharmony_ci 28a8e1175bSopenharmony_ci#include "mbedtls/net_sockets.h" 29a8e1175bSopenharmony_ci#include "mbedtls/debug.h" 30a8e1175bSopenharmony_ci#include "mbedtls/ssl.h" 31a8e1175bSopenharmony_ci#include "mbedtls/entropy.h" 32a8e1175bSopenharmony_ci#include "mbedtls/ctr_drbg.h" 33a8e1175bSopenharmony_ci#include "mbedtls/error.h" 34a8e1175bSopenharmony_ci#include "test/certs.h" 35a8e1175bSopenharmony_ci 36a8e1175bSopenharmony_ci#include <string.h> 37a8e1175bSopenharmony_ci 38a8e1175bSopenharmony_ci#define SERVER_PORT "4433" 39a8e1175bSopenharmony_ci#define SERVER_NAME "localhost" 40a8e1175bSopenharmony_ci#define GET_REQUEST "GET / HTTP/1.0\r\n\r\n" 41a8e1175bSopenharmony_ci 42a8e1175bSopenharmony_ci#define DEBUG_LEVEL 1 43a8e1175bSopenharmony_ci 44a8e1175bSopenharmony_ci 45a8e1175bSopenharmony_cistatic void my_debug(void *ctx, int level, 46a8e1175bSopenharmony_ci const char *file, int line, 47a8e1175bSopenharmony_ci const char *str) 48a8e1175bSopenharmony_ci{ 49a8e1175bSopenharmony_ci ((void) level); 50a8e1175bSopenharmony_ci 51a8e1175bSopenharmony_ci mbedtls_fprintf((FILE *) ctx, "%s:%04d: %s", file, line, str); 52a8e1175bSopenharmony_ci fflush((FILE *) ctx); 53a8e1175bSopenharmony_ci} 54a8e1175bSopenharmony_ci 55a8e1175bSopenharmony_ciint main(void) 56a8e1175bSopenharmony_ci{ 57a8e1175bSopenharmony_ci int ret = 1, len; 58a8e1175bSopenharmony_ci int exit_code = MBEDTLS_EXIT_FAILURE; 59a8e1175bSopenharmony_ci mbedtls_net_context server_fd; 60a8e1175bSopenharmony_ci uint32_t flags; 61a8e1175bSopenharmony_ci unsigned char buf[1024]; 62a8e1175bSopenharmony_ci const char *pers = "ssl_client1"; 63a8e1175bSopenharmony_ci 64a8e1175bSopenharmony_ci mbedtls_entropy_context entropy; 65a8e1175bSopenharmony_ci mbedtls_ctr_drbg_context ctr_drbg; 66a8e1175bSopenharmony_ci mbedtls_ssl_context ssl; 67a8e1175bSopenharmony_ci mbedtls_ssl_config conf; 68a8e1175bSopenharmony_ci mbedtls_x509_crt cacert; 69a8e1175bSopenharmony_ci 70a8e1175bSopenharmony_ci#if defined(MBEDTLS_DEBUG_C) 71a8e1175bSopenharmony_ci mbedtls_debug_set_threshold(DEBUG_LEVEL); 72a8e1175bSopenharmony_ci#endif 73a8e1175bSopenharmony_ci 74a8e1175bSopenharmony_ci /* 75a8e1175bSopenharmony_ci * 0. Initialize the RNG and the session data 76a8e1175bSopenharmony_ci */ 77a8e1175bSopenharmony_ci mbedtls_net_init(&server_fd); 78a8e1175bSopenharmony_ci mbedtls_ssl_init(&ssl); 79a8e1175bSopenharmony_ci mbedtls_ssl_config_init(&conf); 80a8e1175bSopenharmony_ci mbedtls_x509_crt_init(&cacert); 81a8e1175bSopenharmony_ci mbedtls_ctr_drbg_init(&ctr_drbg); 82a8e1175bSopenharmony_ci mbedtls_entropy_init(&entropy); 83a8e1175bSopenharmony_ci 84a8e1175bSopenharmony_ci#if defined(MBEDTLS_USE_PSA_CRYPTO) 85a8e1175bSopenharmony_ci psa_status_t status = psa_crypto_init(); 86a8e1175bSopenharmony_ci if (status != PSA_SUCCESS) { 87a8e1175bSopenharmony_ci mbedtls_fprintf(stderr, "Failed to initialize PSA Crypto implementation: %d\n", 88a8e1175bSopenharmony_ci (int) status); 89a8e1175bSopenharmony_ci goto exit; 90a8e1175bSopenharmony_ci } 91a8e1175bSopenharmony_ci#endif /* MBEDTLS_USE_PSA_CRYPTO */ 92a8e1175bSopenharmony_ci 93a8e1175bSopenharmony_ci mbedtls_printf("\n . Seeding the random number generator..."); 94a8e1175bSopenharmony_ci fflush(stdout); 95a8e1175bSopenharmony_ci 96a8e1175bSopenharmony_ci 97a8e1175bSopenharmony_ci if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, 98a8e1175bSopenharmony_ci (const unsigned char *) pers, 99a8e1175bSopenharmony_ci strlen(pers))) != 0) { 100a8e1175bSopenharmony_ci mbedtls_printf(" failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret); 101a8e1175bSopenharmony_ci goto exit; 102a8e1175bSopenharmony_ci } 103a8e1175bSopenharmony_ci 104a8e1175bSopenharmony_ci mbedtls_printf(" ok\n"); 105a8e1175bSopenharmony_ci 106a8e1175bSopenharmony_ci /* 107a8e1175bSopenharmony_ci * 0. Initialize certificates 108a8e1175bSopenharmony_ci */ 109a8e1175bSopenharmony_ci mbedtls_printf(" . Loading the CA root certificate ..."); 110a8e1175bSopenharmony_ci fflush(stdout); 111a8e1175bSopenharmony_ci 112a8e1175bSopenharmony_ci ret = mbedtls_x509_crt_parse(&cacert, (const unsigned char *) mbedtls_test_cas_pem, 113a8e1175bSopenharmony_ci mbedtls_test_cas_pem_len); 114a8e1175bSopenharmony_ci if (ret < 0) { 115a8e1175bSopenharmony_ci mbedtls_printf(" failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", 116a8e1175bSopenharmony_ci (unsigned int) -ret); 117a8e1175bSopenharmony_ci goto exit; 118a8e1175bSopenharmony_ci } 119a8e1175bSopenharmony_ci 120a8e1175bSopenharmony_ci mbedtls_printf(" ok (%d skipped)\n", ret); 121a8e1175bSopenharmony_ci 122a8e1175bSopenharmony_ci /* 123a8e1175bSopenharmony_ci * 1. Start the connection 124a8e1175bSopenharmony_ci */ 125a8e1175bSopenharmony_ci mbedtls_printf(" . Connecting to tcp/%s/%s...", SERVER_NAME, SERVER_PORT); 126a8e1175bSopenharmony_ci fflush(stdout); 127a8e1175bSopenharmony_ci 128a8e1175bSopenharmony_ci if ((ret = mbedtls_net_connect(&server_fd, SERVER_NAME, 129a8e1175bSopenharmony_ci SERVER_PORT, MBEDTLS_NET_PROTO_TCP)) != 0) { 130a8e1175bSopenharmony_ci mbedtls_printf(" failed\n ! mbedtls_net_connect returned %d\n\n", ret); 131a8e1175bSopenharmony_ci goto exit; 132a8e1175bSopenharmony_ci } 133a8e1175bSopenharmony_ci 134a8e1175bSopenharmony_ci mbedtls_printf(" ok\n"); 135a8e1175bSopenharmony_ci 136a8e1175bSopenharmony_ci /* 137a8e1175bSopenharmony_ci * 2. Setup stuff 138a8e1175bSopenharmony_ci */ 139a8e1175bSopenharmony_ci mbedtls_printf(" . Setting up the SSL/TLS structure..."); 140a8e1175bSopenharmony_ci fflush(stdout); 141a8e1175bSopenharmony_ci 142a8e1175bSopenharmony_ci if ((ret = mbedtls_ssl_config_defaults(&conf, 143a8e1175bSopenharmony_ci MBEDTLS_SSL_IS_CLIENT, 144a8e1175bSopenharmony_ci MBEDTLS_SSL_TRANSPORT_STREAM, 145a8e1175bSopenharmony_ci MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { 146a8e1175bSopenharmony_ci mbedtls_printf(" failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret); 147a8e1175bSopenharmony_ci goto exit; 148a8e1175bSopenharmony_ci } 149a8e1175bSopenharmony_ci 150a8e1175bSopenharmony_ci mbedtls_printf(" ok\n"); 151a8e1175bSopenharmony_ci 152a8e1175bSopenharmony_ci /* OPTIONAL is not optimal for security, 153a8e1175bSopenharmony_ci * but makes interop easier in this simplified example */ 154a8e1175bSopenharmony_ci mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL); 155a8e1175bSopenharmony_ci mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL); 156a8e1175bSopenharmony_ci mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg); 157a8e1175bSopenharmony_ci mbedtls_ssl_conf_dbg(&conf, my_debug, stdout); 158a8e1175bSopenharmony_ci 159a8e1175bSopenharmony_ci if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) { 160a8e1175bSopenharmony_ci mbedtls_printf(" failed\n ! mbedtls_ssl_setup returned %d\n\n", ret); 161a8e1175bSopenharmony_ci goto exit; 162a8e1175bSopenharmony_ci } 163a8e1175bSopenharmony_ci 164a8e1175bSopenharmony_ci if ((ret = mbedtls_ssl_set_hostname(&ssl, SERVER_NAME)) != 0) { 165a8e1175bSopenharmony_ci mbedtls_printf(" failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret); 166a8e1175bSopenharmony_ci goto exit; 167a8e1175bSopenharmony_ci } 168a8e1175bSopenharmony_ci 169a8e1175bSopenharmony_ci mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL); 170a8e1175bSopenharmony_ci 171a8e1175bSopenharmony_ci /* 172a8e1175bSopenharmony_ci * 4. Handshake 173a8e1175bSopenharmony_ci */ 174a8e1175bSopenharmony_ci mbedtls_printf(" . Performing the SSL/TLS handshake..."); 175a8e1175bSopenharmony_ci fflush(stdout); 176a8e1175bSopenharmony_ci 177a8e1175bSopenharmony_ci while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) { 178a8e1175bSopenharmony_ci if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { 179a8e1175bSopenharmony_ci mbedtls_printf(" failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", 180a8e1175bSopenharmony_ci (unsigned int) -ret); 181a8e1175bSopenharmony_ci goto exit; 182a8e1175bSopenharmony_ci } 183a8e1175bSopenharmony_ci } 184a8e1175bSopenharmony_ci 185a8e1175bSopenharmony_ci mbedtls_printf(" ok\n"); 186a8e1175bSopenharmony_ci 187a8e1175bSopenharmony_ci /* 188a8e1175bSopenharmony_ci * 5. Verify the server certificate 189a8e1175bSopenharmony_ci */ 190a8e1175bSopenharmony_ci mbedtls_printf(" . Verifying peer X.509 certificate..."); 191a8e1175bSopenharmony_ci 192a8e1175bSopenharmony_ci /* In real life, we probably want to bail out when ret != 0 */ 193a8e1175bSopenharmony_ci if ((flags = mbedtls_ssl_get_verify_result(&ssl)) != 0) { 194a8e1175bSopenharmony_ci#if !defined(MBEDTLS_X509_REMOVE_INFO) 195a8e1175bSopenharmony_ci char vrfy_buf[512]; 196a8e1175bSopenharmony_ci#endif 197a8e1175bSopenharmony_ci 198a8e1175bSopenharmony_ci mbedtls_printf(" failed\n"); 199a8e1175bSopenharmony_ci 200a8e1175bSopenharmony_ci#if !defined(MBEDTLS_X509_REMOVE_INFO) 201a8e1175bSopenharmony_ci mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), " ! ", flags); 202a8e1175bSopenharmony_ci 203a8e1175bSopenharmony_ci mbedtls_printf("%s\n", vrfy_buf); 204a8e1175bSopenharmony_ci#endif 205a8e1175bSopenharmony_ci } else { 206a8e1175bSopenharmony_ci mbedtls_printf(" ok\n"); 207a8e1175bSopenharmony_ci } 208a8e1175bSopenharmony_ci 209a8e1175bSopenharmony_ci /* 210a8e1175bSopenharmony_ci * 3. Write the GET request 211a8e1175bSopenharmony_ci */ 212a8e1175bSopenharmony_ci mbedtls_printf(" > Write to server:"); 213a8e1175bSopenharmony_ci fflush(stdout); 214a8e1175bSopenharmony_ci 215a8e1175bSopenharmony_ci len = sprintf((char *) buf, GET_REQUEST); 216a8e1175bSopenharmony_ci 217a8e1175bSopenharmony_ci while ((ret = mbedtls_ssl_write(&ssl, buf, len)) <= 0) { 218a8e1175bSopenharmony_ci if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { 219a8e1175bSopenharmony_ci mbedtls_printf(" failed\n ! mbedtls_ssl_write returned %d\n\n", ret); 220a8e1175bSopenharmony_ci goto exit; 221a8e1175bSopenharmony_ci } 222a8e1175bSopenharmony_ci } 223a8e1175bSopenharmony_ci 224a8e1175bSopenharmony_ci len = ret; 225a8e1175bSopenharmony_ci mbedtls_printf(" %d bytes written\n\n%s", len, (char *) buf); 226a8e1175bSopenharmony_ci 227a8e1175bSopenharmony_ci /* 228a8e1175bSopenharmony_ci * 7. Read the HTTP response 229a8e1175bSopenharmony_ci */ 230a8e1175bSopenharmony_ci mbedtls_printf(" < Read from server:"); 231a8e1175bSopenharmony_ci fflush(stdout); 232a8e1175bSopenharmony_ci 233a8e1175bSopenharmony_ci do { 234a8e1175bSopenharmony_ci len = sizeof(buf) - 1; 235a8e1175bSopenharmony_ci memset(buf, 0, sizeof(buf)); 236a8e1175bSopenharmony_ci ret = mbedtls_ssl_read(&ssl, buf, len); 237a8e1175bSopenharmony_ci 238a8e1175bSopenharmony_ci if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) { 239a8e1175bSopenharmony_ci continue; 240a8e1175bSopenharmony_ci } 241a8e1175bSopenharmony_ci 242a8e1175bSopenharmony_ci if (ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { 243a8e1175bSopenharmony_ci break; 244a8e1175bSopenharmony_ci } 245a8e1175bSopenharmony_ci 246a8e1175bSopenharmony_ci if (ret < 0) { 247a8e1175bSopenharmony_ci mbedtls_printf("failed\n ! mbedtls_ssl_read returned %d\n\n", ret); 248a8e1175bSopenharmony_ci break; 249a8e1175bSopenharmony_ci } 250a8e1175bSopenharmony_ci 251a8e1175bSopenharmony_ci if (ret == 0) { 252a8e1175bSopenharmony_ci mbedtls_printf("\n\nEOF\n\n"); 253a8e1175bSopenharmony_ci break; 254a8e1175bSopenharmony_ci } 255a8e1175bSopenharmony_ci 256a8e1175bSopenharmony_ci len = ret; 257a8e1175bSopenharmony_ci mbedtls_printf(" %d bytes read\n\n%s", len, (char *) buf); 258a8e1175bSopenharmony_ci } while (1); 259a8e1175bSopenharmony_ci 260a8e1175bSopenharmony_ci mbedtls_ssl_close_notify(&ssl); 261a8e1175bSopenharmony_ci 262a8e1175bSopenharmony_ci exit_code = MBEDTLS_EXIT_SUCCESS; 263a8e1175bSopenharmony_ci 264a8e1175bSopenharmony_ciexit: 265a8e1175bSopenharmony_ci 266a8e1175bSopenharmony_ci#ifdef MBEDTLS_ERROR_C 267a8e1175bSopenharmony_ci if (exit_code != MBEDTLS_EXIT_SUCCESS) { 268a8e1175bSopenharmony_ci char error_buf[100]; 269a8e1175bSopenharmony_ci mbedtls_strerror(ret, error_buf, 100); 270a8e1175bSopenharmony_ci mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf); 271a8e1175bSopenharmony_ci } 272a8e1175bSopenharmony_ci#endif 273a8e1175bSopenharmony_ci 274a8e1175bSopenharmony_ci mbedtls_net_free(&server_fd); 275a8e1175bSopenharmony_ci mbedtls_x509_crt_free(&cacert); 276a8e1175bSopenharmony_ci mbedtls_ssl_free(&ssl); 277a8e1175bSopenharmony_ci mbedtls_ssl_config_free(&conf); 278a8e1175bSopenharmony_ci mbedtls_ctr_drbg_free(&ctr_drbg); 279a8e1175bSopenharmony_ci mbedtls_entropy_free(&entropy); 280a8e1175bSopenharmony_ci#if defined(MBEDTLS_USE_PSA_CRYPTO) 281a8e1175bSopenharmony_ci mbedtls_psa_crypto_free(); 282a8e1175bSopenharmony_ci#endif /* MBEDTLS_USE_PSA_CRYPTO */ 283a8e1175bSopenharmony_ci 284a8e1175bSopenharmony_ci mbedtls_exit(exit_code); 285a8e1175bSopenharmony_ci} 286a8e1175bSopenharmony_ci#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C && 287a8e1175bSopenharmony_ci MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C && 288a8e1175bSopenharmony_ci MBEDTLS_PEM_PARSE_C && MBEDTLS_CTR_DRBG_C && MBEDTLS_X509_CRT_PARSE_C */ 289