Merge inbound to mozilla-central. a=merge

This commit is contained in:
Brindusan Cristian 2019-07-24 06:53:15 +03:00
Родитель 7d49b2491f b979163b23
Коммит d7222fdc3e
21 изменённых файлов: 661 добавлений и 190 удалений

Просмотреть файл

@ -558,15 +558,26 @@ inline int64_t ToInt64(double d) { return ToSignedInteger<int64_t>(d); }
inline uint64_t ToUint64(double d) { return ToUnsignedInteger<uint64_t>(d); }
/**
* The maximum space needed for the null-terminated result of |ToString| on a
* Number (sign, fractional part, "e+", and exponent of at most three digits,
* e.g. |String(-Number.MAX_VALUE)| as "-1.7976931348623157e+308" is length 24).
* An amount of space large enough to store the null-terminated result of
* |ToString| on any Number.
*
* The <https://tc39.es/ecma262/#sec-tostring-applied-to-the-number-type>
* |NumberToString| algorithm is specified in terms of results, not an
* algorithm. It is extremely unclear from the algorithm's definition what its
* longest output can be. |-(2**-19 - 2**-72)| requires 25 + 1 characters and
* is believed to be at least *very close* to the upper bound, so we round that
* *very generously* upward to a 64-bit pointer-size boundary (to be extra
* cautious) and assume that's adequate.
*
* If you can supply better reasoning for a tighter bound, file a bug to improve
* this!
*/
static constexpr size_t MaximumNumberToStringLength = 24 + 1;
static constexpr size_t MaximumNumberToStringLength = 31 + 1;
/**
* Store in |out| the null-terminated, base-10 result of |ToString| applied to
* |d| per <https://tc39.es/ecma262/#sec-tostring-applied-to-the-number-type>.
* (This will produce "NaN", "-Infinity", or "Infinity" for non-finite |d|.)
*/
extern JS_PUBLIC_API void NumberToString(
double d, char (&out)[MaximumNumberToStringLength]);

Просмотреть файл

