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 721 85.2 %
Date: 2021-04-16 04:11:37 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
  char msg[1024];
519
  snprintf(msg, sizeof(msg), "%s is not a supported JWK key type", kty);
520
  THROW_ERR_CRYPTO_INVALID_JWK(env, msg);
521
  return std::shared_ptr<KeyObjectData>();
522
}
523
524
1507
Maybe<bool> GetSecretKeyDetail(
525
    Environment* env,
526
    std::shared_ptr<KeyObjectData> key,
527
    Local<Object> target) {
528
  // For the secret key detail, all we care about is the length,
529
  // converted to bits.
530
531
1507
  size_t length = key->GetSymmetricKeySize() * CHAR_BIT;
532
  return target->Set(env->context(),
533
                     env->length_string(),
534
6028
                     Number::New(env->isolate(), static_cast<double>(length)));
535
}
536
537
856
Maybe<bool> GetAsymmetricKeyDetail(
538
  Environment* env,
539
  std::shared_ptr<KeyObjectData> key,
540
  Local<Object> target) {
541

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

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

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

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

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

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

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

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


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

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

14310
}  // namespace node