GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: crypto/crypto_keys.cc Lines: 720 815 88.3 %
Date: 2022-12-07 04:23:16 Branches: 344 565 60.9 %

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::Isolate;
28
using v8::Just;
29
using v8::Local;
30
using v8::Maybe;
31
using v8::MaybeLocal;
32
using v8::NewStringType;
33
using v8::Nothing;
34
using v8::Number;
35
using v8::Object;
36
using v8::String;
37
using v8::Uint32;
38
using v8::Undefined;
39
using v8::Value;
40
41
namespace crypto {
42
namespace {
43
5118
void GetKeyFormatAndTypeFromJs(
44
    AsymmetricKeyEncodingConfig* config,
45
    const FunctionCallbackInfo<Value>& args,
46
    unsigned int* offset,
47
    KeyEncodingContext context) {
48
  // During key pair generation, it is possible not to specify a key encoding,
49
  // which will lead to a key object being returned.
50

15354
  if (args[*offset]->IsUndefined()) {
51
1496
    CHECK_EQ(context, kKeyContextGenerate);
52

4488
    CHECK(args[*offset + 1]->IsUndefined());
53
1496
    config->output_key_object_ = true;
54
  } else {
55
3622
    config->output_key_object_ = false;
56
57

7244
    CHECK(args[*offset]->IsInt32());
58
3622
    config->format_ = static_cast<PKFormatType>(
59
10866
        args[*offset].As<Int32>()->Value());
60
61

7244
    if (args[*offset + 1]->IsInt32()) {
62
4250
      config->type_ = Just<PKEncodingType>(static_cast<PKEncodingType>(
63
6375
          args[*offset + 1].As<Int32>()->Value()));
64
    } else {
65



1497
      CHECK(
66
          (context == kKeyContextInput &&
67
           config->format_ == kKeyFormatPEM) ||
68
          (context == kKeyContextGenerate &&
69
           config->format_ == kKeyFormatJWK));
70

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

1055
  if (size < 2 || data[0] != 0x30)
164
    return false;
165
166
1055
  if (data[1] & 0x80) {
167
    // Long form.
168
930
    size_t n_bytes = data[1] & ~0x80;
169

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

80
         data[offset + 1] == 1 &&
199
46
         !(data[offset + 2] & 0xfe);
200
}
201
202
1021
bool IsEncryptedPrivateKeyInfo(const unsigned char* data, size_t size) {
203
  // Both PrivateKeyInfo and EncryptedPrivateKeyInfo start with a SEQUENCE.
204
  size_t offset, len;
205
1021
  if (!IsASN1Sequence(data, size, &offset, &len))
206
    return false;
207
208
  // A PrivateKeyInfo sequence always starts with an integer whereas an
209
  // EncryptedPrivateKeyInfo starts with an AlgorithmIdentifier.
210
2042
  return len >= 1 &&
211
2042
         data[offset] != 2;
212
}
213
214
1541
ParseKeyResult ParsePrivateKey(EVPKeyPointer* pkey,
215
                               const PrivateKeyEncodingConfig& config,
216
                               const char* key,
217
                               size_t key_len) {
218
1541
  const ByteSource* passphrase = config.passphrase_.get();
219
220
1541
  if (config.format_ == kKeyFormatPEM) {
221
507
    BIOPointer bio(BIO_new_mem_buf(key, key_len));
222
507
    if (!bio)
223
      return ParseKeyResult::kParseKeyFailed;
224
225
507
    pkey->reset(PEM_read_bio_PrivateKey(bio.get(),
226
                                        nullptr,
227
                                        PasswordCallback,
228
                                        &passphrase));
229
  } else {
230
1034
    CHECK_EQ(config.format_, kKeyFormatDER);
231
232
2068
    if (config.type_.ToChecked() == kKeyEncodingPKCS1) {
233
13
      const unsigned char* p = reinterpret_cast<const unsigned char*>(key);
234
13
      pkey->reset(d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &p, key_len));
235
2042
    } else if (config.type_.ToChecked() == kKeyEncodingPKCS8) {
236
1021
      BIOPointer bio(BIO_new_mem_buf(key, key_len));
237
1021
      if (!bio)
238
        return ParseKeyResult::kParseKeyFailed;
239
240
1021
      if (IsEncryptedPrivateKeyInfo(
241
              reinterpret_cast<const unsigned char*>(key), key_len)) {
242
17
        pkey->reset(d2i_PKCS8PrivateKey_bio(bio.get(),
243
                                            nullptr,
244
                                            PasswordCallback,
245
                                            &passphrase));
246
      } else {
247
2008
        PKCS8Pointer p8inf(d2i_PKCS8_PRIV_KEY_INFO_bio(bio.get(), nullptr));
248
1004
        if (p8inf)
249
980
          pkey->reset(EVP_PKCS82PKEY(p8inf.get()));
250
      }
251
    } else {
252
      CHECK_EQ(config.type_.ToChecked(), kKeyEncodingSEC1);
253
      const unsigned char* p = reinterpret_cast<const unsigned char*>(key);
254
      pkey->reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &p, key_len));
255
    }
256
  }
257
258
  // OpenSSL can fail to parse the key but still return a non-null pointer.
259
1541
  unsigned long err = ERR_peek_error();  // NOLINT(runtime/int)
260
1541
  if (err != 0)
261
45
    pkey->reset();
262
263
1541
  if (*pkey)
264
1496
    return ParseKeyResult::kParseKeyOk;
265

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

1176
          raw).IsNothing()) {
466
    return Nothing<bool>();
467
  }
468
469
294
  return Just(true);
470
}
471
472
273
std::shared_ptr<KeyObjectData> ImportJWKSecretKey(
473
    Environment* env,
474
    Local<Object> jwk) {
475
  Local<Value> key;
476

1092
  if (!jwk->Get(env->context(), env->jwk_k_string()).ToLocal(&key) ||
477
546
      !key->IsString()) {
478
    THROW_ERR_CRYPTO_INVALID_JWK(env, "Invalid JWK secret key format");
479
    return std::shared_ptr<KeyObjectData>();
480
  }
481
482
546
  ByteSource key_data = ByteSource::FromEncodedString(env, key.As<String>());
483
273
  if (key_data.size() > INT_MAX) {
484
    THROW_ERR_CRYPTO_INVALID_KEYLEN(env);
485
    return std::shared_ptr<KeyObjectData>();
486
  }
487
488
273
  return KeyObjectData::CreateSecret(std::move(key_data));
489
}
490
491
710
Maybe<bool> ExportJWKAsymmetricKey(
492
    Environment* env,
493
    std::shared_ptr<KeyObjectData> key,
494
    Local<Object> target,
495
    bool handleRsaPss) {
496

710
  switch (EVP_PKEY_id(key->GetAsymmetricKey().get())) {
497
2
    case EVP_PKEY_RSA_PSS: {
498
2
      if (handleRsaPss) return ExportJWKRsaKey(env, key, target);
499
2
      break;
500
    }
501
410
    case EVP_PKEY_RSA: return ExportJWKRsaKey(env, key, target);
502
398
    case EVP_PKEY_EC: return ExportJWKEcKey(env, key, target).IsJust() ?
503
199
                               Just(true) : Nothing<bool>();
504
95
    case EVP_PKEY_ED25519:
505
      // Fall through
506
    case EVP_PKEY_ED448:
507
      // Fall through
508
    case EVP_PKEY_X25519:
509
      // Fall through
510
95
    case EVP_PKEY_X448: return ExportJWKEdKey(env, key, target);
511
  }
512
6
  THROW_ERR_CRYPTO_JWK_UNSUPPORTED_KEY_TYPE(env);
513
6
  return Just(false);
514
}
515
516
659
std::shared_ptr<KeyObjectData> ImportJWKAsymmetricKey(
517
    Environment* env,
518
    Local<Object> jwk,
519
    const char* kty,
520
    const FunctionCallbackInfo<Value>& args,
521
    unsigned int offset) {
522
659
  if (strcmp(kty, "RSA") == 0) {
523
503
    return ImportJWKRsaKey(env, jwk, args, offset);
524
156
  } else if (strcmp(kty, "EC") == 0) {
525
156
    return ImportJWKEcKey(env, jwk, args, offset);
526
  }
527
528
  THROW_ERR_CRYPTO_INVALID_JWK(env, "%s is not a supported JWK key type", kty);
529
  return std::shared_ptr<KeyObjectData>();
530
}
531
532
4020
Maybe<bool> GetSecretKeyDetail(
533
    Environment* env,
534
    std::shared_ptr<KeyObjectData> key,
535
    Local<Object> target) {
536
  // For the secret key detail, all we care about is the length,
537
  // converted to bits.
538
539
4020
  size_t length = key->GetSymmetricKeySize() * CHAR_BIT;
540
  return target->Set(env->context(),
541
                     env->length_string(),
542
12060
                     Number::New(env->isolate(), static_cast<double>(length)));
543
}
544
545
2360
Maybe<bool> GetAsymmetricKeyDetail(
546
  Environment* env,
547
  std::shared_ptr<KeyObjectData> key,
548
  Local<Object> target) {
549

2360
  switch (EVP_PKEY_id(key->GetAsymmetricKey().get())) {
550
1698
    case EVP_PKEY_RSA:
551
      // Fall through
552
1698
    case EVP_PKEY_RSA_PSS: return GetRsaKeyDetail(env, key, target);
553
2
    case EVP_PKEY_DSA: return GetDsaKeyDetail(env, key, target);
554
660
    case EVP_PKEY_EC: return GetEcKeyDetail(env, key, target);
555
    case EVP_PKEY_DH: return GetDhKeyDetail(env, key, target);
556
  }
557
  THROW_ERR_CRYPTO_INVALID_KEYTYPE(env);
558
  return Nothing<bool>();
559
}
560
}  // namespace
561
562
10016
ManagedEVPPKey::ManagedEVPPKey(EVPKeyPointer&& pkey) : pkey_(std::move(pkey)),
563
5008
    mutex_(std::make_shared<Mutex>()) {}
