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_keys.cc Lines: 614 720 85.3 %
Date: 2021-05-27 04:11:47 Branches: 298 503 59.2 %

Line Branch Exec Source
1
#include "crypto/crypto_keys.h"
2
#include "crypto/crypto_common.h"
3
#include "crypto/crypto_dsa.h"
4
#include "crypto/crypto_ec.h"
5
#include "crypto/crypto_dh.h"
6
#include "crypto/crypto_rsa.h"
7
#include "crypto/crypto_util.h"
8
#include "async_wrap-inl.h"
9
#include "base_object-inl.h"
10
#include "env-inl.h"
11
#include "memory_tracker-inl.h"
12
#include "node.h"
13
#include "node_buffer.h"
14
#include "string_bytes.h"
15
#include "threadpoolwork-inl.h"
16
#include "util-inl.h"
17
#include "v8.h"
18
19
namespace node {
20
21
using v8::Array;
22
using v8::Context;
23
using v8::Function;
24
using v8::FunctionCallbackInfo;
25
using v8::FunctionTemplate;
26
using v8::Int32;
27
using v8::Just;
28
using v8::Local;
29
using v8::Maybe;
30
using v8::MaybeLocal;
31
using v8::NewStringType;
32
using v8::Nothing;
33
using v8::Number;
34
using v8::Object;
35
using v8::String;
36
using v8::Uint32;
37
using v8::Undefined;
38
using v8::Value;
39
40
namespace crypto {
41
namespace {
42
2487
void GetKeyFormatAndTypeFromJs(
43
    AsymmetricKeyEncodingConfig* config,
44
    const FunctionCallbackInfo<Value>& args,
45
    unsigned int* offset,
46
    KeyEncodingContext context) {
47
  // During key pair generation, it is possible not to specify a key encoding,
48
  // which will lead to a key object being returned.
49
9948
  if (args[*offset]->IsUndefined()) {
50
269
    CHECK_EQ(context, kKeyContextGenerate);
51
1076
    CHECK(args[*offset + 1]->IsUndefined());
52
269
    config->output_key_object_ = true;
53
  } else {
54
2218
    config->output_key_object_ = false;
55
56
6654
    CHECK(args[*offset]->IsInt32());
57
2218
    config->format_ = static_cast<PKFormatType>(
58
11090
        args[*offset].As<Int32>()->Value());
59
60
6654
    if (args[*offset + 1]->IsInt32()) {
61
1684
      config->type_ = Just<PKEncodingType>(static_cast<PKEncodingType>(
62
5052
          args[*offset + 1].As<Int32>()->Value()));
63
    } else {
64

1376
      CHECK(context == kKeyContextInput && config->format_ == kKeyFormatPEM);
65
5504
      CHECK(args[*offset + 1]->IsNullOrUndefined());
66
1376
      config->type_ = Nothing<PKEncodingType>();
67
    }
68
  }
69
70
2487
  *offset += 2;
71
2487
}
72
73
3143
ParseKeyResult TryParsePublicKey(
74
    EVPKeyPointer* pkey,
75
    const BIOPointer& bp,
76
    const char* name,
77
    // NOLINTNEXTLINE(runtime/int)
78
    const std::function<EVP_PKEY*(const unsigned char** p, long l)>& parse) {
79
  unsigned char* der_data;
80
  long der_len;  // NOLINT(runtime/int)
81
82
  // This skips surrounding data and decodes PEM to DER.
83
  {
84
4063
    MarkPopErrorOnReturn mark_pop_error_on_return;
85
3143
    if (PEM_bytes_read_bio(&der_data, &der_len, nullptr, name,
86
                           bp.get(), nullptr, nullptr) != 1)
87
2223
      return ParseKeyResult::kParseKeyNotRecognized;
88
  }
89
90
  // OpenSSL might modify the pointer, so we need to make a copy before parsing.
91
920
  const unsigned char* p = der_data;
92
920
  pkey->reset(parse(&p, der_len));
93
920
  OPENSSL_clear_free(der_data, der_len);
94
95
920
  return *pkey ? ParseKeyResult::kParseKeyOk :
96
1840
                 ParseKeyResult::kParseKeyFailed;
97
}
98
99
1166
ParseKeyResult ParsePublicKeyPEM(EVPKeyPointer* pkey,
100
                                 const char* key_pem,
101
                                 int key_pem_len) {
102
2332
  BIOPointer bp(BIO_new_mem_buf(const_cast<char*>(key_pem), key_pem_len));
103
1166
  if (!bp)
104
    return ParseKeyResult::kParseKeyFailed;
105
106
  ParseKeyResult ret;
107
108
  // Try parsing as a SubjectPublicKeyInfo first.
109
2332
  ret = TryParsePublicKey(pkey, bp, "PUBLIC KEY",
110
170
      [](const unsigned char** p, long l) {  // NOLINT(runtime/int)
111
        return d2i_PUBKEY(nullptr, p, l);
112
1336
      });
113
1166
  if (ret != ParseKeyResult::kParseKeyNotRecognized)
114
170
    return ret;
115
116
  // Maybe it is PKCS#1.
117
996
  CHECK(BIO_reset(bp.get()));
118
1992
  ret = TryParsePublicKey(pkey, bp, "RSA PUBLIC KEY",
119
15
      [](const unsigned char** p, long l) {  // NOLINT(runtime/int)
120
        return d2i_PublicKey(EVP_PKEY_RSA, nullptr, p, l);
121
1011
      });
122
996
  if (ret != ParseKeyResult::kParseKeyNotRecognized)
123
15
    return ret;
124
125
  // X.509 fallback.
126
981
  CHECK(BIO_reset(bp.get()));
127
1962
  return TryParsePublicKey(pkey, bp, "CERTIFICATE",
128
735
      [](const unsigned char** p, long l) {  // NOLINT(runtime/int)
129
1470
        X509Pointer x509(d2i_X509(nullptr, p, l));
130
1470
        return x509 ? X509_get_pubkey(x509.get()) : nullptr;
131
981
      });
132
}
133
134
341
ParseKeyResult ParsePublicKey(EVPKeyPointer* pkey,
135
                              const PublicKeyEncodingConfig& config,
136
                              const char* key,
137
                              size_t key_len) {
138
341
  if (config.format_ == kKeyFormatPEM) {
139
    return ParsePublicKeyPEM(pkey, key, key_len);
140
  } else {
141
341
    CHECK_EQ(config.format_, kKeyFormatDER);
142
143
341
    const unsigned char* p = reinterpret_cast<const unsigned char*>(key);
144
682
    if (config.type_.ToChecked() == kKeyEncodingPKCS1) {
145
22
      pkey->reset(d2i_PublicKey(EVP_PKEY_RSA, nullptr, &p, key_len));
146
    } else {
147
638
      CHECK_EQ(config.type_.ToChecked(), kKeyEncodingSPKI);
148
319
      pkey->reset(d2i_PUBKEY(nullptr, &p, key_len));
149
    }
150
151
341
    return *pkey ? ParseKeyResult::kParseKeyOk :
152
682
                   ParseKeyResult::kParseKeyFailed;
153
  }
154
}
155
156
403
bool IsASN1Sequence(const unsigned char* data, size_t size,
157
                    size_t* data_offset, size_t* data_size) {
158

403
  if (size < 2 || data[0] != 0x30)
159
    return false;
160
161
403
  if (data[1] & 0x80) {
162
    // Long form.
163
375
    size_t n_bytes = data[1] & ~0x80;
164

375
    if (n_bytes + 2 > size || n_bytes > sizeof(size_t))
165
      return false;
166
375
    size_t length = 0;
167
1062
    for (size_t i = 0; i < n_bytes; i++)
168
687
      length = (length << 8) | data[i + 2];
169
375
    *data_offset = 2 + n_bytes;
170
375
    *data_size = std::min(size - 2 - n_bytes, length);
171
  } else {
172
    // Short form.
173
28
    *data_offset = 2;
174
28
    *data_size = std::min<size_t>(size - 2, data[1]);
175
  }
176
177
403
  return true;
178
}
179
180
34
bool IsRSAPrivateKey(const unsigned char* data, size_t size) {
181
  // Both RSAPrivateKey and RSAPublicKey structures start with a SEQUENCE.
182
  size_t offset, len;
183
34
  if (!IsASN1Sequence(data, size, &offset, &len))
184
    return false;
185
186
  // An RSAPrivateKey sequence always starts with a single-byte integer whose
187
  // value is either 0 or 1, whereas an RSAPublicKey starts with the modulus
188
  // (which is the product of two primes and therefore at least 4), so we can
189
  // decide the type of the structure based on the first three bytes of the
190
  // sequence.
191
68
  return len >= 3 &&
192
68
         data[offset] == 2 &&
193

80
         data[offset + 1] == 1 &&
194
46
         !(data[offset + 2] & 0xfe);
195
}
196
197
369
bool IsEncryptedPrivateKeyInfo(const unsigned char* data, size_t size) {
198
  // Both PrivateKeyInfo and EncryptedPrivateKeyInfo start with a SEQUENCE.
199
  size_t offset, len;
200
369
  if (!IsASN1Sequence(data, size, &offset, &len))
201
    return false;
202
203
  // A PrivateKeyInfo sequence always starts with an integer whereas an
204
  // EncryptedPrivateKeyInfo starts with an AlgorithmIdentifier.
205

738
  return len >= 1 &&
206
738
         data[offset] != 2;
207
}
208
209
838
ParseKeyResult ParsePrivateKey(EVPKeyPointer* pkey,
210
                               const PrivateKeyEncodingConfig& config,
211
                               const char* key,
212
                               size_t key_len) {
213
838
  const ByteSource* passphrase = config.passphrase_.get();
214
215
838
  if (config.format_ == kKeyFormatPEM) {
216
912
    BIOPointer bio(BIO_new_mem_buf(key, key_len));
217
456
    if (!bio)
218
      return ParseKeyResult::kParseKeyFailed;
219
220
456
    pkey->reset(PEM_read_bio_PrivateKey(bio.get(),
221
                                        nullptr,
222
                                        PasswordCallback,
223
456
                                        &passphrase));
224
  } else {
225
382
    CHECK_EQ(config.format_, kKeyFormatDER);
226
227
764
    if (config.type_.ToChecked() == kKeyEncodingPKCS1) {
228
13
      const unsigned char* p = reinterpret_cast<const unsigned char*>(key);
229
13
      pkey->reset(d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &p, key_len));
230
738
    } else if (config.type_.ToChecked() == kKeyEncodingPKCS8) {
231
738
      BIOPointer bio(BIO_new_mem_buf(key, key_len));
232
369
      if (!bio)
233
        return ParseKeyResult::kParseKeyFailed;
234
235
369
      if (IsEncryptedPrivateKeyInfo(
236
              reinterpret_cast<const unsigned char*>(key), key_len)) {
237
17
        pkey->reset(d2i_PKCS8PrivateKey_bio(bio.get(),
238
                                            nullptr,
239
                                            PasswordCallback,
240
17
                                            &passphrase));
241
      } else {
242
704
        PKCS8Pointer p8inf(d2i_PKCS8_PRIV_KEY_INFO_bio(bio.get(), nullptr));
243
352
        if (p8inf)
244
352
          pkey->reset(EVP_PKCS82PKEY(p8inf.get()));
245
      }
246
    } else {
247
      CHECK_EQ(config.type_.ToChecked(), kKeyEncodingSEC1);
248
      const unsigned char* p = reinterpret_cast<const unsigned char*>(key);
249
      pkey->reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &p, key_len));
250
    }
251
  }
252
253
  // OpenSSL can fail to parse the key but still return a non-null pointer.
254
838
  unsigned long err = ERR_peek_error();  // NOLINT(runtime/int)
255
838
  if (err != 0)
256
22
    pkey->reset();
257
258
838
  if (*pkey)
259
816
    return ParseKeyResult::kParseKeyOk;
260

36
  if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
261
14
      ERR_GET_REASON(err) == PEM_R_BAD_PASSWORD_READ) {
262
12
    if (config.passphrase_.IsEmpty())
263
11
      return ParseKeyResult::kParseKeyNeedPassphrase;
264
  }
