Commit a3d3f697 authored by Martin Thomson's avatar Martin Thomson

Bug 1325035 - Streamline session ticket key wrapping, r=ttaubert

Differential Revision: https://nss-review.dev.mozaws.net/D127

--HG--
extra : rebase_source : 8efefb1f37dd327397d259c342e60223bd9bed9b
extra : amend_source : bdae9423ae41ed762c18718715425646a5ad0ec2
extra : histedit_source : 2d211aa721bc82eae4a1fb1895e1b2529899c3ae%2C640dfe56df26288f8ba8608dd24d277396d839bb
parent b41c93d1
......@@ -62,10 +62,7 @@ PRBool SSLInt_ExtensionNegotiated(PRFileDesc *fd, PRUint16 ext) {
return (PRBool)(ss && ssl3_ExtensionNegotiated(ss, ext));
}
void SSLInt_ClearSessionTicketKey() {
ssl3_SessionTicketShutdown(NULL, NULL);
NSS_UnregisterShutdown(ssl3_SessionTicketShutdown, NULL);
}
void SSLInt_ClearSessionTicketKey() { ssl_ResetSessionTicketKeys(); }
SECStatus SSLInt_SetMTU(PRFileDesc *fd, PRUint16 mtu) {
sslSocket *ss = ssl_FindSocket(fd);
......@@ -209,7 +206,7 @@ PRBool SSLInt_HasCertWithAuthType(PRFileDesc *fd, SSLAuthType authType) {
return PR_FALSE;
}
return (PRBool)(!!ssl_FindServerCertByAuthType(ss, authType));
return (PRBool)(!!ssl_FindServerCert(ss, authType, NULL));
}
PRBool SSLInt_SendAlert(PRFileDesc *fd, uint8_t level, uint8_t type) {
......
......@@ -62,10 +62,22 @@ static const uint8_t kSctValue[] = {0x01, 0x23, 0x45, 0x67, 0x89};
static const SECItem kSctItem = {siBuffer, const_cast<uint8_t*>(kSctValue),
sizeof(kSctValue)};
static const DataBuffer kSctBuffer(kSctValue, sizeof(kSctValue));
static const SSLExtraServerCertData kExtraSctData = {ssl_auth_null, nullptr,
nullptr, &kSctItem};
// Test timestamps extraction during a successful handshake.
TEST_P(TlsConnectGeneric, SignedCertificateTimestampsHandshake) {
TEST_P(TlsConnectGenericPre13, SignedCertificateTimestampsLegacy) {
EnsureTlsSetup();
// We have to use the legacy API consistently here for configuring certs.
// Also, this doesn't work in TLS 1.3 because this only configures the SCT for
// RSA decrypt and PKCS#1 signing, not PSS.
ScopedCERTCertificate cert;
ScopedSECKEYPrivateKey priv;
ASSERT_TRUE(TlsAgent::LoadCertificate(TlsAgent::kServerRsa, &cert, &priv));
EXPECT_EQ(SECSuccess, SSL_ConfigSecureServerWithCertChain(
server_->ssl_fd(), cert.get(), nullptr, priv.get(),
ssl_kea_rsa));
EXPECT_EQ(SECSuccess, SSL_SetSignedCertTimestamps(server_->ssl_fd(),
&kSctItem, ssl_kea_rsa));
EXPECT_EQ(SECSuccess,
......@@ -78,13 +90,10 @@ TEST_P(TlsConnectGeneric, SignedCertificateTimestampsHandshake) {
timestamps_extractor.assertTimestamps(kSctBuffer);
}
TEST_P(TlsConnectGeneric, SignedCertificateTimestampsConfig) {
static const SSLExtraServerCertData kExtraData = {ssl_auth_rsa_sign, nullptr,
nullptr, &kSctItem};
TEST_P(TlsConnectGeneric, SignedCertificateTimestampsSuccess) {
EnsureTlsSetup();
EXPECT_TRUE(
server_->ConfigServerCert(TlsAgent::kServerRsa, true, &kExtraData));
server_->ConfigServerCert(TlsAgent::kServerRsa, true, &kExtraSctData));
EXPECT_EQ(SECSuccess,
SSL_OptionSet(client_->ssl_fd(), SSL_ENABLE_SIGNED_CERT_TIMESTAMPS,
PR_TRUE));
......@@ -99,8 +108,8 @@ TEST_P(TlsConnectGeneric, SignedCertificateTimestampsConfig) {
// when the client / the server / both have not enabled the feature.
TEST_P(TlsConnectGeneric, SignedCertificateTimestampsInactiveClient) {
EnsureTlsSetup();
EXPECT_EQ(SECSuccess, SSL_SetSignedCertTimestamps(server_->ssl_fd(),
&kSctItem, ssl_kea_rsa));
EXPECT_TRUE(
server_->ConfigServerCert(TlsAgent::kServerRsa, true, &kExtraSctData));
SignedCertificateTimestampsExtractor timestamps_extractor(client_);
Connect();
......@@ -141,8 +150,8 @@ static const SECItem kOcspItems[] = {
{siBuffer, const_cast<uint8_t*>(kOcspValue2), sizeof(kOcspValue2)}};
static const SECItemArray kOcspResponses = {const_cast<SECItem*>(kOcspItems),
PR_ARRAY_SIZE(kOcspItems)};
const static SSLExtraServerCertData kOcspExtraData = {
ssl_auth_rsa_sign, nullptr, &kOcspResponses, nullptr};
const static SSLExtraServerCertData kOcspExtraData = {ssl_auth_null, nullptr,
&kOcspResponses, nullptr};
TEST_P(TlsConnectGeneric, NoOcsp) {
EnsureTlsSetup();
......
......@@ -128,16 +128,22 @@ class TlsCipherSuiteTestBase : public TlsConnectTestBase {
Connect();
SendReceive();
// Check that we used the right cipher suite.
// Check that we used the right cipher suite, auth type and kea type.
uint16_t actual;
EXPECT_TRUE(client_->cipher_suite(&actual) && actual == cipher_suite_);
EXPECT_TRUE(server_->cipher_suite(&actual) && actual == cipher_suite_);
EXPECT_TRUE(client_->cipher_suite(&actual));
EXPECT_EQ(cipher_suite_, actual);
EXPECT_TRUE(server_->cipher_suite(&actual));
EXPECT_EQ(cipher_suite_, actual);
SSLAuthType auth;
EXPECT_TRUE(client_->auth_type(&auth) && auth == auth_type_);
EXPECT_TRUE(server_->auth_type(&auth) && auth == auth_type_);
EXPECT_TRUE(client_->auth_type(&auth));
EXPECT_EQ(auth_type_, auth);
EXPECT_TRUE(server_->auth_type(&auth));
EXPECT_EQ(auth_type_, auth);
SSLKEAType kea;
EXPECT_TRUE(client_->kea_type(&kea) && kea == kea_type_);
EXPECT_TRUE(server_->kea_type(&kea) && kea == kea_type_);
EXPECT_TRUE(client_->kea_type(&kea));
EXPECT_EQ(kea_type_, kea);
EXPECT_TRUE(server_->kea_type(&kea));
EXPECT_EQ(kea_type_, kea);
}
// Get the expected limit on the number of records that can be sent for the
......
......@@ -102,23 +102,35 @@ void TlsAgent::SetState(State state) {
state_ = state;
}
/*static*/ bool TlsAgent::LoadCertificate(const std::string& name,
ScopedCERTCertificate* cert,
ScopedSECKEYPrivateKey* priv) {
cert->reset(PK11_FindCertFromNickname(name.c_str(), nullptr));
EXPECT_NE(nullptr, cert->get());
if (!cert->get()) return false;
priv->reset(PK11_FindKeyByAnyCert(cert->get(), nullptr));
EXPECT_NE(nullptr, priv->get());
if (!priv->get()) return false;
return true;
}
bool TlsAgent::ConfigServerCert(const std::string& name, bool updateKeyBits,
const SSLExtraServerCertData* serverCertData) {
ScopedCERTCertificate cert(PK11_FindCertFromNickname(name.c_str(), nullptr));
EXPECT_NE(nullptr, cert.get());
if (!cert.get()) return false;
ScopedCERTCertificate cert;
ScopedSECKEYPrivateKey priv;
if (!TlsAgent::LoadCertificate(name, &cert, &priv)) {
return false;
}
ScopedSECKEYPublicKey pub(CERT_ExtractPublicKey(cert.get()));
EXPECT_NE(nullptr, pub.get());
if (!pub.get()) return false;
if (updateKeyBits) {
ScopedSECKEYPublicKey pub(CERT_ExtractPublicKey(cert.get()));
EXPECT_NE(nullptr, pub.get());
if (!pub.get()) return false;
server_key_bits_ = SECKEY_PublicKeyStrengthInBits(pub.get());
}
ScopedSECKEYPrivateKey priv(PK11_FindKeyByAnyCert(cert.get(), nullptr));
EXPECT_NE(nullptr, priv.get());
if (!priv.get()) return false;
SECStatus rv =
SSL_ConfigSecureServer(ssl_fd_, nullptr, nullptr, ssl_kea_null);
EXPECT_EQ(SECFailure, rv);
......@@ -181,30 +193,23 @@ void TlsAgent::SetupClientAuth() {
reinterpret_cast<void*>(this)));
}
bool TlsAgent::GetClientAuthCredentials(CERTCertificate** cert,
SECKEYPrivateKey** priv) const {
*cert = PK11_FindCertFromNickname(name_.c_str(), nullptr);
EXPECT_NE(nullptr, *cert);
if (!*cert) return false;
*priv = PK11_FindKeyByAnyCert(*cert, nullptr);
EXPECT_NE(nullptr, *priv);
if (!*priv) return false; // Leak cert.
return true;
}
SECStatus TlsAgent::GetClientAuthDataHook(void* self, PRFileDesc* fd,
CERTDistNames* caNames,
CERTCertificate** cert,
SECKEYPrivateKey** privKey) {
CERTCertificate** clientCert,
SECKEYPrivateKey** clientKey) {
TlsAgent* agent = reinterpret_cast<TlsAgent*>(self);
ScopedCERTCertificate peerCert(SSL_PeerCertificate(agent->ssl_fd()));
EXPECT_TRUE(peerCert) << "Client should be able to see the server cert";
if (agent->GetClientAuthCredentials(cert, privKey)) {
return SECSuccess;
ScopedCERTCertificate cert;
ScopedSECKEYPrivateKey priv;
if (!TlsAgent::LoadCertificate(agent->name(), &cert, &priv)) {
return SECFailure;
}
return SECFailure;
*clientCert = cert.release();
*clientKey = priv.release();
return SECSuccess;
}
bool TlsAgent::GetPeerChainLength(size_t* count) {
......
......@@ -18,6 +18,7 @@
#define GTEST_HAS_RTTI 0
#include "gtest/gtest.h"
#include "scoped_ptrs.h"
extern bool g_ssl_gtest_verbose;
......@@ -115,6 +116,9 @@ class TlsAgent : public PollTarget {
void PrepareForRenegotiate();
// Prepares for renegotiation, then actually triggers it.
void StartRenegotiate();
static bool LoadCertificate(const std::string& name,
ScopedCERTCertificate* cert,
ScopedSECKEYPrivateKey* priv);
bool ConfigServerCert(const std::string& name, bool updateKeyBits = false,
const SSLExtraServerCertData* serverCertData = nullptr);
bool ConfigServerCertWithChain(const std::string& name);
......@@ -122,8 +126,6 @@ class TlsAgent : public PollTarget {
void SetupClientAuth();
void RequestClientAuth(bool requireAuth);
bool GetClientAuthCredentials(CERTCertificate** cert,
SECKEYPrivateKey** priv) const;
void ConfigureSessionCache(SessionResumptionMode mode);
void SetSessionTicketsEnabled(bool en);
......
......@@ -13,6 +13,7 @@ extern "C" {
#include "databuffer.h"
#include "gtest_utils.h"
#include "scoped_ptrs.h"
#include "sslproto.h"
extern std::string g_working_dir_path;
......@@ -345,6 +346,13 @@ void TlsConnectTestBase::CheckKeys(SSLKEAType kea_type,
scheme = ssl_sig_none;
break;
case ssl_auth_rsa_sign:
if (version_ >= SSL_LIBRARY_VERSION_TLS_1_2) {
scheme = ssl_sig_rsa_pss_sha256;
} else {
scheme = ssl_sig_rsa_pkcs1_sha256;
}
break;
case ssl_auth_rsa_pss:
scheme = ssl_sig_rsa_pss_sha256;
break;
case ssl_auth_ecdsa:
......@@ -390,6 +398,7 @@ void TlsConnectTestBase::ConnectExpectFailOneSide(TlsAgent::Role failing_side) {
}
void TlsConnectTestBase::ConfigureVersion(uint16_t version) {
version_ = version;
client_->SetVersionRange(version, version);
server_->SetVersionRange(version, version);
}
......@@ -440,10 +449,16 @@ void TlsConnectTestBase::ConfigureSessionCache(SessionResumptionMode client,
client_->ConfigureSessionCache(client);
server_->ConfigureSessionCache(server);
if ((server & RESUME_TICKET) != 0) {
// This is an abomination. NSS encrypts session tickets with the server's
// RSA public key. That means we need the server to have an RSA certificate
// even if it won't be used for the connection.
server_->ConfigServerCert(TlsAgent::kServerRsaDecrypt);
ScopedCERTCertificate cert;
ScopedSECKEYPrivateKey privKey;
ASSERT_TRUE(TlsAgent::LoadCertificate(TlsAgent::kServerRsaDecrypt, &cert,
&privKey));
ScopedSECKEYPublicKey pubKey(CERT_ExtractPublicKey(cert.get()));
ASSERT_TRUE(pubKey);
EXPECT_EQ(SECSuccess,
SSL_SetSessionTicketKeyPair(pubKey.get(), privKey.get()));
}
}
......
......@@ -221,3 +221,9 @@ SSL_SignatureSchemePrefGet;
;+ local:
;+*;
;+};
;+NSS_3.30 { # NSS 3.30 release
;+ global:
SSL_SetSessionTicketKeyPair;
;+ local:
;+*;
;+};
......@@ -913,6 +913,19 @@ SSL_ConfigSecureServerWithCertChain(PRFileDesc *fd, CERTCertificate *cert,
const CERTCertificateList *certChainOpt,
SECKEYPrivateKey *key, SSLKEAType kea);
/*
** SSL_SetSessionTicketKeyPair configures an asymmetric key pair for use in
** wrapping session ticket keys, used by the server. This function currently
** only accepts an RSA public/private key pair.
**
** Prior to the existence of this function, NSS used an RSA private key
** associated with a configured certificate to perform session ticket
** encryption. If this function isn't used, the keys provided with a configured
** RSA certificate are used for wrapping session ticket keys.
*/
SSL_IMPORT SECStatus
SSL_SetSessionTicketKeyPair(SECKEYPublicKey *pubKey, SECKEYPrivateKey *privKey);
/*
** Configure a secure server's session-id cache. Define the maximum number
** of entries in the cache, the longevity of the entires, and the directory
......
This diff is collapsed.
......@@ -440,23 +440,19 @@ ssl_GetECGroupForServerSocket(sslSocket *ss)
return NULL;
}
if (cert->certType.authType == ssl_auth_rsa_sign) {
if (SSL_CERT_IS(cert, ssl_auth_rsa_sign) ||
SSL_CERT_IS(cert, ssl_auth_rsa_pss)) {
certKeySize = SECKEY_PublicKeyStrengthInBits(cert->serverKeyPair->pubKey);
certKeySize =
SSL_RSASTRENGTH_TO_ECSTRENGTH(certKeySize);
} else if (cert->certType.authType == ssl_auth_ecdsa ||
cert->certType.authType == ssl_auth_ecdh_rsa ||
cert->certType.authType == ssl_auth_ecdh_ecdsa) {
const sslNamedGroupDef *groupDef = cert->certType.namedCurve;
certKeySize = SSL_RSASTRENGTH_TO_ECSTRENGTH(certKeySize);
} else if (SSL_CERT_IS_EC(cert)) {
/* We won't select a certificate unless the named curve has been
* negotiated (or supported_curves was absent), double check that. */
PORT_Assert(groupDef->keaType == ssl_kea_ecdh);
PORT_Assert(ssl_NamedGroupEnabled(ss, groupDef));
if (!ssl_NamedGroupEnabled(ss, groupDef)) {
PORT_Assert(cert->namedCurve->keaType == ssl_kea_ecdh);
PORT_Assert(ssl_NamedGroupEnabled(ss, cert->namedCurve));
if (!ssl_NamedGroupEnabled(ss, cert->namedCurve)) {
return NULL;
}
certKeySize = groupDef->bits;
certKeySize = cert->namedCurve->bits;
} else {
PORT_Assert(0);
return NULL;
......
......@@ -16,12 +16,6 @@
#include "ssl3exthandle.h"
#include "tls13exthandle.h" /* For tls13_ServerSendStatusRequestXtn. */
static unsigned char key_name[SESS_TICKET_KEY_NAME_LEN];
static PK11SymKey *session_ticket_enc_key = NULL;
static PK11SymKey *session_ticket_mac_key = NULL;
static PRCallOnceType generate_session_keys_once;
static SECStatus ssl3_ParseEncryptedSessionTicket(sslSocket *ss,
SECItem *data, EncryptedSessionTicket *enc_session_ticket);
static SECStatus ssl3_AppendToItem(SECItem *item, const unsigned char *buf,
......@@ -29,8 +23,6 @@ static SECStatus ssl3_AppendToItem(SECItem *item, const unsigned char *buf,
static SECStatus ssl3_ConsumeFromItem(SECItem *item, unsigned char **buf, PRUint32 bytes);
static SECStatus ssl3_AppendNumberToItem(SECItem *item, PRUint32 num,
PRInt32 lenSize);
static SECStatus ssl3_GetSessionTicketKeys(sslSocket *ss,
PK11SymKey **aes_key, PK11SymKey **mac_key);
static SECStatus ssl3_ConsumeFromItem(SECItem *item, unsigned char **buf, PRUint32 bytes);
/*
......@@ -76,83 +68,6 @@ ssl3_AppendNumberToItem(SECItem *item, PRUint32 num, PRInt32 lenSize)
return rv;
}
SECStatus
ssl3_SessionTicketShutdown(void *appData, void *nssData)
{
if (session_ticket_enc_key) {
PK11_FreeSymKey(session_ticket_enc_key);
session_ticket_enc_key = NULL;
}
if (session_ticket_mac_key) {
PK11_FreeSymKey(session_ticket_mac_key);
session_ticket_mac_key = NULL;
}
PORT_Memset(&generate_session_keys_once, 0,
sizeof(generate_session_keys_once));
return SECSuccess;
}
static PRStatus
ssl3_GenerateSessionTicketKeys(void *data)
{
SECStatus rv;
sslSocket *ss = (sslSocket *)data;
sslServerCertType certType = { ssl_auth_rsa_decrypt, NULL };
const sslServerCert *sc;
SECKEYPrivateKey *svrPrivKey;
SECKEYPublicKey *svrPubKey;
sc = ssl_FindServerCert(ss, &certType);
if (!sc || !sc->serverKeyPair) {
SSL_DBG(("%d: SSL[%d]: No ssl_auth_rsa_decrypt cert and key pair",
SSL_GETPID(), ss->fd));
goto loser;
}
svrPrivKey = sc->serverKeyPair->privKey;
svrPubKey = sc->serverKeyPair->pubKey;
if (svrPrivKey == NULL || svrPubKey == NULL) {
SSL_DBG(("%d: SSL[%d]: Pub or priv key(s) is NULL.",
SSL_GETPID(), ss->fd));
goto loser;
}
/* Get a copy of the session keys from shared memory. */
PORT_Memcpy(key_name, SESS_TICKET_KEY_NAME_PREFIX,
sizeof(SESS_TICKET_KEY_NAME_PREFIX));
if (!ssl_GetSessionTicketKeys(svrPrivKey, svrPubKey, ss->pkcs11PinArg,
&key_name[SESS_TICKET_KEY_NAME_PREFIX_LEN],
&session_ticket_enc_key, &session_ticket_mac_key))
return PR_FAILURE;
rv = NSS_RegisterShutdown(ssl3_SessionTicketShutdown, NULL);
if (rv != SECSuccess)
goto loser;
return PR_SUCCESS;
loser:
ssl3_SessionTicketShutdown(NULL, NULL);
return PR_FAILURE;
}
static SECStatus
ssl3_GetSessionTicketKeys(sslSocket *ss, PK11SymKey **aes_key,
PK11SymKey **mac_key)
{
if (PR_CallOnceWithArg(&generate_session_keys_once,
ssl3_GenerateSessionTicketKeys, ss) !=
PR_SUCCESS)
return SECFailure;
if (session_ticket_enc_key == NULL ||
session_ticket_mac_key == NULL)
return SECFailure;
*aes_key = session_ticket_enc_key;
*mac_key = session_ticket_mac_key;
return SECSuccess;
}
/* Format an SNI extension, using the name from the socket's URL,
* unless that name is a dotted decimal string.
* Used by client and server.
......@@ -960,6 +875,7 @@ ssl3_EncodeSessionTicket(sslSocket *ss,
PRUint32 cert_length = 0;
PRUint8 length_buf[4];
PRUint32 now;
unsigned char key_name[SESS_TICKET_KEY_NAME_LEN];
PK11SymKey *aes_key = NULL;
PK11SymKey *mac_key = NULL;
CK_MECHANISM_TYPE cipherMech = CKM_AES_CBC;
......@@ -975,7 +891,6 @@ ssl3_EncodeSessionTicket(sslSocket *ss,
CK_MECHANISM_TYPE msWrapMech = 0; /* dummy default value,
* must be >= 0 */
ssl3CipherSpec *spec;
const sslServerCertType *certType;
SECItem alpnSelection = { siBuffer, NULL, 0 };
SSL_TRC(3, ("%d: SSL3[%d]: send session_ticket handshake",
......@@ -995,7 +910,7 @@ ssl3_EncodeSessionTicket(sslSocket *ss,
if (rv != SECSuccess)
goto loser;
rv = ssl3_GetSessionTicketKeys(ss, &aes_key, &mac_key);
rv = ssl_GetSessionTicketKeys(ss, key_name, &aes_key, &mac_key);
if (rv != SECSuccess)
goto loser;
......@@ -1014,8 +929,7 @@ ssl3_EncodeSessionTicket(sslSocket *ss,
sslSessionID sid;
PORT_Memset(&sid, 0, sizeof(sslSessionID));
rv = ssl3_CacheWrappedMasterSecret(ss, &sid, spec,
ss->ssl3.hs.kea_def->authKeyType);
rv = ssl3_CacheWrappedMasterSecret(ss, &sid, spec);
if (rv == SECSuccess) {
if (sid.u.ssl3.keys.wrapped_master_secret_len > sizeof(wrapped_ms))
goto loser;
......@@ -1108,22 +1022,15 @@ ssl3_EncodeSessionTicket(sslSocket *ss,
goto loser;
/* certificate type */
certType = &ss->sec.serverCert->certType;
PORT_Assert(certType->authType == ss->sec.authType);
switch (ss->sec.authType) {
case ssl_auth_ecdsa:
case ssl_auth_ecdh_rsa:
case ssl_auth_ecdh_ecdsa:
PORT_Assert(certType->namedCurve);
PORT_Assert(certType->namedCurve->keaType == ssl_kea_ecdh);
/* EC curves only use the second of the two bytes. */
PORT_Assert(certType->namedCurve->name < 256);
rv = ssl3_AppendNumberToItem(&plaintext,
certType->namedCurve->name, 1);
break;
default:
rv = ssl3_AppendNumberToItem(&plaintext, 0, 1);
break;
PORT_Assert(SSL_CERT_IS(ss->sec.serverCert, ss->sec.authType));
if (SSL_CERT_IS_EC(ss->sec.serverCert)) {
const sslServerCert *cert = ss->sec.serverCert;
PORT_Assert(cert->namedCurve);
/* EC curves only use the second of the two bytes. */
PORT_Assert(cert->namedCurve->name < 256);
rv = ssl3_AppendNumberToItem(&plaintext, cert->namedCurve->name, 1);
} else {
rv = ssl3_AppendNumberToItem(&plaintext, 0, 1);
}
if (rv != SECSuccess)
goto loser;
......@@ -1350,6 +1257,7 @@ ssl3_ProcessSessionTicketCommon(sslSocket *ss, SECItem *data)
EncryptedSessionTicket enc_session_ticket;
unsigned char computed_mac[TLS_EX_SESS_TICKET_MAC_LENGTH];
unsigned int computed_mac_length;
unsigned char key_name[SESS_TICKET_KEY_NAME_LEN];
PK11SymKey *aes_key = NULL;
PK11SymKey *mac_key = NULL;
PK11Context *hmac_ctx;
......@@ -1387,7 +1295,7 @@ ssl3_ProcessSessionTicketCommon(sslSocket *ss, SECItem *data)
}
/* Get session ticket keys. */
rv = ssl3_GetSessionTicketKeys(ss, &aes_key, &mac_key);
rv = ssl_GetSessionTicketKeys(ss, key_name, &aes_key, &mac_key);
if (rv != SECSuccess) {
SSL_DBG(("%d: SSL[%d]: Unable to get/generate session ticket keys.",
SSL_GETPID(), ss->fd));
......@@ -1538,24 +1446,19 @@ ssl3_ProcessSessionTicketCommon(sslSocket *ss, SECItem *data)
goto no_ticket;
parsed_session_ticket->keaKeyBits = temp;
/* Read certificate slot */
parsed_session_ticket->certType.authType = parsed_session_ticket->authType;
/* Read the optional named curve. */
rv = ssl3_ExtConsumeHandshakeNumber(ss, &temp, 1, &buffer, &buffer_len);
if (rv != SECSuccess)
goto no_ticket;
switch (parsed_session_ticket->authType) {
case ssl_auth_ecdsa:
case ssl_auth_ecdh_rsa:
case ssl_auth_ecdh_ecdsa: {
const sslNamedGroupDef *group =
ssl_LookupNamedGroup((SSLNamedGroup)temp);
if (!group || group->keaType != ssl_kea_ecdh) {
goto no_ticket;
}
parsed_session_ticket->certType.namedCurve = group;
} break;
default:
break;
if (parsed_session_ticket->authType == ssl_auth_ecdsa ||
parsed_session_ticket->authType == ssl_auth_ecdh_rsa ||
parsed_session_ticket->authType == ssl_auth_ecdh_ecdsa) {
const sslNamedGroupDef *group =
ssl_LookupNamedGroup((SSLNamedGroup)temp);
if (!group || group->keaType != ssl_kea_ecdh) {
goto no_ticket;
}
parsed_session_ticket->namedCurve = group;
}
/* Read wrapped master_secret. */
......@@ -1682,8 +1585,7 @@ ssl3_ProcessSessionTicketCommon(sslSocket *ss, SECItem *data)
sid->authKeyBits = parsed_session_ticket->authKeyBits;
sid->keaType = parsed_session_ticket->keaType;
sid->keaKeyBits = parsed_session_ticket->keaKeyBits;
memcpy(&sid->certType, &parsed_session_ticket->certType,
sizeof(sslServerCertType));
sid->namedCurve = parsed_session_ticket->namedCurve;
if (SECITEM_CopyItem(NULL, &sid->u.ssl3.locked.sessionTicket.ticket,
&extension_data) != SECSuccess)
......
This diff is collapsed.
......@@ -13,26 +13,21 @@
#include "secitem.h"
#include "keyhi.h"
/* The following struct identifies a single slot into which a certificate can be
** loaded. The authType field determines the basic slot, then additional
** parameters further narrow the slot.
**
** An EC key (ssl_auth_ecdsa or ssl_auth_ecdh_*) is assigned to a slot based on
** the named curve of the key.
*/
typedef struct sslServerCertTypeStr {
SSLAuthType authType;
/* This type is a bitvector that is indexed by SSLAuthType values. Note that
* the bit for ssl_auth_null(0) - the least significant bit - isn't used. */
typedef PRUint16 sslAuthTypeMask;
PR_STATIC_ASSERT(sizeof(sslAuthTypeMask) * 8 >= ssl_auth_size);
typedef struct sslServerCertStr {
PRCList link; /* The linked list link */
/* The auth types that this certificate provides. */
sslAuthTypeMask authTypes;
/* For ssl_auth_ecdsa and ssl_auth_ecdh_*. This is only the named curve
* of the end-entity certificate key. The keys in other certificates in
* the chain aren't directly relevant to the operation of TLS (though it
* might make certificate validation difficult, libssl doesn't care). */
const sslNamedGroupDef *namedCurve;
} sslServerCertType;
typedef struct sslServerCertStr {
PRCList link; /* The linked list link */
sslServerCertType certType; /* The certificate slot this occupies */
/* Configuration state for server sockets */
CERTCertificate *serverCert;
......@@ -48,12 +43,18 @@ typedef struct sslServerCertStr {
SECItem signedCertTimestamps;
} sslServerCert;
extern sslServerCert *ssl_NewServerCert(const sslServerCertType *slot);
#define SSL_CERT_IS(c, t) ((c)->authTypes & (1 << (t)))
#define SSL_CERT_IS_ONLY(c, t) ((c)->authTypes == (1 << (t)))
#define SSL_CERT_IS_EC(c) \
((c)->authTypes & ((1 << ssl_auth_ecdsa) | \
(1 << ssl_auth_ecdh_rsa) | \
(1 << ssl_auth_ecdh_ecdsa)))
extern sslServerCert *ssl_NewServerCert();
extern sslServerCert *ssl_CopyServerCert(const sslServerCert *oc);
extern sslServerCert *ssl_FindServerCert(const sslSocket *ss,
const sslServerCertType *slot);
extern sslServerCert *ssl_FindServerCertByAuthType(const sslSocket *ss,
SSLAuthType authType);
extern const sslServerCert *ssl_FindServerCert(
const sslSocket *ss, SSLAuthType authType,
const sslNamedGroupDef *namedCurve);
extern void ssl_FreeServerCert(sslServerCert *sc);
#endif /* __sslcert_h_ */
......@@ -125,7 +125,8 @@ typedef enum { SSLAppOpRead = 0,
#define SSL3_MASTER_SECRET_LENGTH 48
/* number of wrap mechanisms potentially used to wrap master secrets. */
#define SSL_NUM_WRAP_MECHS 16
#define SSL_NUM_WRAP_MECHS 15
#define SSL_NUM_WRAP_KEYS 6
/* This makes the cert cache entry exactly 4k. */
#define SSL_MAX_CACHED_CERT_LEN 4060
......@@ -530,10 +531,10 @@ struct sslSessionIDStr {
*/
CERTCertificate *peerCert;
SECItemArray peerCertStatus; /* client only */
const char *peerID; /* client only */
const char *urlSvrName; /* client only */
sslServerCertType certType;
SECItemArray peerCertStatus; /* client only */
const char *peerID; /* client only */
const char *urlSvrName; /* client only */
const sslNamedGroupDef *namedCurve; /* (server) for certificate lookup */
CERTCertificate *localCert;
PRIPv6Addr addr;
......@@ -983,8 +984,8 @@ typedef struct SSLWrappedSymWrappingKeyStr {
CK_MECHANISM_TYPE asymWrapMechanism;
/* mechanism used to wrap the SymmetricWrappingKey using
* server's public and/or private keys. */
SSLAuthType authType; /* type of keys used to wrap SymWrapKey*/
PRInt32 symWrapMechIndex;
PRInt16 wrapMechIndex;
PRUint16 wrapKeyIndex;
PRUint16 wrappedSymKeyLen;
} SSLWrappedSymWrappingKey;
......@@ -997,7 +998,8 @@ typedef struct SessionTicketStr {
PRUint32 authKeyBits;
SSLKEAType keaType;
PRUint32 keaKeyBits;
sslServerCertType certType;
const sslNamedGroupDef *namedCurve; /* For certificate lookup. */
/*
* msWrapMech contains a meaningful value only if ms_is_wrapped is true.
*/
......@@ -1228,7 +1230,6 @@ extern char ssl_debug;
extern char ssl_trace;
extern FILE *ssl_trace_iob;
extern FILE *ssl_keylog_iob;
extern CERTDistNames *ssl3_server_ca_list;
extern PRUint32 ssl_sid_timeout;
extern PRUint32 ssl3_sid_timeout;
......@@ -1684,8 +1685,7 @@ extern SECStatus ssl3_SignHashes(sslSocket *ss, SSL3Hashes *hash,
extern SECStatus ssl3_VerifySignedHashes(sslSocket *ss, SSLSignatureScheme scheme,
SSL3Hashes *hash, SECItem *buf);
extern SECStatus ssl3_CacheWrappedMasterSecret(
sslSocket *ss, sslSessionID *sid,
ssl3CipherSpec *spec, SSLAuthType authType);
sslSocket *ss, sslSessionID *sid, ssl3CipherSpec *spec);
extern void ssl3_FreeSniNameArray(TLSExtensionData *xtnData);
/* Hello Extension related routines. */
......@@ -1694,11 +1694,10 @@ extern void ssl3_SetSIDSessionTicket(sslSessionID *sid,
SECStatus ssl3_EncodeSessionTicket(sslSocket *ss,
const NewSessionTicket *ticket_input,
SECItem *ticket_data);
extern PRBool ssl_GetSessionTicketKeys(SECKEYPrivateKey *svrPrivKey,
SECKEYPublicKey *svrPubKey, void *pwArg,
unsigned char *keyName, PK11SymKey **aesKey,
PK11SymKey **macKey);
extern SECStatus ssl3_SessionTicketShutdown(void *appData, void *nssData);
SECStatus ssl_MaybeSetSessionTicketKeyPair(const sslKeyPair *keyPair);
SECStatus ssl_GetSessionTicketKeys(sslSocket *ss, unsigned char *keyName,
PK11SymKey **encKey, PK11SymKey **macKey);
void ssl_ResetSessionTicketKeys();
/* Tell clients to consider tickets valid for this long. */
#define TLS_EX_SESS_TICKET_LIFETIME_HINT (2 * 24 * 60 * 60) /* 2 days */
......@@ -1716,8 +1715,8 @@ extern void ssl_FreePRSocket(PRFileDesc *fd);
extern int ssl3_config_match_init(sslSocket *);
/* calls for accessing wrapping keys across processes. */
extern PRBool
ssl_GetWrappingKey(PRInt32 symWrapMechIndex, SSLAuthType authType,
extern SECStatus
ssl_GetWrappingKey(unsigned int symWrapMechIndex, unsigned int wrapKeyIndex,
SSLWrappedSymWrappingKey *wswk);
/* The caller passes in the new value it wants
......@@ -1729,7 +1728,7 @@ ssl_GetWrappingKey(PRInt32 symWrapMechIndex, SSLAuthType authType,
* This is all done while holding the locks/semaphores necessary to make
* the operation atomic.
*/
extern PRBool