Skip to content

Commit

Permalink
chore: group args of ExportCertificateAndKey for readability
Browse files Browse the repository at this point in the history
  • Loading branch information
addaleax committed Aug 8, 2024
1 parent 3620641 commit 234200b
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 47 deletions.
48 changes: 24 additions & 24 deletions src/binding.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@ namespace {
using namespace Napi;
using namespace WinExportCertificateAndKey;

Array BufferListToArray(Env env, const std::vector<std::vector<BYTE>>& vec) {
Array ret = Array::New(env);
if (vec.size() > static_cast<uint32_t>(-1)) {
throw std::runtime_error("result length exceeds uint32 max");
}
for (uint32_t i = 0; i < vec.size(); i++) {
ret[i] = Buffer<BYTE>::Copy(env, vec[i].data(), vec[i].size());
}
return ret;
}

// Convert UTF-8 to a Windows UTF-16 wstring.
std::wstring MultiByteToWideChar(Value value) {
static_assert(sizeof(std::wstring::value_type) == sizeof(std::u16string::value_type),
Expand All @@ -18,16 +29,8 @@ Value ExportAllCertificatesSync(const CallbackInfo& args) {
DWORD store_type = args[1].ToNumber().Uint32Value();

try {
std::vector<std::vector<BYTE>> certs =
ExportAllCertificates(sys_store_name, store_type);
if (certs.size() > static_cast<uint32_t>(-1)) {
throw std::runtime_error("result length exceeds uint32 max");
}
Array result = Array::New(args.Env());
for (uint32_t i = 0; i < certs.size(); i++) {
result[i] = Buffer<BYTE>::Copy(args.Env(), certs[i].data(), certs[i].size());
}
return result;
return BufferListToArray(
args.Env(), ExportAllCertificates(sys_store_name, store_type));
} catch (const std::exception& e) {
throw Error::New(args.Env(), e.what());
}
Expand All @@ -36,28 +39,25 @@ Value ExportAllCertificatesSync(const CallbackInfo& args) {
// Export a given certificate from a system certificate store,
// identified either by its thumbprint or its subject line.
Value ExportCertificateAndKeySync(const CallbackInfo& args) {
std::wstring password_buf = MultiByteToWideChar(args[0].ToString());
std::wstring sys_store_name = MultiByteToWideChar(args[1].ToString());
DWORD store_type = args[2].ToNumber().Uint32Value();
bool use_thumbprint;
std::vector<BYTE> thumbprint;
std::wstring subject;
bool require_private_key = args[4].ToBoolean();
ExportCertificateAndKeyArgs exp_args;
exp_args.password_buf = MultiByteToWideChar(args[0].ToString());
exp_args.sys_store_name = MultiByteToWideChar(args[1].ToString());
exp_args.store_type = args[2].ToNumber().Uint32Value();
exp_args.require_private_key = args[4].ToBoolean();

Object search_spec = args[3].ToObject();
if (search_spec.HasOwnProperty("thumbprint")) {
use_thumbprint = true;
Buffer<BYTE> thumbprint_buf = search_spec.Get("thumbprint").As<Buffer<BYTE>>();
thumbprint = {thumbprint_buf.Data(), thumbprint_buf.Data() + thumbprint_buf.Length()};
exp_args.use_thumbprint = true;
Buffer<BYTE> thumbprint = search_spec.Get("thumbprint").As<Buffer<BYTE>>();
exp_args.thumbprint = {thumbprint.Data(), thumbprint.Data() + thumbprint.Length()};
} else if (search_spec.HasOwnProperty("subject")) {
use_thumbprint = false;
subject = MultiByteToWideChar(search_spec.Get("subject").ToString());
exp_args.use_thumbprint = false;
exp_args.subject = MultiByteToWideChar(search_spec.Get("subject").ToString());
} else {
throw Error::New(args.Env(), "Need to specify either `thumbprint` or `subject`");
}
try {
auto result = ExportCertificateAndKey(
store_type, sys_store_name, use_thumbprint, thumbprint, subject, password_buf, require_private_key);
auto result = ExportCertificateAndKey(exp_args);
return Buffer<BYTE>::Copy(args.Env(), result.data(), result.size());
} catch (const std::exception& e) {
throw Error::New(args.Env(), e.what());
Expand Down
23 changes: 8 additions & 15 deletions src/certs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -132,22 +132,15 @@ std::vector<std::vector<BYTE>> ExportAllCertificates(
return result;
}

std::vector<BYTE> ExportCertificateAndKey(
DWORD store_type,
const std::wstring& sys_store_name,
bool use_thumbprint,
const std::vector<BYTE>& thumbprint,
const std::wstring& subject,
const std::wstring& password_buf,
bool require_private_key) {
LPCWSTR password = password_buf.data();
CertStoreHandle sys_cs = CertOpenStore(sys_store_name, store_type);
std::vector<BYTE> ExportCertificateAndKey(const ExportCertificateAndKeyArgs& args) {
LPCWSTR password = args.password_buf.data();
CertStoreHandle sys_cs = CertOpenStore(args.sys_store_name, args.store_type);
PCCERT_CONTEXT cert = nullptr;

if (use_thumbprint) {
if (args.use_thumbprint) {
CRYPT_HASH_BLOB thumbprint_blob = {
static_cast<DWORD>(thumbprint.size()),
const_cast<BYTE*>(thumbprint.data())
static_cast<DWORD>(args.thumbprint.size()),
const_cast<BYTE*>(args.thumbprint.data())
};
cert = CertFindCertificateInStore(
sys_cs.get(),
Expand All @@ -162,7 +155,7 @@ std::vector<BYTE> ExportCertificateAndKey(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
0,
CERT_FIND_SUBJECT_STR,
subject.data(),
args.subject.data(),
nullptr);
}

Expand All @@ -173,7 +166,7 @@ std::vector<BYTE> ExportCertificateAndKey(
Cleanup cleanup_cert([&]() { CertFreeCertificateContext(cert); });

DWORD export_flags = EXPORT_PRIVATE_KEYS;
if (require_private_key) {
if (args.require_private_key) {
export_flags |= REPORT_NO_PRIVATE_KEY | REPORT_NOT_ABLE_TO_EXPORT_PRIVATE_KEY;
}
return CertToBuffer(cert, password, export_flags);
Expand Down
19 changes: 11 additions & 8 deletions src/certs.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@
#include <windows.h>

namespace WinExportCertificateAndKey {
std::vector<BYTE> ExportCertificateAndKey(
DWORD store_type,
const std::wstring& sys_store_name,
bool use_thumbprint,
const std::vector<BYTE>& thumbprint,
const std::wstring& subject,
const std::wstring& password_buf,
bool require_private_key);
struct ExportCertificateAndKeyArgs {
DWORD store_type;
std::wstring sys_store_name;
bool use_thumbprint;
std::vector<BYTE> thumbprint;
std::wstring subject;
std::wstring password_buf;
bool require_private_key;
};

std::vector<BYTE> ExportCertificateAndKey(const ExportCertificateAndKeyArgs& args);

std::vector<std::vector<BYTE>> ExportAllCertificates(
const std::wstring& sys_store_name, DWORD store_type);
Expand Down

0 comments on commit 234200b

Please sign in to comment.