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: 71 715 9.9 %
Date: 2021-02-19 04:08:54 Branches: 10 501 2.0 %

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
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
  if (args[*offset]->IsUndefined()) {
50
    CHECK_EQ(context, kKeyContextGenerate);
51
    CHECK(args[*offset + 1]->IsUndefined());
52
    config->output_key_object_ = true;
53
  } else {
54
    config->output_key_object_ = false;
55
56
    CHECK(args[*offset]->IsInt32());
57
    config->format_ = static_cast<PKFormatType>(
58
        args[*offset].As<Int32>()->Value());
59
60
    if (args[*offset + 1]->IsInt32()) {
61
      config->type_ = Just<PKEncodingType>(static_cast<PKEncodingType>(
62
          args[*offset + 1].As<Int32>()->Value()));
63
    } else {
64
      CHECK(context == kKeyContextInput && config->format_ == kKeyFormatPEM);
65
      CHECK(args[*offset + 1]->IsNullOrUndefined());
66
      config->type_ = Nothing<PKEncodingType>();
67
    }
68
  }
69
70
  *offset += 2;
71
}
72
73
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
    MarkPopErrorOnReturn mark_pop_error_on_return;
85
    if (PEM_bytes_read_bio(&der_data, &der_len, nullptr, name,
86
                           bp.get(), nullptr, nullptr) != 1)
87
      return ParseKeyResult::kParseKeyNotRecognized;
88
  }
89
90
  // OpenSSL might modify the pointer, so we need to make a copy before parsing.
91
  const unsigned char* p = der_data;
92
  pkey->reset(parse(&p, der_len));
93
  OPENSSL_clear_free(der_data, der_len);
94
95
  return *pkey ? ParseKeyResult::kParseKeyOk :
96
                 ParseKeyResult::kParseKeyFailed;
97
}
98
99
ParseKeyResult ParsePublicKeyPEM(EVPKeyPointer* pkey,
100
                                 const char* key_pem,
101
                                 int key_pem_len) {
102
  BIOPointer bp(BIO_new_mem_buf(const_cast<char*>(key_pem), key_pem_len));
103
  if (!bp)
104
    return ParseKeyResult::kParseKeyFailed;
105
106
  ParseKeyResult ret;
107
108
  // Try parsing as a SubjectPublicKeyInfo first.
109
  ret = TryParsePublicKey(pkey, bp, "PUBLIC KEY",
110
      [](const unsigned char** p, long l) {  // NOLINT(runtime/int)
111
        return d2i_PUBKEY(nullptr, p, l);
112
      });
113
  if (ret != ParseKeyResult::kParseKeyNotRecognized)
114
    return ret;
115
116
  // Maybe it is PKCS#1.
117
  CHECK(BIO_reset(bp.get()));
118
  ret = TryParsePublicKey(pkey, bp, "RSA PUBLIC KEY",
119
      [](const unsigned char** p, long l) {  // NOLINT(runtime/int)
120
        return d2i_PublicKey(EVP_PKEY_RSA, nullptr, p, l);
121
      });
122
  if (ret != ParseKeyResult::kParseKeyNotRecognized)
123
    return ret;
124
125
  // X.509 fallback.
126
  CHECK(BIO_reset(bp.get()));
127
  return TryParsePublicKey(pkey, bp, "CERTIFICATE",
128
      [](const unsigned char** p, long l) {  // NOLINT(runtime/int)
129
        X509Pointer x509(d2i_X509(nullptr, p, l));
130
        return x509 ? X509_get_pubkey(x509.get()) : nullptr;
131
      });
132
}
133
134
ParseKeyResult ParsePublicKey(EVPKeyPointer* pkey,
135
                              const PublicKeyEncodingConfig& config,
136
                              const char* key,
137
                              size_t key_len) {
138
  if (config.format_ == kKeyFormatPEM) {
139
    return ParsePublicKeyPEM(pkey, key, key_len);
140
  } else {
141
    CHECK_EQ(config.format_, kKeyFormatDER);
142
143
    const unsigned char* p = reinterpret_cast<const unsigned char*>(key);
144
    if (config.type_.ToChecked() == kKeyEncodingPKCS1) {
145
      pkey->reset(d2i_PublicKey(EVP_PKEY_RSA, nullptr, &p, key_len));
146
    } else {
147
      CHECK_EQ(config.type_.ToChecked(), kKeyEncodingSPKI);
148
      pkey->reset(d2i_PUBKEY(nullptr, &p, key_len));
149
    }
150
151
    return *pkey ? ParseKeyResult::kParseKeyOk :
152
                   ParseKeyResult::kParseKeyFailed;
153
  }
154
}
155
156
bool IsASN1Sequence(const unsigned char* data, size_t size,
157
                    size_t* data_offset, size_t* data_size) {
158
  if (size < 2 || data[0] != 0x30)
159
    return false;
160
161
  if (data[1] & 0x80) {
162
    // Long form.
163
    size_t n_bytes = data[1] & ~0x80;
164
    if (n_bytes + 2 > size || n_bytes > sizeof(size_t))
165
      return false;
166
    size_t length = 0;
167
    for (size_t i = 0; i < n_bytes; i++)
168
      length = (length << 8) | data[i + 2];
169
    *data_offset = 2 + n_bytes;
170
    *data_size = std::min(size - 2 - n_bytes, length);
171
  } else {
172
    // Short form.
173
    *data_offset = 2;
174
    *data_size = std::min<size_t>(size - 2, data[1]);
175
  }
176
177
  return true;
178
}
179
180
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
  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
  return len >= 3 &&
192
         data[offset] == 2 &&
193
         data[offset + 1] == 1 &&
194
         !(data[offset + 2] & 0xfe);
