1#include "crypto/crypto_keygen.h"
2#include "async_wrap-inl.h"
3#include "base_object-inl.h"
4#include "debug_utils-inl.h"
5#include "env-inl.h"
6#include "memory_tracker-inl.h"
7#include "threadpoolwork-inl.h"
8#include "v8.h"
9
10#include <cmath>
11
12namespace node {
13
14using v8::FunctionCallbackInfo;
15using v8::Int32;
16using v8::Just;
17using v8::Local;
18using v8::Maybe;
19using v8::Object;
20using v8::Uint32;
21using v8::Value;
22
23namespace crypto {
24// NidKeyPairGenJob input arguments:
25//   1. CryptoJobMode
26//   2. NID
27//   3. Public Format
28//   4. Public Type
29//   5. Private Format
30//   6. Private Type
31//   7. Cipher
32//   8. Passphrase
33Maybe<bool> NidKeyPairGenTraits::AdditionalConfig(
34    CryptoJobMode mode,
35    const FunctionCallbackInfo<Value>& args,
36    unsigned int* offset,
37    NidKeyPairGenConfig* params) {
38  CHECK(args[*offset]->IsInt32());
39  params->params.id = args[*offset].As<Int32>()->Value();
40
41  *offset += 1;
42
43  return Just(true);
44}
45
46EVPKeyCtxPointer NidKeyPairGenTraits::Setup(NidKeyPairGenConfig* params) {
47  EVPKeyCtxPointer ctx =
48      EVPKeyCtxPointer(EVP_PKEY_CTX_new_id(params->params.id, nullptr));
49  if (!ctx || EVP_PKEY_keygen_init(ctx.get()) <= 0)
50    return EVPKeyCtxPointer();
51
52  return ctx;
53}
54
55void SecretKeyGenConfig::MemoryInfo(MemoryTracker* tracker) const {
56  if (out != nullptr)
57    tracker->TrackFieldWithSize("out", length);
58}
59
60Maybe<bool> SecretKeyGenTraits::AdditionalConfig(
61    CryptoJobMode mode,
62    const FunctionCallbackInfo<Value>& args,
63    unsigned int* offset,
64    SecretKeyGenConfig* params) {
65  CHECK(args[*offset]->IsUint32());
66  uint32_t bits = args[*offset].As<Uint32>()->Value();
67  static_assert(std::numeric_limits<decltype(bits)>::max() / CHAR_BIT <=
68                INT_MAX);
69  params->length = bits / CHAR_BIT;
70  *offset += 1;
71  return Just(true);
72}
73
74KeyGenJobStatus SecretKeyGenTraits::DoKeyGen(
75    Environment* env,
76    SecretKeyGenConfig* params) {
77  CHECK_LE(params->length, INT_MAX);
78  params->out = MallocOpenSSL<char>(params->length);
79  if (CSPRNG(reinterpret_cast<unsigned char*>(params->out),
80             params->length).is_err()) {
81    OPENSSL_clear_free(params->out, params->length);
82    params->out = nullptr;
83    params->length = 0;
84    return KeyGenJobStatus::FAILED;
85  }
86  return KeyGenJobStatus::OK;
87}
88
89Maybe<bool> SecretKeyGenTraits::EncodeKey(
90    Environment* env,
91    SecretKeyGenConfig* params,
92    Local<Value>* result) {
93  ByteSource out = ByteSource::Allocated(params->out, params->length);
94  std::shared_ptr<KeyObjectData> data =
95      KeyObjectData::CreateSecret(std::move(out));
96  return Just(KeyObjectHandle::Create(env, data).ToLocal(result));
97}
98
99namespace Keygen {
100void Initialize(Environment* env, Local<Object> target) {
101  NidKeyPairGenJob::Initialize(env, target);
102  SecretKeyGenJob::Initialize(env, target);
103}
104
105void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
106  NidKeyPairGenJob::RegisterExternalReferences(registry);
107  SecretKeyGenJob::RegisterExternalReferences(registry);
108}
109
110}  // namespace Keygen
111}  // namespace crypto
112}  // namespace node
113