564
565
18849
ManagedEVPPKey::ManagedEVPPKey(const ManagedEVPPKey& that) {
566
18849
  *this = that;
567
18849
}
568
569
24587
ManagedEVPPKey& ManagedEVPPKey::operator=(const ManagedEVPPKey& that) {
570
24587
  Mutex::ScopedLock lock(*that.mutex_);
571
572
24587
  pkey_.reset(that.get());
573
574
24587
  if (pkey_)
575
23753
    EVP_PKEY_up_ref(pkey_.get());
576
577
24587
  mutex_ = that.mutex_;
578
579
24587
  return *this;
580
}
581
582
9907
ManagedEVPPKey::operator bool() const {
583
9907
  return !!pkey_;
584
}
585
586
48741
EVP_PKEY* ManagedEVPPKey::get() const {
587
48741
  return pkey_.get();
588
}
589
590
6949
Mutex* ManagedEVPPKey::mutex() const {
591
6949
  return mutex_.get();
592
}
593
594
void ManagedEVPPKey::MemoryInfo(MemoryTracker* tracker) const {
595
  tracker->TrackFieldWithSize("pkey",
596
                              !pkey_ ? 0 : kSizeOf_EVP_PKEY +
597
                              size_of_private_key() +
598
                              size_of_public_key());
599
}
600
601
size_t ManagedEVPPKey::size_of_private_key() const {
602
  size_t len = 0;
603
  return (pkey_ && EVP_PKEY_get_raw_private_key(
604
      pkey_.get(), nullptr, &len) == 1) ? len : 0;
605
}
606
607
size_t ManagedEVPPKey::size_of_public_key() const {
608
  size_t len = 0;
609
  return (pkey_ && EVP_PKEY_get_raw_public_key(
610
      pkey_.get(), nullptr, &len) == 1) ? len : 0;
611
}
612
613
// This maps true to Just<bool>(true) and false to Nothing<bool>().
614
1342
static inline Maybe<bool> Tristate(bool b) {
615
1342
  return b ? Just(true) : Nothing<bool>();
616
}
617
618
1004
Maybe<bool> ExportJWKInner(Environment* env,
619
                           std::shared_ptr<KeyObjectData> key,
620
                           Local<Value> result,
621
                           bool handleRsaPss) {
622
1004
  switch (key->GetKeyType()) {
623
294
    case kKeyTypeSecret:
624
294
      return ExportJWKSecretKey(env, key, result.As<Object>());
625
710
    case kKeyTypePublic:
626
      // Fall through
627
    case kKeyTypePrivate:
628
      return ExportJWKAsymmetricKey(
629
1420
        env, key, result.As<Object>(), handleRsaPss);
630
    default:
631
      UNREACHABLE();
632
  }
633
}
634
635
684
Maybe<bool> ManagedEVPPKey::ToEncodedPublicKey(
636
    Environment* env,
637
    const PublicKeyEncodingConfig& config,
638
    Local<Value>* out) {
639
684
  if (!*this) return Nothing<bool>();
640
684
  if (config.output_key_object_) {
641
    // Note that this has the downside of containing sensitive data of the
642
    // private key.
643
    std::shared_ptr<KeyObjectData> data =
644
652
        KeyObjectData::CreateAsymmetric(kKeyTypePublic, *this);
645
1304
    return Tristate(KeyObjectHandle::Create(env, data).ToLocal(out));
646
32
  } else if (config.format_ == kKeyFormatJWK) {
647
    std::shared_ptr<KeyObjectData> data =
648
11
        KeyObjectData::CreateAsymmetric(kKeyTypePublic, *this);
649
11
    *out = Object::New(env->isolate());
650
11
    return ExportJWKInner(env, data, *out, false);
651
  }
652
653
42
  return Tristate(WritePublicKey(env, get(), config).ToLocal(out));
654
}
655
656
679
Maybe<bool> ManagedEVPPKey::ToEncodedPrivateKey(
657
    Environment* env,
658
    const PrivateKeyEncodingConfig& config,
659
    Local<Value>* out) {
660
679
  if (!*this) return Nothing<bool>();
661
679
  if (config.output_key_object_) {
662
    std::shared_ptr<KeyObjectData> data =
663
651
        KeyObjectData::CreateAsymmetric(kKeyTypePrivate, *this);
664
1302
    return Tristate(KeyObjectHandle::Create(env, data).ToLocal(out));
665
28
  } else if (config.format_ == kKeyFormatJWK) {
666
    std::shared_ptr<KeyObjectData> data =
667
10
        KeyObjectData::CreateAsymmetric(kKeyTypePrivate, *this);
668
10
    *out = Object::New(env->isolate());
669
10
    return ExportJWKInner(env, data, *out, false);
670
  }
671
672
36
  return Tristate(WritePrivateKey(env, get(), config).ToLocal(out));
673
}
674
675
NonCopyableMaybe<PrivateKeyEncodingConfig>
676
4286
ManagedEVPPKey::GetPrivateKeyEncodingFromJs(
677
    const FunctionCallbackInfo<Value>& args,
678
    unsigned int* offset,
679
    KeyEncodingContext context) {
680
4286
  Environment* env = Environment::GetCurrent(args);
681
682
8572
  PrivateKeyEncodingConfig result;
683
4286
  GetKeyFormatAndTypeFromJs(&result, args, offset, context);
684
685
4286
  if (result.output_key_object_) {
686
749
    if (context != kKeyContextInput)
687
749
      (*offset)++;
688
  } else {
689
3537
    bool needs_passphrase = false;
690
3537
    if (context != kKeyContextInput) {
691

228
      if (args[*offset]->IsString()) {
692
28
        Utf8Value cipher_name(env->isolate(), args[*offset]);
693
14
        result.cipher_ = EVP_get_cipherbyname(*cipher_name);
694
14
        if (result.cipher_ == nullptr) {
695
1
          THROW_ERR_CRYPTO_UNKNOWN_CIPHER(env);
696
1
          return NonCopyableMaybe<PrivateKeyEncodingConfig>();
697
        }
698
13
        needs_passphrase = true;
699
      } else {
700

186
        CHECK(args[*offset]->IsNullOrUndefined());
701
62
        result.cipher_ = nullptr;
702
      }
703
75
      (*offset)++;
704
    }
705
706

7072
    if (IsAnyByteSource(args[*offset])) {
707

97
      CHECK_IMPLIES(context != kKeyContextInput, result.cipher_ != nullptr);
708
194
      ArrayBufferOrViewContents<char> passphrase(args[*offset]);
709
97
      if (UNLIKELY(!passphrase.CheckSizeInt32())) {
710
        THROW_ERR_OUT_OF_RANGE(env, "passphrase is too big");
711
        return NonCopyableMaybe<PrivateKeyEncodingConfig>();
712
      }
713
194
      result.passphrase_ = NonCopyableMaybe<ByteSource>(
714
291
          passphrase.ToNullTerminatedCopy());
715
    } else {
716


10317
      CHECK(args[*offset]->IsNullOrUndefined() && !needs_passphrase);
717
    }
718
  }
719
720
4285
  (*offset)++;
721
4285
  return NonCopyableMaybe<PrivateKeyEncodingConfig>(std::move(result));
722
}
723
724
832
PublicKeyEncodingConfig ManagedEVPPKey::GetPublicKeyEncodingFromJs(
725
    const FunctionCallbackInfo<Value>& args,
726
    unsigned int* offset,
727
    KeyEncodingContext context) {
728
832
  PublicKeyEncodingConfig result;
729
832
  GetKeyFormatAndTypeFromJs(&result, args, offset, context);
730
832
  return result;
731
}
732
733
1430
ManagedEVPPKey ManagedEVPPKey::GetPrivateKeyFromJs(
734
    const FunctionCallbackInfo<Value>& args,
735
    unsigned int* offset,
736
    bool allow_key_object) {
737


5720
  if (args[*offset]->IsString() || IsAnyByteSource(args[*offset])) {
738
1209
    Environment* env = Environment::GetCurrent(args);
739
3627
    ByteSource key = ByteSource::FromStringOrBuffer(env, args[(*offset)++]);
740
    NonCopyableMaybe<PrivateKeyEncodingConfig> config =
741
2418
        GetPrivateKeyEncodingFromJs(args, offset, kKeyContextInput);
742
1209
    if (config.IsEmpty())
743
      return ManagedEVPPKey();
744
745
1209
    EVPKeyPointer pkey;
746
    ParseKeyResult ret =
747
1209
        ParsePrivateKey(&pkey, config.Release(), key.data<char>(), key.size());
748
1209
    return GetParsedKey(env, std::move(pkey), ret,
749
1209
                        "Failed to read private key");
750
  } else {
751


442
    CHECK(args[*offset]->IsObject() && allow_key_object);
752
    KeyObjectHandle* key;
753

663
    ASSIGN_OR_RETURN_UNWRAP(&key, args[*offset].As<Object>(), ManagedEVPPKey());
754
221
    CHECK_EQ(key->Data()->GetKeyType(), kKeyTypePrivate);
755
221
    (*offset) += 4;
756
221
    return key->Data()->GetAsymmetricKey();
757
  }
758
}
759
760
2967
ManagedEVPPKey ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(
761
    const FunctionCallbackInfo<Value>& args,
762
    unsigned int* offset) {
763

5934
  if (IsAnyByteSource(args[*offset])) {
764
2252
    Environment* env = Environment::GetCurrent(args);
765
4504
    ArrayBufferOrViewContents<char> data(args[(*offset)++]);
766
2252
    if (UNLIKELY(!data.CheckSizeInt32())) {
767
      THROW_ERR_OUT_OF_RANGE(env, "keyData is too big");
768
      return ManagedEVPPKey();
769
    }
770
    NonCopyableMaybe<PrivateKeyEncodingConfig> config_ =
771
4504
        GetPrivateKeyEncodingFromJs(args, offset, kKeyContextInput);
772
2252
    if (config_.IsEmpty())
773
      return ManagedEVPPKey();
774
775
    ParseKeyResult ret;
776
4504
    PrivateKeyEncodingConfig config = config_.Release();
777
2252
    EVPKeyPointer pkey;
778
2252
    if (config.format_ == kKeyFormatPEM) {
779
      // For PEM, we can easily determine whether it is a public or private key
780
      // by looking for the respective PEM tags.
781
1231
      ret = ParsePublicKeyPEM(&pkey, data.data(), data.size());
782
1231
      if (ret == ParseKeyResult::kParseKeyNotRecognized) {
783
263
        ret = ParsePrivateKey(&pkey, config, data.data(), data.size());
784
      }
785
    } else {
786
      // For DER, the type determines how to parse it. SPKI, PKCS#8 and SEC1 are
787
      // easy, but PKCS#1 can be a public key or a private key.
788
      bool is_public;
789

1021
      switch (config.type_.ToChecked()) {
790
34
        case kKeyEncodingPKCS1:
791
68
          is_public = !IsRSAPrivateKey(
792
34
              reinterpret_cast<const unsigned char*>(data.data()), data.size());
793
34
          break;
794
930
        case kKeyEncodingSPKI:
795
930
          is_public = true;
796
930
          break;
797
57
        case kKeyEncodingPKCS8:
798
        case kKeyEncodingSEC1:
799
57
          is_public = false;
800
57
          break;
801
        default:
802
          UNREACHABLE("Invalid key encoding type");
803
      }
804
805
1021
      if (is_public) {
806
952
        ret = ParsePublicKey(&pkey, config, data.data(), data.size());
807
      } else {
808
69
        ret = ParsePrivateKey(&pkey, config, data.data(), data.size());
809
      }
810
    }
811
812
    return ManagedEVPPKey::GetParsedKey(
813
2252
        env, std::move(pkey), ret, "Failed to read asymmetric key");
814
  } else {
815

1430
    CHECK(args[*offset]->IsObject());
816
2145
    KeyObjectHandle* key = Unwrap<KeyObjectHandle>(args[*offset].As<Object>());
817
715
    CHECK_NOT_NULL(key);
818
715
    CHECK_NE(key->Data()->GetKeyType(), kKeyTypeSecret);
819
715
    (*offset) += 4;
820
715
    return key->Data()->GetAsymmetricKey();
821
  }
822
}
823
824
3461
ManagedEVPPKey ManagedEVPPKey::GetParsedKey(Environment* env,
825
                                            EVPKeyPointer&& pkey,
826
                                            ParseKeyResult ret,
827
                                            const char* default_msg) {
828
3461
  switch (ret) {
829
3404
    case ParseKeyResult::kParseKeyOk:
830
3404
      CHECK(pkey);
831
3404
      break;
832
2
    case ParseKeyResult::kParseKeyNeedPassphrase:
833
2
      THROW_ERR_MISSING_PASSPHRASE(env,
834
                                   "Passphrase required for encrypted key");
835
2
      break;
836
55
    default:
837
55
      ThrowCryptoError(env, ERR_get_error(), default_msg);
838
  }
839
840
3461
  return ManagedEVPPKey(std::move(pkey));
841
}
842
843
5489
KeyObjectData::KeyObjectData(ByteSource symmetric_key)
844
    : key_type_(KeyType::kKeyTypeSecret),