265
11
  return ParseKeyResult::kParseKeyFailed;
266
}
267
268
112
MaybeLocal<Value> BIOToStringOrBuffer(
269
    Environment* env,
270
    BIO* bio,
271
    PKFormatType format) {
272
  BUF_MEM* bptr;
273
112
  BIO_get_mem_ptr(bio, &bptr);
274
112
  if (format == kKeyFormatPEM) {
275
    // PEM is an ASCII format, so we will return it as a string.
276
222
    return String::NewFromUtf8(env->isolate(), bptr->data,
277
                               NewStringType::kNormal,
278
296
                               bptr->length).FromMaybe(Local<Value>());
279
  } else {
280
38
    CHECK_EQ(format, kKeyFormatDER);
281
    // DER is binary, return it as a buffer.
282
76
    return Buffer::Copy(env, bptr->data, bptr->length)
283
76
        .FromMaybe(Local<Value>());
284
  }
285
}
286
287
288
54
MaybeLocal<Value> WritePrivateKey(
289
    Environment* env,
290
    EVP_PKEY* pkey,
291
    const PrivateKeyEncodingConfig& config) {
292
108
  BIOPointer bio(BIO_new(BIO_s_mem()));
293
54
  CHECK(bio);
294
295
  // If an empty string was passed as the passphrase, the ByteSource might
296
  // contain a null pointer, which OpenSSL will ignore, causing it to invoke its
297
  // default passphrase callback, which would block the thread until the user
298
  // manually enters a passphrase. We could supply our own passphrase callback
299
  // to handle this special case, but it is easier to avoid passing a null
300
  // pointer to OpenSSL.
301
54
  char* pass = nullptr;
302
54
  size_t pass_len = 0;
303
54
  if (!config.passphrase_.IsEmpty()) {
304
11
    pass = const_cast<char*>(config.passphrase_->get());
305
11
    pass_len = config.passphrase_->size();
306
11
    if (pass == nullptr) {
307
      // OpenSSL will not actually dereference this pointer, so it can be any
308
      // non-null pointer. We cannot assert that directly, which is why we
309
      // intentionally use a pointer that will likely cause a segmentation fault
310
      // when dereferenced.
311
2
      CHECK_EQ(pass_len, 0);
312
2
      pass = reinterpret_cast<char*>(-1);
313
2
      CHECK_NE(pass, nullptr);
314
    }
315
  }
316
317
  bool err;
318
319
108
  PKEncodingType encoding_type = config.type_.ToChecked();
320
54
  if (encoding_type == kKeyEncodingPKCS1) {
321
    // PKCS#1 is only permitted for RSA keys.
322
12
    CHECK_EQ(EVP_PKEY_id(pkey), EVP_PKEY_RSA);
323
324
24
    RSAPointer rsa(EVP_PKEY_get1_RSA(pkey));
325
12
    if (config.format_ == kKeyFormatPEM) {
326
      // Encode PKCS#1 as PEM.
327
22
      err = PEM_write_bio_RSAPrivateKey(
328
                bio.get(), rsa.get(),
329
11
                config.cipher_,
330
                reinterpret_cast<unsigned char*>(pass),
331
                pass_len,
332
                nullptr, nullptr) != 1;
333
    } else {
334
      // Encode PKCS#1 as DER. This does not permit encryption.
335
1
      CHECK_EQ(config.format_, kKeyFormatDER);
336
1
      CHECK_NULL(config.cipher_);
337
1
      err = i2d_RSAPrivateKey_bio(bio.get(), rsa.get()) != 1;
338
    }
339
42
  } else if (encoding_type == kKeyEncodingPKCS8) {
340
38
    if (config.format_ == kKeyFormatPEM) {
341
      // Encode PKCS#8 as PEM.
342
42
      err = PEM_write_bio_PKCS8PrivateKey(
343
                bio.get(), pkey,
344
21
                config.cipher_,
345
                pass,
346
                pass_len,
347
                nullptr, nullptr) != 1;
348
    } else {
349
      // Encode PKCS#8 as DER.
350
17
      CHECK_EQ(config.format_, kKeyFormatDER);
351
34
      err = i2d_PKCS8PrivateKey_bio(
352
                bio.get(), pkey,
353
17
                config.cipher_,
354
                pass,
355
                pass_len,
356
                nullptr, nullptr) != 1;
357
    }
358
  } else {
359
4
    CHECK_EQ(encoding_type, kKeyEncodingSEC1);
360
361
    // SEC1 is only permitted for EC keys.
362
4
    CHECK_EQ(EVP_PKEY_id(pkey), EVP_PKEY_EC);
363
364
8
    ECKeyPointer ec_key(EVP_PKEY_get1_EC_KEY(pkey));
365
4
    if (config.format_ == kKeyFormatPEM) {
366
      // Encode SEC1 as PEM.
367
8
      err = PEM_write_bio_ECPrivateKey(
368
                bio.get(), ec_key.get(),
369
4
                config.cipher_,
370
                reinterpret_cast<unsigned char*>(pass),
371
                pass_len,
372
                nullptr, nullptr) != 1;
373
    } else {
374
      // Encode SEC1 as DER. This does not permit encryption.
375
      CHECK_EQ(config.format_, kKeyFormatDER);
376
      CHECK_NULL(config.cipher_);
377
      err = i2d_ECPrivateKey_bio(bio.get(), ec_key.get()) != 1;
378
    }
379
  }
380
381
54
  if (err) {
382
    ThrowCryptoError(env, ERR_get_error(), "Failed to encode private key");
383
    return MaybeLocal<Value>();
384
  }
385
54
  return BIOToStringOrBuffer(env, bio.get(), config.format_);
386
}
387
388
62
bool WritePublicKeyInner(EVP_PKEY* pkey,
389
                         const BIOPointer& bio,
390
                         const PublicKeyEncodingConfig& config) {
391
124
  if (config.type_.ToChecked() == kKeyEncodingPKCS1) {
392
    // PKCS#1 is only valid for RSA keys.
393
13
    CHECK_EQ(EVP_PKEY_id(pkey), EVP_PKEY_RSA);
394
26
    RSAPointer rsa(EVP_PKEY_get1_RSA(pkey));
395
13
    if (config.format_ == kKeyFormatPEM) {
396
      // Encode PKCS#1 as PEM.
397
7
      return PEM_write_bio_RSAPublicKey(bio.get(), rsa.get()) == 1;
398
    } else {
399
      // Encode PKCS#1 as DER.
400
6
      CHECK_EQ(config.format_, kKeyFormatDER);
401
6
      return i2d_RSAPublicKey_bio(bio.get(), rsa.get()) == 1;
402
    }
403
  } else {
404
98
    CHECK_EQ(config.type_.ToChecked(), kKeyEncodingSPKI);
405
49
    if (config.format_ == kKeyFormatPEM) {
406
      // Encode SPKI as PEM.
407
31
      return PEM_write_bio_PUBKEY(bio.get(), pkey) == 1;
408
    } else {
409
      // Encode SPKI as DER.
410
18
      CHECK_EQ(config.format_, kKeyFormatDER);
411
18
      return i2d_PUBKEY_bio(bio.get(), pkey) == 1;
412
    }
413
  }
414
}
415
416
62
MaybeLocal<Value> WritePublicKey(Environment* env,
417
                                 EVP_PKEY* pkey,
418
                                 const PublicKeyEncodingConfig& config) {
419
124
  BIOPointer bio(BIO_new(BIO_s_mem()));
420
62
  CHECK(bio);
421
422
62
  if (!WritePublicKeyInner(pkey, bio, config)) {
423
4
    ThrowCryptoError(env, ERR_get_error(), "Failed to encode public key");
424
4
    return MaybeLocal<Value>();
425
  }
426
58
  return BIOToStringOrBuffer(env, bio.get(), config.format_);
427
}
428
429
68
Maybe<bool> ExportJWKSecretKey(
430
    Environment* env,
431
    std::shared_ptr<KeyObjectData> key,
432
    Local<Object> target) {
433
68
  CHECK_EQ(key->GetKeyType(), kKeyTypeSecret);
434
435
  Local<Value> error;
436
  Local<Value> raw;
437
  MaybeLocal<Value> key_data =
438
      StringBytes::Encode(
439
          env->isolate(),
440
          key->GetSymmetricKey(),
441
          key->GetSymmetricKeySize(),
442
          BASE64URL,
443
68
          &error);
444
68
  if (key_data.IsEmpty()) {
445
    CHECK(!error.IsEmpty());
446
    env->isolate()->ThrowException(error);
447
    return Nothing<bool>();
448
  }
449
68
  if (!key_data.ToLocal(&raw))
450
    return Nothing<bool>();
451
452
272
  if (target->Set(
453
          env->context(),
454
          env->jwk_kty_string(),
455

476
          env->jwk_oct_string()).IsNothing() ||
456
136
      target->Set(
457
          env->context(),
458
          env->jwk_k_string(),
459
340
          raw).IsNothing()) {
460
    return Nothing<bool>();
461
  }
462
463
68
  return Just(true);
464
}
465
466
20
std::shared_ptr<KeyObjectData> ImportJWKSecretKey(
467
    Environment* env,
468
    Local<Object> jwk) {
469
  Local<Value> key;
470

100
  if (!jwk->Get(env->context(), env->jwk_k_string()).ToLocal(&key) ||
471
40
      !key->IsString()) {
472
    THROW_ERR_CRYPTO_INVALID_JWK(env, "Invalid JWK secret key format");
473
    return std::shared_ptr<KeyObjectData>();
474
  }
475
476
40
  ByteSource key_data = ByteSource::FromEncodedString(env, key.As<String>());
477
20
  if (key_data.size() > INT_MAX) {
478
    THROW_ERR_CRYPTO_INVALID_KEYLEN(env);
479
    return std::shared_ptr<KeyObjectData>();
480
  }
481
482
20
  return KeyObjectData::CreateSecret(std::move(key_data));
483
}
484
485
285
Maybe<bool> ExportJWKAsymmetricKey(
486
    Environment* env,
487
    std::shared_ptr<KeyObjectData> key,
488
    Local<Object> target) {
489

285
  switch (EVP_PKEY_id(key->GetAsymmetricKey().get())) {
490
    case EVP_PKEY_RSA:
491
      // Fall through
492
157
    case EVP_PKEY_RSA_PSS: return ExportJWKRsaKey(env, key, target);
493
90
    case EVP_PKEY_EC: return ExportJWKEcKey(env, key, target);
494
    case EVP_PKEY_ED25519:
495
      // Fall through
496
    case EVP_PKEY_ED448:
497
      // Fall through
498
    case EVP_PKEY_X25519:
499
      // Fall through
500
38
    case EVP_PKEY_X448: return ExportJWKEdKey(env, key, target);
501
  }
502
  THROW_ERR_CRYPTO_INVALID_KEYTYPE(env);
503
  return Just(false);
504
}
505
506
262
std::shared_ptr<KeyObjectData> ImportJWKAsymmetricKey(
507
    Environment* env,
508
    Local<Object> jwk,
509
    const char* kty,
510
    const FunctionCallbackInfo<Value>& args,
511
    unsigned int offset) {
512
262
  if (strcmp(kty, "RSA") == 0) {
513
186
    return ImportJWKRsaKey(env, jwk, args, offset);
514
76
  } else if (strcmp(kty, "EC") == 0) {
515
76
    return ImportJWKEcKey(env, jwk, args, offset);
516
  }
517
518
  THROW_ERR_CRYPTO_INVALID_JWK(env, "%s is not a supported JWK key type", kty);
519
  return std::shared_ptr<KeyObjectData>();
520
}
521
522
643
Maybe<bool> GetSecretKeyDetail(
523
    Environment* env,
524
    std::shared_ptr<KeyObjectData> key,
525
    Local<Object> target) {
526
  // For the secret key detail, all we care about is the length,
527
  // converted to bits.
528
529
643
  size_t length = key->GetSymmetricKeySize() * CHAR_BIT;
530
  return target->Set(env->context(),
531
                     env->length_string(),
532
2572
                     Number::New(env->isolate(), static_cast<double>(length)));
533
}
534
535
857
Maybe<bool> GetAsymmetricKeyDetail(
536
  Environment* env,
537
  std::shared_ptr<KeyObjectData> key,
538
  Local<Object> target) {
539

857
  switch (EVP_PKEY_id(key->GetAsymmetricKey().get())) {
540
    case EVP_PKEY_RSA:
541
      // Fall through
542
615
    case EVP_PKEY_RSA_PSS: return GetRsaKeyDetail(env, key, target);
543
42
    case EVP_PKEY_DSA: return GetDsaKeyDetail(env, key, target);
544
197
    case EVP_PKEY_EC: return GetEcKeyDetail(env, key, target);
545
3
    case EVP_PKEY_DH: return GetDhKeyDetail(env, key, target);
546
  }
547
  THROW_ERR_CRYPTO_INVALID_KEYTYPE(env);
548
  return Nothing<bool>();
549
}
550
}  // namespace
551
552
5094
ManagedEVPPKey::ManagedEVPPKey(EVPKeyPointer&& pkey) : pkey_(std::move(pkey)),
553
5094
    mutex_(std::make_shared<Mutex>()) {}
