Bug 1577822 - land NSS NSS_3_47_BETA4 UPGRADE_NSS_RELEASE, r=kjacobs

2019-10-18  Deian Stefan  <deian@cs.ucsd.edu>

	* lib/softoken/pkcs11c.c:
	Bug 1459141 - Rewrite softoken CBC pad check to be constant
	r=jcj,kjacobs

	[d3c8638f85cd] [NSS_3_47_BETA4]

2019-10-17  Kevin Jacobs  <kjacobs@mozilla.com>

	* gtests/pk11_gtest/pk11_cbc_unittest.cc:
	Bug 1589120 - Additional test vectors for CBC padding. r=jcj

	This patch adds more test vectors for AES-CBC and 3DES-CBC padding.

	[7f17b911ac99]

	* gtests/pk11_gtest/manifest.mn,
	gtests/pk11_gtest/pk11_aeskeywrappad_unittest.cc,
	gtests/pk11_gtest/pk11_gtest.gyp:
	Bug 1589120 - Tests for padded AES key wrap r=jcj

	This patch adds test vectors for padded AES Key Wrap. AES-CBC and
	3DES-CBC ports of the same vectors will be included in a separate
	revision.

	[fb4d9b6ea2c4]

2019-10-16  Kevin Jacobs  <kjacobs@mozilla.com>

	* gtests/ssl_gtest/tls_agent.cc, gtests/ssl_gtest/tls_agent.h,
	gtests/ssl_gtest/tls_subcerts_unittest.cc, lib/ssl/ssl3con.c,
	lib/ssl/sslimpl.h, lib/ssl/tls13subcerts.c,
	tests/common/certsetup.sh, tests/ssl_gtests/ssl_gtests.sh:
	Bug 1588244 - SSLExp_DelegateCredential to support 'rsaEncryption'
	end-entity certs with default scheme override r=mt

	If an end-entity cert has an SPKI type of 'rsaEncryption', override
	the DC alg to be `ssl_sig_rsa_pss_rsae_sha256`.

	[93383e0fb833]

2019-10-16  J.C. Jones  <jjones@mozilla.com>

	* .hgtags:
	Added tag NSS_3_47_BETA3 for changeset f10c3e0757b7
	[fa8a67bee2dc]

Differential Revision: https://phabricator.services.mozilla.com/D49774

--HG--
extra : moz-landing-system : lando
This commit is contained in:
J.C. Jones 2019-10-18 17:05:24 +00:00
parent 3812c7138b
commit 00dafac3ef
15 changed files with 708 additions and 65 deletions

View File

@ -1 +1 @@
NSS_3_47_BETA3
NSS_3_47_BETA4

View File

@ -10,4 +10,3 @@
*/
#error "Do not include this header file."

View File

@ -9,6 +9,7 @@ MODULE = nss
CPPSRCS = \
pk11_aes_gcm_unittest.cc \
pk11_aeskeywrap_unittest.cc \
pk11_aeskeywrappad_unittest.cc \
pk11_cbc_unittest.cc \
pk11_chacha20poly1305_unittest.cc \
pk11_curve25519_unittest.cc \

View File

