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: 60 86 69.8 %
Date: 2021-01-16 04:10:54 Branches: 29 68 42.6 %

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
444
class KeyGenJob final : public CryptoJob<KeyGenTraits> {
32
 public:
33
  using AdditionalParams = typename KeyGenTraits::AdditionalParameters;
34
35
223
  static void New(const v8::FunctionCallbackInfo<v8::Value>& args) {
36
223
    Environment* env = Environment::GetCurrent(args);
37

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

446
    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

223
    new KeyGenJob<KeyGenTraits>(env, args.This(), mode, std::move(params));
53
  }
54
55
3978
  static void Initialize(
56
      Environment* env,
57
      v8::Local<v8::Object> target) {
58
3978
    CryptoJob<KeyGenTraits>::Initialize(New, env, target);
59
3978
  }
60
61
223
  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
223
            std::move(params)) {}
72
73
220
  void DoThreadPoolWork() override {
74
    // Make sure the the CSPRNG is properly seeded so the results are secure
75
220
    CheckEntropy();
76
77
220
    AdditionalParams* params = CryptoJob<KeyGenTraits>::params();
78
79

220
    switch (KeyGenTraits::DoKeyGen(AsyncWrap::env(), params)) {
80
      case KeyGenJobStatus::OK:
81
219
        status_ = KeyGenJobStatus::OK;
82
        // Success!
83
219
        break;
84
      case KeyGenJobStatus::FAILED: {
85
        CryptoErrorVector* errors = CryptoJob<KeyGenTraits>::errors();
86
        errors->Capture();
87
        if (errors->empty())
88
          errors->push_back(std::string("Key generation job failed"));
89
      }
90
    }
91
219
  }
92
93
219
  v8::Maybe<bool> ToResult(
94
      v8::Local<v8::Value>* err,
95
      v8::Local<v8::Value>* result) override {
96
219
    Environment* env = AsyncWrap::env();
97
219
    CryptoErrorVector* errors = CryptoJob<KeyGenTraits>::errors();
98
219
    AdditionalParams* params = CryptoJob<KeyGenTraits>::params();
99



657
    if (status_ == KeyGenJobStatus::OK &&
100
657
        LIKELY(!KeyGenTraits::EncodeKey(env, params, result).IsNothing())) {
101
438
      *err = Undefined(env->isolate());
102
219
      return v8::Just(true);
103
    }
104
105
    if (errors->empty())
106
      errors->Capture();
107
    CHECK(!errors->empty());
108
    *result = Undefined(env->isolate());
109
    return v8::Just(errors->ToException(env).ToLocal(err));
110
  }
111
112
  SET_SELF_SIZE(KeyGenJob);
113
114
 private:
115
  KeyGenJobStatus status_ = KeyGenJobStatus::FAILED;
116
};
117
118
// A Base KeyGenTraits for Key Pair generation algorithms.
119
template <typename KeyPairAlgorithmTraits>
120
struct KeyPairGenTraits final {
121
  using AdditionalParameters =
122
      typename KeyPairAlgorithmTraits::AdditionalParameters;
123
124
  static const AsyncWrap::ProviderType Provider =
125
      AsyncWrap::PROVIDER_KEYPAIRGENREQUEST;
126
  static constexpr const char* JobName = KeyPairAlgorithmTraits::JobName;
127
128
141
  static v8::Maybe<bool> AdditionalConfig(
129
      CryptoJobMode mode,
130
      const v8::FunctionCallbackInfo<v8::Value>& args,
131
      unsigned int* offset,
132
      AdditionalParameters* params) {
133
    // Notice that offset is a pointer. Each of the AdditionalConfig,
134
    // GetPublicKeyEncodingFromJs, and GetPrivateKeyEncodingFromJs
135
    // functions will update the value of the offset as they successfully
136
    // process input parameters. This allows each job to have a variable
137
    // number of input parameters specific to each job type.
138
282
    if (KeyPairAlgorithmTraits::AdditionalConfig(mode, args, offset, params)
139
            .IsNothing()) {
140
2
      return v8::Just(false);
141
    }
142
143
139
    params->public_key_encoding = ManagedEVPPKey::GetPublicKeyEncodingFromJs(
144
        args,
145
        offset,
146
        kKeyContextGenerate);
147
148
    auto private_key_encoding =
149
        ManagedEVPPKey::GetPrivateKeyEncodingFromJs(
150
            args,
151
            offset,
152
278
            kKeyContextGenerate);
153
154
139
    if (!private_key_encoding.IsEmpty())
155
138
      params->private_key_encoding = private_key_encoding.Release();
156
157
139
    return v8::Just(true);
158
  }
159
160
138
  static KeyGenJobStatus DoKeyGen(
161
      Environment* env,
162
      AdditionalParameters* params) {
163
276
    EVPKeyCtxPointer ctx = KeyPairAlgorithmTraits::Setup(params);
164

138
    if (!ctx || EVP_PKEY_keygen_init(ctx.get()) <= 0)
165
      return KeyGenJobStatus::FAILED;
166
167
    // Generate the key
168
138
    EVP_PKEY* pkey = nullptr;
169
138
    if (!EVP_PKEY_keygen(ctx.get(), &pkey))
170
      return KeyGenJobStatus::FAILED;
171
172
138
    params->key = ManagedEVPPKey(EVPKeyPointer(pkey));
173
138
    return KeyGenJobStatus::OK;
174
  }
175
176
137
  static v8::Maybe<bool> EncodeKey(
177
      Environment* env,
178
      AdditionalParameters* params,
179
      v8::Local<v8::Value>* result) {
180
411
    v8::Local<v8::Value> keys[2];
181

548
    if (ManagedEVPPKey::ToEncodedPublicKey(
182
            env,
183
137
            std::move(params->key),
184
            params->public_key_encoding,
185

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