845
5489
      symmetric_key_(std::move(symmetric_key)),
846
5489
      asymmetric_key_() {}
847
848
4147
KeyObjectData::KeyObjectData(KeyType type, const ManagedEVPPKey& pkey)
849
4147
    : key_type_(type), symmetric_key_(), asymmetric_key_{pkey} {}
850
851
void KeyObjectData::MemoryInfo(MemoryTracker* tracker) const {
852
  switch (GetKeyType()) {
853
    case kKeyTypeSecret:
854
      tracker->TrackFieldWithSize("symmetric_key", symmetric_key_.size());
855
      break;
856
    case kKeyTypePrivate:
857
      // Fall through
858
    case kKeyTypePublic:
859
      tracker->TrackFieldWithSize("key", asymmetric_key_);
860
      break;
861
    default:
862
      UNREACHABLE();
863
  }
864
}
865
866
5489
std::shared_ptr<KeyObjectData> KeyObjectData::CreateSecret(ByteSource key) {
867
5489
  return std::shared_ptr<KeyObjectData>(new KeyObjectData(std::move(key)));
868
}
869
870
4147
std::shared_ptr<KeyObjectData> KeyObjectData::CreateAsymmetric(
871
    KeyType key_type,
872
    const ManagedEVPPKey& pkey) {
873
4147
  CHECK(pkey);
874
4147
  return std::shared_ptr<KeyObjectData>(new KeyObjectData(key_type, pkey));
875
}
876
877
19307
KeyType KeyObjectData::GetKeyType() const {
878
19307
  return key_type_;
879
}
880
881
11184
ManagedEVPPKey KeyObjectData::GetAsymmetricKey() const {
882
11184
  CHECK_NE(key_type_, kKeyTypeSecret);
883
11184
  return asymmetric_key_;
884
}
885
886
8123
const char* KeyObjectData::GetSymmetricKey() const {
887
8123
  CHECK_EQ(key_type_, kKeyTypeSecret);
888
8123
  return symmetric_key_.data<char>();
889
}
890
891
11899
size_t KeyObjectData::GetSymmetricKeySize() const {
892
11899
  CHECK_EQ(key_type_, kKeyTypeSecret);
893
11899
  return symmetric_key_.size();
894
}
895
896
3412
v8::Local<v8::Function> KeyObjectHandle::Initialize(Environment* env) {
897
3412
  Local<Function> templ = env->crypto_key_object_handle_constructor();
898
3412
  if (!templ.IsEmpty()) {
899
2612
    return templ;
900
  }
901
800
  Isolate* isolate = env->isolate();
902
800
  Local<FunctionTemplate> t = NewFunctionTemplate(isolate, New);
903
1600
  t->InstanceTemplate()->SetInternalFieldCount(
904
      KeyObjectHandle::kInternalFieldCount);
905
800
  t->Inherit(BaseObject::GetConstructorTemplate(env));
906
907
800
  SetProtoMethod(isolate, t, "init", Init);
908
800
  SetProtoMethodNoSideEffect(
909
      isolate, t, "getSymmetricKeySize", GetSymmetricKeySize);
910
800
  SetProtoMethodNoSideEffect(
911
      isolate, t, "getAsymmetricKeyType", GetAsymmetricKeyType);
912
800
  SetProtoMethod(isolate, t, "export", Export);
913
800
  SetProtoMethod(isolate, t, "exportJwk", ExportJWK);
914
800
  SetProtoMethod(isolate, t, "initECRaw", InitECRaw);
915
800
  SetProtoMethod(isolate, t, "initEDRaw", InitEDRaw);
916
800
  SetProtoMethod(isolate, t, "initJwk", InitJWK);
917
800
  SetProtoMethod(isolate, t, "keyDetail", GetKeyDetail);
918
800
  SetProtoMethod(isolate, t, "equals", Equals);
919
920
800
  auto function = t->GetFunction(env->context()).ToLocalChecked();
921
800
  env->set_crypto_key_object_handle_constructor(function);
922
800
  return function;
923
}
924
925
5639
void KeyObjectHandle::RegisterExternalReferences(
926
    ExternalReferenceRegistry* registry) {
927
5639
  registry->Register(New);
928
5639
  registry->Register(Init);
929
5639
  registry->Register(GetSymmetricKeySize);
930
5639
  registry->Register(GetAsymmetricKeyType);
931
5639
  registry->Register(Export);
932
5639
  registry->Register(ExportJWK);
933
5639
  registry->Register(InitECRaw);
934
5639
  registry->Register(InitEDRaw);
935
5639
  registry->Register(InitJWK);
936
5639
  registry->Register(GetKeyDetail);
937
5639
  registry->Register(Equals);
938
5639
}
939
940
2612
MaybeLocal<Object> KeyObjectHandle::Create(
941
    Environment* env,
942
    std::shared_ptr<KeyObjectData> data) {
943
  Local<Object> obj;
944
2612
  Local<Function> ctor = KeyObjectHandle::Initialize(env);
945
5224
  CHECK(!env->crypto_key_object_handle_constructor().IsEmpty());
946
5224
  if (!ctor->NewInstance(env->context(), 0, nullptr).ToLocal(&obj))
947
    return MaybeLocal<Object>();
948
949
2612
  KeyObjectHandle* key = Unwrap<KeyObjectHandle>(obj);
950
2612
  CHECK_NOT_NULL(key);
951
2612
  key->data_ = data;
952
2612
  return obj;
953
}
954
955
28360
const std::shared_ptr<KeyObjectData>& KeyObjectHandle::Data() {
956
28360
  return data_;
957
}
958
959
9700
void KeyObjectHandle::New(const FunctionCallbackInfo<Value>& args) {
960
9700
  CHECK(args.IsConstructCall());
961
9700
  Environment* env = Environment::GetCurrent(args);
962
9700
  new KeyObjectHandle(env, args.This());
963
9700
}
964
965
9700
KeyObjectHandle::KeyObjectHandle(Environment* env,
966
9700
                                 Local<Object> wrap)
