// STL includes #include #include // Linux includes #include #ifndef _WIN32 #include #endif // Local Hyperion includes #include "ProviderUdpSSL.h" #include const int MAX_RETRY = 5; const ushort MAX_PORT_SSL = 65535; ProviderUdpSSL::ProviderUdpSSL(const QJsonObject &deviceConfig) : LedDevice(deviceConfig) , client_fd() , entropy() , ssl() , conf() , ctr_drbg() , timer() , _transport_type("DTLS") , _custom("dtls_client") , _address("127.0.0.1") , _defaultHost("127.0.0.1") , _port(1) , _ssl_port(1) , _server_name() , _psk() , _psk_identity() , _read_timeout(STREAM_SSL_READ_TIMEOUT.count()) , _handshake_timeout_min(STREAM_SSL_HANDSHAKE_TIMEOUT_MIN.count()) , _handshake_timeout_max(STREAM_SSL_HANDSHAKE_TIMEOUT_MAX.count()) , _handshake_attempts(5) , _retry_left(MAX_RETRY) , _stopConnection(true) , _debugStreamer(false) , _debugLevel(0) { _latchTime_ms = 1; } ProviderUdpSSL::~ProviderUdpSSL() { } bool ProviderUdpSSL::init(const QJsonObject &deviceConfig) { bool isInitOK = false; // Initialise sub-class if ( LedDevice::init(deviceConfig) ) { _debugStreamer = deviceConfig["debugStreamer"].toBool(false); _debugLevel = deviceConfig["debugLevel"].toString().toInt(0); //PSK Pre Shared Key _psk = deviceConfig["psk"].toString(); _psk_identity = deviceConfig["psk_identity"].toString(); _port = deviceConfig["sslport"].toInt(2100); _server_name = deviceConfig["servername"].toString(); if( deviceConfig.contains("transport_type") ) _transport_type = deviceConfig["transport_type"].toString("DTLS"); if( deviceConfig.contains("seed_custom") ) _custom = deviceConfig["seed_custom"].toString("dtls_client"); if( deviceConfig.contains("retry_left") ) _retry_left = deviceConfig["retry_left"].toInt(MAX_RETRY); if( deviceConfig.contains("read_timeout") ) _read_timeout = deviceConfig["read_timeout"].toInt(0); if( deviceConfig.contains("hs_timeout_min") ) _handshake_timeout_min = deviceConfig["hs_timeout_min"].toInt(400); if( deviceConfig.contains("hs_timeout_max") ) _handshake_timeout_max = deviceConfig["hs_timeout_max"].toInt(1000); if( deviceConfig.contains("hs_attempts") ) _handshake_attempts = deviceConfig["hs_attempts"].toInt(5); QString host = deviceConfig["host"].toString(_defaultHost); //Split hostname from API-port in case given QStringList addressparts = QStringUtils::split(host, ":", QStringUtils::SplitBehavior::SkipEmptyParts); QString udpHost = addressparts[0]; QStringList debugLevels = QStringList() << "No Debug" << "Error" << "State Change" << "Informational" << "Verbose"; configLog( "SSL Streamer Debug", "%s", ( _debugStreamer ) ? "yes" : "no" ); configLog( "SSL DebugLevel", "[%d] %s", _debugLevel, QSTRING_CSTR( debugLevels[ _debugLevel ]) ); configLog( "SSL Servername", "%s", QSTRING_CSTR( _server_name ) ); configLog( "SSL Host", "%s", QSTRING_CSTR( host ) ); configLog( "SSL Port", "%d", _port ); configLog( "PSK", "%s", QSTRING_CSTR( _psk ) ); configLog( "PSK-Identity", "%s", QSTRING_CSTR( _psk_identity ) ); configLog( "SSL Transport Type", "%s", QSTRING_CSTR( _transport_type ) ); configLog( "SSL Seed Custom", "%s", QSTRING_CSTR( _custom ) ); configLog( "SSL Retry Left", "%d", _retry_left ); configLog( "SSL Read Timeout", "%d", _read_timeout ); configLog( "SSL Handshake Timeout min", "%d", _handshake_timeout_min ); configLog( "SSL Handshake Timeout max", "%d", _handshake_timeout_max ); configLog( "SSL Handshake attempts", "%d", _handshake_attempts ); if ( _address.setAddress(udpHost) ) { Debug( _log, "Successfully parsed %s as an ip address.", QSTRING_CSTR(udpHost) ); } else { Debug( _log, "Failed to parse [%s] as an ip address.", QSTRING_CSTR(udpHost) ); QHostInfo info = QHostInfo::fromName(udpHost); if ( info.addresses().isEmpty() ) { Debug( _log, "Failed to parse [%s] as a hostname.", QSTRING_CSTR(udpHost) ); QString errortext = QString("Invalid target address [%1]!").arg(host); this->setInError( errortext ); isInitOK = false; } else { Debug( _log, "Successfully parsed %s as a hostname.", QSTRING_CSTR(udpHost) ); _address = info.addresses().first(); } } int config_port = deviceConfig["sslport"].toInt(_port); if ( config_port <= 0 || config_port > MAX_PORT_SSL ) { QString errortext = QString ("Invalid target port [%1]!").arg(config_port); this->setInError( errortext ); isInitOK = false; } else { _ssl_port = config_port; Debug( _log, "UDP SSL using %s:%u", QSTRING_CSTR( _address.toString() ), _ssl_port ); isInitOK = true; } } return isInitOK; } int ProviderUdpSSL::open() { int retval = -1; _isDeviceReady = false; // TODO: Question: Just checking .... Is this one time initialisation or required with every open request (during switch-off/switch-on)? // In case one time initialisation, it should go to the init method. // Everything that is required to pen a UDP-SSL connection again (after it maybe was closed remotely should go here) if ( !initNetwork() ) { this->setInError( "UDP SSL Network error!" ); } else { // Everything is OK -> enable device _isDeviceReady = true; retval = 0; } return retval; } int ProviderUdpSSL::close() { // LedDevice specific closing activities int retval = 0; _isDeviceReady = false; // TODO: You may want to check, if the device is already closed or close it and return, if ok or not // Test, if device requires closing if ( true /*If device is still open*/ ) { // Close device LedDevice::close(); closeSSLConnection(); // Everything is OK -> device is closed } return retval; } void ProviderUdpSSL::closeSSLConnection() { if( _isDeviceReady && !_stopConnection ) { closeSSLNotify(); freeSSLConnection(); } } const int *ProviderUdpSSL::getCiphersuites() const { return mbedtls_ssl_list_ciphersuites(); } void ProviderUdpSSL::configLog(const char* msg, const char* type, ...) { if( _debugStreamer ) { const size_t max_val_length = 1024; char val[max_val_length]; va_list args; va_start(args, type); vsnprintf(val, max_val_length, type, args); va_end(args); std::string s = msg; int max = 30; s.append(max - s.length(), ' '); Debug( _log, "%s: %s", s.c_str(), val ); } } void ProviderUdpSSL::sslLog(const QString &msg, const char* errorType) { sslLog( QSTRING_CSTR( msg ), errorType ); } void ProviderUdpSSL::sslLog(const char* msg, const char* errorType) { if( strcmp("fatal", errorType) == 0 ) Error( _log, "%s", msg ); if( _debugStreamer ) { if( strcmp("debug", errorType) == 0 ) Debug( _log, "%s", msg ); if( strcmp("warning", errorType) == 0 ) Warning( _log, "%s", msg ); if( strcmp("error", errorType) == 0 ) Error( _log, "%s", msg ); } } bool ProviderUdpSSL::initNetwork() { sslLog( "init SSL Network..." ); QMutexLocker locker(&_hueMutex); if (!initConnection()) return false; sslLog( "init SSL Network...ok" ); _stopConnection = false; return true; } bool ProviderUdpSSL::initConnection() { sslLog( "init SSL Network -> initConnection" ); mbedtls_net_init(&client_fd); mbedtls_ssl_init(&ssl); mbedtls_ssl_config_init(&conf); mbedtls_x509_crt_init(&cacert); mbedtls_ctr_drbg_init(&ctr_drbg); if(!seedingRNG()) return false; return setupStructure(); } bool ProviderUdpSSL::seedingRNG() { int ret = 0; sslLog( "Seeding the random number generator..." ); mbedtls_entropy_init(&entropy); sslLog( "Set mbedtls_ctr_drbg_seed..." ); const char* custom = QSTRING_CSTR( _custom ); if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, reinterpret_cast(custom), strlen(custom))) != 0) { sslLog( QString("mbedtls_ctr_drbg_seed FAILED %1").arg( errorMsg( ret ) ), "error" ); return false; } sslLog( "Seeding the random number generator...ok" ); return true; } bool ProviderUdpSSL::setupStructure() { int ret = 0; sslLog( QString( "Setting up the %1 structure").arg( _transport_type ) ); //TLS MBEDTLS_SSL_TRANSPORT_STREAM //DTLS MBEDTLS_SSL_TRANSPORT_DATAGRAM int transport = ( _transport_type == "DTLS" ) ? MBEDTLS_SSL_TRANSPORT_DATAGRAM : MBEDTLS_SSL_TRANSPORT_STREAM; if ((ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT, transport, MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { sslLog( QString("mbedtls_ssl_config_defaults FAILED %1").arg( errorMsg( ret ) ), "error" ); return false; } const int * ciphersuites = getCiphersuites(); if( _debugStreamer ) { int s = ( sizeof( ciphersuites ) ) / sizeof( int ); QString cipher_values; for(int i=0; i 0) cipher_values.append(", "); cipher_values.append(QString::number(ciphersuites[i])); } sslLog( ( QString("used ciphersuites value: %1").arg( cipher_values ) ) ); } mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_REQUIRED); //mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL); //mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_NONE); mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL); mbedtls_ssl_conf_ciphersuites(&conf, ciphersuites); mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg); if ( _debugLevel > 0) { mbedtls_ssl_conf_verify(&conf, ProviderUdpSSLVerify, NULL); mbedtls_ssl_conf_dbg(&conf, ProviderUdpSSLDebug, NULL); mbedtls_debug_set_threshold( _debugLevel ); } if( _read_timeout > 0 ) mbedtls_ssl_conf_read_timeout(&conf, _read_timeout); mbedtls_ssl_conf_handshake_timeout(&conf, _handshake_timeout_min, _handshake_timeout_max); if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) { sslLog( QString("mbedtls_ssl_setup FAILED %1").arg( errorMsg( ret ) ), "error" ); return false; } if ((ret = mbedtls_ssl_set_hostname(&ssl, QSTRING_CSTR( _server_name ))) != 0) { sslLog( QString("mbedtls_ssl_set_hostname FAILED %1").arg( errorMsg( ret ) ), "error" ); return false; } sslLog( QString( "Setting up the %1 structure...ok").arg( _transport_type ) ); return startUPDConnection(); } bool ProviderUdpSSL::startUPDConnection() { sslLog( "init SSL Network -> startUPDConnection" ); int ret = 0; mbedtls_ssl_session_reset(&ssl); if(!setupPSK()) return false; sslLog( QString("Connecting to udp %1:%2").arg( _address.toString() ).arg( _ssl_port ) ); if ((ret = mbedtls_net_connect( &client_fd, _address.toString().toUtf8(), std::to_string(_ssl_port).c_str(), MBEDTLS_NET_PROTO_UDP)) != 0) { sslLog( QString("mbedtls_net_connect FAILED %1").arg( errorMsg( ret ) ), "error" ); return false; } mbedtls_ssl_set_bio(&ssl, &client_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); sslLog( "Connecting...ok" ); return startSSLHandshake(); } bool ProviderUdpSSL::setupPSK() { int ret; QByteArray pskArray = _psk.toUtf8(); QByteArray pskRawArray = QByteArray::fromHex(pskArray); QByteArray pskIdArray = _psk_identity.toUtf8(); QByteArray pskIdRawArray = pskIdArray; if (0 != (ret = mbedtls_ssl_conf_psk( &conf, ( const unsigned char* ) pskRawArray.data(), pskRawArray.length() * sizeof(char), reinterpret_cast ( pskIdRawArray.data() ), pskIdRawArray.length() * sizeof(char) ) ) ) { sslLog( QString("mbedtls_ssl_conf_psk FAILED %1").arg( errorMsg( ret ) ), "error" ); return false; } return true; } bool ProviderUdpSSL::startSSLHandshake() { sslLog( "init SSL Network -> startSSLHandshake" ); int ret = 0; sslLog( QString( "Performing the SSL/%1 handshake...").arg( _transport_type ) ); for (unsigned int attempt = 1; attempt <= _handshake_attempts; ++attempt) { sslLog( QString("handshake attempt %1/%2").arg( attempt ).arg( _handshake_attempts ) ); do { ret = mbedtls_ssl_handshake(&ssl); } while (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE); if (ret == 0) { break; } else { sslLog( QString("mbedtls_ssl_handshake attempt %1/%2 FAILED %3").arg( attempt ).arg( _handshake_attempts ).arg( errorMsg( ret ) ) ); } QThread::msleep(200); } if (ret != 0) { sslLog( QString("mbedtls_ssl_handshake FAILED %1").arg( errorMsg( ret ) ), "error" ); handleReturn(ret); sslLog( "UDP SSL Connection failed!", "fatal" ); return false; } else { if( ( mbedtls_ssl_get_verify_result( &ssl ) ) != 0 ) { sslLog( "SSL certificate verification failed!", "fatal" ); return false; } } sslLog( QString( "Performing the SSL/%1 handshake...ok").arg( _transport_type ) ); return true; } void ProviderUdpSSL::freeSSLConnection() { sslLog( "SSL Connection clean-up..." ); _stopConnection = true; try { mbedtls_ssl_session_reset(&ssl); mbedtls_net_free(&client_fd); mbedtls_ssl_free(&ssl); mbedtls_ssl_config_free(&conf); mbedtls_x509_crt_free(&cacert); mbedtls_ctr_drbg_free(&ctr_drbg); mbedtls_entropy_free(&entropy); sslLog( "SSL Connection clean-up...ok" ); } catch (std::exception &e) { sslLog( QString("SSL Connection clean-up Error: %s").arg( e.what() ) ); } catch (...) { sslLog( "SSL Connection clean-up Error: " ); } } void ProviderUdpSSL::writeBytes(unsigned size, const unsigned char * data) { if( _stopConnection ) return; QMutexLocker locker(&_hueMutex); int ret = 0; do { ret = mbedtls_ssl_write(&ssl, data, size); } while (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE); if (ret <= 0) { handleReturn(ret); } } void ProviderUdpSSL::handleReturn(int ret) { bool closeNotify = false; bool gotoExit = false; switch (ret) { case MBEDTLS_ERR_SSL_TIMEOUT: sslLog( errorMsg( ret ), "warning" ); if ( _retry_left-- > 0 ) return; gotoExit = true; break; case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: sslLog( "SSL Connection was closed gracefully", "warning" ); ret = 0; closeNotify = true; break; default: sslLog( QString("mbedtls_ssl_read returned %1").arg( errorMsg( ret ) ), "warning" ); gotoExit = true; } if (closeNotify) { closeSSLNotify(); gotoExit = true; } if (gotoExit) { sslLog( "Exit SSL connection" ); _stopConnection = true; } } QString ProviderUdpSSL::errorMsg(int ret) { QString msg; #ifdef MBEDTLS_ERROR_C char error_buf[1024]; mbedtls_strerror(ret, error_buf, 1024); msg = QString("Last error was: %1 - %2").arg( ret ).arg( error_buf ); #else switch (ret) { #if defined(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE) case MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE: msg = "The requested feature is not available. - MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE -0x7080"; break; #endif #if defined(MBEDTLS_ERR_SSL_BAD_INPUT_DATA) case MBEDTLS_ERR_SSL_BAD_INPUT_DATA: msg = "Bad input parameters to function. - MBEDTLS_ERR_SSL_BAD_INPUT_DATA -0x7100"; break; #endif #if defined(MBEDTLS_ERR_SSL_INVALID_MAC) case MBEDTLS_ERR_SSL_INVALID_MAC: msg = "Verification of the message MAC failed. - MBEDTLS_ERR_SSL_INVALID_MAC -0x7180"; break; #endif #if defined(MBEDTLS_ERR_SSL_INVALID_RECORD) case MBEDTLS_ERR_SSL_INVALID_RECORD: msg = "An invalid SSL record was received. - MBEDTLS_ERR_SSL_INVALID_RECORD -0x7200"; break; #endif #if defined(MBEDTLS_ERR_SSL_CONN_EOF) case MBEDTLS_ERR_SSL_CONN_EOF: msg = "The connection indicated an EOF. - MBEDTLS_ERR_SSL_CONN_EOF -0x7280"; break; #endif #if defined(MBEDTLS_ERR_SSL_UNKNOWN_CIPHER) case MBEDTLS_ERR_SSL_UNKNOWN_CIPHER: msg = "An unknown cipher was received. - MBEDTLS_ERR_SSL_UNKNOWN_CIPHER -0x7300"; break; #endif #if defined(MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN) case MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN: msg = "The server has no ciphersuites in common with the client. - MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN -0x7380"; break; #endif #if defined(MBEDTLS_ERR_SSL_NO_RNG) case MBEDTLS_ERR_SSL_NO_RNG: msg = "No RNG was provided to the SSL module. - MBEDTLS_ERR_SSL_NO_RNG -0x7400"; break; #endif #if defined(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE) case MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE: msg = "No client certification received from the client, but required by the authentication mode. - MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE -0x7480"; break; #endif #if defined(MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE) case MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE: msg = "Our own certificate(s) is/are too large to send in an SSL message. - MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE -0x7500"; break; #endif #if defined(MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED) case MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED: msg = "The own certificate is not set, but needed by the server. - MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED -0x7580"; break; #endif #if defined(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED) case MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED: msg = "The own private key or pre-shared key is not set, but needed. - MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED -0x7600"; break; #endif #if defined(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED) case MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED: msg = "No CA Chain is set, but required to operate. - MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED -0x7680"; break; #endif #if defined(MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE) case MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE: msg = "An unexpected message was received from our peer. - MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE -0x7700"; break; #endif #if defined(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE) case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE: msg = "A fatal alert message was received from our peer. - MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE -0x7780"; break; #endif #if defined(MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED) case MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED: msg = "Verification of our peer failed. - MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED -0x7800"; break; #endif #if defined(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: msg = "The peer notified us that the connection is going to be closed. - MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY -0x7880"; break; #endif #if defined(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO) case MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO: msg = "Processing of the ClientHello handshake message failed. - MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO -0x7900"; break; #endif #if defined(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO) case MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO: msg = "Processing of the ServerHello handshake message failed. - MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO -0x7980"; break; #endif #if defined(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE) case MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE: msg = "Processing of the Certificate handshake message failed. - MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE -0x7A00"; break; #endif #if defined(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST) case MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST: msg = "Processing of the CertificateRequest handshake message failed. - MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST -0x7A80"; break; #endif #if defined(MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE) case MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE: msg = "Processing of the ServerKeyExchange handshake message failed. - MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE -0x7B00"; break; #endif #if defined(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE) case MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE: msg = "Processing of the ServerHelloDone handshake message failed. - MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE -0x7B80"; break; #endif #if defined(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE) case MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE: msg = "Processing of the ClientKeyExchange handshake message failed. - MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE -0x7C00"; break; #endif #if defined(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP) case MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP: msg = "Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public. - MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP -0x7C80"; break; #endif #if defined(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS) case MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS: msg = "Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret. - MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS -0x7D00"; break; #endif #if defined(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY) case MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY: msg = "Processing of the CertificateVerify handshake message failed. - MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY -0x7D80"; break; #endif #if defined(MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC) case MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC: msg = "Processing of the ChangeCipherSpec handshake message failed. - MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC -0x7E00"; break; #endif #if defined(MBEDTLS_ERR_SSL_BAD_HS_FINISHED) case MBEDTLS_ERR_SSL_BAD_HS_FINISHED: msg = "Processing of the Finished handshake message failed. - MBEDTLS_ERR_SSL_BAD_HS_FINISHED -0x7E80"; break; #endif #if defined(MBEDTLS_ERR_SSL_ALLOC_FAILED) case MBEDTLS_ERR_SSL_ALLOC_FAILED: msg = "Memory allocation failed. - MBEDTLS_ERR_SSL_ALLOC_FAILED -0x7F00"; break; #endif #if defined(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED) case MBEDTLS_ERR_SSL_HW_ACCEL_FAILED: msg = "Hardware acceleration function returned with error. - MBEDTLS_ERR_SSL_HW_ACCEL_FAILED -0x7F80"; break; #endif #if defined(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH) case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH: msg = "Hardware acceleration function skipped / left alone data. - MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH -0x6F80"; break; #endif #if defined(MBEDTLS_ERR_SSL_COMPRESSION_FAILED) case MBEDTLS_ERR_SSL_COMPRESSION_FAILED: msg = "Processing of the compression / decompression failed. - MBEDTLS_ERR_SSL_COMPRESSION_FAILED -0x6F00"; break; #endif #if defined(MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION) case MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION: msg = "Handshake protocol not within min/max boundaries. - MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION -0x6E80"; break; #endif #if defined(MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET) case MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET: msg = "Processing of the NewSessionTicket handshake message failed. - MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET -0x6E00"; break; #endif #if defined(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED) case MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED: msg = "Session ticket has expired. - MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED -0x6D80"; break; #endif #if defined(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH) case MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH: msg = "Public key type mismatch (eg, asked for RSA key exchange and presented EC key) - MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH -0x6D00"; break; #endif #if defined(MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) case MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY: msg = "Unknown identity received (eg, PSK identity) - MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY -0x6C80"; break; #endif #if defined(MBEDTLS_ERR_SSL_INTERNAL_ERROR) case MBEDTLS_ERR_SSL_INTERNAL_ERROR: msg = "Internal error (eg, unexpected failure in lower-level module) - MBEDTLS_ERR_SSL_INTERNAL_ERROR -0x6C00"; break; #endif #if defined(MBEDTLS_ERR_SSL_COUNTER_WRAPPING) case MBEDTLS_ERR_SSL_COUNTER_WRAPPING: msg = "A counter would wrap (eg, too many messages exchanged). - MBEDTLS_ERR_SSL_COUNTER_WRAPPING -0x6B80"; break; #endif #if defined(MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO) case MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO: msg = "Unexpected message at ServerHello in renegotiation. - MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO -0x6B00"; break; #endif #if defined(MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) case MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED: msg = "DTLS client must retry for hello verification. - MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED -0x6A80"; break; #endif #if defined(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) case MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL: msg = "A buffer is too small to receive or write a message. - MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL -0x6A00"; break; #endif #if defined(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE) case MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE: msg = "None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages). - MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE -0x6980"; break; #endif #if defined(MBEDTLS_ERR_SSL_WANT_READ) case MBEDTLS_ERR_SSL_WANT_READ: msg = "No data of requested type currently available on underlying transport. - MBEDTLS_ERR_SSL_WANT_READ -0x6900"; break; #endif #if defined(MBEDTLS_ERR_SSL_WANT_WRITE) case MBEDTLS_ERR_SSL_WANT_WRITE: msg = "Connection requires a write call. - MBEDTLS_ERR_SSL_WANT_WRITE -0x6880"; break; #endif #if defined(MBEDTLS_ERR_SSL_TIMEOUT) case MBEDTLS_ERR_SSL_TIMEOUT: msg = "The operation timed out. - MBEDTLS_ERR_SSL_TIMEOUT -0x6800"; break; #endif #if defined(MBEDTLS_ERR_SSL_CLIENT_RECONNECT) case MBEDTLS_ERR_SSL_CLIENT_RECONNECT: msg = "The client initiated a reconnect from the same port. - MBEDTLS_ERR_SSL_CLIENT_RECONNECT -0x6780"; break; #endif #if defined(MBEDTLS_ERR_SSL_UNEXPECTED_RECORD) case MBEDTLS_ERR_SSL_UNEXPECTED_RECORD: msg = "Record header looks valid but is not expected. - MBEDTLS_ERR_SSL_UNEXPECTED_RECORD -0x6700"; break; #endif #if defined(MBEDTLS_ERR_SSL_NON_FATAL) case MBEDTLS_ERR_SSL_NON_FATAL: msg = "The alert message received indicates a non-fatal error. - MBEDTLS_ERR_SSL_NON_FATAL -0x6680"; break; #endif #if defined(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH) case MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH: msg = "Couldn't set the hash for verifying CertificateVerify. - MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600"; break; #endif #if defined(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING) case MBEDTLS_ERR_SSL_CONTINUE_PROCESSING: msg = "Internal-only message signaling that further message-processing should be done. - MBEDTLS_ERR_SSL_CONTINUE_PROCESSING -0x6580"; break; #endif #if defined(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS: msg = "The asynchronous operation is not completed yet. - MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS -0x6500"; break; #endif #if defined(MBEDTLS_ERR_SSL_EARLY_MESSAGE) case MBEDTLS_ERR_SSL_EARLY_MESSAGE: msg = "Internal-only message signaling that a message arrived early. - MBEDTLS_ERR_SSL_EARLY_MESSAGE -0x6480"; break; #endif #if defined(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS: msg = "A cryptographic operation is in progress. - MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS -0x7000"; break; #endif default: msg.append("Last error was: ").append( QString::number(ret) ); } #endif return msg; } void ProviderUdpSSL::closeSSLNotify() { int ret = 0; sslLog( "Closing SSL connection..." ); /* No error checking, the connection might be closed already */ do { ret = mbedtls_ssl_close_notify(&ssl); } while (ret == MBEDTLS_ERR_SSL_WANT_WRITE); sslLog( "SSL Connection successful closed" ); }