Bug 1345368 - land NSS 09c491ef3b41, r=me

--HG--
extra : rebase_source : 586448bdfc1cb86dd086c39c9b20f98ac10cc98e
This commit is contained in:
Franziskus Kiefer 2017-03-13 06:01:21 +01:00
parent 269eb591be
commit e9489ae053
8 changed files with 119 additions and 56 deletions

View File

@ -1 +1 @@
848abc2061a4
09c491ef3b41

View File

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

View File

@ -12575,7 +12575,7 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf)
ssl3CipherSpec *crSpec;
SSL3ContentType rType;
sslBuffer *plaintext;
sslBuffer temp_buf;
sslBuffer temp_buf = { NULL, 0, 0 };
SSL3AlertDescription alert = internal_error;
PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
@ -12632,25 +12632,11 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf)
/* If we will be decompressing the buffer we need to decrypt somewhere
* other than into databuf */
if (crSpec->decompressor) {
temp_buf.buf = NULL;
temp_buf.space = 0;
plaintext = &temp_buf;
} else {
plaintext = databuf;
}
plaintext->len = 0; /* filled in by Unprotect call below. */
if (plaintext->space < MAX_FRAGMENT_LENGTH) {
rv = sslBuffer_Grow(plaintext, MAX_FRAGMENT_LENGTH + 2048);
if (rv != SECSuccess) {
ssl_ReleaseSpecReadLock(ss); /*************************/
SSL_DBG(("%d: SSL3[%d]: HandleRecord, tried to get %d bytes",
SSL_GETPID(), ss->fd, MAX_FRAGMENT_LENGTH + 2048));
/* sslBuffer_Grow has set a memory error code. */
/* Perhaps we should send an alert. (but we have no memory!) */
return SECFailure;
}
}
/* We're waiting for another ClientHello, which will appear unencrypted.
* Use the content type to tell whether this is should be discarded.
@ -12665,6 +12651,18 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf)
return SECSuccess;
}
if (plaintext->space < MAX_FRAGMENT_LENGTH) {
rv = sslBuffer_Grow(plaintext, MAX_FRAGMENT_LENGTH + 2048);
if (rv != SECSuccess) {
ssl_ReleaseSpecReadLock(ss); /*************************/
SSL_DBG(("%d: SSL3[%d]: HandleRecord, tried to get %d bytes",
SSL_GETPID(), ss->fd, MAX_FRAGMENT_LENGTH + 2048));
/* sslBuffer_Grow has set a memory error code. */
/* Perhaps we should send an alert. (but we have no memory!) */
return SECFailure;
}
}
#ifdef UNSAFE_FUZZER_MODE
rv = Null_Cipher(NULL, plaintext->buf, (int *)&plaintext->len,
plaintext->space, cText->buf->buf, cText->buf->len);
@ -12686,6 +12684,9 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf)
SSL_DBG(("%d: SSL3[%d]: decryption failed", SSL_GETPID(), ss->fd));
/* Clear the temp buffer used for decompression upon failure. */
sslBuffer_Clear(&temp_buf);
if (IS_DTLS(ss) ||
(ss->sec.isServer &&
ss->ssl3.hs.zeroRttIgnore == ssl_0rtt_ignore_trial)) {
@ -12730,7 +12731,7 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf)
SSL3_COMPRESSION_MAX_EXPANSION));
/* sslBuffer_Grow has set a memory error code. */
/* Perhaps we should send an alert. (but we have no memory!) */
PORT_Free(plaintext->buf);
sslBuffer_Clear(&temp_buf);
return SECFailure;
}
}
@ -12768,12 +12769,12 @@ ssl3_HandleRecord(sslSocket *ss, SSL3Ciphertext *cText, sslBuffer *databuf)
}
}
PORT_Free(plaintext->buf);
sslBuffer_Clear(&temp_buf);
PORT_SetError(err);
return SECFailure;
}
PORT_Free(plaintext->buf);
sslBuffer_Clear(&temp_buf);
}
/*

View File

@ -478,7 +478,7 @@ sslBuffer_Append(sslBuffer *b, const void *data, unsigned int len)
void
sslBuffer_Clear(sslBuffer *b)
{
if (b->len > 0) {
if (b->buf) {
PORT_Free(b->buf);
b->buf = NULL;
b->len = 0;

View File

@ -4,6 +4,7 @@
#include "util.h"
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
@ -73,6 +74,17 @@ static char *GetModulePassword(PK11SlotInfo *slot, int retry, void *arg) {
return nullptr;
}
static std::vector<char> ReadFromIstream(std::istream &is) {
std::vector<char> certData;
while (is) {
char buf[1024];
is.read(buf, sizeof(buf));
certData.insert(certData.end(), buf, buf + is.gcount());
}
return certData;
}
bool InitSlotPassword(void) {
ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
if (slot.get() == nullptr) {
@ -133,3 +145,22 @@ std::string StringToHex(const ScopedSECItem &input) {
return ss.str();
}
std::vector<char> ReadInputData(std::string &dataPath) {
std::vector<char> data;
if (dataPath.empty()) {
std::cout << "No input file path given, using stdin." << std::endl;
data = ReadFromIstream(std::cin);
} else {
std::ifstream is(dataPath, std::ifstream::binary);
if (is.good()) {
data = ReadFromIstream(is);
} else {
std::cerr << "IO Error when opening " << dataPath << std::endl;
std::cerr << "Input file does not exist or you don't have permissions."
<< std::endl;
}
}
return data;
}

View File

@ -9,6 +9,7 @@
#include <secmodt.h>
#include <string>
#include <vector>
enum PwDataType { PW_NONE = 0, PW_FROMFILE = 1, PW_PLAINTEXT = 2 };
typedef struct {
@ -19,5 +20,6 @@ typedef struct {
bool InitSlotPassword(void);
bool DBLoginIfNeeded(const ScopedPK11SlotInfo &slot);
std::string StringToHex(const ScopedSECItem &input);
std::vector<char> ReadInputData(std::string &dataPath);
#endif // util_h__

View File

@ -8,27 +8,32 @@
#include "util.h"
#include <dirent.h>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <memory>
#include <regex>
#include <sstream>
#include <cert.h>
#include <certdb.h>
#include <nss.h>
#include <pk11pub.h>
#include <prerror.h>
#include <prio.h>
const std::vector<std::string> kCommandArgs({"--create", "--list-certs",
"--import-cert", "--list-keys"});
"--import-cert", "--list-keys",
"--import-key"});
static bool HasSingleCommandArgument(const ArgParser &parser) {
auto pred = [&](const std::string &cmd) { return parser.Has(cmd); };
return std::count_if(kCommandArgs.begin(), kCommandArgs.end(), pred) == 1;
}
static bool HasArgumentRequiringWriteAccess(const ArgParser &parser) {
return parser.Has("--create") || parser.Has("--import-cert") ||
parser.Has("--import-key");
}
static std::string PrintFlags(unsigned int flags) {
std::stringstream ss;
if ((flags & CERTDB_VALID_CA) && !(flags & CERTDB_TRUSTED_CA) &&
@ -62,17 +67,6 @@ static std::string PrintFlags(unsigned int flags) {
return ss.str();
}
static std::vector<char> ReadFromIstream(std::istream &is) {
std::vector<char> certData;
while (is) {
char buf[1024];
is.read(buf, sizeof(buf));
certData.insert(certData.end(), buf, buf + is.gcount());
}
return certData;
}
static const char *const keyTypeName[] = {"null", "rsa", "dsa", "fortezza",
"dh", "kea", "ec"};
@ -83,6 +77,7 @@ void DBTool::Usage() {
std::cerr << " --import-cert [<path>] --name <name> [--trusts <trusts>]"
<< std::endl;
std::cerr << " --list-keys" << std::endl;
std::cerr << " --import-key [<path> [-- name <name>]]" << std::endl;
}
bool DBTool::Run(const std::vector<std::string> &arguments) {
@ -95,7 +90,7 @@ bool DBTool::Run(const std::vector<std::string> &arguments) {
PRAccessHow how = PR_ACCESS_READ_OK;
bool readOnly = true;
if (parser.Has("--create") || parser.Has("--import-cert")) {
if (HasArgumentRequiringWriteAccess(parser)) {
how = PR_ACCESS_WRITE_OK;
readOnly = false;
}
@ -149,6 +144,8 @@ bool DBTool::Run(const std::vector<std::string> &arguments) {
}
} else if (parser.Has("--list-keys")) {
ret = ListKeys();
} else if (parser.Has("--import-key")) {
ret = ImportKey(parser);
}
// shutdown nss
@ -233,6 +230,7 @@ bool DBTool::ImportCertificate(const ArgParser &parser) {
if (!parser.Has("--name")) {
std::cerr << "A name (--name) is required to import a certificate."
<< std::endl;
Usage();
return false;
}
@ -250,27 +248,13 @@ bool DBTool::ImportCertificate(const ArgParser &parser) {
return false;
}
ScopedPK11SlotInfo slot = ScopedPK11SlotInfo(PK11_GetInternalKeySlot());
ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
if (slot.get() == nullptr) {
std::cerr << "Error: Init PK11SlotInfo failed!" << std::endl;
return false;
}
std::vector<char> certData;
if (derFilePath.empty()) {
std::cout << "No Certificate file path given, using stdin." << std::endl;
certData = ReadFromIstream(std::cin);
} else {
std::ifstream is(derFilePath, std::ifstream::binary);
if (!is.good()) {
std::cerr << "IO Error when opening " << derFilePath << std::endl;
std::cerr
<< "Certificate file does not exist or you don't have permissions."
<< std::endl;
return false;
}
certData = ReadFromIstream(is);
}
std::vector<char> certData = ReadInputData(derFilePath);
ScopedCERTCertificate cert(
CERT_DecodeCertFromPackage(certData.data(), certData.size()));
@ -300,7 +284,7 @@ bool DBTool::ImportCertificate(const ArgParser &parser) {
}
bool DBTool::ListKeys() {
ScopedPK11SlotInfo slot = ScopedPK11SlotInfo(PK11_GetInternalKeySlot());
ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
if (slot.get() == nullptr) {
std::cerr << "Error: Init PK11SlotInfo failed!" << std::endl;
return false;
@ -322,7 +306,7 @@ bool DBTool::ListKeys() {
for (node = PRIVKEY_LIST_HEAD(list.get());
!PRIVKEY_LIST_END(node, list.get()); node = PRIVKEY_LIST_NEXT(node)) {
char *keyNameRaw = PK11_GetPrivateKeyNickname(node->key);
std::string keyName(keyNameRaw ? "" : keyNameRaw);
std::string keyName(keyNameRaw ? keyNameRaw : "");
if (keyName.empty()) {
ScopedCERTCertificate cert(PK11_GetCertFromPrivateKey(node->key));
@ -367,3 +351,49 @@ bool DBTool::ListKeys() {
return true;
}
bool DBTool::ImportKey(const ArgParser &parser) {
std::string privKeyFilePath = parser.Get("--import-key");
std::string name;
if (parser.Has("--name")) {
name = parser.Get("--name");
}
ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
if (slot.get() == nullptr) {
std::cerr << "Error: Init PK11SlotInfo failed!" << std::endl;
return false;
}
if (!DBLoginIfNeeded(slot)) {
return false;
}
std::vector<char> privKeyData = ReadInputData(privKeyFilePath);
if (privKeyData.empty()) {
return false;
}
SECItem pkcs8PrivKeyItem = {
siBuffer, reinterpret_cast<unsigned char *>(privKeyData.data()),
static_cast<unsigned int>(privKeyData.size())};
SECItem nickname = {siBuffer, nullptr, 0};
if (!name.empty()) {
nickname.data = const_cast<unsigned char *>(
reinterpret_cast<const unsigned char *>(name.c_str()));
nickname.len = static_cast<unsigned int>(name.size());
}
SECStatus rv = PK11_ImportDERPrivateKeyInfo(
slot.get(), &pkcs8PrivKeyItem,
nickname.data == nullptr ? nullptr : &nickname, nullptr /*publicValue*/,
true /*isPerm*/, false /*isPrivate*/, KU_ALL, nullptr);
if (rv != SECSuccess) {
std::cerr << "Importing a private key in DER format failed with error "
<< PR_ErrorToName(PR_GetError()) << std::endl;
return false;
}
std::cout << "Key import succeeded." << std::endl;
return true;
}

View File

@ -13,13 +13,13 @@ class DBTool {
public:
bool Run(const std::vector<std::string>& arguments);
void Usage();
private:
void Usage();
bool PathHasDBFiles(std::string path);
void ListCertificates();
bool ImportCertificate(const ArgParser& parser);
bool ListKeys();
bool ImportKey(const ArgParser& parser);
};
#endif // dbtool_h__