Where Online Learning is simpler!
The C and C++ Include Header Files
cat -n /usr/include/nodejs/src/crypto/crypto_keygen.h
1 #ifndef SRC_CRYPTO_CRYPTO_KEYGEN_H_ 2 #define SRC_CRYPTO_CRYPTO_KEYGEN_H_ 3 4 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 5 6 #include "async_wrap.h" 7 #include "base_object.h" 8 #include "crypto/crypto_keys.h" 9 #include "crypto/crypto_util.h" 10 #include "env.h" 11 #include "memory_tracker.h" 12 #include "v8.h" 13 14 namespace node { 15 namespace crypto { 16 namespace Keygen { 17 void Initialize(Environment* env, v8::Local<v8::Object> target); 18 void RegisterExternalReferences(ExternalReferenceRegistry* registry); 19 } // namespace Keygen 20 21 enum class KeyGenJobStatus { 22 OK, 23 FAILED 24 }; 25 26 // A Base CryptoJob for generating secret keys or key pairs. 27 // The KeyGenTraits is largely responsible for the details of 28 // the implementation, while KeyGenJob handles the common 29 // mechanisms. 30 template <typename KeyGenTraits> 31 class KeyGenJob final : public CryptoJob<KeyGenTraits> { 32 public: 33 using AdditionalParams = typename KeyGenTraits::AdditionalParameters; 34 35 static void New(const v8::FunctionCallbackInfo<v8::Value>& args) { 36 Environment* env = Environment::GetCurrent(args); 37 CHECK(args.IsConstructCall()); 38 39 CryptoJobMode mode = GetCryptoJobMode(args[0]); 40 41 unsigned int offset = 1; 42 43 AdditionalParams params; 44 if (KeyGenTraits::AdditionalConfig(mode, args, &offset, ¶ms) 45 .IsNothing()) { 46 // The KeyGenTraits::AdditionalConfig is responsible for 47 // calling an appropriate THROW_CRYPTO_* variant reporting 48 // whatever error caused initialization to fail. 49 return; 50 } 51 52 new KeyGenJob<KeyGenTraits>(env, args.This(), mode, std::move(params)); 53 } 54 55 static void Initialize( 56 Environment* env, 57 v8::Local<v8::Object> target) { 58 CryptoJob<KeyGenTraits>::Initialize(New, env, target); 59 } 60 61 static void RegisterExternalReferences(ExternalReferenceRegistry* registry) { 62 CryptoJob<KeyGenTraits>::RegisterExternalReferences(New, registry); 63 } 64 65 KeyGenJob( 66 Environment* env, 67 v8::Local<v8::Object> object, 68 CryptoJobMode mode, 69 AdditionalParams&& params) 70 : CryptoJob<KeyGenTraits>( 71 env, 72 object, 73 KeyGenTraits::Provider, 74 mode, 75 std::move(params)) {} 76 77 void DoThreadPoolWork() override { 78 AdditionalParams* params = CryptoJob<KeyGenTraits>::params(); 79 80 switch (KeyGenTraits::DoKeyGen(AsyncWrap::env(), params)) { 81 case KeyGenJobStatus::OK: 82 status_ = KeyGenJobStatus::OK; 83 // Success! 84 break; 85 case KeyGenJobStatus::FAILED: { 86 CryptoErrorStore* errors = CryptoJob<KeyGenTraits>::errors(); 87 errors->Capture(); 88 if (errors->Empty()) 89 errors->Insert(NodeCryptoError::KEY_GENERATION_JOB_FAILED); 90 } 91 } 92 } 93 94 v8::Maybe<void> ToResult(v8::Local<v8::Value>* err, 95 v8::Local<v8::Value>* result) override { 96 Environment* env = AsyncWrap::env(); 97 CryptoErrorStore* errors = CryptoJob<KeyGenTraits>::errors(); 98 AdditionalParams* params = CryptoJob<KeyGenTraits>::params(); 99 100 if (status_ == KeyGenJobStatus::OK) { 101 v8::TryCatch try_catch(env->isolate()); 102 if (KeyGenTraits::EncodeKey(env, params).ToLocal(result)) { 103 *err = Undefined(env->isolate()); 104 } else { 105 CHECK(try_catch.HasCaught()); 106 CHECK(try_catch.CanContinue()); 107 *result = Undefined(env->isolate()); 108 *err = try_catch.Exception(); 109 } 110 } else { 111 if (errors->Empty()) errors->Capture(); 112 CHECK(!errors->Empty()); 113 *result = Undefined(env->isolate()); 114 if (!errors->ToException(env).ToLocal(err)) { 115 return v8::Nothing<void>(); 116 } 117 } 118 CHECK(!result->IsEmpty()); 119 CHECK(!err->IsEmpty()); 120 return v8::JustVoid(); 121 } 122 123 SET_SELF_SIZE(KeyGenJob) 124 125 private: 126 KeyGenJobStatus status_ = KeyGenJobStatus::FAILED; 127 }; 128 129 // A Base KeyGenTraits for Key Pair generation algorithms. 130 template <typename KeyPairAlgorithmTraits> 131 struct KeyPairGenTraits final { 132 using AdditionalParameters = 133 typename KeyPairAlgorithmTraits::AdditionalParameters; 134 135 static const AsyncWrap::ProviderType Provider = 136 AsyncWrap::PROVIDER_KEYPAIRGENREQUEST; 137 static constexpr const char* JobName = KeyPairAlgorithmTraits::JobName; 138 139 static v8::Maybe<void> AdditionalConfig( 140 CryptoJobMode mode, 141 const v8::FunctionCallbackInfo<v8::Value>& args, 142 unsigned int* offset, 143 AdditionalParameters* params) { 144 // Notice that offset is a pointer. Each of the AdditionalConfig, 145 // GetPublicKeyEncodingFromJs, and GetPrivateKeyEncodingFromJs 146 // functions will update the value of the offset as they successfully 147 // process input parameters. This allows each job to have a variable 148 // number of input parameters specific to each job type. 149 if (KeyPairAlgorithmTraits::AdditionalConfig(mode, args, offset, params) 150 .IsNothing() || 151 !KeyObjectData::GetPublicKeyEncodingFromJs( 152 args, offset, kKeyContextGenerate) 153 .To(¶ms->public_key_encoding) || 154 !KeyObjectData::GetPrivateKeyEncodingFromJs( 155 args, offset, kKeyContextGenerate) 156 .To(¶ms->private_key_encoding)) { 157 return v8::Nothing<void>(); 158 } 159 160 return v8::JustVoid(); 161 } 162 163 static KeyGenJobStatus DoKeyGen( 164 Environment* env, 165 AdditionalParameters* params) { 166 ncrypto::EVPKeyCtxPointer ctx = KeyPairAlgorithmTraits::Setup(params); 167 168 if (!ctx) 169 return KeyGenJobStatus::FAILED; 170 171 // Generate the key 172 EVP_PKEY* pkey = nullptr; 173 if (!EVP_PKEY_keygen(ctx.get(), &pkey)) 174 return KeyGenJobStatus::FAILED; 175 176 auto data = KeyObjectData::CreateAsymmetric(KeyType::kKeyTypePrivate, 177 ncrypto::EVPKeyPointer(pkey)); 178 if (!data) [[unlikely]] 179 return KeyGenJobStatus::FAILED; 180 params->key = std::move(data); 181 return KeyGenJobStatus::OK; 182 } 183 184 static v8::MaybeLocal<v8::Value> EncodeKey(Environment* env, 185 AdditionalParameters* params) { 186 v8::Local<v8::Value> keys[2]; 187 if (params->key 188 .ToEncodedPublicKey(env, params->public_key_encoding, &keys[0]) 189 .IsNothing() || 190 params->key 191 .ToEncodedPrivateKey(env, params->private_key_encoding, &keys[1]) 192 .IsNothing()) { 193 return v8::MaybeLocal<v8::Value>(); 194 } 195 return v8::Array::New(env->isolate(), keys, arraysize(keys)); 196 } 197 }; 198 199 struct SecretKeyGenConfig final : public MemoryRetainer { 200 size_t length; // In bytes. 201 ByteSource out; // Placeholder for the generated key bytes. 202 203 void MemoryInfo(MemoryTracker* tracker) const override; 204 SET_MEMORY_INFO_NAME(SecretKeyGenConfig) 205 SET_SELF_SIZE(SecretKeyGenConfig) 206 }; 207 208 struct SecretKeyGenTraits final { 209 using AdditionalParameters = SecretKeyGenConfig; 210 static const AsyncWrap::ProviderType Provider = 211 AsyncWrap::PROVIDER_KEYGENREQUEST; 212 static constexpr const char* JobName = "SecretKeyGenJob"; 213 214 static v8::Maybe<void> AdditionalConfig( 215 CryptoJobMode mode, 216 const v8::FunctionCallbackInfo<v8::Value>& args, 217 unsigned int* offset, 218 SecretKeyGenConfig* params); 219 220 static KeyGenJobStatus DoKeyGen( 221 Environment* env, 222 SecretKeyGenConfig* params); 223 224 static v8::MaybeLocal<v8::Value> EncodeKey(Environment* env, 225 SecretKeyGenConfig* params); 226 }; 227 228 template <typename AlgorithmParams> 229 struct KeyPairGenConfig final : public MemoryRetainer { 230 ncrypto::EVPKeyPointer::PublicKeyEncodingConfig public_key_encoding; 231 ncrypto::EVPKeyPointer::PrivateKeyEncodingConfig private_key_encoding; 232 KeyObjectData key; 233 AlgorithmParams params; 234 235 KeyPairGenConfig() = default; 236 ~KeyPairGenConfig() { 237 if (key) { 238 Mutex::ScopedLock priv_lock(key.mutex()); 239 } 240 } 241 242 explicit KeyPairGenConfig(KeyPairGenConfig&& other) noexcept 243 : public_key_encoding(other.public_key_encoding), 244 private_key_encoding( 245 std::forward<ncrypto::EVPKeyPointer::PrivateKeyEncodingConfig>( 246 other.private_key_encoding)), 247 key(std::move(other.key)), 248 params(std::move(other.params)) {} 249 250 KeyPairGenConfig& operator=(KeyPairGenConfig&& other) noexcept { 251 if (&other == this) return *this; 252 this->~KeyPairGenConfig(); 253 return *new (this) KeyPairGenConfig(std::move(other)); 254 } 255 256 void MemoryInfo(MemoryTracker* tracker) const override { 257 tracker->TrackField("key", key); 258 if (private_key_encoding.passphrase.has_value()) { 259 auto& passphrase = private_key_encoding.passphrase.value(); 260 tracker->TrackFieldWithSize("private_key_encoding.passphrase", 261 passphrase.size()); 262 } 263 tracker->TrackField("params", params); 264 } 265 266 SET_MEMORY_INFO_NAME(KeyPairGenConfig) 267 SET_SELF_SIZE(KeyPairGenConfig) 268 }; 269 270 struct NidKeyPairParams final : public MemoryRetainer { 271 int id; 272 SET_NO_MEMORY_INFO() 273 SET_MEMORY_INFO_NAME(NidKeyPairParams) 274 SET_SELF_SIZE(NidKeyPairParams) 275 }; 276 277 using NidKeyPairGenConfig = KeyPairGenConfig<NidKeyPairParams>; 278 279 struct NidKeyPairGenTraits final { 280 using AdditionalParameters = NidKeyPairGenConfig; 281 static constexpr const char* JobName = "NidKeyPairGenJob"; 282 283 static ncrypto::EVPKeyCtxPointer Setup(NidKeyPairGenConfig* params); 284 285 static v8::Maybe<void> AdditionalConfig( 286 CryptoJobMode mode, 287 const v8::FunctionCallbackInfo<v8::Value>& args, 288 unsigned int* offset, 289 NidKeyPairGenConfig* params); 290 }; 291 292 using NidKeyPairGenJob = KeyGenJob<KeyPairGenTraits<NidKeyPairGenTraits>>; 293 using SecretKeyGenJob = KeyGenJob<SecretKeyGenTraits>; 294 } // namespace crypto 295 } // namespace node 296 297 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 298 #endif // SRC_CRYPTO_CRYPTO_KEYGEN_H_ 299