Skip to content

Commit

Permalink
Bug 1346250 - Implement --import-key for nss-tool r=ttaubert
Browse files Browse the repository at this point in the history
Differential Revision: https://nss-review.dev.mozaws.net/D235

--HG--
extra : amend_source : af52e9ef8a98e77ced7ff9af55c454bc14220d82
  • Loading branch information
sg-dev1 committed Mar 10, 2017
1 parent fe432d9 commit 2badc79
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 35 deletions.
31 changes: 31 additions & 0 deletions nss-tool/common/util.cc
Expand Up @@ -4,6 +4,7 @@

#include "util.h"

#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}
2 changes: 2 additions & 0 deletions nss-tool/common/util.h
Expand Up @@ -9,6 +9,7 @@

#include <secmodt.h>
#include <string>
#include <vector>

enum PwDataType { PW_NONE = 0, PW_FROMFILE = 1, PW_PLAINTEXT = 2 };
typedef struct {
Expand All @@ -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__
96 changes: 63 additions & 33 deletions nss-tool/db/dbtool.cc
Expand Up @@ -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) &&
Expand Down Expand Up @@ -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"};

Expand All @@ -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) {
Expand All @@ -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;
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
}

Expand All @@ -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()));
Expand Down Expand Up @@ -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;
Expand All @@ -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));
Expand Down Expand Up @@ -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;
}
4 changes: 2 additions & 2 deletions nss-tool/db/dbtool.h
Expand Up @@ -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__

0 comments on commit 2badc79

Please sign in to comment.