Bug 1264578 - NSS support for http with TLS 1.3. r=keeler

--HG--
extra : rebase_source : 26b322f6d6f8e0160087c5214024dc9cccd328f9
This commit is contained in:
Dragana Damjanovic 2016-08-19 05:01:00 -04:00
parent 79e0168a9b
commit 3cf6ee23d9
6 changed files with 97 additions and 0 deletions

View File

@ -7,6 +7,7 @@ pref("security.tls.version.max", 3);
pref("security.tls.version.fallback-limit", 3);
pref("security.tls.insecure_fallback_hosts", "");
pref("security.tls.unrestricted_rc4_fallback", false);
pref("security.tls.enable_0rtt_data", false);
pref("security.ssl.treat_unsafe_negotiation_as_broken", false);
pref("security.ssl.require_safe_negotiation", false);

View File

@ -44,6 +44,22 @@ interface nsISSLSocketControl : nsISupports {
*/
readonly attribute ACString negotiatedNPN;
/* For 0RTT we need to know the alpn protocol selected for the last tls
* session. This function will return a value if applicable or an error
* NS_ERROR_NOT_AVAILABLE.
*/
ACString getAlpnEarlySelection();
/* If 0RTT handshake was applied and some data has been sent, as soon as
* the handshake finishes this attribute will be set to appropriate value.
*/
readonly attribute bool earlyDataAccepted;
/* When 0RTT is performed, PR_Write will not drive the handshake forward.
* It must be forced by calling this function.
*/
void driveHandshake();
/* Determine if a potential SSL connection to hostname:port with
* a desired NPN negotiated protocol of npnProtocol can use the socket
* associated with this object instead of making a new one.

View File

@ -838,6 +838,7 @@ PreliminaryHandshakeDone(PRFileDesc* fd)
SSLChannelInfo channelInfo;
if (SSL_GetChannelInfo(fd, &channelInfo, sizeof(channelInfo)) == SECSuccess) {
infoObject->SetSSLVersionUsed(channelInfo.protocolVersion);
infoObject->SetEarlyDataAccepted(channelInfo.earlyDataAccepted);
SSLCipherSuiteInfo cipherInfo;
if (SSL_GetCipherSuiteInfo(channelInfo.cipherSuite, &cipherInfo,

View File

@ -1369,6 +1369,7 @@ static const bool REQUIRE_SAFE_NEGOTIATION_DEFAULT = false;
static const bool FALSE_START_ENABLED_DEFAULT = true;
static const bool NPN_ENABLED_DEFAULT = true;
static const bool ALPN_ENABLED_DEFAULT = false;
static const bool ENABLED_0RTT_DATA_DEFAULT = false;
static void
ConfigureTLSSessionIdentifiers()
@ -1776,6 +1777,10 @@ nsNSSComponent::InitializeNSS()
Preferences::GetBool("security.ssl.enable_alpn",
ALPN_ENABLED_DEFAULT));
SSL_OptionSetDefault(SSL_ENABLE_0RTT_DATA,
Preferences::GetBool("security.tls.enable_0rtt_data",
ENABLED_0RTT_DATA_DEFAULT));
if (NS_FAILED(InitializeCipherSuite())) {
MOZ_LOG(gPIPNSSLog, LogLevel::Error, ("Unable to initialize cipher suite settings\n"));
return NS_ERROR_FAILURE;
@ -1961,6 +1966,10 @@ nsNSSComponent::Observe(nsISupports* aSubject, const char* aTopic,
SSL_OptionSetDefault(SSL_ENABLE_ALPN,
Preferences::GetBool("security.ssl.enable_alpn",
ALPN_ENABLED_DEFAULT));
} else if (prefName.EqualsLiteral("security.tls.enable_0rtt_data")) {
SSL_OptionSetDefault(SSL_ENABLE_0RTT_DATA,
Preferences::GetBool("security.tls.enable_0rtt_data",
ENABLED_0RTT_DATA_DEFAULT));
} else if (prefName.Equals("security.ssl.disable_session_identifiers")) {
ConfigureTLSSessionIdentifiers();
} else if (prefName.EqualsLiteral("security.OCSP.enabled") ||

View File

@ -58,6 +58,8 @@ using namespace mozilla::psm;
namespace {
#define MAX_ALPN_LENGTH 255
void
getSiteKey(const nsACString& hostName, uint16_t port,
/*out*/ nsCSubstring& key)
@ -87,6 +89,7 @@ nsNSSSocketInfo::nsNSSSocketInfo(SharedSSLState& aState, uint32_t providerFlags)
mRememberClientAuthCertificate(false),
mPreliminaryHandshakeDone(false),
mNPNCompleted(false),
mEarlyDataAccepted(false),
mFalseStartCallbackCalled(false),
mFalseStarted(false),
mIsFullHandshake(false),
@ -307,6 +310,71 @@ nsNSSSocketInfo::GetNegotiatedNPN(nsACString& aNegotiatedNPN)
return NS_OK;
}
NS_IMETHODIMP
nsNSSSocketInfo::GetAlpnEarlySelection(nsACString& aAlpnSelected)
{
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown() || isPK11LoggedOut()) {
return NS_ERROR_NOT_AVAILABLE;
}
SSLNextProtoState alpnState;
unsigned char chosenAlpn[MAX_ALPN_LENGTH];
unsigned int chosenAlpnLen;
SECStatus rv = SSL_GetNextProto(mFd, &alpnState, chosenAlpn, &chosenAlpnLen,
AssertedCast<unsigned int>(ArrayLength(chosenAlpn)));
if (rv != SECSuccess || alpnState != SSL_NEXT_PROTO_EARLY_VALUE ||
chosenAlpnLen == 0) {
return NS_ERROR_NOT_AVAILABLE;
}
aAlpnSelected.Assign(BitwiseCast<char*, unsigned char*>(chosenAlpn),
chosenAlpnLen);
return NS_OK;
}
NS_IMETHODIMP
nsNSSSocketInfo::GetEarlyDataAccepted(bool* aAccepted)
{
*aAccepted = mEarlyDataAccepted;
return NS_OK;
}
void
nsNSSSocketInfo::SetEarlyDataAccepted(bool aAccepted)
{
mEarlyDataAccepted = aAccepted;
}
NS_IMETHODIMP
nsNSSSocketInfo::DriveHandshake()
{
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown() || isPK11LoggedOut()) {
return NS_ERROR_NOT_AVAILABLE;
}
if (!mFd) {
return NS_ERROR_FAILURE;
}
PRErrorCode errorCode = GetErrorCode();
if (errorCode) {
return GetXPCOMFromNSSError(errorCode);
}
SECStatus rv = SSL_ForceHandshake(mFd);
if (rv != SECSuccess) {
errorCode = PR_GetError();
if (errorCode == PR_WOULD_BLOCK_ERROR) {
return NS_BASE_STREAM_WOULD_BLOCK;
}
SetCanceled(errorCode, PlainErrorMessage);
return GetXPCOMFromNSSError(errorCode);
}
return NS_OK;
}
NS_IMETHODIMP
nsNSSSocketInfo::IsAcceptableForHost(const nsACString& hostname, bool* _retval)
{

View File

@ -53,6 +53,7 @@ public:
const nsNSSShutDownPreventionLock& proofOfLock);
void SetNegotiatedNPN(const char* value, uint32_t length);
void SetEarlyDataAccepted(bool aAccepted);
void SetHandshakeCompleted();
void NoteTimeUntilReady();
@ -132,6 +133,7 @@ private:
nsCString mNegotiatedNPN;
bool mNPNCompleted;
bool mEarlyDataAccepted;
bool mFalseStartCallbackCalled;
bool mFalseStarted;
bool mIsFullHandshake;