967
9700
    : BaseObject(env, wrap) {
968
9700
  MakeWeak();
969
9700
}
970
971
5919
void KeyObjectHandle::Init(const FunctionCallbackInfo<Value>& args) {
972
  KeyObjectHandle* key;
973
5960
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
974
5919
  MarkPopErrorOnReturn mark_pop_error_on_return;
975
976
5919
  CHECK(args[0]->IsInt32());
977
11838
  KeyType type = static_cast<KeyType>(args[0].As<Uint32>()->Value());
978
979
  unsigned int offset;
980
5919
  ManagedEVPPKey pkey;
981
982

5919
  switch (type) {
983
3917
  case kKeyTypeSecret: {
984
3917
    CHECK_EQ(args.Length(), 2);
985
3917
    ArrayBufferOrViewContents<char> buf(args[1]);
986
3917
    key->data_ = KeyObjectData::CreateSecret(buf.ToCopy());
987
3917
    break;
988
  }
989
1003
  case kKeyTypePublic: {
990
1003
    CHECK_EQ(args.Length(), 5);
991
992
1003
    offset = 1;
993
1003
    pkey = ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(args, &offset);
994
1003
    if (!pkey)
995
12
      return;
996
991
    key->data_ = KeyObjectData::CreateAsymmetric(type, pkey);
997
991
    break;
998
  }
999
999
  case kKeyTypePrivate: {
1000
999
    CHECK_EQ(args.Length(), 5);
1001
1002
999
    offset = 1;
1003
999
    pkey = ManagedEVPPKey::GetPrivateKeyFromJs(args, &offset, false);
1004
999
    if (!pkey)
1005
29
      return;
1006
970
    key->data_ = KeyObjectData::CreateAsymmetric(type, pkey);
1007
970
    break;
1008
  }
1009
  default:
1010
    UNREACHABLE();
1011
  }
1012
}
1013
1014
932
void KeyObjectHandle::InitJWK(const FunctionCallbackInfo<Value>& args) {
1015
932
  Environment* env = Environment::GetCurrent(args);
1016
  KeyObjectHandle* key;
1017
932
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1018
932
  MarkPopErrorOnReturn mark_pop_error_on_return;
1019
1020
  // The argument must be a JavaScript object that we will inspect
1021
  // to get the JWK properties from.
1022
932
  CHECK(args[0]->IsObject());
1023
1024
  // Step one, Secret key or not?
1025
1864
  Local<Object> input = args[0].As<Object>();
1026
1027
  Local<Value> kty;
1028

3728
  if (!input->Get(env->context(), env->jwk_kty_string()).ToLocal(&kty) ||
1029
1864
      !kty->IsString()) {
1030
    return THROW_ERR_CRYPTO_INVALID_JWK(env);
1031
  }
1032
1033
932
  Utf8Value kty_string(env->isolate(), kty);
1034
1035
932
  if (strcmp(*kty_string, "oct") == 0) {
1036
    // Secret key
1037
273
    key->data_ = ImportJWKSecretKey(env, input);
1038
273
    if (!key->data_) {
1039
      // ImportJWKSecretKey is responsible for throwing an appropriate error
1040
      return;
1041
    }
1042
  } else {
1043
659
    key->data_ = ImportJWKAsymmetricKey(env, input, *kty_string, args, 1);
1044
659
    if (!key->data_) {
1045
      // ImportJWKAsymmetricKey is responsible for throwing an appropriate error
1046
      return;
1047
    }
1048
  }
1049
1050
1864
  args.GetReturnValue().Set(key->data_->GetKeyType());
1051
}
1052
1053
12
void KeyObjectHandle::InitECRaw(const FunctionCallbackInfo<Value>& args) {
1054
12
  Environment* env = Environment::GetCurrent(args);
1055
  KeyObjectHandle* key;
1056
12
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1057
1058
24
  CHECK(args[0]->IsString());
1059
12
  Utf8Value name(env->isolate(), args[0]);
1060
1061
12
  MarkPopErrorOnReturn mark_pop_error_on_return;
1062
1063
12
  int id = OBJ_txt2nid(*name);
1064
12
  ECKeyPointer eckey(EC_KEY_new_by_curve_name(id));
1065
12
  if (!eckey)
1066
    return args.GetReturnValue().Set(false);
1067
1068
12
  const EC_GROUP* group = EC_KEY_get0_group(eckey.get());
1069
12
  ECPointPointer pub(ECDH::BufferToPoint(env, group, args[1]));
1070
1071
12
  if (!pub ||
1072


24
      !eckey ||
1073
12
      !EC_KEY_set_public_key(eckey.get(), pub.get())) {
1074
    return args.GetReturnValue().Set(false);
1075
  }
1076
1077
12
  EVPKeyPointer pkey(EVP_PKEY_new());
1078
12
  if (!EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()))
