diff options
Diffstat (limited to 'nss-tool')
-rw-r--r-- | nss-tool/common/util.cc | 31 | ||||
-rw-r--r-- | nss-tool/common/util.h | 2 | ||||
-rw-r--r-- | nss-tool/db/dbtool.cc | 96 | ||||
-rw-r--r-- | nss-tool/db/dbtool.h | 4 |
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__ |