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
12 namespace node {
13
14 using v8::FunctionCallbackInfo;
15 using v8::Int32;
16 using v8::Just;
17 using v8::Local;
18 using v8::Maybe;
19 using v8::Object;
20 using v8::Uint32;
21 using v8::Value;
22
23 namespace 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
AdditionalConfig(CryptoJobMode mode,const FunctionCallbackInfo<Value> & args,unsigned int * offset,NidKeyPairGenConfig * params)33 Maybe<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
Setup(NidKeyPairGenConfig * params)46 EVPKeyCtxPointer 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
MemoryInfo(MemoryTracker * tracker) const55 void SecretKeyGenConfig::MemoryInfo(MemoryTracker* tracker) const {
56 if (out != nullptr)
57 tracker->TrackFieldWithSize("out", length);
58 }
59
AdditionalConfig(CryptoJobMode mode,const FunctionCallbackInfo<Value> & args,unsigned int * offset,SecretKeyGenConfig * params)60 Maybe<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
DoKeyGen(Environment * env,SecretKeyGenConfig * params)74 KeyGenJobStatus 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
EncodeKey(Environment * env,SecretKeyGenConfig * params,Local<Value> * result)89 Maybe<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
99 namespace Keygen {
Initialize(Environment * env,Local<Object> target)100 void Initialize(Environment* env, Local<Object> target) {
101 NidKeyPairGenJob::Initialize(env, target);
102 SecretKeyGenJob::Initialize(env, target);
103 }
104
RegisterExternalReferences(ExternalReferenceRegistry * registry)105 void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
106 NidKeyPairGenJob::RegisterExternalReferences(registry);
107 SecretKeyGenJob::RegisterExternalReferences(registry);
108 }
109
110 } // namespace Keygen
111 } // namespace crypto
112 } // namespace node
113