1079
    args.GetReturnValue().Set(false);
1080
1081
12
  eckey.release();  // Release ownership of the key
1082
1083
12
  key->data_ =
1084
24
      KeyObjectData::CreateAsymmetric(
1085
          kKeyTypePublic,
1086
36
          ManagedEVPPKey(std::move(pkey)));
1087
1088
24
  args.GetReturnValue().Set(true);
1089
}
1090
1091
189
void KeyObjectHandle::InitEDRaw(const FunctionCallbackInfo<Value>& args) {
1092
189
  Environment* env = Environment::GetCurrent(args);
1093
  KeyObjectHandle* key;
1094
189
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1095
1096
378
  CHECK(args[0]->IsString());
1097
189
  Utf8Value name(env->isolate(), args[0]);
1098
1099
189
  ArrayBufferOrViewContents<unsigned char> key_data(args[1]);
1100
378
  KeyType type = static_cast<KeyType>(args[2].As<Int32>()->Value());
1101
1102
189
  MarkPopErrorOnReturn mark_pop_error_on_return;
1103
1104
  typedef EVP_PKEY* (*new_key_fn)(int, ENGINE*, const unsigned char*, size_t);
1105
189
  new_key_fn fn = type == kKeyTypePrivate
1106
189
      ? EVP_PKEY_new_raw_private_key
1107
      : EVP_PKEY_new_raw_public_key;
1108
1109
189
  int id = GetOKPCurveFromName(*name);
1110
1111
189
  switch (id) {
1112
189
    case EVP_PKEY_X25519:
1113
    case EVP_PKEY_X448:
1114
    case EVP_PKEY_ED25519:
1115
    case EVP_PKEY_ED448: {
1116
189
      EVPKeyPointer pkey(fn(id, nullptr, key_data.data(), key_data.size()));
1117
189
      if (!pkey)
1118
        return args.GetReturnValue().Set(false);
1119
189
      key->data_ =
1120
378
          KeyObjectData::CreateAsymmetric(
1121
              type,
1122
567
              ManagedEVPPKey(std::move(pkey)));
1123
189
      CHECK(key->data_);
1124
189
      break;
1125
    }
1126
    default:
1127
      UNREACHABLE();
1128
  }
1129
1130
378
  args.GetReturnValue().Set(true);
1131
}
1132
1133
71
void KeyObjectHandle::Equals(const FunctionCallbackInfo<Value>& args) {
1134
  KeyObjectHandle* self_handle;
1135
  KeyObjectHandle* arg_handle;
1136
71
  ASSIGN_OR_RETURN_UNWRAP(&self_handle, args.Holder());
1137
142
  ASSIGN_OR_RETURN_UNWRAP(&arg_handle, args[0].As<Object>());
1138
71
  std::shared_ptr<KeyObjectData> key = self_handle->Data();
1139
71
  std::shared_ptr<KeyObjectData> key2 = arg_handle->Data();
1140
1141
71
  KeyType key_type = key->GetKeyType();
1142
71
  CHECK_EQ(key_type, key2->GetKeyType());
1143
1144
  bool ret;
1145
71
  switch (key_type) {
1146
7
    case kKeyTypeSecret: {
1147
7
      size_t size = key->GetSymmetricKeySize();
1148
7
      if (size == key2->GetSymmetricKeySize()) {
1149
5
        ret = CRYPTO_memcmp(
1150
5
          key->GetSymmetricKey(),
1151
5
          key2->GetSymmetricKey(),
1152
          size) == 0;
1153
      } else {
1154
2
        ret = false;
1155
      }
1156
7
      break;
1157
    }
1158
64
    case kKeyTypePublic:
1159
    case kKeyTypePrivate: {
1160
64
      EVP_PKEY* pkey = key->GetAsymmetricKey().get();
1161
64
      EVP_PKEY* pkey2 = key2->GetAsymmetricKey().get();
1162
#if OPENSSL_VERSION_MAJOR >= 3
1163
64
      int ok = EVP_PKEY_eq(pkey, pkey2);
1164
#else
1165
      int ok = EVP_PKEY_cmp(pkey, pkey2);
1166
#endif
1167
64
      if (ok == -2) {
1168
        Environment* env = Environment::GetCurrent(args);
1169
        return THROW_ERR_CRYPTO_UNSUPPORTED_OPERATION(env);
1170
      }
1171
64
      ret = ok == 1;
1172
64
      break;
1173
    }
1174
    default:
1175
      UNREACHABLE("unsupported key type");
1176
  }
1177
1178
142
  args.GetReturnValue().Set(ret);
1179
}
1180
1181
6380
void KeyObjectHandle::GetKeyDetail(const FunctionCallbackInfo<Value>& args) {
1182
6380
  Environment* env = Environment::GetCurrent(args);
1183
  KeyObjectHandle* key;
1184
6380
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1185
1186
6380
  CHECK(args[0]->IsObject());
1187
1188
6380
  std::shared_ptr<KeyObjectData> data = key->Data();
1189
1190
6380
  switch (data->GetKeyType()) {
1191
4020
    case kKeyTypeSecret:
1192
12060
      if (GetSecretKeyDetail(env, data, args[0].As<Object>()).IsNothing())
1193
        return;
1194
4020
      break;
1195
2360
    case kKeyTypePublic:
1196
      // Fall through
1197
    case kKeyTypePrivate:
1198
7080
      if (GetAsymmetricKeyDetail(env, data, args[0].As<Object>()).IsNothing())
1199
        return;
1200
2360
      break;
1201
    default:
1202
      UNREACHABLE();
1203
  }
1204
1205
12760
  args.GetReturnValue().Set(args[0]);
1206
}
1207
1208
2710
Local<Value> KeyObjectHandle::GetAsymmetricKeyType() const {
1209
5420
  const ManagedEVPPKey& key = data_->GetAsymmetricKey();
1210


2710
  switch (EVP_PKEY_id(key.get())) {
1211
1719
  case EVP_PKEY_RSA:
1212
3438
    return env()->crypto_rsa_string();
1213
22
  case EVP_PKEY_RSA_PSS:
1214
44
    return env()->crypto_rsa_pss_string();
1215
10
  case EVP_PKEY_DSA:
1216
20
    return env()->crypto_dsa_string();
1217
18
  case EVP_PKEY_DH:
1218
36
    return env()->crypto_dh_string();
1219
680
  case EVP_PKEY_EC:
1220
1360
    return env()->crypto_ec_string();
1221
101
  case EVP_PKEY_ED25519:
1222
202
    return env()->crypto_ed25519_string();
1223
58
  case EVP_PKEY_ED448:
1224
116
    return env()->crypto_ed448_string();
1225
51
  case EVP_PKEY_X25519:
1226
102
    return env()->crypto_x25519_string();
1227
51
  case EVP_PKEY_X448:
1228
102
    return env()->crypto_x448_string();
1229
  default:
1230
    return Undefined(env()->isolate());
1231
  }
1232
}
1233
1234
2710
void KeyObjectHandle::GetAsymmetricKeyType(
1235
    const FunctionCallbackInfo<Value>& args) {
1236
  KeyObjectHandle* key;
1237
2710
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1238
1239
5420
  args.GetReturnValue().Set(key->GetAsymmetricKeyType());
1240
}
1241
1242
3
void KeyObjectHandle::GetSymmetricKeySize(
1243
    const FunctionCallbackInfo<Value>& args) {
1244
  KeyObjectHandle* key;
1245
3
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1246
6
  args.GetReturnValue().Set(
1247
3
      static_cast<uint32_t>(key->Data()->GetSymmetricKeySize()));
1248
}
1249
1250
5428
void KeyObjectHandle::Export(const FunctionCallbackInfo<Value>& args) {
1251
  KeyObjectHandle* key;
1252
5428
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1253
1254
5428
  KeyType type = key->Data()->GetKeyType();
1255
1256
  MaybeLocal<Value> result;
1257
5428
  if (type == kKeyTypeSecret) {
1258
5331
    result = key->ExportSecretKey();
1259
97
  } else if (type == kKeyTypePublic) {
1260
52
    unsigned int offset = 0;
1261
    PublicKeyEncodingConfig config =
1262
        ManagedEVPPKey::GetPublicKeyEncodingFromJs(
1263
52
            args, &offset, kKeyContextExport);
1264
52
    CHECK_EQ(offset, static_cast<unsigned int>(args.Length()));
1265
52
    result = key->ExportPublicKey(config);
1266
  } else {
1267
45
    CHECK_EQ(type, kKeyTypePrivate);
1268
45
    unsigned int offset = 0;
1269
    NonCopyableMaybe<PrivateKeyEncodingConfig> config =
1270
        ManagedEVPPKey::GetPrivateKeyEncodingFromJs(
1271
45
            args, &offset, kKeyContextExport);
1272
45
    if (config.IsEmpty())
1273
      return;
1274
45
    CHECK_EQ(offset, static_cast<unsigned int>(args.Length()));
1275
45
    result = key->ExportPrivateKey(config.Release());
1276
  }
1277
1278
5428
  if (!result.IsEmpty())
1279
16284
    args.GetReturnValue().Set(result.FromMaybe(Local<Value>()));
1280
}
1281
1282
5331
MaybeLocal<Value> KeyObjectHandle::ExportSecretKey() const {
1283
5331
  const char* buf = data_->GetSymmetricKey();
1284
5331
  unsigned int len = data_->GetSymmetricKeySize();
1285
10662
  return Buffer::Copy(env(), buf, len).FromMaybe(Local<Value>());
1286
}
1287
1288
52
MaybeLocal<Value> KeyObjectHandle::ExportPublicKey(
1289
    const PublicKeyEncodingConfig& config) const {
1290
52
  return WritePublicKey(env(), data_->GetAsymmetricKey().get(), config);
1291
}
1292
1293
45
MaybeLocal<Value> KeyObjectHandle::ExportPrivateKey(
1294
    const PrivateKeyEncodingConfig& config) const {
1295
45
  return WritePrivateKey(env(), data_->GetAsymmetricKey().get(), config);
1296
}
1297
1298
983
void KeyObjectHandle::ExportJWK(
1299
    const v8::FunctionCallbackInfo<v8::Value>& args) {
1300
983
  Environment* env = Environment::GetCurrent(args);
1301
  KeyObjectHandle* key;
1302
983
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1303
1304
983
  CHECK(args[0]->IsObject());
1305
983
  CHECK(args[1]->IsBoolean());
1306
1307
1966
  ExportJWKInner(env, key->Data(), args[0], args[1]->IsTrue());
1308
1309
1966
  args.GetReturnValue().Set(args[0]);
1310
}
1311
1312
800
void NativeKeyObject::Initialize(Environment* env, Local<Object> target) {
1313
800
  SetMethod(env->context(),
1314
            target,
1315
            "createNativeKeyObjectClass",
1316
            NativeKeyObject::CreateNativeKeyObjectClass);
1317
800
}
1318
1319
5639
void NativeKeyObject::RegisterExternalReferences(
1320
    ExternalReferenceRegistry* registry) {
1321
5639
  registry->Register(NativeKeyObject::CreateNativeKeyObjectClass);
1322
5639
  registry->Register(NativeKeyObject::New);
1323
5639
}
1324
1325
9609
void NativeKeyObject::New(const FunctionCallbackInfo<Value>& args) {
1326
9609
  Environment* env = Environment::GetCurrent(args);
1327
9609
  CHECK_EQ(args.Length(), 1);
1328
9609
  CHECK(args[0]->IsObject());
1329
19218
  KeyObjectHandle* handle = Unwrap<KeyObjectHandle>(args[0].As<Object>());
1330
9609
  new NativeKeyObject(env, args.This(), handle->Data());
1331
9609
}
1332
1333
800
void NativeKeyObject::CreateNativeKeyObjectClass(
1334
    const FunctionCallbackInfo<Value>& args) {
1335
800
  Environment* env = Environment::GetCurrent(args);
1336
800
  Isolate* isolate = env->isolate();
1337
1338
800
  CHECK_EQ(args.Length(), 1);
1339
800
  Local<Value> callback = args[0];
1340
800
  CHECK(callback->IsFunction());
1341
1342
  Local<FunctionTemplate> t =
1343
800
      NewFunctionTemplate(isolate, NativeKeyObject::New);
1344
1600
  t->InstanceTemplate()->SetInternalFieldCount(
1345
      KeyObjectHandle::kInternalFieldCount);
1346
800
  t->Inherit(BaseObject::GetConstructorTemplate(env));
1347
1348
  Local<Value> ctor;
1349
1600
  if (!t->GetFunction(env->context()).ToLocal(&ctor))
1350
    return;
1351
1352
1600
  Local<Value> recv = Undefined(env->isolate());
1353
  Local<Value> ret_v;
1354
800
  if (!callback.As<Function>()->Call(
1355
1600
          env->context(), recv, 1, &ctor).ToLocal(&ret_v)) {
1356
    return;
1357
  }
1358
800
  Local<Array> ret = ret_v.As<Array>();
1359
1600
  if (!ret->Get(env->context(), 1).ToLocal(&ctor)) return;
1360
800
  env->set_crypto_key_object_secret_constructor(ctor.As<Function>());
1361
1600
  if (!ret->Get(env->context(), 2).ToLocal(&ctor)) return;
1362
800
  env->set_crypto_key_object_public_constructor(ctor.As<Function>());
1363
1600
  if (!ret->Get(env->context(), 3).ToLocal(&ctor)) return;
1364
800
  env->set_crypto_key_object_private_constructor(ctor.As<Function>());
1365
1600
  args.GetReturnValue().Set(ret);
1366
}
1367
1368
11
BaseObjectPtr<BaseObject> NativeKeyObject::KeyObjectTransferData::Deserialize(
1369
        Environment* env,
1370
        Local<Context> context,
1371
        std::unique_ptr<worker::TransferData> self) {
1372
22
  if (context != env->context()) {
1373
3
    THROW_ERR_MESSAGE_TARGET_CONTEXT_UNAVAILABLE(env);
1374
3
    return {};
1375
  }
1376
1377
  Local<Value> handle;
1378
16
  if (!KeyObjectHandle::Create(env, data_).ToLocal(&handle))
1379
    return {};
1380
1381
  Local<Function> key_ctor;
1382
  Local<Value> arg = FIXED_ONE_BYTE_STRING(env->isolate(),
1383
8
                                           "internal/crypto/keys");
1384
8
  if (env->builtin_module_require()
1385
16
          ->Call(context, Null(env->isolate()), 1, &arg)
1386
8
          .IsEmpty()) {
1387
    return {};
1388
  }
1389

8
  switch (data_->GetKeyType()) {
1390
4
    case kKeyTypeSecret:
1391
4
      key_ctor = env->crypto_key_object_secret_constructor();
1392
4
      break;
1393
2
    case kKeyTypePublic:
1394
2
      key_ctor = env->crypto_key_object_public_constructor();
1395
2
      break;
1396
2
    case kKeyTypePrivate:
1397
2
      key_ctor = env->crypto_key_object_private_constructor();
1398
2
      break;
1399
    default:
1400
      CHECK(false);
1401
  }
1402
1403
  Local<Value> key;
1404
16
  if (!key_ctor->NewInstance(context, 1, &handle).ToLocal(&key))
1405
    return {};
1406
1407
8
  return BaseObjectPtr<BaseObject>(Unwrap<KeyObjectHandle>(key.As<Object>()));
1408
}
1409
1410
11
BaseObject::TransferMode NativeKeyObject::GetTransferMode() const {
1411
11
  return BaseObject::TransferMode::kCloneable;
1412
}
1413
1414
11
std::unique_ptr<worker::TransferData> NativeKeyObject::CloneForMessaging()
1415
    const {
1416
11
  return std::make_unique<KeyObjectTransferData>(handle_data_);
1417
}
1418
1419
265
WebCryptoKeyExportStatus PKEY_SPKI_Export(
1420
    KeyObjectData* key_data,
1421
    ByteSource* out) {
1422
265
  CHECK_EQ(key_data->GetKeyType(), kKeyTypePublic);
1423
530
  ManagedEVPPKey m_pkey = key_data->GetAsymmetricKey();
1424
530
  Mutex::ScopedLock lock(*m_pkey.mutex());
1425
530
  BIOPointer bio(BIO_new(BIO_s_mem()));
1426
265
  CHECK(bio);
1427
265
  if (!i2d_PUBKEY_bio(bio.get(), m_pkey.get()))
1428
    return WebCryptoKeyExportStatus::FAILED;
1429
1430
265
  *out = ByteSource::FromBIO(bio);
1431
265
  return WebCryptoKeyExportStatus::OK;
1432
}
1433
1434
283
WebCryptoKeyExportStatus PKEY_PKCS8_Export(
1435
    KeyObjectData* key_data,
1436
    ByteSource* out) {
1437
283
  CHECK_EQ(key_data->GetKeyType(), kKeyTypePrivate);
1438
566
  ManagedEVPPKey m_pkey = key_data->GetAsymmetricKey();
1439
566
  Mutex::ScopedLock lock(*m_pkey.mutex());
1440
1441
566
  BIOPointer bio(BIO_new(BIO_s_mem()));
1442
283
  CHECK(bio);
1443
566
  PKCS8Pointer p8inf(EVP_PKEY2PKCS8(m_pkey.get()));
1444
283
  if (!i2d_PKCS8_PRIV_KEY_INFO_bio(bio.get(), p8inf.get()))
1445
    return WebCryptoKeyExportStatus::FAILED;
1446
1447
283
  *out = ByteSource::FromBIO(bio);
1448
283
  return WebCryptoKeyExportStatus::OK;
1449
}
1450
1451
namespace Keys {
1452
800
void Initialize(Environment* env, Local<Object> target) {
1453
800
  target->Set(env->context(),
1454
              FIXED_ONE_BYTE_STRING(env->isolate(), "KeyObjectHandle"),
1455
3200
              KeyObjectHandle::Initialize(env)).Check();
1456
1457
2400
  NODE_DEFINE_CONSTANT(target, kWebCryptoKeyFormatRaw);
1458
2400
  NODE_DEFINE_CONSTANT(target, kWebCryptoKeyFormatPKCS8);
1459
2400
  NODE_DEFINE_CONSTANT(target, kWebCryptoKeyFormatSPKI);
1460
2400
  NODE_DEFINE_CONSTANT(target, kWebCryptoKeyFormatJWK);
1461
1462
2400
  NODE_DEFINE_CONSTANT(target, EVP_PKEY_ED25519);
1463
2400
  NODE_DEFINE_CONSTANT(target, EVP_PKEY_ED448);
1464
2400
  NODE_DEFINE_CONSTANT(target, EVP_PKEY_X25519);
1465
2400
  NODE_DEFINE_CONSTANT(target, EVP_PKEY_X448);
1466
2400
  NODE_DEFINE_CONSTANT(target, kKeyEncodingPKCS1);
1467
2400
  NODE_DEFINE_CONSTANT(target, kKeyEncodingPKCS8);
1468
2400
  NODE_DEFINE_CONSTANT(target, kKeyEncodingSPKI);
1469
2400
  NODE_DEFINE_CONSTANT(target, kKeyEncodingSEC1);
1470
2400
  NODE_DEFINE_CONSTANT(target, kKeyFormatDER);
1471
2400
  NODE_DEFINE_CONSTANT(target, kKeyFormatPEM);
1472
2400
  NODE_DEFINE_CONSTANT(target, kKeyFormatJWK);
1473
2400
  NODE_DEFINE_CONSTANT(target, kKeyTypeSecret);
1474
2400
  NODE_DEFINE_CONSTANT(target, kKeyTypePublic);
1475
2400
  NODE_DEFINE_CONSTANT(target, kKeyTypePrivate);
1476
2400
  NODE_DEFINE_CONSTANT(target, kSigEncDER);
1477
1600
  NODE_DEFINE_CONSTANT(target, kSigEncP1363);
1478
800
}
1479
1480
5639
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
1481
5639
  KeyObjectHandle::RegisterExternalReferences(registry);
1482
5639
}
1483
}  // namespace Keys
1484
1485
}  // namespace crypto
1486
}  // namespace node