in src/governance/ccf-app/cpp/app/js_extensions.cpp [73:161]
JSValue js_generate_self_signed_cert(
JSContext* ctx, JSValueConst, int argc, JSValueConst* argv)
{
if (argc != 5 && argc != 6)
return JS_ThrowTypeError(
ctx, "Passed %d arguments, but expected 5 or 6", argc);
ccf::js::core::Context& jsctx =
*(ccf::js::core::Context*)JS_GetContextOpaque(ctx);
auto priv_key = jsctx.to_str(argv[0]);
if (!priv_key)
{
return ccf::js::core::constants::Exception;
}
auto subject_name = jsctx.to_str(argv[1]);
if (!subject_name)
{
return ccf::js::core::constants::Exception;
}
std::vector<std::string> subject_alt_names;
bool allow_empty = true;
JSValue rv =
extract_string_array(jsctx, argv[2], subject_alt_names, allow_empty);
if (!JS_IsUndefined(rv))
{
return JS_ThrowTypeError(ctx, "3rd argument must be a string array");
}
auto sans = ccf::crypto::sans_from_string_list(subject_alt_names);
int32_t validity_period_days;
if (JS_ToInt32(ctx, &validity_period_days, argv[3]) < 0)
{
return ccf::js::core::constants::Exception;
}
const auto v = argv[4];
if (!JS_IsBool(v))
{
return JS_ThrowTypeError(ctx, "5th argument must be a boolean");
}
auto ca = JS_ToBool(ctx, v);
std::optional<int> ca_path_len_constraint;
if (argc == 6)
{
int32_t value;
if (JS_ToInt32(ctx, &value, argv[5]) < 0)
{
return ccf::js::core::constants::Exception;
}
ca_path_len_constraint = value;
}
try
{
auto kp = cleanroom::crypto::make_key_pair(priv_key.value());
OPENSSL_cleanse(priv_key.value().data(), priv_key.value().size());
using namespace std::literals;
// valid_from starts a day before the current time so validity period is
// adjusted accordingly by increasing the input validity_period_days by 1.
auto valid_from =
ccf::ds::to_x509_time_string(std::chrono::system_clock::now() - 24h);
ccf::crypto::Pem cert_pem = cleanroom::crypto::create_self_signed_cert(
kp,
subject_name.value(),
sans,
valid_from,
validity_period_days + 1,
ca,
ca_path_len_constraint);
auto r = jsctx.new_obj();
JS_CHECK_EXC(r);
auto cert = jsctx.new_string_len((char*)cert_pem.data(), cert_pem.size());
JS_CHECK_EXC(cert);
JS_CHECK_SET(r.set("cert", std::move(cert)));
return r.take();
}
catch (const std::exception& exc)
{
return JS_ThrowInternalError(
ctx, "Failed to generate self signed cert: %s", exc.what());
}
}