Where Online Learning is simpler!
The C and C++ Include Header Files
cat -n /usr/include/nodejs/src/crypto/crypto_cipher.h
1 #ifndef SRC_CRYPTO_CRYPTO_CIPHER_H_ 2 #define SRC_CRYPTO_CRYPTO_CIPHER_H_ 3 4 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 5 6 #include "crypto/crypto_keys.h" 7 #include "crypto/crypto_util.h" 8 #include "base_object.h" 9 #include "env.h" 10 #include "memory_tracker.h" 11 #include "v8.h" 12 13 #include <string> 14 15 namespace node { 16 namespace crypto { 17 class CipherBase : public BaseObject { 18 public: 19 static void GetSSLCiphers(const v8::FunctionCallbackInfo<v8::Value>& args); 20 static void GetCiphers(const v8::FunctionCallbackInfo<v8::Value>& args); 21 22 static void Initialize(Environment* env, v8::Local<v8::Object> target); 23 static void RegisterExternalReferences(ExternalReferenceRegistry* registry); 24 25 void MemoryInfo(MemoryTracker* tracker) const override; 26 SET_MEMORY_INFO_NAME(CipherBase) 27 SET_SELF_SIZE(CipherBase) 28 29 protected: 30 enum CipherKind { 31 kCipher, 32 kDecipher 33 }; 34 enum UpdateResult { 35 kSuccess, 36 kErrorMessageSize, 37 kErrorState 38 }; 39 enum AuthTagState { 40 kAuthTagUnknown, 41 kAuthTagKnown, 42 kAuthTagPassedToOpenSSL 43 }; 44 static const unsigned kNoAuthTagLength = static_cast<unsigned>(-1); 45 46 void CommonInit(const char* cipher_type, 47 const ncrypto::Cipher& cipher, 48 const unsigned char* key, 49 int key_len, 50 const unsigned char* iv, 51 int iv_len, 52 unsigned int auth_tag_len); 53 void Init(const char* cipher_type, 54 const ArrayBufferOrViewContents<unsigned char>& key_buf, 55 unsigned int auth_tag_len); 56 void InitIv(const char* cipher_type, 57 const ByteSource& key_buf, 58 const ArrayBufferOrViewContents<unsigned char>& iv_buf, 59 unsigned int auth_tag_len); 60 bool InitAuthenticated(const char* cipher_type, int iv_len, 61 unsigned int auth_tag_len); 62 bool CheckCCMMessageLength(int message_len); 63 UpdateResult Update(const char* data, size_t len, 64 std::unique_ptr<v8::BackingStore>* out); 65 bool Final(std::unique_ptr<v8::BackingStore>* out); 66 bool SetAutoPadding(bool auto_padding); 67 68 bool IsAuthenticatedMode() const; 69 bool SetAAD( 70 const ArrayBufferOrViewContents<unsigned char>& data, 71 int plaintext_len); 72 bool MaybePassAuthTagToOpenSSL(); 73 74 static void New(const v8::FunctionCallbackInfo<v8::Value>& args); 75 static void Init(const v8::FunctionCallbackInfo<v8::Value>& args); 76 static void InitIv(const v8::FunctionCallbackInfo<v8::Value>& args); 77 static void Update(const v8::FunctionCallbackInfo<v8::Value>& args); 78 static void Final(const v8::FunctionCallbackInfo<v8::Value>& args); 79 static void SetAutoPadding(const v8::FunctionCallbackInfo<v8::Value>& args); 80 81 static void GetAuthTag(const v8::FunctionCallbackInfo<v8::Value>& args); 82 static void SetAuthTag(const v8::FunctionCallbackInfo<v8::Value>& args); 83 static void SetAAD(const v8::FunctionCallbackInfo<v8::Value>& args); 84 85 CipherBase(Environment* env, v8::Local<v8::Object> wrap, CipherKind kind); 86 87 private: 88 ncrypto::CipherCtxPointer ctx_; 89 const CipherKind kind_; 90 AuthTagState auth_tag_state_; 91 unsigned int auth_tag_len_; 92 char auth_tag_[EVP_GCM_TLS_TAG_LEN]; 93 bool pending_auth_failed_; 94 int max_message_size_; 95 }; 96 97 class PublicKeyCipher { 98 public: 99 typedef int (*EVP_PKEY_cipher_init_t)(EVP_PKEY_CTX* ctx); 100 typedef int (*EVP_PKEY_cipher_t)(EVP_PKEY_CTX* ctx, 101 unsigned char* out, size_t* outlen, 102 const unsigned char* in, size_t inlen); 103 104 enum Operation { 105 kPublic, 106 kPrivate 107 }; 108 109 template <Operation operation, 110 EVP_PKEY_cipher_init_t EVP_PKEY_cipher_init, 111 EVP_PKEY_cipher_t EVP_PKEY_cipher> 112 static bool Cipher(Environment* env, 113 const ncrypto::EVPKeyPointer& pkey, 114 int padding, 115 const EVP_MD* digest, 116 const ArrayBufferOrViewContents<unsigned char>& oaep_label, 117 const ArrayBufferOrViewContents<unsigned char>& data, 118 std::unique_ptr<v8::BackingStore>* out); 119 120 template <Operation operation, 121 EVP_PKEY_cipher_init_t EVP_PKEY_cipher_init, 122 EVP_PKEY_cipher_t EVP_PKEY_cipher> 123 static void Cipher(const v8::FunctionCallbackInfo<v8::Value>& args); 124 }; 125 126 enum WebCryptoCipherMode { 127 kWebCryptoCipherEncrypt, 128 kWebCryptoCipherDecrypt 129 }; 130 131 enum class WebCryptoCipherStatus { 132 OK, 133 INVALID_KEY_TYPE, 134 FAILED 135 }; 136 137 // CipherJob is a base implementation class for implementations of 138 // one-shot sync and async ciphers. It has been added primarily to 139 // support the AES and RSA ciphers underlying the WebCrypt API. 140 // 141 // See the crypto_aes and crypto_rsa headers for examples of how to 142 // use CipherJob. 143 template <typename CipherTraits> 144 class CipherJob final : public CryptoJob<CipherTraits> { 145 public: 146 using AdditionalParams = typename CipherTraits::AdditionalParameters; 147 148 static void New(const v8::FunctionCallbackInfo<v8::Value>& args) { 149 Environment* env = Environment::GetCurrent(args); 150 CHECK(args.IsConstructCall()); 151 152 CryptoJobMode mode = GetCryptoJobMode(args[0]); 153 154 CHECK(args[1]->IsUint32()); // Cipher Mode 155 156 uint32_t cmode = args[1].As<v8::Uint32>()->Value(); 157 CHECK_LE(cmode, WebCryptoCipherMode::kWebCryptoCipherDecrypt); 158 WebCryptoCipherMode cipher_mode = static_cast<WebCryptoCipherMode>(cmode); 159 160 CHECK(args[2]->IsObject()); // KeyObject 161 KeyObjectHandle* key; 162 ASSIGN_OR_RETURN_UNWRAP(&key, args[2]); 163 CHECK_NOT_NULL(key); 164 165 ArrayBufferOrViewContents<char> data(args[3]); // data to operate on 166 if (!data.CheckSizeInt32()) 167 return THROW_ERR_OUT_OF_RANGE(env, "data is too large"); 168 169 AdditionalParams params; 170 if (CipherTraits::AdditionalConfig(mode, args, 4, cipher_mode, ¶ms) 171 .IsNothing()) { 172 // The CipherTraits::AdditionalConfig is responsible for 173 // calling an appropriate THROW_CRYPTO_* variant reporting 174 // whatever error caused initialization to fail. 175 return; 176 } 177 178 new CipherJob<CipherTraits>( 179 env, 180 args.This(), 181 mode, 182 key, 183 cipher_mode, 184 data, 185 std::move(params)); 186 } 187 188 static void Initialize( 189 Environment* env, 190 v8::Local<v8::Object> target) { 191 CryptoJob<CipherTraits>::Initialize(New, env, target); 192 } 193 194 static void RegisterExternalReferences(ExternalReferenceRegistry* registry) { 195 CryptoJob<CipherTraits>::RegisterExternalReferences(New, registry); 196 } 197 198 CipherJob(Environment* env, 199 v8::Local<v8::Object> object, 200 CryptoJobMode mode, 201 KeyObjectHandle* key, 202 WebCryptoCipherMode cipher_mode, 203 const ArrayBufferOrViewContents<char>& data, 204 AdditionalParams&& params) 205 : CryptoJob<CipherTraits>(env, 206 object, 207 AsyncWrap::PROVIDER_CIPHERREQUEST, 208 mode, 209 std::move(params)), 210 key_(key->Data().addRef()), 211 cipher_mode_(cipher_mode), 212 in_(mode == kCryptoJobAsync ? data.ToCopy() : data.ToByteSource()) {} 213 214 const KeyObjectData& key() const { return key_; } 215 216 WebCryptoCipherMode cipher_mode() const { return cipher_mode_; } 217 218 void DoThreadPoolWork() override { 219 const WebCryptoCipherStatus status = 220 CipherTraits::DoCipher( 221 AsyncWrap::env(), 222 key(), 223 cipher_mode_, 224 *CryptoJob<CipherTraits>::params(), 225 in_, 226 &out_); 227 if (status == WebCryptoCipherStatus::OK) { 228 // Success! 229 return; 230 } 231 CryptoErrorStore* errors = CryptoJob<CipherTraits>::errors(); 232 errors->Capture(); 233 if (errors->Empty()) { 234 switch (status) { 235 case WebCryptoCipherStatus::OK: 236 UNREACHABLE(); 237 break; 238 case WebCryptoCipherStatus::INVALID_KEY_TYPE: 239 errors->Insert(NodeCryptoError::INVALID_KEY_TYPE); 240 break; 241 case WebCryptoCipherStatus::FAILED: 242 errors->Insert(NodeCryptoError::CIPHER_JOB_FAILED); 243 break; 244 } 245 } 246 } 247 248 v8::Maybe<void> ToResult(v8::Local<v8::Value>* err, 249 v8::Local<v8::Value>* result) override { 250 Environment* env = AsyncWrap::env(); 251 CryptoErrorStore* errors = CryptoJob<CipherTraits>::errors(); 252 253 if (errors->Empty()) 254 errors->Capture(); 255 256 if (out_.size() > 0 || errors->Empty()) { 257 CHECK(errors->Empty()); 258 *err = v8::Undefined(env->isolate()); 259 *result = out_.ToArrayBuffer(env); 260 if (result->IsEmpty()) { 261 return v8::Nothing<void>(); 262 } 263 } else { 264 *result = v8::Undefined(env->isolate()); 265 if (!errors->ToException(env).ToLocal(err)) { 266 return v8::Nothing<void>(); 267 } 268 } 269 CHECK(!result->IsEmpty()); 270 CHECK(!err->IsEmpty()); 271 return v8::JustVoid(); 272 } 273 274 SET_SELF_SIZE(CipherJob) 275 void MemoryInfo(MemoryTracker* tracker) const override { 276 if (CryptoJob<CipherTraits>::mode() == kCryptoJobAsync) 277 tracker->TrackFieldWithSize("in", in_.size()); 278 tracker->TrackFieldWithSize("out", out_.size()); 279 CryptoJob<CipherTraits>::MemoryInfo(tracker); 280 } 281 282 private: 283 KeyObjectData key_; 284 WebCryptoCipherMode cipher_mode_; 285 ByteSource in_; 286 ByteSource out_; 287 }; 288 289 } // namespace crypto 290 } // namespace node 291 292 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 293 #endif // SRC_CRYPTO_CRYPTO_CIPHER_H_