static unsigned int _DTLSVerifyOptions_set(dtls_session_t *p_dtls_session, unsigned char *p_ca_cert_pem) { int result; unsigned int err_code = DTLS_SUCCESS; #ifdef MBEDTLS_X509_CRT_PARSE_C if (p_ca_cert_pem != NULL) { #ifndef TEST_COAP_DAILY mbedtls_ssl_conf_authmode(&p_dtls_session->conf, MBEDTLS_SSL_VERIFY_REQUIRED); #else mbedtls_ssl_conf_authmode(&p_dtls_session->conf, MBEDTLS_SSL_VERIFY_OPTIONAL); #endif DTLS_TRC("Call mbedtls_ssl_conf_authmode\r\n"); DTLS_TRC("x509 ca cert pem len %d\r\n%s\r\n", (int)strlen((char *)p_ca_cert_pem) + 1, p_ca_cert_pem); result = mbedtls_x509_crt_parse(&p_dtls_session->cacert, p_ca_cert_pem, strlen((const char *)p_ca_cert_pem) + 1); DTLS_TRC("mbedtls_x509_crt_parse result 0x%04x\r\n", result); if (0 != result) { err_code = DTLS_INVALID_CA_CERTIFICATE; } else { mbedtls_ssl_conf_ca_chain(&p_dtls_session->conf, &p_dtls_session->cacert, NULL); } } else #endif { mbedtls_ssl_conf_authmode(&p_dtls_session->conf, MBEDTLS_SSL_VERIFY_NONE); } return err_code; }
/* Initialize TLS library */ int init_tls_module(mbedtls_x509_crt *ca_certificates) { char version[16]; if (mbedtls_version_get_number() < 0x02000000) { mbedtls_version_get_string(version); fprintf(stderr, "This Hiawatha installation requires at least mbed TLS v2.0.0 and you have v%s.", version); return -1; } if (mbedtls_version_check_feature("MBEDTLS_THREADING_PTHREAD") != 0) { fprintf(stderr, "mbed TLS was compiled without the required MBEDTLS_THREADING_PTHREAD compiler flag.\n"); return -1; } #ifdef ENABLE_DEBUG mbedtls_debug_set_threshold(TLS_DEBUG_LEVEL); #endif /* Entropy settings */ mbedtls_entropy_init(&entropy); mbedtls_ctr_drbg_init(&ctr_drbg); if (mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (unsigned char*)"Hiawatha_RND", 10) != 0) { return -1; } mbedtls_ctr_drbg_set_prediction_resistance(&ctr_drbg, MBEDTLS_CTR_DRBG_PR_OFF); /* Cache settings */ mbedtls_ssl_cache_init(&cache); mbedtls_ssl_cache_set_max_entries(&cache, 100); /* Client SSL configuratiomn */ mbedtls_ssl_config_init(&client_config); if (mbedtls_ssl_config_defaults(&client_config, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) != 0) { return -1; } mbedtls_ssl_conf_min_version(&client_config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1); mbedtls_ssl_conf_renegotiation(&client_config, MBEDTLS_SSL_RENEGOTIATION_DISABLED); mbedtls_ssl_conf_rng(&client_config, tls_random, &ctr_drbg); #ifdef ENABLE_DEBUG mbedtls_ssl_conf_dbg(&client_config, tls_debug, &client_config); #endif if (ca_certificates == NULL) { mbedtls_ssl_conf_authmode(&client_config, MBEDTLS_SSL_VERIFY_NONE); } else { mbedtls_ssl_conf_authmode(&client_config, MBEDTLS_SSL_VERIFY_REQUIRED); mbedtls_ssl_conf_ca_chain(&client_config, ca_certificates, NULL); } if (pthread_mutex_init(&random_mutex, NULL) != 0) { return -1; } else if (pthread_mutex_init(&cache_mutex, NULL) != 0) { return -1; } return 0; }
static value conf_set_verify( value config, value b ) { val_check_kind(config, k_ssl_conf); if( !val_is_null(b) ) val_check(b, bool); if( val_is_null(b) ) mbedtls_ssl_conf_authmode(val_conf(config), MBEDTLS_SSL_VERIFY_OPTIONAL); else if( val_bool(b) ) mbedtls_ssl_conf_authmode(val_conf(config), MBEDTLS_SSL_VERIFY_REQUIRED); else mbedtls_ssl_conf_authmode(val_conf(config), MBEDTLS_SSL_VERIFY_NONE); return val_true; }
int coap_security_handler_configure_keys( coap_security_t *sec, coap_security_keys_t keys ) { int ret = -1; switch( sec->_conn_mode ){ case Certificate:{ #if defined(MBEDTLS_X509_CRT_PARSE_C) if( mbedtls_x509_crt_parse( &sec->_cacert, keys._server_cert, keys._server_cert_len ) < 0 ){ break; } if( mbedtls_x509_crt_parse( &sec->_owncert, keys._pub_cert_or_identifier, keys._pub_len ) < 0 ){ break; } if( mbedtls_pk_parse_key(&sec->_pkey, keys._priv, keys._priv_len, NULL, 0) < 0){ break; } //TODO: If needed in server mode, this won't work if( 0 != mbedtls_ssl_conf_own_cert(&sec->_conf, &sec->_owncert, &sec->_pkey) ){ break; } //TODO: use MBEDTLS_SSL_VERIFY_REQUIRED instead of optional mbedtls_ssl_conf_authmode( &sec->_conf, MBEDTLS_SSL_VERIFY_OPTIONAL ); mbedtls_ssl_conf_ca_chain( &sec->_conf, &sec->_cacert, NULL ); ret = 0; #endif break; } case PSK: { #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) if( 0 != mbedtls_ssl_conf_psk(&sec->_conf, keys._priv, keys._priv_len, keys._pub_cert_or_identifier, keys._pub_len) ){ break; } mbedtls_ssl_conf_ciphersuites(&sec->_conf, PSK_SUITES); ret = 0; #endif break; } case ECJPAKE: { #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if( mbedtls_ssl_set_hs_ecjpake_password(&sec->_ssl, keys._priv, keys._priv_len) != 0 ){ return -1; } mbedtls_ssl_conf_ciphersuites(&sec->_conf, ECJPAKE_SUITES); //NOTE: If thread starts supporting PSK in other modes, then this will be needed! mbedtls_ssl_conf_export_keys_cb(&sec->_conf, export_key_block, &sec->_keyblk); ret = 0; #endif break; } default: break; } return ret; }
static int setup_cert(struct net_app_ctx *ctx, void *cert) { #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) mbedtls_ssl_conf_psk(&ctx->tls.mbedtls.conf, client_psk, sizeof(client_psk), (const unsigned char *)client_psk_id, sizeof(client_psk_id) - 1); #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) { mbedtls_x509_crt *ca_cert = cert; int ret; ret = mbedtls_x509_crt_parse_der(ca_cert, ca_certificate, sizeof(ca_certificate)); if (ret != 0) { NET_ERR("mbedtls_x509_crt_parse_der failed " "(-0x%x)", -ret); return ret; } mbedtls_ssl_conf_ca_chain(&ctx->tls.mbedtls.conf, ca_cert, NULL); /* In this example, we skip the certificate checks. In real * life scenarios, one should always verify the certificates. */ mbedtls_ssl_conf_authmode(&ctx->tls.mbedtls.conf, MBEDTLS_SSL_VERIFY_REQUIRED); mbedtls_ssl_conf_cert_profile(&ctx->tls.mbedtls.conf, &mbedtls_x509_crt_profile_default); #define VERIFY_CERTS 0 #if VERIFY_CERTS mbedtls_ssl_conf_authmode(&ctx->tls.mbedtls.conf, MBEDTLS_SSL_VERIFY_OPTIONAL); #else ; #endif /* VERIFY_CERTS */ } #endif /* MBEDTLS_X509_CRT_PARSE_C */ return 0; }
// コンテキストを初期化します。 // mtls_alloc() に続いてコールしてください。 // 成功すれば 0、失敗すれば -1 を返します。 int mtls_init(mtlsctx_t* ctx) { int r; TRACE("start\n"); // グローバルコンテキストの初期化 if (gctx.initialized == 0) { mbedtls_ctr_drbg_init(&gctx.ctr_drbg); mbedtls_entropy_init(&gctx.entropy); // init RNG r = mbedtls_ctr_drbg_seed(&gctx.ctr_drbg, mbedtls_entropy_func, &gctx.entropy, "a", 1); if (r != 0) { ERROR("mbedtls_ctr_drbg_seed failed: %s\n", mtls_errmsg(r)); goto errexit; } gctx.initialized = 1; } ctx->usessl = 0; mbedtls_net_init(&ctx->net); mbedtls_ssl_init(&ctx->ssl); mbedtls_ssl_config_init(&ctx->conf); // TLS config r = mbedtls_ssl_config_defaults(&ctx->conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); if (r != 0) { ERROR("mbedtls_ssl_config_defaults failed: %s\n", mtls_errmsg(r)); goto errexit; } mbedtls_ssl_conf_authmode(&ctx->conf, MBEDTLS_SSL_VERIFY_NONE); mbedtls_ssl_conf_rng(&ctx->conf, mbedtls_ctr_drbg_random, &gctx.ctr_drbg); mbedtls_ssl_conf_dbg(&ctx->conf, debug_callback, stderr); r = mbedtls_ssl_setup(&ctx->ssl, &ctx->conf); if (r != 0) { ERROR("mbedtls_ssl_setup failed: %s\n", mtls_errmsg(r)); goto errexit; } mbedtls_ssl_set_bio(&ctx->ssl, &ctx->net, mbedtls_net_send, mbedtls_net_recv, NULL); ctx->initialized = 1; TRACE("done\n"); return 0; errexit: // cleanup TRACE("NG\n"); return -1; }
rb_ssl_ctx * rb_setup_ssl_client(const char *ssl_cipher_list, const char *cert, const char *keyfile) { int ret; rb_ssl_ctx *sctx; sctx = rb_malloc(sizeof(rb_ssl_ctx)); mbedtls_ssl_config_init(&sctx->config); if ((ret = mbedtls_ssl_config_defaults(&sctx->config, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { rb_lib_log("rb_init_ssl: unable to initialize default SSL parameters for client context: -0x%x", -ret); return 0; } mbedtls_ssl_conf_rng(&sctx->config, mbedtls_ctr_drbg_random, &ctr_drbg); mbedtls_ssl_conf_authmode(&sctx->config, MBEDTLS_SSL_VERIFY_NONE); if(cert != NULL && keyfile != NULL) { mbedtls_x509_crt_init(&sctx->x509); ret = mbedtls_x509_crt_parse_file(&sctx->x509, cert); if (ret != 0) { rb_lib_log("rb_setup_ssl_client: failed to parse certificate '%s': -0x%x", cert, -ret); return 0; } mbedtls_pk_init(&sctx->serv_pk); ret = mbedtls_pk_parse_keyfile(&sctx->serv_pk, keyfile, NULL); if (ret != 0) { rb_lib_log("rb_setup_ssl_client: failed to parse private key '%s': -0x%x", keyfile, -ret); return 0; } if (&sctx->x509.next) mbedtls_ssl_conf_ca_chain(&sctx->config, sctx->x509.next, NULL); if ((ret = mbedtls_ssl_conf_own_cert(&sctx->config, &sctx->x509, &sctx->serv_pk)) != 0) { rb_lib_log("rb_setup_ssl_client: failed to set up own certificate: -0x%x", -ret); return 0; } } return sctx; }
int tls_set_config(mbedtls_ssl_config **tls_config, t_tls_setup *tls_setup) { if ((*tls_config = (mbedtls_ssl_config*)malloc(sizeof(mbedtls_ssl_config))) == NULL) { return -1; } mbedtls_ssl_config_init(*tls_config); if (mbedtls_ssl_config_defaults(*tls_config, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) != 0) { return -1; } mbedtls_ssl_conf_min_version(*tls_config, MBEDTLS_SSL_MAJOR_VERSION_3, tls_setup->min_tls_version); mbedtls_ssl_conf_renegotiation(*tls_config, MBEDTLS_SSL_RENEGOTIATION_DISABLED); mbedtls_ssl_conf_rng(*tls_config, tls_random, &ctr_drbg); mbedtls_ssl_conf_sni(*tls_config, sni_callback, NULL); mbedtls_ssl_conf_session_cache(*tls_config, &cache, mbedtls_ssl_cache_get, mbedtls_ssl_cache_set); #ifdef ENABLE_DEBUG mbedtls_ssl_conf_dbg(*tls_config, tls_debug, &tls_config); #endif mbedtls_ssl_conf_ciphersuites_for_version(*tls_config, ciphersuites_tls10, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_1); mbedtls_ssl_conf_ciphersuites_for_version(*tls_config, ciphersuites_tls10, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_2); mbedtls_ssl_conf_ciphersuites_for_version(*tls_config, ciphersuites_tls12, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); if (tls_setup->ca_certificate == NULL) { mbedtls_ssl_conf_authmode(*tls_config, MBEDTLS_SSL_VERIFY_NONE); } else { mbedtls_ssl_conf_authmode(*tls_config, MBEDTLS_SSL_VERIFY_REQUIRED); mbedtls_ssl_conf_ca_chain(*tls_config, tls_setup->ca_certificate, tls_setup->ca_crl); } mbedtls_ssl_conf_own_cert(*tls_config, tls_setup->certificate, tls_setup->private_key); if (tls_setup->dh_size == 2048) { mbedtls_ssl_conf_dh_param(*tls_config, MBEDTLS_DHM_RFC5114_MODP_2048_P, MBEDTLS_DHM_RFC5114_MODP_2048_G); } else if (tls_setup->dh_size == 4096) { mbedtls_ssl_conf_dh_param(*tls_config, dhm_4096_P, dhm_4096_G); } else if (tls_setup->dh_size == 8192) { mbedtls_ssl_conf_dh_param(*tls_config, dhm_8192_P, dhm_8192_G); } return 0; }
static dukf_ssl_context_t *create_dukf_ssl_context(const char *hostname, int fd) { char errortext[256]; dukf_ssl_context_t *dukf_ssl_context; dukf_ssl_context = malloc(sizeof(dukf_ssl_context_t)); mbedtls_ssl_init(&dukf_ssl_context->ssl); mbedtls_ssl_config_init(&dukf_ssl_context->conf); mbedtls_x509_crt_init(&dukf_ssl_context->cacert); mbedtls_ctr_drbg_init(&dukf_ssl_context->ctr_drbg); mbedtls_entropy_init(&dukf_ssl_context->entropy); mbedtls_ssl_conf_dbg(&dukf_ssl_context->conf, debug_log, NULL); dukf_ssl_context->fd = fd; int rc = mbedtls_ctr_drbg_seed( &dukf_ssl_context->ctr_drbg, mbedtls_entropy_func, &dukf_ssl_context->entropy, (const unsigned char *) pers, strlen(pers)); if (rc != 0) { LOGE(" failed\n ! mbedtls_ctr_drbg_seed returned %d", rc); return NULL; } rc = mbedtls_ssl_config_defaults( &dukf_ssl_context->conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); if (rc != 0) { LOGE("mbedtls_ssl_config_defaults returned %d", rc); return NULL; } mbedtls_ssl_conf_authmode(&dukf_ssl_context->conf, MBEDTLS_SSL_VERIFY_NONE); mbedtls_ssl_conf_rng(&dukf_ssl_context->conf, mbedtls_ctr_drbg_random, &dukf_ssl_context->ctr_drbg); rc = mbedtls_ssl_setup(&dukf_ssl_context->ssl, &dukf_ssl_context->conf); if (rc != 0) { mbedtls_strerror(rc, errortext, sizeof(errortext)); LOGE("error from mbedtls_ssl_setup: %d - %x - %s\n", rc, rc, errortext); return NULL; } rc = mbedtls_ssl_set_hostname(&dukf_ssl_context->ssl, hostname); if (rc) { mbedtls_strerror(rc, errortext, sizeof(errortext)); LOGE("error from mbedtls_ssl_set_hostname: %s %d - %x - %s", hostname, rc, rc, errortext); return NULL; } mbedtls_ssl_set_bio(&dukf_ssl_context->ssl, dukf_ssl_context, ssl_send, ssl_recv, NULL); return dukf_ssl_context; } // create_ssl_socket
Context(CTRDRBG& ctrdrbg, unsigned int endpoint) { mbedtls_ssl_config_init(&conf); #ifdef INSPIRCD_MBEDTLS_LIBRARY_DEBUG mbedtls_debug_set_threshold(INT_MAX); mbedtls_ssl_conf_dbg(&conf, DebugLogFunc, NULL); #endif mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL); // TODO: check ret of mbedtls_ssl_config_defaults mbedtls_ssl_config_defaults(&conf, endpoint, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); ctrdrbg.SetupConf(&conf); }
void cSslConfig::SetAuthMode(const eSslAuthMode a_AuthMode) { const int Mode = [=]() { switch (a_AuthMode) { case eSslAuthMode::None: return MBEDTLS_SSL_VERIFY_NONE; case eSslAuthMode::Optional: return MBEDTLS_SSL_VERIFY_OPTIONAL; case eSslAuthMode::Required: return MBEDTLS_SSL_VERIFY_REQUIRED; case eSslAuthMode::Unset: return MBEDTLS_SSL_VERIFY_UNSET; } UNREACHABLE("Unsupported SSL auth mode"); }(); mbedtls_ssl_conf_authmode(&m_Config, Mode); }
static int dslink_socket_connect_secure(SslSocket *sock, const char *address, unsigned short port) { if ((errno = mbedtls_ctr_drbg_seed(sock->drbg, mbedtls_entropy_func, sock->entropy, NULL, 0)) != 0) { return DSLINK_CRYPT_ENTROPY_SEED_ERR; } char num[6]; snprintf(num, sizeof(num), "%d", port); if ((errno = mbedtls_net_connect(sock->socket_fd, address, num, MBEDTLS_NET_PROTO_TCP)) != 0) { return DSLINK_SOCK_CONNECT_ERR; } if ((errno = mbedtls_ssl_config_defaults(sock->conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { return DSLINK_SOCK_SSL_CONFIG_ERR; } mbedtls_ssl_conf_authmode(sock->conf, MBEDTLS_SSL_VERIFY_NONE); mbedtls_ssl_conf_rng(sock->conf, mbedtls_ctr_drbg_random, sock->drbg); if ((errno = mbedtls_ssl_setup(sock->ssl, sock->conf)) != 0) { return DSLINK_SOCK_SSL_SETUP_ERR; } if ((errno = mbedtls_ssl_set_hostname(sock->ssl, "_")) != 0) { return DSLINK_SOCK_SSL_HOSTNAME_SET_ERR; } mbedtls_ssl_set_bio(sock->ssl, sock->socket_fd, mbedtls_net_send, mbedtls_net_recv, NULL); int stat; while ((stat = mbedtls_ssl_handshake(sock->ssl)) != 0) { if (stat != MBEDTLS_ERR_SSL_WANT_READ && stat != MBEDTLS_ERR_SSL_WANT_WRITE) { errno = stat; return DSLINK_SOCK_SSL_HANDSHAKE_ERR; } } return 0; }
Error StreamPeerMbedTLS::connect_to_stream(Ref<StreamPeer> p_base, bool p_validate_certs, const String &p_for_hostname) { base = p_base; int ret = 0; int authmode = p_validate_certs ? MBEDTLS_SSL_VERIFY_REQUIRED : MBEDTLS_SSL_VERIFY_NONE; mbedtls_ssl_init(&ssl); mbedtls_ssl_config_init(&conf); mbedtls_ctr_drbg_init(&ctr_drbg); mbedtls_entropy_init(&entropy); ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0); if (ret != 0) { ERR_PRINTS(" failed\n ! mbedtls_ctr_drbg_seed returned an error" + itos(ret)); return FAILED; } mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); mbedtls_ssl_conf_authmode(&conf, authmode); 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); mbedtls_ssl_setup(&ssl, &conf); mbedtls_ssl_set_hostname(&ssl, p_for_hostname.utf8().get_data()); mbedtls_ssl_set_bio(&ssl, this, bio_send, bio_recv, NULL); while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { ERR_PRINTS("TLS handshake error: " + itos(ret)); _print_error(ret); status = STATUS_ERROR_HOSTNAME_MISMATCH; return FAILED; } } connected = true; status = STATUS_CONNECTED; return OK; }
ProtocolError DTLSMessageChannel::init( const uint8_t* core_private, size_t core_private_len, const uint8_t* core_public, size_t core_public_len, const uint8_t* server_public, size_t server_public_len, const uint8_t* device_id, Callbacks& callbacks, message_id_t* coap_state) { init(); this->coap_state = coap_state; int ret; this->callbacks = callbacks; this->device_id = device_id; keys_checksum = compute_checksum(callbacks.calculate_crc, server_public, server_public_len, core_private, core_private_len); ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_DATAGRAM, MBEDTLS_SSL_PRESET_DEFAULT); EXIT_ERROR(ret, "unable to configure defaults"); mbedtls_ssl_conf_handshake_timeout(&conf, 3000, 6000); mbedtls_ssl_conf_rng(&conf, dtls_rng, this); mbedtls_ssl_conf_dbg(&conf, my_debug, nullptr); mbedtls_ssl_conf_min_version(&conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3); ret = mbedtls_pk_parse_public_key(&pkey, core_public, core_public_len); EXIT_ERROR(ret, "unable to parse device public key"); ret = mbedtls_pk_parse_key(&pkey, core_private, core_private_len, NULL, 0); EXIT_ERROR(ret, "unable to parse device private key"); ret = mbedtls_ssl_conf_own_cert(&conf, &clicert, &pkey); EXIT_ERROR(ret, "unable to configure own certificate"); mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL); static int ssl_cert_types[] = { MBEDTLS_TLS_CERT_TYPE_RAW_PUBLIC_KEY, MBEDTLS_TLS_CERT_TYPE_NONE }; mbedtls_ssl_conf_client_certificate_types(&conf, ssl_cert_types); mbedtls_ssl_conf_server_certificate_types(&conf, ssl_cert_types); mbedtls_ssl_conf_certificate_receive(&conf, MBEDTLS_SSL_RECEIVE_CERTIFICATE_DISABLED); this->server_public = new uint8_t[server_public_len]; memcpy(this->server_public, server_public, server_public_len); this->server_public_len = server_public_len; return NO_ERROR; }
int websocket_tls_handshake(websocket_t *data, char *hostname, int auth_mode) { int r; /* set socket file descriptor */ data->tls_net.fd = data->fd; /* set authentication mode */ mbedtls_ssl_conf_authmode(data->tls_conf, auth_mode); /* default setting block mode */ if ((r = mbedtls_net_set_block(&(data->tls_net))) != 0) { WEBSOCKET_DEBUG("Error: mbedtls_net_set_block returned -%4x\n", -r); return -1; } if ((r = mbedtls_ssl_setup(data->tls_ssl, data->tls_conf)) != 0) { WEBSOCKET_DEBUG("Error: mbedtls_ssl_setup returned -%4x\n", -r); return -1; } #if WEBSOCKET_CONF_CHECK_TLS_HOSTNAME if (hostname != NULL) { if ((r = mbedtls_ssl_set_hostname(data->tls_ssl, hostname)) != 0) { WEBSOCKET_DEBUG("Error: mbedtls_hostname returned -%4x\n", -r); return -1; } } #endif mbedtls_ssl_set_bio(data->tls_ssl, &(data->tls_net), mbedtls_net_send, mbedtls_net_recv, NULL); /* Handshake */ WEBSOCKET_DEBUG(" . Performing the SSL/TLS handshake..."); while ((r = mbedtls_ssl_handshake(data->tls_ssl)) != 0) { if (r != MBEDTLS_ERR_SSL_WANT_READ && r != MBEDTLS_ERR_SSL_WANT_WRITE) { WEBSOCKET_DEBUG("Error: mbedtls_ssl_handshake returned -%4x\n", -r); return r; } } WEBSOCKET_DEBUG("OK\n"); return WEBSOCKET_SUCCESS; }
int ssl_socket_connect(void *state_data, void *data, bool timeout_enable, bool nonblock) { struct ssl_state *state = (struct ssl_state*)state_data; int ret, flags; if (socket_connect(state->net_ctx.fd, data, timeout_enable)) return -1; if (mbedtls_ssl_config_defaults(&state->conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT) != 0) return -1; mbedtls_ssl_conf_authmode(&state->conf, MBEDTLS_SSL_VERIFY_OPTIONAL); mbedtls_ssl_conf_ca_chain(&state->conf, &state->ca, NULL); mbedtls_ssl_conf_rng(&state->conf, mbedtls_ctr_drbg_random, &state->ctr_drbg); mbedtls_ssl_conf_dbg(&state->conf, ssl_debug, stderr); if (mbedtls_ssl_setup(&state->ctx, &state->conf) != 0) return -1; #if defined(MBEDTLS_X509_CRT_PARSE_C) if (mbedtls_ssl_set_hostname(&state->ctx, state->domain) != 0) return -1; #endif mbedtls_ssl_set_bio(&state->ctx, &state->net_ctx, mbedtls_net_send, mbedtls_net_recv, NULL); while ((ret = mbedtls_ssl_handshake(&state->ctx)) != 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) return -1; } if ((flags = mbedtls_ssl_get_verify_result(&state->ctx)) != 0) { char vrfy_buf[512]; mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), " ! ", flags); } return state->net_ctx.fd; }
/** * @brief reload SSL low-level certification object */ static int ssl_pm_reload_crt(SSL *ssl) { int ret; int mode; struct ssl_pm *ssl_pm = ssl->ssl_pm; struct x509_pm *ca_pm = (struct x509_pm *)ssl->client_CA->x509_pm; struct pkey_pm *pkey_pm = (struct pkey_pm *)ssl->cert->pkey->pkey_pm; struct x509_pm *crt_pm = (struct x509_pm *)ssl->cert->x509->x509_pm; if (ssl->verify_mode == SSL_VERIFY_PEER) mode = MBEDTLS_SSL_VERIFY_OPTIONAL; else if (ssl->verify_mode == SSL_VERIFY_FAIL_IF_NO_PEER_CERT) mode = MBEDTLS_SSL_VERIFY_OPTIONAL; else if (ssl->verify_mode == SSL_VERIFY_CLIENT_ONCE) mode = MBEDTLS_SSL_VERIFY_UNSET; else mode = MBEDTLS_SSL_VERIFY_NONE; mbedtls_ssl_conf_authmode(&ssl_pm->conf, mode); if (ca_pm->x509_crt) { mbedtls_ssl_conf_ca_chain(&ssl_pm->conf, ca_pm->x509_crt, NULL); } else if (ca_pm->ex_crt) { mbedtls_ssl_conf_ca_chain(&ssl_pm->conf, ca_pm->ex_crt, NULL); } if (crt_pm->x509_crt && pkey_pm->pkey) { ret = mbedtls_ssl_conf_own_cert(&ssl_pm->conf, crt_pm->x509_crt, pkey_pm->pkey); } else if (crt_pm->ex_crt && pkey_pm->ex_pkey) { ret = mbedtls_ssl_conf_own_cert(&ssl_pm->conf, crt_pm->ex_crt, pkey_pm->ex_pkey); } else { ret = 0; } if (ret) { SSL_DEBUG(SSL_PLATFORM_ERROR_LEVEL, "mbedtls_ssl_conf_own_cert() return -0x%x", -ret); ret = -1; } return ret; }
int setup_cert(struct net_app_ctx *ctx, void *cert) { #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) mbedtls_ssl_conf_psk(&ctx->tls.mbedtls.conf, client_psk, sizeof(client_psk), (const unsigned char *)client_psk_id, sizeof(client_psk_id) - 1); #endif #if defined(MBEDTLS_X509_CRT_PARSE_C) { mbedtls_x509_crt *ca_cert = cert; int ret; ret = mbedtls_x509_crt_parse_der(ca_cert, ca_certificate, sizeof(ca_certificate)); if (ret != 0) { NET_ERR("mbedtls_x509_crt_parse_der failed " "(-0x%x)", -ret); return ret; } /* mbedtls_x509_crt_verify() should be called to verify the * cerificate in the real cases */ mbedtls_ssl_conf_ca_chain(&ctx->tls.mbedtls.conf, ca_cert, NULL); mbedtls_ssl_conf_authmode(&ctx->tls.mbedtls.conf, MBEDTLS_SSL_VERIFY_REQUIRED); mbedtls_ssl_conf_cert_profile(&ctx->tls.mbedtls.conf, &mbedtls_x509_crt_profile_default); } #endif /* MBEDTLS_X509_CRT_PARSE_C */ return 0; }
struct flb_tls_session *flb_tls_session_new(struct flb_tls_context *ctx) { int ret; struct flb_tls_session *session; session = malloc(sizeof(struct flb_tls_session)); if (!session) { return NULL; } mbedtls_ssl_init(&session->ssl); mbedtls_ssl_config_init(&session->conf); ret = mbedtls_ssl_config_defaults(&session->conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); if (ret != 0) { io_tls_error(ret); } mbedtls_ssl_conf_rng(&session->conf, mbedtls_ctr_drbg_random, &ctx->ctr_drbg); mbedtls_ssl_conf_authmode(&session->conf, MBEDTLS_SSL_VERIFY_NONE); ret = mbedtls_ssl_setup(&session->ssl, &session->conf); if (ret == -1) { flb_error("[tls] ssl_setup"); goto error; } return session; error: free(session); return NULL; }
int main( int argc, const char *argv[] ) { /* Client and server declarations. */ int ret; int len; #if SOCKET_COMMUNICATION mbedtls_net_context listen_fd, client_fd, server_fd; #endif unsigned char buf[1024]; /* Handshake step counter */ size_t step = 1; int flags; mbedtls_ssl_context s_ssl, c_ssl; mbedtls_ssl_config s_conf, c_conf; mbedtls_x509_crt srvcert; mbedtls_pk_context pkey; #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_context cache; #endif if( argc == 3) { packet_in_num = atoi(argv[1]); packet_in_file = argv[2]; } else if( argc != 1) { usage(argv[0]); exit(1); } /* Server init */ #if SOCKET_COMMUNICATION mbedtls_net_init( &listen_fd ); mbedtls_net_init( &client_fd ); #endif mbedtls_ssl_init( &s_ssl ); mbedtls_ssl_config_init( &s_conf ); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_init( &cache ); #endif mbedtls_x509_crt_init( &srvcert ); mbedtls_pk_init( &pkey ); /* Client init */ #if SOCKET_COMMUNICATION mbedtls_net_init( &server_fd ); #endif mbedtls_ssl_init( &c_ssl ); mbedtls_ssl_config_init( &c_conf ); /*mbedtls_x509_crt_init( &cacert );*/ #if defined(MBEDTLS_DEBUG_C) mbedtls_debug_set_threshold( DEBUG_LEVEL ); #endif /* * Server: * Load the certificates and private RSA key */ if( packet_in_num == 0 ) { mbedtls_printf( " . Loading the server cert. and key..." ); fflush( stdout ); } /* * This demonstration program uses embedded test certificates. * Instead, you may want to use mbedtls_x509_crt_parse_file() to read the * server and CA certificates, as well as mbedtls_pk_parse_keyfile(). */ ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_srv_crt, mbedtls_test_srv_crt_len ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_cas_pem, mbedtls_test_cas_pem_len ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret ); goto exit; } ret = mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_srv_key, mbedtls_test_srv_key_len, NULL, 0 ); if( ret != 0 ) { mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret ); goto exit; } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } /* * Server: * Setup stuff */ if( packet_in_num == 0 ) { mbedtls_printf( " . Server: Setting up the SSL data...." ); fflush( stdout ); } if( ( ret = mbedtls_ssl_config_defaults( &s_conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); goto exit; } mbedtls_ssl_conf_rng( &s_conf, mbedtls_ctr_drbg_deterministic, NULL ); mbedtls_ssl_conf_dbg( &s_conf, my_debug, stdout ); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_conf_session_cache( &s_conf, &cache, mbedtls_ssl_cache_get, mbedtls_ssl_cache_set ); #endif mbedtls_ssl_conf_ca_chain( &s_conf, srvcert.next, NULL ); if( ( ret = mbedtls_ssl_conf_own_cert( &s_conf, &srvcert, &pkey ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret ); goto exit; } if( ( ret = mbedtls_ssl_setup( &s_ssl, &s_conf ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); goto exit; } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } mbedtls_ssl_session_reset( &s_ssl ); #if SOCKET_COMMUNICATION /* * Server: * Setup the listening TCP socket */ if( packet_in_num == 0 ) { mbedtls_printf( " . Bind on https://localhost:%s/ ...", SERVER_PORT ); fflush( stdout ); } if( ( ret = mbedtls_net_bind( &listen_fd, NULL, SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_bind returned %d\n\n", ret ); goto exit; } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } /* * Client: * Start the connection */ if( packet_in_num == 0 ) { mbedtls_printf( " . Connecting to tcp/%s/%s...", SERVER_NAME, SERVER_PORT ); fflush( stdout ); } if( ( ret = mbedtls_net_connect( &server_fd, SERVER_NAME, SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret ); goto exit; } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } /* * Server: * Start listening for client connections */ if( packet_in_num == 0 ) { mbedtls_printf( " . Waiting for a remote connection ..." ); fflush( stdout ); } /* * Server: * Accept client connection (socket is set non-blocking in * library/net.c) */ if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd, NULL, 0, NULL ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_net_accept returned %d\n\n", ret ); goto exit; } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } mbedtls_ssl_set_bio( &s_ssl, &client_fd, mbedtls_send_custom, mbedtls_recv_custom, NULL ); #else mbedtls_ssl_set_bio( &s_ssl, NULL, mbedtls_server_send_buf, mbedtls_server_recv_buf, NULL ); #endif /* * Client: * Setup stuff */ if( packet_in_num == 0 ) { mbedtls_printf( " . Client: Setting up the SSL/TLS structure..." ); fflush( stdout ); } if( ( ret = mbedtls_ssl_config_defaults( &c_conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); goto exit; } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } /* OPTIONAL is not optimal for security, * but makes interop easier in this simplified example */ mbedtls_ssl_conf_authmode( &c_conf, MBEDTLS_SSL_VERIFY_OPTIONAL ); /* NONE permits man-in-the-middle attacks. */ /*mbedtls_ssl_conf_authmode( &c_conf, MBEDTLS_SSL_VERIFY_NONE );*/ /*mbedtls_ssl_conf_authmode( &c_conf, MBEDTLS_SSL_VERIFY_REQUIRED );*/ mbedtls_ssl_conf_ca_chain( &c_conf, &srvcert, NULL ); mbedtls_ssl_conf_rng( &c_conf, mbedtls_ctr_drbg_deterministic, NULL ); mbedtls_ssl_conf_dbg( &c_conf, my_debug, stdout ); if( ( ret = mbedtls_ssl_setup( &c_ssl, &c_conf ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); goto exit; } if( ( ret = mbedtls_ssl_set_hostname( &c_ssl, "mbed TLS Server 1" ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret ); goto exit; } #if SOCKET_COMMUNICATION mbedtls_ssl_set_bio( &c_ssl, &server_fd, mbedtls_send_custom, mbedtls_recv_custom, NULL ); #else mbedtls_ssl_set_bio( &c_ssl, NULL, mbedtls_client_send_buf, mbedtls_client_recv_buf, NULL ); #endif if( packet_in_num == 0 ) { mbedtls_printf( " . Performing the SSL/TLS handshake...\n" ); fflush( stdout ); } /* * The following number of steps are hardcoded to ensure * that the client and server complete the handshake without * waiting infinitely for the other side to send data. * * 1 2 3 4 5 6 7 8 9 10 */ int client_steps[] = { 2, 1, 1, 1, 4, 2, 1, 1, 2, 1 }; int server_steps[] = { 3, 1, 1, 2, 3, 1, 2, 1, 1, 1 }; do { /* * Client: * Handshake step */ int i; int no_steps; if( c_ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER) { no_steps = 0; } else { no_steps = client_steps[step - 1]; } for (i = 0; i < no_steps; i++) { if( ( ret = mbedtls_ssl_handshake_step( &c_ssl ) ) != 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret ); goto exit; } } } if( packet_in_num == 0 ) { mbedtls_printf( "--- client handshake step %zd ok\n", step ); } /* * Server: * Handshake step */ if( s_ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER) { no_steps = 0; } else { no_steps = server_steps[step - 1]; } for (i = 0; i < no_steps; i++) { if( ( ret = mbedtls_ssl_handshake_step( &s_ssl ) ) != 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned %d\n\n", ret ); goto exit; } } } if( packet_in_num == 0 ) { mbedtls_printf( "--- server handshake step %zd ok\n", step ); } step++; } while( ((c_ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER) || (s_ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER)) && (step <= MAX_HANDSHAKE_STEPS) ); if( packet_in_num == 0 ) { mbedtls_printf( "c_ssl.state: %d\n", c_ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER ); mbedtls_printf( "s_ssl.state: %d\n", s_ssl.state != MBEDTLS_SSL_HANDSHAKE_OVER ); } /* * Client: * Verify the server certificate */ if( packet_in_num == 0 ) { mbedtls_printf( " . Verifying peer X.509 certificate..." ); } /* In real life, we probably want to bail out when ret != 0 */ if( ( flags = mbedtls_ssl_get_verify_result( &c_ssl ) ) != 0 ) { char vrfy_buf[512]; mbedtls_printf( " failed\n" ); mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags ); mbedtls_printf( "%s\n", vrfy_buf ); } else if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } /* * Client: * Write the GET request */ if( packet_in_num == 0 ) { mbedtls_printf( " > Write to server:" ); fflush( stdout ); } len = sprintf( (char *) buf, GET_REQUEST ); while( ( ret = mbedtls_ssl_write( &c_ssl, buf, len ) ) <= 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); goto exit; } } len = ret; if( packet_in_num == 0 ) { mbedtls_printf( " %d bytes written\n\n%s", len, (char *) buf ); } /* * Server: * Read the HTTP Request */ if( packet_in_num == 0 ) { mbedtls_printf( " < Read from client:" ); fflush( stdout ); } do { len = sizeof( buf ) - 1; memset( buf, 0, sizeof( buf ) ); ret = mbedtls_ssl_read( &s_ssl, buf, len ); if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ) continue; if( ret <= 0 ) { switch( ret ) { case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: mbedtls_printf( " connection was closed gracefully\n" ); break; case MBEDTLS_ERR_NET_CONN_RESET: mbedtls_printf( " connection was reset by peer\n" ); break; default: mbedtls_printf( " mbedtls_ssl_read returned -0x%x\n", -ret ); break; } break; } len = ret; if( packet_in_num == 0 ) { mbedtls_printf( " %d bytes read\n\n%s", len, (char *) buf ); } if( ret > 0 ) break; } while( 1 ); /* * Server: * Write the 200 Response */ if( packet_in_num == 0 ) { mbedtls_printf( " > Write to client:" ); fflush( stdout ); } len = sprintf( (char *) buf, HTTP_RESPONSE, mbedtls_ssl_get_ciphersuite( &s_ssl ) ); while( ( ret = mbedtls_ssl_write( &s_ssl, buf, len ) ) <= 0 ) { if( ret == MBEDTLS_ERR_NET_CONN_RESET ) { mbedtls_printf( " failed\n ! peer closed the connection\n\n" ); goto exit; } if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); goto exit; } } len = ret; if( packet_in_num == 0 ) { mbedtls_printf( " %d bytes written\n\n%s\n", len, (char *) buf ); } /* * Client: * Read the HTTP response */ if( packet_in_num == 0 ) { mbedtls_printf( " < Read from server:" ); fflush( stdout ); } do { len = sizeof( buf ) - 1; memset( buf, 0, sizeof( buf ) ); ret = mbedtls_ssl_read( &c_ssl, buf, len ); if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE ) continue; if( ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY ) { ret = 0; break; } if( ret < 0 ) { mbedtls_printf( "failed\n ! mbedtls_ssl_read returned %d\n\n", ret ); break; } if( ret == 0 ) { mbedtls_printf( "\n\nEOF\n\n" ); break; } len = ret; if( packet_in_num == 0 ) { mbedtls_printf( " %d bytes read\n\n%s", len, (char *) buf ); } /* * Server: * Client read response. Close connection. */ if ( packet_in_num == 0 ) { mbedtls_printf( " . Closing the connection..." ); fflush( stdout ); } while( ( ret = mbedtls_ssl_close_notify( &s_ssl ) ) < 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) { mbedtls_printf( " failed\n ! mbedtls_ssl_close_notify returned %d\n\n", ret ); goto exit; } } if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } } while( 1 ); /* * Client: * Close connection. */ if( packet_in_num == 0 ) { mbedtls_printf( " . Closing the connection..." ); fflush( stdout ); } mbedtls_ssl_close_notify( &c_ssl ); if( packet_in_num == 0 ) { mbedtls_printf( " ok\n" ); } /* * Server: * We do not have multiple clients and therefore do not goto reset. */ /*ret = 0;*/ /*goto reset;*/ exit: #ifdef MBEDTLS_ERROR_C if( ret != 0 ) { char error_buf[100]; mbedtls_strerror( ret, error_buf, 100 ); mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf ); } #endif #if SOCKET_COMMUNICATION mbedtls_net_free( &client_fd ); mbedtls_net_free( &listen_fd ); mbedtls_net_free( &server_fd ); #endif mbedtls_x509_crt_free( &srvcert ); mbedtls_pk_free( &pkey ); mbedtls_ssl_free( &s_ssl ); mbedtls_ssl_free( &c_ssl ); mbedtls_ssl_config_free( &s_conf ); mbedtls_ssl_config_free( &c_conf ); #if defined(MBEDTLS_SSL_CACHE_C) mbedtls_ssl_cache_free( &cache ); #endif #if defined(_WIN32) mbedtls_printf( " Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); #endif return( ret ); }
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(&ts_entropy); mbedtls_ctr_drbg_init(&BACKEND->ctr_drbg); ret = mbedtls_ctr_drbg_seed(&BACKEND->ctr_drbg, entropy_func_mutex, &ts_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(&BACKEND->entropy); mbedtls_ctr_drbg_init(&BACKEND->ctr_drbg); ret = mbedtls_ctr_drbg_seed(&BACKEND->ctr_drbg, mbedtls_entropy_func, &BACKEND->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(&BACKEND->cacert); if(ssl_cafile) { ret = mbedtls_x509_crt_parse_file(&BACKEND->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(&BACKEND->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(&BACKEND->clicert); if(ssl_cert) { ret = mbedtls_x509_crt_parse_file(&BACKEND->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(&BACKEND->pk); if(SSL_SET_OPTION(key)) { ret = mbedtls_pk_parse_keyfile(&BACKEND->pk, SSL_SET_OPTION(key), SSL_SET_OPTION(key_passwd)); if(ret == 0 && !mbedtls_pk_can_do(&BACKEND->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(&BACKEND->crl); if(ssl_crlfile) { ret = mbedtls_x509_crl_parse_file(&BACKEND->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(&BACKEND->config); mbedtls_ssl_init(&BACKEND->ssl); if(mbedtls_ssl_setup(&BACKEND->ssl, &BACKEND->config)) { failf(data, "mbedTLS: ssl_init failed"); return CURLE_SSL_CONNECT_ERROR; } ret = mbedtls_ssl_config_defaults(&BACKEND->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(&BACKEND->config, &mbedtls_x509_crt_profile_fr); switch(SSL_CONN_CONFIG(version)) { case CURL_SSLVERSION_DEFAULT: case CURL_SSLVERSION_TLSv1: mbedtls_ssl_conf_min_version(&BACKEND->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(&BACKEND->config, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_0); mbedtls_ssl_conf_max_version(&BACKEND->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: case CURL_SSLVERSION_TLSv1_1: case CURL_SSLVERSION_TLSv1_2: case CURL_SSLVERSION_TLSv1_3: { CURLcode result = set_ssl_version_min_max(conn, sockindex); if(result != CURLE_OK) return result; break; } default: failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); return CURLE_SSL_CONNECT_ERROR; } mbedtls_ssl_conf_authmode(&BACKEND->config, MBEDTLS_SSL_VERIFY_OPTIONAL); mbedtls_ssl_conf_rng(&BACKEND->config, mbedtls_ctr_drbg_random, &BACKEND->ctr_drbg); mbedtls_ssl_set_bio(&BACKEND->ssl, &conn->sock[sockindex], mbedtls_net_send, mbedtls_net_recv, NULL /* rev_timeout() */); mbedtls_ssl_conf_ciphersuites(&BACKEND->config, mbedtls_ssl_list_ciphersuites()); #if defined(MBEDTLS_SSL_RENEGOTIATION) mbedtls_ssl_conf_renegotiation(&BACKEND->config, MBEDTLS_SSL_RENEGOTIATION_ENABLED); #endif #if defined(MBEDTLS_SSL_SESSION_TICKETS) mbedtls_ssl_conf_session_tickets(&BACKEND->config, MBEDTLS_SSL_SESSION_TICKETS_DISABLED); #endif /* Check if there's a cached ID we can/should use here! */ if(SSL_SET_OPTION(primary.sessionid)) { void *old_session = NULL; Curl_ssl_sessionid_lock(conn); if(!Curl_ssl_getsessionid(conn, &old_session, NULL, sockindex)) { ret = mbedtls_ssl_set_session(&BACKEND->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(&BACKEND->config, &BACKEND->cacert, &BACKEND->crl); if(SSL_SET_OPTION(key)) { mbedtls_ssl_conf_own_cert(&BACKEND->config, &BACKEND->clicert, &BACKEND->pk); } if(mbedtls_ssl_set_hostname(&BACKEND->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 = &BACKEND->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(&BACKEND->config, &BACKEND->protocols[0])) { failf(data, "Failed setting ALPN protocols"); return CURLE_SSL_CONNECT_ERROR; } for(p = &BACKEND->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(&BACKEND->config, mbed_debug, data); /* - 0 No debug * - 1 Error * - 2 State change * - 3 Informational * - 4 Verbose */ mbedtls_debug_set_threshold(4); #endif /* give application a chance to interfere with mbedTLS set up. */ if(data->set.ssl.fsslctx) { ret = (*data->set.ssl.fsslctx)(data, &BACKEND->config, data->set.ssl.fsslctxp); if(ret) { failf(data, "error signaled by ssl ctx callback"); return ret; } } connssl->connecting_state = ssl_connect_2; return CURLE_OK; }
int _ssl_init(nsp_state *N, TCP_SOCKET *sock, short srvmode, char *certfile, char *keyfile) { #define __FN__ __FILE__ ":_ssl_init()" #if defined HAVE_OPENSSL SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); if (srvmode) { sock->ssl_meth = (SSL_METHOD *)SSLv23_server_method(); } else { sock->ssl_meth = (SSL_METHOD *)SSLv23_client_method(); } sock->ssl_ctx = SSL_CTX_new(sock->ssl_meth); if (!sock->ssl_ctx) { n_warn(N, __FN__, "SSL Error"); return -1; } if ((certfile == NULL) || (keyfile == NULL)) return 0; if (SSL_CTX_use_certificate_file(sock->ssl_ctx, certfile, SSL_FILETYPE_PEM) <= 0) { n_warn(N, __FN__, "SSL Error loading certificate '%s'", certfile); return -1; } if (SSL_CTX_use_PrivateKey_file(sock->ssl_ctx, keyfile, SSL_FILETYPE_PEM) <= 0) { n_warn(N, __FN__, "SSL Error loading private key '%s'", keyfile); return -1; } if (!SSL_CTX_check_private_key(sock->ssl_ctx)) { n_warn(N, __FN__, "Private key does not match the public certificate"); return -1; } return 0; #elif defined HAVE_MBEDTLS const char *pers = "ssl_server"; int rc; mbedtls_ssl_config_init(&sock->conf); if ((rc = mbedtls_ssl_config_defaults(&sock->conf, srvmode ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { n_warn(N, __FN__, "mbedtls_ssl_config_defaults failed. error %d", rc); return -1; } mbedtls_ssl_conf_authmode(&sock->conf, MBEDTLS_SSL_VERIFY_NONE); mbedtls_entropy_init(&sock->entropy); mbedtls_ctr_drbg_init(&sock->ctr_drbg); if ((rc = mbedtls_ctr_drbg_seed(&sock->ctr_drbg, mbedtls_entropy_func, &sock->entropy, (const unsigned char *)pers, nc_strlen(pers))) != 0) { print_mbedtls_error(N, __FN__, rc); return -1; } mbedtls_ssl_conf_rng(&sock->conf, mbedtls_ctr_drbg_random, &sock->ctr_drbg); if ((certfile == NULL) || (keyfile == NULL)) { return 0; //if ((rc = mbedtls_x509_crt_parse(&sock->srvcert, (unsigned char *)mbedtls_test_srv_crt, nc_strlen(mbedtls_test_srv_crt))) != 0) { // print_mbedtls_error(N, __FN__, rc); // return -1; //} //if ((rc = mbedtls_x509_crt_parse(&sock->srvcert, (unsigned char *)mbedtls_test_ca_crt, nc_strlen(mbedtls_test_ca_crt))) != 0) { // print_mbedtls_error(N, __FN__, rc); // return -1; //} //if ((rc = mbedtls_pk_parse_key(&sock->pubkey, (unsigned char *)mbedtls_test_srv_key, nc_strlen(mbedtls_test_srv_key), NULL, 0)) != 0) { // print_mbedtls_error(N, __FN__, rc); // return -1; //} } else { if ((rc = mbedtls_x509_crt_parse_file(&sock->srvcert, certfile)) != 0) { //n_warn(N, __FN__, "x509_read_crtfile returned %08x", rc); print_mbedtls_error(N, __FN__, rc); return -1; } if ((rc = mbedtls_pk_parse_keyfile(&sock->pubkey, keyfile, NULL)) != 0) { //n_warn(N, __FN__, "x509_read_keyfile returned %08x", rc); print_mbedtls_error(N, __FN__, rc); return -1; } } mbedtls_ssl_conf_ca_chain(&sock->conf, sock->srvcert.next, NULL); if ((rc = mbedtls_ssl_conf_own_cert(&sock->conf, &sock->srvcert, &sock->pubkey)) != 0) { n_warn(N, __FN__, "mbedtls_ssl_conf_own_cert returned %08x", rc); return -1; } return 0; #endif #undef __FN__ }
int main( int argc, char *argv[] ) { int ret = 0, len; 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) ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_cas_pem, mbedtls_test_cas_pem_len ); #else { ret = 1; mbedtls_printf("MBEDTLS_CERTS_C not defined."); } #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 { ret = -1; mbedtls_printf("MBEDTLS_CERTS_C not defined."); } #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 { ret = -1; mbedtls_printf("MBEDTLS_CERTS_C or MBEDTLS_PEM_PARSE_C not defined."); } #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: 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( ret ); }
/** Create new TLS configuration * ATTENTION: Server certificate and private key have to be added outside this function! */ static struct altcp_tls_config * altcp_tls_create_config(int is_server, int have_cert, int have_pkey, int have_ca) { size_t sz; int ret; struct altcp_tls_config *conf; mbedtls_x509_crt *mem; if (TCP_WND < MBEDTLS_SSL_MAX_CONTENT_LEN) { LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG|LWIP_DBG_LEVEL_SERIOUS, ("altcp_tls: TCP_WND is smaller than the RX decrypion buffer, connection RX might stall!\n")); } altcp_mbedtls_mem_init(); sz = sizeof(struct altcp_tls_config); if (have_cert) { sz += sizeof(mbedtls_x509_crt); } if (have_ca) { sz += sizeof(mbedtls_x509_crt); } if (have_pkey) { sz += sizeof(mbedtls_pk_context); } conf = (struct altcp_tls_config *)altcp_mbedtls_alloc_config(sz); if (conf == NULL) { return NULL; } mem = (mbedtls_x509_crt *)(conf + 1); if (have_cert) { conf->cert = mem; mem++; } if (have_ca) { conf->ca = mem; mem++; } if (have_pkey) { conf->pkey = (mbedtls_pk_context *)mem; } mbedtls_ssl_config_init(&conf->conf); mbedtls_entropy_init(&conf->entropy); mbedtls_ctr_drbg_init(&conf->ctr_drbg); /* Seed the RNG */ ret = mbedtls_ctr_drbg_seed(&conf->ctr_drbg, ALTCP_MBEDTLS_RNG_FN, &conf->entropy, ALTCP_MBEDTLS_ENTROPY_PTR, ALTCP_MBEDTLS_ENTROPY_LEN); if (ret != 0) { LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ctr_drbg_seed failed: %d\n", ret)); altcp_mbedtls_free_config(conf); return NULL; } /* Setup ssl context (@todo: what's different for a client here? -> might better be done on listen/connect) */ ret = mbedtls_ssl_config_defaults(&conf->conf, is_server ? MBEDTLS_SSL_IS_SERVER : MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); if (ret != 0) { LWIP_DEBUGF(ALTCP_MBEDTLS_DEBUG, ("mbedtls_ssl_config_defaults failed: %d\n", ret)); altcp_mbedtls_free_config(conf); return NULL; } mbedtls_ssl_conf_authmode(&conf->conf, MBEDTLS_SSL_VERIFY_OPTIONAL); mbedtls_ssl_conf_rng(&conf->conf, mbedtls_ctr_drbg_random, &conf->ctr_drbg); #if ALTCP_MBEDTLS_DEBUG != LWIP_DBG_OFF mbedtls_ssl_conf_dbg(&conf->conf, altcp_mbedtls_debug, stdout); #endif #if defined(MBEDTLS_SSL_CACHE_C) && ALTCP_MBEDTLS_SESSION_CACHE_TIMEOUT_SECONDS mbedtls_ssl_conf_session_cache(&conf->conf, &conf->cache, mbedtls_ssl_cache_get, mbedtls_ssl_cache_set); mbedtls_ssl_cache_set_timeout(&conf->cache, 30); mbedtls_ssl_cache_set_max_entries(&conf->cache, 30); #endif return conf; }
void SetOptionalVerifyCert() { mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL); }
int dtlsclient_main( int argc, char *argv[] ) { int ret, 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; ((void) argc); ((void) argv); #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 ); 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_cas_pem, mbedtls_test_cas_pem_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_NAME, 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: mbedtls_printf( " > Write to server:" ); fflush( stdout ); 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\n", ret ); goto exit; } len = ret; mbedtls_printf( " %d bytes written\n\n%s\n\n", len, MESSAGE ); /* * 7. Read the echo response */ mbedtls_printf( " < Read from server:" ); fflush( stdout ); 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\n", -ret ); goto exit; } } len = ret; mbedtls_printf( " %d bytes read\n\n%s\n\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( ret ); }
/** * Constructor. */ ManuvrTLSClient::ManuvrTLSClient(BufferPipe* _n) : ManuvrTLS(_n, MBEDTLS_DEBUG_LEVEL) { _tls_pipe_name = "TLSClient"; mbedtls_ssl_init(&_ssl); if (nullptr != _n) { // This is the point at which we detect if our underlying transport // is a stream or datagram. This will impact our choices later on. int ret = mbedtls_ssl_config_defaults(&_conf, MBEDTLS_SSL_IS_CLIENT, _n->_bp_flag(BPIPE_FLAG_PIPE_PACKETIZED) ? MBEDTLS_SSL_TRANSPORT_DATAGRAM : MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT ); if (0 == ret) { mbedtls_ssl_conf_ciphersuites(&_conf, ManuvrTLS::allowed_ciphersuites); // TODO: Sec-fail. YOU FAIL! Remove once inter-op is demonstrated. mbedtls_ssl_conf_authmode(&_conf, MBEDTLS_SSL_VERIFY_OPTIONAL); // TODO: Need to be able to load a CA cert. If we also have // runtime-writable storage, we could do cert-pinning at this point. //mbedtls_ssl_conf_ca_chain( &_conf, &cacert, nullptr); mbedtls_ssl_conf_rng(&_conf, mbedtls_ctr_drbg_random, &_ctr_drbg); mbedtls_ssl_conf_dbg(&_conf, tls_log_shunt, stdout); // TODO: Suspect... // TODO: If appropriate, we load a certificate. //ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) if (0 == ret) { // TODO: This should be loaded from secure storage. // TODO: This is a choice independent from the cert. // TODO: We hardcode the same IoTivity default creds used elsewhere. ret = mbedtls_ssl_conf_psk(&_conf, (const unsigned char*)"AAAAAAAAAAAAAAAA", 16, (const unsigned char*)"32323232-3232-3232-3232-323232323232", 36); if (0 == ret) { ret = mbedtls_ssl_setup(&_ssl, &_conf); if (0 == ret) { // TODO: This might be the lookup name if we had DNS. //ret = mbedtls_ssl_set_hostname(&_ssl, SERVER_NAME); if (0 == ret) { _log.concatf("ManuvrTLSClient(): Construction completed.\n"); } else { _log.concatf("ManuvrTLSClient() failed: mbedtls_ssl_set_hostname returned 0x%04x\n", ret); } } else { _log.concatf("ManuvrTLSClient() failed: mbedtls_ssl_setup returned 0x%04x\n", ret); } } else { _log.concatf("ManuvrTLSClient() failed: mbedtls_ssl_conf_psk returned 0x%04x\n", ret); } } else { _log.concatf("ManuvrTLSClient() failed: mbedtls_x509_crt_parse returned 0x%04x\n", ret); } } else { _log.concatf("ManuvrTLSClient() failed: mbedtls_ssl_config_defaults returned 0x%04x\n", ret); } } Kernel::log(&_log); }
int ssl_connect(SSLConnection* conn, const char* host, int port) { int ret; char buffer[8]; ret = mbedtls_ctr_drbg_seed(&conn->drbg_ctx, mbedtls_entropy_func, &conn->entropy_ctx, (const unsigned char *) pers, strlen(pers)); if (ret < 0) { return -1; } ret = mbedtls_x509_crt_parse(&conn->ca_cert, (const unsigned char *) conn->ca_cert_str, strlen(conn->ca_cert_str) + 1); if (ret < 0) { return handle_error(ret); } ret = mbedtls_x509_crt_parse(&conn->client_cert, (const unsigned char *) conn->client_cert_str, strlen(conn->client_cert_str) + 1); if (ret < 0) { return handle_error(ret); } ret = mbedtls_pk_parse_key(&conn->client_key, (const unsigned char *) conn->client_key_str, strlen(conn->client_key_str) + 1, NULL, 0); if (ret != 0) { return handle_error(ret); } snprintf(buffer, sizeof(buffer), "%d", port); ret = mbedtls_net_connect(&conn->net_ctx, host, buffer, MBEDTLS_NET_PROTO_TCP); if (ret != 0) { return handle_error(ret); } ret = mbedtls_ssl_config_defaults(&conn->ssl_conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT); if (ret != 0) { return handle_error(ret); } #ifdef MBEDTLS_DEBUG_C mbedtls_ssl_conf_dbg(&conn->ssl_conf, my_debug, stdout); mbedtls_debug_set_threshold(5); #endif mbedtls_ssl_conf_authmode(&conn->ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED); mbedtls_ssl_conf_rng(&conn->ssl_conf, mbedtls_ctr_drbg_random, &conn->drbg_ctx); mbedtls_ssl_conf_read_timeout(&conn->ssl_conf, SSL_READ_TIMEOUT_MS); mbedtls_ssl_conf_ca_chain(&conn->ssl_conf, &conn->ca_cert, NULL); ret = mbedtls_ssl_conf_own_cert(&conn->ssl_conf, &conn->client_cert, &conn->client_key); if (ret != 0) { return handle_error(ret); } ret = mbedtls_ssl_setup(&conn->ssl_ctx, &conn->ssl_conf); if (ret != 0) { return handle_error(ret); } ret = mbedtls_ssl_set_hostname(&conn->ssl_ctx, host); if (ret != 0) { return handle_error(ret); } mbedtls_ssl_set_bio(&conn->ssl_ctx, &conn->net_ctx, mbedtls_net_send, NULL, mbedtls_net_recv_timeout); while ((ret = mbedtls_ssl_handshake(&conn->ssl_ctx)) != 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) { return handle_error(ret); } } handle_error(ret); vTaskDelay(5000 / portTICK_PERIOD_MS); } mbedtls_ssl_get_record_expansion(&conn->ssl_ctx); ret = mbedtls_ssl_get_verify_result(&conn->ssl_ctx); if (ret != 0) { return handle_error(ret); } return ret; }
static CURLcode mbed_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; 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, 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; }
void clax_loop_ssl(clax_ctx_t *clax_ctx) { int ret = 0; char pers[] = "clax_server"; #ifdef MVS clax_etoa(pers, strlen(pers)); #endif 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_ssl_cache_context cache; mbedtls_ssl_init(&ssl); mbedtls_ssl_config_init(&conf); mbedtls_ssl_cache_init(&cache); 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 clax_log("Loading the server cert and key..."); unsigned char *file = NULL; size_t file_len = 0; clax_log("Loading '%s'...", options.cert_file); file = clax_slurp_alloc(options.cert_file, &file_len); if (file == NULL) { clax_log("Can't load cert_file '%s': %s", options.cert_file, strerror(errno)); goto exit; } #ifdef MVS clax_etoa((char *)file, file_len); #endif clax_log("Parsing '%s'...", options.cert_file); ret = mbedtls_x509_crt_parse(&srvcert, (const unsigned char *)file, file_len); free(file); if (ret != 0) { clax_log("failed\n ! mbedtls_x509_crt_parse returned %d", ret); goto exit; } clax_log("Loading '%s'...", options.key_file); file = clax_slurp_alloc(options.key_file, &file_len); if (file == NULL) { clax_log("Can't load key_file: %s", options.key_file); goto exit; } #ifdef MVS clax_etoa((char *)file, file_len); #endif clax_log("Parsing '%s'...", options.key_file); ret = mbedtls_pk_parse_key(&pkey, (const unsigned char *)file, file_len, NULL, 0); free(file); if (ret != 0) { clax_log("failed\n ! mbedtls_pk_parse_key returned %d", ret); goto exit; } clax_log("ok"); if (options.entropy_file[0]) { clax_log("Using '%s' as entropy file...", options.entropy_file); if ((ret = mbedtls_entropy_add_source(&entropy, dev_random_entropy_poll, NULL, DEV_RANDOM_THRESHOLD, MBEDTLS_ENTROPY_SOURCE_STRONG)) != 0) { clax_log("failed\n ! mbedtls_entropy_add_source returned -0x%04x", -ret); goto exit; } clax_log("ok"); } clax_log("Seeding the random number generator..."); if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *)pers, strlen(pers))) != 0) { clax_log("failed\n ! mbedtls_ctr_drbg_seed returned %d", ret); goto exit; } clax_log("ok"); clax_log("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) { clax_log("failed\n ! mbedtls_ssl_config_defaults returned %d", ret); goto exit; } if (!options.no_ssl_verify) { mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_REQUIRED); } mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg); mbedtls_ssl_conf_session_cache(&conf, &cache, mbedtls_ssl_cache_get, mbedtls_ssl_cache_set); mbedtls_ssl_conf_ca_chain(&conf, srvcert.next, NULL); if ((ret = mbedtls_ssl_conf_own_cert(&conf, &srvcert, &pkey)) != 0) { clax_log(" failed\n ! mbedtls_ssl_conf_own_cert returned %d", ret); goto exit; } if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) { clax_log(" failed\n ! mbedtls_ssl_setup returned %d", ret); goto exit; } clax_log("ok"); mbedtls_ssl_session_reset(&ssl); mbedtls_ssl_set_bio(&ssl, NULL, clax_send, clax_recv, NULL); clax_log("ok"); clax_log("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) { clax_log("failed\n ! mbedtls_ssl_handshake returned %d", ret); goto exit; } } clax_log("ok"); clax_http_dispatch(clax_ctx, clax_send_ssl, clax_recv_ssl, &ssl); clax_log("Closing the connection..."); while ((ret = mbedtls_ssl_close_notify(&ssl)) < 0) { if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { clax_log("failed\n ! mbedtls_ssl_close_notify returned %d", ret); goto exit; } } clax_log("ok"); ret = 0; goto exit; exit: fflush(stdout); #ifdef MBEDTLS_ERROR_C if (ret != 0) { char error_buf[100]; mbedtls_strerror(ret, error_buf, 100); #ifdef MVS clax_atoe(error_buf, strlen(error_buf)); #endif clax_log("Last error was: %d - %s", ret, error_buf); } #endif mbedtls_x509_crt_free(&srvcert); mbedtls_pk_free(&pkey); mbedtls_ssl_free(&ssl); mbedtls_ssl_config_free(&conf); mbedtls_ssl_cache_free(&cache); mbedtls_ctr_drbg_free(&ctr_drbg); mbedtls_entropy_free(&entropy); }