195
}
196
197
bool IsEncryptedPrivateKeyInfo(const unsigned char* data, size_t size) {
198
  // Both PrivateKeyInfo and EncryptedPrivateKeyInfo start with a SEQUENCE.
199
  size_t offset, len;
200
  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
  return len >= 1 &&
206
         data[offset] != 2;
207
}
208
209
ParseKeyResult ParsePrivateKey(EVPKeyPointer* pkey,
210
                               const PrivateKeyEncodingConfig& config,
211
                               const char* key,
212
                               size_t key_len) {
213
  const ByteSource* passphrase = config.passphrase_.get();
214
215
  if (config.format_ == kKeyFormatPEM) {
216
    BIOPointer bio(BIO_new_mem_buf(key, key_len));
217
    if (!bio)
218
      return ParseKeyResult::kParseKeyFailed;
219
220
    pkey->reset(PEM_read_bio_PrivateKey(bio.get(),
221
                                        nullptr,
222
                                        PasswordCallback,
223
                                        &passphrase));
224
  } else {
225
    CHECK_EQ(config.format_, kKeyFormatDER);
226
227
    if (config.type_.ToChecked() == kKeyEncodingPKCS1) {
228
      const unsigned char* p = reinterpret_cast<const unsigned char*>(key);
229
      pkey->reset(d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &p, key_len));
230
    } else if (config.type_.ToChecked() == kKeyEncodingPKCS8) {
231
      BIOPointer bio(BIO_new_mem_buf(key, key_len));
232
      if (!bio)
233
        return ParseKeyResult::kParseKeyFailed;
234
235
      if (IsEncryptedPrivateKeyInfo(
236
              reinterpret_cast<const unsigned char*>(key), key_len)) {
237
        pkey->reset(d2i_PKCS8PrivateKey_bio(bio.get(),
238
                                            nullptr,
239
                                            PasswordCallback,
240
                                            &passphrase));
241
      } else {
242
        PKCS8Pointer p8inf(d2i_PKCS8_PRIV_KEY_INFO_bio(bio.get(), nullptr));
243
        if (p8inf)
244
          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
  unsigned long err = ERR_peek_error();  // NOLINT(runtime/int)
255
  if (err != 0)
256
    pkey->reset();
257
258
  if (*pkey)
259
    return ParseKeyResult::kParseKeyOk;
260
  if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
261
      ERR_GET_REASON(err) == PEM_R_BAD_PASSWORD_READ) {
262
    if (config.passphrase_.IsEmpty())
263
      return ParseKeyResult::kParseKeyNeedPassphrase;
264
  }
265
  return ParseKeyResult::kParseKeyFailed;
266
}
267
268
MaybeLocal<Value> BIOToStringOrBuffer(
269
    Environment* env,
270
    BIO* bio,
271
    PKFormatType format) {
272
  BUF_MEM* bptr;
273
  BIO_get_mem_ptr(bio, &bptr);
274
  if (format == kKeyFormatPEM) {
275
    // PEM is an ASCII format, so we will return it as a string.
276
    return String::NewFromUtf8(env->isolate(), bptr->data,
277
                               NewStringType::kNormal,
278
                               bptr->length).FromMaybe(Local<Value>());
279
  } else {
280
    CHECK_EQ(format, kKeyFormatDER);
281
    // DER is binary, return it as a buffer.
282
    return Buffer::Copy(env, bptr->data, bptr->length)
283
        .FromMaybe(Local<Value>());
284
  }
285
}
286
287
288
MaybeLocal<Value> WritePrivateKey(
289
    Environment* env,
290
    EVP_PKEY* pkey,
291
    const PrivateKeyEncodingConfig& config) {
292
  BIOPointer bio(BIO_new(BIO_s_mem()));
293
  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
  char* pass = nullptr;
302
  size_t pass_len = 0;
303
  if (!config.passphrase_.IsEmpty()) {
304
    pass = const_cast<char*>(config.passphrase_->get());
305
    pass_len = config.passphrase_->size();
306
    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
      CHECK_EQ(pass_len, 0);
312
      pass = reinterpret_cast<char*>(-1);
313
      CHECK_NE(pass, nullptr);
314
    }
315
  }
316
317
  bool err;
318
319
  PKEncodingType encoding_type = config.type_.ToChecked();
320
  if (encoding_type == kKeyEncodingPKCS1) {
321
    // PKCS#1 is only permitted for RSA keys.
322
    CHECK_EQ(EVP_PKEY_id(pkey), EVP_PKEY_RSA);
323
324
    RSAPointer rsa(EVP_PKEY_get1_RSA(pkey));
325
    if (config.format_ == kKeyFormatPEM) {
326
      // Encode PKCS#1 as PEM.
327
      err = PEM_write_bio_RSAPrivateKey(
328
                bio.get(), rsa.get(),
329
                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
      CHECK_EQ(config.format_, kKeyFormatDER);
336
      CHECK_NULL(config.cipher_);
337
      err = i2d_RSAPrivateKey_bio(bio.get(), rsa.get()) != 1;
338
    }
339
  } else if (encoding_type == kKeyEncodingPKCS8) {
340
    if (config.format_ == kKeyFormatPEM) {
341
      // Encode PKCS#8 as PEM.
342
      err = PEM_write_bio_PKCS8PrivateKey(
343
                bio.get(), pkey,
344
                config.cipher_,
345
                pass,
346
                pass_len,
347
                nullptr, nullptr) != 1;
348
    } else {
349
      // Encode PKCS#8 as DER.
350
      CHECK_EQ(config.format_, kKeyFormatDER);
351
      err = i2d_PKCS8PrivateKey_bio(
352
                bio.get(), pkey,
353
                config.cipher_,
354
                pass,
355
                pass_len,
356
                nullptr, nullptr) != 1;
357
    }
358
  } else {
359
    CHECK_EQ(encoding_type, kKeyEncodingSEC1);
360
361
    // SEC1 is only permitted for EC keys.
362
    CHECK_EQ(EVP_PKEY_id(pkey), EVP_PKEY_EC);
363
364
    ECKeyPointer ec_key(EVP_PKEY_get1_EC_KEY(pkey));
365
    if (config.format_ == kKeyFormatPEM) {
366
      // Encode SEC1 as PEM.
367
      err = PEM_write_bio_ECPrivateKey(
368
                bio.get(), ec_key.get(),
369
                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
  if (err) {
382
    ThrowCryptoError(env, ERR_get_error(), "Failed to encode private key");
383
    return MaybeLocal<Value>();
384
  }
385
  return BIOToStringOrBuffer(env, bio.get(), config.format_);
386
}
387
388
bool WritePublicKeyInner(EVP_PKEY* pkey,
389
                         const BIOPointer& bio,
390
                         const PublicKeyEncodingConfig& config) {
391
  if (config.type_.ToChecked() == kKeyEncodingPKCS1) {
392
    // PKCS#1 is only valid for RSA keys.
393
    CHECK_EQ(EVP_PKEY_id(pkey), EVP_PKEY_RSA);
394
    RSAPointer rsa(EVP_PKEY_get1_RSA(pkey));
395
    if (config.format_ == kKeyFormatPEM) {
396
      // Encode PKCS#1 as PEM.
397
      return PEM_write_bio_RSAPublicKey(bio.get(), rsa.get()) == 1;
398
    } else {
399
      // Encode PKCS#1 as DER.
400
      CHECK_EQ(config.format_, kKeyFormatDER);
401
      return i2d_RSAPublicKey_bio(bio.get(), rsa.get()) == 1;
402
    }
403
  } else {
404
    CHECK_EQ(config.type_.ToChecked(), kKeyEncodingSPKI);
405
    if (config.format_ == kKeyFormatPEM) {
406
      // Encode SPKI as PEM.
407
      return PEM_write_bio_PUBKEY(bio.get(), pkey) == 1;
408
    } else {
409
      // Encode SPKI as DER.
410
      CHECK_EQ(config.format_, kKeyFormatDER);
411
      return i2d_PUBKEY_bio(bio.get(), pkey) == 1;
412
    }
413
  }
414
}
415
416
MaybeLocal<Value> WritePublicKey(Environment* env,
417
                                 EVP_PKEY* pkey,
418
                                 const PublicKeyEncodingConfig& config) {
419
  BIOPointer bio(BIO_new(BIO_s_mem()));
420
  CHECK(bio);
421
422
  if (!WritePublicKeyInner(pkey, bio, config)) {
423
    ThrowCryptoError(env, ERR_get_error(), "Failed to encode public key");
424
    return MaybeLocal<Value>();
425
  }
426
  return BIOToStringOrBuffer(env, bio.get(), config.format_);
427
}
428
429
Maybe<bool> ExportJWKSecretKey(
430
    Environment* env,
431
    std::shared_ptr<KeyObjectData> key,
432
    Local<Object> target) {
433
  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
          &error);
444
  if (key_data.IsEmpty()) {
445
    CHECK(!error.IsEmpty());
446
    env->isolate()->ThrowException(error);
447
    return Nothing<bool>();
448
  }
449
  if (!key_data.ToLocal(&raw))
450
    return Nothing<bool>();
451
452
  if (target->Set(
453
          env->context(),
454
          env->jwk_kty_string(),
455
          env->jwk_oct_string()).IsNothing() ||
456
      target->Set(
457
          env->context(),
458
          env->jwk_k_string(),
459
          raw).IsNothing()) {
460
    return Nothing<bool>();
461
  }
462
463
  return Just(true);
464
}
465
466
std::shared_ptr<KeyObjectData> ImportJWKSecretKey(
467
    Environment* env,
468
    Local<Object> jwk) {
469
  Local<Value> key;
470
  if (!jwk->Get(env->context(), env->jwk_k_string()).ToLocal(&key) ||
471
      !key->IsString()) {
472
    THROW_ERR_CRYPTO_INVALID_JWK(env, "Invalid JWK secret key format");
473
    return std::shared_ptr<KeyObjectData>();
474
  }
475
476
  ByteSource key_data = ByteSource::FromEncodedString(env, key.As<String>());
477
  if (key_data.size() > INT_MAX) {
478
    THROW_ERR_CRYPTO_INVALID_KEYLEN(env);
479
    return std::shared_ptr<KeyObjectData>();
480
  }
481
482
  return KeyObjectData::CreateSecret(std::move(key_data));
483
}
484
485
Maybe<bool> ExportJWKAsymmetricKey(
486
    Environment* env,
487
    std::shared_ptr<KeyObjectData> key,
488
    Local<Object> target) {
489
  switch (EVP_PKEY_id(key->GetAsymmetricKey().get())) {
490
    case EVP_PKEY_RSA:
491
      // Fall through
492
    case EVP_PKEY_RSA_PSS: return ExportJWKRsaKey(env, key, target);
493
    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
    case EVP_PKEY_X448: return ExportJWKEdKey(env, key, target);
501
  }
502
  THROW_ERR_CRYPTO_INVALID_KEYTYPE(env);
503
  return Just(false);
504
}
505
506
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
  if (strcmp(kty, "RSA") == 0) {
513
    return ImportJWKRsaKey(env, jwk, args, offset);
514
  } else if (strcmp(kty, "EC") == 0) {
515
    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
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
  size_t length = key->GetSymmetricKeySize() * CHAR_BIT;
532
  return target->Set(
533
      env->context(),
534
      env->length_string(),
535
      Number::New(env->isolate(), length));
536
}
537
538
Maybe<bool> GetAsymmetricKeyDetail(
539
  Environment* env,
540
  std::shared_ptr<KeyObjectData> key,
541
  Local<Object> target) {
542
  switch (EVP_PKEY_id(key->GetAsymmetricKey().get())) {
543
    case EVP_PKEY_RSA:
544
      // Fall through
545
    case EVP_PKEY_RSA_PSS: return GetRsaKeyDetail(env, key, target);
546
    case EVP_PKEY_DSA: return GetDsaKeyDetail(env, key, target);
547
    case EVP_PKEY_EC: return GetEcKeyDetail(env, key, target);
548
    case EVP_PKEY_DH: return GetDhKeyDetail(env, key, target);
549
  }
550
  THROW_ERR_CRYPTO_INVALID_KEYTYPE(env);
551
  return Nothing<bool>();
552
}
553
}  // namespace
554
555
ManagedEVPPKey::ManagedEVPPKey(EVPKeyPointer&& pkey) : pkey_(std::move(pkey)),
556
    mutex_(std::make_shared<Mutex>()) {}
557
558
ManagedEVPPKey::ManagedEVPPKey(const ManagedEVPPKey& that) {
559
  *this = that;
560
}
561
562
ManagedEVPPKey& ManagedEVPPKey::operator=(const ManagedEVPPKey& that) {
563
  pkey_.reset(that.get());
564
565
  if (pkey_)
566
    EVP_PKEY_up_ref(pkey_.get());
567
568
  mutex_ = that.mutex_;
569
570
  return *this;
571
}
572
573
ManagedEVPPKey::operator bool() const {
574
  return !!pkey_;
575
}
576
577
EVP_PKEY* ManagedEVPPKey::get() const {
578
  return pkey_.get();
579
}
580
581
Mutex* ManagedEVPPKey::mutex() const {
582
  return mutex_.get();
583
}
584
585
void ManagedEVPPKey::MemoryInfo(MemoryTracker* tracker) const {
586
  tracker->TrackFieldWithSize("pkey",
587
                              !pkey_ ? 0 : kSizeOf_EVP_PKEY +
588
                              size_of_private_key() +
589
                              size_of_public_key());
590
}
591
592
size_t ManagedEVPPKey::size_of_private_key() const {
593
  size_t len = 0;
594
  return (pkey_ && EVP_PKEY_get_raw_private_key(
595
      pkey_.get(), nullptr, &len) == 1) ? len : 0;
596
}
597
598
size_t ManagedEVPPKey::size_of_public_key() const {
599
  size_t len = 0;
600
  return (pkey_ && EVP_PKEY_get_raw_public_key(
601
      pkey_.get(), nullptr, &len) == 1) ? len : 0;
602
}
603
604
Maybe<bool> ManagedEVPPKey::ToEncodedPublicKey(
605
    Environment* env,
606
    ManagedEVPPKey key,
607
    const PublicKeyEncodingConfig& config,
608
    Local<Value>* out) {
609
  if (!key) return Nothing<bool>();
610
  if (config.output_key_object_) {
611
    // Note that this has the downside of containing sensitive data of the
612
    // private key.
613
    std::shared_ptr<KeyObjectData> data =
614
          KeyObjectData::CreateAsymmetric(kKeyTypePublic, std::move(key));
615
    return Just(KeyObjectHandle::Create(env, data).ToLocal(out));
616
  }
617
  return Just(WritePublicKey(env, key.get(), config).ToLocal(out));
618
}
619
620
Maybe<bool> ManagedEVPPKey::ToEncodedPrivateKey(
621
    Environment* env,
622
    ManagedEVPPKey key,
623
    const PrivateKeyEncodingConfig& config,
624
    Local<Value>* out) {
625
  if (!key) return Nothing<bool>();
626
  if (config.output_key_object_) {
627
    std::shared_ptr<KeyObjectData> data =
628
        KeyObjectData::CreateAsymmetric(kKeyTypePrivate, std::move(key));
629
    return Just(KeyObjectHandle::Create(env, data).ToLocal(out));
630
  }
631
632
  return Just(WritePrivateKey(env, key.get(), config).ToLocal(out));
633
}
634
635
NonCopyableMaybe<PrivateKeyEncodingConfig>
636
ManagedEVPPKey::GetPrivateKeyEncodingFromJs(
637
    const FunctionCallbackInfo<Value>& args,
638
    unsigned int* offset,
639
    KeyEncodingContext context) {
640
  Environment* env = Environment::GetCurrent(args);
641
642
  PrivateKeyEncodingConfig result;
643
  GetKeyFormatAndTypeFromJs(&result, args, offset, context);
644
645
  if (result.output_key_object_) {
646
    if (context != kKeyContextInput)
647
      (*offset)++;
648
  } else {
649
    bool needs_passphrase = false;
650
    if (context != kKeyContextInput) {
651
      if (args[*offset]->IsString()) {
652
        Utf8Value cipher_name(env->isolate(), args[*offset]);
653
        result.cipher_ = EVP_get_cipherbyname(*cipher_name);
654
        if (result.cipher_ == nullptr) {
655
          THROW_ERR_CRYPTO_UNKNOWN_CIPHER(env);
656
          return NonCopyableMaybe<PrivateKeyEncodingConfig>();
657
        }
658
        needs_passphrase = true;
659
      } else {
660
        CHECK(args[*offset]->IsNullOrUndefined());
661
        result.cipher_ = nullptr;
662
      }
663
      (*offset)++;
664
    }
665
666
    if (IsAnyByteSource(args[*offset])) {
667
      CHECK_IMPLIES(context != kKeyContextInput, result.cipher_ != nullptr);
668
      ArrayBufferOrViewContents<char> passphrase(args[*offset]);
669
      if (UNLIKELY(!passphrase.CheckSizeInt32())) {
670
        THROW_ERR_OUT_OF_RANGE(env, "passphrase is too big");
671
        return NonCopyableMaybe<PrivateKeyEncodingConfig>();
672
      }
673
      result.passphrase_ = NonCopyableMaybe<ByteSource>(
674
          passphrase.ToNullTerminatedCopy());
675
    } else {
676
      CHECK(args[*offset]->IsNullOrUndefined() && !needs_passphrase);
677
    }
678
  }
679
680
  (*offset)++;
681
  return NonCopyableMaybe<PrivateKeyEncodingConfig>(std::move(result));
682
}
683
684
PublicKeyEncodingConfig ManagedEVPPKey::GetPublicKeyEncodingFromJs(
685
    const FunctionCallbackInfo<Value>& args,
686
    unsigned int* offset,
687
    KeyEncodingContext context) {
688
  PublicKeyEncodingConfig result;
689
  GetKeyFormatAndTypeFromJs(&result, args, offset, context);
690
  return result;
691
}
692
693
ManagedEVPPKey ManagedEVPPKey::GetPrivateKeyFromJs(
694
    const FunctionCallbackInfo<Value>& args,
695
    unsigned int* offset,
696
    bool allow_key_object) {
697
  if (args[*offset]->IsString() || IsAnyByteSource(args[*offset])) {
698
    Environment* env = Environment::GetCurrent(args);
699
    ByteSource key = ByteSource::FromStringOrBuffer(env, args[(*offset)++]);
700
    NonCopyableMaybe<PrivateKeyEncodingConfig> config =
701
        GetPrivateKeyEncodingFromJs(args, offset, kKeyContextInput);
702
    if (config.IsEmpty())
703
      return ManagedEVPPKey();
704
705
    EVPKeyPointer pkey;
706
    ParseKeyResult ret =
707
        ParsePrivateKey(&pkey, config.Release(), key.get(), key.size());
708
    return GetParsedKey(env, std::move(pkey), ret,
709
                        "Failed to read private key");
710
  } else {
711
    CHECK(args[*offset]->IsObject() && allow_key_object);
712
    KeyObjectHandle* key;
713
    ASSIGN_OR_RETURN_UNWRAP(&key, args[*offset].As<Object>(), ManagedEVPPKey());
714
    CHECK_EQ(key->Data()->GetKeyType(), kKeyTypePrivate);
715
    (*offset) += 4;
716
    return key->Data()->GetAsymmetricKey();
717
  }
718
}
719
720
ManagedEVPPKey ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(
721
    const FunctionCallbackInfo<Value>& args,
722
    unsigned int* offset) {
723
  if (IsAnyByteSource(args[*offset])) {
724
    Environment* env = Environment::GetCurrent(args);
725
    ArrayBufferOrViewContents<char> data(args[(*offset)++]);
726
    if (UNLIKELY(!data.CheckSizeInt32())) {
727
      THROW_ERR_OUT_OF_RANGE(env, "keyData is too big");
728
      return ManagedEVPPKey();
729
    }
730
    NonCopyableMaybe<PrivateKeyEncodingConfig> config_ =
731
        GetPrivateKeyEncodingFromJs(args, offset, kKeyContextInput);
732
    if (config_.IsEmpty())
733
      return ManagedEVPPKey();
734
735
    ParseKeyResult ret;
736
    PrivateKeyEncodingConfig config = config_.Release();
737
    EVPKeyPointer pkey;
738
    if (config.format_ == kKeyFormatPEM) {
739
      // For PEM, we can easily determine whether it is a public or private key
740
      // by looking for the respective PEM tags.
741
      ret = ParsePublicKeyPEM(&pkey, data.data(), data.size());
742
      if (ret == ParseKeyResult::kParseKeyNotRecognized) {
743
        ret = ParsePrivateKey(&pkey, config, data.data(), data.size());
744
      }
745
    } else {
746
      // For DER, the type determines how to parse it. SPKI, PKCS#8 and SEC1 are
747
      // easy, but PKCS#1 can be a public key or a private key.
748
      bool is_public;
749
      switch (config.type_.ToChecked()) {
750
        case kKeyEncodingPKCS1:
751
          is_public = !IsRSAPrivateKey(
752
              reinterpret_cast<const unsigned char*>(data.data()), data.size());
753
          break;
754
        case kKeyEncodingSPKI:
755
          is_public = true;
756
          break;
757
        case kKeyEncodingPKCS8:
758
        case kKeyEncodingSEC1:
759
          is_public = false;
760
          break;
761
        default:
762
          UNREACHABLE("Invalid key encoding type");
763
      }
764
765
      if (is_public) {
766
        ret = ParsePublicKey(&pkey, config, data.data(), data.size());
767
      } else {
768
        ret = ParsePrivateKey(&pkey, config, data.data(), data.size());
769
      }
770
    }
771
772
    return ManagedEVPPKey::GetParsedKey(
773
        env, std::move(pkey), ret, "Failed to read asymmetric key");
774
  } else {
775
    CHECK(args[*offset]->IsObject());
776
    KeyObjectHandle* key = Unwrap<KeyObjectHandle>(args[*offset].As<Object>());
777
    CHECK_NOT_NULL(key);
778
    CHECK_NE(key->Data()->GetKeyType(), kKeyTypeSecret);
779
    (*offset) += 4;
780
    return key->Data()->GetAsymmetricKey();
781
  }
782
}
783
784
ManagedEVPPKey ManagedEVPPKey::GetParsedKey(Environment* env,
785
                                            EVPKeyPointer&& pkey,
786
                                            ParseKeyResult ret,
787
                                            const char* default_msg) {
788
  switch (ret) {
789
    case ParseKeyResult::kParseKeyOk:
790
      CHECK(pkey);
791
      break;
792
    case ParseKeyResult::kParseKeyNeedPassphrase:
793
      THROW_ERR_MISSING_PASSPHRASE(env,
794
                                   "Passphrase required for encrypted key");
795
      break;
796
    default:
797
      ThrowCryptoError(env, ERR_get_error(), default_msg);
798
  }
799
800
  return ManagedEVPPKey(std::move(pkey));
801
}
802
803
KeyObjectData::KeyObjectData(
804
    ByteSource symmetric_key)
805
    : key_type_(KeyType::kKeyTypeSecret),
806
      symmetric_key_(std::move(symmetric_key)),
807
      symmetric_key_len_(symmetric_key_.size()),
808
      asymmetric_key_() {}
809
810
KeyObjectData::KeyObjectData(
811
    KeyType type,
812
    const ManagedEVPPKey& pkey)
813
    : key_type_(type),
814
      symmetric_key_(),
815
      symmetric_key_len_(0),
816
      asymmetric_key_{pkey} {}
817
818
void KeyObjectData::MemoryInfo(MemoryTracker* tracker) const {
819
  switch (GetKeyType()) {
820
    case kKeyTypeSecret:
821
      tracker->TrackFieldWithSize("symmetric_key", symmetric_key_.size());
822
      break;
823
    case kKeyTypePrivate:
824
      // Fall through
825
    case kKeyTypePublic:
826
      tracker->TrackFieldWithSize("key", asymmetric_key_);
827
      break;
828
    default:
829
      UNREACHABLE();
830
  }
831
}
832
833
std::shared_ptr<KeyObjectData> KeyObjectData::CreateSecret(
834
    const ArrayBufferOrViewContents<char>& buf) {
835
  return CreateSecret(buf.ToCopy());
836
}
837
838
std::shared_ptr<KeyObjectData> KeyObjectData::CreateSecret(ByteSource key) {
839
  CHECK(key);
840
  return std::shared_ptr<KeyObjectData>(new KeyObjectData(std::move(key)));
841
}
842
843
std::shared_ptr<KeyObjectData> KeyObjectData::CreateAsymmetric(
844
    KeyType key_type,
845
    const ManagedEVPPKey& pkey) {
846
  CHECK(pkey);
847
  return std::shared_ptr<KeyObjectData>(new KeyObjectData(key_type, pkey));
848
}
849
850
KeyType KeyObjectData::GetKeyType() const {
851
  return key_type_;
852
}
853
854
ManagedEVPPKey KeyObjectData::GetAsymmetricKey() const {
855
  CHECK_NE(key_type_, kKeyTypeSecret);
856
  return asymmetric_key_;
857
}
858
859
const char* KeyObjectData::GetSymmetricKey() const {
860
  CHECK_EQ(key_type_, kKeyTypeSecret);
861
  return symmetric_key_.get();
862
}
863
864
size_t KeyObjectData::GetSymmetricKeySize() const {
865
  CHECK_EQ(key_type_, kKeyTypeSecret);
866
  return symmetric_key_len_;
867
}
868
869
2
v8::Local<v8::Function> KeyObjectHandle::Initialize(Environment* env) {
870
2
  Local<Function> templ = env->crypto_key_object_handle_constructor();
871
2
  if (!templ.IsEmpty()) {
872
    return templ;
873
  }
874
2
  Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
875
6
  t->InstanceTemplate()->SetInternalFieldCount(
876
2
      KeyObjectHandle::kInternalFieldCount);
877
4
  t->Inherit(BaseObject::GetConstructorTemplate(env));
878
879
2
  env->SetProtoMethod(t, "init", Init);
880
  env->SetProtoMethodNoSideEffect(t, "getSymmetricKeySize",
881
2
                                  GetSymmetricKeySize);
882
  env->SetProtoMethodNoSideEffect(t, "getAsymmetricKeyType",
883
2
                                  GetAsymmetricKeyType);
884
2
  env->SetProtoMethod(t, "export", Export);
885
2
  env->SetProtoMethod(t, "exportJwk", ExportJWK);
886
2
  env->SetProtoMethod(t, "initECRaw", InitECRaw);
887
2
  env->SetProtoMethod(t, "initEDRaw", InitEDRaw);
888
2
  env->SetProtoMethod(t, "initJwk", InitJWK);
889
2
  env->SetProtoMethod(t, "keyDetail", GetKeyDetail);
890
891
6
  auto function = t->GetFunction(env->context()).ToLocalChecked();
892
2
  env->set_crypto_key_object_handle_constructor(function);
893
2
  return function;
894
}
895
896
MaybeLocal<Object> KeyObjectHandle::Create(
897
    Environment* env,
898
    std::shared_ptr<KeyObjectData> data) {
899
  Local<Object> obj;
900
  Local<Function> ctor = KeyObjectHandle::Initialize(env);
901
  CHECK(!env->crypto_key_object_handle_constructor().IsEmpty());
902
  if (!ctor->NewInstance(env->context(), 0, nullptr).ToLocal(&obj))
903
    return MaybeLocal<Object>();
904
905
  KeyObjectHandle* key = Unwrap<KeyObjectHandle>(obj);
906
  CHECK_NOT_NULL(key);
907
  key->data_ = data;
908
  return obj;
909
}
910
911
const std::shared_ptr<KeyObjectData>& KeyObjectHandle::Data() {
912
  return data_;
913
}
914
915
void KeyObjectHandle::New(const FunctionCallbackInfo<Value>& args) {
916
  CHECK(args.IsConstructCall());
917
  Environment* env = Environment::GetCurrent(args);
918
  new KeyObjectHandle(env, args.This());
919
}
920
921
KeyObjectHandle::KeyObjectHandle(Environment* env,
922
                                 Local<Object> wrap)
923
    : BaseObject(env, wrap) {
924
  MakeWeak();
925
}
926
927
void KeyObjectHandle::Init(const FunctionCallbackInfo<Value>& args) {
928
  KeyObjectHandle* key;
929
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
930
  MarkPopErrorOnReturn mark_pop_error_on_return;
931
932
  CHECK(args[0]->IsInt32());
933
  KeyType type = static_cast<KeyType>(args[0].As<Uint32>()->Value());
934
935
  unsigned int offset;
936
  ManagedEVPPKey pkey;
937
938
  switch (type) {
939
  case kKeyTypeSecret: {
940
    CHECK_EQ(args.Length(), 2);
941
    ArrayBufferOrViewContents<char> buf(args[1]);
942
    key->data_ = KeyObjectData::CreateSecret(buf.ToCopy());
943
    break;
944
  }
945
  case kKeyTypePublic: {
946
    CHECK_EQ(args.Length(), 5);
947
948
    offset = 1;
949
    pkey = ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(args, &offset);
950
    if (!pkey)
951
      return;
952
    key->data_ = KeyObjectData::CreateAsymmetric(type, pkey);
953
    break;
954
  }
955
  case kKeyTypePrivate: {
956
    CHECK_EQ(args.Length(), 5);
957
958
    offset = 1;
959
    pkey = ManagedEVPPKey::GetPrivateKeyFromJs(args, &offset, false);
960
    if (!pkey)
961
      return;
962
    key->data_ = KeyObjectData::CreateAsymmetric(type, pkey);
963
    break;
964
  }
965
  default:
966
    UNREACHABLE();
967
  }
968
}
969
970
void KeyObjectHandle::InitJWK(const FunctionCallbackInfo<Value>& args) {
971
  Environment* env = Environment::GetCurrent(args);
972
  KeyObjectHandle* key;
973
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
974
  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
  CHECK(args[0]->IsObject());
979
980
  // Step one, Secret key or not?
981
  Local<Object> input = args[0].As<Object>();
982
983
  Local<Value> kty;
984
  if (!input->Get(env->context(), env->jwk_kty_string()).ToLocal(&kty) ||
985
      !kty->IsString()) {
986
    return THROW_ERR_CRYPTO_INVALID_JWK(env);
987
  }
988
989
  Utf8Value kty_string(env->isolate(), kty);
990
991
  if (strcmp(*kty_string, "oct") == 0) {
992
    // Secret key
993
    key->data_ = ImportJWKSecretKey(env, input);
994
    if (!key->data_) {
995
      // ImportJWKSecretKey is responsible for throwing an appropriate error
996
      return;
997
    }
998
  } else {
999
    key->data_ = ImportJWKAsymmetricKey(env, input, *kty_string, args, 1);
1000
    if (!key->data_) {
1001
      // ImportJWKAsymmetricKey is responsible for throwing an appropriate error
1002
      return;
1003
    }
1004
  }
1005
1006
  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
void KeyObjectHandle::InitEDRaw(const FunctionCallbackInfo<Value>& args) {
1048
  Environment* env = Environment::GetCurrent(args);
1049
  KeyObjectHandle* key;
1050
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1051
1052
  CHECK(args[0]->IsString());
1053
  Utf8Value name(env->isolate(), args[0]);
1054
1055
  ArrayBufferOrViewContents<unsigned char> key_data(args[1]);
1056
  KeyType type = static_cast<KeyType>(args[2].As<Int32>()->Value());
1057
1058
  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
      ? EVP_PKEY_new_raw_private_key
1063
      : EVP_PKEY_new_raw_public_key;
1064
1065
  int id = GetOKPCurveFromName(*name);
1066
1067
  switch (id) {
1068
    case EVP_PKEY_X25519:
1069
    case EVP_PKEY_X448:
1070
    case EVP_PKEY_ED25519:
1071
    case EVP_PKEY_ED448: {
1072
      EVPKeyPointer pkey(fn(id, nullptr, key_data.data(), key_data.size()));
1073
      if (!pkey)
1074
        return args.GetReturnValue().Set(false);
1075
      key->data_ =
1076
          KeyObjectData::CreateAsymmetric(
1077
              type,
1078
              ManagedEVPPKey(std::move(pkey)));
1079
      CHECK(key->data_);
1080
      break;
1081
    }
1082
    default:
1083
      UNREACHABLE();
1084
  }
1085
1086
  args.GetReturnValue().Set(true);
1087
}
1088
1089
void KeyObjectHandle::GetKeyDetail(const FunctionCallbackInfo<Value>& args) {
1090
  Environment* env = Environment::GetCurrent(args);
1091
  KeyObjectHandle* key;
1092
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1093
1094
  CHECK(args[0]->IsObject());
1095
1096
  std::shared_ptr<KeyObjectData> data = key->Data();
1097
1098
  switch (data->GetKeyType()) {
1099
    case kKeyTypeSecret:
1100
      if (GetSecretKeyDetail(env, data, args[0].As<Object>()).IsNothing())
1101
        return;
1102
      break;
1103
    case kKeyTypePublic:
1104
      // Fall through
1105
    case kKeyTypePrivate:
1106
      if (GetAsymmetricKeyDetail(env, data, args[0].As<Object>()).IsNothing())
1107
        return;
1108
      break;
1109
    default:
1110
      UNREACHABLE();
1111
  }
1112
1113
  args.GetReturnValue().Set(args[0]);
1114
}
1115
1116
Local<Value> KeyObjectHandle::GetAsymmetricKeyType() const {
1117
  const ManagedEVPPKey& key = data_->GetAsymmetricKey();
1118
  switch (EVP_PKEY_id(key.get())) {
1119
  case EVP_PKEY_RSA:
1120
    return env()->crypto_rsa_string();
1121
  case EVP_PKEY_RSA_PSS:
1122
    return env()->crypto_rsa_pss_string();
1123
  case EVP_PKEY_DSA:
1124
    return env()->crypto_dsa_string();
1125
  case EVP_PKEY_DH:
1126
    return env()->crypto_dh_string();
1127
  case EVP_PKEY_EC:
1128
    return env()->crypto_ec_string();
1129
  case EVP_PKEY_ED25519:
1130
    return env()->crypto_ed25519_string();
1131
  case EVP_PKEY_ED448:
1132
    return env()->crypto_ed448_string();
1133
  case EVP_PKEY_X25519:
1134
    return env()->crypto_x25519_string();
1135
  case EVP_PKEY_X448:
1136
    return env()->crypto_x448_string();
1137
  default:
1138
    return Undefined(env()->isolate());
1139
  }
1140
}
1141
1142
void KeyObjectHandle::GetAsymmetricKeyType(
1143
    const FunctionCallbackInfo<Value>& args) {
1144
  KeyObjectHandle* key;
1145
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1146
1147
  args.GetReturnValue().Set(key->GetAsymmetricKeyType());
1148
}
1149
1150
void KeyObjectHandle::GetSymmetricKeySize(
1151
    const FunctionCallbackInfo<Value>& args) {
1152
  KeyObjectHandle* key;
1153
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1154
  args.GetReturnValue().Set(
1155
      static_cast<uint32_t>(key->Data()->GetSymmetricKeySize()));
1156
}
1157
1158
void KeyObjectHandle::Export(const FunctionCallbackInfo<Value>& args) {
1159
  KeyObjectHandle* key;
1160
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1161
1162
  KeyType type = key->Data()->GetKeyType();
1163
1164
  MaybeLocal<Value> result;
1165
  if (type == kKeyTypeSecret) {
1166
    result = key->ExportSecretKey();
1167
  } else if (type == kKeyTypePublic) {
1168
    unsigned int offset = 0;
1169
    PublicKeyEncodingConfig config =
1170
        ManagedEVPPKey::GetPublicKeyEncodingFromJs(
1171
            args, &offset, kKeyContextExport);
1172
    CHECK_EQ(offset, static_cast<unsigned int>(args.Length()));
1173
    result = key->ExportPublicKey(config);
1174
  } else {
1175
    CHECK_EQ(type, kKeyTypePrivate);
1176
    unsigned int offset = 0;
1177
    NonCopyableMaybe<PrivateKeyEncodingConfig> config =
1178
        ManagedEVPPKey::GetPrivateKeyEncodingFromJs(
1179
            args, &offset, kKeyContextExport);
1180
    if (config.IsEmpty())
1181
      return;
1182
    CHECK_EQ(offset, static_cast<unsigned int>(args.Length()));
1183
    result = key->ExportPrivateKey(config.Release());
1184
  }
1185
1186
  if (!result.IsEmpty())
1187
    args.GetReturnValue().Set(result.FromMaybe(Local<Value>()));
1188
}
1189
1190
MaybeLocal<Value> KeyObjectHandle::ExportSecretKey() const {
1191
  const char* buf = data_->GetSymmetricKey();
1192
  unsigned int len = data_->GetSymmetricKeySize();
1193
  return Buffer::Copy(env(), buf, len).FromMaybe(Local<Value>());
1194
}
1195
1196
MaybeLocal<Value> KeyObjectHandle::ExportPublicKey(
1197
    const PublicKeyEncodingConfig& config) const {
1198
  return WritePublicKey(env(), data_->GetAsymmetricKey().get(), config);
1199
}
1200
1201
MaybeLocal<Value> KeyObjectHandle::ExportPrivateKey(
1202
    const PrivateKeyEncodingConfig& config) const {
1203
  return WritePrivateKey(env(), data_->GetAsymmetricKey().get(), config);
1204
}
1205
1206
void KeyObjectHandle::ExportJWK(
1207
    const v8::FunctionCallbackInfo<v8::Value>& args) {
1208
  Environment* env = Environment::GetCurrent(args);
1209
  KeyObjectHandle* key;
1210
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1211
1212
  CHECK(args[0]->IsObject());
1213
1214
  switch (key->Data()->GetKeyType()) {
1215
    case kKeyTypeSecret:
1216
      if (ExportJWKSecretKey(env, key->Data(), args[0].As<Object>())
1217
              .IsNothing()) {
1218
        return;
1219
      }
1220
      break;
1221
    case kKeyTypePublic:
1222
      // Fall through
1223
    case kKeyTypePrivate:
1224
      if (ExportJWKAsymmetricKey(env, key->Data(), args[0].As<Object>())
1225
              .IsNothing()) {
1226
        return;
1227
      }
1228
      break;
1229
    default:
1230
      UNREACHABLE();
1231
  }
1232
1233
  args.GetReturnValue().Set(args[0]);
1234
}
1235
1236
2
void NativeKeyObject::Initialize(Environment* env, Local<Object> target) {
1237
  env->SetMethod(target, "createNativeKeyObjectClass",
1238
2
                 NativeKeyObject::CreateNativeKeyObjectClass);
1239
2
}
1240
1241
void NativeKeyObject::New(const FunctionCallbackInfo<Value>& args) {
1242
  Environment* env = Environment::GetCurrent(args);
1243
  CHECK_EQ(args.Length(), 1);
1244
  CHECK(args[0]->IsObject());
1245
  KeyObjectHandle* handle = Unwrap<KeyObjectHandle>(args[0].As<Object>());
1246
  new NativeKeyObject(env, args.This(), handle->Data());
1247
}
1248
1249
2
void NativeKeyObject::CreateNativeKeyObjectClass(
1250
    const FunctionCallbackInfo<Value>& args) {
1251
2
  Environment* env = Environment::GetCurrent(args);
1252
1253
2
  CHECK_EQ(args.Length(), 1);
1254
2
  Local<Value> callback = args[0];
1255
2
  CHECK(callback->IsFunction());
1256
1257
2
  Local<FunctionTemplate> t = env->NewFunctionTemplate(NativeKeyObject::New);
1258
6
  t->InstanceTemplate()->SetInternalFieldCount(
1259
2
      KeyObjectHandle::kInternalFieldCount);
1260
4
  t->Inherit(BaseObject::GetConstructorTemplate(env));
1261
1262
  Local<Value> ctor;
1263
6
  if (!t->GetFunction(env->context()).ToLocal(&ctor))
1264
    return;
1265
1266
2
  Local<Value> recv = Undefined(env->isolate());
1267
  Local<Value> ret_v;
1268
6
  if (!callback.As<Function>()->Call(
1269
6
          env->context(), recv, 1, &ctor).ToLocal(&ret_v)) {
1270
    return;
1271
  }
1272
2
  Local<Array> ret = ret_v.As<Array>();
1273
6
  if (!ret->Get(env->context(), 1).ToLocal(&ctor)) return;
1274
2
  env->set_crypto_key_object_secret_constructor(ctor.As<Function>());
1275
6
  if (!ret->Get(env->context(), 2).ToLocal(&ctor)) return;
1276
2
  env->set_crypto_key_object_public_constructor(ctor.As<Function>());
1277
6
  if (!ret->Get(env->context(), 3).ToLocal(&ctor)) return;
1278
2
  env->set_crypto_key_object_private_constructor(ctor.As<Function>());
1279
4
  args.GetReturnValue().Set(ret);
1280
}
1281
1282
BaseObjectPtr<BaseObject> NativeKeyObject::KeyObjectTransferData::Deserialize(
1283
        Environment* env,
1284
        Local<Context> context,
1285
        std::unique_ptr<worker::TransferData> self) {
1286
  if (context != env->context()) {
1287
    THROW_ERR_MESSAGE_TARGET_CONTEXT_UNAVAILABLE(env);
1288
    return {};
1289
  }
1290
1291
  Local<Value> handle;
1292
  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
                                           "internal/crypto/keys");
1298
  if (env->native_module_require()->
1299
      Call(context, Null(env->isolate()), 1, &arg).IsEmpty()) {
1300
    return {};
1301
  }
1302
  switch (data_->GetKeyType()) {
1303
    case kKeyTypeSecret:
1304
      key_ctor = env->crypto_key_object_secret_constructor();
1305
      break;
1306
    case kKeyTypePublic:
1307
      key_ctor = env->crypto_key_object_public_constructor();
1308
      break;
1309
    case kKeyTypePrivate:
1310
      key_ctor = env->crypto_key_object_private_constructor();
1311
      break;
1312
    default:
1313
      CHECK(false);
1314
  }
1315
1316
  Local<Value> key;
1317
  if (!key_ctor->NewInstance(context, 1, &handle).ToLocal(&key))
1318
    return {};
1319
1320
  return BaseObjectPtr<BaseObject>(Unwrap<KeyObjectHandle>(key.As<Object>()));
1321
}
1322
1323
BaseObject::TransferMode NativeKeyObject::GetTransferMode() const {
1324
  return BaseObject::TransferMode::kCloneable;
1325
}
1326
1327
std::unique_ptr<worker::TransferData> NativeKeyObject::CloneForMessaging()
1328
    const {
1329
  return std::make_unique<KeyObjectTransferData>(handle_data_);
1330
}
1331
1332
WebCryptoKeyExportStatus PKEY_SPKI_Export(
1333
    KeyObjectData* key_data,
1334
    ByteSource* out) {
1335
  CHECK_EQ(key_data->GetKeyType(), kKeyTypePublic);
1336
  ManagedEVPPKey m_pkey = key_data->GetAsymmetricKey();
1337
  Mutex::ScopedLock lock(*m_pkey.mutex());
1338
  BIOPointer bio(BIO_new(BIO_s_mem()));
1339
  if (!i2d_PUBKEY_bio(bio.get(), m_pkey.get()))
1340
    return WebCryptoKeyExportStatus::FAILED;
1341
1342
  *out = ByteSource::FromBIO(bio);
1343
  return WebCryptoKeyExportStatus::OK;
1344
}
1345
1346
WebCryptoKeyExportStatus PKEY_PKCS8_Export(
1347
    KeyObjectData* key_data,
1348
    ByteSource* out) {
1349
  CHECK_EQ(key_data->GetKeyType(), kKeyTypePrivate);
1350
  ManagedEVPPKey m_pkey = key_data->GetAsymmetricKey();
1351
  Mutex::ScopedLock lock(*m_pkey.mutex());
1352
1353
  BIOPointer bio(BIO_new(BIO_s_mem()));
1354
  PKCS8Pointer p8inf(EVP_PKEY2PKCS8(m_pkey.get()));
1355
  if (!i2d_PKCS8_PRIV_KEY_INFO_bio(bio.get(), p8inf.get()))
1356
    return WebCryptoKeyExportStatus::FAILED;
1357
1358
  *out = ByteSource::FromBIO(bio);
1359
  return WebCryptoKeyExportStatus::OK;
1360
}
1361
1362
namespace Keys {
1363
2
void Initialize(Environment* env, Local<Object> target) {
1364
4
  target->Set(env->context(),
1365
              FIXED_ONE_BYTE_STRING(env->isolate(), "KeyObjectHandle"),
1366
10
              KeyObjectHandle::Initialize(env)).Check();
1367
1368
4
  NODE_DEFINE_CONSTANT(target, kWebCryptoKeyFormatRaw);
1369
2
  NODE_DEFINE_CONSTANT(target, kWebCryptoKeyFormatPKCS8);
1370
6
  NODE_DEFINE_CONSTANT(target, kWebCryptoKeyFormatSPKI);
1371
10
  NODE_DEFINE_CONSTANT(target, kWebCryptoKeyFormatJWK);
1372
14
1373
12
  NODE_DEFINE_CONSTANT(target, EVP_PKEY_ED25519);
1374
12
  NODE_DEFINE_CONSTANT(target, EVP_PKEY_ED448);
1375
14
  NODE_DEFINE_CONSTANT(target, EVP_PKEY_X25519);
1376
14
  NODE_DEFINE_CONSTANT(target, EVP_PKEY_X448);
1377
18
  NODE_DEFINE_CONSTANT(target, kKeyEncodingPKCS1);
1378
18
  NODE_DEFINE_CONSTANT(target, kKeyEncodingPKCS8);
1379
20
  NODE_DEFINE_CONSTANT(target, kKeyEncodingSPKI);
1380
20
  NODE_DEFINE_CONSTANT(target, kKeyEncodingSEC1);
1381
20
  NODE_DEFINE_CONSTANT(target, kKeyFormatDER);
1382
20
  NODE_DEFINE_CONSTANT(target, kKeyFormatPEM);
1383
18
  NODE_DEFINE_CONSTANT(target, kKeyTypeSecret);
1384
18
  NODE_DEFINE_CONSTANT(target, kKeyTypePublic);
1385
18
  NODE_DEFINE_CONSTANT(target, kKeyTypePrivate);
1386
18
  NODE_DEFINE_CONSTANT(target, kSigEncDER);
1387
18
  NODE_DEFINE_CONSTANT(target, kSigEncP1363);
1388
18
}
1389
12
}  // namespace Keys
1390
10
1391
4
}  // namespace crypto
1392

366
}  // namespace node