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_keygen.h Lines: 64 89 71.9 %
Date: 2021-06-09 04:12:02 Branches: 34 68 50.0 %

Line Branch Exec Source
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 "crypto/crypto_keys.h"
7
#include "crypto/crypto_util.h"
8
#include "allocated_buffer.h"
9
#include "async_wrap.h"
10
#include "base_object.h"
11
#include "env.h"
12
#include "memory_tracker.h"
13
#include "v8.h"
14
15
namespace node {
16
namespace crypto {
17
namespace Keygen {
18
void Initialize(Environment* env, v8::Local<v8::Object> target);
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
480
class KeyGenJob final : public CryptoJob<KeyGenTraits> {
32
 public:
33
  using AdditionalParams = typename KeyGenTraits::AdditionalParameters;
34
35
241
  static void New(const v8::FunctionCallbackInfo<v8::Value>& args) {
36
241
    Environment* env = Environment::GetCurrent(args);
37

241
    CHECK(args.IsConstructCall());
38
39
241
    CryptoJobMode mode = GetCryptoJobMode(args[0]);
40
41
241
    unsigned int offset = 1;
42
43
482
    AdditionalParams params;
44

482
    if (KeyGenTraits::AdditionalConfig(mode, args, &offset, &params)
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

241
    new KeyGenJob<KeyGenTraits>(env, args.This(), mode, std::move(params));
53
  }
54
55
25014
  static void Initialize(
56
      Environment* env,
57
      v8::Local<v8::Object> target) {
58
25014
    CryptoJob<KeyGenTraits>::Initialize(New, env, target);
59
25014
  }
60
61
241
  KeyGenJob(
62
      Environment* env,
63
      v8::Local<v8::Object> object,
64
      CryptoJobMode mode,
65
      AdditionalParams&& params)
66
      : CryptoJob<KeyGenTraits>(
67
            env,
68
            object,
69
            KeyGenTraits::Provider,
70
            mode,
71
241
            std::move(params)) {}
72
73
234
  void DoThreadPoolWork() override {
74
    // Make sure the CSPRNG is properly seeded so the results are secure.
75
234
    CheckEntropy();
76
77
234
    AdditionalParams* params = CryptoJob<KeyGenTraits>::params();
78
79

234
    switch (KeyGenTraits::DoKeyGen(AsyncWrap::env(), params)) {
80
      case KeyGenJobStatus::OK:
81
234
        status_ = KeyGenJobStatus::OK;
82
        // Success!
83
234
        break;
84
      case KeyGenJobStatus::FAILED: {
85
        CryptoErrorStore* errors = CryptoJob<KeyGenTraits>::errors();
86
        errors->Capture();
87
        if (errors->Empty())
88
          errors->Insert(NodeCryptoError::KEY_GENERATION_JOB_FAILED);
89
      }
90
    }
91
234
  }
92
93
233
  v8::Maybe<bool> ToResult(
94
      v8::Local<v8::Value>* err,
95
      v8::Local<v8::Value>* result) override {
96
233
    Environment* env = AsyncWrap::env();
97
233
    CryptoErrorStore* errors = CryptoJob<KeyGenTraits>::errors();
98
233
    AdditionalParams* params = CryptoJob<KeyGenTraits>::params();
99
100

233
    if (status_ == KeyGenJobStatus::OK) {
101
233
      v8::Maybe<bool> ret = KeyGenTraits::EncodeKey(env, params, result);
102



462
      if (ret.IsJust() && ret.FromJust()) {
103
458
        *err = Undefined(env->isolate());
104
      }
105
233
      return ret;
106
    }
107
108
    if (errors->Empty())
109
      errors->Capture();
110
    CHECK(!errors->Empty());
111
    *result = Undefined(env->isolate());
112
    return v8::Just(errors->ToException(env).ToLocal(err));
113
  }
114
115
  SET_SELF_SIZE(KeyGenJob)
116
117
 private:
118
  KeyGenJobStatus status_ = KeyGenJobStatus::FAILED;
119
};
120
121
// A Base KeyGenTraits for Key Pair generation algorithms.
122
template <typename KeyPairAlgorithmTraits>
123
struct KeyPairGenTraits final {
124
  using AdditionalParameters =
125
      typename KeyPairAlgorithmTraits::AdditionalParameters;
126
127
  static const AsyncWrap::ProviderType Provider =
128
      AsyncWrap::PROVIDER_KEYPAIRGENREQUEST;
129
  static constexpr const char* JobName = KeyPairAlgorithmTraits::JobName;
130
131
159
  static v8::Maybe<bool> AdditionalConfig(
132
      CryptoJobMode mode,
133
      const v8::FunctionCallbackInfo<v8::Value>& args,
134
      unsigned int* offset,
135
      AdditionalParameters* params) {
136
    // Notice that offset is a pointer. Each of the AdditionalConfig,
137
    // GetPublicKeyEncodingFromJs, and GetPrivateKeyEncodingFromJs
138
    // functions will update the value of the offset as they successfully
139
    // process input parameters. This allows each job to have a variable
140
    // number of input parameters specific to each job type.
141
318
    if (KeyPairAlgorithmTraits::AdditionalConfig(mode, args, offset, params)
142
            .IsNothing()) {
143
6
      return v8::Just(false);
144
    }
145
146
153
    params->public_key_encoding = ManagedEVPPKey::GetPublicKeyEncodingFromJs(
147
        args,
148
        offset,
149
        kKeyContextGenerate);
150
151
    auto private_key_encoding =
152
        ManagedEVPPKey::GetPrivateKeyEncodingFromJs(
153
            args,
154
            offset,
155
306
            kKeyContextGenerate);
156
157
153
    if (!private_key_encoding.IsEmpty())
158
152
      params->private_key_encoding = private_key_encoding.Release();
159
160
153
    return v8::Just(true);
161
  }
162
163
152
  static KeyGenJobStatus DoKeyGen(
164
      Environment* env,
165
      AdditionalParameters* params) {
166
304
    EVPKeyCtxPointer ctx = KeyPairAlgorithmTraits::Setup(params);
167
168
152
    if (!ctx)
169
      return KeyGenJobStatus::FAILED;
170
171
    // Generate the key
172
152
    EVP_PKEY* pkey = nullptr;
173
152
    if (!EVP_PKEY_keygen(ctx.get(), &pkey))
174
      return KeyGenJobStatus::FAILED;
175
176
152
    params->key = ManagedEVPPKey(EVPKeyPointer(pkey));
177
152
    return KeyGenJobStatus::OK;
178
  }
179
180
151
  static v8::Maybe<bool> EncodeKey(
181
      Environment* env,
182
      AdditionalParameters* params,
183
      v8::Local<v8::Value>* result) {
184
453
    v8::Local<v8::Value> keys[2];
185

604
    if (ManagedEVPPKey::ToEncodedPublicKey(
186
            env,
187
151
            std::move(params->key),
188
            params->public_key_encoding,
189

449
            &keys[0]).IsNothing() ||
190
445
        ManagedEVPPKey::ToEncodedPrivateKey(
191
            env,
192
147
            std::move(params->key),
193
            params->private_key_encoding,
194
            &keys[1]).IsNothing()) {
195
4
      return v8::Nothing<bool>();
196
    }
197
294
    *result = v8::Array::New(env->isolate(), keys, arraysize(keys));
198
147
    return v8::Just(true);
199
  }
200
};
201
202
328
struct SecretKeyGenConfig final : public MemoryRetainer {
203
  size_t length;  // Expressed a a number of bits
204
  char* out = nullptr;  // Placeholder for the generated key bytes
205
206
  void MemoryInfo(MemoryTracker* tracker) const override;
207
  SET_MEMORY_INFO_NAME(SecretKeyGenConfig)
208
  SET_SELF_SIZE(SecretKeyGenConfig)
209
};
210
211
struct SecretKeyGenTraits final {
212
  using AdditionalParameters = SecretKeyGenConfig;
213
  static const AsyncWrap::ProviderType Provider =
214
      AsyncWrap::PROVIDER_KEYGENREQUEST;
215
  static constexpr const char* JobName = "SecretKeyGenJob";
216
217
  static v8::Maybe<bool> AdditionalConfig(
218
      CryptoJobMode mode,
219
      const v8::FunctionCallbackInfo<v8::Value>& args,
220
      unsigned int* offset,
221
      SecretKeyGenConfig* params);
222
223
  static KeyGenJobStatus DoKeyGen(
224
      Environment* env,
225
      SecretKeyGenConfig* params);
226
227
  static v8::Maybe<bool> EncodeKey(
228
      Environment* env,
229
      SecretKeyGenConfig* params,
230
      v8::Local<v8::Value>* result);
231
};
232
233
template <typename AlgorithmParams>
234
struct KeyPairGenConfig final : public MemoryRetainer {
235
  PublicKeyEncodingConfig public_key_encoding;
236
  PrivateKeyEncodingConfig private_key_encoding;
237
  ManagedEVPPKey key;
238
  AlgorithmParams params;
239
240
159
  KeyPairGenConfig() = default;
241
317
  ~KeyPairGenConfig() {
242
317
    Mutex::ScopedLock priv_lock(*key.mutex());
243
634
  }
244
245
159
  explicit KeyPairGenConfig(KeyPairGenConfig&& other) noexcept
246
      : public_key_encoding(other.public_key_encoding),
247
        private_key_encoding(
248
            std::forward<PrivateKeyEncodingConfig>(
249
                other.private_key_encoding)),
250
159
        key(std::move(other.key)),
251
318
        params(std::move(other.params)) {}
252
253
  KeyPairGenConfig& operator=(KeyPairGenConfig&& other) noexcept {
254
    if (&other == this) return *this;
255
    this->~KeyPairGenConfig();
256
    return *new (this) KeyPairGenConfig(std::move(other));
257
  }
258
259
  void MemoryInfo(MemoryTracker* tracker) const override {
260
    tracker->TrackField("key", key);
261
    if (!private_key_encoding.passphrase_.IsEmpty()) {
262
      tracker->TrackFieldWithSize("private_key_encoding.passphrase",
263
                                  private_key_encoding.passphrase_->size());
264
    }
265
    tracker->TrackField("params", params);
266
  }
267
268
  SET_MEMORY_INFO_NAME(KeyPairGenConfig)
269
  SET_SELF_SIZE(KeyPairGenConfig)
270
};
271
272
80
struct NidKeyPairParams final : public MemoryRetainer {
273
  int id;
274
  SET_NO_MEMORY_INFO()
275
  SET_MEMORY_INFO_NAME(NidKeyPairParams)
276
  SET_SELF_SIZE(NidKeyPairParams)
277
};
278
279
using NidKeyPairGenConfig = KeyPairGenConfig<NidKeyPairParams>;
280
281
struct NidKeyPairGenTraits final {
282
  using AdditionalParameters = NidKeyPairGenConfig;
283
  static constexpr const char* JobName = "NidKeyPairGenJob";
284
285
  static EVPKeyCtxPointer Setup(NidKeyPairGenConfig* params);
286
287
  static v8::Maybe<bool> AdditionalConfig(
288
      CryptoJobMode mode,
289
      const v8::FunctionCallbackInfo<v8::Value>& args,
290
      unsigned int* offset,
291
      NidKeyPairGenConfig* params);
292
};
293
294
using NidKeyPairGenJob = KeyGenJob<KeyPairGenTraits<NidKeyPairGenTraits>>;
295
using SecretKeyGenJob = KeyGenJob<SecretKeyGenTraits>;
296
}  // namespace crypto
297
}  // namespace node
298
299
#endif  // !defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
300
#endif  // SRC_CRYPTO_CRYPTO_KEYGEN_H_
301