summaryrefslogtreecommitdiff
path: root/nss-tool
diff options
context:
space:
mode:
authorStefan Gschiel <stefan.gschiel.sg@gmail.com>2017-03-10 16:57:55 +0100
committerStefan Gschiel <stefan.gschiel.sg@gmail.com>2017-03-10 16:57:55 +0100
commita293142f83420788ec272aa42155d9728e0c6183 (patch)
tree412c7b0528bb0287aa303f64093a490e8e1f4306 /nss-tool
parent56ae3aea11e101dbf46096170c258897f1c00798 (diff)
downloadnss-hg-a293142f83420788ec272aa42155d9728e0c6183.tar.gz
Bug 1346250 - Implement --import-key for nss-tool r=ttaubert
Differential Revision: https://nss-review.dev.mozaws.net/D235
Diffstat (limited to 'nss-tool')
-rw-r--r--nss-tool/common/util.cc31
-rw-r--r--nss-tool/common/util.h2
-rw-r--r--nss-tool/db/dbtool.cc96
-rw-r--r--nss-tool/db/dbtool.h4
4 files changed, 98 insertions, 35 deletions
diff --git a/nss-tool/common/util.cc b/nss-tool/common/util.cc
index f8abf82b3..7cc4352c6 100644
--- a/nss-tool/common/util.cc
+++ b/nss-tool/common/util.cc
@@ -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;
+}
diff --git a/nss-tool/common/util.h b/nss-tool/common/util.h
index d4fc257ff..8b3b0f11e 100644
--- a/nss-tool/common/util.h
+++ b/nss-tool/common/util.h
@@ -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__
diff --git a/nss-tool/db/dbtool.cc b/nss-tool/db/dbtool.cc
index f88ba4187..f1d1b0edd 100644
--- a/nss-tool/db/dbtool.cc
+++ b/nss-tool/db/dbtool.cc
@@ -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;
+}
diff --git a/nss-tool/db/dbtool.h b/nss-tool/db/dbtool.h
index ed44e74ae..9d5ddedb2 100644
--- a/nss-tool/db/dbtool.h
+++ b/nss-tool/db/dbtool.h
@@ -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__