int openssl_check_connect(struct connection *conn) { int rc = mbedtls_ssl_handshake(conn->ssl); switch (rc) { case 0: /* success */ conn->connected = 1; set_writable(conn); if (verbose) printf("Ciphersuite is %s\n", mbedtls_ssl_get_ciphersuite(conn->ssl)); return 0; case MBEDTLS_ERR_SSL_WANT_READ: set_readable(conn); return 0; case MBEDTLS_ERR_SSL_WANT_WRITE: set_writable(conn); return 0; case MBEDTLS_ERR_NET_CONN_RESET: reset_connection(conn); return 1; default: printf("Not read or write 0x%x\n", rc); return 1; } }
const char * rb_ssl_get_cipher(rb_fde_t *F) { if(F == NULL || F->ssl == NULL) return NULL; return mbedtls_ssl_get_ciphersuite(SSL_P(F)); }
static int do_handshake( mbedtls_ssl_context *ssl ) { int ret; uint32_t flags; unsigned char buf[1024]; memset(buf, 0, 1024); /* * 4. Handshake */ mbedtls_printf( " . Performing the SSL/TLS handshake..." ); fflush( stdout ); while( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { #if defined(MBEDTLS_ERROR_C) mbedtls_strerror( ret, (char *) buf, 1024 ); #endif mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned %d: %s\n\n", ret, buf ); return( -1 ); } } mbedtls_printf( " ok\n [ Ciphersuite is %s ]\n", mbedtls_ssl_get_ciphersuite( ssl ) ); /* * 5. Verify the server certificate */ mbedtls_printf( " . Verifying peer X.509 certificate..." ); /* In real life, we probably want to bail out when ret != 0 */ if( ( flags = mbedtls_ssl_get_verify_result( ssl ) ) != 0 ) { char vrfy_buf[512]; mbedtls_printf( " failed\n" ); mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags ); mbedtls_printf( "%s\n", vrfy_buf ); } else mbedtls_printf( " ok\n" ); mbedtls_printf( " . Peer certificate information ...\n" ); mbedtls_x509_crt_info( (char *) buf, sizeof( buf ) - 1, " ", mbedtls_ssl_get_peer_cert( ssl ) ); mbedtls_printf( "%s\n", buf ); return( 0 ); }
static CURLcode mbed_connect_step2(struct connectdata *conn, int sockindex) { int ret; struct SessionHandle *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; const mbedtls_x509_crt *peercert; #ifdef HAS_ALPN const char* next_protocol; #endif char errorbuf[128]; errorbuf[0] = 0; conn->recv[sockindex] = mbed_recv; conn->send[sockindex] = mbed_send; ret = mbedtls_ssl_handshake(&connssl->ssl); if(ret == MBEDTLS_ERR_SSL_WANT_READ) { connssl->connecting_state = ssl_connect_2_reading; return CURLE_OK; } else if(ret == MBEDTLS_ERR_SSL_WANT_WRITE) { connssl->connecting_state = ssl_connect_2_writing; return CURLE_OK; } else if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "ssl_handshake returned - mbedTLS: (-0x%04X) %s", -ret, errorbuf); return CURLE_SSL_CONNECT_ERROR; } infof(data, "mbedTLS: Handshake complete, cipher is %s\n", mbedtls_ssl_get_ciphersuite(&conn->ssl[sockindex].ssl) ); ret = mbedtls_ssl_get_verify_result(&conn->ssl[sockindex].ssl); if(ret && data->set.ssl.verifypeer) { if(ret & MBEDTLS_X509_BADCERT_EXPIRED) failf(data, "Cert verify failed: BADCERT_EXPIRED"); if(ret & MBEDTLS_X509_BADCERT_REVOKED) { failf(data, "Cert verify failed: BADCERT_REVOKED"); return CURLE_SSL_CACERT; } if(ret & MBEDTLS_X509_BADCERT_CN_MISMATCH) failf(data, "Cert verify failed: BADCERT_CN_MISMATCH"); if(ret & MBEDTLS_X509_BADCERT_NOT_TRUSTED) failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED"); return CURLE_PEER_FAILED_VERIFICATION; } peercert = mbedtls_ssl_get_peer_cert(&connssl->ssl); if(peercert && data->set.verbose) { const size_t bufsize = 16384; char *buffer = malloc(bufsize); if(!buffer) return CURLE_OUT_OF_MEMORY; if(mbedtls_x509_crt_info(buffer, bufsize, "* ", peercert) > 0) infof(data, "Dumping cert info:\n%s\n", buffer); else infof(data, "Unable to dump certificate information.\n"); free(buffer); } if(data->set.str[STRING_SSL_PINNEDPUBLICKEY]) { int size; CURLcode result; mbedtls_x509_crt *p; unsigned char pubkey[PUB_DER_MAX_BYTES]; if(!peercert || !peercert->raw.p || !peercert->raw.len) { failf(data, "Failed due to missing peer certificate"); return CURLE_SSL_PINNEDPUBKEYNOTMATCH; } p = calloc(1, sizeof(*p)); if(!p) return CURLE_OUT_OF_MEMORY; mbedtls_x509_crt_init(p); /* Make a copy of our const peercert because mbedtls_pk_write_pubkey_der needs a non-const key, for now. https://github.com/ARMmbed/mbedtls/issues/396 */ if(mbedtls_x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) { failf(data, "Failed copying peer certificate"); mbedtls_x509_crt_free(p); free(p); return CURLE_SSL_PINNEDPUBKEYNOTMATCH; } size = mbedtls_pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES); if(size <= 0) { failf(data, "Failed copying public key from peer certificate"); mbedtls_x509_crt_free(p); free(p); return CURLE_SSL_PINNEDPUBKEYNOTMATCH; } /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */ result = Curl_pin_peer_pubkey(data, data->set.str[STRING_SSL_PINNEDPUBLICKEY], &pubkey[PUB_DER_MAX_BYTES - size], size); if(result) { mbedtls_x509_crt_free(p); free(p); return result; } mbedtls_x509_crt_free(p); free(p); } #ifdef HAS_ALPN if(conn->bits.tls_enable_alpn) { next_protocol = mbedtls_ssl_get_alpn_protocol(&connssl->ssl); if(next_protocol) { infof(data, "ALPN, server accepted to use %s\n", next_protocol); #ifdef USE_NGHTTP2 if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID, NGHTTP2_PROTO_VERSION_ID_LEN) && !next_protocol[NGHTTP2_PROTO_VERSION_ID_LEN]) { conn->negnpn = CURL_HTTP_VERSION_2; } else #endif if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH) && !next_protocol[ALPN_HTTP_1_1_LENGTH]) { conn->negnpn = CURL_HTTP_VERSION_1_1; } } else { infof(data, "ALPN, server did not agree to a protocol\n"); } } #endif connssl->connecting_state = ssl_connect_3; infof(data, "SSL connected\n"); return CURLE_OK; }
int main( void ) { int ret, len, cnt = 0, pid; mbedtls_net_context listen_fd, client_fd; unsigned char buf[1024]; const char *pers = "ssl_fork_server"; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_x509_crt srvcert; mbedtls_pk_context pkey; mbedtls_net_init( &listen_fd ); mbedtls_net_init( &client_fd ); mbedtls_ssl_init( &ssl ); mbedtls_ssl_config_init( &conf ); mbedtls_entropy_init( &entropy ); mbedtls_pk_init( &pkey ); mbedtls_x509_crt_init( &srvcert ); mbedtls_ctr_drbg_init( &ctr_drbg ); signal( SIGCHLD, SIG_IGN ); /* * 0. Initial seeding of the RNG */ mbedtls_printf( "\n . Initial seeding of the random generator..." ); fflush( stdout ); if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 1. Load the certificates and private RSA key */ mbedtls_printf( " . Loading the server cert. and key..." ); fflush( stdout ); /* * This demonstration program uses embedded test certificates. * Instead, you may want to use mbedtls_x509_crt_parse_file() to read the * server and CA certificates, as well as mbedtls_pk_parse_keyfile(). */ ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_srv_crt, mbedtls_test_srv_crt_len ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_cas_pem, mbedtls_test_cas_pem_len ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } ret = mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_srv_key, mbedtls_test_srv_key_len, NULL, 0 ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 1b. Prepare SSL configuration */ mbedtls_printf( " . Configuring SSL..." ); fflush( stdout ); if( ( ret = mbedtls_ssl_config_defaults( &conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); goto exit; } mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); mbedtls_ssl_conf_ca_chain( &conf, srvcert.next, NULL ); if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, &pkey ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 2. Setup the listening TCP socket */ mbedtls_printf( " . Bind on https://localhost:4433/ ..." ); fflush( stdout ); if( ( ret = mbedtls_net_bind( &listen_fd, NULL, "4433", MBEDTLS_NET_PROTO_TCP ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_bind returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); while( 1 ) { /* * 3. Wait until a client connects */ mbedtls_net_init( &client_fd ); mbedtls_ssl_init( &ssl ); mbedtls_printf( " . Waiting for a remote connection ..." ); fflush( stdout ); if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd, NULL, 0, NULL ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_accept returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 3.5. Forking server thread */ pid = fork(); mbedtls_printf( " . Forking to handle connection ..." ); fflush( stdout ); if( pid < 0 ) { mbedtls_printf(" failed\n ! fork returned %d\n\n", pid ); goto exit; } mbedtls_printf( " ok\n" ); if( pid != 0 ) { if( ( ret = mbedtls_ctr_drbg_reseed( &ctr_drbg, (const unsigned char *) "parent", 6 ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_reseed returned %d\n", ret ); goto exit; } mbedtls_net_free( &client_fd ); continue; } mbedtls_net_free( &listen_fd ); /* * 4. Setup stuff */ mbedtls_printf( " . Setting up the SSL data...." ); fflush( stdout ); if( ( ret = mbedtls_ctr_drbg_reseed( &ctr_drbg, (const unsigned char *) "child", 5 ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_reseed returned %d\n", ret ); goto exit; } if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); goto exit; } mbedtls_ssl_set_bio( &ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, NULL ); mbedtls_printf( " ok\n" ); /* * 5. Handshake */ mbedtls_printf( " . Performing the SSL/TLS handshake..." ); fflush( stdout ); while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned %d\n\n", ret ); goto exit; } } mbedtls_printf( " ok\n" ); /* * 6. Read the HTTP Request */ mbedtls_printf( " < Read from client:" ); fflush( stdout ); do { len = sizeof( buf ) - 1; memset( buf, 0, sizeof( buf ) ); ret = mbedtls_ssl_read( &ssl, buf, len ); if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ) continue; if( ret <= 0 ) { switch( ret ) { case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: mbedtls_printf( " connection was closed gracefully\n" ); break; case MBEDTLS_ERR_NET_CONN_RESET: mbedtls_printf( " connection was reset by peer\n" ); break; default: mbedtls_printf( " mbedtls_ssl_read returned %d\n", ret ); break; } break; } len = ret; mbedtls_printf( " %d bytes read\n\n%s", len, (char *) buf ); if( ret > 0 ) break; } while( 1 ); /* * 7. Write the 200 Response */ mbedtls_printf( " > Write to client:" ); fflush( stdout ); len = sprintf( (char *) buf, HTTP_RESPONSE, mbedtls_ssl_get_ciphersuite( &ssl ) ); while( cnt++ < 100 ) { while( ( ret = mbedtls_ssl_write( &ssl, buf, len ) ) <= 0 ) { if( ret == MBEDTLS_ERR_NET_CONN_RESET ) { mbedtls_printf( " failed\n ! peer closed the connection\n\n" ); goto exit; } if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); goto exit; } } len = ret; mbedtls_printf( " %d bytes written\n\n%s\n", len, (char *) buf ); mbedtls_net_usleep( 1000000 ); } mbedtls_ssl_close_notify( &ssl ); goto exit; } exit: mbedtls_net_free( &client_fd ); mbedtls_net_free( &listen_fd ); mbedtls_x509_crt_free( &srvcert ); mbedtls_pk_free( &pkey ); mbedtls_ssl_free( &ssl ); mbedtls_ssl_config_free( &conf ); mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); #if defined(_WIN32) mbedtls_printf( " Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
int main( int argc, const char *argv[] ) { /* Client and server declarations. */ int ret; int len; #if SOCKET_COMMUNICATION mbedtls_net_context listen_fd, client_fd, server_fd; #endif unsigned char buf[1024]; /* Handshake step counter */ size_t step = 1; int flags; mbedtls_ssl_context s_ssl, c_ssl; mbedtls_ssl_config s_conf, c_conf; mbedtls_x509_crt srvcert; mbedtls_pk_context pkey; #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_context cache; #endif if( argc == 3) { packet_in_num = atoi(argv[1]); packet_in_file = argv[2]; } else if( argc != 1) { usage(argv[0]); exit(1); } /* Server init */ #if SOCKET_COMMUNICATION mbedtls_net_init( &listen_fd ); mbedtls_net_init( &client_fd ); #endif mbedtls_ssl_init( &s_ssl ); mbedtls_ssl_config_init( &s_conf ); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_init( &cache ); #endif mbedtls_x509_crt_init( &srvcert ); mbedtls_pk_init( &pkey ); /* Client init */ #if SOCKET_COMMUNICATION mbedtls_net_init( &server_fd ); #endif mbedtls_ssl_init( &c_ssl ); mbedtls_ssl_config_init( &c_conf ); /*mbedtls_x509_crt_init( &cacert );*/ #if defined(MBEDTLS_DEBUG_C) mbedtls_debug_set_threshold( DEBUG_LEVEL ); #endif /* * Server: * Load the certificates and private RSA key */ if( packet_in_num == 0 ) { mbedtls_printf( " . Loading the server cert. and key..." ); fflush( stdout ); } /* * This demonstration program uses embedded test certificates. * Instead, you may want to use mbedtls_x509_crt_parse_file() to read the * server and CA certificates, as well as mbedtls_pk_parse_keyfile(). */ ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_srv_crt, mbedtls_test_srv_crt_len ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_cas_pem, mbedtls_test_cas_pem_len ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } ret = mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_srv_key, mbedtls_test_srv_key_len, NULL, 0 ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret ); goto exit; } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } /* * Server: * Setup stuff */ if( packet_in_num == 0 ) { mbedtls_printf( " . Server: Setting up the SSL data...." ); fflush( stdout ); } if( ( ret = mbedtls_ssl_config_defaults( &s_conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); goto exit; } mbedtls_ssl_conf_rng( &s_conf, mbedtls_ctr_drbg_deterministic, NULL ); mbedtls_ssl_conf_dbg( &s_conf, my_debug, stdout ); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_conf_session_cache( &s_conf, &cache, mbedtls_ssl_cache_get, mbedtls_ssl_cache_set ); #endif mbedtls_ssl_conf_ca_chain( &s_conf, srvcert.next, NULL ); if( ( ret = mbedtls_ssl_conf_own_cert( &s_conf, &srvcert, &pkey ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret ); goto exit; } if( ( ret = mbedtls_ssl_setup( &s_ssl, &s_conf ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); goto exit; } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } mbedtls_ssl_session_reset( &s_ssl ); #if SOCKET_COMMUNICATION /* * Server: * Setup the listening TCP socket */ if( packet_in_num == 0 ) { mbedtls_printf( " . Bind on https://localhost:%s/ ...", SERVER_PORT ); fflush( stdout ); } if( ( ret = mbedtls_net_bind( &listen_fd, NULL, SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_bind returned %d\n\n", ret ); goto exit; } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } /* * Client: * Start the connection */ if( packet_in_num == 0 ) { mbedtls_printf( " . Connecting to tcp/%s/%s...", SERVER_NAME, SERVER_PORT ); fflush( stdout ); } if( ( ret = mbedtls_net_connect( &server_fd, SERVER_NAME, SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret ); goto exit; } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } /* * Server: * Start listening for client connections */ if( packet_in_num == 0 ) { mbedtls_printf( " . Waiting for a remote connection ..." ); fflush( stdout ); } /* * Server: * Accept client connection (socket is set non-blocking in * library/net.c) */ if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd, NULL, 0, NULL ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_accept returned %d\n\n", ret ); goto exit; } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } mbedtls_ssl_set_bio( &s_ssl, &client_fd, mbedtls_send_custom, mbedtls_recv_custom, NULL ); #else mbedtls_ssl_set_bio( &s_ssl, NULL, mbedtls_server_send_buf, mbedtls_server_recv_buf, NULL ); #endif /* * Client: * Setup stuff */ if( packet_in_num == 0 ) { mbedtls_printf( " . Client: Setting up the SSL/TLS structure..." ); fflush( stdout ); } if( ( ret = mbedtls_ssl_config_defaults( &c_conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); goto exit; } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } /* OPTIONAL is not optimal for security, * but makes interop easier in this simplified example */ mbedtls_ssl_conf_authmode( &c_conf, MBEDTLS_SSL_VERIFY_OPTIONAL ); /* NONE permits man-in-the-middle attacks. */ /*mbedtls_ssl_conf_authmode( &c_conf, MBEDTLS_SSL_VERIFY_NONE );*/ /*mbedtls_ssl_conf_authmode( &c_conf, MBEDTLS_SSL_VERIFY_REQUIRED );*/ mbedtls_ssl_conf_ca_chain( &c_conf, &srvcert, NULL ); mbedtls_ssl_conf_rng( &c_conf, mbedtls_ctr_drbg_deterministic, NULL ); mbedtls_ssl_conf_dbg( &c_conf, my_debug, stdout ); if( ( ret = mbedtls_ssl_setup( &c_ssl, &c_conf ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); goto exit; } if( ( ret = mbedtls_ssl_set_hostname( &c_ssl, "mbed TLS Server 1" ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret ); goto exit; } #if SOCKET_COMMUNICATION mbedtls_ssl_set_bio( &c_ssl, &server_fd, mbedtls_send_custom, mbedtls_recv_custom, NULL ); #else mbedtls_ssl_set_bio( &c_ssl, NULL, mbedtls_client_send_buf, mbedtls_client_recv_buf, NULL ); #endif if( packet_in_num == 0 ) { mbedtls_printf( " . Performing the SSL/TLS handshake...\n" ); fflush( stdout ); } /* * The following number of steps are hardcoded to ensure * that the client and server complete the handshake without * waiting infinitely for the other side to send data. * * 1 2 3 4 5 6 7 8 9 10 */ int client_steps[] = { 2, 1, 1, 1, 4, 2, 1, 1, 2, 1 }; int server_steps[] = { 3, 1, 1, 2, 3, 1, 2, 1, 1, 1 }; do { /* * Client: * Handshake step */ int i; int no_steps; if( c_ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER) { no_steps = 0; } else { no_steps = client_steps[step - 1]; } for (i = 0; i < no_steps; i++) { if( ( ret = mbedtls_ssl_handshake_step( &c_ssl ) ) != 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret ); goto exit; } } } if( packet_in_num == 0 ) { mbedtls_printf( "--- client handshake step %zd ok\n", step ); } /* * Server: * Handshake step */ if( s_ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER) { no_steps = 0; } else { no_steps = server_steps[step - 1]; } for (i = 0; i < no_steps; i++) { if( ( ret = mbedtls_ssl_handshake_step( &s_ssl ) ) != 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned %d\n\n", ret ); goto exit; } } } if( packet_in_num == 0 ) { mbedtls_printf( "--- server handshake step %zd ok\n", step ); } step++; } while( ((c_ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER) || (s_ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)) && (step <= MAX_HANDSHAKE_STEPS) ); if( packet_in_num == 0 ) { mbedtls_printf( "c_ssl.state: %d\n", c_ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER ); mbedtls_printf( "s_ssl.state: %d\n", s_ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER ); } /* * Client: * Verify the server certificate */ if( packet_in_num == 0 ) { mbedtls_printf( " . Verifying peer X.509 certificate..." ); } /* In real life, we probably want to bail out when ret != 0 */ if( ( flags = mbedtls_ssl_get_verify_result( &c_ssl ) ) != 0 ) { char vrfy_buf[512]; mbedtls_printf( " failed\n" ); mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags ); mbedtls_printf( "%s\n", vrfy_buf ); } else if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } /* * Client: * Write the GET request */ if( packet_in_num == 0 ) { mbedtls_printf( " > Write to server:" ); fflush( stdout ); } len = sprintf( (char *) buf, GET_REQUEST ); while( ( ret = mbedtls_ssl_write( &c_ssl, buf, len ) ) <= 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); goto exit; } } len = ret; if( packet_in_num == 0 ) { mbedtls_printf( " %d bytes written\n\n%s", len, (char *) buf ); } /* * Server: * Read the HTTP Request */ if( packet_in_num == 0 ) { mbedtls_printf( " < Read from client:" ); fflush( stdout ); } do { len = sizeof( buf ) - 1; memset( buf, 0, sizeof( buf ) ); ret = mbedtls_ssl_read( &s_ssl, buf, len ); if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ) continue; if( ret <= 0 ) { switch( ret ) { case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: mbedtls_printf( " connection was closed gracefully\n" ); break; case MBEDTLS_ERR_NET_CONN_RESET: mbedtls_printf( " connection was reset by peer\n" ); break; default: mbedtls_printf( " mbedtls_ssl_read returned -0x%x\n", -ret ); break; } break; } len = ret; if( packet_in_num == 0 ) { mbedtls_printf( " %d bytes read\n\n%s", len, (char *) buf ); } if( ret > 0 ) break; } while( 1 ); /* * Server: * Write the 200 Response */ if( packet_in_num == 0 ) { mbedtls_printf( " > Write to client:" ); fflush( stdout ); } len = sprintf( (char *) buf, HTTP_RESPONSE, mbedtls_ssl_get_ciphersuite( &s_ssl ) ); while( ( ret = mbedtls_ssl_write( &s_ssl, buf, len ) ) <= 0 ) { if( ret == MBEDTLS_ERR_NET_CONN_RESET ) { mbedtls_printf( " failed\n ! peer closed the connection\n\n" ); goto exit; } if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); goto exit; } } len = ret; if( packet_in_num == 0 ) { mbedtls_printf( " %d bytes written\n\n%s\n", len, (char *) buf ); } /* * Client: * Read the HTTP response */ if( packet_in_num == 0 ) { mbedtls_printf( " < Read from server:" ); fflush( stdout ); } do { len = sizeof( buf ) - 1; memset( buf, 0, sizeof( buf ) ); ret = mbedtls_ssl_read( &c_ssl, buf, len ); if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ) continue; if( ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ) { ret = 0; break; } if( ret < 0 ) { mbedtls_printf( "failed\n ! mbedtls_ssl_read returned %d\n\n", ret ); break; } if( ret == 0 ) { mbedtls_printf( "\n\nEOF\n\n" ); break; } len = ret; if( packet_in_num == 0 ) { mbedtls_printf( " %d bytes read\n\n%s", len, (char *) buf ); } /* * Server: * Client read response. Close connection. */ if ( packet_in_num == 0 ) { mbedtls_printf( " . Closing the connection..." ); fflush( stdout ); } while( ( ret = mbedtls_ssl_close_notify( &s_ssl ) ) < 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_close_notify returned %d\n\n", ret ); goto exit; } } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } } while( 1 ); /* * Client: * Close connection. */ if( packet_in_num == 0 ) { mbedtls_printf( " . Closing the connection..." ); fflush( stdout ); } mbedtls_ssl_close_notify( &c_ssl ); if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } /* * Server: * We do not have multiple clients and therefore do not goto reset. */ /*ret = 0;*/ /*goto reset;*/ exit: #ifdef MBEDTLS_ERROR_C if( ret != 0 ) { char error_buf[100]; mbedtls_strerror( ret, error_buf, 100 ); mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf ); } #endif #if SOCKET_COMMUNICATION mbedtls_net_free( &client_fd ); mbedtls_net_free( &listen_fd ); mbedtls_net_free( &server_fd ); #endif mbedtls_x509_crt_free( &srvcert ); mbedtls_pk_free( &pkey ); mbedtls_ssl_free( &s_ssl ); mbedtls_ssl_free( &c_ssl ); mbedtls_ssl_config_free( &s_conf ); mbedtls_ssl_config_free( &c_conf ); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_free( &cache ); #endif #if defined(_WIN32) mbedtls_printf( " Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
/* Get TLS cipher */ char *tls_cipher_string(mbedtls_ssl_context *context) { return (char*)mbedtls_ssl_get_ciphersuite(context); }
static void *handle_ssl_connection( void *data ) { int ret, len; thread_info_t *thread_info = (thread_info_t *) data; mbedtls_net_context *client_fd = &thread_info->client_fd; long int thread_id = (long int) pthread_self(); unsigned char buf[1024]; mbedtls_ssl_context ssl; /* Make sure memory references are valid */ mbedtls_ssl_init( &ssl ); mbedtls_printf( " [ #%ld ] Setting up SSL/TLS data\n", thread_id ); /* * 4. Get the SSL context ready */ if( ( ret = mbedtls_ssl_setup( &ssl, thread_info->config ) ) != 0 ) { mbedtls_printf( " [ #%ld ] failed: mbedtls_ssl_setup returned -0x%04x\n", thread_id, -ret ); goto thread_exit; } mbedtls_ssl_set_bio( &ssl, client_fd, mbedtls_net_send, mbedtls_net_recv, NULL ); /* * 5. Handshake */ mbedtls_printf( " [ #%ld ] Performing the SSL/TLS handshake\n", thread_id ); while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " [ #%ld ] failed: mbedtls_ssl_handshake returned -0x%04x\n", thread_id, -ret ); goto thread_exit; } } mbedtls_printf( " [ #%ld ] ok\n", thread_id ); /* * 6. Read the HTTP Request */ mbedtls_printf( " [ #%ld ] < Read from client\n", thread_id ); do { len = sizeof( buf ) - 1; memset( buf, 0, sizeof( buf ) ); ret = mbedtls_ssl_read( &ssl, buf, len ); if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ) continue; if( ret <= 0 ) { switch( ret ) { case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: mbedtls_printf( " [ #%ld ] connection was closed gracefully\n", thread_id ); goto thread_exit; case MBEDTLS_ERR_NET_CONN_RESET: mbedtls_printf( " [ #%ld ] connection was reset by peer\n", thread_id ); goto thread_exit; default: mbedtls_printf( " [ #%ld ] mbedtls_ssl_read returned -0x%04x\n", thread_id, -ret ); goto thread_exit; } } len = ret; mbedtls_printf( " [ #%ld ] %d bytes read\n=====\n%s\n=====\n", thread_id, len, (char *) buf ); if( ret > 0 ) break; } while( 1 ); /* * 7. Write the 200 Response */ mbedtls_printf( " [ #%ld ] > Write to client:\n", thread_id ); len = sprintf( (char *) buf, HTTP_RESPONSE, mbedtls_ssl_get_ciphersuite( &ssl ) ); while( ( ret = mbedtls_ssl_write( &ssl, buf, len ) ) <= 0 ) { if( ret == MBEDTLS_ERR_NET_CONN_RESET ) { mbedtls_printf( " [ #%ld ] failed: peer closed the connection\n", thread_id ); goto thread_exit; } if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " [ #%ld ] failed: mbedtls_ssl_write returned -0x%04x\n", thread_id, ret ); goto thread_exit; } } len = ret; mbedtls_printf( " [ #%ld ] %d bytes written\n=====\n%s\n=====\n", thread_id, len, (char *) buf ); mbedtls_printf( " [ #%ld ] . Closing the connection...", thread_id ); while( ( ret = mbedtls_ssl_close_notify( &ssl ) ) < 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " [ #%ld ] failed: mbedtls_ssl_close_notify returned -0x%04x\n", thread_id, ret ); goto thread_exit; } } mbedtls_printf( " ok\n" ); ret = 0; thread_exit: #ifdef MBEDTLS_ERROR_C if( ret != 0 ) { char error_buf[100]; mbedtls_strerror( ret, error_buf, 100 ); mbedtls_printf(" [ #%ld ] Last error was: -0x%04x - %s\n\n", thread_id, -ret, error_buf ); } #endif mbedtls_net_free( client_fd ); mbedtls_ssl_free( &ssl ); thread_info->thread_complete = 1; return( NULL ); }
int SSLContext::getCipherSuite(State & state, SSLContextData * ssl_context_data) { Stack * stack = state.stack; stack->push<const std::string &>(mbedtls_ssl_get_ciphersuite(ssl_context_data->context)); return 1; }
static void https_get_task(void *pvParameters) { char buf[512]; int ret, flags, len; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_x509_crt cacert; mbedtls_ssl_config conf; mbedtls_net_context server_fd; mbedtls_ssl_init(&ssl); mbedtls_x509_crt_init(&cacert); mbedtls_ctr_drbg_init(&ctr_drbg); ESP_LOGI(TAG, "Seeding the random number generator"); mbedtls_ssl_config_init(&conf); mbedtls_entropy_init(&entropy); if((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0)) != 0) { ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned %d", ret); abort(); } ESP_LOGI(TAG, "Loading the CA root certificate..."); ret = mbedtls_x509_crt_parse(&cacert, server_root_cert_pem_start, server_root_cert_pem_end-server_root_cert_pem_start); if(ret < 0) { ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); abort(); } ESP_LOGI(TAG, "Setting hostname for TLS session..."); /* Hostname set here should match CN in server certificate */ if((ret = mbedtls_ssl_set_hostname(&ssl, WEB_SERVER)) != 0) { ESP_LOGE(TAG, "mbedtls_ssl_set_hostname returned -0x%x", -ret); abort(); } ESP_LOGI(TAG, "Setting up the SSL/TLS structure..."); if((ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { ESP_LOGE(TAG, "mbedtls_ssl_config_defaults returned %d", ret); goto exit; } /* MBEDTLS_SSL_VERIFY_OPTIONAL is bad for security, in this example it will print a warning if CA verification fails but it will continue to connect. You should consider using MBEDTLS_SSL_VERIFY_REQUIRED in your own code. */ mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL); mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL); mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg); #ifdef CONFIG_MBEDTLS_DEBUG mbedtls_esp_enable_debug_log(&conf, 4); #endif if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) { ESP_LOGE(TAG, "mbedtls_ssl_setup returned -0x%x\n\n", -ret); goto exit; } while(1) { /* Wait for the callback to set the CONNECTED_BIT in the event group. */ xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY); ESP_LOGI(TAG, "Connected to AP"); mbedtls_net_init(&server_fd); ESP_LOGI(TAG, "Connecting to %s:%s...", WEB_SERVER, WEB_PORT); if ((ret = mbedtls_net_connect(&server_fd, WEB_SERVER, WEB_PORT, MBEDTLS_NET_PROTO_TCP)) != 0) { ESP_LOGE(TAG, "mbedtls_net_connect returned -%x", -ret); goto exit; } ESP_LOGI(TAG, "Connected."); mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL); ESP_LOGI(TAG, "Performing the SSL/TLS handshake..."); while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { ESP_LOGE(TAG, "mbedtls_ssl_handshake returned -0x%x", -ret); goto exit; } } ESP_LOGI(TAG, "Verifying peer X.509 certificate..."); if ((flags = mbedtls_ssl_get_verify_result(&ssl)) != 0) { /* In real life, we probably want to close connection if ret != 0 */ ESP_LOGW(TAG, "Failed to verify peer certificate!"); bzero(buf, sizeof(buf)); mbedtls_x509_crt_verify_info(buf, sizeof(buf), " ! ", flags); ESP_LOGW(TAG, "verification info: %s", buf); } else { ESP_LOGI(TAG, "Certificate verified."); } ESP_LOGI(TAG, "Cipher suite is %s", mbedtls_ssl_get_ciphersuite(&ssl)); ESP_LOGI(TAG, "Writing HTTP request..."); size_t written_bytes = 0; do { ret = mbedtls_ssl_write(&ssl, (const unsigned char *)REQUEST + written_bytes, strlen(REQUEST) - written_bytes); if (ret >= 0) { ESP_LOGI(TAG, "%d bytes written", ret); written_bytes += ret; } else if (ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != MBEDTLS_ERR_SSL_WANT_READ) { ESP_LOGE(TAG, "mbedtls_ssl_write returned -0x%x", -ret); goto exit; } } while(written_bytes < strlen(REQUEST)); ESP_LOGI(TAG, "Reading HTTP response..."); do { len = sizeof(buf) - 1; bzero(buf, sizeof(buf)); ret = mbedtls_ssl_read(&ssl, (unsigned char *)buf, len); if(ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) continue; if(ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { ret = 0; break; } if(ret < 0) { ESP_LOGE(TAG, "mbedtls_ssl_read returned -0x%x", -ret); break; } if(ret == 0) { ESP_LOGI(TAG, "connection closed"); break; } len = ret; ESP_LOGD(TAG, "%d bytes read", len); /* Print response directly to stdout as it is read */ for(int i = 0; i < len; i++) { putchar(buf[i]); } } while(1); mbedtls_ssl_close_notify(&ssl); exit: mbedtls_ssl_session_reset(&ssl); mbedtls_net_free(&server_fd); if(ret != 0) { mbedtls_strerror(ret, buf, 100); ESP_LOGE(TAG, "Last error was: -0x%x - %s", -ret, buf); } putchar('\n'); // JSON output doesn't have a newline at end static int request_count; ESP_LOGI(TAG, "Completed %d requests", ++request_count); for(int countdown = 10; countdown >= 0; countdown--) { ESP_LOGI(TAG, "%d...", countdown); vTaskDelay(1000 / portTICK_PERIOD_MS); } ESP_LOGI(TAG, "Starting again!"); } }
IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) { int ret = SUCCESS; TLSDataParams *tlsDataParams = NULL; char portBuffer[6]; char info_buf[256]; if(NULL == pNetwork) { return NULL_VALUE_ERROR; } if(NULL != params) { _iot_tls_set_connect_params(pNetwork, params->pRootCALocation, params->pDeviceCertLocation, params->pDevicePrivateKeyLocation, params->pDestinationURL, params->DestinationPort, params->timeout_ms, params->ServerVerificationFlag); } tlsDataParams = &(pNetwork->tlsDataParams); mbedtls_net_init(&(tlsDataParams->server_fd)); mbedtls_ssl_init(&(tlsDataParams->ssl)); mbedtls_ssl_config_init(&(tlsDataParams->conf)); #ifdef CONFIG_MBEDTLS_DEBUG mbedtls_esp_enable_debug_log(&(tlsDataParams->conf), 4); #endif mbedtls_ctr_drbg_init(&(tlsDataParams->ctr_drbg)); mbedtls_x509_crt_init(&(tlsDataParams->cacert)); mbedtls_x509_crt_init(&(tlsDataParams->clicert)); mbedtls_pk_init(&(tlsDataParams->pkey)); ESP_LOGD(TAG, "Seeding the random number generator..."); mbedtls_entropy_init(&(tlsDataParams->entropy)); if((ret = mbedtls_ctr_drbg_seed(&(tlsDataParams->ctr_drbg), mbedtls_entropy_func, &(tlsDataParams->entropy), (const unsigned char *) TAG, strlen(TAG))) != 0) { ESP_LOGE(TAG, "failed! mbedtls_ctr_drbg_seed returned -0x%x", -ret); return NETWORK_MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; } /* Load root CA... Certs/keys can be paths or they can be raw data. These use a very basic heuristic: if the cert starts with '/' then it's a path, if it's longer than this then it's raw cert data (PEM or DER, neither of which can start with a slash. */ if (pNetwork->tlsConnectParams.pRootCALocation[0] == '/') { ESP_LOGD(TAG, "Loading CA root certificate from file ..."); ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->cacert), pNetwork->tlsConnectParams.pRootCALocation); } else { ESP_LOGD(TAG, "Loading embedded CA root certificate ..."); ret = mbedtls_x509_crt_parse(&(tlsDataParams->cacert), (const unsigned char *)pNetwork->tlsConnectParams.pRootCALocation, strlen(pNetwork->tlsConnectParams.pRootCALocation)+1); } if(ret < 0) { ESP_LOGE(TAG, "failed! mbedtls_x509_crt_parse returned -0x%x while parsing root cert", -ret); return NETWORK_X509_ROOT_CRT_PARSE_ERROR; } ESP_LOGD(TAG, "ok (%d skipped)", ret); /* Load client certificate... */ if (pNetwork->tlsConnectParams.pDeviceCertLocation[0] == '/') { ESP_LOGD(TAG, "Loading client cert from file..."); ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->clicert), pNetwork->tlsConnectParams.pDeviceCertLocation); } else { ESP_LOGD(TAG, "Loading embedded client certificate..."); ret = mbedtls_x509_crt_parse(&(tlsDataParams->clicert), (const unsigned char *)pNetwork->tlsConnectParams.pDeviceCertLocation, strlen(pNetwork->tlsConnectParams.pDeviceCertLocation)+1); } if(ret != 0) { ESP_LOGE(TAG, "failed! mbedtls_x509_crt_parse returned -0x%x while parsing device cert", -ret); return NETWORK_X509_DEVICE_CRT_PARSE_ERROR; } /* Parse client private key... */ if (pNetwork->tlsConnectParams.pDevicePrivateKeyLocation[0] == '/') { ESP_LOGD(TAG, "Loading client private key from file..."); ret = mbedtls_pk_parse_keyfile(&(tlsDataParams->pkey), pNetwork->tlsConnectParams.pDevicePrivateKeyLocation, ""); } else { ESP_LOGD(TAG, "Loading embedded client private key..."); ret = mbedtls_pk_parse_key(&(tlsDataParams->pkey), (const unsigned char *)pNetwork->tlsConnectParams.pDevicePrivateKeyLocation, strlen(pNetwork->tlsConnectParams.pDevicePrivateKeyLocation)+1, (const unsigned char *)"", 0); } if(ret != 0) { ESP_LOGE(TAG, "failed! mbedtls_pk_parse_key returned -0x%x while parsing private key", -ret); return NETWORK_PK_PRIVATE_KEY_PARSE_ERROR; } /* Done parsing certs */ ESP_LOGD(TAG, "ok"); snprintf(portBuffer, 6, "%d", pNetwork->tlsConnectParams.DestinationPort); ESP_LOGD(TAG, "Connecting to %s/%s...", pNetwork->tlsConnectParams.pDestinationURL, portBuffer); if((ret = mbedtls_net_connect(&(tlsDataParams->server_fd), pNetwork->tlsConnectParams.pDestinationURL, portBuffer, MBEDTLS_NET_PROTO_TCP)) != 0) { ESP_LOGE(TAG, "failed! mbedtls_net_connect returned -0x%x", -ret); switch(ret) { case MBEDTLS_ERR_NET_SOCKET_FAILED: return NETWORK_ERR_NET_SOCKET_FAILED; case MBEDTLS_ERR_NET_UNKNOWN_HOST: return NETWORK_ERR_NET_UNKNOWN_HOST; case MBEDTLS_ERR_NET_CONNECT_FAILED: default: return NETWORK_ERR_NET_CONNECT_FAILED; }; } ret = mbedtls_net_set_block(&(tlsDataParams->server_fd)); if(ret != 0) { ESP_LOGE(TAG, "failed! net_set_(non)block() returned -0x%x", -ret); return SSL_CONNECTION_ERROR; } ESP_LOGD(TAG, "ok"); ESP_LOGD(TAG, "Setting up the SSL/TLS structure..."); if((ret = mbedtls_ssl_config_defaults(&(tlsDataParams->conf), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { ESP_LOGE(TAG, "failed! mbedtls_ssl_config_defaults returned -0x%x", -ret); return SSL_CONNECTION_ERROR; } mbedtls_ssl_conf_verify(&(tlsDataParams->conf), _iot_tls_verify_cert, NULL); if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) { mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_REQUIRED); } else { mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_OPTIONAL); } mbedtls_ssl_conf_rng(&(tlsDataParams->conf), mbedtls_ctr_drbg_random, &(tlsDataParams->ctr_drbg)); mbedtls_ssl_conf_ca_chain(&(tlsDataParams->conf), &(tlsDataParams->cacert), NULL); ret = mbedtls_ssl_conf_own_cert(&(tlsDataParams->conf), &(tlsDataParams->clicert), &(tlsDataParams->pkey)); if(ret != 0) { ESP_LOGE(TAG, "failed! mbedtls_ssl_conf_own_cert returned %d", ret); return SSL_CONNECTION_ERROR; } mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), pNetwork->tlsConnectParams.timeout_ms); #ifdef CONFIG_MBEDTLS_SSL_ALPN /* Use the AWS IoT ALPN extension for MQTT, if port 443 is requested */ if (pNetwork->tlsConnectParams.DestinationPort == 443) { const char *alpnProtocols[] = { "x-amzn-mqtt-ca", NULL }; if ((ret = mbedtls_ssl_conf_alpn_protocols(&(tlsDataParams->conf), alpnProtocols)) != 0) { ESP_LOGE(TAG, "failed! mbedtls_ssl_conf_alpn_protocols returned -0x%x", -ret); return SSL_CONNECTION_ERROR; } } #endif if((ret = mbedtls_ssl_setup(&(tlsDataParams->ssl), &(tlsDataParams->conf))) != 0) { ESP_LOGE(TAG, "failed! mbedtls_ssl_setup returned -0x%x", -ret); return SSL_CONNECTION_ERROR; } if((ret = mbedtls_ssl_set_hostname(&(tlsDataParams->ssl), pNetwork->tlsConnectParams.pDestinationURL)) != 0) { ESP_LOGE(TAG, "failed! mbedtls_ssl_set_hostname returned %d", ret); return SSL_CONNECTION_ERROR; } ESP_LOGD(TAG, "SSL state connect : %d ", tlsDataParams->ssl.state); mbedtls_ssl_set_bio(&(tlsDataParams->ssl), &(tlsDataParams->server_fd), mbedtls_net_send, NULL, mbedtls_net_recv_timeout); ESP_LOGD(TAG, "ok"); ESP_LOGD(TAG, "SSL state connect : %d ", tlsDataParams->ssl.state); ESP_LOGD(TAG, "Performing the SSL/TLS handshake..."); while((ret = mbedtls_ssl_handshake(&(tlsDataParams->ssl))) != 0) { if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { ESP_LOGE(TAG, "failed! mbedtls_ssl_handshake returned -0x%x", -ret); if(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { ESP_LOGE(TAG, " Unable to verify the server's certificate. "); } return SSL_CONNECTION_ERROR; } } ESP_LOGD(TAG, "ok [ Protocol is %s ] [ Ciphersuite is %s ]", mbedtls_ssl_get_version(&(tlsDataParams->ssl)), mbedtls_ssl_get_ciphersuite(&(tlsDataParams->ssl))); if((ret = mbedtls_ssl_get_record_expansion(&(tlsDataParams->ssl))) >= 0) { ESP_LOGD(TAG, " [ Record expansion is %d ]", ret); } else { ESP_LOGD(TAG, " [ Record expansion is unknown (compression) ]"); } ESP_LOGD(TAG, "Verifying peer X.509 certificate..."); if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) { if((tlsDataParams->flags = mbedtls_ssl_get_verify_result(&(tlsDataParams->ssl))) != 0) { ESP_LOGE(TAG, "failed"); mbedtls_x509_crt_verify_info(info_buf, sizeof(info_buf), " ! ", tlsDataParams->flags); ESP_LOGE(TAG, "%s", info_buf); ret = SSL_CONNECTION_ERROR; } else { ESP_LOGD(TAG, "ok"); ret = SUCCESS; } } else { ESP_LOGW(TAG, " Server Verification skipped"); ret = SUCCESS; } if(LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) { if (mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl)) != NULL) { ESP_LOGD(TAG, "Peer certificate information:"); mbedtls_x509_crt_info((char *) info_buf, sizeof(info_buf) - 1, " ", mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl))); ESP_LOGD(TAG, "%s", info_buf); } } return (IoT_Error_t) ret; }
int conn_link_open(struct conn_link_s *link, int *sock, bool use_ssl, uint32_t recv_timeout_ms, uint32_t send_timeout_ms) { DEBUGASSERT(link->sock < 0); #ifdef CONFIG_THINGSEE_HTTPS_PROTOCOL DEBUGASSERT(link->ssl == NULL); #ifdef CONFIG_MBEDTLS DEBUGASSERT(link->net.fd < 0); #endif #endif link->send_timeout_ms = send_timeout_ms; link->recv_timeout_ms = recv_timeout_ms; if (!use_ssl) { link->sock = *sock; *sock = -1; return OK; } else { #ifdef CONFIG_THINGSEE_HTTPS_PROTOCOL #ifdef CONFIG_MBEDTLS int ret; struct timeval tv; if (!g_https_data.initialized) { con_dbg_save_pos(); if (conn_link_mbedtls_initialize() < 0) return ERROR; } mbedtls_ssl_conf_read_timeout(&g_https_data.mbedtls->conf, link->recv_timeout_ms); /* Set up a send timeout */ tv.tv_sec = link->send_timeout_ms / 1000; tv.tv_usec = (link->send_timeout_ms % 1000) * 1000; ret = setsockopt(*sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(struct timeval)); if (ret < 0) { con_dbg("Setting SO_SNDTIMEO failed, errno: %d\n", errno); /* Return here. Socket is more than likely broken */ return ERROR; } else { http_con_dbg("SO_SNDTIMEO := %d msecs\n", link->send_timeout_ms); } /* Set up a receive timeout */ tv.tv_sec = link->recv_timeout_ms / 1000; tv.tv_usec = (link->recv_timeout_ms % 1000) * 1000; ret = setsockopt(*sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval)); if (ret < 0) { con_dbg("Setting SO_RCVTIMEO failed, errno: %d\n", errno); /* Return if ERROR occurred */ return ERROR; } else { http_con_dbg("SO_RCVTIMEO := %d msecs\n", link->recv_timeout_ms); } con_dbg_save_pos(); link->ssl = malloc(sizeof(*link->ssl)); if (!link->ssl) return -1; mbedtls_ssl_init(link->ssl); ret = mbedtls_ssl_setup(link->ssl, &g_https_data.mbedtls->conf); if (ret != 0) { con_dbg("mbedtls_ssl_setup error: -0x%x\n", -ret); goto err_close_tls; } link->net.fd = *sock; link->sock = link->net.fd; *sock = -1; ret = mbedtls_ssl_set_session(link->ssl, &g_https_data.mbedtls->saved_session); if (ret != 0) { con_dbg( "mbedtls_ssl_set_session error: -0x%x\n\n", -ret); } mbedtls_ssl_set_bio(link->ssl, &link->net, mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout); ret = mbedtls_ssl_handshake(link->ssl); if (ret != 0) { int lowlevel_err = -(-ret & 0x007F); int highlevel_err = -(-ret & 0x7F80); con_dbg("mbedtls_ssl_handshake error: -0x%x\n", -ret); /* Check out-of-memory cases. If we have run out memory or memory * has become too fragmented, device will be stuck in bad state. * In this case, it will be better to reset. * TODO: Should we add controlled reset? */ DEBUGASSERT(lowlevel_err != MBEDTLS_ERR_MPI_ALLOC_FAILED); DEBUGASSERT(lowlevel_err != MBEDTLS_ERR_ASN1_ALLOC_FAILED); DEBUGASSERT(highlevel_err != MBEDTLS_ERR_X509_ALLOC_FAILED); DEBUGASSERT(highlevel_err != MBEDTLS_ERR_DHM_ALLOC_FAILED); DEBUGASSERT(highlevel_err != MBEDTLS_ERR_PK_ALLOC_FAILED); DEBUGASSERT(highlevel_err != MBEDTLS_ERR_ECP_ALLOC_FAILED); DEBUGASSERT(highlevel_err != MBEDTLS_ERR_CIPHER_ALLOC_FAILED); DEBUGASSERT(highlevel_err != MBEDTLS_ERR_SSL_ALLOC_FAILED); goto err_close_tls; } con_dbg("%c[38;5;%d48;5;%dm" "HTTPS: TLS version is '%s'." "%c[0m\n", 0x1B, 0, 1, mbedtls_ssl_get_version(link->ssl), 0x1B); con_dbg("%c[38;5;%d48;5;%dm" "HTTPS: TLS cipher suite is '%s'." "%c[0m\n", 0x1B, 0, 1, mbedtls_ssl_get_ciphersuite(link->ssl), 0x1B); ret = mbedtls_ssl_get_session(link->ssl, &g_https_data.mbedtls->saved_session); if (ret != 0) { con_dbg( "mbedtls_ssl_get_session error: -0x%x\n\n", -ret); } return OK; err_close_tls: con_dbg_save_pos(); mbedtls_ssl_free(link->ssl); free(link->ssl); link->ssl = NULL; return ERROR; #endif #endif return ERROR; } }
int iot_tls_connect(Network *pNetwork, TLSConnectParams params) { const char *pers = "aws_iot_tls_wrapper"; unsigned char buf[MBEDTLS_SSL_MAX_CONTENT_LEN + 1]; DEBUG(" . Loading the CA root certificate ..."); ret = mbedtls_x509_crt_parse_file(&cacert, params.pRootCALocation); if (ret < 0) { ERROR(" failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); return ret; } DEBUG(" ok (%d skipped)\n", ret); DEBUG(" . Loading the client cert. and key..."); ret = mbedtls_x509_crt_parse_file(&clicert, params.pDeviceCertLocation); if (ret != 0) { ERROR(" failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); return ret; } ret = mbedtls_pk_parse_keyfile(&pkey, params.pDevicePrivateKeyLocation, ""); if (ret != 0) { ERROR(" failed\n ! mbedtls_pk_parse_key returned -0x%x\n\n", -ret); return ret; } DEBUG(" ok\n"); char portBuffer[6]; sprintf(portBuffer, "%d", params.DestinationPort); DEBUG(" . Connecting to %s/%s...", params.pDestinationURL, portBuffer); if ((ret = mbedtls_net_connect(&server_fd, params.pDestinationURL, portBuffer, MBEDTLS_NET_PROTO_TCP)) != 0) { ERROR(" failed\n ! mbedtls_net_connect returned -0x%x\n\n", -ret); return ret; } ret = mbedtls_net_set_block(&server_fd); if (ret != 0) { ERROR(" failed\n ! net_set_(non)block() returned -0x%x\n\n", -ret); return ret; } DEBUG(" ok\n"); DEBUG(" . Setting up the SSL/TLS structure..."); if ((ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { ERROR(" failed\n ! mbedtls_ssl_config_defaults returned -0x%x\n\n", -ret); return ret; } mbedtls_ssl_conf_verify(&conf, myCertVerify, NULL); if (params.ServerVerificationFlag == true) { mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_REQUIRED); } else { mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL); } mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg); mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL); if ((ret = mbedtls_ssl_conf_own_cert(&conf, &clicert, &pkey)) != 0) { ERROR(" failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret); return ret; } mbedtls_ssl_conf_read_timeout(&conf, params.timeout_ms); if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) { ERROR(" failed\n ! mbedtls_ssl_setup returned -0x%x\n\n", -ret); return ret; } if ((ret = mbedtls_ssl_set_hostname(&ssl, params.pDestinationURL)) != 0) { ERROR(" failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret); return ret; } mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, NULL, mbedtls_net_recv_timeout); DEBUG(" ok\n"); DEBUG(" . Performing the SSL/TLS handshake..."); while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { ERROR(" failed\n ! mbedtls_ssl_handshake returned -0x%x\n", -ret); if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { ERROR(" Unable to verify the server's certificate. " "Either it is invalid,\n" " or you didn't set ca_file or ca_path " "to an appropriate value.\n" " Alternatively, you may want to use " "auth_mode=optional for testing purposes.\n"); } return ret; } } DEBUG(" ok\n [ Protocol is %s ]\n [ Ciphersuite is %s ]\n", mbedtls_ssl_get_version(&ssl), mbedtls_ssl_get_ciphersuite(&ssl)); if ((ret = mbedtls_ssl_get_record_expansion(&ssl)) >= 0) { DEBUG(" [ Record expansion is %d ]\n", ret); } else { DEBUG(" [ Record expansion is unknown (compression) ]\n"); } DEBUG(" . Verifying peer X.509 certificate..."); if (params.ServerVerificationFlag == true) { if ((flags = mbedtls_ssl_get_verify_result(&ssl)) != 0) { char vrfy_buf[512]; ERROR(" failed\n"); mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), " ! ", flags); ERROR("%s\n", vrfy_buf); } else { DEBUG(" ok\n"); ret = NONE_ERROR; } } else { DEBUG(" Server Verification skipped\n"); ret = NONE_ERROR; } if (mbedtls_ssl_get_peer_cert(&ssl) != NULL) { DEBUG(" . Peer certificate information ...\n"); mbedtls_x509_crt_info((char *) buf, sizeof(buf) - 1, " ", mbedtls_ssl_get_peer_cert(&ssl)); DEBUG("%s\n", buf); } mbedtls_ssl_conf_read_timeout(&conf, 10); return ret; }
IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) { if(NULL == pNetwork) { return NULL_VALUE_ERROR; } if(NULL != params) { _iot_tls_set_connect_params(pNetwork, params->pRootCALocation, params->pDeviceCertLocation, params->pDevicePrivateKeyLocation, params->pDestinationURL, params->DestinationPort, params->timeout_ms, params->ServerVerificationFlag); } int ret = 0; const char *pers = "aws_iot_tls_wrapper"; #ifdef IOT_DEBUG unsigned char buf[MBEDTLS_SSL_MAX_CONTENT_LEN + 1]; #endif TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams); mbedtls_net_init(&(tlsDataParams->server_fd)); mbedtls_ssl_init(&(tlsDataParams->ssl)); mbedtls_ssl_config_init(&(tlsDataParams->conf)); mbedtls_ctr_drbg_init(&(tlsDataParams->ctr_drbg)); mbedtls_x509_crt_init(&(tlsDataParams->cacert)); mbedtls_x509_crt_init(&(tlsDataParams->clicert)); mbedtls_pk_init(&(tlsDataParams->pkey)); DEBUG("\n . Seeding the random number generator..."); mbedtls_entropy_init(&(tlsDataParams->entropy)); if ((ret = mbedtls_ctr_drbg_seed(&(tlsDataParams->ctr_drbg), mbedtls_entropy_func, &(tlsDataParams->entropy), (const unsigned char *) pers, strlen(pers))) != 0) { ERROR(" failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n", -ret); return NETWORK_MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED; } DEBUG(" . Loading the CA root certificate ..."); ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->cacert), pNetwork->tlsConnectParams.pRootCALocation); if (ret < 0) { ERROR(" failed\n ! mbedtls_x509_crt_parse returned -0x%x while parsing root cert\n\n", -ret); return NETWORK_X509_ROOT_CRT_PARSE_ERROR; } DEBUG(" ok (%d skipped)\n", ret); DEBUG(" . Loading the client cert. and key..."); ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->clicert), pNetwork->tlsConnectParams.pDeviceCertLocation); if (ret != 0) { ERROR(" failed\n ! mbedtls_x509_crt_parse returned -0x%x while parsing device cert\n\n", -ret); return NETWORK_X509_DEVICE_CRT_PARSE_ERROR; } ret = mbedtls_pk_parse_keyfile(&(tlsDataParams->pkey), pNetwork->tlsConnectParams.pDevicePrivateKeyLocation, ""); if (ret != 0) { ERROR(" failed\n ! mbedtls_pk_parse_key returned -0x%x while parsing private key\n\n", -ret); DEBUG(" path : %s ", pNetwork->tlsConnectParams.pDevicePrivateKeyLocation); return NETWORK_PK_PRIVATE_KEY_PARSE_ERROR; } DEBUG(" ok\n"); char portBuffer[6]; snprintf(portBuffer, 6, "%d", pNetwork->tlsConnectParams.DestinationPort); DEBUG(" . Connecting to %s/%s...", pNetwork->tlsConnectParams.pDestinationURL, portBuffer); if ((ret = mbedtls_net_connect(&(tlsDataParams->server_fd), pNetwork->tlsConnectParams.pDestinationURL, portBuffer, MBEDTLS_NET_PROTO_TCP)) != 0) { ERROR(" failed\n ! mbedtls_net_connect returned -0x%x\n\n", -ret); switch(ret) { case MBEDTLS_ERR_NET_SOCKET_FAILED: return NETWORK_ERR_NET_SOCKET_FAILED; case MBEDTLS_ERR_NET_UNKNOWN_HOST: return NETWORK_ERR_NET_UNKNOWN_HOST; case MBEDTLS_ERR_NET_CONNECT_FAILED: default: return NETWORK_ERR_NET_CONNECT_FAILED; }; } ret = mbedtls_net_set_block(&(tlsDataParams->server_fd)); if (ret != 0) { ERROR(" failed\n ! net_set_(non)block() returned -0x%x\n\n", -ret); return SSL_CONNECTION_ERROR; } DEBUG(" ok\n"); DEBUG(" . Setting up the SSL/TLS structure..."); if ((ret = mbedtls_ssl_config_defaults(&(tlsDataParams->conf), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { ERROR(" failed\n ! mbedtls_ssl_config_defaults returned -0x%x\n\n", -ret); return SSL_CONNECTION_ERROR; } mbedtls_ssl_conf_verify(&(tlsDataParams->conf), _iot_tls_verify_cert, NULL); if (pNetwork->tlsConnectParams.ServerVerificationFlag == true) { mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_REQUIRED); } else { mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_OPTIONAL); } mbedtls_ssl_conf_rng(&(tlsDataParams->conf), mbedtls_ctr_drbg_random, &(tlsDataParams->ctr_drbg)); mbedtls_ssl_conf_ca_chain(&(tlsDataParams->conf), &(tlsDataParams->cacert), NULL); if ((ret = mbedtls_ssl_conf_own_cert(&(tlsDataParams->conf), &(tlsDataParams->clicert), &(tlsDataParams->pkey))) != 0) { ERROR(" failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret); return SSL_CONNECTION_ERROR; } mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), pNetwork->tlsConnectParams.timeout_ms); if ((ret = mbedtls_ssl_setup(&(tlsDataParams->ssl), &(tlsDataParams->conf))) != 0) { ERROR(" failed\n ! mbedtls_ssl_setup returned -0x%x\n\n", -ret); return SSL_CONNECTION_ERROR; } if ((ret = mbedtls_ssl_set_hostname(&(tlsDataParams->ssl), pNetwork->tlsConnectParams.pDestinationURL)) != 0) { ERROR(" failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret); return SSL_CONNECTION_ERROR; } DEBUG("\n\nSSL state connect : %d ", tlsDataParams->ssl.state); mbedtls_ssl_set_bio(&(tlsDataParams->ssl), &(tlsDataParams->server_fd), mbedtls_net_send, NULL, mbedtls_net_recv_timeout); DEBUG(" ok\n"); DEBUG("\n\nSSL state connect : %d ", tlsDataParams->ssl.state); DEBUG(" . Performing the SSL/TLS handshake..."); while ((ret = mbedtls_ssl_handshake(&(tlsDataParams->ssl))) != 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { ERROR(" failed\n ! mbedtls_ssl_handshake returned -0x%x\n", -ret); if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { ERROR(" Unable to verify the server's certificate. " "Either it is invalid,\n" " or you didn't set ca_file or ca_path " "to an appropriate value.\n" " Alternatively, you may want to use " "auth_mode=optional for testing purposes.\n"); } return SSL_CONNECTION_ERROR; } } DEBUG(" ok\n [ Protocol is %s ]\n [ Ciphersuite is %s ]\n", mbedtls_ssl_get_version(&(tlsDataParams->ssl)), mbedtls_ssl_get_ciphersuite(&(tlsDataParams->ssl))); if ((ret = mbedtls_ssl_get_record_expansion(&(tlsDataParams->ssl))) >= 0) { DEBUG(" [ Record expansion is %d ]\n", ret); } else { DEBUG(" [ Record expansion is unknown (compression) ]\n"); } DEBUG(" . Verifying peer X.509 certificate..."); if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) { if((tlsDataParams->flags = mbedtls_ssl_get_verify_result(&(tlsDataParams->ssl))) != 0) { char vrfy_buf[512]; ERROR(" failed\n"); mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), " ! ", tlsDataParams->flags); ERROR("%s\n", vrfy_buf); ret = SSL_CONNECTION_ERROR; } else { DEBUG(" ok\n"); ret = SUCCESS; } } else { DEBUG(" Server Verification skipped\n"); ret = SUCCESS; } #ifdef IOT_DEBUG if (mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl)) != NULL) { DEBUG(" . Peer certificate information ...\n"); mbedtls_x509_crt_info((char *) buf, sizeof(buf) - 1, " ", mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl))); DEBUG("%s\n", buf); } #endif mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), IOT_SSL_READ_TIMEOUT); return ret; }
static CURLcode mbedtls_connect_step2(struct connectdata *conn, int sockindex) { int ret; struct SessionHandle *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; char buffer[1024]; #ifdef HAS_ALPN const char* next_protocol; #endif char errorbuf[128]; errorbuf[0] = 0; conn->recv[sockindex] = mbedtls_recv; conn->send[sockindex] = mbedtls_send; ret = mbedtls_ssl_handshake(&connssl->ssl); if(ret == MBEDTLS_ERR_SSL_WANT_READ) { connssl->connecting_state = ssl_connect_2_reading; return CURLE_OK; } else if(ret == MBEDTLS_ERR_SSL_WANT_WRITE) { connssl->connecting_state = ssl_connect_2_writing; return CURLE_OK; } else if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "ssl_handshake returned - mbedTLS: (-0x%04X) %s", -ret, errorbuf); return CURLE_SSL_CONNECT_ERROR; } infof(data, "mbedTLS: Handshake complete, cipher is %s\n", mbedtls_ssl_get_ciphersuite(&conn->ssl[sockindex].ssl) ); ret = mbedtls_ssl_get_verify_result(&conn->ssl[sockindex].ssl); if(ret && data->set.ssl.verifypeer) { if(ret & MBEDTLS_X509_BADCERT_EXPIRED) failf(data, "Cert verify failed: BADCERT_EXPIRED"); if(ret & MBEDTLS_X509_BADCERT_REVOKED) { failf(data, "Cert verify failed: BADCERT_REVOKED"); return CURLE_SSL_CACERT; } if(ret & MBEDTLS_X509_BADCERT_CN_MISMATCH) failf(data, "Cert verify failed: BADCERT_CN_MISMATCH"); if(ret & MBEDTLS_X509_BADCERT_NOT_TRUSTED) failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED"); return CURLE_PEER_FAILED_VERIFICATION; } if(mbedtls_ssl_get_peer_cert(&(connssl->ssl))) { /* If the session was resumed, there will be no peer certs */ memset(buffer, 0, sizeof(buffer)); if(mbedtls_x509_crt_info(buffer, sizeof(buffer), (char *)"* ", mbedtls_ssl_get_peer_cert(&(connssl->ssl))) != -1) infof(data, "Dumping cert info:\n%s\n", buffer); } #ifdef HAS_ALPN if(data->set.ssl_enable_alpn) { next_protocol = mbedtls_ssl_get_alpn_protocol(&connssl->ssl); if(next_protocol) { infof(data, "ALPN, server accepted to use %s\n", next_protocol); #ifdef USE_NGHTTP2 if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID, NGHTTP2_PROTO_VERSION_ID_LEN) && !next_protocol[NGHTTP2_PROTO_VERSION_ID_LEN]) { conn->negnpn = CURL_HTTP_VERSION_2; } else #endif if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH) && !next_protocol[ALPN_HTTP_1_1_LENGTH]) { conn->negnpn = CURL_HTTP_VERSION_1_1; } } else { infof(data, "ALPN, server did not agree to a protocol\n"); } } #endif connssl->connecting_state = ssl_connect_3; infof(data, "SSL connected\n"); return CURLE_OK; }