@ -0,0 +1,415 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <memory>
#include "gtest/gtest.h"
#include "nss.h"
#include "nss_scoped_ptrs.h"
#include "pk11pub.h"
namespace nss_test {
class Pkcs11AESKeyWrapPadTest : public ::testing::Test {};
// Encrypt an ephemeral EC key (U2F use case)
TEST_F(Pkcs11AESKeyWrapPadTest, WrapUnwrapECKey) {
const uint32_t kwrappedBufLen = 256;
const uint32_t kPublicKeyLen = 65;
const uint32_t kOidLen = 65;
unsigned char param_buf[kOidLen];
unsigned char unwrap_buf[kPublicKeyLen];
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
ASSERT_NE(nullptr, slot);
SECItem ecdsa_params = {siBuffer, param_buf, sizeof(param_buf)};
SECOidData* oid_data = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1);
ASSERT_NE(oid_data, nullptr);
ecdsa_params.data[0] = SEC_ASN1_OBJECT_ID;
ecdsa_params.data[1] = oid_data->oid.len;
memcpy(ecdsa_params.data + 2, oid_data->oid.data, oid_data->oid.len);
ecdsa_params.len = oid_data->oid.len + 2;
SECKEYPublicKey* pub_tmp;
ScopedSECKEYPublicKey pub_key;
ScopedSECKEYPrivateKey priv_key(
PK11_GenerateKeyPair(slot.get(), CKM_EC_KEY_PAIR_GEN, &ecdsa_params,
&pub_tmp, PR_FALSE, PR_TRUE, nullptr));
ASSERT_NE(nullptr, priv_key);
ASSERT_NE(nullptr, pub_tmp);
pub_key.reset(pub_tmp);
// Generate a KEK.
ScopedPK11SymKey kek(
PK11_KeyGen(slot.get(), CKM_AES_CBC, nullptr, 16, nullptr));
ASSERT_NE(nullptr, kek);
// Wrap the key
ScopedSECItem wrapped(::SECITEM_AllocItem(nullptr, nullptr, kwrappedBufLen));
ScopedSECItem param(PK11_ParamFromIV(CKM_NSS_AES_KEY_WRAP_PAD, nullptr));
SECStatus rv = PK11_WrapPrivKey(slot.get(), kek.get(), priv_key.get(),
CKM_NSS_AES_KEY_WRAP_PAD, param.get(),
wrapped.get(), nullptr);
ASSERT_EQ(rv, SECSuccess);
SECItem pubKey = {siBuffer, unwrap_buf, kPublicKeyLen};
CK_ATTRIBUTE_TYPE usages[] = {CKA_SIGN};
int usageCount = 1;
ScopedSECKEYPrivateKey unwrapped(
PK11_UnwrapPrivKey(slot.get(), kek.get(), CKM_NSS_AES_KEY_WRAP_PAD,
param.get(), wrapped.get(), nullptr, &pubKey, false,
true, CKK_EC, usages, usageCount, nullptr));
ASSERT_EQ(0, PORT_GetError());
ASSERT_TRUE(!!unwrapped);
}
// Encrypt an ephemeral RSA key
TEST_F(Pkcs11AESKeyWrapPadTest, WrapUnwrapRsaKey) {
const uint32_t kwrappedBufLen = 648;
unsigned char unwrap_buf[kwrappedBufLen];
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
ASSERT_NE(nullptr, slot);
PK11RSAGenParams rsa_param;
rsa_param.keySizeInBits = 1024;
rsa_param.pe = 65537L;
SECKEYPublicKey* pub_tmp;
ScopedSECKEYPublicKey pub_key;
ScopedSECKEYPrivateKey priv_key(
PK11_GenerateKeyPair(slot.get(), CKM_RSA_PKCS_KEY_PAIR_GEN, &rsa_param,
&pub_tmp, PR_FALSE, PR_FALSE, nullptr));
ASSERT_NE(nullptr, priv_key);
ASSERT_NE(nullptr, pub_tmp);
pub_key.reset(pub_tmp);
// Generate a KEK.
ScopedPK11SymKey kek(
PK11_KeyGen(slot.get(), CKM_AES_CBC, nullptr, 16, nullptr));
ASSERT_NE(nullptr, kek);
// Wrap the key
ScopedSECItem wrapped(::SECITEM_AllocItem(nullptr, nullptr, kwrappedBufLen));
ScopedSECItem param(PK11_ParamFromIV(CKM_NSS_AES_KEY_WRAP_PAD, nullptr));
SECStatus rv = PK11_WrapPrivKey(slot.get(), kek.get(), priv_key.get(),
CKM_NSS_AES_KEY_WRAP_PAD, param.get(),
wrapped.get(), nullptr);
ASSERT_EQ(rv, SECSuccess);
SECItem pubKey = {siBuffer, unwrap_buf, kwrappedBufLen};
CK_ATTRIBUTE_TYPE usages[] = {CKA_SIGN};
int usageCount = 1;
ScopedSECKEYPrivateKey unwrapped(
PK11_UnwrapPrivKey(slot.get(), kek.get(), CKM_NSS_AES_KEY_WRAP_PAD,
param.get(), wrapped.get(), nullptr, &pubKey, false,
false, CKK_EC, usages, usageCount, nullptr));
ASSERT_EQ(0, PORT_GetError());
ASSERT_TRUE(!!unwrapped);
ScopedSECItem priv_key_data(
PK11_ExportDERPrivateKeyInfo(priv_key.get(), nullptr));
ScopedSECItem unwrapped_data(
PK11_ExportDERPrivateKeyInfo(unwrapped.get(), nullptr));
EXPECT_TRUE(!!priv_key_data);
EXPECT_TRUE(!!unwrapped_data);
ASSERT_EQ(priv_key_data->len, unwrapped_data->len);
ASSERT_EQ(
0, memcmp(priv_key_data->data, unwrapped_data->data, priv_key_data->len));
}
// Wrap a random that's a multiple of the block size, and compare the unwrap
// result.
TEST_F(Pkcs11AESKeyWrapPadTest, WrapUnwrapRandom_EvenBlock) {
const uint32_t kInputKeyLen = 128;
uint32_t out_len = 0;
std::vector<unsigned char> input_key(kInputKeyLen);
std::vector<unsigned char> wrapped_key(
kInputKeyLen + AES_BLOCK_SIZE); // One block of padding
std::vector<unsigned char> unwrapped_key(
kInputKeyLen + AES_BLOCK_SIZE); // One block of padding
// Generate input key material
SECStatus rv = PK11_GenerateRandom(input_key.data(), input_key.size());
EXPECT_EQ(SECSuccess, rv);
// Generate a KEK.
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
ASSERT_NE(nullptr, slot);
ScopedPK11SymKey kek(
PK11_KeyGen(slot.get(), CKM_AES_CBC, nullptr, 16, nullptr));
ASSERT_NE(nullptr, kek);
// Wrap the key
rv = PK11_Encrypt(kek.get(), CKM_NSS_AES_KEY_WRAP_PAD, /* param */ nullptr,
wrapped_key.data(), &out_len,
static_cast<unsigned int>(wrapped_key.size()),
input_key.data(),
static_cast<unsigned int>(input_key.size()));
ASSERT_EQ(SECSuccess, rv);
rv = PK11_Decrypt(kek.get(), CKM_NSS_AES_KEY_WRAP_PAD, /* param */ nullptr,
unwrapped_key.data(), &out_len,
static_cast<unsigned int>(unwrapped_key.size()),
wrapped_key.data(), out_len);
ASSERT_EQ(SECSuccess, rv);
ASSERT_EQ(input_key.size(), out_len);
ASSERT_EQ(0, memcmp(input_key.data(), unwrapped_key.data(), out_len));
}
// Wrap a random that's NOT a multiple of the block size, and compare the unwrap
// result.
TEST_F(Pkcs11AESKeyWrapPadTest, WrapUnwrapRandom_OddBlock1) {
const uint32_t kInputKeyLen = 65;
uint32_t out_len = 0;
std::vector<unsigned char> input_key(kInputKeyLen);
std::vector<unsigned char> wrapped_key(
kInputKeyLen + AES_BLOCK_SIZE); // One block of padding
std::vector<unsigned char> unwrapped_key(
kInputKeyLen + AES_BLOCK_SIZE); // One block of padding
// Generate input key material
SECStatus rv = PK11_GenerateRandom(input_key.data(), input_key.size());
EXPECT_EQ(SECSuccess, rv);
// Generate a KEK.
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
ASSERT_NE(nullptr, slot);
ScopedPK11SymKey kek(
PK11_KeyGen(slot.get(), CKM_AES_CBC, nullptr, 16, nullptr));
ASSERT_NE(nullptr, kek);
// Wrap the key
rv = PK11_Encrypt(kek.get(), CKM_NSS_AES_KEY_WRAP_PAD, /* param */ nullptr,
wrapped_key.data(), &out_len,
static_cast<unsigned int>(wrapped_key.size()),
input_key.data(),
static_cast<unsigned int>(input_key.size()));
ASSERT_EQ(SECSuccess, rv);
rv = PK11_Decrypt(kek.get(), CKM_NSS_AES_KEY_WRAP_PAD, /* param */ nullptr,
unwrapped_key.data(), &out_len,
static_cast<unsigned int>(unwrapped_key.size()),
wrapped_key.data(), out_len);
ASSERT_EQ(SECSuccess, rv);
ASSERT_EQ(input_key.size(), out_len);
ASSERT_EQ(0, memcmp(input_key.data(), unwrapped_key.data(), out_len));
}
// Wrap a random that's NOT a multiple of the block size, and compare the unwrap
// result.
TEST_F(Pkcs11AESKeyWrapPadTest, WrapUnwrapRandom_OddBlock2) {
const uint32_t kInputKeyLen = 63;
uint32_t out_len = 0;
std::vector<unsigned char> input_key(kInputKeyLen);
std::vector<unsigned char> wrapped_key(
kInputKeyLen + AES_BLOCK_SIZE); // One block of padding
std::vector<unsigned char> unwrapped_key(
kInputKeyLen + AES_BLOCK_SIZE); // One block of padding
// Generate input key material
SECStatus rv = PK11_GenerateRandom(input_key.data(), input_key.size());
EXPECT_EQ(SECSuccess, rv);
// Generate a KEK.
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
ASSERT_NE(nullptr, slot);
ScopedPK11SymKey kek(
PK11_KeyGen(slot.get(), CKM_AES_CBC, nullptr, 16, nullptr));
ASSERT_NE(nullptr, kek);
// Wrap the key
rv = PK11_Encrypt(kek.get(), CKM_NSS_AES_KEY_WRAP_PAD, /* param */ nullptr,
wrapped_key.data(), &out_len, wrapped_key.size(),
input_key.data(), input_key.size());
ASSERT_EQ(SECSuccess, rv);
rv = PK11_Decrypt(kek.get(), CKM_NSS_AES_KEY_WRAP_PAD, /* param */ nullptr,
unwrapped_key.data(), &out_len,
static_cast<unsigned int>(unwrapped_key.size()),
wrapped_key.data(), out_len);
ASSERT_EQ(SECSuccess, rv);
ASSERT_EQ(input_key.size(), out_len);
ASSERT_EQ(0, memcmp(input_key.data(), unwrapped_key.data(), out_len));
}
// Invalid long padding (over the block size, but otherwise valid)
TEST_F(Pkcs11AESKeyWrapPadTest, WrapUnwrapRandom_PaddingTooLong) {
const uint32_t kInputKeyLen = 32;
uint32_t out_len = 0;
// Apply our own padding
const unsigned char buf[32] = {
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
std::vector<unsigned char> wrapped_key(kInputKeyLen + AES_BLOCK_SIZE);
std::vector<unsigned char> unwrapped_key(kInputKeyLen + AES_BLOCK_SIZE);
// Generate a KEK.
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
ASSERT_NE(nullptr, slot);
ScopedPK11SymKey kek(
PK11_KeyGen(slot.get(), CKM_AES_CBC, nullptr, 16, nullptr));
ASSERT_NE(nullptr, kek);
// Wrap the key
SECStatus rv =
PK11_Encrypt(kek.get(), CKM_NSS_AES_KEY_WRAP, // Don't apply more padding
/* param */ nullptr, wrapped_key.data(), &out_len,
wrapped_key.size(), buf, sizeof(buf));
ASSERT_EQ(SECSuccess, rv);
rv = PK11_Decrypt(kek.get(), CKM_NSS_AES_KEY_WRAP_PAD, /* param */ nullptr,
unwrapped_key.data(), &out_len,
static_cast<unsigned int>(unwrapped_key.size()),
wrapped_key.data(), out_len);
ASSERT_EQ(SECFailure, rv);
}
// Invalid 0-length padding (there should be a full block if the message doesn't
// need to be padded)
TEST_F(Pkcs11AESKeyWrapPadTest, WrapUnwrapRandom_NoPadding) {
const uint32_t kInputKeyLen = 32;
uint32_t out_len = 0;
// Apply our own padding
const unsigned char buf[32] = {0};
std::vector<unsigned char> wrapped_key(kInputKeyLen + AES_BLOCK_SIZE);
std::vector<unsigned char> unwrapped_key(kInputKeyLen + AES_BLOCK_SIZE);
// Generate a KEK.
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
ASSERT_NE(nullptr, slot);
ScopedPK11SymKey kek(
PK11_KeyGen(slot.get(), CKM_AES_CBC, nullptr, 16, nullptr));
ASSERT_NE(nullptr, kek);
// Wrap the key
SECStatus rv =
PK11_Encrypt(kek.get(), CKM_NSS_AES_KEY_WRAP, // Don't apply more padding
/* param */ nullptr, wrapped_key.data(), &out_len,
wrapped_key.size(), buf, sizeof(buf));
ASSERT_EQ(SECSuccess, rv);
rv = PK11_Decrypt(kek.get(), CKM_NSS_AES_KEY_WRAP_PAD, /* param */ nullptr,
unwrapped_key.data(), &out_len,
static_cast<unsigned int>(unwrapped_key.size()),
wrapped_key.data(), out_len);
ASSERT_EQ(SECFailure, rv);
}
// Invalid padding
TEST_F(Pkcs11AESKeyWrapPadTest, WrapUnwrapRandom_BadPadding1) {
const uint32_t kInputKeyLen = 32;
uint32_t out_len = 0;
// Apply our own padding
const unsigned char buf[32] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08}; // Check all 8 bytes
std::vector<unsigned char> wrapped_key(kInputKeyLen + AES_BLOCK_SIZE);
std::vector<unsigned char> unwrapped_key(kInputKeyLen + AES_BLOCK_SIZE);
// Generate a KEK.
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
ASSERT_NE(nullptr, slot);
ScopedPK11SymKey kek(
PK11_KeyGen(slot.get(), CKM_AES_CBC, nullptr, 16, nullptr));
ASSERT_NE(nullptr, kek);
// Wrap the key
SECStatus rv =
PK11_Encrypt(kek.get(), CKM_NSS_AES_KEY_WRAP, // Don't apply more padding
/* param */ nullptr, wrapped_key.data(), &out_len,
wrapped_key.size(), buf, sizeof(buf));
ASSERT_EQ(SECSuccess, rv);
rv = PK11_Decrypt(kek.get(), CKM_NSS_AES_KEY_WRAP_PAD, /* param */ nullptr,
unwrapped_key.data(), &out_len,
static_cast<unsigned int>(unwrapped_key.size()),
wrapped_key.data(), out_len);
ASSERT_EQ(SECFailure, rv);
}
// Invalid padding
TEST_F(Pkcs11AESKeyWrapPadTest, WrapUnwrapRandom_BadPadding2) {
const uint32_t kInputKeyLen = 32;
uint32_t out_len = 0;
// Apply our own padding
const unsigned char
buf[32] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x02}; // Check first loop repeat
std::vector<unsigned char> wrapped_key(kInputKeyLen + AES_BLOCK_SIZE);
std::vector<unsigned char> unwrapped_key(kInputKeyLen + AES_BLOCK_SIZE);
// Generate a KEK.
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
ASSERT_NE(nullptr, slot);
ScopedPK11SymKey kek(
PK11_KeyGen(slot.get(), CKM_AES_CBC, nullptr, 16, nullptr));
ASSERT_NE(nullptr, kek);
// Wrap the key
SECStatus rv =
PK11_Encrypt(kek.get(), CKM_NSS_AES_KEY_WRAP, // Don't apply more padding
/* param */ nullptr, wrapped_key.data(), &out_len,
wrapped_key.size(), buf, sizeof(buf));
ASSERT_EQ(SECSuccess, rv);
rv = PK11_Decrypt(kek.get(), CKM_NSS_AES_KEY_WRAP_PAD, /* param */ nullptr,
unwrapped_key.data(), &out_len,
static_cast<unsigned int>(unwrapped_key.size()),
wrapped_key.data(), out_len);
ASSERT_EQ(SECFailure, rv);
}
// Minimum valid padding
TEST_F(Pkcs11AESKeyWrapPadTest, WrapUnwrapRandom_ShortValidPadding) {
const uint32_t kInputKeyLen = 32;
uint32_t out_len = 0;
// Apply our own padding
const unsigned char buf[kInputKeyLen] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; // Minimum
std::vector<unsigned char> wrapped_key(kInputKeyLen + AES_BLOCK_SIZE);
std::vector<unsigned char> unwrapped_key(kInputKeyLen + AES_BLOCK_SIZE);
// Generate a KEK.
ScopedPK11SlotInfo slot(PK11_GetInternalSlot());
ASSERT_NE(nullptr, slot);
ScopedPK11SymKey kek(
PK11_KeyGen(slot.get(), CKM_AES_CBC, nullptr, 16, nullptr));
ASSERT_NE(nullptr, kek);
// Wrap the key
SECStatus rv =
PK11_Encrypt(kek.get(), CKM_NSS_AES_KEY_WRAP, // Don't apply more padding
/* param */ nullptr, wrapped_key.data(), &out_len,
wrapped_key.size(), buf, sizeof(buf));
ASSERT_EQ(SECSuccess, rv);
rv = PK11_Decrypt(kek.get(), CKM_NSS_AES_KEY_WRAP_PAD, /* param */ nullptr,
unwrapped_key.data(), &out_len,
static_cast<unsigned int>(unwrapped_key.size()),
wrapped_key.data(), out_len);
ASSERT_EQ(SECSuccess, rv);
ASSERT_EQ(kInputKeyLen - 1, out_len);
ASSERT_EQ(0, memcmp(buf, unwrapped_key.data(), out_len));
}
} /* nss_test */

