Bug 1523175 - land NSS f7be0a534e89 UPGRADE_NSS_RELEASE, r=me

--HG--
extra : rebase_source : 373a3bcc93e21eef7dcc6e1208419b3ef58b87b3
This commit is contained in:
J.C. Jones 2019-02-25 20:59:41 +00:00
parent 599b9792dc
commit 3a5a08c197
37 changed files with 1266 additions and 366 deletions

View File

@ -1 +1 @@
1f04eea8834a
f7be0a534e89

View File

@ -105,7 +105,6 @@ Usage(char *progName)
"-i input");
fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
"-o output");
exit(-1);
}
int
@ -113,12 +112,12 @@ main(int argc, char **argv)
{
char *progName;
SECStatus rv;
FILE *inFile, *outFile;
PLOptState *optstate;
FILE *inFile = NULL, *outFile = NULL;
PRBool closeIn = PR_TRUE, closeOut = PR_TRUE;
PLOptState *optstate = NULL;
PLOptStatus status;
int exitCode = -1;
inFile = 0;
outFile = 0;
progName = strrchr(argv[0], '/');
progName = progName ? progName + 1 : argv[0];
@ -129,6 +128,7 @@ main(int argc, char **argv)
case '?':
case 'h':
Usage(progName);
goto loser;
break;
case 'i':
@ -136,7 +136,7 @@ main(int argc, char **argv)
if (!inFile) {
fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
progName, optstate->value);
return -1;
goto loser;
}
break;
@ -145,13 +145,15 @@ main(int argc, char **argv)
if (!outFile) {
fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
progName, optstate->value);
return -1;
goto loser;
}
break;
}
}
if (!inFile)
if (!inFile) {
inFile = stdin;
closeIn = PR_FALSE;
}
if (!outFile) {
#if defined(WIN32)
int smrv = _setmode(_fileno(stdout), _O_BINARY);
@ -159,16 +161,28 @@ main(int argc, char **argv)
fprintf(stderr,
"%s: Cannot change stdout to binary mode. Use -o option instead.\n",
progName);
return smrv;
goto loser;
}
#endif
outFile = stdout;
closeOut = PR_FALSE;
}
rv = decode_file(outFile, inFile);
if (rv != SECSuccess) {
fprintf(stderr, "%s: lossage: error=%d errno=%d\n",
progName, PORT_GetError(), errno);
return -1;
goto loser;
}
return 0;
exitCode = 0;
loser:
if (optstate) {
PL_DestroyOptState(optstate);
}
if (inFile && closeIn) {
fclose(inFile);
}
if (outFile && closeOut) {
fclose(outFile);
}
return exitCode;
}

View File

@ -99,7 +99,6 @@ Usage(char *progName)
"-w suffix");
fprintf(stderr, "%-20s (use \"c\" as a shortcut for suffix CERTIFICATE)\n",
"");
exit(-1);
}
int
@ -107,13 +106,13 @@ main(int argc, char **argv)
{
char *progName;
SECStatus rv;
FILE *inFile, *outFile;
PLOptState *optstate;
FILE *inFile = NULL, *outFile = NULL;
PRBool closeIn = PR_TRUE, closeOut = PR_TRUE;
PLOptState *optstate = NULL;
PLOptStatus status;
char *suffix = NULL;
int exitCode = -1;
inFile = 0;
outFile = 0;
progName = strrchr(argv[0], '/');
if (!progName)
progName = strrchr(argv[0], '\\');
@ -125,6 +124,7 @@ main(int argc, char **argv)
switch (optstate->option) {
default:
Usage(progName);
goto loser;
break;
case 'i':
@ -132,7 +132,7 @@ main(int argc, char **argv)
if (!inFile) {
fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
progName, optstate->value);
return -1;
goto loser;
}
break;
@ -141,7 +141,7 @@ main(int argc, char **argv)
if (!outFile) {
fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
progName, optstate->value);
return -1;
goto loser;
}
break;
@ -166,10 +166,11 @@ main(int argc, char **argv)
fprintf(stderr,
"%s: Cannot change stdin to binary mode. Use -i option instead.\n",
progName);
return smrv;
goto loser;
}
#endif
inFile = stdin;
closeIn = PR_FALSE;
}
if (!outFile) {
#if defined(WIN32)
@ -182,10 +183,11 @@ main(int argc, char **argv)
fprintf(stderr,
"%s: Cannot change stdout to binary mode. Use -o option instead.\n",
progName);
return smrv;
goto loser;
}
#endif
outFile = stdout;
closeOut = PR_FALSE;
}
if (suffix) {
fprintf(outFile, "-----BEGIN %s-----\n", suffix);
@ -194,10 +196,21 @@ main(int argc, char **argv)
if (rv != SECSuccess) {
fprintf(stderr, "%s: lossage: error=%d errno=%d\n",
progName, PORT_GetError(), errno);
return -1;
goto loser;
}
if (suffix) {
fprintf(outFile, "-----END %s-----\n", suffix);
}
return 0;
exitCode = 0;
loser:
if (optstate) {
PL_DestroyOptState(optstate);
}
if (inFile && closeIn) {
fclose(inFile);
}
if (outFile && closeOut) {
fclose(outFile);
}
return exitCode;
}

View File

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

View File

@ -14,6 +14,7 @@ struct ScopedDeleteSSL {
void operator()(SSLResumptionTokenInfo* token) {
SSL_DestroyResumptionTokenInfo(token);
}
void operator()(SSLAeadContext* ctx) { SSL_DestroyAead(ctx); }
};
template <class T>
@ -29,6 +30,7 @@ struct ScopedMaybeDeleteSSL {
#define SCOPED(x) typedef std::unique_ptr<x, ScopedMaybeDeleteSSL<x> > Scoped##x
SCOPED(SSLResumptionTokenInfo);
SCOPED(SSLAeadContext);
#undef SCOPED

View File

@ -35,6 +35,7 @@ CPPSRCS = \
ssl_keyupdate_unittest.cc \
ssl_loopback_unittest.cc \
ssl_misc_unittest.cc \
ssl_primitive_unittest.cc \
ssl_record_unittest.cc \
ssl_recordsep_unittest.cc \
ssl_recordsize_unittest.cc \

View File

@ -547,6 +547,56 @@ TEST_P(TlsExtensionTest12, SignatureAlgorithmConfiguration) {
}
}
// This only works on TLS 1.2, since it relies on DSA.
TEST_P(TlsExtensionTest12, SignatureAlgorithmDisableDSA) {
const std::vector<SSLSignatureScheme> schemes = {
ssl_sig_dsa_sha1, ssl_sig_dsa_sha256, ssl_sig_dsa_sha384,
ssl_sig_dsa_sha512, ssl_sig_rsa_pss_rsae_sha256};
// Connect with DSA enabled by policy.
SECStatus rv = NSS_SetAlgorithmPolicy(SEC_OID_ANSIX9_DSA_SIGNATURE,
NSS_USE_ALG_IN_SSL_KX, 0);
ASSERT_EQ(SECSuccess, rv);
rv = NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL,
0);
ASSERT_EQ(SECSuccess, rv);
Reset(TlsAgent::kServerDsa);
auto capture1 =
MakeTlsFilter<TlsExtensionCapture>(client_, ssl_signature_algorithms_xtn);
client_->SetSignatureSchemes(schemes.data(), schemes.size());
Connect();
// Check if all the signature algorithms are advertised.
EXPECT_TRUE(capture1->captured());
const DataBuffer& ext1 = capture1->extension();
EXPECT_EQ(2U + 2U * schemes.size(), ext1.len());
// Connect with DSA disabled by policy.
rv = NSS_SetAlgorithmPolicy(SEC_OID_ANSIX9_DSA_SIGNATURE, 0,
NSS_USE_ALG_IN_SSL_KX);
ASSERT_EQ(SECSuccess, rv);
rv = NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, NSS_USE_POLICY_IN_SSL,
0);
ASSERT_EQ(SECSuccess, rv);
Reset(TlsAgent::kServerDsa);
auto capture2 =
MakeTlsFilter<TlsExtensionCapture>(client_, ssl_signature_algorithms_xtn);
client_->SetSignatureSchemes(schemes.data(), schemes.size());
ConnectExpectAlert(server_, kTlsAlertHandshakeFailure);
server_->CheckErrorCode(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
client_->CheckErrorCode(SSL_ERROR_NO_CYPHER_OVERLAP);
// Check if no DSA algorithms are advertised.
EXPECT_TRUE(capture2->captured());
const DataBuffer& ext2 = capture2->extension();
EXPECT_EQ(2U + 2U, ext2.len());
uint32_t v = 0;
EXPECT_TRUE(ext2.Read(2, 2, &v));
EXPECT_EQ(ssl_sig_rsa_pss_rsae_sha256, v);
}
// Temporary test to verify that we choke on an empty ClientKeyShare.
// This test will fail when we implement HelloRetryRequest.
TEST_P(TlsExtensionTest13, EmptyClientKeyShare) {
@ -1121,6 +1171,10 @@ INSTANTIATE_TEST_CASE_P(
INSTANTIATE_TEST_CASE_P(ExtensionDatagramOnly, TlsExtensionTestDtls,
TlsConnectTestBase::kTlsV11Plus);
INSTANTIATE_TEST_CASE_P(ExtensionTls12, TlsExtensionTest12,
::testing::Combine(TlsConnectTestBase::kTlsVariantsAll,
TlsConnectTestBase::kTlsV12));
INSTANTIATE_TEST_CASE_P(ExtensionTls12Plus, TlsExtensionTest12Plus,
::testing::Combine(TlsConnectTestBase::kTlsVariantsAll,
TlsConnectTestBase::kTlsV12Plus));

View File

@ -36,6 +36,7 @@
'ssl_keyupdate_unittest.cc',
'ssl_loopback_unittest.cc',
'ssl_misc_unittest.cc',
'ssl_primitive_unittest.cc',
'ssl_record_unittest.cc',
'ssl_recordsep_unittest.cc',
'ssl_recordsize_unittest.cc',

View File

@ -0,0 +1,217 @@
/* -*- 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 "keyhi.h"
#include "pk11pub.h"
#include "secerr.h"
#include "ssl.h"
#include "sslerr.h"
#include "sslexp.h"
#include "sslproto.h"
#include "gtest_utils.h"
#include "nss_scoped_ptrs.h"
#include "scoped_ptrs_ssl.h"
#include "tls_connect.h"
namespace nss_test {
// From tls_hkdf_unittest.cc:
extern size_t GetHashLength(SSLHashType ht);
class AeadTest : public ::testing::Test {
public:
AeadTest() : slot_(PK11_GetInternalSlot()) {}
void InitSecret(SSLHashType hash_type) {
static const uint8_t kData[64] = {'s', 'e', 'c', 'r', 'e', 't'};
SECItem key_item = {siBuffer, const_cast<uint8_t *>(kData),
static_cast<unsigned int>(GetHashLength(hash_type))};
PK11SymKey *s =
PK11_ImportSymKey(slot_.get(), CKM_SSL3_MASTER_KEY_DERIVE,
PK11_OriginUnwrap, CKA_DERIVE, &key_item, NULL);
ASSERT_NE(nullptr, s);
secret_.reset(s);
}
void SetUp() override {
InitSecret(ssl_hash_sha256);
PORT_SetError(0);
}
protected:
static void EncryptDecrypt(const ScopedSSLAeadContext &ctx,
const uint8_t *ciphertext, size_t ciphertext_len) {
static const uint8_t kAad[] = {'a', 'a', 'd'};
static const uint8_t kPlaintext[] = {'t', 'e', 'x', 't'};
static const size_t kMaxSize = 32;
ASSERT_GE(kMaxSize, ciphertext_len);
uint8_t output[kMaxSize];
unsigned int output_len = 0;
EXPECT_EQ(SECSuccess, SSL_AeadEncrypt(ctx.get(), 0, kAad, sizeof(kAad),
kPlaintext, sizeof(kPlaintext),
output, &output_len, sizeof(output)));
ASSERT_EQ(ciphertext_len, static_cast<size_t>(output_len));
EXPECT_EQ(0, memcmp(ciphertext, output, ciphertext_len));
memset(output, 0, sizeof(output));
EXPECT_EQ(SECSuccess, SSL_AeadDecrypt(ctx.get(), 0, kAad, sizeof(kAad),
ciphertext, ciphertext_len, output,
&output_len, sizeof(output)));
ASSERT_EQ(sizeof(kPlaintext), static_cast<size_t>(output_len));
EXPECT_EQ(0, memcmp(kPlaintext, output, sizeof(kPlaintext)));
// Now for some tests of decryption failure.
// Truncate the input.
EXPECT_EQ(SECFailure, SSL_AeadDecrypt(ctx.get(), 0, kAad, sizeof(kAad),
ciphertext, ciphertext_len - 1,
output, &output_len, sizeof(output)));
EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError());
// Skip the first byte of the AAD.
EXPECT_EQ(
SECFailure,
SSL_AeadDecrypt(ctx.get(), 0, kAad + 1, sizeof(kAad) - 1, ciphertext,
ciphertext_len, output, &output_len, sizeof(output)));
EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError());
uint8_t input[kMaxSize] = {0};
// Toggle a byte of the input.
memcpy(input, ciphertext, ciphertext_len);
input[0] ^= 9;
EXPECT_EQ(SECFailure, SSL_AeadDecrypt(ctx.get(), 0, kAad, sizeof(kAad),
input, ciphertext_len, output,
&output_len, sizeof(output)));
EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError());
// Toggle the last byte (the auth tag).
memcpy(input, ciphertext, ciphertext_len);
input[ciphertext_len - 1] ^= 77;
EXPECT_EQ(SECFailure, SSL_AeadDecrypt(ctx.get(), 0, kAad, sizeof(kAad),
input, ciphertext_len, output,
&output_len, sizeof(output)));
EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError());
// Toggle some of the AAD.
memcpy(input, kAad, sizeof(kAad));
input[1] ^= 23;
EXPECT_EQ(SECFailure, SSL_AeadDecrypt(ctx.get(), 0, input, sizeof(kAad),
ciphertext, ciphertext_len, output,
&output_len, sizeof(output)));
EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError());
}
protected:
ScopedPK11SymKey secret_;
private:
ScopedPK11SlotInfo slot_;
};
// These tests all use fixed inputs: a fixed secret, a fixed label, and fixed
// inputs. So they have fixed outputs.
static const char *kLabel = "test ";
static const uint8_t kCiphertextAes128Gcm[] = {
0x11, 0x14, 0xfc, 0x58, 0x4f, 0x44, 0xff, 0x8c, 0xb6, 0xd8,
0x20, 0xb3, 0xfb, 0x50, 0xd9, 0x3b, 0xd4, 0xc6, 0xe1, 0x14};
static const uint8_t kCiphertextAes256Gcm[] = {
0xf7, 0x27, 0x35, 0x80, 0x88, 0xaf, 0x99, 0x85, 0xf2, 0x83,
0xca, 0xbb, 0x95, 0x42, 0x09, 0x3f, 0x9c, 0xf3, 0x29, 0xf0};
static const uint8_t kCiphertextChaCha20Poly1305[] = {
0x4e, 0x89, 0x2c, 0xfa, 0xfc, 0x8c, 0x40, 0x55, 0x6d, 0x7e,
0x99, 0xac, 0x8e, 0x54, 0x58, 0xb1, 0x18, 0xd2, 0x66, 0x22};
TEST_F(AeadTest, AeadBadVersion) {
SSLAeadContext *ctx = nullptr;
ASSERT_EQ(SECFailure,
SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_2, TLS_AES_128_GCM_SHA256,
secret_.get(), kLabel, strlen(kLabel), &ctx));
EXPECT_EQ(nullptr, ctx);
}
TEST_F(AeadTest, AeadUnsupportedCipher) {
SSLAeadContext *ctx = nullptr;
ASSERT_EQ(SECFailure,
SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_RSA_WITH_NULL_MD5,
secret_.get(), kLabel, strlen(kLabel), &ctx));
EXPECT_EQ(nullptr, ctx);
}
TEST_F(AeadTest, AeadOlderCipher) {
SSLAeadContext *ctx = nullptr;
ASSERT_EQ(
SECFailure,
SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_RSA_WITH_AES_128_CBC_SHA,
secret_.get(), kLabel, strlen(kLabel), &ctx));
EXPECT_EQ(nullptr, ctx);
}
TEST_F(AeadTest, AeadNoLabel) {
SSLAeadContext *ctx = nullptr;
ASSERT_EQ(SECFailure,
SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_AES_128_GCM_SHA256,
secret_.get(), nullptr, 12, &ctx));
EXPECT_EQ(nullptr, ctx);
}
TEST_F(AeadTest, AeadLongLabel) {
SSLAeadContext *ctx = nullptr;
ASSERT_EQ(SECFailure,
SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_AES_128_GCM_SHA256,
secret_.get(), "", 254, &ctx));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
EXPECT_EQ(nullptr, ctx);
}
TEST_F(AeadTest, AeadNoPointer) {
SSLAeadContext *ctx = nullptr;
ASSERT_EQ(SECFailure,
SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_AES_128_GCM_SHA256,
secret_.get(), kLabel, strlen(kLabel), nullptr));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
EXPECT_EQ(nullptr, ctx);
}
TEST_F(AeadTest, AeadAes128Gcm) {
SSLAeadContext *ctxInit;
ASSERT_EQ(SECSuccess,
SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_AES_128_GCM_SHA256,
secret_.get(), kLabel, strlen(kLabel), &ctxInit));
ScopedSSLAeadContext ctx(ctxInit);
EXPECT_NE(nullptr, ctx);
EncryptDecrypt(ctx, kCiphertextAes128Gcm, sizeof(kCiphertextAes128Gcm));
}
TEST_F(AeadTest, AeadAes256Gcm) {
SSLAeadContext *ctxInit;
ASSERT_EQ(SECSuccess,
SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_AES_256_GCM_SHA384,
secret_.get(), kLabel, strlen(kLabel), &ctxInit));
ScopedSSLAeadContext ctx(ctxInit);
EXPECT_NE(nullptr, ctx);
EncryptDecrypt(ctx, kCiphertextAes256Gcm, sizeof(kCiphertextAes256Gcm));
}
TEST_F(AeadTest, AeadChaCha20Poly1305) {
SSLAeadContext *ctxInit;
ASSERT_EQ(
SECSuccess,
SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3, TLS_CHACHA20_POLY1305_SHA256,
secret_.get(), kLabel, strlen(kLabel), &ctxInit));
ScopedSSLAeadContext ctx(ctxInit);
EXPECT_NE(nullptr, ctx);
EncryptDecrypt(ctx, kCiphertextChaCha20Poly1305,
sizeof(kCiphertextChaCha20Poly1305));
}
} // namespace nss_test

View File

@ -224,8 +224,26 @@ class StagedRecords {
void ForwardAll(std::shared_ptr<TlsAgent>& peer,
TlsAgent::State expected_state) {
ForwardAll(peer);
peer->Handshake();
EXPECT_EQ(expected_state, peer->state());
switch (expected_state) {
case TlsAgent::STATE_CONNECTED:
// The handshake callback should have been called, so check that before
// checking that SSL_ForceHandshake succeeds.
EXPECT_EQ(expected_state, peer->state());
EXPECT_EQ(SECSuccess, SSL_ForceHandshake(peer->ssl_fd()));
break;
case TlsAgent::STATE_CONNECTING:
// Check that SSL_ForceHandshake() blocks.
EXPECT_EQ(SECFailure, SSL_ForceHandshake(peer->ssl_fd()));
EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError());
// Update and check the state.
peer->Handshake();
EXPECT_EQ(TlsAgent::STATE_CONNECTING, peer->state());
break;
default:
ADD_FAILURE() << "No idea how to handle this state";
}
}
void ForwardPartial(std::shared_ptr<TlsAgent>& peer) {
@ -260,12 +278,10 @@ class StagedRecords {
if (g_ssl_gtest_verbose) {
std::cerr << role_ << ": forward " << data_ << std::endl;
}
SECStatus rv = SSL_RecordLayerData(
peer->ssl_fd(), epoch_, content_type_, data_.data(),
static_cast<unsigned int>(data_.len()));
if (rv != SECSuccess) {
EXPECT_EQ(PR_WOULD_BLOCK_ERROR, PORT_GetError());
}
EXPECT_EQ(SECSuccess,
SSL_RecordLayerData(peer->ssl_fd(), epoch_, content_type_,
data_.data(),
static_cast<unsigned int>(data_.len())));
}
// Slices the tail off this record and returns it.

View File

@ -214,12 +214,6 @@ class TestPolicyVersionRange
ASSERT_EQ(SECSuccess, rv);
rv = NSS_OptionSet(NSS_DTLS_VERSION_MAX_POLICY, saved_max_dtls_);
ASSERT_EQ(SECSuccess, rv);
// If it wasn't set initially, clear the bit that we set.
if (!(saved_algorithm_policy_ & NSS_USE_POLICY_IN_SSL)) {
rv = NSS_SetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY, 0,
NSS_USE_POLICY_IN_SSL);
ASSERT_EQ(SECSuccess, rv);
}
}
private:
@ -233,16 +227,12 @@ class TestPolicyVersionRange
ASSERT_EQ(SECSuccess, rv);
rv = NSS_OptionGet(NSS_DTLS_VERSION_MAX_POLICY, &saved_max_dtls_);
ASSERT_EQ(SECSuccess, rv);
rv = NSS_GetAlgorithmPolicy(SEC_OID_APPLY_SSL_POLICY,
&saved_algorithm_policy_);
ASSERT_EQ(SECSuccess, rv);
}
int32_t saved_min_tls_;
int32_t saved_max_tls_;
int32_t saved_min_dtls_;
int32_t saved_max_dtls_;
uint32_t saved_algorithm_policy_;
};
VersionPolicy saved_version_policy_;

View File

@ -183,12 +183,33 @@ void TlsConnectTestBase::ClearServerCache() {
SSL_ConfigServerSessionIDCache(1024, 0, 0, g_working_dir_path.c_str());
}
void TlsConnectTestBase::SaveAlgorithmPolicy() {
saved_policies_.clear();
for (auto it = algorithms_.begin(); it != algorithms_.end(); ++it) {
uint32_t policy;
SECStatus rv = NSS_GetAlgorithmPolicy(*it, &policy);
ASSERT_EQ(SECSuccess, rv);
saved_policies_.push_back(std::make_tuple(*it, policy));
}
}
void TlsConnectTestBase::RestoreAlgorithmPolicy() {
for (auto it = saved_policies_.begin(); it != saved_policies_.end(); ++it) {
auto algorithm = std::get<0>(*it);
auto policy = std::get<1>(*it);
SECStatus rv = NSS_SetAlgorithmPolicy(
algorithm, policy, NSS_USE_POLICY_IN_SSL | NSS_USE_ALG_IN_SSL_KX);
ASSERT_EQ(SECSuccess, rv);
}
}
void TlsConnectTestBase::SetUp() {
SSL_ConfigServerSessionIDCache(1024, 0, 0, g_working_dir_path.c_str());
SSLInt_ClearSelfEncryptKey();
SSLInt_SetTicketLifetime(30);
SSL_SetupAntiReplay(1 * PR_USEC_PER_SEC, 1, 3);
ClearStats();
SaveAlgorithmPolicy();
Init();
}
@ -199,6 +220,7 @@ void TlsConnectTestBase::TearDown() {
SSL_ClearSessionCache();
SSLInt_ClearSelfEncryptKey();
SSL_ShutdownServerSessionIDCache();
RestoreAlgorithmPolicy();
}
void TlsConnectTestBase::Init() {

View File

@ -132,6 +132,9 @@ class TlsConnectTestBase : public ::testing::Test {
// Move the DTLS timers for both endpoints to pop the next timer.
void ShiftDtlsTimers();
void SaveAlgorithmPolicy();
void RestoreAlgorithmPolicy();
protected:
SSLProtocolVariant variant_;
std::shared_ptr<TlsAgent> client_;
@ -149,6 +152,13 @@ class TlsConnectTestBase : public ::testing::Test {
// NSS will move this final entry to the front when used with ALPN.
const uint8_t alpn_dummy_val_[4] = {0x01, 0x62, 0x01, 0x61};
// A list of algorithm IDs whose policies need to be preserved
// around test cases. In particular, DSA is checked in
// ssl_extension_unittest.cc.
const std::vector<SECOidTag> algorithms_ = {SEC_OID_APPLY_SSL_POLICY,
SEC_OID_ANSIX9_DSA_SIGNATURE};
std::vector<std::tuple<SECOidTag, uint32_t>> saved_policies_;
private:
void CheckResumption(SessionResumptionMode expected);
void CheckExtendedMasterSecret();

View File

@ -7,6 +7,9 @@
#include <memory>
#include "nss.h"
#include "pk11pub.h"
#include "secerr.h"
#include "sslproto.h"
#include "sslexp.h"
#include "tls13hkdf.h"
#include "databuffer.h"
@ -56,6 +59,27 @@ const size_t kHashLength[] = {
64, /* ssl_hash_sha512 */
};
size_t GetHashLength(SSLHashType hash) {
size_t i = static_cast<size_t>(hash);
if (i < PR_ARRAY_SIZE(kHashLength)) {
return kHashLength[i];
}
ADD_FAILURE() << "Unknown hash: " << hash;
return 0;
}
PRUint16 GetSomeCipherSuiteForHash(SSLHashType hash) {
switch (hash) {
case ssl_hash_sha256:
return TLS_AES_128_GCM_SHA256;
case ssl_hash_sha384:
return TLS_AES_256_GCM_SHA384;
default:
ADD_FAILURE() << "Unknown hash: " << hash;
}
return 0;
}
const std::string kHashName[] = {"None", "MD5", "SHA-1", "SHA-224",
"SHA-256", "SHA-384", "SHA-512"};
@ -64,7 +88,7 @@ static void ImportKey(ScopedPK11SymKey* to, const DataBuffer& key,
ASSERT_LT(hash_type, sizeof(kHashLength));
ASSERT_LE(kHashLength[hash_type], key.len());
SECItem key_item = {siBuffer, const_cast<uint8_t*>(key.data()),
static_cast<unsigned int>(kHashLength[hash_type])};
static_cast<unsigned int>(GetHashLength(hash_type))};
PK11SymKey* inner =
PK11_ImportSymKey(slot, CKM_SSL3_MASTER_KEY_DERIVE, PK11_OriginUnwrap,
@ -134,6 +158,14 @@ class TlsHkdfTest : public ::testing::Test,
DumpKey("Output", prkk);
VerifyKey(prkk, expected);
// Now test the public wrapper.
PRUint16 cs = GetSomeCipherSuiteForHash(base_hash);
rv = SSL_HkdfExtract(SSL_LIBRARY_VERSION_TLS_1_3, cs, ikmk1.get(),
ikmk2.get(), &prk);
ASSERT_EQ(SECSuccess, rv);
ASSERT_NE(nullptr, prk);
VerifyKey(ScopedPK11SymKey(prk), expected);
}
void HkdfExpandLabel(ScopedPK11SymKey* prk, SSLHashType base_hash,
@ -150,6 +182,19 @@ class TlsHkdfTest : public ::testing::Test,
ASSERT_EQ(SECSuccess, rv);
DumpData("Output", &output[0], output.size());
EXPECT_EQ(0, memcmp(expected.data(), &output[0], expected.len()));
if (session_hash_len > 0) {
return;
}
// Verify that the public API produces the same result.
PRUint16 cs = GetSomeCipherSuiteForHash(base_hash);
PK11SymKey* secret;
rv = SSL_HkdfDeriveSecret(SSL_LIBRARY_VERSION_TLS_1_3, cs, prk->get(),
label, label_len, &secret);
EXPECT_EQ(SECSuccess, rv);
ASSERT_NE(nullptr, prk);
VerifyKey(ScopedPK11SymKey(secret), expected);
}
protected:
@ -175,7 +220,7 @@ TEST_P(TlsHkdfTest, HkdfNullNull) {
0x10, 0xba, 0x18, 0xe2, 0x35, 0x7e, 0x71, 0x69, 0x71, 0xf9, 0x36, 0x2f,
0x2c, 0x2f, 0xe2, 0xa7, 0x6b, 0xfd, 0x78, 0xdf, 0xec, 0x4e, 0xa9, 0xb5}};
const DataBuffer expected_data(tv[hash_type_], kHashLength[hash_type_]);
const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_));
HkdfExtract(nullptr, nullptr, hash_type_, expected_data);
}
@ -193,7 +238,7 @@ TEST_P(TlsHkdfTest, HkdfKey1Only) {
0x57, 0xc2, 0x76, 0x9f, 0x3f, 0x83, 0x45, 0x2f, 0xf6, 0xf3, 0x56, 0x1f,
0x58, 0x63, 0xdb, 0x88, 0xda, 0x40, 0xce, 0x63, 0x7d, 0x24, 0x37, 0xf3}};
const DataBuffer expected_data(tv[hash_type_], kHashLength[hash_type_]);
const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_));
HkdfExtract(k1_, nullptr, hash_type_, expected_data);
}
@ -211,7 +256,7 @@ TEST_P(TlsHkdfTest, HkdfKey2Only) {
0xd4, 0x6a, 0xf6, 0xe5, 0xec, 0xea, 0xf8, 0x7d, 0x91, 0x71, 0x81, 0xf1,
0xdb, 0x3b, 0xaf, 0xbf, 0xde, 0x71, 0x61, 0x15, 0xeb, 0xb5, 0x5f, 0x68}};
const DataBuffer expected_data(tv[hash_type_], kHashLength[hash_type_]);
const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_));
HkdfExtract(nullptr, k2_, hash_type_, expected_data);
}
@ -229,7 +274,7 @@ TEST_P(TlsHkdfTest, HkdfKey1Key2) {
0x1c, 0x5b, 0x98, 0x0b, 0x02, 0x92, 0x3f, 0xfd, 0x73, 0x5a, 0x6f, 0x2a,
0x95, 0xa3, 0xee, 0xf6, 0xd6, 0x8e, 0x6f, 0x86, 0xea, 0x63, 0xf8, 0x33}};
const DataBuffer expected_data(tv[hash_type_], kHashLength[hash_type_]);
const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_));
HkdfExtract(k1_, k2_, hash_type_, expected_data);
}
@ -247,12 +292,111 @@ TEST_P(TlsHkdfTest, HkdfExpandLabel) {
0x74, 0xf7, 0x8b, 0x06, 0x38, 0x28, 0x06, 0x37, 0x75, 0x23, 0xa2, 0xb7,
0x34, 0xb1, 0x72, 0x2e, 0x59, 0x6d, 0x5a, 0x31, 0xf5, 0x53, 0xab, 0x99}};
const DataBuffer expected_data(tv[hash_type_], kHashLength[hash_type_]);
HkdfExpandLabel(&k1_, hash_type_, kSessionHash, kHashLength[hash_type_],
const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_));
HkdfExpandLabel(&k1_, hash_type_, kSessionHash, GetHashLength(hash_type_),
kLabelMasterSecret, strlen(kLabelMasterSecret),
expected_data);
}
TEST_P(TlsHkdfTest, HkdfExpandLabelNoHash) {
const uint8_t tv[][48] = {
{/* ssl_hash_none */},
{/* ssl_hash_md5 */},
{/* ssl_hash_sha1 */},
{/* ssl_hash_sha224 */},
{0xb7, 0x08, 0x00, 0xe3, 0x8e, 0x48, 0x68, 0x91, 0xb1, 0x0f, 0x5e,
0x6f, 0x22, 0x53, 0x6b, 0x84, 0x69, 0x75, 0xaa, 0xa3, 0x2a, 0xe7,
0xde, 0xaa, 0xc3, 0xd1, 0xb4, 0x05, 0x22, 0x5c, 0x68, 0xf5},
{0x13, 0xd3, 0x36, 0x9f, 0x3c, 0x78, 0xa0, 0x32, 0x40, 0xee, 0x16, 0xe9,
0x11, 0x12, 0x66, 0xc7, 0x51, 0xad, 0xd8, 0x3c, 0xa1, 0xa3, 0x97, 0x74,
0xd7, 0x45, 0xff, 0xa7, 0x88, 0x9e, 0x52, 0x17, 0x2e, 0xaa, 0x3a, 0xd2,
0x35, 0xd8, 0xd5, 0x35, 0xfd, 0x65, 0x70, 0x9f, 0xa9, 0xf9, 0xfa, 0x23}};
const DataBuffer expected_data(tv[hash_type_], GetHashLength(hash_type_));
HkdfExpandLabel(&k1_, hash_type_, nullptr, 0, kLabelMasterSecret,
strlen(kLabelMasterSecret), expected_data);
}
TEST_P(TlsHkdfTest, BadExtractWrapperInput) {
PK11SymKey* key = nullptr;
// Bad version.
EXPECT_EQ(SECFailure,
SSL_HkdfExtract(SSL_LIBRARY_VERSION_TLS_1_2, TLS_AES_128_GCM_SHA256,
k1_.get(), k2_.get(), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Bad ciphersuite.
EXPECT_EQ(SECFailure,
SSL_HkdfExtract(SSL_LIBRARY_VERSION_TLS_1_3, TLS_RSA_WITH_NULL_SHA,
k1_.get(), k2_.get(), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Old ciphersuite.
EXPECT_EQ(SECFailure, SSL_HkdfExtract(SSL_LIBRARY_VERSION_TLS_1_3,
TLS_RSA_WITH_AES_128_CBC_SHA, k1_.get(),
k2_.get(), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// NULL outparam..
EXPECT_EQ(SECFailure, SSL_HkdfExtract(SSL_LIBRARY_VERSION_TLS_1_3,
TLS_RSA_WITH_AES_128_CBC_SHA, k1_.get(),
k2_.get(), nullptr));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
EXPECT_EQ(nullptr, key);
}
TEST_P(TlsHkdfTest, BadDeriveSecretWrapperInput) {
PK11SymKey* key = nullptr;
static const char* kLabel = "label";
// Bad version.
EXPECT_EQ(SECFailure, SSL_HkdfDeriveSecret(SSL_LIBRARY_VERSION_TLS_1_2,
TLS_AES_128_GCM_SHA256, k1_.get(),
kLabel, strlen(kLabel), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Bad ciphersuite.
EXPECT_EQ(SECFailure, SSL_HkdfDeriveSecret(SSL_LIBRARY_VERSION_TLS_1_3,
TLS_RSA_WITH_NULL_MD5, k1_.get(),
kLabel, strlen(kLabel), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Old ciphersuite.
EXPECT_EQ(SECFailure,
SSL_HkdfDeriveSecret(SSL_LIBRARY_VERSION_TLS_1_3,
TLS_RSA_WITH_AES_128_CBC_SHA, k1_.get(),
kLabel, strlen(kLabel), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Null PRK.
EXPECT_EQ(SECFailure, SSL_HkdfDeriveSecret(SSL_LIBRARY_VERSION_TLS_1_2,
TLS_AES_128_GCM_SHA256, nullptr,
kLabel, strlen(kLabel), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Null, non-zero-length label.
EXPECT_EQ(SECFailure, SSL_HkdfDeriveSecret(SSL_LIBRARY_VERSION_TLS_1_3,
TLS_AES_128_GCM_SHA256, k1_.get(),
nullptr, strlen(kLabel), &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Null, empty label.
EXPECT_EQ(SECFailure, SSL_HkdfDeriveSecret(SSL_LIBRARY_VERSION_TLS_1_3,
TLS_AES_128_GCM_SHA256, k1_.get(),
nullptr, 0, &key));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
// Null key pointer..
EXPECT_EQ(SECFailure, SSL_HkdfDeriveSecret(SSL_LIBRARY_VERSION_TLS_1_3,
TLS_AES_128_GCM_SHA256, k1_.get(),
kLabel, strlen(kLabel), nullptr));
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
EXPECT_EQ(nullptr, key);
}
static const SSLHashType kHashTypes[] = {ssl_hash_sha256, ssl_hash_sha384};
INSTANTIATE_TEST_CASE_P(AllHashFuncs, TlsHkdfTest,
::testing::ValuesIn(kHashTypes));

View File

@ -5,101 +5,11 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "tls_protect.h"
#include "sslproto.h"
#include "tls_filter.h"
// Do this to avoid having to re-implement HKDF.
#include "tls13hkdf.h"
namespace nss_test {
AeadCipher::~AeadCipher() {
if (key_) {
PK11_FreeSymKey(key_);
}
}
bool AeadCipher::Init(PK11SymKey* key, const uint8_t* iv) {
key_ = key;
if (!key_) return false;
memcpy(iv_, iv, sizeof(iv_));
if (g_ssl_gtest_verbose) {
EXPECT_EQ(SECSuccess, PK11_ExtractKeyValue(key_));
SECItem* raw_key = PK11_GetKeyData(key_);
std::cerr << "key: " << DataBuffer(raw_key->data, raw_key->len)
<< std::endl;
std::cerr << "iv: " << DataBuffer(iv_, 12) << std::endl;
}
return true;
}
void AeadCipher::FormatNonce(uint64_t seq, uint8_t* nonce) {
memcpy(nonce, iv_, 12);
for (size_t i = 0; i < 8; ++i) {
nonce[12 - (i + 1)] ^= seq & 0xff;
seq >>= 8;
}
}
bool AeadCipher::AeadInner(bool decrypt, void* params, size_t param_length,
const uint8_t* in, size_t inlen, uint8_t* out,
size_t* outlen, size_t maxlen) {
SECStatus rv;
unsigned int uoutlen = 0;
SECItem param = {
siBuffer, static_cast<unsigned char*>(params),
static_cast<unsigned int>(param_length),
};
if (decrypt) {
rv = PK11_Decrypt(key_, mech_, &param, out, &uoutlen, maxlen, in, inlen);
} else {
rv = PK11_Encrypt(key_, mech_, &param, out, &uoutlen, maxlen, in, inlen);
}
*outlen = (int)uoutlen;
return rv == SECSuccess;
}
bool AeadCipherAesGcm::Aead(bool decrypt, const uint8_t* hdr, size_t hdr_len,
uint64_t seq, const uint8_t* in, size_t inlen,
uint8_t* out, size_t* outlen, size_t maxlen) {
CK_GCM_PARAMS aeadParams;
unsigned char nonce[12];
memset(&aeadParams, 0, sizeof(aeadParams));
aeadParams.pIv = nonce;
aeadParams.ulIvLen = sizeof(nonce);
aeadParams.pAAD = const_cast<uint8_t*>(hdr);
aeadParams.ulAADLen = hdr_len;
aeadParams.ulTagBits = 128;
FormatNonce(seq, nonce);
return AeadInner(decrypt, (unsigned char*)&aeadParams, sizeof(aeadParams), in,
inlen, out, outlen, maxlen);
}
bool AeadCipherChacha20Poly1305::Aead(bool decrypt, const uint8_t* hdr,
size_t hdr_len, uint64_t seq,
const uint8_t* in, size_t inlen,
uint8_t* out, size_t* outlen,
size_t maxlen) {
CK_NSS_AEAD_PARAMS aeadParams;
unsigned char nonce[12];
memset(&aeadParams, 0, sizeof(aeadParams));
aeadParams.pNonce = nonce;
aeadParams.ulNonceLen = sizeof(nonce);
aeadParams.pAAD = const_cast<uint8_t*>(hdr);
aeadParams.ulAADLen = hdr_len;
aeadParams.ulTagLen = 16;
FormatNonce(seq, nonce);
return AeadInner(decrypt, (unsigned char*)&aeadParams, sizeof(aeadParams), in,
inlen, out, outlen, maxlen);
}
static uint64_t FirstSeqno(bool dtls, uint16_t epoc) {
if (dtls) {
return static_cast<uint64_t>(epoc) << 48;
@ -115,42 +25,16 @@ TlsCipherSpec::TlsCipherSpec(bool dtls, uint16_t epoc)
bool TlsCipherSpec::SetKeys(SSLCipherSuiteInfo* cipherinfo,
PK11SymKey* secret) {
CK_MECHANISM_TYPE mech;
switch (cipherinfo->symCipher) {
case ssl_calg_aes_gcm:
aead_.reset(new AeadCipherAesGcm());
mech = CKM_AES_GCM;
break;
case ssl_calg_chacha20:
aead_.reset(new AeadCipherChacha20Poly1305());
mech = CKM_NSS_CHACHA20_POLY1305;
break;
default:
return false;
}
PK11SymKey* key;
const std::string kPurposeKey = "key";
SECStatus rv = tls13_HkdfExpandLabel(
secret, cipherinfo->kdfHash, NULL, 0, kPurposeKey.c_str(),
kPurposeKey.length(), mech, cipherinfo->symKeyBits / 8, &key);
SSLAeadContext* ctx;
SECStatus rv = SSL_MakeAead(SSL_LIBRARY_VERSION_TLS_1_3,
cipherinfo->cipherSuite, secret, "",
0, // Use the default labels.
&ctx);
if (rv != SECSuccess) {
ADD_FAILURE() << "unable to derive key for epoch " << epoch_;
return false;
}
// No constant for IV length, but everything we know of uses 12.
uint8_t iv[12];
const std::string kPurposeIv = "iv";
rv = tls13_HkdfExpandLabelRaw(secret, cipherinfo->kdfHash, NULL, 0,
kPurposeIv.c_str(), kPurposeIv.length(), iv,
sizeof(iv));
if (rv != SECSuccess) {
ADD_FAILURE() << "unable to derive IV for epoch " << epoch_;
return false;
}
return aead_->Init(key, iv);
aead_.reset(ctx);
return true;
}
bool TlsCipherSpec::Unprotect(const TlsRecordHeader& header,
@ -163,22 +47,23 @@ bool TlsCipherSpec::Unprotect(const TlsRecordHeader& header,
plaintext->Allocate(ciphertext.len());
auto header_bytes = header.header();
size_t len;
unsigned int len;
uint64_t seqno;
if (dtls_) {
seqno = header.sequence_number();
} else {
seqno = in_seqno_;
}
bool ret = aead_->Aead(true, header_bytes.data(), header_bytes.len(), seqno,
ciphertext.data(), ciphertext.len(), plaintext->data(),
&len, plaintext->len());
if (!ret) {
SECStatus rv =
SSL_AeadDecrypt(aead_.get(), seqno, header_bytes.data(),
header_bytes.len(), ciphertext.data(), ciphertext.len(),
plaintext->data(), &len, plaintext->len());
if (rv != SECSuccess) {
return false;
}
RecordUnprotected(seqno);
plaintext->Truncate(len);
plaintext->Truncate(static_cast<size_t>(len));
return true;
}
@ -192,7 +77,7 @@ bool TlsCipherSpec::Protect(const TlsRecordHeader& header,
// Make a padded buffer.
ciphertext->Allocate(plaintext.len() +
32); // Room for any plausible auth tag
size_t len;
unsigned int len;
DataBuffer header_bytes;
(void)header.WriteHeader(&header_bytes, 0, plaintext.len() + 16);
@ -203,10 +88,11 @@ bool TlsCipherSpec::Protect(const TlsRecordHeader& header,
seqno = out_seqno_;
}
bool ret = aead_->Aead(false, header_bytes.data(), header_bytes.len(), seqno,
plaintext.data(), plaintext.len(), ciphertext->data(),
&len, ciphertext->len());
if (!ret) {
SECStatus rv =
SSL_AeadEncrypt(aead_.get(), seqno, header_bytes.data(),
header_bytes.len(), plaintext.data(), plaintext.len(),
ciphertext->data(), &len, ciphertext->len());
if (rv != SECSuccess) {
return false;
}

View File

@ -10,54 +10,16 @@
#include <cstdint>
#include <memory>
#include "databuffer.h"
#include "pk11pub.h"
#include "sslt.h"
#include "sslexp.h"
#include "databuffer.h"
#include "scoped_ptrs_ssl.h"
namespace nss_test {
class TlsRecordHeader;
class AeadCipher {
public:
AeadCipher(CK_MECHANISM_TYPE mech) : mech_(mech), key_(nullptr) {}
virtual ~AeadCipher();
bool Init(PK11SymKey* key, const uint8_t* iv);
virtual bool Aead(bool decrypt, const uint8_t* hdr, size_t hdr_len,
uint64_t seq, const uint8_t* in, size_t inlen, uint8_t* out,
size_t* outlen, size_t maxlen) = 0;
protected:
void FormatNonce(uint64_t seq, uint8_t* nonce);
bool AeadInner(bool decrypt, void* params, size_t param_length,
const uint8_t* in, size_t inlen, uint8_t* out, size_t* outlen,
size_t maxlen);
CK_MECHANISM_TYPE mech_;
PK11SymKey* key_;
uint8_t iv_[12];
};
class AeadCipherChacha20Poly1305 : public AeadCipher {
public:
AeadCipherChacha20Poly1305() : AeadCipher(CKM_NSS_CHACHA20_POLY1305) {}
protected:
bool Aead(bool decrypt, const uint8_t* hdr, size_t hdr_len, uint64_t seq,
const uint8_t* in, size_t inlen, uint8_t* out, size_t* outlen,
size_t maxlen);
};
class AeadCipherAesGcm : public AeadCipher {
public:
AeadCipherAesGcm() : AeadCipher(CKM_AES_GCM) {}
protected:
bool Aead(bool decrypt, const uint8_t* hdr, size_t hdr_len, uint64_t seq,
const uint8_t* in, size_t inlen, uint8_t* out, size_t* outlen,
size_t maxlen);
};
// Our analog of ssl3CipherSpec
class TlsCipherSpec {
public:
@ -89,7 +51,7 @@ class TlsCipherSpec {
uint64_t in_seqno_;
uint64_t out_seqno_;
bool record_dropped_ = false;
std::unique_ptr<AeadCipher> aead_;
ScopedSSLAeadContext aead_;
};
} // namespace nss_test

View File

@ -37,7 +37,7 @@ CERT_CertTimesValid(CERTCertificate *c)
return (valid == secCertTimeValid) ? SECSuccess : SECFailure;
}
SECStatus
static SECStatus
checkKeyParams(const SECAlgorithmID *sigAlgorithm, const SECKEYPublicKey *key)
{
SECStatus rv;
@ -47,6 +47,12 @@ checkKeyParams(const SECAlgorithmID *sigAlgorithm, const SECKEYPublicKey *key)
PRInt32 minLen, len;
sigAlg = SECOID_GetAlgorithmTag(sigAlgorithm);
rv = NSS_GetAlgorithmPolicy(sigAlg, &policyFlags);
if (rv == SECSuccess &&
!(policyFlags & NSS_USE_ALG_IN_CERT_SIGNATURE)) {
PORT_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED);
return SECFailure;
}
switch (sigAlg) {
case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:

View File

@ -32,7 +32,7 @@ RNG_SystemRNG(void *dest, size_t maxLen)
size_t fileBytes = 0;
unsigned char *buffer = dest;
#if defined(__OpenBSD__) || (defined(LINUX) && defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 25))))
#if defined(__OpenBSD__) || (defined(__FreeBSD__) && __FreeBSD_version >= 1200000) || (defined(LINUX) && defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 25))))
int result;
while (fileBytes < maxLen) {

View File

@ -384,18 +384,26 @@ static const oidValDef kxOptList[] = {
{ CIPHER_NAME("ECDH-RSA"), SEC_OID_TLS_ECDH_RSA, NSS_USE_ALG_IN_SSL_KX },
};
static const oidValDef signOptList[] = {
/* Signatures */
{ CIPHER_NAME("DSA"), SEC_OID_ANSIX9_DSA_SIGNATURE,
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_CERT_SIGNATURE },
};
typedef struct {
const oidValDef *list;
PRUint32 entries;
const char *description;
PRBool allowEmpty;
} algListsDef;
static const algListsDef algOptLists[] = {
{ curveOptList, PR_ARRAY_SIZE(curveOptList), "ECC" },
{ hashOptList, PR_ARRAY_SIZE(hashOptList), "HASH" },
{ macOptList, PR_ARRAY_SIZE(macOptList), "MAC" },
{ cipherOptList, PR_ARRAY_SIZE(cipherOptList), "CIPHER" },
{ kxOptList, PR_ARRAY_SIZE(kxOptList), "OTHER-KX" },
{ curveOptList, PR_ARRAY_SIZE(curveOptList), "ECC", PR_FALSE },
{ hashOptList, PR_ARRAY_SIZE(hashOptList), "HASH", PR_FALSE },
{ macOptList, PR_ARRAY_SIZE(macOptList), "MAC", PR_FALSE },
{ cipherOptList, PR_ARRAY_SIZE(cipherOptList), "CIPHER", PR_FALSE },
{ kxOptList, PR_ARRAY_SIZE(kxOptList), "OTHER-KX", PR_FALSE },
{ signOptList, PR_ARRAY_SIZE(signOptList), "OTHER-SIGN", PR_TRUE },
};
static const optionFreeDef sslOptList[] = {
@ -718,7 +726,7 @@ secmod_sanityCheckCryptoPolicy(void)
for (i = 0; i < PR_ARRAY_SIZE(algOptLists); i++) {
const algListsDef *algOptList = &algOptLists[i];
fprintf(stderr, "NSS-POLICY-%s: NUMBER-OF-%s: %u\n", enabledCount[i] ? sInfo : sWarn, algOptList->description, enabledCount[i]);
if (!enabledCount[i]) {
if (!enabledCount[i] && !algOptList->allowEmpty) {
haveWarning = PR_TRUE;
}
}

View File

@ -55,6 +55,7 @@ CSRCS = \
tls13replay.c \
sslcert.c \
sslgrp.c \
sslprimitive.c \
tls13esni.c \
$(NULL)

View File

@ -35,6 +35,7 @@
'sslinit.c',
'sslmutex.c',
'sslnonce.c',
'sslprimitive.c',
'sslreveal.c',
'sslsecur.c',
'sslsnce.c',

View File

@ -64,6 +64,7 @@ static SECStatus ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags);
static CK_MECHANISM_TYPE ssl3_GetHashMechanismByHashType(SSLHashType hashType);
static CK_MECHANISM_TYPE ssl3_GetMgfMechanismByHashType(SSLHashType hash);
PRBool ssl_IsRsaPssSignatureScheme(SSLSignatureScheme scheme);
PRBool ssl_IsDsaSignatureScheme(SSLSignatureScheme scheme);
const PRUint8 ssl_hello_retry_random[] = {
0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
@ -553,10 +554,9 @@ SSL_AtomicIncrementLong(long *x)
}
}
static PRBool
ssl3_CipherSuiteAllowedForVersionRange(
ssl3CipherSuite cipherSuite,
const SSLVersionRange *vrange)
PRBool
ssl3_CipherSuiteAllowedForVersionRange(ssl3CipherSuite cipherSuite,
const SSLVersionRange *vrange)
{
switch (cipherSuite) {
case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
@ -912,8 +912,8 @@ count_cipher_suites(sslSocket *ss, PRUint8 policy)
* Null compression, mac and encryption functions
*/
SECStatus
Null_Cipher(void *ctx, unsigned char *output, int *outputLen, int maxOutputLen,
const unsigned char *input, int inputLen)
Null_Cipher(void *ctx, unsigned char *output, unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen)
{
if (inputLen > maxOutputLen) {
*outputLen = 0; /* Match PK11_CipherOp in setting outputLen */
@ -1554,15 +1554,15 @@ ssl3_BuildRecordPseudoHeader(DTLSEpoch epoch,
}
static SECStatus
ssl3_AESGCM(ssl3KeyMaterial *keys,
ssl3_AESGCM(const ssl3KeyMaterial *keys,
PRBool doDecrypt,
unsigned char *out,
int *outlen,
int maxout,
unsigned int *outlen,
unsigned int maxout,
const unsigned char *in,
int inlen,
unsigned int inlen,
const unsigned char *additionalData,
int additionalDataLen)
unsigned int additionalDataLen)
{
SECItem param;
SECStatus rv = SECFailure;
@ -1616,11 +1616,11 @@ ssl3_AESGCM(ssl3KeyMaterial *keys,
}
static SECStatus
ssl3_ChaCha20Poly1305(ssl3KeyMaterial *keys, PRBool doDecrypt,
unsigned char *out, int *outlen, int maxout,
const unsigned char *in, int inlen,
ssl3_ChaCha20Poly1305(const ssl3KeyMaterial *keys, PRBool doDecrypt,
unsigned char *out, unsigned int *outlen, unsigned int maxout,
const unsigned char *in, unsigned int inlen,
const unsigned char *additionalData,
int additionalDataLen)
unsigned int additionalDataLen)
{
size_t i;
SECItem param;
@ -2012,7 +2012,7 @@ ssl3_MACEncryptRecord(ssl3CipherSpec *cwSpec,
unsigned int ivLen = 0;
unsigned char pseudoHeaderBuf[13];
sslBuffer pseudoHeader = SSL_BUFFER(pseudoHeaderBuf);
int len;
unsigned int len;
if (cwSpec->cipherDef->type == type_block &&
cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) {
@ -2130,15 +2130,15 @@ ssl3_MACEncryptRecord(ssl3CipherSpec *cwSpec,
memmove(SSL_BUFFER_NEXT(wrBuf) + p1Len, pIn + p1Len, oddLen);
}
if (p1Len > 0) {
int cipherBytesPart1 = -1;
unsigned int cipherBytesPart1 = 0;
rv = cwSpec->cipher(cwSpec->cipherContext,
SSL_BUFFER_NEXT(wrBuf), /* output */
&cipherBytesPart1, /* actual outlen */
p1Len, /* max outlen */
pIn,
p1Len); /* input, and inputlen */
PORT_Assert(rv == SECSuccess && cipherBytesPart1 == (int)p1Len);
if (rv != SECSuccess || cipherBytesPart1 != (int)p1Len) {
PORT_Assert(rv == SECSuccess && cipherBytesPart1 == p1Len);
if (rv != SECSuccess || cipherBytesPart1 != p1Len) {
PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
return SECFailure;
}
@ -2146,15 +2146,15 @@ ssl3_MACEncryptRecord(ssl3CipherSpec *cwSpec,
PORT_Assert(rv == SECSuccess);
}
if (p2Len > 0) {
int cipherBytesPart2 = -1;
unsigned int cipherBytesPart2 = 0;
rv = cwSpec->cipher(cwSpec->cipherContext,
SSL_BUFFER_NEXT(wrBuf),
&cipherBytesPart2, /* output and actual outLen */
p2Len, /* max outlen */
SSL_BUFFER_NEXT(wrBuf),
p2Len); /* input and inputLen*/
PORT_Assert(rv == SECSuccess && cipherBytesPart2 == (int)p2Len);
if (rv != SECSuccess || cipherBytesPart2 != (int)p2Len) {
PORT_Assert(rv == SECSuccess && cipherBytesPart2 == p2Len);
if (rv != SECSuccess || cipherBytesPart2 != p2Len) {
PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
return SECFailure;
}
@ -2241,7 +2241,7 @@ ssl_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec, SSLContentType ct,
#ifdef UNSAFE_FUZZER_MODE
{
int len;
unsigned int len;
rv = Null_Cipher(NULL, SSL_BUFFER_NEXT(wrBuf), &len,
SSL_BUFFER_SPACE(wrBuf), pIn, contentLen);
if (rv != SECSuccess) {
@ -4320,6 +4320,22 @@ ssl_IsRsaPssSignatureScheme(SSLSignatureScheme scheme)
return PR_FALSE;
}
PRBool
ssl_IsDsaSignatureScheme(SSLSignatureScheme scheme)
{
switch (scheme) {
case ssl_sig_dsa_sha256:
case ssl_sig_dsa_sha384:
case ssl_sig_dsa_sha512:
case ssl_sig_dsa_sha1:
return PR_TRUE;
default:
return PR_FALSE;
}
return PR_FALSE;
}
SSLAuthType
ssl_SignatureSchemeToAuthType(SSLSignatureScheme scheme)
{
@ -6032,6 +6048,13 @@ ssl_CanUseSignatureScheme(SSLSignatureScheme scheme,
return PR_FALSE;
}
if (ssl_IsDsaSignatureScheme(scheme) &&
(NSS_GetAlgorithmPolicy(SEC_OID_ANSIX9_DSA_SIGNATURE, &policy) ==
SECSuccess) &&
!(policy & NSS_USE_ALG_IN_SSL_KX)) {
return PR_FALSE;
}
hashType = ssl_SignatureSchemeToHashType(scheme);
if (requireSha1 && (hashType != ssl_hash_sha1)) {
return PR_FALSE;
@ -9510,6 +9533,14 @@ ssl3_EncodeSigAlgs(const sslSocket *ss, sslBuffer *buf)
continue;
}
/* Skip DSA scheme if it is disabled by policy. */
if (ssl_IsDsaSignatureScheme(ss->ssl3.signatureSchemes[i]) &&
(NSS_GetAlgorithmPolicy(SEC_OID_ANSIX9_DSA_SIGNATURE, &policy) ==
SECSuccess) &&
!(policy & NSS_USE_ALG_IN_SSL_KX)) {
continue;
}
if ((NSS_GetAlgorithmPolicy(hashOID, &policy) != SECSuccess) ||
(policy & NSS_USE_ALG_IN_SSL_KX)) {
rv = sslBuffer_AppendNumber(buf, ss->ssl3.signatureSchemes[i], 2);
@ -12200,7 +12231,7 @@ ssl3_UnprotectRecord(sslSocket *ss,
* discard it before decrypting the rest.
*/
PRUint8 iv[MAX_IV_LENGTH];
int decoded;
unsigned int decoded;
ivLen = cipher_def->iv_size;
if (ivLen < 8 || ivLen > sizeof(iv)) {
@ -12248,12 +12279,12 @@ ssl3_UnprotectRecord(sslSocket *ss,
rType, isTLS, rVersion, IS_DTLS(ss), decryptedLen, &header);
PORT_Assert(rv == SECSuccess);
rv = spec->aead(&spec->keyMaterial,
PR_TRUE, /* do decrypt */
plaintext->buf, /* out */
(int *)&plaintext->len, /* outlen */
plaintext->space, /* maxout */
cText->buf->buf, /* in */
cText->buf->len, /* inlen */
PR_TRUE, /* do decrypt */
plaintext->buf, /* out */
&plaintext->len, /* outlen */
plaintext->space, /* maxout */
cText->buf->buf, /* in */
cText->buf->len, /* inlen */
SSL_BUFFER_BASE(&header), SSL_BUFFER_LEN(&header));
if (rv != SECSuccess) {
good = 0;
@ -12266,7 +12297,7 @@ ssl3_UnprotectRecord(sslSocket *ss,
/* decrypt from cText buf to plaintext. */
rv = spec->cipher(
spec->cipherContext, plaintext->buf, (int *)&plaintext->len,
spec->cipherContext, plaintext->buf, &plaintext->len,
plaintext->space, cText->buf->buf + ivLen, cText->buf->len - ivLen);
if (rv != SECSuccess) {
goto decrypt_loser;
@ -12548,7 +12579,7 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText)
rv = SECFailure;
} else {
#ifdef UNSAFE_FUZZER_MODE
rv = Null_Cipher(NULL, plaintext->buf, (int *)&plaintext->len,
rv = Null_Cipher(NULL, plaintext->buf, &plaintext->len,
plaintext->space, cText->buf->buf, cText->buf->len);
#else
/* IMPORTANT: Unprotect functions MUST NOT send alerts

View File

@ -407,7 +407,7 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
SSL_TRC(3, ("%d: SSL3[%d] Cannot gather data; fatal alert already sent",
SSL_GETPID(), ss->fd));
PORT_SetError(SSL_ERROR_HANDSHAKE_FAILED);
return SECFailure;
return -1;
}
SSL_TRC(30, ("%d: SSL3[%d]: ssl3_GatherCompleteHandshake",
@ -427,13 +427,6 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
processingEarlyData = ss->ssl3.hs.zeroRttState == ssl_0rtt_accepted;
/* If we have a detached record layer, don't ever gather. */
if (ss->recordWriteCallback) {
ssl_ReleaseSSL3HandshakeLock(ss);
PORT_SetError(PR_WOULD_BLOCK_ERROR);
return (int)SECFailure;
}
/* Without this, we may end up wrongly reporting
* SSL_ERROR_RX_UNEXPECTED_* errors if we receive any records from the
* peer while we are waiting to be restarted.
@ -441,7 +434,18 @@ ssl3_GatherCompleteHandshake(sslSocket *ss, int flags)
if (ss->ssl3.hs.restartTarget) {
ssl_ReleaseSSL3HandshakeLock(ss);
PORT_SetError(PR_WOULD_BLOCK_ERROR);
return (int)SECFailure;
return -1;
}
/* If we have a detached record layer, don't ever gather. */
if (ss->recordWriteCallback) {
PRBool done = ss->firstHsDone;
ssl_ReleaseSSL3HandshakeLock(ss);
if (done) {
return 1;
}
PORT_SetError(PR_WOULD_BLOCK_ERROR);
return -1;
}
ssl_ReleaseSSL3HandshakeLock(ss);
@ -663,7 +667,8 @@ SSLExp_RecordLayerData(PRFileDesc *fd, PRUint16 epoch,
* available to PR_Read(). */
if (contentType != ssl_ct_application_data) {
rv = ssl3_HandleNonApplicationData(ss, contentType, 0, 0, &ss->gs.buf);
if (rv != SECSuccess) {
/* This occasionally blocks, but that's OK here. */
if (rv != SECSuccess && PORT_GetError() != PR_WOULD_BLOCK_ERROR) {
goto loser;
}
}

View File

@ -626,6 +626,80 @@ typedef SECStatus(PR_CALLBACK *SSLRecordWriteCallback)(
PRUint16 * _writeEpoch), \
(fd, readEpoch, writeEpoch))
/*
* The following AEAD functions expose an AEAD primitive that uses a ciphersuite
* to set parameters. The ciphersuite determines the Hash function used by
* HKDF, the AEAD function, and the size of key and IV. This is only supported
* for TLS 1.3.
*
* The key and IV are generated using the TLS KDF with a custom label. That is
* HKDF-Expand-Label(secret, labelPrefix + " key" or " iv", "", L).
*
* The encrypt and decrypt functions use a nonce construction identical to that
* used in TLS. The lower bits of the IV are XORed with the 64-bit counter to
* produce the nonce. Otherwise, this is an AEAD interface similar to that
* described in RFC 5116.
*/
typedef struct SSLAeadContextStr SSLAeadContext;
#define SSL_MakeAead(version, cipherSuite, secret, \
labelPrefix, labelPrefixLen, ctx) \
SSL_EXPERIMENTAL_API("SSL_MakeAead", \
(PRUint16 _version, PRUint16 _cipherSuite, \
PK11SymKey * _secret, \
const char *_labelPrefix, \
unsigned int _labelPrefixLen, \
SSLAeadContext **_ctx), \
(version, cipherSuite, secret, \
labelPrefix, labelPrefixLen, ctx))
#define SSL_AeadEncrypt(ctx, counter, aad, aadLen, in, inLen, \
output, outputLen, maxOutputLen) \
SSL_EXPERIMENTAL_API("SSL_AeadEncrypt", \
(const SSLAeadContext *_ctx, PRUint64 _counter, \
const PRUint8 *_aad, unsigned int _aadLen, \
const PRUint8 *_in, unsigned int _inLen, \
PRUint8 *_out, unsigned int *_outLen, \
unsigned int _maxOut), \
(ctx, counter, aad, aadLen, in, inLen, \
output, outputLen, maxOutputLen))
#define SSL_AeadDecrypt(ctx, counter, aad, aadLen, in, inLen, \
output, outputLen, maxOutputLen) \
SSL_EXPERIMENTAL_API("SSL_AeadDecrypt", \
(const SSLAeadContext *_ctx, PRUint64 _counter, \
const PRUint8 *_aad, unsigned int _aadLen, \
const PRUint8 *_in, unsigned int _inLen, \
PRUint8 *_output, unsigned int *_outLen, \
unsigned int _maxOut), \
(ctx, counter, aad, aadLen, in, inLen, \
output, outputLen, maxOutputLen))
#define SSL_DestroyAead(ctx) \
SSL_EXPERIMENTAL_API("SSL_DestroyAead", \
(SSLAeadContext * _ctx), \
(ctx))
/* SSL_HkdfExtract and SSL_HkdfExpandLabel implement the functions from TLS,
* using the version and ciphersuite to set parameters. This allows callers to
* use these TLS functions as a KDF. This is only supported for TLS 1.3. */
#define SSL_HkdfExtract(version, cipherSuite, salt, ikm, keyp) \
SSL_EXPERIMENTAL_API("SSL_HkdfExtract", \
(PRUint16 _version, PRUint16 _cipherSuite, \
PK11SymKey * _salt, PK11SymKey * _ikm, \
PK11SymKey * *_keyp), \
(version, cipherSuite, salt, ikm, keyp))
#define SSL_HkdfDeriveSecret(version, cipherSuite, prk, \
label, labelLen, keyp) \
SSL_EXPERIMENTAL_API("SSL_HkdfDeriveSecret", \
(PRUint16 _version, PRUint16 _cipherSuite, \
PK11SymKey * _prk, \
const char *_label, unsigned int _labelLen, \
PK11SymKey **_keyp), \
(version, cipherSuite, prk, \
label, labelLen, keyp))
/* Deprecated experimental APIs */
#define SSL_UseAltServerHelloType(fd, enable) SSL_DEPRECATED_EXPERIMENTAL_API

View File

@ -1209,9 +1209,9 @@ extern SECStatus ssl_CipherPrefSetDefault(PRInt32 which, PRBool enabled);
extern SECStatus ssl3_ConstrainRangeByPolicy(void);
extern SECStatus ssl3_InitState(sslSocket *ss);
extern SECStatus Null_Cipher(void *ctx, unsigned char *output, int *outputLen,
int maxOutputLen, const unsigned char *input,
int inputLen);
extern SECStatus Null_Cipher(void *ctx, unsigned char *output, unsigned int *outputLen,
unsigned int maxOutputLen, const unsigned char *input,
unsigned int inputLen);
extern void ssl3_RestartHandshakeHashes(sslSocket *ss);
extern SECStatus ssl3_UpdateHandshakeHashes(sslSocket *ss,
const unsigned char *b,
@ -1663,6 +1663,8 @@ SECStatus ssl3_FillInCachedSID(sslSocket *ss, sslSessionID *sid,
const ssl3CipherSuiteDef *ssl_LookupCipherSuiteDef(ssl3CipherSuite suite);
const ssl3CipherSuiteCfg *ssl_LookupCipherSuiteCfg(ssl3CipherSuite suite,
const ssl3CipherSuiteCfg *suites);
PRBool ssl3_CipherSuiteAllowedForVersionRange(ssl3CipherSuite cipherSuite,
const SSLVersionRange *vrange);
SECStatus ssl3_SelectServerCert(sslSocket *ss);
SECStatus ssl_PickSignatureScheme(sslSocket *ss,
@ -1758,6 +1760,25 @@ SECStatus SSLExp_GetCurrentEpoch(PRFileDesc *fd, PRUint16 *readEpoch,
#define SSLResumptionTokenVersion 2
SECStatus SSLExp_MakeAead(PRUint16 version, PRUint16 cipherSuite, PK11SymKey *secret,
const char *labelPrefix, unsigned int labelPrefixLen,
SSLAeadContext **ctx);
SECStatus SSLExp_DestroyAead(SSLAeadContext *ctx);
SECStatus SSLExp_AeadEncrypt(const SSLAeadContext *ctx, PRUint64 counter,
const PRUint8 *aad, unsigned int aadLen,
const PRUint8 *plaintext, unsigned int plaintextLen,
PRUint8 *out, unsigned int *outLen, unsigned int maxOut);
SECStatus SSLExp_AeadDecrypt(const SSLAeadContext *ctx, PRUint64 counter,
const PRUint8 *aad, unsigned int aadLen,
const PRUint8 *plaintext, unsigned int plaintextLen,
PRUint8 *out, unsigned int *outLen, unsigned int maxOut);
SECStatus SSLExp_HkdfExtract(PRUint16 version, PRUint16 cipherSuite,
PK11SymKey *salt, PK11SymKey *ikm, PK11SymKey **keyp);
SECStatus SSLExp_HkdfDeriveSecret(PRUint16 version, PRUint16 cipherSuite, PK11SymKey *prk,
const char *label, unsigned int labelLen,
PK11SymKey **key);
SEC_END_PROTOS
#if defined(XP_UNIX) || defined(XP_OS2) || defined(XP_BEOS)

View File

@ -0,0 +1,249 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* SSL Primitives: Public HKDF and AEAD Functions
*
* 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 "keyhi.h"
#include "pk11pub.h"
#include "sechash.h"
#include "ssl.h"
#include "sslexp.h"
#include "sslerr.h"
#include "sslproto.h"
#include "sslimpl.h"
#include "tls13con.h"
#include "tls13hkdf.h"
struct SSLAeadContextStr {
CK_MECHANISM_TYPE mech;
ssl3KeyMaterial keys;
};
static SECStatus
tls13_GetHashAndCipher(PRUint16 version, PRUint16 cipherSuite,
SSLHashType *hash, const ssl3BulkCipherDef **cipher)
{
if (version < SSL_LIBRARY_VERSION_TLS_1_3) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
// Lookup and check the suite.
SSLVersionRange vrange = { version, version };
if (!ssl3_CipherSuiteAllowedForVersionRange(cipherSuite, &vrange)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
const ssl3CipherSuiteDef *suiteDef = ssl_LookupCipherSuiteDef(cipherSuite);
const ssl3BulkCipherDef *cipherDef = ssl_GetBulkCipherDef(suiteDef);
if (cipherDef->type != type_aead) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
*hash = suiteDef->prf_hash;
*cipher = cipherDef;
return SECSuccess;
}
SECStatus
SSLExp_MakeAead(PRUint16 version, PRUint16 cipherSuite, PK11SymKey *secret,
const char *labelPrefix, unsigned int labelPrefixLen,
SSLAeadContext **ctx)
{
SSLAeadContext *out = NULL;
char label[255]; // Maximum length label.
static const char *const keySuffix = "key";
static const char *const ivSuffix = "iv";
PORT_Assert(strlen(keySuffix) >= strlen(ivSuffix));
if (secret == NULL || ctx == NULL ||
(labelPrefix == NULL && labelPrefixLen > 0) ||
labelPrefixLen + strlen(keySuffix) > sizeof(label)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
goto loser;
}
SSLHashType hash;
const ssl3BulkCipherDef *cipher;
SECStatus rv = tls13_GetHashAndCipher(version, cipherSuite,
&hash, &cipher);
if (rv != SECSuccess) {
goto loser; /* Code already set. */
}
out = PORT_ZNew(SSLAeadContext);
if (out == NULL) {
goto loser;
}
out->mech = ssl3_Alg2Mech(cipher->calg);
memcpy(label, labelPrefix, labelPrefixLen);
memcpy(label + labelPrefixLen, ivSuffix, strlen(ivSuffix));
unsigned int labelLen = labelPrefixLen + strlen(ivSuffix);
unsigned int ivLen = cipher->iv_size + cipher->explicit_nonce_size;
rv = tls13_HkdfExpandLabelRaw(secret, hash,
NULL, 0, // Handshake hash.
label, labelLen,
out->keys.iv, ivLen);
if (rv != SECSuccess) {
goto loser;
}
memcpy(label + labelPrefixLen, keySuffix, strlen(keySuffix));
labelLen = labelPrefixLen + strlen(keySuffix);
rv = tls13_HkdfExpandLabel(secret, hash,
NULL, 0, // Handshake hash.
label, labelLen,
out->mech, cipher->key_size, &out->keys.key);
if (rv != SECSuccess) {
goto loser;
}
*ctx = out;
return SECSuccess;
loser:
SSLExp_DestroyAead(out);
return SECFailure;
}
SECStatus
SSLExp_DestroyAead(SSLAeadContext *ctx)
{
if (!ctx) {
return SECSuccess;
}
PK11_FreeSymKey(ctx->keys.key);
PORT_ZFree(ctx, sizeof(*ctx));
return SECSuccess;
}
/* Bug 1529440 exists to refactor this and the other AEAD uses. */
static SECStatus
ssl_AeadInner(const SSLAeadContext *ctx, PRBool decrypt, PRUint64 counter,
const PRUint8 *aad, unsigned int aadLen,
const PRUint8 *plaintext, unsigned int plaintextLen,
PRUint8 *out, unsigned int *outLen, unsigned int maxOut)
{
if (ctx == NULL || (aad == NULL && aadLen > 0) || plaintext == NULL ||
out == NULL || outLen == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
// Setup the nonce.
PRUint8 nonce[12] = { 0 };
sslBuffer nonceBuf = SSL_BUFFER_FIXED(nonce + sizeof(nonce) - sizeof(counter),
sizeof(counter));
SECStatus rv = sslBuffer_AppendNumber(&nonceBuf, counter, sizeof(counter));
if (rv != SECSuccess) {
PORT_Assert(0);
return SECFailure;
}
for (int i = 0; i < sizeof(nonce); ++i) {
nonce[i] ^= ctx->keys.iv[i];
}
// Build AEAD parameters.
CK_GCM_PARAMS gcmParams = { 0 };
CK_NSS_AEAD_PARAMS aeadParams = { 0 };
unsigned char *params;
unsigned int paramsLen;
switch (ctx->mech) {
case CKM_AES_GCM:
gcmParams.pIv = nonce;
gcmParams.ulIvLen = sizeof(nonce);
gcmParams.pAAD = (unsigned char *)aad; // const cast :(
gcmParams.ulAADLen = aadLen;
gcmParams.ulTagBits = 128; // GCM measures in bits.
params = (unsigned char *)&gcmParams;
paramsLen = sizeof(gcmParams);
break;
case CKM_NSS_CHACHA20_POLY1305:
aeadParams.pNonce = nonce;
aeadParams.ulNonceLen = sizeof(nonce);
aeadParams.pAAD = (unsigned char *)aad; // const cast :(
aeadParams.ulAADLen = aadLen;
aeadParams.ulTagLen = 16; // AEAD measures in octets.
params = (unsigned char *)&aeadParams;
paramsLen = sizeof(aeadParams);
break;
default:
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
return tls13_AEAD(&ctx->keys, decrypt, out, outLen, maxOut,
plaintext, plaintextLen, ctx->mech, params, paramsLen);
}
SECStatus
SSLExp_AeadEncrypt(const SSLAeadContext *ctx, PRUint64 counter,
const PRUint8 *aad, unsigned int aadLen,
const PRUint8 *plaintext, unsigned int plaintextLen,
PRUint8 *out, unsigned int *outLen, unsigned int maxOut)
{
// false == encrypt
return ssl_AeadInner(ctx, PR_FALSE, counter, aad, aadLen,
plaintext, plaintextLen, out, outLen, maxOut);
}
SECStatus
SSLExp_AeadDecrypt(const SSLAeadContext *ctx, PRUint64 counter,
const PRUint8 *aad, unsigned int aadLen,
const PRUint8 *plaintext, unsigned int plaintextLen,
PRUint8 *out, unsigned int *outLen, unsigned int maxOut)
{
// true == decrypt
return ssl_AeadInner(ctx, PR_TRUE, counter, aad, aadLen,
plaintext, plaintextLen, out, outLen, maxOut);
}
SECStatus
SSLExp_HkdfExtract(PRUint16 version, PRUint16 cipherSuite,
PK11SymKey *salt, PK11SymKey *ikm, PK11SymKey **keyp)
{
if (keyp == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
SSLHashType hash;
const ssl3BulkCipherDef *cipher; /* Unused here. */
SECStatus rv = tls13_GetHashAndCipher(version, cipherSuite,
&hash, &cipher);
if (rv != SECSuccess) {
return SECFailure; /* Code already set. */
}
return tls13_HkdfExtract(salt, ikm, hash, keyp);
}
SECStatus
SSLExp_HkdfDeriveSecret(PRUint16 version, PRUint16 cipherSuite, PK11SymKey *prk,
const char *label, unsigned int labelLen,
PK11SymKey **keyp)
{
if (prk == NULL || keyp == NULL ||
label == NULL || labelLen == 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
SSLHashType hash;
const ssl3BulkCipherDef *cipher; /* Unused here. */
SECStatus rv = tls13_GetHashAndCipher(version, cipherSuite,
&hash, &cipher);
if (rv != SECSuccess) {
return SECFailure; /* Code already set. */
}
return tls13_HkdfExpandLabel(prk, hash, NULL, 0, label, labelLen,
tls13_GetHkdfMechanismForHash(hash),
tls13_GetHashSizeForHash(hash), keyp);
}

View File

@ -4041,6 +4041,9 @@ struct {
void *function;
} ssl_experimental_functions[] = {
#ifndef SSL_DISABLE_EXPERIMENTAL_API
EXP(AeadDecrypt),
EXP(AeadEncrypt),
EXP(DestroyAead),
EXP(DestroyResumptionTokenInfo),
EXP(EnableESNI),
EXP(EncodeESNIKeys),
@ -4049,7 +4052,10 @@ struct {
EXP(GetResumptionTokenInfo),
EXP(HelloRetryRequestCallback),
EXP(InstallExtensionHooks),
EXP(HkdfExtract),
EXP(HkdfDeriveSecret),
EXP(KeyUpdate),
EXP(MakeAead),
EXP(RecordLayerData),
EXP(RecordLayerWriteCallback),
EXP(SecretCallback),

View File

@ -101,20 +101,20 @@ typedef struct {
typedef SECStatus (*SSLCipher)(void *context,
unsigned char *out,
int *outlen,
int maxout,
unsigned int *outlen,
unsigned int maxout,
const unsigned char *in,
int inlen);
unsigned int inlen);
typedef SECStatus (*SSLAEADCipher)(
ssl3KeyMaterial *keys,
const ssl3KeyMaterial *keys,
PRBool doDecrypt,
unsigned char *out,
int *outlen,
int maxout,
unsigned int *outlen,
unsigned int maxout,
const unsigned char *in,
int inlen,
unsigned int inlen,
const unsigned char *additionalData,
int additionalDataLen);
unsigned int additionalDataLen);
/* The DTLS anti-replay window in number of packets. Defined here because we
* need it in the cipher spec. Note that this is a ring buffer but left and

View File

@ -28,18 +28,24 @@
static SECStatus tls13_SetCipherSpec(sslSocket *ss, PRUint16 epoch,
SSLSecretDirection install,
PRBool deleteSecret);
static SECStatus tls13_AESGCM(
ssl3KeyMaterial *keys,
PRBool doDecrypt,
unsigned char *out, int *outlen, int maxout,
const unsigned char *in, int inlen,
const unsigned char *additionalData, int additionalDataLen);
static SECStatus tls13_ChaCha20Poly1305(
ssl3KeyMaterial *keys,
PRBool doDecrypt,
unsigned char *out, int *outlen, int maxout,
const unsigned char *in, int inlen,
const unsigned char *additionalData, int additionalDataLen);
static SECStatus tls13_AESGCM(const ssl3KeyMaterial *keys,
PRBool doDecrypt,
unsigned char *out,
unsigned int *outlen,
unsigned int maxout,
const unsigned char *in,
unsigned int inlen,
const unsigned char *additionalData,
unsigned int additionalDataLen);
static SECStatus tls13_ChaCha20Poly1305(const ssl3KeyMaterial *keys,
PRBool doDecrypt,
unsigned char *out,
unsigned int *outlen,
unsigned int maxout,
const unsigned char *in,
unsigned int inlen,
const unsigned char *additionalData,
unsigned int additionalDataLen);
static SECStatus tls13_SendServerHelloSequence(sslSocket *ss);
static SECStatus tls13_SendEncryptedExtensions(sslSocket *ss);
static void tls13_SetKeyExchangeType(sslSocket *ss, const sslNamedGroupDef *group);
@ -293,7 +299,7 @@ tls13_GetHashSize(const sslSocket *ss)
return tls13_GetHashSizeForHash(tls13_GetHash(ss));
}
static CK_MECHANISM_TYPE
CK_MECHANISM_TYPE
tls13_GetHkdfMechanismForHash(SSLHashType hash)
{
switch (hash) {
@ -3711,7 +3717,7 @@ tls13_DestroyEarlyData(PRCList *list)
* See RFC 5288 and https://tools.ietf.org/html/draft-ietf-tls-chacha20-poly1305-04#section-2
*/
static void
tls13_WriteNonce(ssl3KeyMaterial *keys,
tls13_WriteNonce(const ssl3KeyMaterial *keys,
const unsigned char *seqNumBuf, unsigned int seqNumLen,
unsigned char *nonce, unsigned int nonceLen)
{
@ -3734,41 +3740,35 @@ tls13_WriteNonce(ssl3KeyMaterial *keys,
* a sequence number. In TLS 1.3 there is no additional data so this value is
* just the encoded sequence number.
*/
static SECStatus
tls13_AEAD(ssl3KeyMaterial *keys, PRBool doDecrypt,
unsigned char *out, int *outlen, int maxout,
const unsigned char *in, int inlen,
SECStatus
tls13_AEAD(const ssl3KeyMaterial *keys, PRBool doDecrypt,
unsigned char *out, unsigned int *outlen, unsigned int maxout,
const unsigned char *in, unsigned int inlen,
CK_MECHANISM_TYPE mechanism,
unsigned char *aeadParams, unsigned int aeadParamLength)
{
SECStatus rv;
unsigned int uOutLen = 0;
SECItem param = {
siBuffer, aeadParams, aeadParamLength
};
if (doDecrypt) {
rv = PK11_Decrypt(keys->key, mechanism, &param,
out, &uOutLen, maxout, in, inlen);
} else {
rv = PK11_Encrypt(keys->key, mechanism, &param,
out, &uOutLen, maxout, in, inlen);
return PK11_Decrypt(keys->key, mechanism, &param,
out, outlen, maxout, in, inlen);
}
*outlen = (int)uOutLen;
return rv;
return PK11_Encrypt(keys->key, mechanism, &param,
out, outlen, maxout, in, inlen);
}
static SECStatus
tls13_AESGCM(ssl3KeyMaterial *keys,
tls13_AESGCM(const ssl3KeyMaterial *keys,
PRBool doDecrypt,
unsigned char *out,
int *outlen,
int maxout,
unsigned int *outlen,
unsigned int maxout,
const unsigned char *in,
int inlen,
unsigned int inlen,
const unsigned char *additionalData,
int additionalDataLen)
unsigned int additionalDataLen)
{
CK_GCM_PARAMS gcmParams;
unsigned char nonce[12];
@ -3789,11 +3789,11 @@ tls13_AESGCM(ssl3KeyMaterial *keys,
}
static SECStatus
tls13_ChaCha20Poly1305(ssl3KeyMaterial *keys, PRBool doDecrypt,
unsigned char *out, int *outlen, int maxout,
const unsigned char *in, int inlen,
tls13_ChaCha20Poly1305(const ssl3KeyMaterial *keys, PRBool doDecrypt,
unsigned char *out, unsigned int *outlen, unsigned int maxout,
const unsigned char *in, unsigned int inlen,
const unsigned char *additionalData,
int additionalDataLen)
unsigned int additionalDataLen)
{
CK_NSS_AEAD_PARAMS aeadParams;
unsigned char nonce[12];
@ -5145,7 +5145,7 @@ tls13_ProtectRecord(sslSocket *ss,
PRBool needsLength;
PRUint8 aad[21];
unsigned int aadLen;
int len;
unsigned int len;
PORT_Assert(cipher_def->type == type_aead);
@ -5266,12 +5266,12 @@ tls13_UnprotectRecord(sslSocket *ss,
return SECFailure;
}
rv = spec->aead(&spec->keyMaterial,
PR_TRUE, /* do decrypt */
plaintext->buf, /* out */
(int *)&plaintext->len, /* outlen */
plaintext->space, /* maxout */
cText->buf->buf, /* in */
cText->buf->len, /* inlen */
PR_TRUE, /* do decrypt */
plaintext->buf, /* out */
&plaintext->len, /* outlen */
plaintext->space, /* maxout */
cText->buf->buf, /* in */
cText->buf->len, /* inlen */
aad, aadLen);
if (rv != SECSuccess) {
SSL_TRC(3,

View File

@ -52,6 +52,7 @@ SSLHashType tls13_GetHash(const sslSocket *ss);
unsigned int tls13_GetHashSizeForHash(SSLHashType hash);
unsigned int tls13_GetHashSize(const sslSocket *ss);
CK_MECHANISM_TYPE tls13_GetHkdfMechanism(sslSocket *ss);
CK_MECHANISM_TYPE tls13_GetHkdfMechanismForHash(SSLHashType hash);
SECStatus tls13_ComputeHash(sslSocket *ss, SSL3Hashes *hashes,
const PRUint8 *buf, unsigned int len);
SECStatus tls13_ComputeHandshakeHashes(sslSocket *ss,
@ -130,6 +131,11 @@ SECStatus tls13_SendKeyUpdate(sslSocket *ss, tls13KeyUpdateRequest request,
SECStatus SSLExp_KeyUpdate(PRFileDesc *fd, PRBool requestUpdate);
PRBool tls13_MaybeTls13(sslSocket *ss);
SSLAEADCipher tls13_GetAead(const ssl3BulkCipherDef *cipherDef);
SECStatus tls13_AEAD(const ssl3KeyMaterial *keys, PRBool doDecrypt,
unsigned char *out, unsigned int *outlen, unsigned int maxout,
const unsigned char *in, unsigned int inlen,
CK_MECHANISM_TYPE mechanism,
unsigned char *aeadParams, unsigned int aeadParamLength);
void tls13_SetSpecRecordVersion(sslSocket *ss, ssl3CipherSpec *spec);
SECStatus SSLExp_SendCertificateRequest(PRFileDesc *fd);

View File

@ -721,8 +721,8 @@ tls13_ServerGetEsniAEAD(const sslSocket *ss, PRUint64 suite,
}
SECStatus
tls13_ServerDecryptEsniXtn(const sslSocket *ss, PRUint8 *in, unsigned int inLen,
PRUint8 *out, int *outLen, int maxLen)
tls13_ServerDecryptEsniXtn(const sslSocket *ss, const PRUint8 *in, unsigned int inLen,
PRUint8 *out, unsigned int *outLen, unsigned int maxLen)
{
sslReader rdr = SSL_READER(in, inLen);
PRUint64 suite;

View File

@ -45,7 +45,7 @@ SECStatus tls13_ComputeESNIKeys(const sslSocket *ss,
SECStatus tls13_FormatEsniAADInput(sslBuffer *aadInput,
PRUint8 *keyShare, unsigned int keyShareLen);
SECStatus tls13_ServerDecryptEsniXtn(const sslSocket *ss, PRUint8 *in, unsigned int inLen,
PRUint8 *out, int *outLen, int maxLen);
SECStatus tls13_ServerDecryptEsniXtn(const sslSocket *ss, const PRUint8 *in, unsigned int inLen,
PRUint8 *out, unsigned int *outLen, unsigned int maxLen);
#endif

View File

@ -1140,7 +1140,7 @@ tls13_ClientSendEsniXtn(const sslSocket *ss, TLSExtensionData *xtnData,
ssl3KeyMaterial keyMat;
SSLAEADCipher aead;
PRUint8 outBuf[1024];
int outLen;
unsigned int outLen;
unsigned int sniStart;
unsigned int sniLen;
sslBuffer aadInput = SSL_BUFFER_EMPTY;
@ -1294,7 +1294,7 @@ tls13_ServerHandleEsniXtn(const sslSocket *ss, TLSExtensionData *xtnData,
{
sslReadBuffer buf;
PRUint8 *plainText = NULL;
int ptLen;
unsigned int ptLen;
SECStatus rv;
/* If we are doing < TLS 1.3, then ignore this. */

View File

@ -140,14 +140,13 @@ tls13_HkdfExpandLabel(PK11SymKey *prk, SSLHashType baseHash,
const char *kLabelPrefix = "tls13 ";
const unsigned int kLabelPrefixLen = strlen(kLabelPrefix);
if (handshakeHash) {
if (handshakeHashLen > 255) {
PORT_Assert(0);
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
} else {
PORT_Assert(!handshakeHashLen);
PORT_Assert(prk);
PORT_Assert(keyp);
if ((handshakeHashLen > 255) ||
(handshakeHash == NULL && handshakeHashLen > 0) ||
(labelLen + kLabelPrefixLen > 255)) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
/*

View File

@ -1,6 +1 @@
Date: Wed, 20 Sep 2000 00:00:01 -0700 (PDT)
From: alice@bogus.com
Subject: message Alice --> Bob
To: bob@bogus.com
This is a test message from Alice to Bob.

View File

@ -51,12 +51,14 @@ smime_init()
mkdir -p ${SMIMEDIR}
cd ${SMIMEDIR}
cp ${QADIR}/smime/alice.txt ${SMIMEDIR}
mkdir tb
}
smime_sign()
cms_sign()
{
HASH_CMD="-H ${HASH}"
SIG=sig.${HASH}
HASH_CMD="-H SHA${HASH}"
SIG=sig.SHA${HASH}
echo "$SCRIPTNAME: Signing Detached Message {$HASH} ------------------"
echo "cmsutil -S -T -N Alice ${HASH_CMD} -i alice.txt -d ${P_R_ALICEDIR} -p nss -o alice.d${SIG}"
@ -102,23 +104,166 @@ smime_sign()
echo "diff alice.txt alice-ec.data.${HASH}"
diff alice.txt alice-ec.data.${HASH}
html_msg $? 0 "Compare Attached Signed Data and Original (ECDSA w/ ${HASH})" "."
}
header_mime_from_to_subject="MIME-Version: 1.0
From: Alice@bogus.com
To: Bob@bogus.com
Subject: "
header_opaque_signed="Content-Type: application/pkcs7-mime; name=smime.p7m;
smime-type=signed-data
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=smime.p7m
Content-Description: S/MIME Cryptographic Signature
"
header_enveloped="Content-Type: application/pkcs7-mime; name=smime.p7m;
smime-type=enveloped-data
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=smime.p7m
Content-Description: S/MIME Encrypted Message
"
header_clearsigned="Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: quoted-printable
Content-Language: en-US
"
multipart_start="Content-Type: multipart/signed; protocol=\"application/pkcs7-signature\"; micalg=sha-HASHHASH; boundary=\"------------ms030903020902020502030404\"
This is a cryptographically signed message in MIME format.
--------------ms030903020902020502030404"
multipart_middle="
--------------ms030903020902020502030404
Content-Type: application/pkcs7-signature; name=smime.p7s
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=smime.p7s
Content-Description: S/MIME Cryptographic Signature
"
multipart_end="--------------ms030903020902020502030404--
"
header_plaintext="Content-Type: text/plain
"
CR=$(printf '\r')
mime_init()
{
OUT="tb/alice.mime"
echo "${header_clearsigned}" >>${OUT}
cat alice.txt >>${OUT}
sed -i"" "s/\$/${CR}/" ${OUT}
OUT="tb/alice.textplain"
echo "${header_plaintext}" >>${OUT}
cat alice.txt >>${OUT}
sed -i"" "s/\$/${CR}/" ${OUT}
}
smime_enveloped()
{
${PROFTOOL} ${BINDIR}/cmsutil -E -r bob@bogus.com -i tb/alice.mime -d ${P_R_ALICEDIR} -p nss -o tb/alice.mime.env
OUT="tb/alice.env.eml"
echo -n "${header_mime_from_to_subject}" >>${OUT}
echo "enveloped ${SIG}" >>${OUT}
echo "${header_enveloped}" >>${OUT}
cat "tb/alice.mime.env" | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT}
echo >>${OUT}
sed -i"" "s/\$/${CR}/" ${OUT}
}
smime_signed_enveloped()
{
SIG=sig.SHA${HASH}
${PROFTOOL} ${BINDIR}/cmsutil -S -T -N Alice ${HASH_CMD} -i tb/alice.mime -d ${P_R_ALICEDIR} -p nss -o tb/alice.mime.d${SIG}
OUT="tb/alice.d${SIG}.multipart"
echo "${multipart_start}" | sed "s/HASHHASH/${HASH}/" >>${OUT}
cat tb/alice.mime | sed 's/\r$//' >>${OUT}
echo "${multipart_middle}" >>${OUT}
cat tb/alice.mime.d${SIG} | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT}
echo "${multipart_end}" >>${OUT}
${PROFTOOL} ${BINDIR}/cmsutil -E -r bob@bogus.com -i ${OUT} -d ${P_R_ALICEDIR} -p nss -o ${OUT}.env
OUT="tb/alice.d${SIG}.multipart.eml"
echo -n "${header_mime_from_to_subject}" >>${OUT}
echo "clear-signed ${SIG}" >>${OUT}
cat "tb/alice.d${SIG}.multipart" >>${OUT}
sed -i"" "s/\$/$CR/" ${OUT}
OUT="tb/alice.d${SIG}.multipart.env.eml"
echo -n "${header_mime_from_to_subject}" >>${OUT}
echo "enveloped clear-signed $SIG" >>${OUT}
echo "$header_enveloped" >>${OUT}
cat "tb/alice.d${SIG}.multipart.env" | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT}
echo >>${OUT}
sed -i"" "s/\$/$CR/" ${OUT}
${PROFTOOL} ${BINDIR}/cmsutil -S -N Alice ${HASH_CMD} -i tb/alice.textplain -d ${P_R_ALICEDIR} -p nss -o tb/alice.textplain.${SIG}
OUT="tb/alice.${SIG}.opaque"
echo "$header_opaque_signed" >>${OUT}
cat tb/alice.textplain.${SIG} | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT}
${PROFTOOL} ${BINDIR}/cmsutil -E -r bob@bogus.com -i ${OUT} -d ${P_R_ALICEDIR} -p nss -o ${OUT}.env
OUT="tb/alice.${SIG}.opaque.eml"
echo -n "${header_mime_from_to_subject}" >>${OUT}
echo "opaque-signed $SIG" >>${OUT}
cat "tb/alice.${SIG}.opaque" >>${OUT}
echo >>${OUT}
sed -i"" "s/\$/$CR/" ${OUT}
OUT="tb/alice.${SIG}.opaque.env.eml"
echo -n "${header_mime_from_to_subject}" >>${OUT}
echo "enveloped opaque-signed $SIG" >>${OUT}
echo "$header_enveloped" >>$OUT
cat "tb/alice.${SIG}.opaque.env" | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT}
echo >>${OUT}
sed -i"" "s/\$/$CR/" ${OUT}
# bad messages below
OUT="tb/alice.d${SIG}.multipart.bad.eml"
echo -n "${header_mime_from_to_subject}" >>${OUT}
echo "BAD clear-signed $SIG" >>${OUT}
cat "tb/alice.d${SIG}.multipart" | sed 's/test message from Alice/FAKE message NOT from Alice/' >>${OUT}
sed -i"" "s/\$/$CR/" ${OUT}
OUT="tb/alice.d${SIG}.multipart.mismatch-econtent"
echo "${multipart_start}" | sed "s/HASHHASH/$HASH/" >>${OUT}
cat tb/alice.mime | sed 's/test message from Alice/FAKE message NOT from Alice/' | sed 's/\r$//' >>${OUT}
echo "${multipart_middle}" >>${OUT}
cat tb/alice.textplain.${SIG} | ${BINDIR}/btoa | sed 's/\r$//' >>${OUT}
echo "${multipart_end}" >>${OUT}
OUT="tb/alice.d${SIG}.multipart.mismatch-econtent.eml"
echo -n "${header_mime_from_to_subject}" >>${OUT}
echo "BAD mismatch-econtent $SIG" >>${OUT}
cat "tb/alice.d${SIG}.multipart.mismatch-econtent" >>${OUT}
sed -i"" "s/\$/$CR/" ${OUT}
}
smime_p7()
{
echo "$SCRIPTNAME: p7 util Data Tests ------------------------------"
echo "p7env -d ${P_R_ALICEDIR} -r Alice -i alice.txt -o alice_p7.env"
${PROFTOOL} ${BINDIR}/p7env -d ${P_R_ALICEDIR} -r Alice -i alice.txt -o alice.env
${PROFTOOL} ${BINDIR}/p7env -d ${P_R_ALICEDIR} -r Alice -i alice.txt -o alice_p7.env
html_msg $? 0 "Creating envelope for user Alice" "."
echo "p7content -d ${P_R_ALICEDIR} -i alice.env -o alice_p7.data"
${PROFTOOL} ${BINDIR}/p7content -d ${P_R_ALICEDIR} -i alice.env -o alice_p7.data -p nss
echo "p7content -d ${P_R_ALICEDIR} -i alice_p7.env -o alice_p7.data"
${PROFTOOL} ${BINDIR}/p7content -d ${P_R_ALICEDIR} -i alice_p7.env -o alice_p7.data -p nss
html_msg $? 0 "Verifying file delivered to user Alice" "."
sed -e '3,8p' -n alice_p7.data > alice_p7.data.sed
sed -e '3,3p' -n alice_p7.data > alice_p7.data.sed
echo "diff alice.txt alice_p7.data.sed"
diff alice.txt alice_p7.data.sed
@ -139,15 +284,21 @@ smime_p7()
########################################################################
smime_main()
{
mime_init
smime_enveloped
HASH=SHA1
smime_sign
HASH=SHA256
smime_sign
HASH=SHA384
smime_sign
HASH=SHA512
smime_sign
HASH="1"
cms_sign
smime_signed_enveloped
HASH="256"
cms_sign
smime_signed_enveloped
HASH="384"
cms_sign
smime_signed_enveloped
HASH="512"
cms_sign
smime_signed_enveloped
echo "$SCRIPTNAME: Enveloped Data Tests ------------------------------"
echo "cmsutil -E -r bob@bogus.com -i alice.txt -d ${P_R_ALICEDIR} -p nss \\"
@ -233,6 +384,16 @@ smime_main()
html_msg $? 0 "Compare Decoded and Original Data" "."
}
smime_data_tb()
{
${BINDIR}/pk12util -d ${P_R_ALICEDIR} -o tb/Alice.p12 -n Alice -K nss -W ""
${BINDIR}/pk12util -d ${P_R_BOBDIR} -o tb/Bob.p12 -n Bob -K nss -W ""
${BINDIR}/pk12util -d ${P_R_DAVEDIR} -o tb/Dave.p12 -n Dave -K nss -W ""
${BINDIR}/pk12util -d ${P_R_EVEDIR} -o tb/Eve.p12 -n Eve -K nss -W ""
CAOUT=tb/TestCA.pem
cat ${P_R_CADIR}/TestCA.ca.cert | sed 's/\r$//' | ${BINDIR}/btoa -w c >> ${CAOUT}
}
############################## smime_cleanup ###########################
# local shell function to finish this script (no exit since it might be
# sourced)
@ -248,6 +409,7 @@ smime_cleanup()
smime_init
smime_main
smime_data_tb
smime_p7
smime_cleanup

View File

@ -74,6 +74,8 @@
# SECT409R1
# SECT571K1
# SECT571R1
# Signatures:
# DSA
# Hashes:
# MD2
# MD4
@ -172,3 +174,4 @@
1 noECC SSL3 d allow=tls-version-min=tls1.0:tls-version-max=tls1.2 Disallow Version Exlicitly
1 noECC SSL3 d disallow=all_allow=hmac-sha1:sha256:rsa:des-ede3-cbc:tls-version-min=tls1.0:tls-version-max=tls1.2 Disallow Version Implicitly Narrow.
1 noECC SSL3 d disallow=all_allow=md2/all:md4/all:md5/all:sha1/all:sha256/all:sha384/all:sha512/all:hmac-sha1/all:hmac-sha224/all:hmac-sha256/all:hmac-sha384/all:hmac-sha512/all:hmac-md5/all:camellia128-cbc/all:camellia192-cbc/all:camellia256-cbc/all:seed-cbc/all:des-ede3-cbc/all:des-40-cbc/all:des-cbc/all:null-cipher/all:rc2/all:rc4/all:idea/all:rsa/all:rsa-export/all:dhe-rsa/all:dhe-dss/all:ecdhe-ecdsa/all:ecdhe-rsa/all:ecdh-ecdsa/all:ecdh-rsa/all:tls-version-min=tls1.0:tls-version-max=tls1.2 Disallow Version Implicitly.
0 noECC SSL3 d disallow=dsa Disallow DSA Signatures Explicitly.