in src/governance/ccf-app/cpp/app/js_extensions.cpp [163:265]
JSValue js_generate_endorsed_cert(
JSContext* ctx, JSValueConst, int argc, JSValueConst* argv)
{
if (argc != 7 && argc != 8)
return JS_ThrowTypeError(
ctx, "Passed %d arguments, but expected 7 or 8", argc);
ccf::js::core::Context& jsctx =
*(ccf::js::core::Context*)JS_GetContextOpaque(ctx);
auto public_key = jsctx.to_str(argv[0]);
if (!public_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;
}
auto issuer_private_key = jsctx.to_str(argv[4]);
if (!issuer_private_key)
{
return ccf::js::core::constants::Exception;
}
auto issuer_cert = jsctx.to_str(argv[5]);
if (!issuer_cert)
{
return ccf::js::core::constants::Exception;
}
const auto v = argv[6];
if (!JS_IsBool(v))
{
return JS_ThrowTypeError(ctx, "7th argument must be a boolean");
}
auto ca = JS_ToBool(ctx, v);
std::optional<int> ca_path_len_constraint;
if (argc == 8)
{
int32_t value;
if (JS_ToInt32(ctx, &value, argv[7]) < 0)
{
return ccf::js::core::constants::Exception;
}
ca_path_len_constraint = value;
}
try
{
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);
auto valid_to = cleanroom::crypto::compute_cert_valid_to_string(
valid_from, validity_period_days + 1);
ccf::crypto::Pem cert_pem = cleanroom::crypto::create_endorsed_cert(
public_key.value(),
subject_name.value(),
sans,
valid_from,
valid_to,
issuer_private_key.value(),
issuer_cert.value(),
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 endorsed cert: %s", exc.what());
}
}