View File

@ -41,6 +41,17 @@ class Pkcs11CbcPadTest : public ::testing::TestWithParam<CK_MECHANISM_TYPE> {
}
return false;
}
uint32_t GetUnpaddedParam() const {
switch (GetParam()) {
case CKM_AES_CBC_PAD:
return CKM_AES_CBC;
case CKM_DES3_CBC_PAD:
return CKM_DES3_CBC;
default:
ADD_FAILURE() << "Unknown padded mechanism " << GetParam();
}
return 0;
}
size_t block_size() const {
return static_cast<size_t>(PK11_GetBlockSize(GetParam(), nullptr));
@ -340,6 +351,139 @@ TEST_P(Pkcs11CbcPadTest, ContextFailDecryptInvalidBlockSize) {
EXPECT_EQ(0, output_len) << "output_len is reset";
}
TEST_P(Pkcs11CbcPadTest, EncryptDecrypt_PaddingTooLong) {
if (!is_padded()) {
return;
}
// Padding that's over the block size
const std::vector<uint8_t> input = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
std::vector<uint8_t> encrypted(input.size());
uint32_t encrypted_len = 0;
ScopedPK11SymKey ek = MakeKey(CKA_ENCRYPT);
SECStatus rv = PK11_Encrypt(ek.get(), GetUnpaddedParam(), GetIv(),
encrypted.data(), &encrypted_len,
encrypted.size(), input.data(), input.size());
ASSERT_EQ(SECSuccess, rv);
EXPECT_EQ(input.size(), encrypted_len);
std::vector<uint8_t> decrypted(input.size());
uint32_t decrypted_len = 0;
ScopedPK11SymKey dk = MakeKey(CKA_DECRYPT);
rv = PK11_Decrypt(dk.get(), GetParam(), GetIv(), decrypted.data(),
&decrypted_len, decrypted.size(), encrypted.data(),
encrypted_len);
EXPECT_EQ(SECFailure, rv);
EXPECT_EQ(0U, decrypted_len);
}
TEST_P(Pkcs11CbcPadTest, EncryptDecrypt_BadPadding1) {
if (!is_padded()) {
return;
}
// Padding that's one byte short
const std::vector<uint8_t> input = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
std::vector<uint8_t> encrypted(input.size());
uint32_t encrypted_len = 0;
ScopedPK11SymKey ek = MakeKey(CKA_ENCRYPT);
SECStatus rv = PK11_Encrypt(ek.get(), GetUnpaddedParam(), GetIv(),
encrypted.data(), &encrypted_len,
encrypted.size(), input.data(), input.size());
ASSERT_EQ(SECSuccess, rv);
EXPECT_EQ(input.size(), encrypted_len);
std::vector<uint8_t> decrypted(input.size());
uint32_t decrypted_len = 0;
ScopedPK11SymKey dk = MakeKey(CKA_DECRYPT);
rv = PK11_Decrypt(dk.get(), GetParam(), GetIv(), decrypted.data(),
&decrypted_len, decrypted.size(), encrypted.data(),
encrypted_len);
EXPECT_EQ(SECFailure, rv);
EXPECT_EQ(0U, decrypted_len);
}
TEST_P(Pkcs11CbcPadTest, EncryptDecrypt_BadPadding2) {
if (!is_padded()) {
return;
}
// Padding that's one byte short
const std::vector<uint8_t> input = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02};
std::vector<uint8_t> encrypted(input.size());
uint32_t encrypted_len = 0;
ScopedPK11SymKey ek = MakeKey(CKA_ENCRYPT);
SECStatus rv = PK11_Encrypt(ek.get(), GetUnpaddedParam(), GetIv(),
encrypted.data(), &encrypted_len,
encrypted.size(), input.data(), input.size());
ASSERT_EQ(SECSuccess, rv);
EXPECT_EQ(input.size(), encrypted_len);
std::vector<uint8_t> decrypted(input.size());
uint32_t decrypted_len = 0;
ScopedPK11SymKey dk = MakeKey(CKA_DECRYPT);
rv = PK11_Decrypt(dk.get(), GetParam(), GetIv(), decrypted.data(),
&decrypted_len, decrypted.size(), encrypted.data(),
encrypted_len);
EXPECT_EQ(SECFailure, rv);
EXPECT_EQ(0U, decrypted_len);
}
TEST_P(Pkcs11CbcPadTest, EncryptDecrypt_ShortValidPadding) {
if (!is_padded()) {
return;
}
// Minimal valid padding
const std::vector<uint8_t> input = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
std::vector<uint8_t> encrypted(input.size());
uint32_t encrypted_len = 0;
ScopedPK11SymKey ek = MakeKey(CKA_ENCRYPT);
SECStatus rv = PK11_Encrypt(ek.get(), GetUnpaddedParam(), GetIv(),
encrypted.data(), &encrypted_len,
encrypted.size(), input.data(), input.size());
ASSERT_EQ(SECSuccess, rv);
EXPECT_EQ(input.size(), encrypted_len);
std::vector<uint8_t> decrypted(input.size());
uint32_t decrypted_len = 0;
ScopedPK11SymKey dk = MakeKey(CKA_DECRYPT);
rv = PK11_Decrypt(dk.get(), GetParam(), GetIv(), decrypted.data(),
&decrypted_len, decrypted.size(), encrypted.data(),
encrypted_len);
EXPECT_EQ(SECSuccess, rv);
EXPECT_EQ(input.size() - 1, decrypted_len);
EXPECT_EQ(0, memcmp(decrypted.data(), input.data(), decrypted_len));
}
INSTANTIATE_TEST_CASE_P(EncryptDecrypt, Pkcs11CbcPadTest,
::testing::Values(CKM_AES_CBC_PAD, CKM_AES_CBC,
CKM_DES3_CBC_PAD, CKM_DES3_CBC));