554
555
7171
ManagedEVPPKey::ManagedEVPPKey(const ManagedEVPPKey& that) {
556
7171
  *this = that;
557
7171
}
558
559
10137
ManagedEVPPKey& ManagedEVPPKey::operator=(const ManagedEVPPKey& that) {
560
20273
  Mutex::ScopedLock lock(*that.mutex_);
561
562
10136
  pkey_.reset(that.get());
563
564
10137
  if (pkey_)
565
9964
    EVP_PKEY_up_ref(pkey_.get());
566
567
10137
  mutex_ = that.mutex_;
568
569
20273
  return *this;
570
}
571
572
4149
ManagedEVPPKey::operator bool() const {
573
4149
  return !!pkey_;
574
}
575
576
22255
EVP_PKEY* ManagedEVPPKey::get() const {
577
22255
  return pkey_.get();
578
}
579
580
2750
Mutex* ManagedEVPPKey::mutex() const {
581
2750
  return mutex_.get();
582
}
583
584
void ManagedEVPPKey::MemoryInfo(MemoryTracker* tracker) const {
585
  tracker->TrackFieldWithSize("pkey",
586
                              !pkey_ ? 0 : kSizeOf_EVP_PKEY +
587
                              size_of_private_key() +
588
                              size_of_public_key());
589
}
590
591
size_t ManagedEVPPKey::size_of_private_key() const {
592
  size_t len = 0;
593
  return (pkey_ && EVP_PKEY_get_raw_private_key(
594
      pkey_.get(), nullptr, &len) == 1) ? len : 0;
595
}
596
597
size_t ManagedEVPPKey::size_of_public_key() const {
598
  size_t len = 0;
599
  return (pkey_ && EVP_PKEY_get_raw_public_key(
600
      pkey_.get(), nullptr, &len) == 1) ? len : 0;
601
}
602
603
// This maps true to Just<bool>(true) and false to Nothing<bool>().
604
298
static inline Maybe<bool> Tristate(bool b) {
605
298
  return b ? Just(true) : Nothing<bool>();
606
}
607
608
151
Maybe<bool> ManagedEVPPKey::ToEncodedPublicKey(
609
    Environment* env,
610
    ManagedEVPPKey key,
611
    const PublicKeyEncodingConfig& config,
612
    Local<Value>* out) {
613
151
  if (!key) return Nothing<bool>();
614
151
  if (config.output_key_object_) {
615
    // Note that this has the downside of containing sensitive data of the
616
    // private key.
617
    std::shared_ptr<KeyObjectData> data =
618
266
          KeyObjectData::CreateAsymmetric(kKeyTypePublic, std::move(key));
619
266
    return Tristate(KeyObjectHandle::Create(env, data).ToLocal(out));
620
  }
621
622
36
  return Tristate(WritePublicKey(env, key.get(), config).ToLocal(out));
623
}
624
625
147
Maybe<bool> ManagedEVPPKey::ToEncodedPrivateKey(
626
    Environment* env,
627
    ManagedEVPPKey key,
628
    const PrivateKeyEncodingConfig& config,
629
    Local<Value>* out) {
630
147
  if (!key) return Nothing<bool>();
631
147
  if (config.output_key_object_) {
632
    std::shared_ptr<KeyObjectData> data =
633
262
        KeyObjectData::CreateAsymmetric(kKeyTypePrivate, std::move(key));
634
262
    return Tristate(KeyObjectHandle::Create(env, data).ToLocal(out));
635
  }
636
637
32
  return Tristate(WritePrivateKey(env, key.get(), config).ToLocal(out));
638
}
639
640
NonCopyableMaybe<PrivateKeyEncodingConfig>
641
2290
ManagedEVPPKey::GetPrivateKeyEncodingFromJs(
642
    const FunctionCallbackInfo<Value>& args,
643
    unsigned int* offset,
644
    KeyEncodingContext context) {
645
2290
  Environment* env = Environment::GetCurrent(args);
646
647
4580
  PrivateKeyEncodingConfig result;
648
2290
  GetKeyFormatAndTypeFromJs(&result, args, offset, context);
649
650
2290
  if (result.output_key_object_) {
651
135
    if (context != kKeyContextInput)
652
135
      (*offset)++;
653
  } else {
654
2155
    bool needs_passphrase = false;
655
2155
    if (context != kKeyContextInput) {
656
224
      if (args[*offset]->IsString()) {
657
35
        Utf8Value cipher_name(env->isolate(), args[*offset]);
658
12
        result.cipher_ = EVP_get_cipherbyname(*cipher_name);
659
12
        if (result.cipher_ == nullptr) {
660
1
          THROW_ERR_CRYPTO_UNKNOWN_CIPHER(env);
661
1
          return NonCopyableMaybe<PrivateKeyEncodingConfig>();
662
        }
663
11
        needs_passphrase = true;
664
      } else {
665
176
        CHECK(args[*offset]->IsNullOrUndefined());
666
44
        result.cipher_ = nullptr;
667
      }
668
55
      (*offset)++;
669
    }
670
671
4308
    if (IsAnyByteSource(args[*offset])) {
672

96
      CHECK_IMPLIES(context != kKeyContextInput, result.cipher_ != nullptr);
673
288
      ArrayBufferOrViewContents<char> passphrase(args[*offset]);
674
96
      if (UNLIKELY(!passphrase.CheckSizeInt32())) {
675
        THROW_ERR_OUT_OF_RANGE(env, "passphrase is too big");
676
        return NonCopyableMaybe<PrivateKeyEncodingConfig>();
677
      }
678
192
      result.passphrase_ = NonCopyableMaybe<ByteSource>(
679
288
          passphrase.ToNullTerminatedCopy());
680
    } else {
681

8232
      CHECK(args[*offset]->IsNullOrUndefined() && !needs_passphrase);
682
    }
683
  }
684
685
2289
  (*offset)++;
686
2289
  return NonCopyableMaybe<PrivateKeyEncodingConfig>(std::move(result));
687
}
688
689
197
PublicKeyEncodingConfig ManagedEVPPKey::GetPublicKeyEncodingFromJs(
690
    const FunctionCallbackInfo<Value>& args,
691
    unsigned int* offset,
692
    KeyEncodingContext context) {
693
197
  PublicKeyEncodingConfig result;
694
197
  GetKeyFormatAndTypeFromJs(&result, args, offset, context);
695
197
  return result;
696
}
697
698
645
ManagedEVPPKey ManagedEVPPKey::GetPrivateKeyFromJs(
699
    const FunctionCallbackInfo<Value>& args,
700
    unsigned int* offset,
701
    bool allow_key_object) {
702

3225
  if (args[*offset]->IsString() || IsAnyByteSource(args[*offset])) {
703
523
    Environment* env = Environment::GetCurrent(args);
704
1569
    ByteSource key = ByteSource::FromStringOrBuffer(env, args[(*offset)++]);
705
    NonCopyableMaybe<PrivateKeyEncodingConfig> config =
706
1046
        GetPrivateKeyEncodingFromJs(args, offset, kKeyContextInput);
707
523
    if (config.IsEmpty())
708
      return ManagedEVPPKey();
709
710
1046
    EVPKeyPointer pkey;
711
    ParseKeyResult ret =
712
523
        ParsePrivateKey(&pkey, config.Release(), key.get(), key.size());
713
523
    return GetParsedKey(env, std::move(pkey), ret,
714
523
                        "Failed to read private key");
715
  } else {
716

366
    CHECK(args[*offset]->IsObject() && allow_key_object);
717
    KeyObjectHandle* key;
718
366
    ASSIGN_OR_RETURN_UNWRAP(&key, args[*offset].As<Object>(), ManagedEVPPKey());
719
122
    CHECK_EQ(key->Data()->GetKeyType(), kKeyTypePrivate);
720
122
    (*offset) += 4;
721
122
    return key->Data()->GetAsymmetricKey();
722
  }
723
}
724
725
1967
ManagedEVPPKey ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(
726
    const FunctionCallbackInfo<Value>& args,
727
    unsigned int* offset) {
728
3934
  if (IsAnyByteSource(args[*offset])) {
729
1576
    Environment* env = Environment::GetCurrent(args);
730
4728
    ArrayBufferOrViewContents<char> data(args[(*offset)++]);
731
1576
    if (UNLIKELY(!data.CheckSizeInt32())) {
732
      THROW_ERR_OUT_OF_RANGE(env, "keyData is too big");
733
      return ManagedEVPPKey();
734
    }
735
    NonCopyableMaybe<PrivateKeyEncodingConfig> config_ =
736
3152
        GetPrivateKeyEncodingFromJs(args, offset, kKeyContextInput);
737
1576
    if (config_.IsEmpty())
738
      return ManagedEVPPKey();
739
740
    ParseKeyResult ret;
741
3152
    PrivateKeyEncodingConfig config = config_.Release();
742
3152
    EVPKeyPointer pkey;
743
1576
    if (config.format_ == kKeyFormatPEM) {
744
      // For PEM, we can easily determine whether it is a public or private key
745
      // by looking for the respective PEM tags.
746
1166
      ret = ParsePublicKeyPEM(&pkey, data.data(), data.size());
747
1166
      if (ret == ParseKeyResult::kParseKeyNotRecognized) {
748
246
        ret = ParsePrivateKey(&pkey, config, data.data(), data.size());
749
      }
750
    } else {
751
      // For DER, the type determines how to parse it. SPKI, PKCS#8 and SEC1 are
752
      // easy, but PKCS#1 can be a public key or a private key.
753
      bool is_public;
754

410
      switch (config.type_.ToChecked()) {
755
        case kKeyEncodingPKCS1:
756
68
          is_public = !IsRSAPrivateKey(
757
34
              reinterpret_cast<const unsigned char*>(data.data()), data.size());
758
34
          break;
759
        case kKeyEncodingSPKI:
760
319
          is_public = true;
761
319
          break;
762
        case kKeyEncodingPKCS8:
763
        case kKeyEncodingSEC1:
764
57
          is_public = false;
765
57
          break;
766
        default:
767
          UNREACHABLE("Invalid key encoding type");
768
      }
769
770
410
      if (is_public) {
771
341
        ret = ParsePublicKey(&pkey, config, data.data(), data.size());
772
      } else {
773
69
        ret = ParsePrivateKey(&pkey, config, data.data(), data.size());
774
      }
775
    }
776
777
    return ManagedEVPPKey::GetParsedKey(
778
1576
        env, std::move(pkey), ret, "Failed to read asymmetric key");
779
  } else {
780
1173
    CHECK(args[*offset]->IsObject());
781
1173
    KeyObjectHandle* key = Unwrap<KeyObjectHandle>(args[*offset].As<Object>());
782
391
    CHECK_NOT_NULL(key);
783
391
    CHECK_NE(key->Data()->GetKeyType(), kKeyTypeSecret);
784
391
    (*offset) += 4;
785
391
    return key->Data()->GetAsymmetricKey();
786
  }
787
}
788
789
2099
ManagedEVPPKey ManagedEVPPKey::GetParsedKey(Environment* env,
790
                                            EVPKeyPointer&& pkey,
791
                                            ParseKeyResult ret,
792
                                            const char* default_msg) {
793
2099
  switch (ret) {
794
    case ParseKeyResult::kParseKeyOk:
795
2077
      CHECK(pkey);
796
2077
      break;
797
    case ParseKeyResult::kParseKeyNeedPassphrase:
798
      THROW_ERR_MISSING_PASSPHRASE(env,
799
11
                                   "Passphrase required for encrypted key");
800
11
      break;
801
    default:
802
11
      ThrowCryptoError(env, ERR_get_error(), default_msg);
803
  }
804
805
2099
  return ManagedEVPPKey(std::move(pkey));
806
}
807
808
899
KeyObjectData::KeyObjectData(
809
899
    ByteSource symmetric_key)
