mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-26 12:20:56 +00:00
Bug 1345368 - land NSS 09c491ef3b41, r=me
--HG-- extra : rebase_source : 586448bdfc1cb86dd086c39c9b20f98ac10cc98e
This commit is contained in:
parent
269eb591be
commit
e9489ae053
@ -1 +1 @@
|
||||
848abc2061a4
|
||||
09c491ef3b41
|
||||
|
@ -10,4 +10,3 @@
|
||||
*/
|
||||
|
||||
#error "Do not include this header 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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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__
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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__
|
||||
|
Loading…
x
Reference in New Issue
Block a user