GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/crypto/crypto_cipher.h Lines: 47 64 73.4 %
Date: 2021-05-04 04:12:26 Branches: 19 40 47.5 %

Line Branch Exec Source
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 "allocated_buffer-inl.h"
9
#include "base_object.h"
10
#include "env.h"
11
#include "memory_tracker.h"
12
#include "v8.h"
13
14
#include <string>
15
16
namespace node {
17
namespace crypto {
18
2546
class CipherBase : public BaseObject {
19
 public:
20
  static void GetSSLCiphers(const v8::FunctionCallbackInfo<v8::Value>& args);
21
  static void GetCiphers(const v8::FunctionCallbackInfo<v8::Value>& args);
22
23
  static void Initialize(Environment* env, v8::Local<v8::Object> target);
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 EVP_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, AllocatedBuffer* out);
64
  bool Final(AllocatedBuffer* out);
65
  bool SetAutoPadding(bool auto_padding);
66
67
  bool IsAuthenticatedMode() const;
68
  bool SetAAD(
69
      const ArrayBufferOrViewContents<unsigned char>& data,
70
      int plaintext_len);
71
  bool MaybePassAuthTagToOpenSSL();
72
73
  static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
74
  static void Init(const v8::FunctionCallbackInfo<v8::Value>& args);
75
  static void InitIv(const v8::FunctionCallbackInfo<v8::Value>& args);
76
  static void Update(const v8::FunctionCallbackInfo<v8::Value>& args);
77
  static void Final(const v8::FunctionCallbackInfo<v8::Value>& args);
78
  static void SetAutoPadding(const v8::FunctionCallbackInfo<v8::Value>& args);
79
80
  static void GetAuthTag(const v8::FunctionCallbackInfo<v8::Value>& args);
81
  static void SetAuthTag(const v8::FunctionCallbackInfo<v8::Value>& args);
82
  static void SetAAD(const v8::FunctionCallbackInfo<v8::Value>& args);
83
84
  CipherBase(Environment* env, v8::Local<v8::Object> wrap, CipherKind kind);
85
86
 private:
87
  DeleteFnPtr<EVP_CIPHER_CTX, EVP_CIPHER_CTX_free> ctx_;
88
  const CipherKind kind_;
89
  AuthTagState auth_tag_state_;
90
  unsigned int auth_tag_len_;
91
  char auth_tag_[EVP_GCM_TLS_TAG_LEN];
92
  bool pending_auth_failed_;
93
  int max_message_size_;
94
};
95
96
class PublicKeyCipher {
97
 public:
98
  typedef int (*EVP_PKEY_cipher_init_t)(EVP_PKEY_CTX* ctx);
99
  typedef int (*EVP_PKEY_cipher_t)(EVP_PKEY_CTX* ctx,
100
                                   unsigned char* out, size_t* outlen,
101
                                   const unsigned char* in, size_t inlen);
102
103
  enum Operation {
104
    kPublic,
105
    kPrivate
106
  };
107
108
  template <Operation operation,
109
            EVP_PKEY_cipher_init_t EVP_PKEY_cipher_init,
110
            EVP_PKEY_cipher_t EVP_PKEY_cipher>
111
  static bool Cipher(Environment* env,
112
                     const ManagedEVPPKey& pkey,
113
                     int padding,
114
                     const EVP_MD* digest,
115
                     const ArrayBufferOrViewContents<unsigned char>& oaep_label,
116
                     const ArrayBufferOrViewContents<unsigned char>& data,
117
                     AllocatedBuffer* out);
118
119
  template <Operation operation,
120
            EVP_PKEY_cipher_init_t EVP_PKEY_cipher_init,
121
            EVP_PKEY_cipher_t EVP_PKEY_cipher>
122
  static void Cipher(const v8::FunctionCallbackInfo<v8::Value>& args);
123
};
124
125
enum WebCryptoCipherMode {
126
  kWebCryptoCipherEncrypt,
127
  kWebCryptoCipherDecrypt
128
};
129
130
enum class WebCryptoCipherStatus {
131
  OK,
132
  INVALID_KEY_TYPE,
133
  FAILED
134
};
135
136
// CipherJob is a base implementation class for implementations of
137
// one-shot sync and async ciphers. It has been added primarily to
138
// support the AES and RSA ciphers underlying the WebCrypt API.
139
//
140
// See the crypto_aes and crypto_rsa headers for examples of how to
141
// use CipherJob.
142
template <typename CipherTraits>
143
896
class CipherJob final : public CryptoJob<CipherTraits> {
144
 public:
145
  using AdditionalParams = typename CipherTraits::AdditionalParameters;
146
147
448
  static void New(const v8::FunctionCallbackInfo<v8::Value>& args) {
148
448
    Environment* env = Environment::GetCurrent(args);
149
448
    CHECK(args.IsConstructCall());
150
151
448
    CryptoJobMode mode = GetCryptoJobMode(args[0]);
152
153
896
    CHECK(args[1]->IsUint32());  // Cipher Mode
154
155
1344
    uint32_t cmode = args[1].As<v8::Uint32>()->Value();
156
448
    CHECK_LE(cmode, WebCryptoCipherMode::kWebCryptoCipherDecrypt);
157
448
    WebCryptoCipherMode cipher_mode = static_cast<WebCryptoCipherMode>(cmode);
158
159
896
    CHECK(args[2]->IsObject());  // KeyObject
160
    KeyObjectHandle* key;
161
448
    ASSIGN_OR_RETURN_UNWRAP(&key, args[2]);
162
448
    CHECK_NOT_NULL(key);
163
164
896
    ArrayBufferOrViewContents<char> data(args[3]);  // data to operate on
165
448
    if (!data.CheckSizeInt32())
166
      return THROW_ERR_OUT_OF_RANGE(env, "data is too large");
167
168
896
    AdditionalParams params;
169
896
    if (CipherTraits::AdditionalConfig(mode, args, 4, cipher_mode, &params)
170
            .IsNothing()) {
171
      // The CipherTraits::AdditionalConfig is responsible for
172
      // calling an appropriate THROW_CRYPTO_* variant reporting
173
      // whatever error caused initialization to fail.
174
      return;
175
    }
176
177
448
    new CipherJob<CipherTraits>(
178
        env,
179
896
        args.This(),
180
        mode,
181
        key,
182
        cipher_mode,
183
        data,
184
        std::move(params));
185
  }
186
187
8310
  static void Initialize(
188
      Environment* env,
189
      v8::Local<v8::Object> target) {
190
8310
    CryptoJob<CipherTraits>::Initialize(New, env, target);
191
8310
  }
192
193
448
  CipherJob(
194
      Environment* env,
195
      v8::Local<v8::Object> object,
196
      CryptoJobMode mode,
197
      KeyObjectHandle* key,
198
      WebCryptoCipherMode cipher_mode,
199
      const ArrayBufferOrViewContents<char>& data,
200
      AdditionalParams&& params)
201
      : CryptoJob<CipherTraits>(
202
            env,
203
            object,
204
            AsyncWrap::PROVIDER_CIPHERREQUEST,
205
            mode,
206
448
            std::move(params)),
207
        key_(key->Data()),
208
        cipher_mode_(cipher_mode),
209
        in_(mode == kCryptoJobAsync
210
            ? data.ToCopy()
211
448
            : data.ToByteSource()) {}
212
213
448
  std::shared_ptr<KeyObjectData> key() const { return key_; }
214
215
  WebCryptoCipherMode cipher_mode() const { return cipher_mode_; }
216
217
448
  void DoThreadPoolWork() override {
218
    const WebCryptoCipherStatus status =
219
1344
        CipherTraits::DoCipher(
220
            AsyncWrap::env(),
221
            key(),
222
            cipher_mode_,
223
448
            *CryptoJob<CipherTraits>::params(),
224
            in_,
225
448
            &out_);
226
448
    if (status == WebCryptoCipherStatus::OK) {
227
      // Success!
228
430
      return;
229
    }
230
18
    CryptoErrorStore* errors = CryptoJob<CipherTraits>::errors();
231
18
    errors->Capture();
232
18
    if (errors->Empty()) {
233
      switch (status) {
234
        case WebCryptoCipherStatus::OK:
235
          UNREACHABLE();
236
          break;
237
        case WebCryptoCipherStatus::INVALID_KEY_TYPE:
238
          errors->Insert(NodeCryptoError::INVALID_KEY_TYPE);
239
          break;
240
        case WebCryptoCipherStatus::FAILED:
241
          errors->Insert(NodeCryptoError::CIPHER_JOB_FAILED);
242
          break;
243
      }
244
    }
245
  }
246
247
448
  v8::Maybe<bool> ToResult(
248
      v8::Local<v8::Value>* err,
249
      v8::Local<v8::Value>* result) override {
250
448
    Environment* env = AsyncWrap::env();
251
448
    CryptoErrorStore* errors = CryptoJob<CipherTraits>::errors();
252
448
    if (out_.size() > 0) {
253
430
      CHECK(errors->Empty());
254
860
      *err = v8::Undefined(env->isolate());
255
860
      *result = out_.ToArrayBuffer(env);
256
430
      return v8::Just(!result->IsEmpty());
257
    }
258
259
18
    if (errors->Empty())
260
      errors->Capture();
261
18
    CHECK(!errors->Empty());
262
36
    *result = v8::Undefined(env->isolate());
263
36
    return v8::Just(errors->ToException(env).ToLocal(err));
264
  }
265
266
  SET_SELF_SIZE(CipherJob)
267
  void MemoryInfo(MemoryTracker* tracker) const override {
268
    if (CryptoJob<CipherTraits>::mode() == kCryptoJobAsync)
269
      tracker->TrackFieldWithSize("in", in_.size());
270
    tracker->TrackFieldWithSize("out", out_.size());
271
    CryptoJob<CipherTraits>::MemoryInfo(tracker);
272
  }
273
274
 private:
275
  std::shared_ptr<KeyObjectData> key_;
276
  WebCryptoCipherMode cipher_mode_;
277
  ByteSource in_;
278
  ByteSource out_;
279
};
280
281
}  // namespace crypto
282
}  // namespace node
283
284
#endif  // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
285
#endif  // SRC_CRYPTO_CRYPTO_CIPHER_H_