810
    : key_type_(KeyType::kKeyTypeSecret),
811
899
      symmetric_key_(std::move(symmetric_key)),
812
899
      symmetric_key_len_(symmetric_key_.size()),
813
2697
      asymmetric_key_() {}
814
815
1232
KeyObjectData::KeyObjectData(
816
    KeyType type,
817
1232
    const ManagedEVPPKey& pkey)
818
    : key_type_(type),
819
      symmetric_key_(),
820
      symmetric_key_len_(0),
821
1232
      asymmetric_key_{pkey} {}
822
823
void KeyObjectData::MemoryInfo(MemoryTracker* tracker) const {
824
  switch (GetKeyType()) {
825
    case kKeyTypeSecret:
826
      tracker->TrackFieldWithSize("symmetric_key", symmetric_key_.size());
827
      break;
828
    case kKeyTypePrivate:
829
      // Fall through
830
    case kKeyTypePublic:
831
      tracker->TrackFieldWithSize("key", asymmetric_key_);
832
      break;
833
    default:
834
      UNREACHABLE();
835
  }
836
}
837
838
899
std::shared_ptr<KeyObjectData> KeyObjectData::CreateSecret(ByteSource key) {
839
899
  CHECK(key);
840
899
  return std::shared_ptr<KeyObjectData>(new KeyObjectData(std::move(key)));
841
}
842
843
1232
std::shared_ptr<KeyObjectData> KeyObjectData::CreateAsymmetric(
844
    KeyType key_type,
845
    const ManagedEVPPKey& pkey) {
846
1232
  CHECK(pkey);
847
1232
  return std::shared_ptr<KeyObjectData>(new KeyObjectData(key_type, pkey));
848
}
849
850
4895
KeyType KeyObjectData::GetKeyType() const {
851
4895
  return key_type_;
852
}
853
854
3504
ManagedEVPPKey KeyObjectData::GetAsymmetricKey() const {
855
3504
  CHECK_NE(key_type_, kKeyTypeSecret);
856
3504
  return asymmetric_key_;
857
}
858
859
1455
const char* KeyObjectData::GetSymmetricKey() const {
860
1455
  CHECK_EQ(key_type_, kKeyTypeSecret);
861
1455
  return symmetric_key_.get();
862
}
863
864
2031
size_t KeyObjectData::GetSymmetricKeySize() const {
865
2031
  CHECK_EQ(key_type_, kKeyTypeSecret);
866
2031
  return symmetric_key_len_;
867
}
868
869
4521
v8::Local<v8::Function> KeyObjectHandle::Initialize(Environment* env) {
870
4521
  Local<Function> templ = env->crypto_key_object_handle_constructor();
871
4521
  if (!templ.IsEmpty()) {
872
356
    return templ;
873
  }
874
4165
  Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
875
12495
  t->InstanceTemplate()->SetInternalFieldCount(
876
4165
      KeyObjectHandle::kInternalFieldCount);
877
8330
  t->Inherit(BaseObject::GetConstructorTemplate(env));
878
879
4165
  env->SetProtoMethod(t, "init", Init);
880
  env->SetProtoMethodNoSideEffect(t, "getSymmetricKeySize",
881
4165
                                  GetSymmetricKeySize);
882
  env->SetProtoMethodNoSideEffect(t, "getAsymmetricKeyType",
883
4165
                                  GetAsymmetricKeyType);
884
4165
  env->SetProtoMethod(t, "export", Export);
885
4165
  env->SetProtoMethod(t, "exportJwk", ExportJWK);
886
4165
  env->SetProtoMethod(t, "initECRaw", InitECRaw);
887
4165
  env->SetProtoMethod(t, "initEDRaw", InitEDRaw);
888
4165
  env->SetProtoMethod(t, "initJwk", InitJWK);
889
4165
  env->SetProtoMethod(t, "keyDetail", GetKeyDetail);
890
891
12495
  auto function = t->GetFunction(env->context()).ToLocalChecked();
892
4165
  env->set_crypto_key_object_handle_constructor(function);
893
4165
  return function;
894
}
895
896
356
MaybeLocal<Object> KeyObjectHandle::Create(
897
    Environment* env,
898
    std::shared_ptr<KeyObjectData> data) {
899
  Local<Object> obj;
900
356
  Local<Function> ctor = KeyObjectHandle::Initialize(env);
901
712
  CHECK(!env->crypto_key_object_handle_constructor().IsEmpty());
902
1068
  if (!ctor->NewInstance(env->context(), 0, nullptr).ToLocal(&obj))
903
    return MaybeLocal<Object>();
904
905
356
  KeyObjectHandle* key = Unwrap<KeyObjectHandle>(obj);
906
356
  CHECK_NOT_NULL(key);
907
356
  key->data_ = data;
908
356
  return obj;
909
}
910
911
7414
const std::shared_ptr<KeyObjectData>& KeyObjectHandle::Data() {
912
7414
  return data_;
913
}
914
915
2148
void KeyObjectHandle::New(const FunctionCallbackInfo<Value>& args) {
916
2148
  CHECK(args.IsConstructCall());
917
2148
  Environment* env = Environment::GetCurrent(args);
918
2148
  new KeyObjectHandle(env, args.This());
919
2148
}
920
921
2148
KeyObjectHandle::KeyObjectHandle(Environment* env,
922
2148
                                 Local<Object> wrap)