View File

@ -14,6 +14,7 @@
'pk11_aes_cmac_unittest.cc',
'pk11_aes_gcm_unittest.cc',
'pk11_aeskeywrap_unittest.cc',
'pk11_aeskeywrappad_unittest.cc',
'pk11_cbc_unittest.cc',
'pk11_chacha20poly1305_unittest.cc',
'pk11_cipherop_unittest.cc',

View File

@ -48,6 +48,7 @@ const std::string TlsAgent::kServerEcdhRsa = "ecdh_rsa";
const std::string TlsAgent::kServerEcdhEcdsa = "ecdh_ecdsa";
const std::string TlsAgent::kServerDsa = "dsa";
const std::string TlsAgent::kDelegatorEcdsa256 = "delegator_ecdsa256";
const std::string TlsAgent::kDelegatorRsae2048 = "delegator_rsae2048";
static const uint8_t kCannedTls13ServerHello[] = {
0x03, 0x03, 0x9c, 0xbc, 0x14, 0x9b, 0x0e, 0x2e, 0xfa, 0x0d, 0xf3,

View File

@ -77,6 +77,7 @@ class TlsAgent : public PollTarget {
static const std::string kServerEcdhRsa;
static const std::string kServerDsa;
static const std::string kDelegatorEcdsa256; // draft-ietf-tls-subcerts
static const std::string kDelegatorRsae2048; // draft-ietf-tls-subcerts
TlsAgent(const std::string& name, Role role, SSLProtocolVariant variant);
virtual ~TlsAgent();

View File

@ -16,7 +16,8 @@
namespace nss_test {
const std::string kDelegatorId = TlsAgent::kDelegatorEcdsa256;
const std::string kEcdsaDelegatorId = TlsAgent::kDelegatorEcdsa256;
const std::string kRsaeDelegatorId = TlsAgent::kDelegatorRsae2048;
const std::string kDCId = TlsAgent::kServerEcdsa256;
const SSLSignatureScheme kDCScheme = ssl_sig_ecdsa_secp256r1_sha256;
const PRUint32 kDCValidFor = 60 * 60 * 24 * 7 /* 1 week (seconds */;
@ -37,27 +38,27 @@ TEST_P(TlsConnectTls13, DCNotConfigured) {
EXPECT_TRUE(TlsAgent::LoadKeyPairFromCert(kDCId, &pub, &priv));
StackSECItem dc;
TlsAgent::DelegateCredential(kDelegatorId, pub, kDCScheme, kDCValidFor, now(),
&dc);
TlsAgent::DelegateCredential(kEcdsaDelegatorId, pub, kDCScheme, kDCValidFor,
now(), &dc);
// Attempt to install the certificate and DC with a missing DC private key.
EnsureTlsSetup();
SSLExtraServerCertData extra_data_missing_dc_priv_key = {
ssl_auth_null, nullptr, nullptr, nullptr, &dc, nullptr};
EXPECT_FALSE(server_->ConfigServerCert(kDelegatorId, true,
EXPECT_FALSE(server_->ConfigServerCert(kEcdsaDelegatorId, true,
&extra_data_missing_dc_priv_key));
// Attempt to install the certificate and with only the DC private key.
EnsureTlsSetup();
SSLExtraServerCertData extra_data_missing_dc = {
ssl_auth_null, nullptr, nullptr, nullptr, nullptr, priv.get()};
EXPECT_FALSE(
server_->ConfigServerCert(kDelegatorId, true, &extra_data_missing_dc));
EXPECT_FALSE(server_->ConfigServerCert(kEcdsaDelegatorId, true,
&extra_data_missing_dc));
}
// Connected with ECDSA-P256.
TEST_P(TlsConnectTls13, DCConnectEcdsaP256) {
Reset(kDelegatorId);
Reset(kEcdsaDelegatorId);
client_->EnableDelegatedCredentials();
server_->AddDelegatedCredential(TlsAgent::kServerEcdsa256,
ssl_sig_ecdsa_secp256r1_sha256, kDCValidFor,
@ -74,7 +75,7 @@ TEST_P(TlsConnectTls13, DCConnectEcdsaP256) {
// Connected with ECDSA-P521.
TEST_P(TlsConnectTls13, DCConnectEcdsaP521) {
Reset(kDelegatorId);
Reset(kEcdsaDelegatorId);
client_->EnableDelegatedCredentials();
server_->AddDelegatedCredential(TlsAgent::kServerEcdsa521,
ssl_sig_ecdsa_secp521r1_sha512, kDCValidFor,
@ -90,9 +91,9 @@ TEST_P(TlsConnectTls13, DCConnectEcdsaP521) {
EXPECT_EQ(ssl_sig_ecdsa_secp521r1_sha512, client_->info().signatureScheme);
}
// Connected with RSA-PSS, using an RSAE SPKI.
// Connected with RSA-PSS, using an RSAE DC SPKI.
TEST_P(TlsConnectTls13, DCConnectRsaPssRsae) {
Reset(kDelegatorId);
Reset(kEcdsaDelegatorId);
client_->EnableDelegatedCredentials();
server_->AddDelegatedCredential(
TlsAgent::kServerRsaPss, ssl_sig_rsa_pss_rsae_sha256, kDCValidFor, now());
@ -106,9 +107,31 @@ TEST_P(TlsConnectTls13, DCConnectRsaPssRsae) {
EXPECT_EQ(ssl_sig_rsa_pss_rsae_sha256, client_->info().signatureScheme);
}
// Connected with RSA-PSS, using a RSAE Delegator SPKI.
TEST_P(TlsConnectTls13, DCConnectRsaeDelegator) {
Reset(kRsaeDelegatorId);
static const SSLSignatureScheme kSchemes[] = {ssl_sig_rsa_pss_rsae_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);
}
// Connected with RSA-PSS, using a PSS SPKI.
TEST_P(TlsConnectTls13, DCConnectRsaPssPss) {
Reset(kDelegatorId);
Reset(kEcdsaDelegatorId);
// Need to enable PSS-PSS, which is not on by default.
static const SSLSignatureScheme kSchemes[] = {ssl_sig_ecdsa_secp256r1_sha256,
@ -172,7 +195,7 @@ static void GenerateWeakRsaKey(ScopedSECKEYPrivateKey& priv,
// Fail to connect with a weak RSA key.
TEST_P(TlsConnectTls13, DCWeakKey) {
Reset(kDelegatorId);
Reset(kEcdsaDelegatorId);
EnsureTlsSetup();
ScopedSECKEYPrivateKey dc_priv;
@ -182,14 +205,14 @@ TEST_P(TlsConnectTls13, DCWeakKey) {
// Construct a DC.
StackSECItem dc;
TlsAgent::DelegateCredential(kDelegatorId, dc_pub,
TlsAgent::DelegateCredential(kEcdsaDelegatorId, 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));
EXPECT_TRUE(server_->ConfigServerCert(kEcdsaDelegatorId, true, &extra_data));
client_->EnableDelegatedCredentials();
@ -215,7 +238,7 @@ class ReplaceDCSigScheme : public TlsHandshakeFilter {
// Aborted because of incorrect DC signature algorithm indication.
TEST_P(TlsConnectTls13, DCAbortBadExpectedCertVerifyAlg) {
Reset(kDelegatorId);
Reset(kEcdsaDelegatorId);
client_->EnableDelegatedCredentials();
server_->AddDelegatedCredential(TlsAgent::kServerEcdsa256,
ssl_sig_ecdsa_secp256r1_sha256, kDCValidFor,
@ -229,7 +252,7 @@ TEST_P(TlsConnectTls13, DCAbortBadExpectedCertVerifyAlg) {
// Aborted because of invalid DC signature.
TEST_P(TlsConnectTls13, DCAbortBadSignature) {
Reset(kDelegatorId);
Reset(kEcdsaDelegatorId);
EnsureTlsSetup();
client_->EnableDelegatedCredentials();
@ -238,8 +261,8 @@ TEST_P(TlsConnectTls13, DCAbortBadSignature) {
EXPECT_TRUE(TlsAgent::LoadKeyPairFromCert(kDCId, &pub, &priv));
StackSECItem dc;
TlsAgent::DelegateCredential(kDelegatorId, pub, kDCScheme, kDCValidFor, now(),
&dc);
TlsAgent::DelegateCredential(kEcdsaDelegatorId, pub, kDCScheme, kDCValidFor,
now(), &dc);
ASSERT_TRUE(dc.data != nullptr);
// Flip the first bit of the DC so that the signature is invalid.
@ -247,7 +270,7 @@ TEST_P(TlsConnectTls13, DCAbortBadSignature) {
SSLExtraServerCertData extra_data = {ssl_auth_null, nullptr, nullptr,
nullptr, &dc, priv.get()};
EXPECT_TRUE(server_->ConfigServerCert(kDelegatorId, true, &extra_data));
EXPECT_TRUE(server_->ConfigServerCert(kEcdsaDelegatorId, true, &extra_data));
ConnectExpectAlert(client_, kTlsAlertIllegalParameter);
client_->CheckErrorCode(SSL_ERROR_DC_BAD_SIGNATURE);
@ -256,7 +279,7 @@ TEST_P(TlsConnectTls13, DCAbortBadSignature) {
// Aborted because of expired DC.
TEST_P(TlsConnectTls13, DCAbortExpired) {
Reset(kDelegatorId);
Reset(kEcdsaDelegatorId);
server_->AddDelegatedCredential(kDCId, kDCScheme, kDCValidFor, now());
client_->EnableDelegatedCredentials();
// When the client checks the time, it will be at least one second after the
@ -278,7 +301,7 @@ TEST_P(TlsConnectTls13, DCAbortBadKeyUsage) {
// Connected without DC because of no client indication.
TEST_P(TlsConnectTls13, DCConnectNoClientSupport) {
Reset(kDelegatorId);
Reset(kEcdsaDelegatorId);
server_->AddDelegatedCredential(kDCId, kDCScheme, kDCValidFor, now());
auto cfilter = MakeTlsFilter<TlsExtensionCapture>(
@ -291,7 +314,7 @@ TEST_P(TlsConnectTls13, DCConnectNoClientSupport) {
// Connected without DC because of no server DC.
TEST_P(TlsConnectTls13, DCConnectNoServerSupport) {
Reset(kDelegatorId);
Reset(kEcdsaDelegatorId);
client_->EnableDelegatedCredentials();
auto cfilter = MakeTlsFilter<TlsExtensionCapture>(
@ -304,7 +327,7 @@ TEST_P(TlsConnectTls13, DCConnectNoServerSupport) {
// Connected without DC because client doesn't support TLS 1.3.
TEST_P(TlsConnectTls13, DCConnectClientNoTls13) {
Reset(kDelegatorId);
Reset(kEcdsaDelegatorId);
client_->EnableDelegatedCredentials();
server_->AddDelegatedCredential(kDCId, kDCScheme, kDCValidFor, now());
@ -324,7 +347,7 @@ TEST_P(TlsConnectTls13, DCConnectClientNoTls13) {
// Connected without DC because server doesn't support TLS 1.3.
TEST_P(TlsConnectTls13, DCConnectServerNoTls13) {
Reset(kDelegatorId);
Reset(kEcdsaDelegatorId);
client_->EnableDelegatedCredentials();
server_->AddDelegatedCredential(kDCId, kDCScheme, kDCValidFor, now());
@ -345,7 +368,7 @@ TEST_P(TlsConnectTls13, DCConnectServerNoTls13) {
// Connected without DC because client doesn't support the signature scheme.
TEST_P(TlsConnectTls13, DCConnectExpectedCertVerifyAlgNotSupported) {
Reset(kDelegatorId);
Reset(kEcdsaDelegatorId);
client_->EnableDelegatedCredentials();
static const SSLSignatureScheme kClientSchemes[] = {
ssl_sig_ecdsa_secp256r1_sha256,
@ -371,7 +394,7 @@ TEST_F(DCDelegation, DCDelegations) {
PRTime now = PR_Now();
ScopedCERTCertificate cert;
ScopedSECKEYPrivateKey priv;
ASSERT_TRUE(TlsAgent::LoadCertificate(kDelegatorId, &cert, &priv));
ASSERT_TRUE(TlsAgent::LoadCertificate(kEcdsaDelegatorId, &cert, &priv));
ScopedSECKEYPublicKey pub_rsa;
ScopedSECKEYPrivateKey priv_rsa;

View File

@ -1605,6 +1605,68 @@ NSC_DecryptUpdate(CK_SESSION_HANDLE hSession,
return CKR_OK;
}
/* From ssl3con.c: Constant-time helper macro that copies the MSB of x to all
* other bits. */
#define DUPLICATE_MSB_TO_ALL(x) ((unsigned int)((int)(x) >> (sizeof(int) * 8 - 1)))
/* CK_RVToMask returns, in constant time, a mask value of
* all ones if rv == CKR_OK. Otherwise it returns zero. */
static unsigned int
CK_RVToMask(CK_RV rv)
{
unsigned int good;
/* rv ^ CKR_OK is zero iff rv == CKR_OK. Subtracting one results
* in the MSB being set to one iff it was zero before. */
good = rv ^ CKR_OK;
good--;
return DUPLICATE_MSB_TO_ALL(good);
}
/* Constant-time helper macro that selects l or r depending on all-1 or all-0
* mask m */
#define CT_SEL(m, l, r) (((m) & (l)) | (~(m) & (r)))
/* Constant-time helper macro that returns all-1s if x is not 0; and all-0s
* otherwise. */
#define CT_NOT_ZERO(x) (DUPLICATE_MSB_TO_ALL(((x) | (0 - x))))
/* sftk_CheckCBCPadding checks, in constant time, the padding validity and
* accordingly sets the pad length. */
static CK_RV
sftk_CheckCBCPadding(CK_BYTE_PTR pLastPart,
unsigned int blockSize, unsigned int *outPadSize)
{
PORT_Assert(outPadSize);
unsigned int padSize = (unsigned int)pLastPart[blockSize - 1];
/* If padSize <= blockSize, set goodPad to all-1s and all-0s otherwise.*/
unsigned int goodPad = DUPLICATE_MSB_TO_ALL(~(blockSize - padSize));
/* padSize should not be 0 */
goodPad &= CT_NOT_ZERO(padSize);
unsigned int i;
for (i = 0; i < blockSize; i++) {
/* If i < padSize, set loopMask to all-1s and all-0s otherwise.*/
unsigned int loopMask = DUPLICATE_MSB_TO_ALL(~(padSize - 1 - i));
/* Get the padding value (should be padSize) from buffer */
unsigned int padVal = pLastPart[blockSize - 1 - i];
/* Update goodPad only if i < padSize */
goodPad &= CT_SEL(loopMask, ~(padVal ^ padSize), goodPad);
}
/* If any of the final padding bytes had the wrong value, one or more
* of the lower eight bits of |goodPad| will be cleared. We AND the
* bottom 8 bits together and duplicate the result to all the bits. */
goodPad &= goodPad >> 4;
goodPad &= goodPad >> 2;
goodPad &= goodPad >> 1;
goodPad <<= sizeof(goodPad) * 8 - 1;
goodPad = DUPLICATE_MSB_TO_ALL(goodPad);
/* Set outPadSize to padSize or 0 */
*outPadSize = CT_SEL(goodPad, padSize, 0);
/* Return OK if the pad is valid */
return CT_SEL(goodPad, CKR_OK, CKR_ENCRYPTED_DATA_INVALID);
}
/* NSC_DecryptFinal finishes a multiple-part decryption operation. */
CK_RV
NSC_DecryptFinal(CK_SESSION_HANDLE hSession,
@ -1643,24 +1705,10 @@ NSC_DecryptFinal(CK_SESSION_HANDLE hSession,
if (rv != SECSuccess) {
crv = sftk_MapDecryptError(PORT_GetError());
} else {
unsigned int padSize =
(unsigned int)pLastPart[context->blockSize - 1];
if ((padSize > context->blockSize) || (padSize == 0)) {
crv = CKR_ENCRYPTED_DATA_INVALID;
} else {
unsigned int i;
unsigned int badPadding = 0; /* used as a boolean */
for (i = 0; i < padSize; i++) {
badPadding |=
(unsigned int)pLastPart[context->blockSize - 1 - i] ^
padSize;
}
if (badPadding) {
crv = CKR_ENCRYPTED_DATA_INVALID;
} else {
*pulLastPartLen = outlen - padSize;
}
}
unsigned int padSize = 0;
crv = sftk_CheckCBCPadding(&pLastPart[outlen - context->blockSize], context->blockSize, &padSize);
/* Update pulLastPartLen, in constant time, if crv is OK */
*pulLastPartLen = CT_SEL(CK_RVToMask(crv), outlen - padSize, *pulLastPartLen);
}
}
}
@ -1693,7 +1741,7 @@ NSC_Decrypt(CK_SESSION_HANDLE hSession,
return crv;
if (!pData) {
outlen = ulEncryptedDataLen + context->blockSize;
*pulDataLen = (CK_ULONG)(ulEncryptedDataLen + context->blockSize);
goto done;
}
@ -1721,29 +1769,19 @@ NSC_Decrypt(CK_SESSION_HANDLE hSession,
pEncryptedData, ulEncryptedDataLen);
/* XXX need to do MUCH better error mapping than this. */
crv = (rv == SECSuccess) ? CKR_OK : sftk_MapDecryptError(PORT_GetError());
if (rv == SECSuccess && context->doPad) {
unsigned int padding = pData[outlen - 1];
if (padding > context->blockSize || !padding) {
crv = CKR_ENCRYPTED_DATA_INVALID;
if (rv == SECSuccess) {
if (context->doPad) {
unsigned int padSize = 0;
crv = sftk_CheckCBCPadding(&pData[outlen - context->blockSize], context->blockSize, &padSize);
/* Update pulDataLen, in constant time, if crv is OK */
*pulDataLen = CT_SEL(CK_RVToMask(crv), outlen - padSize, *pulDataLen);
} else {
unsigned int i;
unsigned int badPadding = 0; /* used as a boolean */
for (i = 0; i < padding; i++) {
badPadding |= (unsigned int)pData[outlen - 1 - i] ^ padding;
}
if (badPadding) {
crv = CKR_ENCRYPTED_DATA_INVALID;
} else {
outlen -= padding;
}
*pulDataLen = (CK_ULONG)outlen;
}
}
sftk_TerminateOp(session, SFTK_DECRYPT, context);
done:
sftk_FreeSession(session);
if (crv == CKR_OK) {
*pulDataLen = (CK_ULONG)outlen;
}
return crv;
}

View File

@ -4255,7 +4255,7 @@ ssl_SignatureSchemeMatchesSpkiOid(SSLSignatureScheme scheme, SECOidTag spkiOid)
}
/* Validate that the signature scheme works for the given key type. */
static PRBool
PRBool
ssl_SignatureSchemeValid(SSLSignatureScheme scheme, SECOidTag spkiOid,
PRBool isTls13)
{

View File

@ -1737,6 +1737,8 @@ SECStatus ssl3_SetupCipherSuite(sslSocket *ss, PRBool initHashes);
SECStatus ssl_InsertRecordHeader(const sslSocket *ss, ssl3CipherSpec *cwSpec,
SSLContentType contentType, sslBuffer *wrBuf,
PRBool *needsLength);
PRBool ssl_SignatureSchemeValid(SSLSignatureScheme scheme, SECOidTag spkiOid,
PRBool isTls13);
/* Pull in DTLS functions */
#include "dtlscon.h"

View File

@ -703,6 +703,18 @@ SSLExp_DelegateCredential(const CERTCertificate *cert,
if (rv != SECSuccess) {
goto loser;
}
if (dc->alg == ssl_sig_none) {
SECOidTag spkiOid = SECOID_GetAlgorithmTag(&cert->subjectPublicKeyInfo.algorithm);
/* If the Cert SPKI contained an AlgorithmIdentifier of "rsaEncryption", set a
* default rsa_pss_rsae_sha256 scheme. */
if (spkiOid == SEC_OID_PKCS1_RSA_ENCRYPTION) {
SSLSignatureScheme scheme = ssl_sig_rsa_pss_rsae_sha256;
if (ssl_SignatureSchemeValid(scheme, spkiOid, PR_TRUE /* isTls13 */)) {
dc->alg = scheme;
}
}
}
PORT_Assert(dc->alg != ssl_sig_none);
rv = tls13_AppendCredentialParams(&dcBuf, dc);

View File

@ -51,6 +51,11 @@ make_cert() {
type_args=(-q nistp256 --extGeneric 1.3.6.1.4.1.44363.44:not-critical:empty.txt)
type=ec
;;
delegator_rsae2048)
touch empty.txt
type_args=(-g 2048 --extGeneric 1.3.6.1.4.1.44363.44:not-critical:empty.txt)
type=rsa
;;
esac
msg="create certificate: $@"
shift 2

View File

@ -58,6 +58,7 @@ ssl_gtest_certs() {
make_cert ecdh_rsa ecdh_rsa kex
make_cert dsa dsa sign
make_cert delegator_ecdsa256 delegator_p256 sign
make_cert delegator_rsae2048 delegator_rsae2048 sign
}
############################## ssl_gtest_init ##########################