diff options
Diffstat (limited to 'nss-tool/db/dbtool.cc')
-rw-r--r-- | nss-tool/db/dbtool.cc | 96 |
1 files changed, 63 insertions, 33 deletions
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; +} |