923
2148
    : BaseObject(env, wrap) {
924
2148
  MakeWeak();
925
2148
}
926
927
1474
void KeyObjectHandle::Init(const FunctionCallbackInfo<Value>& args) {
928
  KeyObjectHandle* key;
929
1479
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
930
2943
  MarkPopErrorOnReturn mark_pop_error_on_return;
931
932
2948
  CHECK(args[0]->IsInt32());
933
4422
  KeyType type = static_cast<KeyType>(args[0].As<Uint32>()->Value());
934
935
  unsigned int offset;
936
2943
  ManagedEVPPKey pkey;
937
938

1474
  switch (type) {
939
  case kKeyTypeSecret: {
940
797
    CHECK_EQ(args.Length(), 2);
941
1594
    ArrayBufferOrViewContents<char> buf(args[1]);
942
797
    key->data_ = KeyObjectData::CreateSecret(buf.ToCopy());
943
797
    break;
944
  }
945
  case kKeyTypePublic: {
946
340
    CHECK_EQ(args.Length(), 5);
947
948
340
    offset = 1;
949
340
    pkey = ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(args, &offset);
950
340
    if (!pkey)
951
      return;
952
340
    key->data_ = KeyObjectData::CreateAsymmetric(type, pkey);
953
340
    break;
954
  }
955
  case kKeyTypePrivate: {
956
337
    CHECK_EQ(args.Length(), 5);
957
958
337
    offset = 1;
959
337
    pkey = ManagedEVPPKey::GetPrivateKeyFromJs(args, &offset, false);
960
337
    if (!pkey)
961
5
      return;
962
332
    key->data_ = KeyObjectData::CreateAsymmetric(type, pkey);
963
332
    break;
964
  }
965
  default:
966
    UNREACHABLE();
967
  }
968
}
969
970
282
void KeyObjectHandle::InitJWK(const FunctionCallbackInfo<Value>& args) {
971
282
  Environment* env = Environment::GetCurrent(args);
972
  KeyObjectHandle* key;
973
282
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
974
564
  MarkPopErrorOnReturn mark_pop_error_on_return;
975
976
  // The argument must be a JavaScript object that we will inspect
977
  // to get the JWK properties from.
978
564
  CHECK(args[0]->IsObject());
979
980
  // Step one, Secret key or not?
981
564
  Local<Object> input = args[0].As<Object>();
982
983
  Local<Value> kty;
984

1410
  if (!input->Get(env->context(), env->jwk_kty_string()).ToLocal(&kty) ||
985
564
      !kty->IsString()) {
986
    return THROW_ERR_CRYPTO_INVALID_JWK(env);
987
  }
988
989
564
  Utf8Value kty_string(env->isolate(), kty);
990
991
282
  if (strcmp(*kty_string, "oct") == 0) {
992
    // Secret key
993
20
    key->data_ = ImportJWKSecretKey(env, input);
994
20
    if (!key->data_) {
995
      // ImportJWKSecretKey is responsible for throwing an appropriate error
996
      return;
997
    }
998
  } else {
999
262
    key->data_ = ImportJWKAsymmetricKey(env, input, *kty_string, args, 1);
1000
262
    if (!key->data_) {
1001
      // ImportJWKAsymmetricKey is responsible for throwing an appropriate error
1002
      return;
1003
    }
1004
  }
1005
1006
846
  args.GetReturnValue().Set(key->data_->GetKeyType());
1007
}
1008
1009
void KeyObjectHandle::InitECRaw(const FunctionCallbackInfo<Value>& args) {
1010
  Environment* env = Environment::GetCurrent(args);
1011
  KeyObjectHandle* key;
1012
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1013
1014
  CHECK(args[0]->IsString());
1015
  Utf8Value name(env->isolate(), args[0]);
1016
1017
  MarkPopErrorOnReturn mark_pop_error_on_return;
1018
1019
  int id = OBJ_txt2nid(*name);
1020
  ECKeyPointer eckey(EC_KEY_new_by_curve_name(id));
1021
  if (!eckey)
1022
    return args.GetReturnValue().Set(false);
1023
1024
  const EC_GROUP* group = EC_KEY_get0_group(eckey.get());
1025
  ECPointPointer pub(ECDH::BufferToPoint(env, group, args[1]));
1026
1027
  if (!pub ||
1028
      !eckey ||
1029
      !EC_KEY_set_public_key(eckey.get(), pub.get())) {
1030
    return args.GetReturnValue().Set(false);
1031
  }
1032
1033
  EVPKeyPointer pkey(EVP_PKEY_new());
1034
  if (!EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()))
