bool TransportLayerDtls::SetupCipherSuites(PRFileDesc* ssl_fd) const { SECStatus rv; // Set the SRTP ciphers if (!srtp_ciphers_.empty()) { // Note: std::vector is guaranteed to contiguous rv = SSL_SetSRTPCiphers(ssl_fd, &srtp_ciphers_[0], srtp_ciphers_.size()); if (rv != SECSuccess) { MOZ_MTLOG(ML_ERROR, "Couldn't set SRTP cipher suite"); return false; } } for (size_t i = 0; i < PR_ARRAY_SIZE(EnabledCiphers); ++i) { MOZ_MTLOG(ML_INFO, LAYER_INFO << "Enabling: " << EnabledCiphers[i]); rv = SSL_CipherPrefSet(ssl_fd, EnabledCiphers[i], PR_TRUE); if (rv != SECSuccess) { MOZ_MTLOG(ML_ERROR, LAYER_INFO << "Unable to enable suite: " << EnabledCiphers[i]); return false; } } // Don't remove suites; TODO([email protected]) restore; bug 1052610 #if 0 for (size_t i = 0; i < PR_ARRAY_SIZE(DisabledCiphers); ++i) { MOZ_MTLOG(ML_INFO, LAYER_INFO << "Disabling: " << DisabledCiphers[i]); PRBool enabled = false; rv = SSL_CipherPrefGet(ssl_fd, DisabledCiphers[i], &enabled); if (rv != SECSuccess) { MOZ_MTLOG(ML_NOTICE, LAYER_INFO << "Unable to check if suite is enabled: " << DisabledCiphers[i]); return false; } if (enabled) { rv = SSL_CipherPrefSet(ssl_fd, DisabledCiphers[i], PR_FALSE); if (rv != SECSuccess) { MOZ_MTLOG(ML_NOTICE, LAYER_INFO << "Unable to disable suite: " << DisabledCiphers[i]); return false; } } } #endif return true; }
// TODO: make sure this is called from STS. Otherwise // we have thread safety issues bool TransportLayerDtls::Setup() { CheckThread(); SECStatus rv; if (!downward_) { MOZ_MTLOG(PR_LOG_ERROR, "DTLS layer with nothing below. This is useless"); return false; } nspr_io_adapter_ = new TransportLayerNSPRAdapter(downward_); if (!identity_) { MOZ_MTLOG(PR_LOG_ERROR, "Can't start DTLS without an identity"); return false; } if (verification_mode_ == VERIFY_UNSET) { MOZ_MTLOG(PR_LOG_ERROR, "Can't start DTLS without specifying a verification mode"); return false; } if (transport_layer_identity == PR_INVALID_IO_LAYER) { transport_layer_identity = PR_GetUniqueIdentity("nssstreamadapter"); } ScopedPRFileDesc pr_fd(PR_CreateIOLayerStub(transport_layer_identity, &TransportLayerMethods)); MOZ_ASSERT(pr_fd != nullptr); if (!pr_fd) return false; pr_fd->secret = reinterpret_cast<PRFilePrivate *>(nspr_io_adapter_.get()); ScopedPRFileDesc ssl_fd; if (mode_ == DGRAM) { ssl_fd = DTLS_ImportFD(nullptr, pr_fd); } else { ssl_fd = SSL_ImportFD(nullptr, pr_fd); } MOZ_ASSERT(ssl_fd != nullptr); // This should never happen if (!ssl_fd) { return false; } pr_fd.forget(); // ownership transfered to ssl_fd; if (role_ == CLIENT) { rv = SSL_GetClientAuthDataHook(ssl_fd, GetClientAuthDataHook, this); if (rv != SECSuccess) { MOZ_MTLOG(PR_LOG_ERROR, "Couldn't set identity"); return false; } } else { // Server side rv = SSL_ConfigSecureServer(ssl_fd, identity_->cert(), identity_->privkey(), kt_rsa); if (rv != SECSuccess) { MOZ_MTLOG(PR_LOG_ERROR, "Couldn't set identity"); return false; } // Insist on a certificate from the client rv = SSL_OptionSet(ssl_fd, SSL_REQUEST_CERTIFICATE, PR_TRUE); if (rv != SECSuccess) { MOZ_MTLOG(PR_LOG_ERROR, "Couldn't request certificate"); return false; } rv = SSL_OptionSet(ssl_fd, SSL_REQUIRE_CERTIFICATE, PR_TRUE); if (rv != SECSuccess) { MOZ_MTLOG(PR_LOG_ERROR, "Couldn't require certificate"); return false; } } // Require TLS 1.1. Perhaps some day in the future we will allow // TLS 1.0 for stream modes. SSLVersionRange version_range = { SSL_LIBRARY_VERSION_TLS_1_1, SSL_LIBRARY_VERSION_TLS_1_1 }; rv = SSL_VersionRangeSet(ssl_fd, &version_range); if (rv != SECSuccess) { MOZ_MTLOG(PR_LOG_ERROR, "Can't disable SSLv3"); return false; } rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_SESSION_TICKETS, PR_FALSE); if (rv != SECSuccess) { MOZ_MTLOG(PR_LOG_ERROR, "Couldn't disable session tickets"); return false; } rv = SSL_OptionSet(ssl_fd, SSL_NO_CACHE, PR_TRUE); if (rv != SECSuccess) { MOZ_MTLOG(PR_LOG_ERROR, "Couldn't disable session caching"); return false; } rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_DEFLATE, PR_FALSE); if (rv != SECSuccess) { MOZ_MTLOG(PR_LOG_ERROR, "Couldn't disable deflate"); return false; } rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_RENEGOTIATION, SSL_RENEGOTIATE_NEVER); if (rv != SECSuccess) { MOZ_MTLOG(PR_LOG_ERROR, "Couldn't disable renegotiation"); return false; } rv = SSL_OptionSet(ssl_fd, SSL_ENABLE_FALSE_START, PR_FALSE); if (rv != SECSuccess) { MOZ_MTLOG(PR_LOG_ERROR, "Couldn't disable false start"); return false; } rv = SSL_OptionSet(ssl_fd, SSL_NO_LOCKS, PR_TRUE); if (rv != SECSuccess) { MOZ_MTLOG(PR_LOG_ERROR, "Couldn't disable locks"); return false; } // Set the SRTP ciphers if (srtp_ciphers_.size()) { // Note: std::vector is guaranteed to contiguous rv = SSL_SetSRTPCiphers(ssl_fd, &srtp_ciphers_[0], srtp_ciphers_.size()); if (rv != SECSuccess) { MOZ_MTLOG(PR_LOG_ERROR, "Couldn't set SRTP cipher suite"); return false; } } // Certificate validation rv = SSL_AuthCertificateHook(ssl_fd, AuthCertificateHook, reinterpret_cast<void *>(this)); if (rv != SECSuccess) { MOZ_MTLOG(PR_LOG_ERROR, "Couldn't set certificate validation hook"); return false; } // Now start the handshake rv = SSL_ResetHandshake(ssl_fd, role_ == SERVER ? PR_TRUE : PR_FALSE); if (rv != SECSuccess) { MOZ_MTLOG(PR_LOG_ERROR, "Couldn't reset handshake"); return false; } ssl_fd_ = ssl_fd.forget(); // Finally, get ready to receive data downward_->SignalStateChange.connect(this, &TransportLayerDtls::StateChange); downward_->SignalPacketReceived.connect(this, &TransportLayerDtls::PacketReceived); if (downward_->state() == TS_OPEN) { Handshake(); } return true; }