Where Online Learning is simpler!
The C and C++ Include Header Files
cat -n /usr/include/nodejs/src/crypto/crypto_keys.h
1 #ifndef SRC_CRYPTO_CRYPTO_KEYS_H_ 2 #define SRC_CRYPTO_CRYPTO_KEYS_H_ 3 4 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 5 6 #include "crypto/crypto_util.h" 7 #include "base_object.h" 8 #include "env.h" 9 #include "memory_tracker.h" 10 #include "node_buffer.h" 11 #include "node_worker.h" 12 #include "v8.h" 13 14 #include <openssl/evp.h> 15 16 #include <memory> 17 #include <string> 18 19 namespace node { 20 namespace crypto { 21 22 enum KeyType { 23 kKeyTypeSecret, 24 kKeyTypePublic, 25 kKeyTypePrivate 26 }; 27 28 enum KeyEncodingContext { 29 kKeyContextInput, 30 kKeyContextExport, 31 kKeyContextGenerate 32 }; 33 34 enum class ParseKeyResult { 35 kParseKeyNotRecognized = 36 static_cast<int>(ncrypto::EVPKeyPointer::PKParseError::NOT_RECOGNIZED), 37 kParseKeyNeedPassphrase = 38 static_cast<int>(ncrypto::EVPKeyPointer::PKParseError::NEED_PASSPHRASE), 39 kParseKeyFailed = 40 static_cast<int>(ncrypto::EVPKeyPointer::PKParseError::FAILED), 41 kParseKeyOk, 42 }; 43 44 // Objects of this class can safely be shared among threads. 45 class KeyObjectData final : public MemoryRetainer { 46 public: 47 static KeyObjectData CreateSecret(ByteSource key); 48 49 static KeyObjectData CreateAsymmetric(KeyType type, 50 ncrypto::EVPKeyPointer&& pkey); 51 52 KeyObjectData(std::nullptr_t = nullptr); 53 54 inline operator bool() const { return data_ != nullptr; } 55 56 KeyType GetKeyType() const; 57 58 // These functions allow unprotected access to the raw key material and should 59 // only be used to implement cryptographic operations requiring the key. 60 const ncrypto::EVPKeyPointer& GetAsymmetricKey() const; 61 const char* GetSymmetricKey() const; 62 size_t GetSymmetricKeySize() const; 63 64 void MemoryInfo(MemoryTracker* tracker) const override; 65 SET_MEMORY_INFO_NAME(KeyObjectData) 66 SET_SELF_SIZE(KeyObjectData) 67 68 Mutex& mutex() const; 69 70 static v8::Maybe<ncrypto::EVPKeyPointer::PublicKeyEncodingConfig> 71 GetPublicKeyEncodingFromJs(const v8::FunctionCallbackInfo<v8::Value>& args, 72 unsigned int* offset, 73 KeyEncodingContext context); 74 75 static KeyObjectData GetPrivateKeyFromJs( 76 const v8::FunctionCallbackInfo<v8::Value>& args, 77 unsigned int* offset, 78 bool allow_key_object); 79 80 static KeyObjectData GetPublicOrPrivateKeyFromJs( 81 const v8::FunctionCallbackInfo<v8::Value>& args, unsigned int* offset); 82 83 static v8::Maybe<ncrypto::EVPKeyPointer::PrivateKeyEncodingConfig> 84 GetPrivateKeyEncodingFromJs(const v8::FunctionCallbackInfo<v8::Value>& args, 85 unsigned int* offset, 86 KeyEncodingContext context); 87 88 v8::Maybe<void> ToEncodedPublicKey( 89 Environment* env, 90 const ncrypto::EVPKeyPointer::PublicKeyEncodingConfig& config, 91 v8::Local<v8::Value>* out); 92 93 v8::Maybe<void> ToEncodedPrivateKey( 94 Environment* env, 95 const ncrypto::EVPKeyPointer::PrivateKeyEncodingConfig& config, 96 v8::Local<v8::Value>* out); 97 98 inline KeyObjectData addRef() const { 99 return KeyObjectData(key_type_, mutex_, data_); 100 } 101 102 inline KeyObjectData addRefWithType(KeyType type) const { 103 return KeyObjectData(type, mutex_, data_); 104 } 105 106 private: 107 explicit KeyObjectData(ByteSource symmetric_key); 108 explicit KeyObjectData(KeyType type, ncrypto::EVPKeyPointer&& pkey); 109 110 static KeyObjectData GetParsedKey(KeyType type, 111 Environment* env, 112 ncrypto::EVPKeyPointer&& pkey, 113 ParseKeyResult ret, 114 const char* default_msg); 115 116 KeyType key_type_; 117 mutable std::shared_ptr<Mutex> mutex_; 118 119 struct Data { 120 const ByteSource symmetric_key; 121 const ncrypto::EVPKeyPointer asymmetric_key; 122 explicit Data(ByteSource symmetric_key) 123 : symmetric_key(std::move(symmetric_key)) {} 124 explicit Data(ncrypto::EVPKeyPointer asymmetric_key) 125 : asymmetric_key(std::move(asymmetric_key)) {} 126 }; 127 std::shared_ptr<Data> data_; 128 129 KeyObjectData(KeyType type, 130 std::shared_ptr<Mutex> mutex, 131 std::shared_ptr<Data> data) 132 : key_type_(type), mutex_(std::move(mutex)), data_(std::move(data)) {} 133 }; 134 135 class KeyObjectHandle : public BaseObject { 136 public: 137 static bool HasInstance(Environment* env, v8::Local<v8::Value> value); 138 static v8::Local<v8::Function> Initialize(Environment* env); 139 static void RegisterExternalReferences(ExternalReferenceRegistry* registry); 140 141 static v8::MaybeLocal<v8::Object> Create(Environment* env, 142 const KeyObjectData& data); 143 144 // TODO(tniessen): track the memory used by OpenSSL types 145 SET_NO_MEMORY_INFO() 146 SET_MEMORY_INFO_NAME(KeyObjectHandle) 147 SET_SELF_SIZE(KeyObjectHandle) 148 149 const KeyObjectData& Data(); 150 151 protected: 152 static void New(const v8::FunctionCallbackInfo<v8::Value>& args); 153 154 static void Init(const v8::FunctionCallbackInfo<v8::Value>& args); 155 static void InitECRaw(const v8::FunctionCallbackInfo<v8::Value>& args); 156 static void InitEDRaw(const v8::FunctionCallbackInfo<v8::Value>& args); 157 static void InitJWK(const v8::FunctionCallbackInfo<v8::Value>& args); 158 static void GetKeyDetail(const v8::FunctionCallbackInfo<v8::Value>& args); 159 static void Equals(const v8::FunctionCallbackInfo<v8::Value>& args); 160 161 static void ExportJWK(const v8::FunctionCallbackInfo<v8::Value>& args); 162 163 static void GetAsymmetricKeyType( 164 const v8::FunctionCallbackInfo<v8::Value>& args); 165 v8::Local<v8::Value> GetAsymmetricKeyType() const; 166 167 static void CheckEcKeyData(const v8::FunctionCallbackInfo<v8::Value>& args); 168 bool CheckEcKeyData() const; 169 170 static void GetSymmetricKeySize( 171 const v8::FunctionCallbackInfo<v8::Value>& args); 172 173 static void Export(const v8::FunctionCallbackInfo<v8::Value>& args); 174 175 v8::MaybeLocal<v8::Value> ExportSecretKey() const; 176 v8::MaybeLocal<v8::Value> ExportPublicKey( 177 const ncrypto::EVPKeyPointer::PublicKeyEncodingConfig& config) const; 178 v8::MaybeLocal<v8::Value> ExportPrivateKey( 179 const ncrypto::EVPKeyPointer::PrivateKeyEncodingConfig& config) const; 180 181 KeyObjectHandle(Environment* env, 182 v8::Local<v8::Object> wrap); 183 184 private: 185 KeyObjectData data_; 186 }; 187 188 class NativeKeyObject : public BaseObject { 189 public: 190 static void Initialize(Environment* env, v8::Local<v8::Object> target); 191 static void RegisterExternalReferences(ExternalReferenceRegistry* registry); 192 193 static void New(const v8::FunctionCallbackInfo<v8::Value>& args); 194 static void CreateNativeKeyObjectClass( 195 const v8::FunctionCallbackInfo<v8::Value>& args); 196 197 SET_NO_MEMORY_INFO() 198 SET_MEMORY_INFO_NAME(NativeKeyObject) 199 SET_SELF_SIZE(NativeKeyObject) 200 201 class KeyObjectTransferData : public worker::TransferData { 202 public: 203 explicit KeyObjectTransferData(const KeyObjectData& data) 204 : data_(data.addRef()) {} 205 206 BaseObjectPtr<BaseObject> Deserialize( 207 Environment* env, 208 v8::Local<v8::Context> context, 209 std::unique_ptr<worker::TransferData> self) override; 210 211 SET_MEMORY_INFO_NAME(KeyObjectTransferData) 212 SET_SELF_SIZE(KeyObjectTransferData) 213 SET_NO_MEMORY_INFO() 214 215 private: 216 KeyObjectData data_; 217 }; 218 219 BaseObject::TransferMode GetTransferMode() const override; 220 std::unique_ptr<worker::TransferData> CloneForMessaging() const override; 221 222 private: 223 NativeKeyObject(Environment* env, 224 v8::Local<v8::Object> wrap, 225 const KeyObjectData& handle_data) 226 : BaseObject(env, wrap), handle_data_(handle_data.addRef()) { 227 MakeWeak(); 228 } 229 230 KeyObjectData handle_data_; 231 }; 232 233 enum WebCryptoKeyFormat { 234 kWebCryptoKeyFormatRaw, 235 kWebCryptoKeyFormatPKCS8, 236 kWebCryptoKeyFormatSPKI, 237 kWebCryptoKeyFormatJWK 238 }; 239 240 enum class WebCryptoKeyExportStatus { 241 OK, 242 INVALID_KEY_TYPE, 243 FAILED 244 }; 245 246 template <typename KeyExportTraits> 247 class KeyExportJob final : public CryptoJob<KeyExportTraits> { 248 public: 249 using AdditionalParams = typename KeyExportTraits::AdditionalParameters; 250 251 static void New(const v8::FunctionCallbackInfo<v8::Value>& args) { 252 Environment* env = Environment::GetCurrent(args); 253 CHECK(args.IsConstructCall()); 254 255 CryptoJobMode mode = GetCryptoJobMode(args[0]); 256 257 CHECK(args[1]->IsUint32()); // Export Type 258 CHECK(args[2]->IsObject()); // KeyObject 259 260 WebCryptoKeyFormat format = 261 static_cast<WebCryptoKeyFormat>(args[1].As<v8::Uint32>()->Value()); 262 263 KeyObjectHandle* key; 264 ASSIGN_OR_RETURN_UNWRAP(&key, args[2]); 265 266 CHECK_NOT_NULL(key); 267 268 AdditionalParams params; 269 if (KeyExportTraits::AdditionalConfig(args, 3, ¶ms).IsNothing()) { 270 // The KeyExportTraits::AdditionalConfig is responsible for 271 // calling an appropriate THROW_CRYPTO_* variant reporting 272 // whatever error caused initialization to fail. 273 return; 274 } 275 276 new KeyExportJob<KeyExportTraits>( 277 env, 278 args.This(), 279 mode, 280 key->Data(), 281 format, 282 std::move(params)); 283 } 284 285 static void Initialize( 286 Environment* env, 287 v8::Local<v8::Object> target) { 288 CryptoJob<KeyExportTraits>::Initialize(New, env, target); 289 } 290 291 static void RegisterExternalReferences(ExternalReferenceRegistry* registry) { 292 CryptoJob<KeyExportTraits>::RegisterExternalReferences(New, registry); 293 } 294 295 KeyExportJob(Environment* env, 296 v8::Local<v8::Object> object, 297 CryptoJobMode mode, 298 const KeyObjectData& key, 299 WebCryptoKeyFormat format, 300 AdditionalParams&& params) 301 : CryptoJob<KeyExportTraits>(env, 302 object, 303 AsyncWrap::PROVIDER_KEYEXPORTREQUEST, 304 mode, 305 std::move(params)), 306 key_(key.addRef()), 307 format_(format) {} 308 309 WebCryptoKeyFormat format() const { return format_; } 310 311 void DoThreadPoolWork() override { 312 const WebCryptoKeyExportStatus status = 313 KeyExportTraits::DoExport( 314 key_, 315 format_, 316 *CryptoJob<KeyExportTraits>::params(), 317 &out_); 318 if (status == WebCryptoKeyExportStatus::OK) { 319 // Success! 320 return; 321 } 322 CryptoErrorStore* errors = CryptoJob<KeyExportTraits>::errors(); 323 errors->Capture(); 324 if (errors->Empty()) { 325 switch (status) { 326 case WebCryptoKeyExportStatus::OK: 327 UNREACHABLE(); 328 break; 329 case WebCryptoKeyExportStatus::INVALID_KEY_TYPE: 330 errors->Insert(NodeCryptoError::INVALID_KEY_TYPE); 331 break; 332 case WebCryptoKeyExportStatus::FAILED: 333 errors->Insert(NodeCryptoError::CIPHER_JOB_FAILED); 334 break; 335 } 336 } 337 } 338 339 v8::Maybe<void> ToResult(v8::Local<v8::Value>* err, 340 v8::Local<v8::Value>* result) override { 341 Environment* env = AsyncWrap::env(); 342 CryptoErrorStore* errors = CryptoJob<KeyExportTraits>::errors(); 343 if (out_.size() > 0) { 344 CHECK(errors->Empty()); 345 *err = v8::Undefined(env->isolate()); 346 *result = out_.ToArrayBuffer(env); 347 if (result->IsEmpty()) { 348 return v8::Nothing<void>(); 349 } 350 } else { 351 if (errors->Empty()) errors->Capture(); 352 CHECK(!errors->Empty()); 353 *result = v8::Undefined(env->isolate()); 354 if (!errors->ToException(env).ToLocal(err)) { 355 return v8::Nothing<void>(); 356 } 357 } 358 CHECK(!result->IsEmpty()); 359 CHECK(!err->IsEmpty()); 360 return v8::JustVoid(); 361 } 362 363 SET_SELF_SIZE(KeyExportJob) 364 void MemoryInfo(MemoryTracker* tracker) const override { 365 tracker->TrackFieldWithSize("out", out_.size()); 366 CryptoJob<KeyExportTraits>::MemoryInfo(tracker); 367 } 368 369 private: 370 KeyObjectData key_; 371 WebCryptoKeyFormat format_; 372 ByteSource out_; 373 }; 374 375 WebCryptoKeyExportStatus PKEY_SPKI_Export(const KeyObjectData& key_data, 376 ByteSource* out); 377 378 WebCryptoKeyExportStatus PKEY_PKCS8_Export(const KeyObjectData& key_data, 379 ByteSource* out); 380 381 int GetOKPCurveFromName(const char* name); 382 383 namespace Keys { 384 void Initialize(Environment* env, v8::Local<v8::Object> target); 385 void RegisterExternalReferences(ExternalReferenceRegistry* registry); 386 } // namespace Keys 387 388 } // namespace crypto 389 } // namespace node 390 391 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 392 #endif // SRC_CRYPTO_CRYPTO_KEYS_H_