int dtls_server_cb(void *args) { int ret; int len; int ots = 0xFFFF; size_t cliip_len; unsigned char buf[1024]; const char *pers = "dtls_server"; unsigned char client_ip[16] = { 0 }; struct pthread_arg arg; mbedtls_ssl_cookie_ctx cookie_ctx; mbedtls_net_context listen_fd; mbedtls_net_context client_fd; 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_timing_delay_context timer; #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_context cache; #endif if (args) { arg.argc = ((struct pthread_arg *)args)->argc; arg.argv = ((struct pthread_arg *)args)->argv; if (arg.argc == 1) { ots = 1; } } mbedtls_net_init(&listen_fd); mbedtls_net_init(&client_fd); mbedtls_ssl_init(&ssl); mbedtls_ssl_config_init(&conf); mbedtls_ssl_cookie_init(&cookie_ctx); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_init(&cache); #endif mbedtls_x509_crt_init(&srvcert); mbedtls_pk_init(&pkey); mbedtls_entropy_init(&entropy); mbedtls_ctr_drbg_init(&ctr_drbg); #if defined(MBEDTLS_DEBUG_C) mbedtls_debug_set_threshold(DEBUG_LEVEL); #endif /* * 1. Load the certificates and private RSA key */ mbedtls_printf("\n . 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_rsa, mbedtls_test_srv_crt_rsa_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_ca_crt_rsa, mbedtls_test_ca_crt_rsa_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_rsa, mbedtls_test_srv_key_rsa_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"); /* * 2. Setup the "listening" UDP socket */ mbedtls_printf(" . Bind on udp/*/4433 ..."); fflush(stdout); if ((ret = mbedtls_net_bind(&listen_fd, NULL, "4433", MBEDTLS_NET_PROTO_UDP)) != 0) { mbedtls_printf(" failed\n ! mbedtls_net_bind returned %d\n\n", ret); goto exit; } mbedtls_printf(" ok\n"); /* * 3. Seed the RNG */ mbedtls_printf(" . Seeding the random number 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"); /* * 4. Setup stuff */ mbedtls_printf(" . Setting up the DTLS data..."); fflush(stdout); if ((ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_DATAGRAM, 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); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_conf_session_cache(&conf, &cache, mbedtls_ssl_cache_get, mbedtls_ssl_cache_set); #endif 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; } if ((ret = mbedtls_ssl_cookie_setup(&cookie_ctx, mbedtls_ctr_drbg_random, &ctr_drbg)) != 0) { mbedtls_printf(" failed\n ! mbedtls_ssl_cookie_setup returned %d\n\n", ret); goto exit; } mbedtls_ssl_conf_dtls_cookies(&conf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check, &cookie_ctx); 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_timer_cb(&ssl, &timer, mbedtls_timing_set_delay, mbedtls_timing_get_delay); mbedtls_printf(" ok\n"); reset: #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 mbedtls_net_free(&client_fd); mbedtls_ssl_session_reset(&ssl); /* * 3. Wait until a client connects */ mbedtls_printf(" . Waiting for a remote connection ..."); fflush(stdout); if (listen_fd.fd < 0) { goto exit; } if ((ret = mbedtls_net_accept(&listen_fd, &client_fd, client_ip, sizeof(client_ip), &cliip_len)) != 0) { mbedtls_printf(" failed\n ! mbedtls_net_accept returned %d\n\n", ret); goto exit; } /* For HelloVerifyRequest cookies */ if ((ret = mbedtls_ssl_set_client_transport_id(&ssl, client_ip, cliip_len)) != 0) { mbedtls_printf(" failed\n ! " "mbedtls_ssl_set_client_transport_id() returned -0x%x\n\n", -ret); goto exit; } mbedtls_ssl_set_bio(&ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout); mbedtls_printf(" ok\n"); /* * 5. Handshake */ mbedtls_printf(" . Performing the DTLS handshake..."); fflush(stdout); do { ret = mbedtls_ssl_handshake(&ssl); } while (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE); if (ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) { mbedtls_printf(" hello verification requested\n"); ret = 0; goto reset; } else if (ret != 0) { mbedtls_printf(" failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret); if (ots == 1) { goto exit; } goto reset; } mbedtls_printf(" ok\n"); /* * 6. Read the echo Request */ len = sizeof(buf) - 1; memset(buf, 0, sizeof(buf)); do { ret = mbedtls_ssl_read(&ssl, buf, len); } while (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE); if (ret <= 0) { switch (ret) { case MBEDTLS_ERR_SSL_TIMEOUT: mbedtls_printf(" timeout\n\n"); if (ots != 1) { goto reset; } goto exit; case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: mbedtls_printf(" connection was closed gracefully\n"); ret = 0; goto close_notify; default: mbedtls_printf(" mbedtls_ssl_read returned -0x%x\n", -ret); if (ots != 1) { goto reset; } goto exit; } } len = ret; mbedtls_printf(" < READ FROM CLIENT %d bytes read : %s\n", len, buf); /* * 7. Write the 200 Response */ do { ret = mbedtls_ssl_write(&ssl, buf, len); } while (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE); if (ret < 0) { mbedtls_printf(" failed\n ! mbedtls_ssl_write returned %d\n", ret); goto exit; } len = ret; mbedtls_printf(" > WRITE TO CLIENT %d bytes written : %s\n", len, buf); /* * 8. Done, cleanly close the connection */ close_notify: mbedtls_printf(" . Closing the connection..."); /* No error checking, the connection might be closed already */ do { ret = mbedtls_ssl_close_notify(&ssl); } while (ret == MBEDTLS_ERR_SSL_WANT_WRITE); ret = 0; mbedtls_printf(" done\n"); if (--ots) { goto reset; } /* * Final clean-ups and exit */ 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 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_ssl_cookie_free(&cookie_ctx); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_free(&cache); #endif mbedtls_ctr_drbg_free(&ctr_drbg); mbedtls_entropy_free(&entropy); return ret; }
static CURLcode mbed_connect_step1(struct connectdata *conn, int sockindex) { struct Curl_easy *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; const char * const ssl_cafile = SSL_CONN_CONFIG(CAfile); const bool verifypeer = SSL_CONN_CONFIG(verifypeer); const char * const ssl_capath = SSL_CONN_CONFIG(CApath); char * const ssl_cert = SSL_SET_OPTION(cert); const char * const ssl_crlfile = SSL_SET_OPTION(CRLfile); const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name : conn->host.name; const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port; int ret = -1; char errorbuf[128]; errorbuf[0]=0; /* mbedTLS only supports SSLv3 and TLSv1 */ if(SSL_CONN_CONFIG(version) == CURL_SSLVERSION_SSLv2) { failf(data, "mbedTLS does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; } #ifdef THREADING_SUPPORT entropy_init_mutex(&entropy); mbedtls_ctr_drbg_init(&connssl->ctr_drbg); ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, entropy_func_mutex, &entropy, NULL, 0); if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n", -ret, errorbuf); } #else mbedtls_entropy_init(&connssl->entropy); mbedtls_ctr_drbg_init(&connssl->ctr_drbg); ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, mbedtls_entropy_func, &connssl->entropy, NULL, 0); if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n", -ret, errorbuf); } #endif /* THREADING_SUPPORT */ /* Load the trusted CA */ mbedtls_x509_crt_init(&connssl->cacert); if(ssl_cafile) { ret = mbedtls_x509_crt_parse_file(&connssl->cacert, ssl_cafile); if(ret<0) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s", ssl_cafile, -ret, errorbuf); if(verifypeer) return CURLE_SSL_CACERT_BADFILE; } } if(ssl_capath) { ret = mbedtls_x509_crt_parse_path(&connssl->cacert, ssl_capath); if(ret<0) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s", ssl_capath, -ret, errorbuf); if(verifypeer) return CURLE_SSL_CACERT_BADFILE; } } /* Load the client certificate */ mbedtls_x509_crt_init(&connssl->clicert); if(ssl_cert) { ret = mbedtls_x509_crt_parse_file(&connssl->clicert, ssl_cert); if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s", ssl_cert, -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } } /* Load the client private key */ mbedtls_pk_init(&connssl->pk); if(SSL_SET_OPTION(key)) { ret = mbedtls_pk_parse_keyfile(&connssl->pk, SSL_SET_OPTION(key), SSL_SET_OPTION(key_passwd)); if(ret == 0 && !mbedtls_pk_can_do(&connssl->pk, MBEDTLS_PK_RSA)) ret = MBEDTLS_ERR_PK_TYPE_MISMATCH; if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s", SSL_SET_OPTION(key), -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } } /* Load the CRL */ mbedtls_x509_crl_init(&connssl->crl); if(ssl_crlfile) { ret = mbedtls_x509_crl_parse_file(&connssl->crl, ssl_crlfile); if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s", ssl_crlfile, -ret, errorbuf); return CURLE_SSL_CRL_BADFILE; } } infof(data, "mbedTLS: Connecting to %s:%d\n", hostname, port); mbedtls_ssl_config_init(&connssl->config); mbedtls_ssl_init(&connssl->ssl); if(mbedtls_ssl_setup(&connssl->ssl, &connssl->config)) { failf(data, "mbedTLS: ssl_init failed"); return CURLE_SSL_CONNECT_ERROR; } ret = mbedtls_ssl_config_defaults(&connssl->config, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); if(ret) { failf(data, "mbedTLS: ssl_config failed"); return CURLE_SSL_CONNECT_ERROR; } /* new profile with RSA min key len = 1024 ... */ mbedtls_ssl_conf_cert_profile(&connssl->config, &mbedtls_x509_crt_profile_fr); switch(SSL_CONN_CONFIG(version)) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1); infof(data, "mbedTLS: Set min SSL version to TLS 1.0\n"); break; case CURL_SSLVERSION_SSLv3: mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0); mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0); infof(data, "mbedTLS: Set SSL version to SSLv3\n"); break; case CURL_SSLVERSION_TLSv1_0: mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1); mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1); infof(data, "mbedTLS: Set SSL version to TLS 1.0\n"); break; case CURL_SSLVERSION_TLSv1_1: mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_2); mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_2); infof(data, "mbedTLS: Set SSL version to TLS 1.1\n"); break; case CURL_SSLVERSION_TLSv1_2: mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); infof(data, "mbedTLS: Set SSL version to TLS 1.2\n"); break; case CURL_SSLVERSION_TLSv1_3: failf(data, "mbedTLS: TLS 1.3 is not yet supported"); return CURLE_SSL_CONNECT_ERROR; default: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); return CURLE_SSL_CONNECT_ERROR; } mbedtls_ssl_conf_authmode(&connssl->config, MBEDTLS_SSL_VERIFY_OPTIONAL); mbedtls_ssl_conf_rng(&connssl->config, mbedtls_ctr_drbg_random, &connssl->ctr_drbg); mbedtls_ssl_set_bio(&connssl->ssl, &conn->sock[sockindex], mbedtls_net_send, mbedtls_net_recv, NULL /* rev_timeout() */); mbedtls_ssl_conf_ciphersuites(&connssl->config, mbedtls_ssl_list_ciphersuites()); #if defined(MBEDTLS_SSL_SESSION_TICKETS) mbedtls_ssl_conf_session_tickets(&connssl->config, MBEDTLS_SSL_SESSION_TICKETS_DISABLED); #endif /* Check if there's a cached ID we can/should use here! */ if(data->set.general_ssl.sessionid) { void *old_session = NULL; Curl_ssl_sessionid_lock(conn); if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) { ret = mbedtls_ssl_set_session(&connssl->ssl, old_session); if(ret) { Curl_ssl_sessionid_unlock(conn); failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret); return CURLE_SSL_CONNECT_ERROR; } infof(data, "mbedTLS re-using session\n"); } Curl_ssl_sessionid_unlock(conn); } mbedtls_ssl_conf_ca_chain(&connssl->config, &connssl->cacert, &connssl->crl); if(SSL_SET_OPTION(key)) { mbedtls_ssl_conf_own_cert(&connssl->config, &connssl->clicert, &connssl->pk); } if(mbedtls_ssl_set_hostname(&connssl->ssl, hostname)) { /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks *and* the name to set in the SNI extension. So even if curl connects to a host specified as an IP address, this function must be used. */ failf(data, "couldn't set hostname in mbedTLS"); return CURLE_SSL_CONNECT_ERROR; } #ifdef HAS_ALPN if(conn->bits.tls_enable_alpn) { const char **p = &connssl->protocols[0]; #ifdef USE_NGHTTP2 if(data->set.httpversion >= CURL_HTTP_VERSION_2) *p++ = NGHTTP2_PROTO_VERSION_ID; #endif *p++ = ALPN_HTTP_1_1; *p = NULL; /* this function doesn't clone the protocols array, which is why we need to keep it around */ if(mbedtls_ssl_conf_alpn_protocols(&connssl->config, &connssl->protocols[0])) { failf(data, "Failed setting ALPN protocols"); return CURLE_SSL_CONNECT_ERROR; } for(p = &connssl->protocols[0]; *p; ++p) infof(data, "ALPN, offering %s\n", *p); } #endif #ifdef MBEDTLS_DEBUG /* In order to make that work in mbedtls MBEDTLS_DEBUG_C must be defined. */ mbedtls_ssl_conf_dbg(&connssl->config, mbed_debug, data); /* - 0 No debug * - 1 Error * - 2 State change * - 3 Informational * - 4 Verbose */ mbedtls_debug_set_threshold(4); #endif connssl->connecting_state = ssl_connect_2; return CURLE_OK; }
/* * The actual entropy quality is hard to test, but we can at least * test that the functions don't cause errors and write the correct * amount of data to buffers. */ int mbedtls_entropy_self_test( int verbose ) { int ret = 0; mbedtls_entropy_context ctx; unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; size_t i, j; if( verbose != 0 ) mbedtls_printf( " ENTROPY test: " ); mbedtls_entropy_init( &ctx ); /* First do a gather to make sure we have default sources */ if( ( ret = mbedtls_entropy_gather( &ctx ) ) != 0 ) goto cleanup; ret = mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 16, MBEDTLS_ENTROPY_SOURCE_WEAK ); if( ret != 0 ) goto cleanup; if( ( ret = mbedtls_entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 ) goto cleanup; /* * To test that mbedtls_entropy_func writes correct number of bytes: * - use the whole buffer and rely on ASan to detect overruns * - collect entropy 8 times and OR the result in an accumulator: * any byte should then be 0 with probably 2^(-64), so requiring * each of the 32 or 64 bytes to be non-zero has a false failure rate * of at most 2^(-58) which is acceptable. */ for( i = 0; i < 8; i++ ) { if( ( ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 ) goto cleanup; for( j = 0; j < sizeof( buf ); j++ ) acc[j] |= buf[j]; } for( j = 0; j < sizeof( buf ); j++ ) { if( acc[j] == 0 ) { ret = 1; goto cleanup; } } cleanup: mbedtls_entropy_free( &ctx ); if( verbose != 0 ) { if( ret != 0 ) mbedtls_printf( "failed\n" ); else mbedtls_printf( "passed\n" ); mbedtls_printf( "\n" ); } return( ret != 0 ); }
int main( void ) { int ret; mbedtls_net_context listen_fd, client_fd; const char pers[] = "ssl_pthread_server"; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_config conf; mbedtls_x509_crt srvcert; mbedtls_x509_crt cachain; mbedtls_pk_context pkey; #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) unsigned char alloc_buf[100000]; #endif #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_context cache; #endif #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof(alloc_buf) ); #endif #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_init( &cache ); #endif mbedtls_x509_crt_init( &srvcert ); mbedtls_x509_crt_init( &cachain ); mbedtls_ssl_config_init( &conf ); mbedtls_ctr_drbg_init( &ctr_drbg ); memset( threads, 0, sizeof(threads) ); mbedtls_net_init( &listen_fd ); mbedtls_net_init( &client_fd ); mbedtls_mutex_init( &debug_mutex ); base_info.config = &conf; /* * We use only a single entropy source that is used in all the threads. */ mbedtls_entropy_init( &entropy ); /* * 1. Load the certificates and private RSA key */ mbedtls_printf( "\n . 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( &cachain, (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; } mbedtls_pk_init( &pkey ); 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. Seed the random number generator */ mbedtls_printf( " . Seeding the random number generator..." ); if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) ) != 0 ) { mbedtls_printf( " failed: mbedtls_ctr_drbg_seed returned -0x%04x\n", -ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 1c. Prepare SSL configuration */ mbedtls_printf( " . Setting up the SSL data...." ); if( ( ret = mbedtls_ssl_config_defaults( &conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) { mbedtls_printf( " failed: mbedtls_ssl_config_defaults returned -0x%04x\n", -ret ); goto exit; } mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); mbedtls_ssl_conf_dbg( &conf, my_mutexed_debug, stdout ); /* mbedtls_ssl_cache_get() and mbedtls_ssl_cache_set() are thread-safe if * MBEDTLS_THREADING_C is set. */ #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_conf_session_cache( &conf, &cache, mbedtls_ssl_cache_get, mbedtls_ssl_cache_set ); #endif mbedtls_ssl_conf_ca_chain( &conf, &cachain, 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" ); reset: #ifdef MBEDTLS_ERROR_C if( ret != 0 ) { char error_buf[100]; mbedtls_strerror( ret, error_buf, 100 ); mbedtls_printf( " [ main ] Last error was: -0x%04x - %s\n", -ret, error_buf ); } #endif /* * 3. Wait until a client connects */ mbedtls_printf( " [ main ] Waiting for a remote connection\n" ); if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd, NULL, 0, NULL ) ) != 0 ) { mbedtls_printf( " [ main ] failed: mbedtls_net_accept returned -0x%04x\n", ret ); goto exit; } mbedtls_printf( " [ main ] ok\n" ); mbedtls_printf( " [ main ] Creating a new thread\n" ); if( ( ret = thread_create( &client_fd ) ) != 0 ) { mbedtls_printf( " [ main ] failed: thread_create returned %d\n", ret ); mbedtls_net_free( &client_fd ); goto reset; } ret = 0; goto reset; exit: mbedtls_x509_crt_free( &srvcert ); mbedtls_pk_free( &pkey ); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_free( &cache ); #endif mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); mbedtls_ssl_config_free( &conf ); mbedtls_net_free( &listen_fd ); mbedtls_mutex_free( &debug_mutex ); #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) mbedtls_memory_buffer_alloc_free(); #endif #if defined(_WIN32) mbedtls_printf( " Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
int dtls_client_cb(void *args) { int argc; char **argv; char *p; char *q; int ret = 0; int len; mbedtls_net_context server_fd; uint32_t flags; unsigned char buf[1024]; const char *pers = "dtls_client"; int retry_left = MAX_RETRY; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_x509_crt cacert; mbedtls_timing_delay_context timer; #if defined(MBEDTLS_DEBUG_C) mbedtls_debug_set_threshold(DEBUG_LEVEL); #endif char *server_addr = SERVER_ADDR; argc = ((struct pthread_arg *)args)->argc; argv = ((struct pthread_arg *)args)->argv; if (argc == 0) { usage: printf(USAGE_DTLS); goto exit; } else { int i; for (i = 1; i < argc; i++) { p = argv[i]; if ((q = strchr(p, '=')) == NULL) { goto usage; } *q++ = '\0'; if (strcmp(p, "server_addr") == 0) { server_addr = q; } else { goto usage; } } } /* * 0. Initialize the RNG and the session data */ mbedtls_net_init(&server_fd); mbedtls_ssl_init(&ssl); mbedtls_ssl_config_init(&conf); mbedtls_x509_crt_init(&cacert); mbedtls_ctr_drbg_init(&ctr_drbg); mbedtls_printf("\n . Seeding the random number generator..."); fflush(stdout); mbedtls_entropy_init(&entropy); 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"); /* * 0. Load certificates */ mbedtls_printf(" . Loading the CA root certificate ..."); fflush(stdout); ret = mbedtls_x509_crt_parse(&cacert, (const unsigned char *)mbedtls_test_ca_crt_rsa, mbedtls_test_ca_crt_rsa_len); if (ret < 0) { mbedtls_printf(" failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); goto exit; } mbedtls_printf(" ok (%d skipped)\n", ret); /* * 1. Start the connection */ mbedtls_printf(" . Connecting to udp/%s/%s...", server_addr, SERVER_PORT); fflush(stdout); if ((ret = mbedtls_net_connect(&server_fd, server_addr, SERVER_PORT, MBEDTLS_NET_PROTO_UDP)) != 0) { mbedtls_printf(" failed\n ! mbedtls_net_connect returned %d\n\n", ret); goto exit; } mbedtls_printf(" ok\n"); /* * 2. Setup stuff */ mbedtls_printf(" . Setting up the DTLS structure..."); fflush(stdout); if ((ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { mbedtls_printf(" failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret); goto exit; } /* * OPTIONAL is usually a bad choice for security, but makes interop easier * in this simplified example, in which the ca chain is hardcoded. * Production code should set a proper ca chain and use REQUIRED. */ 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); mbedtls_ssl_conf_dbg(&conf, my_debug, stdout); if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) { mbedtls_printf(" failed\n ! mbedtls_ssl_setup returned %d\n\n", ret); goto exit; } if ((ret = mbedtls_ssl_set_hostname(&ssl, SERVER_NAME)) != 0) { mbedtls_printf(" failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret); goto exit; } mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout); mbedtls_ssl_set_timer_cb(&ssl, &timer, mbedtls_timing_set_delay, mbedtls_timing_get_delay); mbedtls_printf(" ok\n"); /* * 4. Handshake */ mbedtls_printf(" . Performing the SSL/TLS handshake..."); fflush(stdout); do { ret = mbedtls_ssl_handshake(&ssl); } while (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE); if (ret != 0) { mbedtls_printf(" failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret); goto exit; } mbedtls_printf(" ok\n"); /* * 5. Verify the server certificate */ mbedtls_printf(" . Verifying peer X.509 certificate..."); /* In real life, we would have used MBEDTLS_SSL_VERIFY_REQUIRED so that the * handshake would not succeed if the peer's cert is bad. Even if we used * MBEDTLS_SSL_VERIFY_OPTIONAL, we would bail out here if 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"); } /* * 6. Write the echo request */ send_request: len = sizeof(MESSAGE) - 1; do { ret = mbedtls_ssl_write(&ssl, (unsigned char *)MESSAGE, len); } while (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE); if (ret < 0) { mbedtls_printf(" failed\n ! mbedtls_ssl_write returned %d\n", ret); goto exit; } len = ret; mbedtls_printf(" > WRITE TO SERVER %d bytes written : %s\n", len, MESSAGE); /* * 7. Read the echo response */ len = sizeof(buf) - 1; memset(buf, 0, sizeof(buf)); do { ret = mbedtls_ssl_read(&ssl, buf, len); } while (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE); if (ret <= 0) { switch (ret) { case MBEDTLS_ERR_SSL_TIMEOUT: mbedtls_printf(" timeout\n\n"); if (retry_left-- > 0) { goto send_request; } goto exit; case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: mbedtls_printf(" connection was closed gracefully\n"); ret = 0; goto close_notify; default: mbedtls_printf(" mbedtls_ssl_read returned -0x%x\n", -ret); goto exit; } } len = ret; mbedtls_printf(" < READ FROM SERVER %d bytes read : %s\n", len, buf); /* * 8. Done, cleanly close the connection */ close_notify: mbedtls_printf(" . Closing the connection..."); /* No error checking, the connection might be closed already */ do { ret = mbedtls_ssl_close_notify(&ssl); } while (ret == MBEDTLS_ERR_SSL_WANT_WRITE); ret = 0; mbedtls_printf(" done\n"); /* * 9. Final clean-ups and exit */ 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 mbedtls_net_free(&server_fd); mbedtls_x509_crt_free(&cacert); 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 /* Shell can not handle large exit numbers -> 1 for errors */ if (ret < 0) { ret = 1; } return 0; }
static CURLcode mbedtls_connect_step1(struct connectdata *conn, int sockindex) { struct SessionHandle *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; bool sni = TRUE; /* default is SNI enabled */ int ret = -1; #ifdef ENABLE_IPV6 struct in6_addr addr; #else struct in_addr addr; #endif void *old_session = NULL; size_t old_session_size = 0; char errorbuf[128]; errorbuf[0]=0; /* mbedTLS only supports SSLv3 and TLSv1 */ if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { failf(data, "mbedTLS does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; } else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) sni = FALSE; /* SSLv3 has no SNI */ #ifdef THREADING_SUPPORT entropy_init_mutex(&entropy); mbedtls_ctr_drbg_init(&connssl->ctr_drbg); ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, entropy_func_mutex, &entropy, connssl->ssn.id, connssl->ssn.id_len); if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n", -ret, errorbuf); } #else mbedtls_entropy_init(&connssl->entropy); mbedtls_ctr_drbg_init(&connssl->ctr_drbg); ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, mbedtls_entropy_func, &connssl->entropy, connssl->ssn.id, connssl->ssn.id_len); if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n", -ret, errorbuf); } #endif /* THREADING_SUPPORT */ /* Load the trusted CA */ mbedtls_x509_crt_init(&connssl->cacert); if(data->set.str[STRING_SSL_CAFILE]) { ret = mbedtls_x509_crt_parse_file(&connssl->cacert, data->set.str[STRING_SSL_CAFILE]); if(ret<0) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s", data->set.str[STRING_SSL_CAFILE], -ret, errorbuf); if(data->set.ssl.verifypeer) return CURLE_SSL_CACERT_BADFILE; } } if(data->set.str[STRING_SSL_CAPATH]) { ret = mbedtls_x509_crt_parse_path(&connssl->cacert, data->set.str[STRING_SSL_CAPATH]); if(ret<0) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s", data->set.str[STRING_SSL_CAPATH], -ret, errorbuf); if(data->set.ssl.verifypeer) return CURLE_SSL_CACERT_BADFILE; } } /* Load the client certificate */ mbedtls_x509_crt_init(&connssl->clicert); if(data->set.str[STRING_CERT]) { ret = mbedtls_x509_crt_parse_file(&connssl->clicert, data->set.str[STRING_CERT]); if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s", data->set.str[STRING_CERT], -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } } /* Load the client private key */ mbedtls_pk_init(&connssl->pk); if(data->set.str[STRING_KEY]) { ret = mbedtls_pk_parse_keyfile(&connssl->pk, data->set.str[STRING_KEY], data->set.str[STRING_KEY_PASSWD]); if(ret == 0 && !mbedtls_pk_can_do(&connssl->pk, MBEDTLS_PK_RSA)) ret = MBEDTLS_ERR_PK_TYPE_MISMATCH; if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s", data->set.str[STRING_KEY], -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } } /* Load the CRL */ mbedtls_x509_crl_init(&connssl->crl); if(data->set.str[STRING_SSL_CRLFILE]) { ret = mbedtls_x509_crl_parse_file(&connssl->crl, data->set.str[STRING_SSL_CRLFILE]); if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s", data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf); return CURLE_SSL_CRL_BADFILE; } } infof(data, "mbedTLS: Connecting to %s:%d\n", conn->host.name, conn->remote_port); mbedtls_ssl_config_init(&connssl->config); mbedtls_ssl_init(&connssl->ssl); if(mbedtls_ssl_setup(&connssl->ssl, &connssl->config)) { failf(data, "mbedTLS: ssl_init failed"); return CURLE_SSL_CONNECT_ERROR; } ret = mbedtls_ssl_config_defaults(&connssl->config, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); if(ret) { failf(data, "mbedTLS: ssl_config failed"); return CURLE_SSL_CONNECT_ERROR; } /* new profile with RSA min key len = 1024 ... */ mbedtls_ssl_conf_cert_profile( &connssl->config, &mbedtls_x509_crt_profile_fr); switch(data->set.ssl.version) { case CURL_SSLVERSION_SSLv3: mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0); infof(data, "mbedTLS: Forced min. SSL Version to be SSLv3\n"); break; case CURL_SSLVERSION_TLSv1_0: mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1); infof(data, "mbedTLS: Forced min. SSL Version to be TLS 1.0\n"); break; case CURL_SSLVERSION_TLSv1_1: mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_2); infof(data, "mbedTLS: Forced min. SSL Version to be TLS 1.1\n"); break; case CURL_SSLVERSION_TLSv1_2: mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); infof(data, "mbedTLS: Forced min. SSL Version to be TLS 1.2\n"); break; } mbedtls_ssl_conf_authmode(&connssl->config, MBEDTLS_SSL_VERIFY_OPTIONAL); mbedtls_ssl_conf_rng(&connssl->config, mbedtls_ctr_drbg_random, &connssl->ctr_drbg); mbedtls_ssl_set_bio(&connssl->ssl, &conn->sock[sockindex], mbedtls_net_send, mbedtls_net_recv, NULL /* rev_timeout() */); mbedtls_ssl_conf_ciphersuites(&connssl->config, mbedtls_ssl_list_ciphersuites()); if(!Curl_ssl_getsessionid(conn, &old_session, &old_session_size)) { memcpy(&connssl->ssn, old_session, old_session_size); infof(data, "mbedTLS re-using session\n"); } mbedtls_ssl_set_session(&connssl->ssl, &connssl->ssn); mbedtls_ssl_conf_ca_chain(&connssl->config, &connssl->cacert, &connssl->crl); if(data->set.str[STRING_KEY]) { mbedtls_ssl_conf_own_cert(&connssl->config, &connssl->clicert, &connssl->pk); } if(!Curl_inet_pton(AF_INET, conn->host.name, &addr) && #ifdef ENABLE_IPV6 !Curl_inet_pton(AF_INET6, conn->host.name, &addr) && #endif sni && mbedtls_ssl_set_hostname(&connssl->ssl, conn->host.name)) { infof(data, "WARNING: failed to configure " "server name indication (SNI) TLS extension\n"); } #ifdef HAS_ALPN if(data->set.ssl_enable_alpn) { const char **p = &connssl->protocols[0]; #ifdef USE_NGHTTP2 if(data->set.httpversion >= CURL_HTTP_VERSION_2) *p++ = NGHTTP2_PROTO_VERSION_ID; #endif *p++ = ALPN_HTTP_1_1; *p = NULL; /* this function doesn't clone the protocols array, which is why we need to keep it around */ if(mbedtls_ssl_conf_alpn_protocols(&connssl->config, &connssl->protocols[0])) { failf(data, "Failed setting ALPN protocols"); return CURLE_SSL_CONNECT_ERROR; } for(p = &connssl->protocols[0]; *p; ++p) infof(data, "ALPN, offering %s\n", *p); } #endif #ifdef MBEDTLS_DEBUG mbedtls_ssl_conf_dbg(&connssl->ssl, mbedtls_debug, data); #endif connssl->connecting_state = ssl_connect_2; return CURLE_OK; }
int main( int argc, char *argv[] ) { int ret; mbedtls_ecdh_context ctx_cli, ctx_srv; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; unsigned char cli_to_srv[32], srv_to_cli[32]; const char pers[] = "ecdh"; ((void) argc); ((void) argv); mbedtls_ecdh_init( &ctx_cli ); mbedtls_ecdh_init( &ctx_srv ); mbedtls_ctr_drbg_init( &ctr_drbg ); /* * Initialize random number generation */ mbedtls_printf( " . Seeding the random number generator..." ); fflush( stdout ); mbedtls_entropy_init( &entropy ); if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, sizeof pers ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * Client: inialize context and generate keypair */ mbedtls_printf( " . Setting up client context..." ); fflush( stdout ); ret = mbedtls_ecp_group_load( &ctx_cli.grp, MBEDTLS_ECP_DP_CURVE25519 ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ecp_group_load returned %d\n", ret ); goto exit; } ret = mbedtls_ecdh_gen_public( &ctx_cli.grp, &ctx_cli.d, &ctx_cli.Q, mbedtls_ctr_drbg_random, &ctr_drbg ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ecdh_gen_public returned %d\n", ret ); goto exit; } ret = mbedtls_mpi_write_binary( &ctx_cli.Q.X, cli_to_srv, 32 ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_write_binary returned %d\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * Server: initialize context and generate keypair */ mbedtls_printf( " . Setting up server context..." ); fflush( stdout ); ret = mbedtls_ecp_group_load( &ctx_srv.grp, MBEDTLS_ECP_DP_CURVE25519 ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ecp_group_load returned %d\n", ret ); goto exit; } ret = mbedtls_ecdh_gen_public( &ctx_srv.grp, &ctx_srv.d, &ctx_srv.Q, mbedtls_ctr_drbg_random, &ctr_drbg ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ecdh_gen_public returned %d\n", ret ); goto exit; } ret = mbedtls_mpi_write_binary( &ctx_srv.Q.X, srv_to_cli, 32 ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_write_binary returned %d\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * Server: read peer's key and generate shared secret */ mbedtls_printf( " . Server reading client key and computing secret..." ); fflush( stdout ); ret = mbedtls_mpi_lset( &ctx_srv.Qp.Z, 1 ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_lset returned %d\n", ret ); goto exit; } ret = mbedtls_mpi_read_binary( &ctx_srv.Qp.X, cli_to_srv, 32 ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_read_binary returned %d\n", ret ); goto exit; } ret = mbedtls_ecdh_compute_shared( &ctx_srv.grp, &ctx_srv.z, &ctx_srv.Qp, &ctx_srv.d, mbedtls_ctr_drbg_random, &ctr_drbg ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ecdh_compute_shared returned %d\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * Client: read peer's key and generate shared secret */ mbedtls_printf( " . Client reading server key and computing secret..." ); fflush( stdout ); ret = mbedtls_mpi_lset( &ctx_cli.Qp.Z, 1 ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_lset returned %d\n", ret ); goto exit; } ret = mbedtls_mpi_read_binary( &ctx_cli.Qp.X, srv_to_cli, 32 ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_read_binary returned %d\n", ret ); goto exit; } ret = mbedtls_ecdh_compute_shared( &ctx_cli.grp, &ctx_cli.z, &ctx_cli.Qp, &ctx_cli.d, mbedtls_ctr_drbg_random, &ctr_drbg ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ecdh_compute_shared returned %d\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * Verification: are the computed secret equal? */ mbedtls_printf( " . Checking if both computed secrets are equal..." ); fflush( stdout ); ret = mbedtls_mpi_cmp_mpi( &ctx_cli.z, &ctx_srv.z ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ecdh_compute_shared returned %d\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); exit: #if defined(_WIN32) mbedtls_printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif mbedtls_ecdh_free( &ctx_srv ); mbedtls_ecdh_free( &ctx_cli ); mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); return( ret != 0 ); }
int pkencrypt_main( int argc, char *argv[] ) { FILE *f; int ret; size_t i, olen = 0; mbedtls_pk_context pk; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; unsigned char input[1024]; unsigned char buf[512]; const char *pers = "mbedtls_pk_encrypt"; ret = 1; mbedtls_ctr_drbg_init( &ctr_drbg ); if( argc != 3 ) { mbedtls_printf( "usage: mbedtls_pk_encrypt <key_file> <string of max 100 characters>\n" ); #if defined(_WIN32) mbedtls_printf( "\n" ); #endif goto exit; } mbedtls_printf( "\n . Seeding the random number generator..." ); fflush( stdout ); mbedtls_entropy_init( &entropy ); 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 -0x%04x\n", -ret ); goto exit; } mbedtls_printf( "\n . Reading public key from '%s'", argv[1] ); fflush( stdout ); mbedtls_pk_init( &pk ); if( ( ret = mbedtls_pk_parse_public_keyfile( &pk, argv[1] ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_pk_parse_public_keyfile returned -0x%04x\n", -ret ); goto exit; } if( strlen( argv[2] ) > 100 ) { mbedtls_printf( " Input data larger than 100 characters.\n\n" ); goto exit; } memcpy( input, argv[2], strlen( argv[2] ) ); /* * Calculate the RSA encryption of the hash. */ mbedtls_printf( "\n . Generating the encrypted value" ); fflush( stdout ); if( ( ret = mbedtls_pk_encrypt( &pk, input, strlen( argv[2] ), buf, &olen, sizeof(buf), mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_pk_encrypt returned -0x%04x\n", -ret ); goto exit; } /* * Write the signature into result-enc.txt */ if( ( f = fopen( "result-enc.txt", "wb+" ) ) == NULL ) { ret = 1; mbedtls_printf( " failed\n ! Could not create %s\n\n", "result-enc.txt" ); goto exit; } for( i = 0; i < olen; i++ ) mbedtls_fprintf( f, "%02X%s", buf[i], ( i + 1 ) % 16 == 0 ? "\r\n" : " " ); fclose( f ); mbedtls_printf( "\n . Done (created \"%s\")\n\n", "result-enc.txt" ); exit: mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); #if defined(MBEDTLS_ERROR_C) if( ret != 0 ) { mbedtls_strerror( ret, (char *) buf, sizeof(buf) ); mbedtls_printf( " ! Last error was: %s\n", buf ); } #endif #if defined(_WIN32) mbedtls_printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
void http_get_task(void *pvParameters) { int successes = 0, failures = 0, ret; printf("HTTP get task starting...\n"); uint32_t flags; unsigned char buf[1024]; const char *pers = "ssl_client1"; 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; /* * 0. Initialize the RNG and the session data */ mbedtls_ssl_init(&ssl); mbedtls_x509_crt_init(&cacert); mbedtls_ctr_drbg_init(&ctr_drbg); printf("\n . 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, (const unsigned char *) pers, strlen(pers))) != 0) { printf(" failed\n ! mbedtls_ctr_drbg_seed returned %d\n", ret); abort(); } printf(" ok\n"); /* * 0. Initialize certificates */ printf(" . Loading the CA root certificate ..."); ret = mbedtls_x509_crt_parse(&cacert, (uint8_t*)server_root_cert, strlen(server_root_cert)+1); if(ret < 0) { printf(" failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); abort(); } printf(" ok (%d skipped)\n", ret); /* Hostname set here should match CN in server certificate */ if((ret = mbedtls_ssl_set_hostname(&ssl, WEB_SERVER)) != 0) { printf(" failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret); abort(); } /* * 2. Setup stuff */ printf(" . 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) { printf(" failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret); goto exit; } printf(" ok\n"); /* OPTIONAL is not optimal for security, in this example it will print a warning if CA verification fails but it will continue to connect. */ 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 MBEDTLS_DEBUG_C mbedtls_debug_set_threshold(DEBUG_LEVEL); mbedtls_ssl_conf_dbg(&conf, my_debug, stdout); #endif if((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) { printf(" failed\n ! mbedtls_ssl_setup returned %d\n\n", ret); goto exit; } /* Wait until we can resolve the DNS for the server, as an indication our network is probably working... */ printf("Waiting for server DNS to resolve... "); err_t dns_err; ip_addr_t host_ip; do { vTaskDelay(500 / portTICK_PERIOD_MS); dns_err = netconn_gethostbyname(WEB_SERVER, &host_ip); } while(dns_err != ERR_OK); printf("done.\n"); while(1) { mbedtls_net_init(&server_fd); printf("top of loop, free heap = %u\n", xPortGetFreeHeapSize()); /* * 1. Start the connection */ printf(" . Connecting to %s:%s...", WEB_SERVER, WEB_PORT); if((ret = mbedtls_net_connect(&server_fd, WEB_SERVER, WEB_PORT, MBEDTLS_NET_PROTO_TCP)) != 0) { printf(" failed\n ! mbedtls_net_connect returned %d\n\n", ret); goto exit; } printf(" ok\n"); mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL); /* * 4. Handshake */ printf(" . 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) { printf(" failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret); goto exit; } } printf(" ok\n"); /* * 5. Verify the server certificate */ 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]; printf(" failed\n"); mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), " ! ", flags); printf("%s\n", vrfy_buf); } else printf(" ok\n"); /* * 3. Write the GET request */ printf(" > Write to server:"); int len = sprintf((char *) buf, GET_REQUEST); while((ret = mbedtls_ssl_write(&ssl, buf, len)) <= 0) { if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { printf(" failed\n ! mbedtls_ssl_write returned %d\n\n", ret); goto exit; } } len = ret; printf(" %d bytes written\n\n%s", len, (char *) buf); /* * 7. Read the HTTP response */ printf(" < Read from server:"); 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 == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) { ret = 0; break; } if(ret < 0) { printf("failed\n ! mbedtls_ssl_read returned %d\n\n", ret); break; } if(ret == 0) { printf("\n\nEOF\n\n"); break; } len = ret; printf(" %d bytes read\n\n%s", len, (char *) buf); } while(1); mbedtls_ssl_close_notify(&ssl); exit: mbedtls_ssl_session_reset(&ssl); mbedtls_net_free(&server_fd); if(ret != 0) { char error_buf[100]; mbedtls_strerror(ret, error_buf, 100); printf("\n\nLast error was: %d - %s\n\n", ret, error_buf); failures++; } else { successes++; } printf("\n\nsuccesses = %d failures = %d\n", successes, failures); for(int countdown = successes ? 10 : 5; countdown >= 0; countdown--) { printf("%d... ", countdown); vTaskDelay(1000 / portTICK_PERIOD_MS); } printf("\nStarting again!\n"); } }
int main(int argc, char *argv[]) { int ret, exitcode; mbedtls_net_context server_fd; uint32_t flags; char scenario[10000] = ""; char server_host[100] = ""; char server_port[6] = ""; char server_ssl_hostname[100] = ""; const char *pers = "dtls_client"; int opt; struct timeval t0, t1; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_x509_crt cacert; mbedtls_timing_delay_context timer; /* Parse command line */ while ((opt = getopt(argc, argv, "h:n:p:s:")) != -1) { switch (opt) { case 'h': strncpy(server_host, optarg, sizeof(server_host)); break; case 'n': strncpy(server_ssl_hostname, optarg, sizeof(server_ssl_hostname)); break; case 'p': strncpy(server_port, optarg, sizeof(server_port)); break; case 's': strncpy(scenario, optarg, sizeof(scenario)); break; default: /* '?' */ print_usage(argv[0]); } } if (!(scenario[0] && server_port[0] && server_host[0])) { print_usage(argv[0]); } if (!server_ssl_hostname[0]) { strncpy(server_ssl_hostname, server_host, sizeof(server_ssl_hostname)); } #if defined(MBEDTLS_DEBUG_C) mbedtls_debug_set_threshold(DEBUG_LEVEL); #endif /* * 0. Initialize the RNG and the session data */ mbedtls_net_init(&server_fd); mbedtls_ssl_init(&ssl); mbedtls_ssl_config_init(&conf); mbedtls_x509_crt_init(&cacert); mbedtls_ctr_drbg_init(&ctr_drbg); plog("Seeding the random number generator..."); mbedtls_entropy_init(&entropy); if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *)pers, strlen(pers))) != 0) { plog("ERROR: failed! mbedtls_ctr_drbg_seed returned %d", ret); goto exit; } /* * 0. Load certificates */ plog("Loading the CA root certificate ..."); ret = mbedtls_x509_crt_parse(&cacert, (const unsigned char *)mbedtls_test_cas_pem, mbedtls_test_cas_pem_len); if (ret < 0) { plog("ERROR: failed! mbedtls_x509_crt_parse returned -0x%x", -ret); goto exit; } plog("Connecting to udp %s:%s (SSL hostname: %s)...", server_host, server_port, server_ssl_hostname); if ((ret = mbedtls_net_connect(&server_fd, server_host, server_port, MBEDTLS_NET_PROTO_UDP)) != 0) { plog("ERROR: failed! mbedtls_net_connect returned %d", ret); goto exit; } plog("The local client UDP source port is %d", get_source_port(server_fd.fd)); plog("Setting up the DTLS structure..."); if ((ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { plog("ERROR: failed! mbedtls_ssl_config_defaults returned %d", ret); goto exit; } /* OPTIONAL is usually a bad choice for security, but makes interop easier * in this simplified example, in which the ca chain is hardcoded. * Production code should set a proper ca chain and use REQUIRED. */ 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); mbedtls_ssl_conf_dbg(&conf, log_mbedtls_debug_callback, NULL); /* TODO timeouts */ if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) { plog("ERROR: failed! mbedtls_ssl_setup returned %d", ret); goto exit; } if ((ret = mbedtls_ssl_set_hostname(&ssl, server_ssl_hostname)) != 0) { plog("ERROR: failed! mbedtls_ssl_set_hostname returned %d", ret); goto exit; } mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout); mbedtls_ssl_set_timer_cb(&ssl, &timer, mbedtls_timing_set_delay, mbedtls_timing_get_delay); plog("Performing the SSL/TLS handshake..."); gettimeofday(&t0, NULL); do { ret = mbedtls_ssl_handshake(&ssl); plog(" ... during SSL handshake, ret=%d (WANT_READ=%d, WANT_WRITE=%d, RECV_FAILED=%d", ret, MBEDTLS_ERR_SSL_WANT_READ, MBEDTLS_ERR_SSL_WANT_WRITE, MBEDTLS_ERR_NET_RECV_FAILED); gettimeofday(&t1, NULL); } while ((duration_ms(&t1, &t0) <= SSL_HANDSHAKE_TIMEOUT_MILLISECS) && (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE)); plog("handshake duration: %d milliseconds", duration_ms(&t1, &t0)); if (duration_ms(&t1, &t0) > SSL_HANDSHAKE_TIMEOUT_MILLISECS) { plog("ERROR: long time to perform handshake: %d milliseconds", duration_ms(&t1, &t0)); ret = MBEDTLS_ERR_SSL_TIMEOUT; goto exit; } if (ret != 0) { plog("ERROR: failed! mbedtls_ssl_handshake returned -0x%x", -ret); goto exit; } plog("Verifying peer X.509 certificate..."); /* In real life, we would have used MBEDTLS_SSL_VERIFY_REQUIRED so that the * handshake would not succeed if the peer's cert is bad. Even if we used * MBEDTLS_SSL_VERIFY_OPTIONAL, we would bail out here if ret != 0 */ if ((flags = mbedtls_ssl_get_verify_result(&ssl)) != 0) { char vrfy_buf[512]; mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), "! ", flags); plog("Verification failed: %s", vrfy_buf); } else { plog("Certificates ok"); } ret = run_scenario(scenario, &ssl); if (ret != 0) { goto exit; } plog("Closing the connection..."); /* No error checking, the connection might be closed already */ do { ret = mbedtls_ssl_close_notify(&ssl); } while (ret == MBEDTLS_ERR_SSL_WANT_WRITE); ret = 0; exit: #ifdef MBEDTLS_ERROR_C if (ret != 0) { char error_buf[100]; mbedtls_strerror(ret, error_buf, 100); plog("ERROR: Last error was: %d - %s", ret, error_buf); } #endif mbedtls_net_free(&server_fd); mbedtls_x509_crt_free(&cacert); mbedtls_ssl_free(&ssl); mbedtls_ssl_config_free(&conf); mbedtls_ctr_drbg_free(&ctr_drbg); mbedtls_entropy_free(&entropy); exitcode = ret == 0 ? 0 : 1; plog("Done, exitcode=%d", exitcode); return exitcode; }
static int conn_link_mbedtls_initialize(void) { if (g_https_data.initialized) return 0; g_https_data.mbedtls = calloc(1, sizeof(*g_https_data.mbedtls)); if (!g_https_data.mbedtls) return -1; mbedtls_platform_set_calloc_free(conn_link_mbedtls_calloc, conn_link_mbedtls_free); mbedtls_ssl_config_init(&g_https_data.mbedtls->conf); mbedtls_ssl_session_init(&g_https_data.mbedtls->saved_session); mbedtls_entropy_init(&g_https_data.mbedtls->entropy); #ifdef CONFIG_MBEDTLS_ENABLE_CTR_DRBG mbedtls_ctr_drbg_init(&g_https_data.mbedtls->drbg); if (mbedtls_ctr_drbg_seed(&g_https_data.mbedtls->drbg, mbedtls_entropy_func, &g_https_data.mbedtls->entropy, (const void *)"sfx", 3) != 0) { goto err_free; } #else const mbedtls_md_info_t *md_info = NULL; #ifdef MBEDTLS_SHA1_C md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); #elif defined(MBEDTLS_SHA256_C) md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); #elif defined(MBEDTLS_SHA512_C) md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512); #endif DEBUGASSERT(md_info != NULL); mbedtls_hmac_drbg_init(&g_https_data.mbedtls->drbg); if (mbedtls_hmac_drbg_seed(&g_https_data.mbedtls->drbg, md_info, mbedtls_entropy_func, &g_https_data.mbedtls->entropy, (const void *)"sfx", 3) != 0) { goto err_free; } #endif if (mbedtls_ssl_config_defaults(&g_https_data.mbedtls->conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) != 0) { goto err_free; } #ifdef CONFIG_MBEDTLS_ENABLE_CTR_DRBG mbedtls_ssl_conf_rng(&g_https_data.mbedtls->conf, mbedtls_ctr_drbg_random, &g_https_data.mbedtls->drbg); #else mbedtls_ssl_conf_rng(&g_https_data.mbedtls->conf, mbedtls_hmac_drbg_random, &g_https_data.mbedtls->drbg); #endif mbedtls_ssl_conf_authmode(&g_https_data.mbedtls->conf, MBEDTLS_SSL_VERIFY_NONE); #ifdef CONFIG_MBEDTLS_MAX_FRAGMENT mbedtls_ssl_conf_max_frag_len(&g_https_data.mbedtls->conf, MBEDTLS_SSL_MAX_FRAG_LEN_512); #endif #ifdef CONFIG_MBEDTLS_TRUNCATED_HMAC mbedtls_ssl_conf_truncated_hmac(&g_https_data.mbedtls->conf, MBEDTLS_SSL_TRUNC_HMAC_ENABLED); #endif #ifdef CONFIG_MBEDTLS_SESSION_TICKET /* Use SSL out-fragment buffer of at least 384 bytes with session tickets, * preferably at least 512 bytes. */ mbedtls_ssl_conf_session_tickets(&g_https_data.mbedtls->conf, MBEDTLS_SSL_SESSION_TICKETS_ENABLED); #endif g_https_data.initialized = true; return 0; err_free: #ifdef CONFIG_MBEDTLS_ENABLE_CTR_DRBG mbedtls_ctr_drbg_free(&g_https_data.mbedtls->drbg); #else mbedtls_hmac_drbg_free(&g_https_data.mbedtls->drbg); #endif mbedtls_ssl_session_free(&g_https_data.mbedtls->saved_session); mbedtls_ssl_config_free(&g_https_data.mbedtls->conf); free(g_https_data.mbedtls); g_https_data.mbedtls = NULL; mbedtls_platform_set_calloc_free(calloc, free); g_https_data.initialized = false; return -1; }
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! mbedtls_ctr_drbg_seed returned %d\n\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! 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! 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! 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! 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! 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! 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 ...\n" ); fflush( stdout ); if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd, NULL, 0, NULL ) ) != 0 ) { mbedtls_printf( " failed! mbedtls_net_accept returned %d\n\n", ret ); goto exit; } /* * 3.5. Forking server thread */ mbedtls_printf( " . Forking to handle connection ..." ); fflush( stdout ); pid = fork(); if( pid < 0 ) { mbedtls_printf(" failed! fork returned %d\n\n", pid ); goto exit; } if( pid != 0 ) { mbedtls_printf( " ok\n" ); if( ( ret = mbedtls_ctr_drbg_reseed( &ctr_drbg, (const unsigned char *) "parent", 6 ) ) != 0 ) { mbedtls_printf( " failed! mbedtls_ctr_drbg_reseed returned %d\n\n", ret ); goto exit; } continue; } mbedtls_net_init( &listen_fd ); pid = getpid(); /* * 4. Setup stuff */ mbedtls_printf( "pid %d: Setting up the SSL data.\n", pid ); fflush( stdout ); if( ( ret = mbedtls_ctr_drbg_reseed( &ctr_drbg, (const unsigned char *) "child", 5 ) ) != 0 ) { mbedtls_printf( "pid %d: SSL setup failed! mbedtls_ctr_drbg_reseed returned %d\n\n", pid, ret ); goto exit; } if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) { mbedtls_printf( "pid %d: SSL setup failed! mbedtls_ssl_setup returned %d\n\n", pid, ret ); goto exit; } mbedtls_ssl_set_bio( &ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, NULL ); mbedtls_printf( "pid %d: SSL setup ok\n", pid ); /* * 5. Handshake */ mbedtls_printf( "pid %d: Performing the SSL/TLS handshake.\n", pid ); fflush( stdout ); while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( "pid %d: SSL handshake failed! mbedtls_ssl_handshake returned %d\n\n", pid, ret ); goto exit; } } mbedtls_printf( "pid %d: SSL handshake ok\n", pid ); /* * 6. Read the HTTP Request */ mbedtls_printf( "pid %d: Start reading from client.\n", pid ); 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( "pid %d: connection was closed gracefully\n", pid ); break; case MBEDTLS_ERR_NET_CONN_RESET: mbedtls_printf( "pid %d: connection was reset by peer\n", pid ); break; default: mbedtls_printf( "pid %d: mbedtls_ssl_read returned %d\n", pid, ret ); break; } break; } len = ret; mbedtls_printf( "pid %d: %d bytes read\n\n%s", pid, len, (char *) buf ); if( ret > 0 ) break; } while( 1 ); /* * 7. Write the 200 Response */ mbedtls_printf( "pid %d: Start writing to client.\n", pid ); 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( "pid %d: Write failed! peer closed the connection\n\n", pid ); goto exit; } if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( "pid %d: Write failed! mbedtls_ssl_write returned %d\n\n", pid, ret ); goto exit; } } len = ret; mbedtls_printf( "pid %d: %d bytes written\n\n%s\n", pid, 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 ); }
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; }
int ssl_init_info(int *server_fd,ssl_info *sslinfo) { int ret; const char *pers = "ssl"; mbedtls_x509_crt_init(&sslinfo->cacert ); mbedtls_ctr_drbg_init(&sslinfo->ctr_drbg); mbedtls_entropy_init(&sslinfo->entropy ); if( mbedtls_ctr_drbg_seed( &sslinfo->ctr_drbg, mbedtls_entropy_func, &sslinfo->entropy, (const unsigned char *) pers, strlen( pers ) ) != 0 ) { return -1; } mbedtls_ssl_init( &sslinfo->ssl ); mbedtls_ssl_config_init( &sslinfo->conf ); if( ( ret = mbedtls_ssl_config_defaults( &sslinfo->conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) { echo( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); return -1; } mbedtls_ssl_conf_endpoint( &sslinfo->conf, MBEDTLS_SSL_IS_CLIENT ); mbedtls_ssl_conf_authmode( &sslinfo->conf, MBEDTLS_SSL_VERIFY_OPTIONAL ); mbedtls_ssl_conf_ca_chain( &sslinfo->conf, &sslinfo->cacert,NULL); mbedtls_ssl_conf_rng( &sslinfo->conf, mbedtls_ctr_drbg_random, &sslinfo->ctr_drbg ); if( ( ret = mbedtls_ssl_setup( &sslinfo->ssl, &sslinfo->conf ) ) != 0 ) { echo( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); return -1; } mbedtls_ssl_set_bio( &sslinfo->ssl, server_fd,mbedtls_net_send, mbedtls_net_recv,NULL ); mbedtls_ssl_set_session(&sslinfo->ssl, &ssn); while((ret = mbedtls_ssl_handshake(&sslinfo->ssl))!=0) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { echo( " failed\n ! ssl_handshake returned -0x%x\n\n", -ret ); return -1; } //CPU sleep sleeps(1); } if((ret = mbedtls_ssl_get_verify_result( &sslinfo->ssl ) ) != 0 ) { // echo( "Verifying peer X.509 certificate...failed \r\n" ); } else { echo( " ok\n" ); } //保存session if( ( ret = mbedtls_ssl_get_session( &sslinfo->ssl, &ssn ) ) != 0 ) { //失败初始化 memset(&ssn, 0, sizeof(mbedtls_ssl_session)); } return 0; }
static int create_ssl_handle(esp_tls_t *tls, const char *hostname, size_t hostlen, const esp_tls_cfg_t *cfg) { int ret; mbedtls_net_init(&tls->server_fd); tls->server_fd.fd = tls->sockfd; mbedtls_ssl_init(&tls->ssl); mbedtls_ctr_drbg_init(&tls->ctr_drbg); mbedtls_ssl_config_init(&tls->conf); mbedtls_entropy_init(&tls->entropy); if ((ret = mbedtls_ctr_drbg_seed(&tls->ctr_drbg, mbedtls_entropy_func, &tls->entropy, NULL, 0)) != 0) { ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned %d", ret); goto exit; } /* Hostname set here should match CN in server certificate */ char *use_host = strndup(hostname, hostlen); if (!use_host) { goto exit; } if ((ret = mbedtls_ssl_set_hostname(&tls->ssl, use_host)) != 0) { ESP_LOGE(TAG, "mbedtls_ssl_set_hostname returned -0x%x", -ret); free(use_host); goto exit; } free(use_host); if ((ret = mbedtls_ssl_config_defaults(&tls->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; } #ifdef CONFIG_MBEDTLS_SSL_ALPN if (cfg->alpn_protos) { mbedtls_ssl_conf_alpn_protocols(&tls->conf, cfg->alpn_protos); } #endif if (cfg->use_global_ca_store == true) { if (global_cacert == NULL) { ESP_LOGE(TAG, "global_cacert is NULL"); goto exit; } tls->cacert_ptr = global_cacert; mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED); mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL); } else if (cfg->cacert_pem_buf != NULL) { tls->cacert_ptr = &tls->cacert; mbedtls_x509_crt_init(tls->cacert_ptr); ret = mbedtls_x509_crt_parse(tls->cacert_ptr, cfg->cacert_pem_buf, cfg->cacert_pem_bytes); if (ret < 0) { ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); goto exit; } mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_REQUIRED); mbedtls_ssl_conf_ca_chain(&tls->conf, tls->cacert_ptr, NULL); } else { mbedtls_ssl_conf_authmode(&tls->conf, MBEDTLS_SSL_VERIFY_NONE); } if (cfg->clientcert_pem_buf != NULL && cfg->clientkey_pem_buf != NULL) { mbedtls_x509_crt_init(&tls->clientcert); mbedtls_pk_init(&tls->clientkey); ret = mbedtls_x509_crt_parse(&tls->clientcert, cfg->clientcert_pem_buf, cfg->clientcert_pem_bytes); if (ret < 0) { ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); goto exit; } ret = mbedtls_pk_parse_key(&tls->clientkey, cfg->clientkey_pem_buf, cfg->clientkey_pem_bytes, cfg->clientkey_password, cfg->clientkey_password_len); if (ret < 0) { ESP_LOGE(TAG, "mbedtls_pk_parse_keyfile returned -0x%x\n\n", -ret); goto exit; } ret = mbedtls_ssl_conf_own_cert(&tls->conf, &tls->clientcert, &tls->clientkey); if (ret < 0) { ESP_LOGE(TAG, "mbedtls_ssl_conf_own_cert returned -0x%x\n\n", -ret); goto exit; } } else if (cfg->clientcert_pem_buf != NULL || cfg->clientkey_pem_buf != NULL) { ESP_LOGE(TAG, "You have to provide both clientcert_pem_buf and clientkey_pem_buf for mutual authentication\n\n"); goto exit; } mbedtls_ssl_conf_rng(&tls->conf, mbedtls_ctr_drbg_random, &tls->ctr_drbg); #ifdef CONFIG_MBEDTLS_DEBUG mbedtls_esp_enable_debug_log(&tls->conf, 4); #endif if ((ret = mbedtls_ssl_setup(&tls->ssl, &tls->conf)) != 0) { ESP_LOGE(TAG, "mbedtls_ssl_setup returned -0x%x\n\n", -ret); goto exit; } mbedtls_ssl_set_bio(&tls->ssl, &tls->server_fd, mbedtls_net_send, mbedtls_net_recv, NULL); return 0; exit: mbedtls_cleanup(tls); return -1; }
void dtls_client(void) { int ret = exit_ok; struct udp_context ctx; struct dtls_timing_context timer; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_ctr_drbg_init(&ctr_drbg); mbedtls_platform_set_printf(printf); /* * 0. Initialize and setup stuff */ mbedtls_ssl_init(&ssl); mbedtls_ssl_config_init(&conf); mbedtls_printf("\n . Seeding the random number generator..."); mbedtls_entropy_init(&entropy); mbedtls_entropy_add_source(&entropy, entropy_source, NULL, MBEDTLS_ENTROPY_MAX_GATHER, MBEDTLS_ENTROPY_SOURCE_STRONG); if (mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *)pers, strlen(pers)) != 0) { ret = ctr_drbg_seed_failed; mbedtls_printf (" failed\n ! mbedtls_ctr_drbg_seed returned 0x%x\n", ret); goto exit; } mbedtls_printf(" ok\n"); mbedtls_printf(" . Setting up the DTLS structure..."); ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_PRESET_DEFAULT); if (ret != 0) { ret = ssl_config_defaults_failed; mbedtls_printf(" failed! returned 0x%x\n\n", ret); goto exit; } /* Modify this to change the default timeouts for the DTSL handshake */ /* mbedtls_ssl_conf_handshake_timeout( &conf, min, max ); */ #if defined(MBEDTLS_DEBUG_C) mbedtls_debug_set_threshold(DEBUG_THRESHOLD); #endif mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg); mbedtls_ssl_conf_dbg(&conf, my_debug, NULL); #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) mbedtls_memory_buffer_alloc_init(heap, sizeof(heap)); #endif if (mbedtls_ssl_setup(&ssl, &conf) != 0) { ret = ssl_setup_failed; mbedtls_printf (" failed\n ! mbedtls_ssl_setup returned 0x%x\n\n", ret); goto exit; } mbedtls_printf(" ok\n"); /* * 1. Start the connection */ mbedtls_printf(" . Connecting to udp %d.%d.%d.%d:%d...", SERVER_IPADDR0, SERVER_IPADDR1, SERVER_IPADDR2, SERVER_IPADDR3, SERVER_PORT); if (udp_init(&ctx) != 0) { ret = connect_failed; mbedtls_printf(" failed\n ! udp_init returned 0x%x\n\n", ret); goto exit; } mbedtls_printf(" ok\n"); #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) mbedtls_printf(" . Setting up ecjpake password ..."); if (mbedtls_ssl_set_hs_ecjpake_password (&ssl, ecjpake_pw, ECJPAKE_PW_SIZE) != 0) { mbedtls_printf(" failed! set ecjpake password returned %d\n\n", ssl_setup_failed); goto exit; } #endif mbedtls_printf(" ok\n"); mbedtls_ssl_set_timer_cb(&ssl, &timer, dtls_timing_set_delay, dtls_timing_get_delay); mbedtls_ssl_set_bio(&ssl, &ctx, udp_tx, udp_rx, NULL); mbedtls_printf(" . Performing the SSL/TLS handshake..."); ret = mbedtls_ssl_handshake(&ssl); if (ret != 0) { ret = ssl_handshake_failed; mbedtls_printf (" failed\n ! mbedtls_ssl_handshake returned 0x%x\n", ret); goto exit; } mbedtls_printf(" ok\n"); /* * 2. Write the GET request and close the connection */ mbedtls_printf(" > Write to server:"); if (mbedtls_ssl_write(&ssl, (const unsigned char *)GET_REQUEST, sizeof(GET_REQUEST) - 1) <= 0) { ret = ssl_write_failed; mbedtls_printf (" failed\n ! mbedtls_ssl_write returned 0x%x\n\n", ret); goto exit; } mbedtls_printf(" ok\n"); mbedtls_printf(" . Closing the connection..."); mbedtls_ssl_close_notify(&ssl); mbedtls_printf(" done\n"); exit: mbedtls_ssl_free(&ssl); mbedtls_ssl_config_free(&conf); mbedtls_ctr_drbg_free(&ctr_drbg); mbedtls_entropy_free(&entropy); }
STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) { // Verify the socket object has the full stream protocol mp_get_stream_raise(sock, MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL); #if MICROPY_PY_USSL_FINALISER mp_obj_ssl_socket_t *o = m_new_obj_with_finaliser(mp_obj_ssl_socket_t); #else mp_obj_ssl_socket_t *o = m_new_obj(mp_obj_ssl_socket_t); #endif o->base.type = &ussl_socket_type; o->sock = sock; int ret; mbedtls_ssl_init(&o->ssl); mbedtls_ssl_config_init(&o->conf); mbedtls_x509_crt_init(&o->cacert); mbedtls_x509_crt_init(&o->cert); mbedtls_pk_init(&o->pkey); mbedtls_ctr_drbg_init(&o->ctr_drbg); #ifdef MBEDTLS_DEBUG_C // Debug level (0-4) mbedtls_debug_set_threshold(0); #endif mbedtls_entropy_init(&o->entropy); const byte seed[] = "upy"; ret = mbedtls_ctr_drbg_seed(&o->ctr_drbg, mbedtls_entropy_func, &o->entropy, seed, sizeof(seed)); if (ret != 0) { goto cleanup; } ret = mbedtls_ssl_config_defaults(&o->conf, args->server_side.u_bool ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); if (ret != 0) { goto cleanup; } mbedtls_ssl_conf_authmode(&o->conf, MBEDTLS_SSL_VERIFY_NONE); mbedtls_ssl_conf_rng(&o->conf, mbedtls_ctr_drbg_random, &o->ctr_drbg); #ifdef MBEDTLS_DEBUG_C mbedtls_ssl_conf_dbg(&o->conf, mbedtls_debug, NULL); #endif ret = mbedtls_ssl_setup(&o->ssl, &o->conf); if (ret != 0) { goto cleanup; } if (args->server_hostname.u_obj != mp_const_none) { const char *sni = mp_obj_str_get_str(args->server_hostname.u_obj); ret = mbedtls_ssl_set_hostname(&o->ssl, sni); if (ret != 0) { goto cleanup; } } mbedtls_ssl_set_bio(&o->ssl, &o->sock, _mbedtls_ssl_send, _mbedtls_ssl_recv, NULL); if (args->key.u_obj != MP_OBJ_NULL) { size_t key_len; const byte *key = (const byte*)mp_obj_str_get_data(args->key.u_obj, &key_len); // len should include terminating null ret = mbedtls_pk_parse_key(&o->pkey, key, key_len + 1, NULL, 0); assert(ret == 0); size_t cert_len; const byte *cert = (const byte*)mp_obj_str_get_data(args->cert.u_obj, &cert_len); // len should include terminating null ret = mbedtls_x509_crt_parse(&o->cert, cert, cert_len + 1); assert(ret == 0); ret = mbedtls_ssl_conf_own_cert(&o->conf, &o->cert, &o->pkey); assert(ret == 0); } if (args->do_handshake.u_bool) { while ((ret = mbedtls_ssl_handshake(&o->ssl)) != 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { printf("mbedtls_ssl_handshake error: -%x\n", -ret); goto cleanup; } } } return o; cleanup: mbedtls_pk_free(&o->pkey); mbedtls_x509_crt_free(&o->cert); mbedtls_x509_crt_free(&o->cacert); mbedtls_ssl_free(&o->ssl); mbedtls_ssl_config_free(&o->conf); mbedtls_ctr_drbg_free(&o->ctr_drbg); mbedtls_entropy_free(&o->entropy); if (ret == MBEDTLS_ERR_SSL_ALLOC_FAILED) { mp_raise_OSError(MP_ENOMEM); } else { mp_raise_OSError(MP_EIO); } }
otError Dtls::Setup(bool aClient) { int rval; // do not handle new connection before guard time expired VerifyOrExit(mState == kStateOpen, rval = MBEDTLS_ERR_SSL_TIMEOUT); mState = kStateInitializing; mbedtls_ssl_init(&mSsl); mbedtls_ssl_config_init(&mConf); mbedtls_ctr_drbg_init(&mCtrDrbg); mbedtls_entropy_init(&mEntropy); #if OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE #ifdef MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED mbedtls_x509_crt_init(&mCaChain); mbedtls_x509_crt_init(&mOwnCert); mbedtls_pk_init(&mPrivateKey); #endif // MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED #endif // OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE rval = mbedtls_entropy_add_source(&mEntropy, &Dtls::HandleMbedtlsEntropyPoll, NULL, MBEDTLS_ENTROPY_MIN_PLATFORM, MBEDTLS_ENTROPY_SOURCE_STRONG); VerifyOrExit(rval == 0); { otExtAddress eui64; otPlatRadioGetIeeeEui64(&GetInstance(), eui64.m8); rval = mbedtls_ctr_drbg_seed(&mCtrDrbg, mbedtls_entropy_func, &mEntropy, eui64.m8, sizeof(eui64)); VerifyOrExit(rval == 0); } rval = mbedtls_ssl_config_defaults(&mConf, aClient ? MBEDTLS_SSL_IS_CLIENT : MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_PRESET_DEFAULT); VerifyOrExit(rval == 0); #if OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE if (mVerifyPeerCertificate && mCipherSuites[0] == MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8) { mbedtls_ssl_conf_authmode(&mConf, MBEDTLS_SSL_VERIFY_REQUIRED); } else { mbedtls_ssl_conf_authmode(&mConf, MBEDTLS_SSL_VERIFY_NONE); } #else OT_UNUSED_VARIABLE(mVerifyPeerCertificate); #endif // OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE mbedtls_ssl_conf_rng(&mConf, mbedtls_ctr_drbg_random, &mCtrDrbg); mbedtls_ssl_conf_min_version(&mConf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); mbedtls_ssl_conf_max_version(&mConf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); mbedtls_ssl_conf_ciphersuites(&mConf, mCipherSuites); mbedtls_ssl_conf_export_keys_cb(&mConf, HandleMbedtlsExportKeys, this); mbedtls_ssl_conf_handshake_timeout(&mConf, 8000, 60000); mbedtls_ssl_conf_dbg(&mConf, HandleMbedtlsDebug, this); #if OPENTHREAD_ENABLE_BORDER_AGENT || OPENTHREAD_ENABLE_COMMISSIONER || OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE if (!aClient) { mbedtls_ssl_cookie_init(&mCookieCtx); rval = mbedtls_ssl_cookie_setup(&mCookieCtx, mbedtls_ctr_drbg_random, &mCtrDrbg); VerifyOrExit(rval == 0); mbedtls_ssl_conf_dtls_cookies(&mConf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check, &mCookieCtx); } #endif // OPENTHREAD_ENABLE_BORDER_AGENT || OPENTHREAD_ENABLE_COMMISSIONER || OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE rval = mbedtls_ssl_setup(&mSsl, &mConf); VerifyOrExit(rval == 0); mbedtls_ssl_set_bio(&mSsl, this, &Dtls::HandleMbedtlsTransmit, HandleMbedtlsReceive, NULL); mbedtls_ssl_set_timer_cb(&mSsl, this, &Dtls::HandleMbedtlsSetTimer, HandleMbedtlsGetTimer); if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8) { rval = mbedtls_ssl_set_hs_ecjpake_password(&mSsl, mPsk, mPskLength); } #if OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE else { rval = SetApplicationCoapSecureKeys(); } #endif // OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE VerifyOrExit(rval == 0); mReceiveMessage = NULL; mMessageSubType = Message::kSubTypeNone; mState = kStateConnecting; if (mCipherSuites[0] == MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8) { otLogInfoMeshCoP("DTLS started"); } #if OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE else { otLogInfoCoap("Application Coap Secure DTLS started"); } #endif // OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE mState = kStateConnecting; Process(); exit: if ((mState == kStateInitializing) && (rval != 0)) { mState = kStateOpen; FreeMbedtls(); } return MapError(rval); }
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!"); } }
int main( void ) { int ret, len; mbedtls_net_context listen_fd, client_fd; unsigned char buf[1024]; const char *pers = "ssl_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; #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_context cache; #endif mbedtls_net_init( &listen_fd ); mbedtls_net_init( &client_fd ); mbedtls_ssl_init( &ssl ); mbedtls_ssl_config_init( &conf ); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_init( &cache ); #endif mbedtls_x509_crt_init( &srvcert ); mbedtls_pk_init( &pkey ); mbedtls_entropy_init( &entropy ); mbedtls_ctr_drbg_init( &ctr_drbg ); #if defined(MBEDTLS_DEBUG_C) mbedtls_debug_set_threshold( DEBUG_LEVEL ); #endif /* * 1. Load the certificates and private RSA key */ mbedtls_printf( "\n . 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" ); /* * 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" ); /* * 3. Seed the RNG */ mbedtls_printf( " . Seeding the random number 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" ); /* * 4. Setup stuff */ mbedtls_printf( " . Setting up the SSL data...." ); 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 ); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_conf_session_cache( &conf, &cache, mbedtls_ssl_cache_get, mbedtls_ssl_cache_set ); #endif 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; } if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); reset: #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 mbedtls_net_free( &client_fd ); mbedtls_ssl_session_reset( &ssl ); /* * 3. Wait until a client connects */ 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_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 reset; } } 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 -0x%x\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( ( 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 reset; } 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_printf( " . Closing the connection..." ); while( ( ret = mbedtls_ssl_close_notify( &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 reset; } } mbedtls_printf( " ok\n" ); 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 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 ); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_free( &cache ); #endif 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, char **argv ) { int ret = 1; mbedtls_mpi G, P, Q; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; const char *pers = "dh_genprime"; FILE *fout; int nbits = DFL_BITS; int i; char *p, *q; mbedtls_mpi_init( &G ); mbedtls_mpi_init( &P ); mbedtls_mpi_init( &Q ); mbedtls_ctr_drbg_init( &ctr_drbg ); mbedtls_entropy_init( &entropy ); if( argc == 0 ) { usage: mbedtls_printf( USAGE ); return( 1 ); } for( i = 1; i < argc; i++ ) { p = argv[i]; if( ( q = strchr( p, '=' ) ) == NULL ) goto usage; *q++ = '\0'; if( strcmp( p, "bits" ) == 0 ) { nbits = atoi( q ); if( nbits < 0 || nbits > MBEDTLS_MPI_MAX_BITS ) goto usage; } else goto usage; } if( ( ret = mbedtls_mpi_read_string( &G, 10, GENERATOR ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_read_string returned %d\n", ret ); goto exit; } mbedtls_printf( " ! Generating large primes may take minutes!\n" ); mbedtls_printf( "\n . Seeding the random number 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 . Generating the modulus, please wait..." ); fflush( stdout ); /* * This can take a long time... */ if( ( ret = mbedtls_mpi_gen_prime( &P, nbits, 1, mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_gen_prime returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n . Verifying that Q = (P-1)/2 is prime..." ); fflush( stdout ); if( ( ret = mbedtls_mpi_sub_int( &Q, &P, 1 ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_sub_int returned %d\n\n", ret ); goto exit; } if( ( ret = mbedtls_mpi_div_int( &Q, NULL, &Q, 2 ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_div_int returned %d\n\n", ret ); goto exit; } if( ( ret = mbedtls_mpi_is_prime( &Q, mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_is_prime returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n . Exporting the value in dh_prime.txt..." ); fflush( stdout ); if( ( fout = fopen( "dh_prime.txt", "wb+" ) ) == NULL ) { ret = 1; mbedtls_printf( " failed\n ! Could not create dh_prime.txt\n\n" ); goto exit; } if( ( ret = mbedtls_mpi_write_file( "P = ", &P, 16, fout ) != 0 ) || ( ret = mbedtls_mpi_write_file( "G = ", &G, 16, fout ) != 0 ) ) { mbedtls_printf( " failed\n ! mbedtls_mpi_write_file returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n\n" ); fclose( fout ); exit: mbedtls_mpi_free( &G ); mbedtls_mpi_free( &P ); mbedtls_mpi_free( &Q ); 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 ); }
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; }
static CURLcode mbed_connect_step1(struct connectdata *conn, int sockindex) { struct SessionHandle *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; int ret = -1; void *old_session = NULL; char errorbuf[128]; errorbuf[0]=0; /* mbedTLS only supports SSLv3 and TLSv1 */ if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) { failf(data, "mbedTLS does not support SSLv2"); return CURLE_SSL_CONNECT_ERROR; } #ifdef THREADING_SUPPORT entropy_init_mutex(&entropy); mbedtls_ctr_drbg_init(&connssl->ctr_drbg); ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, entropy_func_mutex, &entropy, NULL, 0); if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n", -ret, errorbuf); } #else mbedtls_entropy_init(&connssl->entropy); mbedtls_ctr_drbg_init(&connssl->ctr_drbg); ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, mbedtls_entropy_func, &connssl->entropy, NULL, 0); if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Failed - mbedTLS: ctr_drbg_init returned (-0x%04X) %s\n", -ret, errorbuf); } #endif /* THREADING_SUPPORT */ /* Load the trusted CA */ mbedtls_x509_crt_init(&connssl->cacert); if(data->set.str[STRING_SSL_CAFILE]) { ret = mbedtls_x509_crt_parse_file(&connssl->cacert, data->set.str[STRING_SSL_CAFILE]); if(ret<0) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s", data->set.str[STRING_SSL_CAFILE], -ret, errorbuf); if(data->set.ssl.verifypeer) return CURLE_SSL_CACERT_BADFILE; } } if(data->set.str[STRING_SSL_CAPATH]) { ret = mbedtls_x509_crt_parse_path(&connssl->cacert, data->set.str[STRING_SSL_CAPATH]); if(ret<0) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s", data->set.str[STRING_SSL_CAPATH], -ret, errorbuf); if(data->set.ssl.verifypeer) return CURLE_SSL_CACERT_BADFILE; } } /* Load the client certificate */ mbedtls_x509_crt_init(&connssl->clicert); if(data->set.str[STRING_CERT]) { ret = mbedtls_x509_crt_parse_file(&connssl->clicert, data->set.str[STRING_CERT]); if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s", data->set.str[STRING_CERT], -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } } /* Load the client private key */ mbedtls_pk_init(&connssl->pk); if(data->set.str[STRING_KEY]) { ret = mbedtls_pk_parse_keyfile(&connssl->pk, data->set.str[STRING_KEY], data->set.str[STRING_KEY_PASSWD]); if(ret == 0 && !mbedtls_pk_can_do(&connssl->pk, MBEDTLS_PK_RSA)) ret = MBEDTLS_ERR_PK_TYPE_MISMATCH; if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s", data->set.str[STRING_KEY], -ret, errorbuf); return CURLE_SSL_CERTPROBLEM; } } /* Load the CRL */ mbedtls_x509_crl_init(&connssl->crl); if(data->set.str[STRING_SSL_CRLFILE]) { ret = mbedtls_x509_crl_parse_file(&connssl->crl, data->set.str[STRING_SSL_CRLFILE]); if(ret) { #ifdef MBEDTLS_ERROR_C mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); #endif /* MBEDTLS_ERROR_C */ failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s", data->set.str[STRING_SSL_CRLFILE], -ret, errorbuf); return CURLE_SSL_CRL_BADFILE; } } infof(data, "mbedTLS: Connecting to %s:%d\n", conn->host.name, conn->remote_port); mbedtls_ssl_config_init(&connssl->config); mbedtls_ssl_init(&connssl->ssl); if(mbedtls_ssl_setup(&connssl->ssl, &connssl->config)) { failf(data, "mbedTLS: ssl_init failed"); return CURLE_SSL_CONNECT_ERROR; } ret = mbedtls_ssl_config_defaults(&connssl->config, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); if(ret) { failf(data, "mbedTLS: ssl_config failed"); return CURLE_SSL_CONNECT_ERROR; } /* new profile with RSA min key len = 1024 ... */ mbedtls_ssl_conf_cert_profile(&connssl->config, &mbedtls_x509_crt_profile_fr); switch(data->set.ssl.version) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1); infof(data, "mbedTLS: Set min SSL version to TLS 1.0\n"); break; case CURL_SSLVERSION_SSLv3: mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0); mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0); infof(data, "mbedTLS: Set SSL version to SSLv3\n"); break; case CURL_SSLVERSION_TLSv1_0: mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1); mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1); infof(data, "mbedTLS: Set SSL version to TLS 1.0\n"); break; case CURL_SSLVERSION_TLSv1_1: mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_2); mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_2); infof(data, "mbedTLS: Set SSL version to TLS 1.1\n"); break; case CURL_SSLVERSION_TLSv1_2: mbedtls_ssl_conf_min_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); mbedtls_ssl_conf_max_version(&connssl->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); infof(data, "mbedTLS: Set SSL version to TLS 1.2\n"); break; default: failf(data, "mbedTLS: Unsupported SSL protocol version"); return CURLE_SSL_CONNECT_ERROR; } mbedtls_ssl_conf_authmode(&connssl->config, MBEDTLS_SSL_VERIFY_OPTIONAL); mbedtls_ssl_conf_rng(&connssl->config, mbedtls_ctr_drbg_random, &connssl->ctr_drbg); mbedtls_ssl_set_bio(&connssl->ssl, &conn->sock[sockindex], mbedtls_net_send, mbedtls_net_recv, NULL /* rev_timeout() */); mbedtls_ssl_conf_ciphersuites(&connssl->config, mbedtls_ssl_list_ciphersuites()); if(!Curl_ssl_getsessionid(conn, &old_session, NULL)) { ret = mbedtls_ssl_set_session(&connssl->ssl, old_session); if(ret) { failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret); return CURLE_SSL_CONNECT_ERROR; } infof(data, "mbedTLS re-using session\n"); } mbedtls_ssl_conf_ca_chain(&connssl->config, &connssl->cacert, &connssl->crl); if(data->set.str[STRING_KEY]) { mbedtls_ssl_conf_own_cert(&connssl->config, &connssl->clicert, &connssl->pk); } if(mbedtls_ssl_set_hostname(&connssl->ssl, conn->host.name)) { /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks *and* the name to set in the SNI extension. So even if curl connects to a host specified as an IP address, this function must be used. */ failf(data, "couldn't set hostname in mbedTLS"); return CURLE_SSL_CONNECT_ERROR; } #ifdef HAS_ALPN if(conn->bits.tls_enable_alpn) { const char **p = &connssl->protocols[0]; #ifdef USE_NGHTTP2 if(data->set.httpversion >= CURL_HTTP_VERSION_2) *p++ = NGHTTP2_PROTO_VERSION_ID; #endif *p++ = ALPN_HTTP_1_1; *p = NULL; /* this function doesn't clone the protocols array, which is why we need to keep it around */ if(mbedtls_ssl_conf_alpn_protocols(&connssl->config, &connssl->protocols[0])) { failf(data, "Failed setting ALPN protocols"); return CURLE_SSL_CONNECT_ERROR; } for(p = &connssl->protocols[0]; *p; ++p) infof(data, "ALPN, offering %s\n", *p); } #endif #ifdef MBEDTLS_DEBUG mbedtls_ssl_conf_dbg(&connssl->config, mbedtls_debug, data); #endif connssl->connecting_state = ssl_connect_2; return CURLE_OK; }
int main( void ) { int ret = exit_ok; mbedtls_net_context server_fd; struct sockaddr_in addr; #if defined(MBEDTLS_X509_CRT_PARSE_C) mbedtls_x509_crt ca; #endif mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_ctr_drbg_init( &ctr_drbg ); /* * 0. Initialize and setup stuff */ mbedtls_net_init( &server_fd ); mbedtls_ssl_init( &ssl ); mbedtls_ssl_config_init( &conf ); #if defined(MBEDTLS_X509_CRT_PARSE_C) mbedtls_x509_crt_init( &ca ); #endif mbedtls_entropy_init( &entropy ); if( mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen( pers ) ) != 0 ) { ret = ctr_drbg_seed_failed; goto exit; } if( mbedtls_ssl_config_defaults( &conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT ) != 0 ) { ret = ssl_config_defaults_failed; goto exit; } mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) mbedtls_ssl_conf_psk( &conf, psk, sizeof( psk ), (const unsigned char *) psk_id, sizeof( psk_id ) - 1 ); #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) if( mbedtls_x509_crt_parse_der( &ca, ca_cert, sizeof( ca_cert ) ) != 0 ) { ret = x509_crt_parse_failed; goto exit; } mbedtls_ssl_conf_ca_chain( &conf, &ca, NULL ); mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_REQUIRED ); #endif if( mbedtls_ssl_setup( &ssl, &conf ) != 0 ) { ret = ssl_setup_failed; goto exit; } #if defined(MBEDTLS_X509_CRT_PARSE_C) if( mbedtls_ssl_set_hostname( &ssl, HOSTNAME ) != 0 ) { ret = hostname_failed; goto exit; } #endif /* * 1. Start the connection */ memset( &addr, 0, sizeof( addr ) ); addr.sin_family = AF_INET; ret = 1; /* for endianness detection */ addr.sin_port = *((char *) &ret) == ret ? PORT_LE : PORT_BE; addr.sin_addr.s_addr = *((char *) &ret) == ret ? ADDR_LE : ADDR_BE; ret = 0; if( ( server_fd.fd = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 ) { ret = socket_failed; goto exit; } if( connect( server_fd.fd, (const struct sockaddr *) &addr, sizeof( addr ) ) < 0 ) { ret = connect_failed; goto exit; } mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL ); if( mbedtls_ssl_handshake( &ssl ) != 0 ) { ret = ssl_handshake_failed; goto exit; } /* * 2. Write the GET request and close the connection */ if( mbedtls_ssl_write( &ssl, (const unsigned char *) GET_REQUEST, sizeof( GET_REQUEST ) - 1 ) <= 0 ) { ret = ssl_write_failed; goto exit; } mbedtls_ssl_close_notify( &ssl ); exit: mbedtls_net_free( &server_fd ); mbedtls_ssl_free( &ssl ); mbedtls_ssl_config_free( &conf ); mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); #if defined(MBEDTLS_X509_CRT_PARSE_C) mbedtls_x509_crt_free( &ca ); #endif return( ret ); }
int rand_bytes(uint8_t *output, int len) { #if defined(USE_CRYPTO_OPENSSL) return RAND_bytes(output, len); #elif defined(USE_CRYPTO_POLARSSL) static entropy_context ec = {}; static ctr_drbg_context cd_ctx = {}; static unsigned char rand_initialised = 0; const size_t blen = min(len, CTR_DRBG_MAX_REQUEST); if (!rand_initialised) { #ifdef _WIN32 HCRYPTPROV hProvider; union { unsigned __int64 seed; BYTE buffer[8]; } rand_buffer; hProvider = 0; if (CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, \ CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { CryptGenRandom(hProvider, 8, rand_buffer.buffer); CryptReleaseContext(hProvider, 0); } else { rand_buffer.seed = (unsigned __int64)clock(); } #else FILE *urand; union { uint64_t seed; uint8_t buffer[8]; } rand_buffer; urand = fopen("/dev/urandom", "r"); if (urand) { int read = fread(&rand_buffer.seed, sizeof(rand_buffer.seed), 1, urand); fclose(urand); if (read <= 0) { rand_buffer.seed = (uint64_t)clock(); } } else { rand_buffer.seed = (uint64_t)clock(); } #endif entropy_init(&ec); if (ctr_drbg_init(&cd_ctx, entropy_func, &ec, (const unsigned char *)rand_buffer.buffer, 8) != 0) { #if POLARSSL_VERSION_NUMBER >= 0x01030000 entropy_free(&ec); #endif FATAL("Failed to initialize random generator"); } rand_initialised = 1; } while (len > 0) { if (ctr_drbg_random(&cd_ctx, output, blen) != 0) { return 0; } output += blen; len -= blen; } return 1; #elif defined(USE_CRYPTO_MBEDTLS) static mbedtls_entropy_context ec = {}; // XXX: ctr_drbg_context changed, [if defined(MBEDTLS_THREADING_C) mbedtls_threading_mutex_t mutex;] static mbedtls_ctr_drbg_context cd_ctx = {}; static unsigned char rand_initialised = 0; const size_t blen = min(len, MBEDTLS_CTR_DRBG_MAX_REQUEST); if (!rand_initialised) { #ifdef _WIN32 HCRYPTPROV hProvider; union { unsigned __int64 seed; BYTE buffer[8]; } rand_buffer; hProvider = 0; if (CryptAcquireContext(&hProvider, 0, 0, PROV_RSA_FULL, \ CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) { CryptGenRandom(hProvider, 8, rand_buffer.buffer); CryptReleaseContext(hProvider, 0); } else { rand_buffer.seed = (unsigned __int64)clock(); } #else FILE *urand; union { uint64_t seed; uint8_t buffer[8]; } rand_buffer; urand = fopen("/dev/urandom", "r"); if (urand) { int read = fread(&rand_buffer.seed, sizeof(rand_buffer.seed), 1, urand); fclose(urand); if (read <= 0) { rand_buffer.seed = (uint64_t)clock(); } } else { rand_buffer.seed = (uint64_t)clock(); } #endif mbedtls_entropy_init(&ec); // XXX: ctr_drbg_init changed, seems we should initialize it before calling mbedtls_ctr_drbg_seed() mbedtls_ctr_drbg_init(&cd_ctx); if (mbedtls_ctr_drbg_seed(&cd_ctx, mbedtls_entropy_func, &ec, (const unsigned char *)rand_buffer.buffer, 8) != 0) { mbedtls_entropy_free(&ec); FATAL("mbed TLS: Failed to initialize random generator"); } rand_initialised = 1; } while (len > 0) { if (mbedtls_ctr_drbg_random(&cd_ctx, output, blen) != 0) { return 0; } output += blen; len -= blen; } return 1; #endif }
int main( int argc, char *argv[] ) { FILE *f; int ret, c; size_t i, olen = 0; mbedtls_pk_context pk; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; unsigned char result[1024]; unsigned char buf[512]; const char *pers = "mbedtls_pk_decrypt"; ((void) argv); mbedtls_ctr_drbg_init( &ctr_drbg ); memset(result, 0, sizeof( result ) ); ret = 1; if( argc != 2 ) { mbedtls_printf( "usage: mbedtls_pk_decrypt <key_file>\n" ); #if defined(_WIN32) mbedtls_printf( "\n" ); #endif goto exit; } mbedtls_printf( "\n . Seeding the random number generator..." ); fflush( stdout ); mbedtls_entropy_init( &entropy ); 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( "\n . Reading private key from '%s'", argv[1] ); fflush( stdout ); mbedtls_pk_init( &pk ); if( ( ret = mbedtls_pk_parse_keyfile( &pk, argv[1], "" ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile returned -0x%04x\n", -ret ); goto exit; } /* * Extract the RSA encrypted value from the text file */ ret = 1; if( ( f = fopen( "result-enc.txt", "rb" ) ) == NULL ) { mbedtls_printf( "\n ! Could not open %s\n\n", "result-enc.txt" ); goto exit; } i = 0; while( fscanf( f, "%02X", &c ) > 0 && i < (int) sizeof( buf ) ) buf[i++] = (unsigned char) c; fclose( f ); /* * Decrypt the encrypted RSA data and print the result. */ mbedtls_printf( "\n . Decrypting the encrypted data" ); fflush( stdout ); if( ( ret = mbedtls_pk_decrypt( &pk, buf, i, result, &olen, sizeof(result), mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_pk_decrypt returned -0x%04x\n", -ret ); goto exit; } mbedtls_printf( "\n . OK\n\n" ); mbedtls_printf( "The decrypted result is: '%s'\n\n", result ); ret = 0; exit: mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); #if defined(MBEDTLS_ERROR_C) if( ret != 0 ) { mbedtls_strerror( ret, (char *) buf, sizeof(buf) ); mbedtls_printf( " ! Last error was: %s\n", buf ); } #endif #if defined(_WIN32) mbedtls_printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
static int https_init(struct http_client_ctx *ctx) { int ret = 0; k_sem_init(&ctx->https.mbedtls.ssl_ctx.tx_sem, 0, UINT_MAX); k_fifo_init(&ctx->https.mbedtls.ssl_ctx.rx_fifo); k_fifo_init(&ctx->https.mbedtls.ssl_ctx.tx_fifo); mbedtls_platform_set_printf(printk); /* Coverity tells in CID 170746 that the mbedtls_ssl_init() * is overwriting the ssl struct. This looks like false positive as * the struct is initialized with proper size. */ mbedtls_ssl_init(&ctx->https.mbedtls.ssl); /* Coverity tells in CID 170745 that the mbedtls_ssl_config_init() * is overwriting the conf struct. This looks like false positive as * the struct is initialized with proper size. */ mbedtls_ssl_config_init(&ctx->https.mbedtls.conf); mbedtls_entropy_init(&ctx->https.mbedtls.entropy); mbedtls_ctr_drbg_init(&ctx->https.mbedtls.ctr_drbg); #if defined(MBEDTLS_X509_CRT_PARSE_C) mbedtls_x509_crt_init(&ctx->https.mbedtls.ca_cert); #endif #if defined(MBEDTLS_DEBUG_C) && defined(CONFIG_NET_DEBUG_HTTP) mbedtls_debug_set_threshold(DEBUG_THRESHOLD); mbedtls_ssl_conf_dbg(&ctx->https.mbedtls.conf, my_debug, NULL); #endif /* Seed the RNG */ mbedtls_entropy_add_source(&ctx->https.mbedtls.entropy, ctx->https.mbedtls.entropy_src_cb, NULL, MBEDTLS_ENTROPY_MAX_GATHER, MBEDTLS_ENTROPY_SOURCE_STRONG); ret = mbedtls_ctr_drbg_seed( &ctx->https.mbedtls.ctr_drbg, mbedtls_entropy_func, &ctx->https.mbedtls.entropy, (const unsigned char *)ctx->https.mbedtls.personalization_data, ctx->https.mbedtls.personalization_data_len); if (ret != 0) { print_error("mbedtls_ctr_drbg_seed returned -0x%x", ret); goto exit; } /* Setup SSL defaults etc. */ ret = mbedtls_ssl_config_defaults(&ctx->https.mbedtls.conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); if (ret != 0) { print_error("mbedtls_ssl_config_defaults returned -0x%x", ret); goto exit; } mbedtls_ssl_conf_rng(&ctx->https.mbedtls.conf, mbedtls_ctr_drbg_random, &ctx->https.mbedtls.ctr_drbg); /* Load the certificates and other related stuff. This needs to be done * by the user so we call a callback that user must have provided. */ ret = ctx->https.mbedtls.cert_cb(ctx, &ctx->https.mbedtls.ca_cert); if (ret != 0) { goto exit; } ret = mbedtls_ssl_setup(&ctx->https.mbedtls.ssl, &ctx->https.mbedtls.conf); if (ret != 0) { NET_ERR("mbedtls_ssl_setup returned -0x%x", ret); goto exit; } #if defined(MBEDTLS_X509_CRT_PARSE_C) if (ctx->https.cert_host) { ret = mbedtls_ssl_set_hostname(&ctx->https.mbedtls.ssl, ctx->https.cert_host); if (ret != 0) { print_error("mbedtls_ssl_set_hostname returned -0x%x", ret); goto exit; } } #endif NET_DBG("SSL setup done"); /* The HTTPS thread is started do initiate HTTPS handshake etc when * the first HTTP request is being done. */ exit: return ret; }
int main( int argc, char *argv[] ) { int ret = 1, len; int exit_code = MBEDTLS_EXIT_FAILURE; mbedtls_net_context server_fd; unsigned char buf[1024]; #if defined(MBEDTLS_BASE64_C) unsigned char base[1024]; #endif char hostname[32]; const char *pers = "ssl_mail_client"; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; mbedtls_ssl_context ssl; mbedtls_ssl_config conf; mbedtls_x509_crt cacert; mbedtls_x509_crt clicert; mbedtls_pk_context pkey; int i; size_t n; char *p, *q; const int *list; /* * Make sure memory references are valid in case we exit early. */ mbedtls_net_init( &server_fd ); mbedtls_ssl_init( &ssl ); mbedtls_ssl_config_init( &conf ); memset( &buf, 0, sizeof( buf ) ); mbedtls_x509_crt_init( &cacert ); mbedtls_x509_crt_init( &clicert ); mbedtls_pk_init( &pkey ); mbedtls_ctr_drbg_init( &ctr_drbg ); if( argc == 0 ) { usage: mbedtls_printf( USAGE ); list = mbedtls_ssl_list_ciphersuites(); while( *list ) { mbedtls_printf(" %s\n", mbedtls_ssl_get_ciphersuite_name( *list ) ); list++; } mbedtls_printf("\n"); goto exit; } opt.server_name = DFL_SERVER_NAME; opt.server_port = DFL_SERVER_PORT; opt.debug_level = DFL_DEBUG_LEVEL; opt.authentication = DFL_AUTHENTICATION; opt.mode = DFL_MODE; opt.user_name = DFL_USER_NAME; opt.user_pwd = DFL_USER_PWD; opt.mail_from = DFL_MAIL_FROM; opt.mail_to = DFL_MAIL_TO; opt.ca_file = DFL_CA_FILE; opt.crt_file = DFL_CRT_FILE; opt.key_file = DFL_KEY_FILE; opt.force_ciphersuite[0]= DFL_FORCE_CIPHER; for( i = 1; i < argc; i++ ) { p = argv[i]; if( ( q = strchr( p, '=' ) ) == NULL ) goto usage; *q++ = '\0'; if( strcmp( p, "server_name" ) == 0 ) opt.server_name = q; else if( strcmp( p, "server_port" ) == 0 ) opt.server_port = q; else if( strcmp( p, "debug_level" ) == 0 ) { opt.debug_level = atoi( q ); if( opt.debug_level < 0 || opt.debug_level > 65535 ) goto usage; } else if( strcmp( p, "authentication" ) == 0 ) { opt.authentication = atoi( q ); if( opt.authentication < 0 || opt.authentication > 1 ) goto usage; } else if( strcmp( p, "mode" ) == 0 ) { opt.mode = atoi( q ); if( opt.mode < 0 || opt.mode > 1 ) goto usage; } else if( strcmp( p, "user_name" ) == 0 ) opt.user_name = q; else if( strcmp( p, "user_pwd" ) == 0 ) opt.user_pwd = q; else if( strcmp( p, "mail_from" ) == 0 ) opt.mail_from = q; else if( strcmp( p, "mail_to" ) == 0 ) opt.mail_to = q; else if( strcmp( p, "ca_file" ) == 0 ) opt.ca_file = q; else if( strcmp( p, "crt_file" ) == 0 ) opt.crt_file = q; else if( strcmp( p, "key_file" ) == 0 ) opt.key_file = q; else if( strcmp( p, "force_ciphersuite" ) == 0 ) { opt.force_ciphersuite[0] = -1; opt.force_ciphersuite[0] = mbedtls_ssl_get_ciphersuite_id( q ); if( opt.force_ciphersuite[0] <= 0 ) goto usage; opt.force_ciphersuite[1] = 0; } else goto usage; } /* * 0. Initialize the RNG and the session data */ mbedtls_printf( "\n . Seeding the random number generator..." ); fflush( stdout ); mbedtls_entropy_init( &entropy ); 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.1. Load the trusted CA */ mbedtls_printf( " . Loading the CA root certificate ..." ); fflush( stdout ); #if defined(MBEDTLS_FS_IO) if( strlen( opt.ca_file ) ) ret = mbedtls_x509_crt_parse_file( &cacert, opt.ca_file ); else #endif #if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_PEM_PARSE_C) ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_cas_pem, mbedtls_test_cas_pem_len ); #else { mbedtls_printf("MBEDTLS_CERTS_C and/or MBEDTLS_PEM_PARSE_C not defined."); goto exit; } #endif if( ret < 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok (%d skipped)\n", ret ); /* * 1.2. Load own certificate and private key * * (can be skipped if client authentication is not required) */ mbedtls_printf( " . Loading the client cert. and key..." ); fflush( stdout ); #if defined(MBEDTLS_FS_IO) if( strlen( opt.crt_file ) ) ret = mbedtls_x509_crt_parse_file( &clicert, opt.crt_file ); else #endif #if defined(MBEDTLS_CERTS_C) ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt, mbedtls_test_cli_crt_len ); #else { mbedtls_printf("MBEDTLS_CERTS_C not defined."); goto exit; } #endif if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } #if defined(MBEDTLS_FS_IO) if( strlen( opt.key_file ) ) ret = mbedtls_pk_parse_keyfile( &pkey, opt.key_file, "" ); else #endif #if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_PEM_PARSE_C) ret = mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_cli_key, mbedtls_test_cli_key_len, NULL, 0 ); #else { mbedtls_printf("MBEDTLS_CERTS_C or MBEDTLS_PEM_PARSE_C not defined."); goto exit; } #endif if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 2. Start the connection */ mbedtls_printf( " . Connecting to tcp/%s/%s...", opt.server_name, opt.server_port ); fflush( stdout ); if( ( ret = mbedtls_net_connect( &server_fd, opt.server_name, opt.server_port, MBEDTLS_NET_PROTO_TCP ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret ); goto exit; } mbedtls_printf( " ok\n" ); /* * 3. Setup stuff */ mbedtls_printf( " . Setting up the SSL/TLS structure..." ); fflush( stdout ); if( ( ret = mbedtls_ssl_config_defaults( &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; } /* OPTIONAL is not optimal for security, * but makes interop easier in this simplified example */ mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_OPTIONAL ); mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); if( opt.force_ciphersuite[0] != DFL_FORCE_CIPHER ) mbedtls_ssl_conf_ciphersuites( &conf, opt.force_ciphersuite ); mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL ); if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &clicert, &pkey ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\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; } if( ( ret = mbedtls_ssl_set_hostname( &ssl, opt.server_name ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret ); goto exit; } mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL ); mbedtls_printf( " ok\n" ); if( opt.mode == MODE_SSL_TLS ) { if( do_handshake( &ssl ) != 0 ) goto exit; mbedtls_printf( " > Get header from server:" ); fflush( stdout ); ret = write_ssl_and_get_response( &ssl, buf, 0 ); if( ret < 200 || ret > 299 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_printf( " > Write EHLO to server:" ); fflush( stdout ); gethostname( hostname, 32 ); len = sprintf( (char *) buf, "EHLO %s\r\n", hostname ); ret = write_ssl_and_get_response( &ssl, buf, len ); if( ret < 200 || ret > 299 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } } else { mbedtls_printf( " > Get header from server:" ); fflush( stdout ); ret = write_and_get_response( &server_fd, buf, 0 ); if( ret < 200 || ret > 299 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_printf( " > Write EHLO to server:" ); fflush( stdout ); gethostname( hostname, 32 ); len = sprintf( (char *) buf, "EHLO %s\r\n", hostname ); ret = write_and_get_response( &server_fd, buf, len ); if( ret < 200 || ret > 299 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_printf( " > Write STARTTLS to server:" ); fflush( stdout ); gethostname( hostname, 32 ); len = sprintf( (char *) buf, "STARTTLS\r\n" ); ret = write_and_get_response( &server_fd, buf, len ); if( ret < 200 || ret > 299 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); if( do_handshake( &ssl ) != 0 ) goto exit; } #if defined(MBEDTLS_BASE64_C) if( opt.authentication ) { mbedtls_printf( " > Write AUTH LOGIN to server:" ); fflush( stdout ); len = sprintf( (char *) buf, "AUTH LOGIN\r\n" ); ret = write_ssl_and_get_response( &ssl, buf, len ); if( ret < 200 || ret > 399 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_printf( " > Write username to server: %s", opt.user_name ); fflush( stdout ); ret = mbedtls_base64_encode( base, sizeof( base ), &n, (const unsigned char *) opt.user_name, strlen( opt.user_name ) ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_base64_encode returned %d\n\n", ret ); goto exit; } len = sprintf( (char *) buf, "%s\r\n", base ); ret = write_ssl_and_get_response( &ssl, buf, len ); if( ret < 300 || ret > 399 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_printf( " > Write password to server: %s", opt.user_pwd ); fflush( stdout ); ret = mbedtls_base64_encode( base, sizeof( base ), &n, (const unsigned char *) opt.user_pwd, strlen( opt.user_pwd ) ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_base64_encode returned %d\n\n", ret ); goto exit; } len = sprintf( (char *) buf, "%s\r\n", base ); ret = write_ssl_and_get_response( &ssl, buf, len ); if( ret < 200 || ret > 399 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); } #endif mbedtls_printf( " > Write MAIL FROM to server:" ); fflush( stdout ); len = sprintf( (char *) buf, "MAIL FROM:<%s>\r\n", opt.mail_from ); ret = write_ssl_and_get_response( &ssl, buf, len ); if( ret < 200 || ret > 299 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_printf( " > Write RCPT TO to server:" ); fflush( stdout ); len = sprintf( (char *) buf, "RCPT TO:<%s>\r\n", opt.mail_to ); ret = write_ssl_and_get_response( &ssl, buf, len ); if( ret < 200 || ret > 299 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_printf( " > Write DATA to server:" ); fflush( stdout ); len = sprintf( (char *) buf, "DATA\r\n" ); ret = write_ssl_and_get_response( &ssl, buf, len ); if( ret < 300 || ret > 399 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_printf( " > Write content to server:" ); fflush( stdout ); len = sprintf( (char *) buf, "From: %s\r\nSubject: mbed TLS Test mail\r\n\r\n" "This is a simple test mail from the " "mbed TLS mail client example.\r\n" "\r\n" "Enjoy!", opt.mail_from ); ret = write_ssl_data( &ssl, buf, len ); len = sprintf( (char *) buf, "\r\n.\r\n"); ret = write_ssl_and_get_response( &ssl, buf, len ); if( ret < 200 || ret > 299 ) { mbedtls_printf( " failed\n ! server responded with %d\n\n", ret ); goto exit; } mbedtls_printf(" ok\n" ); mbedtls_ssl_close_notify( &ssl ); exit_code = MBEDTLS_EXIT_SUCCESS; exit: mbedtls_net_free( &server_fd ); mbedtls_x509_crt_free( &clicert ); mbedtls_x509_crt_free( &cacert ); 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( exit_code ); }
int main( int argc, char *argv[] ) { FILE *f; int ret = 1; mbedtls_pk_context pk; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; unsigned char hash[32]; unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; char filename[512]; const char *pers = "rsa_sign_pss"; size_t olen = 0; mbedtls_entropy_init( &entropy ); mbedtls_pk_init( &pk ); mbedtls_ctr_drbg_init( &ctr_drbg ); if( argc != 3 ) { mbedtls_printf( "usage: rsa_sign_pss <key_file> <filename>\n" ); #if defined(_WIN32) mbedtls_printf( "\n" ); #endif goto exit; } mbedtls_printf( "\n . Seeding the random number 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( "\n . Reading private key from '%s'", argv[1] ); fflush( stdout ); if( ( ret = mbedtls_pk_parse_keyfile( &pk, argv[1], "" ) ) != 0 ) { ret = 1; mbedtls_printf( " failed\n ! Could not read key from '%s'\n", argv[1] ); mbedtls_printf( " ! mbedtls_pk_parse_public_keyfile returned %d\n\n", ret ); goto exit; } if( !mbedtls_pk_can_do( &pk, MBEDTLS_PK_RSA ) ) { ret = 1; mbedtls_printf( " failed\n ! Key is not an RSA key\n" ); goto exit; } mbedtls_rsa_set_padding( mbedtls_pk_rsa( pk ), MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256 ); /* * Compute the SHA-256 hash of the input file, * then calculate the RSA signature of the hash. */ mbedtls_printf( "\n . Generating the RSA/SHA-256 signature" ); fflush( stdout ); if( ( ret = mbedtls_md_file( mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ), argv[2], hash ) ) != 0 ) { mbedtls_printf( " failed\n ! Could not open or read %s\n\n", argv[2] ); goto exit; } if( ( ret = mbedtls_pk_sign( &pk, MBEDTLS_MD_SHA256, hash, 0, buf, &olen, mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_pk_sign returned %d\n\n", ret ); goto exit; } /* * Write the signature into <filename>.sig */ mbedtls_snprintf( filename, 512, "%s.sig", argv[2] ); if( ( f = fopen( filename, "wb+" ) ) == NULL ) { ret = 1; mbedtls_printf( " failed\n ! Could not create %s\n\n", filename ); goto exit; } if( fwrite( buf, 1, olen, f ) != olen ) { mbedtls_printf( "failed\n ! fwrite failed\n\n" ); goto exit; } fclose( f ); mbedtls_printf( "\n . Done (created \"%s\")\n\n", filename ); exit: mbedtls_pk_free( &pk ); 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, char *argv[] ) { FILE *f; int ret, c; size_t i; mbedtls_rsa_context rsa; mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; unsigned char result[1024]; unsigned char buf[512]; const char *pers = "rsa_decrypt"; ((void) argv); memset(result, 0, sizeof( result ) ); mbedtls_ctr_drbg_init( &ctr_drbg ); ret = 1; if( argc != 1 ) { mbedtls_printf( "usage: rsa_decrypt\n" ); #if defined(_WIN32) mbedtls_printf( "\n" ); #endif goto exit; } mbedtls_printf( "\n . Seeding the random number generator..." ); fflush( stdout ); mbedtls_entropy_init( &entropy ); 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( "\n . Reading private key from rsa_priv.txt" ); fflush( stdout ); if( ( f = fopen( "rsa_priv.txt", "rb" ) ) == NULL ) { mbedtls_printf( " failed\n ! Could not open rsa_priv.txt\n" \ " ! Please run rsa_genkey first\n\n" ); goto exit; } mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); if( ( ret = mbedtls_mpi_read_file( &rsa.N , 16, f ) ) != 0 || ( ret = mbedtls_mpi_read_file( &rsa.E , 16, f ) ) != 0 || ( ret = mbedtls_mpi_read_file( &rsa.D , 16, f ) ) != 0 || ( ret = mbedtls_mpi_read_file( &rsa.P , 16, f ) ) != 0 || ( ret = mbedtls_mpi_read_file( &rsa.Q , 16, f ) ) != 0 || ( ret = mbedtls_mpi_read_file( &rsa.DP, 16, f ) ) != 0 || ( ret = mbedtls_mpi_read_file( &rsa.DQ, 16, f ) ) != 0 || ( ret = mbedtls_mpi_read_file( &rsa.QP, 16, f ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_mpi_read_file returned %d\n\n", ret ); goto exit; } rsa.len = ( mbedtls_mpi_bitlen( &rsa.N ) + 7 ) >> 3; fclose( f ); /* * Extract the RSA encrypted value from the text file */ ret = 1; if( ( f = fopen( "result-enc.txt", "rb" ) ) == NULL ) { mbedtls_printf( "\n ! Could not open %s\n\n", "result-enc.txt" ); goto exit; } i = 0; while( fscanf( f, "%02X", &c ) > 0 && i < (int) sizeof( buf ) ) buf[i++] = (unsigned char) c; fclose( f ); if( i != rsa.len ) { mbedtls_printf( "\n ! Invalid RSA signature format\n\n" ); goto exit; } /* * Decrypt the encrypted RSA data and print the result. */ mbedtls_printf( "\n . Decrypting the encrypted data" ); fflush( stdout ); if( ( ret = mbedtls_rsa_pkcs1_decrypt( &rsa, mbedtls_ctr_drbg_random, &ctr_drbg, MBEDTLS_RSA_PRIVATE, &i, buf, result, 1024 ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_rsa_pkcs1_decrypt returned %d\n\n", ret ); goto exit; } mbedtls_printf( "\n . OK\n\n" ); mbedtls_printf( "The decrypted result is: '%s'\n\n", result ); ret = 0; exit: 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 ); }