@ -15,42 +15,45 @@
#include "jsapi-tests/tests.h" // BEGIN_TEST, CHECK_EQUAL, END_TEST
// Need to account for string literals including the \0 at the end.
#define STR(x) x, (mozilla::ArrayLength(x) - 1)
#define REST(x) x, (mozilla::ArrayLength(x) - 1), __LINE__
static const struct NumberToStringTest {
double number;
const char* expected;
size_t expectedLength;
size_t lineno;
} numberToStringTests[] = {
{5e-324, STR("5e-324")}, // 2**-1074
{9.5367431640625e-7, STR("9.5367431640625e-7")}, // 2**-20
{0.0000019073486328125, STR("0.0000019073486328125")}, // 2**-19
{0.000003814697265625, STR("0.000003814697265625")}, // 2**-18
{0.0000057220458984375, STR("0.0000057220458984375")}, // 2**-18 + 2**-19
{0.000244140625, STR("0.000244140625")}, // 2**-12
{0.125, STR("0.125")},
{0.25, STR("0.25")},
{0.5, STR("0.5")},
{1, STR("1")},
{1.5, STR("1.5")},
{2, STR("2")},
{9, STR("9")},
{10, STR("10")},
{15, STR("15")},
{16, STR("16")},
{389427, STR("389427")},
{1073741823, STR("1073741823")},
{1073741824, STR("1073741824")},
{1073741825, STR("1073741825")},
{2147483647, STR("2147483647")},
{2147483648, STR("2147483648")},
{2147483649, STR("2147483649")},
{4294967294, STR("4294967294")},
{4294967295, STR("4294967295")},
{999999999999999900000.0, STR("999999999999999900000")},
{999999999999999900000.0 + 65535, STR("999999999999999900000")},
{999999999999999900000.0 + 65536, STR("1e+21")},
{1.7976931348623157e+308, STR("1.7976931348623157e+308")},
{5e-324, REST("5e-324")}, // 2**-1074
{9.5367431640625e-7, REST("9.5367431640625e-7")}, // 2**-20
{0.0000010984284297360395, REST("0.0000010984284297360395")},
{0.0000019073486328125, REST("0.0000019073486328125")}, // 2**-19
{0.000003814697265625, REST("0.000003814697265625")}, // 2**-18
{0.0000057220458984375, REST("0.0000057220458984375")}, // 2**-18 + 2**-19
{0.000244140625, REST("0.000244140625")}, // 2**-12
{0.125, REST("0.125")},
{0.25, REST("0.25")},
{0.5, REST("0.5")},
{1, REST("1")},
{1.5, REST("1.5")},
{2, REST("2")},
{9, REST("9")},
{10, REST("10")},
{15, REST("15")},
{16, REST("16")},
{389427, REST("389427")},
{1073741823, REST("1073741823")},
{1073741824, REST("1073741824")},
{1073741825, REST("1073741825")},
{2147483647, REST("2147483647")},
{2147483648, REST("2147483648")},
{2147483649, REST("2147483649")},
{4294967294, REST("4294967294")},
{4294967295, REST("4294967295")},
{4294967296, REST("4294967296")},
{999999999999999900000.0, REST("999999999999999900000")},
{999999999999999900000.0 + 65535, REST("999999999999999900000")},
{999999999999999900000.0 + 65536, REST("1e+21")},
{1.7976931348623157e+308, REST("1.7976931348623157e+308")}, // MAX_VALUE
};
static constexpr char PoisonChar = 0x37;
@ -71,17 +74,17 @@ BEGIN_TEST(testNumberToString) {
return false;
}
NumberToStringTest zeroTest = {0.0, STR("0")};
NumberToStringTest zeroTest = {0.0, REST("0")};
if (!testOne(zeroTest, false, storage)) {
return false;
}
NumberToStringTest negativeZeroTest = {-0.0, STR("0")};
NumberToStringTest negativeZeroTest = {-0.0, REST("0")};
if (!testOne(negativeZeroTest, false, storage)) {
return false;
}
NumberToStringTest infTest = {mozilla::PositiveInfinity<double>(),
STR("Infinity")};
REST("Infinity")};
if (!testOne(infTest, false, storage)) {
return false;
}
@ -89,7 +92,7 @@ BEGIN_TEST(testNumberToString) {
return false;
}
NumberToStringTest nanTest = {mozilla::UnspecifiedNaN<double>(), STR("NaN")};
NumberToStringTest nanTest = {mozilla::UnspecifiedNaN<double>(), REST("NaN")};
return testOne(nanTest, false, storage);
}
@ -117,11 +120,15 @@ bool testOne(const NumberToStringTest& test, bool hasMinusSign,
start++;
}
CHECK_EQUAL(memcmp(start, test.expected, test.expectedLength), 0);
CHECK_EQUAL(start[test.expectedLength], '\0');
if (!checkEqual(memcmp(start, test.expected, test.expectedLength), 0, start,
test.expected, __FILE__, test.lineno)) {
return false;
}
return true;
char actualTerminator[] = {start[test.expectedLength], '\0'};
return checkEqual(actualTerminator[0], '\0', actualTerminator, "'\\0'",
__FILE__, test.lineno);
}
END_TEST(testNumberToString)
#undef STR
#undef REST

Просмотреть файл

@ -121,6 +121,11 @@ class JSAPITest {
return JSAPITestString("<<error converting value to string>>");
}
JSAPITestString toSource(char c) {
char buf[2] = {c, '\0'};
return JSAPITestString(buf);
}
JSAPITestString toSource(long v) {
char buf[40];
sprintf(buf, "%ld", v);

Просмотреть файл

@ -33,8 +33,6 @@ Regenerate defaults_disabled.{h,asm} with:
$ grep -E ".*_(INDEV|OUTDEV|DECODER|ENCODER|DEMUXER|MUXER|PARSER|FILTER|HWACCEL|PROTOCOL|ENCODERS|DECODERS|HWACCELS|INDEVS|OUTDEVS|FILTERS|DEMUXERS|MUXERS|PROTOCOLS|BSF) 0" config.h | sort -u > ~/Work/Mozilla/mozilla-central/media/ffvpx/defaults_disabled.h
$ grep -E ".*_(INDEV|OUTDEV|DECODER|ENCODER|DEMUXER|MUXER|PARSER|FILTER|HWACCEL|PROTOCOL|ENCODERS|DECODERS|HWACCELS|INDEVS|OUTDEVS|FILTERS|DEMUXERS|MUXERS|PROTOCOLS|BSF) 0" config.asm | sort -u > ~/Work/Mozilla/mozilla-central/media/ffvpx/defaults_disabled.asm
All new decoders/muxers/encoders/... should be added in the list of dummy functions found in libavcodec/dummy_funcs.c
otherwise linkage will fail on Windows. On other platforms they are optimised out and aren't necessary.
The GNU comm utility is a useful tool to compare and extract only the changes.
To update the source tree, perform a diff on the files listed in FILES.

Просмотреть файл

@ -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, &params,
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);