зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to mozilla-central. a=merge
This commit is contained in:
Коммит
d7222fdc3e
|
@ -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, ¶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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче