mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-21 01:05:45 +00:00
Bug 1523175 - land NSS f7be0a534e89 UPGRADE_NSS_RELEASE, r=me
--HG-- extra : rebase_source : 373a3bcc93e21eef7dcc6e1208419b3ef58b87b3
This commit is contained in:
parent
599b9792dc
commit
3a5a08c197
@ -1 +1 @@
|
||||
1f04eea8834a
|
||||
f7be0a534e89
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -10,3 +10,4 @@
|
||||
*/
|
||||
|
||||
#error "Do not include this header 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
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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));
|
||||
|
@ -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',
|
||||
|
217
security/nss/gtests/ssl_gtest/ssl_primitive_unittest.cc
Normal file
217
security/nss/gtests/ssl_gtest/ssl_primitive_unittest.cc
Normal 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
|
@ -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.
|
||||
|
@ -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_;
|
||||
|
@ -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() {
|
||||
|
@ -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();
|
||||
|
@ -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));
|
||||
|
@ -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_, ¶m, out, &uoutlen, maxlen, in, inlen);
|
||||
} else {
|
||||
rv = PK11_Encrypt(key_, mech_, ¶m, 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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ CSRCS = \
|
||||
tls13replay.c \
|
||||
sslcert.c \
|
||||
sslgrp.c \
|
||||
sslprimitive.c \
|
||||
tls13esni.c \
|
||||
$(NULL)
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
'sslinit.c',
|
||||
'sslmutex.c',
|
||||
'sslnonce.c',
|
||||
'sslprimitive.c',
|
||||
'sslreveal.c',
|
||||
'sslsecur.c',
|
||||
'sslsnce.c',
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
249
security/nss/lib/ssl/sslprimitive.c
Normal file
249
security/nss/lib/ssl/sslprimitive.c
Normal 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);
|
||||
}
|
@ -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),
|
||||
|
@ -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
|
||||
|
@ -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, ¶m,
|
||||
out, &uOutLen, maxout, in, inlen);
|
||||
} else {
|
||||
rv = PK11_Encrypt(keys->key, mechanism, ¶m,
|
||||
out, &uOutLen, maxout, in, inlen);
|
||||
return PK11_Decrypt(keys->key, mechanism, ¶m,
|
||||
out, outlen, maxout, in, inlen);
|
||||
}
|
||||
*outlen = (int)uOutLen;
|
||||
|
||||
return rv;
|
||||
return PK11_Encrypt(keys->key, mechanism, ¶m,
|
||||
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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user