зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1564499 - land NSS a31fc0eefc4c UPGRADE_NSS_RELEASE, r=me
--HG-- extra : rebase_source : 49049f21b591cf139ea6f4c7fc91f53dfb4e4e1e
This commit is contained in:
Родитель
f03426c144
Коммит
b979163b23
|
@ -1 +1 @@
|
|||
8c6fad5544a6
|
||||
a31fc0eefc4c
|
||||
|
|
|
@ -66,7 +66,7 @@ EncryptFile(FILE *outFile, FILE *inFile, struct recipient *recipients,
|
|||
SEC_PKCS7ContentInfo *cinfo;
|
||||
SEC_PKCS7EncoderContext *ecx;
|
||||
struct recipient *rcpt;
|
||||
SECStatus rv;
|
||||
SECStatus rv = SECFailure;
|
||||
|
||||
if (outFile == NULL || inFile == NULL || recipients == NULL)
|
||||
return -1;
|
||||
|
@ -133,7 +133,7 @@ main(int argc, char **argv)
|
|||
struct recipient *recipients, *rcpt;
|
||||
PLOptState *optstate;
|
||||
PLOptStatus status;
|
||||
SECStatus rv;
|
||||
SECStatus rv = SECFailure;
|
||||
|
||||
progName = strrchr(argv[0], '/');
|
||||
progName = progName ? progName + 1 : argv[0];
|
||||
|
|
|
@ -10,3 +10,4 @@
|
|||
*/
|
||||
|
||||
#error "Do not include this header file."
|
||||
|
||||
|
|
|
@ -90,7 +90,8 @@ SCOPED(SECMODModule);
|
|||
|
||||
struct StackSECItem : public SECItem {
|
||||
StackSECItem() : SECItem({siBuffer, nullptr, 0}) {}
|
||||
~StackSECItem() { SECITEM_FreeItem(this, PR_FALSE); }
|
||||
~StackSECItem() { Reset(); }
|
||||
void Reset() { SECITEM_FreeItem(this, PR_FALSE); }
|
||||
};
|
||||
|
||||
#endif // nss_scoped_ptrs_h__
|
||||
|
|
|
@ -47,6 +47,7 @@ const uint8_t kTlsAlertIllegalParameter = 47;
|
|||
const uint8_t kTlsAlertDecodeError = 50;
|
||||
const uint8_t kTlsAlertDecryptError = 51;
|
||||
const uint8_t kTlsAlertProtocolVersion = 70;
|
||||
const uint8_t kTlsAlertInsufficientSecurity = 71;
|
||||
const uint8_t kTlsAlertInternalError = 80;
|
||||
const uint8_t kTlsAlertInappropriateFallback = 86;
|
||||
const uint8_t kTlsAlertMissingExtension = 109;
|
||||
|
|
|
@ -205,6 +205,42 @@ TEST_F(TlsConnectDatagram13, ShortHeadersServer) {
|
|||
SendReceive();
|
||||
}
|
||||
|
||||
TEST_F(TlsConnectStreamTls13, UnencryptedFinishedMessage) {
|
||||
StartConnect();
|
||||
client_->Handshake(); // Send ClientHello
|
||||
server_->Handshake(); // Send first server flight
|
||||
|
||||
// Record and drop the first record, which is the Finished.
|
||||
auto recorder = std::make_shared<TlsRecordRecorder>(client_);
|
||||
recorder->EnableDecryption();
|
||||
auto dropper = std::make_shared<SelectiveDropFilter>(1);
|
||||
client_->SetFilter(std::make_shared<ChainedPacketFilter>(
|
||||
ChainedPacketFilterInit({recorder, dropper})));
|
||||
client_->Handshake(); // Save and drop CFIN.
|
||||
EXPECT_EQ(TlsAgent::STATE_CONNECTED, client_->state());
|
||||
|
||||
ASSERT_EQ(1U, recorder->count());
|
||||
auto& finished = recorder->record(0);
|
||||
|
||||
DataBuffer d;
|
||||
size_t offset = d.Write(0, ssl_ct_handshake, 1);
|
||||
offset = d.Write(offset, SSL_LIBRARY_VERSION_TLS_1_2, 2);
|
||||
offset = d.Write(offset, finished.buffer.len(), 2);
|
||||
d.Append(finished.buffer);
|
||||
client_->SendDirect(d);
|
||||
|
||||
// Now process the message.
|
||||
ExpectAlert(server_, kTlsAlertUnexpectedMessage);
|
||||
// The server should generate an alert.
|
||||
server_->Handshake();
|
||||
EXPECT_EQ(TlsAgent::STATE_ERROR, server_->state());
|
||||
server_->CheckErrorCode(SSL_ERROR_RX_UNEXPECTED_RECORD_TYPE);
|
||||
// Have the client consume the alert.
|
||||
client_->Handshake();
|
||||
EXPECT_EQ(TlsAgent::STATE_ERROR, client_->state());
|
||||
client_->CheckErrorCode(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT);
|
||||
}
|
||||
|
||||
const static size_t kContentSizesArr[] = {
|
||||
1, kMacSize - 1, kMacSize, 30, 31, 32, 36, 256, 257, 287, 288};
|
||||
|
||||
|
|
|
@ -161,10 +161,10 @@ void TlsAgent::DelegateCredential(const std::string& name,
|
|||
PRUint32 dc_valid_for, PRTime now,
|
||||
SECItem* dc) {
|
||||
ScopedCERTCertificate cert;
|
||||
ScopedSECKEYPrivateKey certPriv;
|
||||
EXPECT_TRUE(TlsAgent::LoadCertificate(name, &cert, &certPriv));
|
||||
ScopedSECKEYPrivateKey cert_priv;
|
||||
EXPECT_TRUE(TlsAgent::LoadCertificate(name, &cert, &cert_priv));
|
||||
EXPECT_EQ(SECSuccess,
|
||||
SSL_DelegateCredential(cert.get(), certPriv.get(), dc_pub.get(),
|
||||
SSL_DelegateCredential(cert.get(), cert_priv.get(), dc_pub.get(),
|
||||
dc_cert_verify_alg, dc_valid_for, now, dc));
|
||||
}
|
||||
|
||||
|
@ -372,10 +372,6 @@ void TlsAgent::CheckCipherSuite(uint16_t suite) {
|
|||
EXPECT_EQ(csinfo_.cipherSuite, suite);
|
||||
}
|
||||
|
||||
void TlsAgent::CheckPeerDelegCred(bool expected) {
|
||||
EXPECT_EQ(expected, info_.peerDelegCred);
|
||||
}
|
||||
|
||||
void TlsAgent::RequestClientAuth(bool requireAuth) {
|
||||
ASSERT_EQ(SERVER, role_);
|
||||
|
||||
|
@ -787,26 +783,26 @@ void TlsAgent::WaitForErrorCode(int32_t expected, uint32_t delay) const {
|
|||
}
|
||||
|
||||
void TlsAgent::CheckPreliminaryInfo() {
|
||||
SSLPreliminaryChannelInfo info;
|
||||
SSLPreliminaryChannelInfo preinfo;
|
||||
EXPECT_EQ(SECSuccess,
|
||||
SSL_GetPreliminaryChannelInfo(ssl_fd(), &info, sizeof(info)));
|
||||
EXPECT_EQ(sizeof(info), info.length);
|
||||
EXPECT_TRUE(info.valuesSet & ssl_preinfo_version);
|
||||
EXPECT_TRUE(info.valuesSet & ssl_preinfo_cipher_suite);
|
||||
SSL_GetPreliminaryChannelInfo(ssl_fd(), &preinfo, sizeof(preinfo)));
|
||||
EXPECT_EQ(sizeof(preinfo), preinfo.length);
|
||||
EXPECT_TRUE(preinfo.valuesSet & ssl_preinfo_version);
|
||||
EXPECT_TRUE(preinfo.valuesSet & ssl_preinfo_cipher_suite);
|
||||
|
||||
// A version of 0 is invalid and indicates no expectation. This value is
|
||||
// initialized to 0 so that tests that don't explicitly set an expected
|
||||
// version can negotiate a version.
|
||||
if (!expected_version_) {
|
||||
expected_version_ = info.protocolVersion;
|
||||
expected_version_ = preinfo.protocolVersion;
|
||||
}
|
||||
EXPECT_EQ(expected_version_, info.protocolVersion);
|
||||
EXPECT_EQ(expected_version_, preinfo.protocolVersion);
|
||||
|
||||
// As with the version; 0 is the null cipher suite (and also invalid).
|
||||
if (!expected_cipher_suite_) {
|
||||
expected_cipher_suite_ = info.cipherSuite;
|
||||
expected_cipher_suite_ = preinfo.cipherSuite;
|
||||
}
|
||||
EXPECT_EQ(expected_cipher_suite_, info.cipherSuite);
|
||||
EXPECT_EQ(expected_cipher_suite_, preinfo.cipherSuite);
|
||||
}
|
||||
|
||||
// Check that all the expected callbacks have been called.
|
||||
|
|
|
@ -184,7 +184,6 @@ class TlsAgent : public PollTarget {
|
|||
void DisableECDHEServerKeyReuse();
|
||||
bool GetPeerChainLength(size_t* count);
|
||||
void CheckCipherSuite(uint16_t cipher_suite);
|
||||
void CheckPeerDelegCred(bool expected);
|
||||
void SetResumptionTokenCallback();
|
||||
bool MaybeSetResumptionToken();
|
||||
void SetResumptionToken(const std::vector<uint8_t>& resumption_token) {
|
||||
|
@ -224,16 +223,17 @@ class TlsAgent : public PollTarget {
|
|||
PRFileDesc* ssl_fd() const { return ssl_fd_.get(); }
|
||||
std::shared_ptr<DummyPrSocket>& adapter() { return adapter_; }
|
||||
|
||||
const SSLChannelInfo& info() const {
|
||||
EXPECT_EQ(STATE_CONNECTED, state_);
|
||||
return info_;
|
||||
}
|
||||
bool is_compressed() const {
|
||||
return info_.compressionMethod != ssl_compression_null;
|
||||
return info().compressionMethod != ssl_compression_null;
|
||||
}
|
||||
uint16_t server_key_bits() const { return server_key_bits_; }
|
||||
uint16_t min_version() const { return vrange_.min; }
|
||||
uint16_t max_version() const { return vrange_.max; }
|
||||
uint16_t version() const {
|
||||
EXPECT_EQ(STATE_CONNECTED, state_);
|
||||
return info_.protocolVersion;
|
||||
}
|
||||
uint16_t version() const { return info().protocolVersion; }
|
||||
|
||||
bool cipher_suite(uint16_t* suite) const {
|
||||
if (state_ != STATE_CONNECTED) return false;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <ctime>
|
||||
|
||||
#include "prtime.h"
|
||||
#include "secerr.h"
|
||||
#include "ssl.h"
|
||||
|
||||
|
@ -20,6 +21,14 @@ const std::string kDCId = TlsAgent::kServerEcdsa256;
|
|||
const SSLSignatureScheme kDCScheme = ssl_sig_ecdsa_secp256r1_sha256;
|
||||
const PRUint32 kDCValidFor = 60 * 60 * 24 * 7 /* 1 week (seconds */;
|
||||
|
||||
static void CheckPeerDelegCred(const std::shared_ptr<TlsAgent>& client,
|
||||
bool expected, PRUint32 key_bits = 0) {
|
||||
EXPECT_EQ(expected, client->info().peerDelegCred);
|
||||
if (expected) {
|
||||
EXPECT_EQ(key_bits, client->info().authKeyBits);
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to configure a DC when either the DC or DC private key is missing.
|
||||
TEST_P(TlsConnectTls13, DCNotConfigured) {
|
||||
// Load and delegate the credential.
|
||||
|
@ -50,14 +59,17 @@ TEST_P(TlsConnectTls13, DCNotConfigured) {
|
|||
TEST_P(TlsConnectTls13, DCConnectEcdsaP256) {
|
||||
Reset(kDelegatorId);
|
||||
client_->EnableDelegatedCredentials();
|
||||
server_->AddDelegatedCredential(kDCId, kDCScheme, kDCValidFor, now());
|
||||
server_->AddDelegatedCredential(TlsAgent::kServerEcdsa256,
|
||||
ssl_sig_ecdsa_secp256r1_sha256, kDCValidFor,
|
||||
now());
|
||||
|
||||
auto cfilter = MakeTlsFilter<TlsExtensionCapture>(
|
||||
client_, ssl_delegated_credentials_xtn);
|
||||
Connect();
|
||||
|
||||
EXPECT_TRUE(cfilter->captured());
|
||||
client_->CheckPeerDelegCred(true);
|
||||
CheckPeerDelegCred(client_, true, 256);
|
||||
EXPECT_EQ(ssl_sig_ecdsa_secp256r1_sha256, client_->info().signatureScheme);
|
||||
}
|
||||
|
||||
// Connected with ECDSA-P521.
|
||||
|
@ -74,11 +86,12 @@ TEST_P(TlsConnectTls13, DCConnectEcdsaP521) {
|
|||
Connect();
|
||||
|
||||
EXPECT_TRUE(cfilter->captured());
|
||||
client_->CheckPeerDelegCred(true);
|
||||
CheckPeerDelegCred(client_, true, 521);
|
||||
EXPECT_EQ(ssl_sig_ecdsa_secp521r1_sha512, client_->info().signatureScheme);
|
||||
}
|
||||
|
||||
// Connected with RSA-PSS.
|
||||
TEST_P(TlsConnectTls13, DCConnectRsaPss) {
|
||||
// Connected with RSA-PSS, using an RSAE SPKI.
|
||||
TEST_P(TlsConnectTls13, DCConnectRsaPssRsae) {
|
||||
Reset(kDelegatorId);
|
||||
client_->EnableDelegatedCredentials();
|
||||
server_->AddDelegatedCredential(
|
||||
|
@ -89,21 +102,133 @@ TEST_P(TlsConnectTls13, DCConnectRsaPss) {
|
|||
Connect();
|
||||
|
||||
EXPECT_TRUE(cfilter->captured());
|
||||
client_->CheckPeerDelegCred(true);
|
||||
CheckPeerDelegCred(client_, true, 1024);
|
||||
EXPECT_EQ(ssl_sig_rsa_pss_rsae_sha256, client_->info().signatureScheme);
|
||||
}
|
||||
|
||||
// Connected with RSA-PSS, using a PSS SPKI.
|
||||
TEST_P(TlsConnectTls13, DCConnectRsaPssPss) {
|
||||
Reset(kDelegatorId);
|
||||
|
||||
// Need to enable PSS-PSS, which is not on by default.
|
||||
static const SSLSignatureScheme kSchemes[] = {ssl_sig_ecdsa_secp256r1_sha256,
|
||||
ssl_sig_rsa_pss_pss_sha256};
|
||||
client_->SetSignatureSchemes(kSchemes, PR_ARRAY_SIZE(kSchemes));
|
||||
server_->SetSignatureSchemes(kSchemes, PR_ARRAY_SIZE(kSchemes));
|
||||
|
||||
client_->EnableDelegatedCredentials();
|
||||
server_->AddDelegatedCredential(
|
||||
TlsAgent::kServerRsaPss, ssl_sig_rsa_pss_pss_sha256, kDCValidFor, now());
|
||||
|
||||
auto cfilter = MakeTlsFilter<TlsExtensionCapture>(
|
||||
client_, ssl_delegated_credentials_xtn);
|
||||
Connect();
|
||||
|
||||
EXPECT_TRUE(cfilter->captured());
|
||||
CheckPeerDelegCred(client_, true, 1024);
|
||||
EXPECT_EQ(ssl_sig_rsa_pss_pss_sha256, client_->info().signatureScheme);
|
||||
}
|
||||
|
||||
// Generate a weak key. We can't do this in the fixture because certutil
|
||||
// won't sign with such a tiny key. That's OK, because this is fast(ish).
|
||||
static void GenerateWeakRsaKey(ScopedSECKEYPrivateKey& priv,
|
||||
ScopedSECKEYPublicKey& pub) {
|
||||
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
|
||||
ASSERT_TRUE(slot);
|
||||
PK11RSAGenParams rsaparams;
|
||||
// The absolute minimum size of RSA key that we can use with SHA-256 is
|
||||
// 256bit (hash) + 256bit (salt) + 8 (start byte) + 8 (end byte) = 528.
|
||||
rsaparams.keySizeInBits = 528;
|
||||
rsaparams.pe = 65537;
|
||||
|
||||
// Bug 1012786: PK11_GenerateKeyPair can fail if there is insufficient
|
||||
// entropy to generate a random key. We can fake some.
|
||||
for (int retry = 0; retry < 10; ++retry) {
|
||||
SECKEYPublicKey* p_pub = nullptr;
|
||||
priv.reset(PK11_GenerateKeyPair(slot.get(), CKM_RSA_PKCS_KEY_PAIR_GEN,
|
||||
&rsaparams, &p_pub, false, false, nullptr));
|
||||
pub.reset(p_pub);
|
||||
if (priv) {
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT_FALSE(pub);
|
||||
if (PORT_GetError() != SEC_ERROR_PKCS11_FUNCTION_FAILED) {
|
||||
break;
|
||||
}
|
||||
|
||||
// https://xkcd.com/221/
|
||||
static const uint8_t FRESH_ENTROPY[16] = {4};
|
||||
ASSERT_EQ(
|
||||
SECSuccess,
|
||||
PK11_RandomUpdate(
|
||||
const_cast<void*>(reinterpret_cast<const void*>(FRESH_ENTROPY)),
|
||||
sizeof(FRESH_ENTROPY)));
|
||||
break;
|
||||
}
|
||||
ADD_FAILURE() << "Unable to generate an RSA key: "
|
||||
<< PORT_ErrorToName(PORT_GetError());
|
||||
}
|
||||
|
||||
// Fail to connect with a weak RSA key.
|
||||
TEST_P(TlsConnectTls13, DCWeakKey) {
|
||||
Reset(kDelegatorId);
|
||||
EnsureTlsSetup();
|
||||
|
||||
ScopedSECKEYPrivateKey dc_priv;
|
||||
ScopedSECKEYPublicKey dc_pub;
|
||||
GenerateWeakRsaKey(dc_priv, dc_pub);
|
||||
ASSERT_TRUE(dc_priv);
|
||||
|
||||
// Construct a DC.
|
||||
StackSECItem dc;
|
||||
TlsAgent::DelegateCredential(kDelegatorId, dc_pub,
|
||||
ssl_sig_rsa_pss_rsae_sha256, kDCValidFor, now(),
|
||||
&dc);
|
||||
|
||||
// Configure the DC on the server.
|
||||
SSLExtraServerCertData extra_data = {ssl_auth_null, nullptr, nullptr,
|
||||
nullptr, &dc, dc_priv.get()};
|
||||
EXPECT_TRUE(server_->ConfigServerCert(kDelegatorId, true, &extra_data));
|
||||
|
||||
client_->EnableDelegatedCredentials();
|
||||
|
||||
auto cfilter = MakeTlsFilter<TlsExtensionCapture>(
|
||||
client_, ssl_delegated_credentials_xtn);
|
||||
ConnectExpectAlert(client_, kTlsAlertInsufficientSecurity);
|
||||
}
|
||||
|
||||
class ReplaceDCSigScheme : public TlsHandshakeFilter {
|
||||
public:
|
||||
ReplaceDCSigScheme(const std::shared_ptr<TlsAgent>& a)
|
||||
: TlsHandshakeFilter(a, {ssl_hs_certificate_verify}) {}
|
||||
|
||||
protected:
|
||||
PacketFilter::Action FilterHandshake(const HandshakeHeader& header,
|
||||
const DataBuffer& input,
|
||||
DataBuffer* output) override {
|
||||
*output = input;
|
||||
output->Write(0, ssl_sig_ecdsa_secp384r1_sha384, 2);
|
||||
return CHANGE;
|
||||
}
|
||||
};
|
||||
|
||||
// Aborted because of incorrect DC signature algorithm indication.
|
||||
TEST_P(TlsConnectTls13, DCAbortBadExpectedCertVerifyAlg) {
|
||||
Reset(kDelegatorId);
|
||||
client_->EnableDelegatedCredentials();
|
||||
server_->AddDelegatedCredential(TlsAgent::kServerEcdsa256,
|
||||
ssl_sig_ecdsa_secp521r1_sha512, kDCValidFor,
|
||||
ssl_sig_ecdsa_secp256r1_sha256, kDCValidFor,
|
||||
now());
|
||||
auto filter = MakeTlsFilter<ReplaceDCSigScheme>(server_);
|
||||
filter->EnableDecryption();
|
||||
ConnectExpectAlert(client_, kTlsAlertIllegalParameter);
|
||||
client_->CheckErrorCode(SSL_ERROR_DC_CERT_VERIFY_ALG_MISMATCH);
|
||||
server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
|
||||
}
|
||||
|
||||
// Aborted because of invalid DC signature.
|
||||
TEST_P(TlsConnectTls13, DCABortBadSignature) {
|
||||
TEST_P(TlsConnectTls13, DCAbortBadSignature) {
|
||||
Reset(kDelegatorId);
|
||||
EnsureTlsSetup();
|
||||
client_->EnableDelegatedCredentials();
|
||||
|
@ -124,6 +249,8 @@ TEST_P(TlsConnectTls13, DCABortBadSignature) {
|
|||
EXPECT_TRUE(server_->ConfigServerCert(kDelegatorId, true, &extra_data));
|
||||
|
||||
ConnectExpectAlert(client_, kTlsAlertIllegalParameter);
|
||||
client_->CheckErrorCode(SSL_ERROR_DC_BAD_SIGNATURE);
|
||||
server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
|
||||
}
|
||||
|
||||
// Aborted because of expired DC.
|
||||
|
@ -135,6 +262,8 @@ TEST_P(TlsConnectTls13, DCAbortExpired) {
|
|||
// DC expired.
|
||||
AdvanceTime((static_cast<PRTime>(kDCValidFor) + 1) * PR_USEC_PER_SEC);
|
||||
ConnectExpectAlert(client_, kTlsAlertIllegalParameter);
|
||||
client_->CheckErrorCode(SSL_ERROR_DC_EXPIRED);
|
||||
server_->CheckErrorCode(SSL_ERROR_ILLEGAL_PARAMETER_ALERT);
|
||||
}
|
||||
|
||||
// Aborted because of invalid key usage.
|
||||
|
@ -156,7 +285,7 @@ TEST_P(TlsConnectTls13, DCConnectNoClientSupport) {
|
|||
Connect();
|
||||
|
||||
EXPECT_FALSE(cfilter->captured());
|
||||
client_->CheckPeerDelegCred(false);
|
||||
CheckPeerDelegCred(client_, false);
|
||||
}
|
||||
|
||||
// Connected without DC because of no server DC.
|
||||
|
@ -169,7 +298,7 @@ TEST_P(TlsConnectTls13, DCConnectNoServerSupport) {
|
|||
Connect();
|
||||
|
||||
EXPECT_TRUE(cfilter->captured());
|
||||
client_->CheckPeerDelegCred(false);
|
||||
CheckPeerDelegCred(client_, false);
|
||||
}
|
||||
|
||||
// Connected without DC because client doesn't support TLS 1.3.
|
||||
|
@ -189,7 +318,7 @@ TEST_P(TlsConnectTls13, DCConnectClientNoTls13) {
|
|||
|
||||
// Should fallback to TLS 1.2 and not negotiate a DC.
|
||||
EXPECT_FALSE(cfilter->captured());
|
||||
client_->CheckPeerDelegCred(false);
|
||||
CheckPeerDelegCred(client_, false);
|
||||
}
|
||||
|
||||
// Connected without DC because server doesn't support TLS 1.3.
|
||||
|
@ -210,7 +339,7 @@ TEST_P(TlsConnectTls13, DCConnectServerNoTls13) {
|
|||
// Should fallback to TLS 1.2 and not negotiate a DC. The client will still
|
||||
// send the indication because it supports 1.3.
|
||||
EXPECT_TRUE(cfilter->captured());
|
||||
client_->CheckPeerDelegCred(false);
|
||||
CheckPeerDelegCred(client_, false);
|
||||
}
|
||||
|
||||
// Connected without DC because client doesn't support the signature scheme.
|
||||
|
@ -232,7 +361,64 @@ TEST_P(TlsConnectTls13, DCConnectExpectedCertVerifyAlgNotSupported) {
|
|||
|
||||
// Client sends indication, but the server doesn't send a DC.
|
||||
EXPECT_TRUE(cfilter->captured());
|
||||
client_->CheckPeerDelegCred(false);
|
||||
CheckPeerDelegCred(client_, false);
|
||||
}
|
||||
|
||||
class DCDelegation : public ::testing::Test {};
|
||||
|
||||
TEST_F(DCDelegation, DCDelegations) {
|
||||
PRTime now = PR_Now();
|
||||
ScopedCERTCertificate cert;
|
||||
ScopedSECKEYPrivateKey priv;
|
||||
ASSERT_TRUE(TlsAgent::LoadCertificate(kDelegatorId, &cert, &priv));
|
||||
|
||||
ScopedSECKEYPublicKey pub_rsa;
|
||||
ScopedSECKEYPrivateKey priv_rsa;
|
||||
ASSERT_TRUE(
|
||||
TlsAgent::LoadKeyPairFromCert(TlsAgent::kServerRsa, &pub_rsa, &priv_rsa));
|
||||
|
||||
StackSECItem dc;
|
||||
EXPECT_EQ(SECFailure,
|
||||
SSL_DelegateCredential(cert.get(), priv.get(), pub_rsa.get(),
|
||||
ssl_sig_ecdsa_secp256r1_sha256, kDCValidFor,
|
||||
now, &dc));
|
||||
EXPECT_EQ(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM, PORT_GetError());
|
||||
|
||||
// Using different PSS hashes should be OK.
|
||||
EXPECT_EQ(SECSuccess,
|
||||
SSL_DelegateCredential(cert.get(), priv.get(), pub_rsa.get(),
|
||||
ssl_sig_rsa_pss_rsae_sha256, kDCValidFor,
|
||||
now, &dc));
|
||||
// Make sure to reset |dc| after each success.
|
||||
dc.Reset();
|
||||
EXPECT_EQ(SECSuccess, SSL_DelegateCredential(
|
||||
cert.get(), priv.get(), pub_rsa.get(),
|
||||
ssl_sig_rsa_pss_pss_sha256, kDCValidFor, now, &dc));
|
||||
dc.Reset();
|
||||
EXPECT_EQ(SECSuccess, SSL_DelegateCredential(
|
||||
cert.get(), priv.get(), pub_rsa.get(),
|
||||
ssl_sig_rsa_pss_pss_sha384, kDCValidFor, now, &dc));
|
||||
dc.Reset();
|
||||
|
||||
ScopedSECKEYPublicKey pub_ecdsa;
|
||||
ScopedSECKEYPrivateKey priv_ecdsa;
|
||||
ASSERT_TRUE(TlsAgent::LoadKeyPairFromCert(TlsAgent::kServerEcdsa256,
|
||||
&pub_ecdsa, &priv_ecdsa));
|
||||
|
||||
EXPECT_EQ(SECFailure,
|
||||
SSL_DelegateCredential(cert.get(), priv.get(), pub_ecdsa.get(),
|
||||
ssl_sig_rsa_pss_rsae_sha256, kDCValidFor,
|
||||
now, &dc));
|
||||
EXPECT_EQ(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM, PORT_GetError());
|
||||
EXPECT_EQ(SECFailure, SSL_DelegateCredential(
|
||||
cert.get(), priv.get(), pub_ecdsa.get(),
|
||||
ssl_sig_rsa_pss_pss_sha256, kDCValidFor, now, &dc));
|
||||
EXPECT_EQ(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM, PORT_GetError());
|
||||
EXPECT_EQ(SECFailure,
|
||||
SSL_DelegateCredential(cert.get(), priv.get(), pub_ecdsa.get(),
|
||||
ssl_sig_ecdsa_secp384r1_sha384, kDCValidFor,
|
||||
now, &dc));
|
||||
EXPECT_EQ(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM, PORT_GetError());
|
||||
}
|
||||
|
||||
} // namespace nss_test
|
||||
|
|
|
@ -205,6 +205,46 @@ GetNeonSupport()
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
static long
|
||||
ReadCPUInfoForHWCAP2()
|
||||
{
|
||||
FILE *cpuinfo;
|
||||
char buf[512];
|
||||
char *p;
|
||||
long hwcap2 = 0;
|
||||
|
||||
cpuinfo = fopen("/proc/cpuinfo", "r");
|
||||
if (!cpuinfo) {
|
||||
return 0;
|
||||
}
|
||||
while (fgets(buf, 511, cpuinfo)) {
|
||||
if (!memcmp(buf, "Features", 8)) {
|
||||
p = strstr(buf, " aes");
|
||||
if (p && (p[4] == ' ' || p[4] == '\n')) {
|
||||
hwcap2 |= HWCAP2_AES;
|
||||
}
|
||||
p = strstr(buf, " sha1");
|
||||
if (p && (p[5] == ' ' || p[5] == '\n')) {
|
||||
hwcap2 |= HWCAP2_SHA1;
|
||||
}
|
||||
p = strstr(buf, " sha2");
|
||||
if (p && (p[5] == ' ' || p[5] == '\n')) {
|
||||
hwcap2 |= HWCAP2_SHA2;
|
||||
}
|
||||
p = strstr(buf, " pmull");
|
||||
if (p && (p[6] == ' ' || p[6] == '\n')) {
|
||||
hwcap2 |= HWCAP2_PMULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(cpuinfo);
|
||||
return hwcap2;
|
||||
}
|
||||
#endif /* __linux__ */
|
||||
|
||||
void
|
||||
CheckARMSupport()
|
||||
{
|
||||
|
@ -217,6 +257,13 @@ CheckARMSupport()
|
|||
// AT_HWCAP2 isn't supported by glibc or Linux kernel, getauxval will
|
||||
// returns 0.
|
||||
long hwcaps = getauxval(AT_HWCAP2);
|
||||
#ifdef __linux__
|
||||
if (!hwcaps) {
|
||||
// Some ARMv8 devices may not implement AT_HWCAP2. So we also
|
||||
// read /proc/cpuinfo if AT_HWCAP2 is 0.
|
||||
hwcaps = ReadCPUInfoForHWCAP2();
|
||||
}
|
||||
#endif
|
||||
arm_aes_support_ = hwcaps & HWCAP2_AES && disable_hw_aes == NULL;
|
||||
arm_pmull_support_ = hwcaps & HWCAP2_PMULL;
|
||||
arm_sha1_support_ = hwcaps & HWCAP2_SHA1;
|
||||
|
|
|
@ -727,7 +727,7 @@ static inline void
|
|||
dcbzl(char *array)
|
||||
{
|
||||
register char *a asm("r2") = array;
|
||||
__asm__ __volatile__("dcbzl %0,r0"
|
||||
__asm__ __volatile__("dcbzl %0,0"
|
||||
: "=r"(a)
|
||||
: "0"(a));
|
||||
}
|
||||
|
|
|
@ -352,7 +352,9 @@ pkix_pl_LdapDefaultClient_VerifyBindResponse(
|
|||
SECItem decode = {siBuffer, NULL, 0};
|
||||
SECStatus rv = SECFailure;
|
||||
LDAPMessage msg;
|
||||
LDAPBindResponse *ldapBindResponse = NULL;
|
||||
LDAPBindResponse *ldapBindResponse = &msg.protocolOp.op.bindResponseMsg;
|
||||
|
||||
ldapBindResponse->resultCode.data = NULL;
|
||||
|
||||
PKIX_ENTER
|
||||
(LDAPDEFAULTCLIENT,
|
||||
|
@ -367,7 +369,6 @@ pkix_pl_LdapDefaultClient_VerifyBindResponse(
|
|||
PKIX_LDAPDEFAULTCLIENTDECODEBINDRESPONSEFAILED);
|
||||
|
||||
if (rv == SECSuccess) {
|
||||
ldapBindResponse = &msg.protocolOp.op.bindResponseMsg;
|
||||
if (*(ldapBindResponse->resultCode.data) == SUCCESS) {
|
||||
client->connectStatus = BOUND;
|
||||
} else {
|
||||
|
|
|
@ -1153,11 +1153,10 @@ ssl3_SignHashes(sslSocket *ss, SSL3Hashes *hash, SECKEYPrivateKey *key,
|
|||
|
||||
/* Called from ssl3_VerifySignedHashes and tls13_HandleCertificateVerify. */
|
||||
SECStatus
|
||||
ssl3_VerifySignedHashesWithSpki(sslSocket *ss, CERTSubjectPublicKeyInfo *spki,
|
||||
SSLSignatureScheme scheme,
|
||||
SSL3Hashes *hash, SECItem *buf)
|
||||
ssl_VerifySignedHashesWithPubKey(sslSocket *ss, SECKEYPublicKey *key,
|
||||
SSLSignatureScheme scheme,
|
||||
SSL3Hashes *hash, SECItem *buf)
|
||||
{
|
||||
SECKEYPublicKey *key;
|
||||
SECItem *signature = NULL;
|
||||
SECStatus rv = SECFailure;
|
||||
SECItem hashItem;
|
||||
|
@ -1166,14 +1165,7 @@ ssl3_VerifySignedHashesWithSpki(sslSocket *ss, CERTSubjectPublicKeyInfo *spki,
|
|||
void *pwArg = ss->pkcs11PinArg;
|
||||
PRBool isRsaPssScheme = ssl_IsRsaPssSignatureScheme(scheme);
|
||||
|
||||
PRINT_BUF(60, (NULL, "check signed hashes",
|
||||
buf->data, buf->len));
|
||||
|
||||
key = SECKEY_ExtractPublicKey(spki);
|
||||
if (key == NULL) {
|
||||
ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
|
||||
return SECFailure;
|
||||
}
|
||||
PRINT_BUF(60, (NULL, "check signed hashes", buf->data, buf->len));
|
||||
|
||||
hashAlg = ssl3_HashTypeToOID(hash->hashAlg);
|
||||
switch (SECKEY_GetPublicKeyType(key)) {
|
||||
|
@ -1281,7 +1273,6 @@ ssl3_VerifySignedHashesWithSpki(sslSocket *ss, CERTSubjectPublicKeyInfo *spki,
|
|||
}
|
||||
|
||||
loser:
|
||||
SECKEY_DestroyPublicKey(key);
|
||||
#ifdef UNSAFE_FUZZER_MODE
|
||||
rv = SECSuccess;
|
||||
PORT_SetError(0);
|
||||
|
@ -1294,9 +1285,16 @@ SECStatus
|
|||
ssl3_VerifySignedHashes(sslSocket *ss, SSLSignatureScheme scheme, SSL3Hashes *hash,
|
||||
SECItem *buf)
|
||||
{
|
||||
CERTSubjectPublicKeyInfo *spki = &ss->sec.peerCert->subjectPublicKeyInfo;
|
||||
return ssl3_VerifySignedHashesWithSpki(
|
||||
ss, spki, scheme, hash, buf);
|
||||
SECKEYPublicKey *pubKey =
|
||||
SECKEY_ExtractPublicKey(&ss->sec.peerCert->subjectPublicKeyInfo);
|
||||
if (pubKey == NULL) {
|
||||
ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
|
||||
return SECFailure;
|
||||
}
|
||||
SECStatus rv = ssl_VerifySignedHashesWithPubKey(ss, pubKey, scheme,
|
||||
hash, buf);
|
||||
SECKEY_DestroyPublicKey(pubKey);
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Caller must set hiLevel error code. */
|
||||
|
@ -10867,6 +10865,66 @@ loser:
|
|||
return SECFailure;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
ssl_SetAuthKeyBits(sslSocket *ss, const SECKEYPublicKey *pubKey)
|
||||
{
|
||||
SECStatus rv;
|
||||
PRUint32 minKey;
|
||||
PRInt32 optval;
|
||||
|
||||
ss->sec.authKeyBits = SECKEY_PublicKeyStrengthInBits(pubKey);
|
||||
switch (SECKEY_GetPublicKeyType(pubKey)) {
|
||||
case rsaKey:
|
||||
case rsaPssKey:
|
||||
case rsaOaepKey:
|
||||
rv = NSS_OptionGet(NSS_RSA_MIN_KEY_SIZE, &optval);
|
||||
if (rv == SECSuccess && optval > 0) {
|
||||
minKey = (PRUint32)optval;
|
||||
} else {
|
||||
minKey = SSL_RSA_MIN_MODULUS_BITS;
|
||||
}
|
||||
break;
|
||||
|
||||
case dsaKey:
|
||||
rv = NSS_OptionGet(NSS_DSA_MIN_KEY_SIZE, &optval);
|
||||
if (rv == SECSuccess && optval > 0) {
|
||||
minKey = (PRUint32)optval;
|
||||
} else {
|
||||
minKey = SSL_DSA_MIN_P_BITS;
|
||||
}
|
||||
break;
|
||||
|
||||
case dhKey:
|
||||
rv = NSS_OptionGet(NSS_DH_MIN_KEY_SIZE, &optval);
|
||||
if (rv == SECSuccess && optval > 0) {
|
||||
minKey = (PRUint32)optval;
|
||||
} else {
|
||||
minKey = SSL_DH_MIN_P_BITS;
|
||||
}
|
||||
break;
|
||||
|
||||
case ecKey:
|
||||
/* Don't check EC strength here on the understanding that we only
|
||||
* support curves we like. */
|
||||
minKey = ss->sec.authKeyBits;
|
||||
break;
|
||||
|
||||
default:
|
||||
FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
/* Too small: not good enough. Send a fatal alert. */
|
||||
if (ss->sec.authKeyBits < minKey) {
|
||||
FATAL_ERROR(ss, SSL_ERROR_WEAK_SERVER_CERT_KEY,
|
||||
ss->version >= SSL_LIBRARY_VERSION_TLS_1_0
|
||||
? insufficient_security
|
||||
: illegal_parameter);
|
||||
return SECFailure;
|
||||
}
|
||||
return SECSuccess;
|
||||
}
|
||||
|
||||
SECStatus
|
||||
ssl3_AuthCertificate(sslSocket *ss)
|
||||
{
|
||||
|
@ -10916,75 +10974,20 @@ ssl3_AuthCertificate(sslSocket *ss)
|
|||
ss->sec.ci.sid->peerCert = CERT_DupCertificate(ss->sec.peerCert);
|
||||
|
||||
if (!ss->sec.isServer) {
|
||||
CERTCertificate *cert = ss->sec.peerCert;
|
||||
|
||||
/* set the server authentication type and size from the value
|
||||
** in the cert. */
|
||||
SECKEYPublicKey *pubKey = CERT_ExtractPublicKey(cert);
|
||||
if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3) {
|
||||
/* These are filled in in tls13_HandleCertificateVerify and
|
||||
* tls13_HandleServerKeyShare. */
|
||||
* tls13_HandleServerKeyShare (keaType). */
|
||||
SECKEYPublicKey *pubKey = CERT_ExtractPublicKey(ss->sec.peerCert);
|
||||
if (pubKey) {
|
||||
rv = ssl_SetAuthKeyBits(ss, pubKey);
|
||||
SECKEY_DestroyPublicKey(pubKey);
|
||||
if (rv != SECSuccess) {
|
||||
return SECFailure; /* Alert sent and code set. */
|
||||
}
|
||||
}
|
||||
ss->sec.authType = ss->ssl3.hs.kea_def->authKeyType;
|
||||
ss->sec.keaType = ss->ssl3.hs.kea_def->exchKeyType;
|
||||
}
|
||||
if (pubKey) {
|
||||
KeyType pubKeyType;
|
||||
PRUint32 minKey;
|
||||
PRInt32 optval;
|
||||
/* This partly fixes Bug 124230 and may cause problems for
|
||||
* callers which depend on the old (wrong) behavior. */
|
||||
ss->sec.authKeyBits = SECKEY_PublicKeyStrengthInBits(pubKey);
|
||||
pubKeyType = SECKEY_GetPublicKeyType(pubKey);
|
||||
minKey = ss->sec.authKeyBits;
|
||||
switch (pubKeyType) {
|
||||
case rsaKey:
|
||||
case rsaPssKey:
|
||||
case rsaOaepKey:
|
||||
rv =
|
||||
NSS_OptionGet(NSS_RSA_MIN_KEY_SIZE, &optval);
|
||||
if (rv == SECSuccess && optval > 0) {
|
||||
minKey = (PRUint32)optval;
|
||||
} else {
|
||||
minKey = SSL_RSA_MIN_MODULUS_BITS;
|
||||
}
|
||||
break;
|
||||
case dsaKey:
|
||||
rv =
|
||||
NSS_OptionGet(NSS_DSA_MIN_KEY_SIZE, &optval);
|
||||
if (rv == SECSuccess && optval > 0) {
|
||||
minKey = (PRUint32)optval;
|
||||
} else {
|
||||
minKey = SSL_DSA_MIN_P_BITS;
|
||||
}
|
||||
break;
|
||||
case dhKey:
|
||||
rv =
|
||||
NSS_OptionGet(NSS_DH_MIN_KEY_SIZE, &optval);
|
||||
if (rv == SECSuccess && optval > 0) {
|
||||
minKey = (PRUint32)optval;
|
||||
} else {
|
||||
minKey = SSL_DH_MIN_P_BITS;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Too small: not good enough. Send a fatal alert. */
|
||||
/* We aren't checking EC here on the understanding that we only
|
||||
* support curves we like, a decision that might need revisiting. */
|
||||
if (ss->sec.authKeyBits < minKey) {
|
||||
PORT_SetError(SSL_ERROR_WEAK_SERVER_CERT_KEY);
|
||||
(void)SSL3_SendAlert(ss, alert_fatal,
|
||||
ss->version >= SSL_LIBRARY_VERSION_TLS_1_0
|
||||
? insufficient_security
|
||||
: illegal_parameter);
|
||||
SECKEY_DestroyPublicKey(pubKey);
|
||||
return SECFailure;
|
||||
}
|
||||
SECKEY_DestroyPublicKey(pubKey);
|
||||
pubKey = NULL;
|
||||
}
|
||||
|
||||
if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
|
||||
TLS13_SET_HS_STATE(ss, wait_cert_verify);
|
||||
|
|
|
@ -1590,11 +1590,11 @@ extern SECStatus ssl3_SignHashesWithPrivKey(SSL3Hashes *hash,
|
|||
SECItem *buf);
|
||||
extern SECStatus ssl3_SignHashes(sslSocket *ss, SSL3Hashes *hash,
|
||||
SECKEYPrivateKey *key, SECItem *buf);
|
||||
extern SECStatus ssl3_VerifySignedHashesWithSpki(sslSocket *ss,
|
||||
CERTSubjectPublicKeyInfo *spki,
|
||||
SSLSignatureScheme scheme,
|
||||
SSL3Hashes *hash,
|
||||
SECItem *buf);
|
||||
extern SECStatus ssl_VerifySignedHashesWithPubKey(sslSocket *ss,
|
||||
SECKEYPublicKey *spki,
|
||||
SSLSignatureScheme scheme,
|
||||
SSL3Hashes *hash,
|
||||
SECItem *buf);
|
||||
extern SECStatus ssl3_VerifySignedHashes(sslSocket *ss, SSLSignatureScheme scheme,
|
||||
SSL3Hashes *hash, SECItem *buf);
|
||||
extern SECStatus ssl3_CacheWrappedSecret(sslSocket *ss, sslSessionID *sid,
|
||||
|
@ -1677,6 +1677,7 @@ SECStatus ssl3_HandleNoCertificate(sslSocket *ss);
|
|||
SECStatus ssl3_SendEmptyCertificate(sslSocket *ss);
|
||||
void ssl3_CleanupPeerCerts(sslSocket *ss);
|
||||
SECStatus ssl3_SendCertificateStatus(sslSocket *ss);
|
||||
SECStatus ssl_SetAuthKeyBits(sslSocket *ss, const SECKEYPublicKey *pubKey);
|
||||
SECStatus ssl3_AuthCertificate(sslSocket *ss);
|
||||
SECStatus ssl_ReadCertificateStatus(sslSocket *ss, PRUint8 *b,
|
||||
PRUint32 length);
|
||||
|
|
|
@ -299,7 +299,13 @@ typedef struct SSLChannelInfoStr {
|
|||
PRUint16 protocolVersion;
|
||||
PRUint16 cipherSuite;
|
||||
|
||||
/* server authentication info */
|
||||
/* The strength of the key used to authenticate the peer. Before
|
||||
* interpreting this value, check authType, signatureScheme, and
|
||||
* peerDelegCred, to determine the type of the key and how it was used.
|
||||
*
|
||||
* Typically, this is the length of the key from the peer's end-entity
|
||||
* certificate. If delegated credentials are used (i.e., peerDelegCred is
|
||||
* PR_TRUE), then this is the strength of the delegated credential key. */
|
||||
PRUint32 authKeyBits;
|
||||
|
||||
/* key exchange algorithm info */
|
||||
|
|
|
@ -4143,7 +4143,8 @@ SECStatus
|
|||
tls13_HandleCertificateVerify(sslSocket *ss, PRUint8 *b, PRUint32 length)
|
||||
{
|
||||
sslDelegatedCredential *dc = ss->xtnData.peerDelegCred;
|
||||
CERTSubjectPublicKeyInfo *spki = NULL;
|
||||
CERTSubjectPublicKeyInfo *spki;
|
||||
SECKEYPublicKey *pubKey = NULL;
|
||||
SECItem signed_hash = { siBuffer, NULL, 0 };
|
||||
SECStatus rv;
|
||||
SSLSignatureScheme sigScheme;
|
||||
|
@ -4239,16 +4240,26 @@ tls13_HandleCertificateVerify(sslSocket *ss, PRUint8 *b, PRUint32 length)
|
|||
return SECFailure;
|
||||
}
|
||||
|
||||
rv = ssl3_VerifySignedHashesWithSpki(
|
||||
ss, spki, sigScheme, &tbsHash, &signed_hash);
|
||||
pubKey = SECKEY_ExtractPublicKey(spki);
|
||||
if (pubKey == NULL) {
|
||||
ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
rv = ssl_VerifySignedHashesWithPubKey(ss, pubKey, sigScheme,
|
||||
&tbsHash, &signed_hash);
|
||||
if (rv != SECSuccess) {
|
||||
FATAL_ERROR(ss, PORT_GetError(), decrypt_error);
|
||||
return SECFailure;
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* Set the auth type. */
|
||||
if (!ss->sec.isServer) {
|
||||
ss->sec.authType = ssl_SignatureSchemeToAuthType(sigScheme);
|
||||
rv = ssl_SetAuthKeyBits(ss, pubKey);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser; /* Alert sent and code set. */
|
||||
}
|
||||
}
|
||||
|
||||
/* Request a client certificate now if one was requested. */
|
||||
|
@ -4259,13 +4270,17 @@ tls13_HandleCertificateVerify(sslSocket *ss, PRUint8 *b, PRUint32 length)
|
|||
&ss->xtnData.certReqAuthorities);
|
||||
if (rv != SECSuccess) {
|
||||
FATAL_ERROR(ss, SEC_ERROR_LIBRARY_FAILURE, internal_error);
|
||||
return rv;
|
||||
goto loser;
|
||||
}
|
||||
}
|
||||
|
||||
SECKEY_DestroyPublicKey(pubKey);
|
||||
TLS13_SET_HS_STATE(ss, wait_finished);
|
||||
|
||||
return SECSuccess;
|
||||
|
||||
loser:
|
||||
SECKEY_DestroyPublicKey(pubKey);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
static SECStatus
|
||||
|
|
|
@ -350,6 +350,7 @@ tls13_VerifyCredentialSignature(sslSocket *ss, sslDelegatedCredential *dc)
|
|||
SSL3Hashes hash;
|
||||
sslBuffer dcBuf = SSL_BUFFER_EMPTY;
|
||||
CERTCertificate *cert = ss->sec.peerCert;
|
||||
SECKEYPublicKey *pubKey = NULL;
|
||||
|
||||
/* Serialize the DC parameters. */
|
||||
rv = tls13_AppendCredentialParams(&dcBuf, dc);
|
||||
|
@ -364,18 +365,26 @@ tls13_VerifyCredentialSignature(sslSocket *ss, sslDelegatedCredential *dc)
|
|||
goto loser;
|
||||
}
|
||||
|
||||
pubKey = SECKEY_ExtractPublicKey(&cert->subjectPublicKeyInfo);
|
||||
if (pubKey == NULL) {
|
||||
FATAL_ERROR(ss, SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE, internal_error);
|
||||
goto loser;
|
||||
}
|
||||
|
||||
/* Verify the signature of the message. */
|
||||
rv = ssl3_VerifySignedHashesWithSpki(
|
||||
ss, &cert->subjectPublicKeyInfo, dc->alg, &hash, &dc->signature);
|
||||
rv = ssl_VerifySignedHashesWithPubKey(ss, pubKey, dc->alg,
|
||||
&hash, &dc->signature);
|
||||
if (rv != SECSuccess) {
|
||||
FATAL_ERROR(ss, SSL_ERROR_DC_BAD_SIGNATURE, illegal_parameter);
|
||||
goto loser;
|
||||
}
|
||||
|
||||
SECKEY_DestroyPublicKey(pubKey);
|
||||
sslBuffer_Clear(&dcBuf);
|
||||
return SECSuccess;
|
||||
|
||||
loser:
|
||||
SECKEY_DestroyPublicKey(pubKey);
|
||||
sslBuffer_Clear(&dcBuf);
|
||||
return SECFailure;
|
||||
}
|
||||
|
@ -484,13 +493,155 @@ tls13_VerifyDelegatedCredential(sslSocket *ss,
|
|||
return rv;
|
||||
}
|
||||
|
||||
static CERTSubjectPublicKeyInfo *
|
||||
tls13_MakePssSpki(const SECKEYPublicKey *pub, SECOidTag hashOid)
|
||||
{
|
||||
SECStatus rv;
|
||||
PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
|
||||
if (!arena) {
|
||||
goto loser; /* Code already set. */
|
||||
}
|
||||
CERTSubjectPublicKeyInfo *spki = PORT_ArenaZNew(arena, CERTSubjectPublicKeyInfo);
|
||||
if (!spki) {
|
||||
goto loser; /* Code already set. */
|
||||
}
|
||||
spki->arena = arena;
|
||||
|
||||
SECKEYRSAPSSParams params = { 0 };
|
||||
params.hashAlg = PORT_ArenaZNew(arena, SECAlgorithmID);
|
||||
rv = SECOID_SetAlgorithmID(arena, params.hashAlg, hashOid, NULL);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser; /* Code already set. */
|
||||
}
|
||||
|
||||
/* Set the mask hash algorithm too, which is an argument to
|
||||
* a SEC_OID_PKCS1_MGF1 value. */
|
||||
SECAlgorithmID maskHashAlg;
|
||||
memset(&maskHashAlg, 0, sizeof(maskHashAlg));
|
||||
rv = SECOID_SetAlgorithmID(arena, &maskHashAlg, hashOid, NULL);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser; /* Code already set. */
|
||||
}
|
||||
SECItem *maskHashAlgItem =
|
||||
SEC_ASN1EncodeItem(arena, NULL, &maskHashAlg,
|
||||
SEC_ASN1_GET(SECOID_AlgorithmIDTemplate));
|
||||
if (!maskHashAlgItem) {
|
||||
/* Probably OOM, but not certain. */
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
goto loser;
|
||||
}
|
||||
|
||||
params.maskAlg = PORT_ArenaZNew(arena, SECAlgorithmID);
|
||||
rv = SECOID_SetAlgorithmID(arena, params.maskAlg, SEC_OID_PKCS1_MGF1,
|
||||
maskHashAlgItem);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser; /* Code already set. */
|
||||
}
|
||||
|
||||
SECItem *algorithmItem =
|
||||
SEC_ASN1EncodeItem(arena, NULL, ¶ms,
|
||||
SEC_ASN1_GET(SECKEY_RSAPSSParamsTemplate));
|
||||
if (!algorithmItem) {
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
goto loser; /* Code already set. */
|
||||
}
|
||||
rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
|
||||
SEC_OID_PKCS1_RSA_PSS_SIGNATURE, algorithmItem);
|
||||
if (rv != SECSuccess) {
|
||||
goto loser; /* Code already set. */
|
||||
}
|
||||
|
||||
PORT_Assert(pub->u.rsa.modulus.type == siUnsignedInteger);
|
||||
PORT_Assert(pub->u.rsa.publicExponent.type == siUnsignedInteger);
|
||||
SECItem *pubItem = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey, pub,
|
||||
SEC_ASN1_GET(SECKEY_RSAPublicKeyTemplate));
|
||||
if (!pubItem) {
|
||||
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
|
||||
goto loser;
|
||||
}
|
||||
spki->subjectPublicKey.len *= 8; /* Key length is in bits. */
|
||||
return spki;
|
||||
|
||||
loser:
|
||||
PORT_FreeArena(arena, PR_FALSE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static CERTSubjectPublicKeyInfo *
|
||||
tls13_MakeDcSpki(const SECKEYPublicKey *dcPub, SSLSignatureScheme dcCertVerifyAlg)
|
||||
{
|
||||
switch (SECKEY_GetPublicKeyType(dcPub)) {
|
||||
case rsaKey: {
|
||||
SECOidTag hashOid;
|
||||
switch (dcCertVerifyAlg) {
|
||||
/* Though we might prefer to use a pure PSS SPKI here, we can't
|
||||
* because we have to choose based on client preferences. And
|
||||
* not all clients advertise the pss_pss schemes. So use the
|
||||
* default SPKI construction for an RSAE SPKI. */
|
||||
case ssl_sig_rsa_pss_rsae_sha256:
|
||||
case ssl_sig_rsa_pss_rsae_sha384:
|
||||
case ssl_sig_rsa_pss_rsae_sha512:
|
||||
return SECKEY_CreateSubjectPublicKeyInfo(dcPub);
|
||||
|
||||
case ssl_sig_rsa_pss_pss_sha256:
|
||||
hashOid = SEC_OID_SHA256;
|
||||
break;
|
||||
case ssl_sig_rsa_pss_pss_sha384:
|
||||
hashOid = SEC_OID_SHA384;
|
||||
break;
|
||||
case ssl_sig_rsa_pss_pss_sha512:
|
||||
hashOid = SEC_OID_SHA512;
|
||||
break;
|
||||
|
||||
default:
|
||||
PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
|
||||
return NULL;
|
||||
}
|
||||
return tls13_MakePssSpki(dcPub, hashOid);
|
||||
}
|
||||
|
||||
case ecKey: {
|
||||
const sslNamedGroupDef *group = ssl_ECPubKey2NamedGroup(dcPub);
|
||||
if (!group) {
|
||||
PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
|
||||
return NULL;
|
||||
}
|
||||
SSLSignatureScheme keyScheme;
|
||||
switch (group->name) {
|
||||
case ssl_grp_ec_secp256r1:
|
||||
keyScheme = ssl_sig_ecdsa_secp256r1_sha256;
|
||||
break;
|
||||
case ssl_grp_ec_secp384r1:
|
||||
keyScheme = ssl_sig_ecdsa_secp384r1_sha384;
|
||||
break;
|
||||
case ssl_grp_ec_secp521r1:
|
||||
keyScheme = ssl_sig_ecdsa_secp521r1_sha512;
|
||||
break;
|
||||
default:
|
||||
PORT_SetError(SEC_ERROR_INVALID_KEY);
|
||||
return NULL;
|
||||
}
|
||||
if (keyScheme != dcCertVerifyAlg) {
|
||||
PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
|
||||
return NULL;
|
||||
}
|
||||
return SECKEY_CreateSubjectPublicKeyInfo(dcPub);
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
PORT_SetError(SEC_ERROR_INVALID_KEY);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Returns a serialized DC with the given parameters.
|
||||
*
|
||||
* Note that this function is meant primarily for testing. In particular, it
|
||||
* DOES NOT verify any of the following:
|
||||
* - |certPriv| is the private key corresponding to |cert|;
|
||||
* - that |checkCertKeyUsage(cert) == SECSuccess|;
|
||||
* - |dcCertVerifyAlg| is consistent with |dcPub|;
|
||||
* - |dcValidFor| is less than 7 days (the maximum permitted by the spec); or
|
||||
* - validTime doesn't overflow a PRUint32.
|
||||
*
|
||||
|
@ -509,7 +660,7 @@ SSLExp_DelegateCredential(const CERTCertificate *cert,
|
|||
{
|
||||
SECStatus rv;
|
||||
SSL3Hashes hash;
|
||||
SECItem *tmp = NULL;
|
||||
CERTSubjectPublicKeyInfo *spki = NULL;
|
||||
SECKEYPrivateKey *tmpPriv = NULL;
|
||||
sslDelegatedCredential *dc = NULL;
|
||||
sslBuffer dcBuf = SSL_BUFFER_EMPTY;
|
||||
|
@ -527,17 +678,20 @@ SSLExp_DelegateCredential(const CERTCertificate *cert,
|
|||
goto loser;
|
||||
}
|
||||
dc->validTime = ((now - start) / PR_USEC_PER_SEC) + dcValidFor;
|
||||
dc->expectedCertVerifyAlg = dcCertVerifyAlg;
|
||||
|
||||
tmp = SECKEY_EncodeDERSubjectPublicKeyInfo(dcPub);
|
||||
if (!tmp) {
|
||||
/* Building the SPKI also validates |dcCertVerifyAlg|. */
|
||||
spki = tls13_MakeDcSpki(dcPub, dcCertVerifyAlg);
|
||||
if (!spki) {
|
||||
goto loser;
|
||||
}
|
||||
dc->expectedCertVerifyAlg = dcCertVerifyAlg;
|
||||
|
||||
SECItem *spkiDer =
|
||||
SEC_ASN1EncodeItem(NULL /*arena*/, &dc->derSpki, spki,
|
||||
SEC_ASN1_GET(CERT_SubjectPublicKeyInfoTemplate));
|
||||
if (!spkiDer) {
|
||||
goto loser;
|
||||
}
|
||||
/* Transfer |tmp| into |dc->derSpki|. */
|
||||
dc->derSpki.type = tmp->type;
|
||||
dc->derSpki.data = tmp->data;
|
||||
dc->derSpki.len = tmp->len;
|
||||
PORT_Free(tmp);
|
||||
|
||||
rv = ssl_SignatureSchemeFromSpki(&cert->subjectPublicKeyInfo,
|
||||
PR_TRUE /* isTls13 */, &dc->alg);
|
||||
|
@ -581,12 +735,14 @@ SSLExp_DelegateCredential(const CERTCertificate *cert,
|
|||
goto loser;
|
||||
}
|
||||
|
||||
SECKEY_DestroySubjectPublicKeyInfo(spki);
|
||||
SECKEY_DestroyPrivateKey(tmpPriv);
|
||||
tls13_DestroyDelegatedCredential(dc);
|
||||
sslBuffer_Clear(&dcBuf);
|
||||
return SECSuccess;
|
||||
|
||||
loser:
|
||||
SECKEY_DestroySubjectPublicKeyInfo(spki);
|
||||
SECKEY_DestroyPrivateKey(tmpPriv);
|
||||
tls13_DestroyDelegatedCredential(dc);
|
||||
sslBuffer_Clear(&dcBuf);
|
||||
|
|
Загрузка…
Ссылка в новой задаче