1035
    args.GetReturnValue().Set(false);
1036
1037
  eckey.release();  // Release ownership of the key
1038
1039
  key->data_ =
1040
      KeyObjectData::CreateAsymmetric(
1041
          kKeyTypePublic,
1042
          ManagedEVPPKey(std::move(pkey)));
1043
1044
  args.GetReturnValue().Set(true);
1045
}
1046
1047
32
void KeyObjectHandle::InitEDRaw(const FunctionCallbackInfo<Value>& args) {
1048
32
  Environment* env = Environment::GetCurrent(args);
1049
  KeyObjectHandle* key;
1050
32
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1051
1052
96
  CHECK(args[0]->IsString());
1053
64
  Utf8Value name(env->isolate(), args[0]);
1054
1055
64
  ArrayBufferOrViewContents<unsigned char> key_data(args[1]);
1056
96
  KeyType type = static_cast<KeyType>(args[2].As<Int32>()->Value());
1057
1058
64
  MarkPopErrorOnReturn mark_pop_error_on_return;
1059
1060
  typedef EVP_PKEY* (*new_key_fn)(int, ENGINE*, const unsigned char*, size_t);
1061
  new_key_fn fn = type == kKeyTypePrivate
1062
32
      ? EVP_PKEY_new_raw_private_key
1063
32
      : EVP_PKEY_new_raw_public_key;
1064
1065
32
  int id = GetOKPCurveFromName(*name);
1066
1067
32
  switch (id) {
1068
    case EVP_PKEY_X25519:
1069
    case EVP_PKEY_X448:
1070
    case EVP_PKEY_ED25519:
1071
    case EVP_PKEY_ED448: {
1072
32
      EVPKeyPointer pkey(fn(id, nullptr, key_data.data(), key_data.size()));
1073
32
      if (!pkey)
1074
        return args.GetReturnValue().Set(false);
1075
32
      key->data_ =
1076
64
          KeyObjectData::CreateAsymmetric(
1077
              type,
1078
96
              ManagedEVPPKey(std::move(pkey)));
1079
32
      CHECK(key->data_);
1080
32
      break;
1081
    }
1082
    default:
1083
      UNREACHABLE();
1084
  }
1085
1086
64
  args.GetReturnValue().Set(true);
1087
}
1088
1089
1500
void KeyObjectHandle::GetKeyDetail(const FunctionCallbackInfo<Value>& args) {
1090
1500
  Environment* env = Environment::GetCurrent(args);
1091
  KeyObjectHandle* key;
1092
1500
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1093
1094
3000
  CHECK(args[0]->IsObject());
1095
1096
3000
  std::shared_ptr<KeyObjectData> data = key->Data();
1097
1098
1500
  switch (data->GetKeyType()) {
1099
    case kKeyTypeSecret:
1100
1929
      if (GetSecretKeyDetail(env, data, args[0].As<Object>()).IsNothing())
1101
        return;
1102
643
      break;
1103
    case kKeyTypePublic:
1104
      // Fall through
1105
    case kKeyTypePrivate:
1106
2571
      if (GetAsymmetricKeyDetail(env, data, args[0].As<Object>()).IsNothing())
1107
        return;
1108
857
      break;
1109
    default:
1110
      UNREACHABLE();
1111
  }
1112
1113
3000
  args.GetReturnValue().Set(args[0]);
1114
}
1115
1116
157
Local<Value> KeyObjectHandle::GetAsymmetricKeyType() const {
1117
314
  const ManagedEVPPKey& key = data_->GetAsymmetricKey();
1118


157
  switch (EVP_PKEY_id(key.get())) {
1119
  case EVP_PKEY_RSA:
1120
70
    return env()->crypto_rsa_string();
1121
  case EVP_PKEY_RSA_PSS:
1122
20
    return env()->crypto_rsa_pss_string();
1123
  case EVP_PKEY_DSA:
1124
20
    return env()->crypto_dsa_string();
1125
  case EVP_PKEY_DH:
1126
44
    return env()->crypto_dh_string();
1127
  case EVP_PKEY_EC:
1128
76
    return env()->crypto_ec_string();
1129
  case EVP_PKEY_ED25519:
1130
18
    return env()->crypto_ed25519_string();
1131
  case EVP_PKEY_ED448:
1132
18
    return env()->crypto_ed448_string();
1133
  case EVP_PKEY_X25519:
1134
24
    return env()->crypto_x25519_string();
1135
  case EVP_PKEY_X448:
1136
24
    return env()->crypto_x448_string();
1137
  default:
1138
    return Undefined(env()->isolate());
1139
  }
1140
}
1141
1142
157
void KeyObjectHandle::GetAsymmetricKeyType(
1143
    const FunctionCallbackInfo<Value>& args) {
1144
  KeyObjectHandle* key;
1145
157
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1146
1147
471
  args.GetReturnValue().Set(key->GetAsymmetricKeyType());
1148
}
1149
1150
1
void KeyObjectHandle::GetSymmetricKeySize(
1151
    const FunctionCallbackInfo<Value>& args) {
1152
  KeyObjectHandle* key;
1153
1
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1154
3
  args.GetReturnValue().Set(
1155
1
      static_cast<uint32_t>(key->Data()->GetSymmetricKeySize()));
1156
}
1157
1158
584
void KeyObjectHandle::Export(const FunctionCallbackInfo<Value>& args) {
1159
  KeyObjectHandle* key;
1160
584
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1161
1162
584
  KeyType type = key->Data()->GetKeyType();
1163
1164
  MaybeLocal<Value> result;
1165
584
  if (type == kKeyTypeSecret) {
1166
502
    result = key->ExportSecretKey();
1167
82
  } else if (type == kKeyTypePublic) {
1168
44
    unsigned int offset = 0;
1169
    PublicKeyEncodingConfig config =
1170
        ManagedEVPPKey::GetPublicKeyEncodingFromJs(
1171
44
            args, &offset, kKeyContextExport);
1172
44
    CHECK_EQ(offset, static_cast<unsigned int>(args.Length()));
1173
44
    result = key->ExportPublicKey(config);
1174
  } else {
1175
38
    CHECK_EQ(type, kKeyTypePrivate);
1176
38
    unsigned int offset = 0;
1177
    NonCopyableMaybe<PrivateKeyEncodingConfig> config =
1178
        ManagedEVPPKey::GetPrivateKeyEncodingFromJs(
1179
76
            args, &offset, kKeyContextExport);
1180
38
    if (config.IsEmpty())
1181
      return;
1182
38
    CHECK_EQ(offset, static_cast<unsigned int>(args.Length()));
1183
38
    result = key->ExportPrivateKey(config.Release());
1184
  }
1185
1186
584
  if (!result.IsEmpty())
1187
1168
    args.GetReturnValue().Set(result.FromMaybe(Local<Value>()));
1188
}
1189
1190
502
MaybeLocal<Value> KeyObjectHandle::ExportSecretKey() const {
1191
502
  const char* buf = data_->GetSymmetricKey();
1192
502
  unsigned int len = data_->GetSymmetricKeySize();
1193
1004
  return Buffer::Copy(env(), buf, len).FromMaybe(Local<Value>());
1194
}
1195
1196
44
MaybeLocal<Value> KeyObjectHandle::ExportPublicKey(
1197
    const PublicKeyEncodingConfig& config) const {
1198
44
  return WritePublicKey(env(), data_->GetAsymmetricKey().get(), config);
1199
}
1200
1201
38
MaybeLocal<Value> KeyObjectHandle::ExportPrivateKey(
1202
    const PrivateKeyEncodingConfig& config) const {
1203
38
  return WritePrivateKey(env(), data_->GetAsymmetricKey().get(), config);
1204
}
1205
1206
353
void KeyObjectHandle::ExportJWK(
1207
    const v8::FunctionCallbackInfo<v8::Value>& args) {
1208
353
  Environment* env = Environment::GetCurrent(args);
1209
  KeyObjectHandle* key;
1210
353
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1211
1212
706
  CHECK(args[0]->IsObject());
1213
1214
353
  switch (key->Data()->GetKeyType()) {
1215
    case kKeyTypeSecret:
1216
204
      if (ExportJWKSecretKey(env, key->Data(), args[0].As<Object>())
1217
              .IsNothing()) {
1218
        return;
1219
      }
1220
68
      break;
1221
    case kKeyTypePublic:
1222
      // Fall through
1223
    case kKeyTypePrivate:
1224
855
      if (ExportJWKAsymmetricKey(env, key->Data(), args[0].As<Object>())
1225
              .IsNothing()) {
1226
        return;
1227
      }
1228
285
      break;
1229
    default:
1230
      UNREACHABLE();
1231
  }
1232
1233
706
  args.GetReturnValue().Set(args[0]);
1234
}
1235
1236
4165
void NativeKeyObject::Initialize(Environment* env, Local<Object> target) {
1237
  env->SetMethod(target, "createNativeKeyObjectClass",
1238
4165
                 NativeKeyObject::CreateNativeKeyObjectClass);
1239
4165
}
1240
1241
2125
void NativeKeyObject::New(const FunctionCallbackInfo<Value>& args) {
1242
2125
  Environment* env = Environment::GetCurrent(args);
1243
2125
  CHECK_EQ(args.Length(), 1);
1244
4250
  CHECK(args[0]->IsObject());
1245
4250
  KeyObjectHandle* handle = Unwrap<KeyObjectHandle>(args[0].As<Object>());
1246
2125
  new NativeKeyObject(env, args.This(), handle->Data());
1247
2125
}
1248
1249
4165
void NativeKeyObject::CreateNativeKeyObjectClass(
1250
    const FunctionCallbackInfo<Value>& args) {
1251
4165
  Environment* env = Environment::GetCurrent(args);
1252
1253
4165
  CHECK_EQ(args.Length(), 1);
1254
4165
  Local<Value> callback = args[0];
1255
4165
  CHECK(callback->IsFunction());
1256
1257
4165
  Local<FunctionTemplate> t = env->NewFunctionTemplate(NativeKeyObject::New);
1258
12495
  t->InstanceTemplate()->SetInternalFieldCount(
1259
4165
      KeyObjectHandle::kInternalFieldCount);
1260
8330
  t->Inherit(BaseObject::GetConstructorTemplate(env));
1261
1262
  Local<Value> ctor;
1263
12495
  if (!t->GetFunction(env->context()).ToLocal(&ctor))
1264
    return;
1265
1266
4165
  Local<Value> recv = Undefined(env->isolate());
1267
  Local<Value> ret_v;
1268
12495
  if (!callback.As<Function>()->Call(
1269
12495
          env->context(), recv, 1, &ctor).ToLocal(&ret_v)) {
1270
    return;
1271
  }
1272
4165
  Local<Array> ret = ret_v.As<Array>();
1273
12495
  if (!ret->Get(env->context(), 1).ToLocal(&ctor)) return;
1274
4165
  env->set_crypto_key_object_secret_constructor(ctor.As<Function>());
1275
12495
  if (!ret->Get(env->context(), 2).ToLocal(&ctor)) return;
1276
4165
  env->set_crypto_key_object_public_constructor(ctor.As<Function>());
1277
12495
  if (!ret->Get(env->context(), 3).ToLocal(&ctor)) return;
1278
4165
  env->set_crypto_key_object_private_constructor(ctor.As<Function>());
1279
8330
  args.GetReturnValue().Set(ret);
1280
}
1281
1282
11
BaseObjectPtr<BaseObject> NativeKeyObject::KeyObjectTransferData::Deserialize(
1283
        Environment* env,
1284
        Local<Context> context,
1285
        std::unique_ptr<worker::TransferData> self) {
1286
22
  if (context != env->context()) {
1287
3
    THROW_ERR_MESSAGE_TARGET_CONTEXT_UNAVAILABLE(env);
1288
3
    return {};
1289
  }
1290
1291
  Local<Value> handle;
1292
16
  if (!KeyObjectHandle::Create(env, data_).ToLocal(&handle))
1293
    return {};
1294
1295
  Local<Function> key_ctor;
1296
  Local<Value> arg = FIXED_ONE_BYTE_STRING(env->isolate(),
1297
8
                                           "internal/crypto/keys");
1298
32
  if (env->native_module_require()->
1299
32
      Call(context, Null(env->isolate()), 1, &arg).IsEmpty()) {
1300
    return {};
1301
  }
1302

8
  switch (data_->GetKeyType()) {
1303
    case kKeyTypeSecret:
1304
4
      key_ctor = env->crypto_key_object_secret_constructor();
1305
4
      break;
1306
    case kKeyTypePublic:
1307
2
      key_ctor = env->crypto_key_object_public_constructor();
1308
2
      break;
1309
    case kKeyTypePrivate:
1310
2
      key_ctor = env->crypto_key_object_private_constructor();
1311
2
      break;
1312
    default:
1313
      CHECK(false);
1314
  }
1315
1316
  Local<Value> key;
1317
16
  if (!key_ctor->NewInstance(context, 1, &handle).ToLocal(&key))
1318
    return {};
1319
1320
8
  return BaseObjectPtr<BaseObject>(Unwrap<KeyObjectHandle>(key.As<Object>()));
1321
}
1322
1323
11
BaseObject::TransferMode NativeKeyObject::GetTransferMode() const {
1324
11
  return BaseObject::TransferMode::kCloneable;
1325
}
1326
1327
11
std::unique_ptr<worker::TransferData> NativeKeyObject::CloneForMessaging()
1328
    const {
1329
11
  return std::make_unique<KeyObjectTransferData>(handle_data_);
1330
}
1331
1332
117
WebCryptoKeyExportStatus PKEY_SPKI_Export(
1333
    KeyObjectData* key_data,
1334
    ByteSource* out) {
1335
117
  CHECK_EQ(key_data->GetKeyType(), kKeyTypePublic);
1336
234
  ManagedEVPPKey m_pkey = key_data->GetAsymmetricKey();
1337
234
  Mutex::ScopedLock lock(*m_pkey.mutex());
1338
234
  BIOPointer bio(BIO_new(BIO_s_mem()));
1339
117
  if (!i2d_PUBKEY_bio(bio.get(), m_pkey.get()))
1340
    return WebCryptoKeyExportStatus::FAILED;
1341
1342
117
  *out = ByteSource::FromBIO(bio);
1343
117
  return WebCryptoKeyExportStatus::OK;
1344
}
1345
1346
107
WebCryptoKeyExportStatus PKEY_PKCS8_Export(
1347
    KeyObjectData* key_data,
1348
    ByteSource* out) {
1349
107
  CHECK_EQ(key_data->GetKeyType(), kKeyTypePrivate);
1350
214
  ManagedEVPPKey m_pkey = key_data->GetAsymmetricKey();
1351
214
  Mutex::ScopedLock lock(*m_pkey.mutex());
1352
1353
214
  BIOPointer bio(BIO_new(BIO_s_mem()));
1354
214
  PKCS8Pointer p8inf(EVP_PKEY2PKCS8(m_pkey.get()));
1355
107
  if (!i2d_PKCS8_PRIV_KEY_INFO_bio(bio.get(), p8inf.get()))
1356
    return WebCryptoKeyExportStatus::FAILED;
1357
1358
107
  *out = ByteSource::FromBIO(bio);
1359
107
  return WebCryptoKeyExportStatus::OK;
1360
}
1361
1362
namespace Keys {
1363
4165
void Initialize(Environment* env, Local<Object> target) {
1364
8330
  target->Set(env->context(),
1365
              FIXED_ONE_BYTE_STRING(env->isolate(), "KeyObjectHandle"),
1366
20825
              KeyObjectHandle::Initialize(env)).Check();
1367
1368
8330
  NODE_DEFINE_CONSTANT(target, kWebCryptoKeyFormatRaw);
1369
4165
  NODE_DEFINE_CONSTANT(target, kWebCryptoKeyFormatPKCS8);
1370
12495
  NODE_DEFINE_CONSTANT(target, kWebCryptoKeyFormatSPKI);
1371
20825
  NODE_DEFINE_CONSTANT(target, kWebCryptoKeyFormatJWK);
1372
29155
1373
24990
  NODE_DEFINE_CONSTANT(target, EVP_PKEY_ED25519);
1374
24990
  NODE_DEFINE_CONSTANT(target, EVP_PKEY_ED448);
1375
29155
  NODE_DEFINE_CONSTANT(target, EVP_PKEY_X25519);
1376
29155
  NODE_DEFINE_CONSTANT(target, EVP_PKEY_X448);
1377
37485
  NODE_DEFINE_CONSTANT(target, kKeyEncodingPKCS1);
1378
37485
  NODE_DEFINE_CONSTANT(target, kKeyEncodingPKCS8);
1379
41650
  NODE_DEFINE_CONSTANT(target, kKeyEncodingSPKI);
1380
41650
  NODE_DEFINE_CONSTANT(target, kKeyEncodingSEC1);
1381
41650
  NODE_DEFINE_CONSTANT(target, kKeyFormatDER);
1382
41650
  NODE_DEFINE_CONSTANT(target, kKeyFormatPEM);
1383
37485
  NODE_DEFINE_CONSTANT(target, kKeyTypeSecret);
1384
37485
  NODE_DEFINE_CONSTANT(target, kKeyTypePublic);
1385
37485
  NODE_DEFINE_CONSTANT(target, kKeyTypePrivate);
1386
37485
  NODE_DEFINE_CONSTANT(target, kSigEncDER);
1387
37485
  NODE_DEFINE_CONSTANT(target, kSigEncP1363);
1388
37485
}
1389
24990
}  // namespace Keys
1390
20825
1391
8330
}  // namespace crypto
1392

14520
}  // namespace node