GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: crypto/crypto_keys.cc Lines: 721 818 88.1 %
Date: 2022-08-12 04:19:25 Branches: 341 567 60.1 %

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
4822
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

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

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

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

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



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

4479
      CHECK(args[*offset + 1]->IsNullOrUndefined());
71
1493
      config->type_ = Nothing<PKEncodingType>();
72
    }
73
  }
74
75
4822
  *offset += 2;
76
4822
}
77
78
3238
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
3238
    MarkPopErrorOnReturn mark_pop_error_on_return;
90
3238
    if (PEM_bytes_read_bio(&der_data, &der_len, nullptr, name,
91
3238
                           bp.get(), nullptr, nullptr) != 1)
92
2271
      return ParseKeyResult::kParseKeyNotRecognized;
93
  }
94
95
  // OpenSSL might modify the pointer, so we need to make a copy before parsing.
96
967
  const unsigned char* p = der_data;
97
967
  pkey->reset(parse(&p, der_len));
98
967
  OPENSSL_clear_free(der_data, der_len);
99
100
967
  return *pkey ? ParseKeyResult::kParseKeyOk :
101
1934
                 ParseKeyResult::kParseKeyFailed;
102
}
103
104
1229
ParseKeyResult ParsePublicKeyPEM(EVPKeyPointer* pkey,
105
                                 const char* key_pem,
106
                                 int key_pem_len) {
107
2458
  BIOPointer bp(BIO_new_mem_buf(const_cast<char*>(key_pem), key_pem_len));
108
1229
  if (!bp)
109
    return ParseKeyResult::kParseKeyFailed;
110
111
  ParseKeyResult ret;
112
113
  // Try parsing as a SubjectPublicKeyInfo first.
114
1229
  ret = TryParsePublicKey(pkey, bp, "PUBLIC KEY",
115
217
      [](const unsigned char** p, long l) {  // NOLINT(runtime/int)
116
217
        return d2i_PUBKEY(nullptr, p, l);
117
      });
118
1229
  if (ret != ParseKeyResult::kParseKeyNotRecognized)
119
217
    return ret;
120
121
  // Maybe it is PKCS#1.
122
1012
  CHECK(BIO_reset(bp.get()));
123
1012
  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
1012
  if (ret != ParseKeyResult::kParseKeyNotRecognized)
128
15
    return ret;
129
130
  // X.509 fallback.
131
997
  CHECK(BIO_reset(bp.get()));
132
1994
  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
997
      });
137
}
138
139
900
ParseKeyResult ParsePublicKey(EVPKeyPointer* pkey,
140
                              const PublicKeyEncodingConfig& config,
141
                              const char* key,
142
                              size_t key_len) {
143
900
  if (config.format_ == kKeyFormatPEM) {
144
    return ParsePublicKeyPEM(pkey, key, key_len);
145
  } else {
146
900
    CHECK_EQ(config.format_, kKeyFormatDER);
147
148
900
    const unsigned char* p = reinterpret_cast<const unsigned char*>(key);
149
1800
    if (config.type_.ToChecked() == kKeyEncodingPKCS1) {
150
22
      pkey->reset(d2i_PublicKey(EVP_PKEY_RSA, nullptr, &p, key_len));
151
    } else {
152
1756
      CHECK_EQ(config.type_.ToChecked(), kKeyEncodingSPKI);
153
878
      pkey->reset(d2i_PUBKEY(nullptr, &p, key_len));
154
    }
155
156
900
    return *pkey ? ParseKeyResult::kParseKeyOk :
157
1800
                   ParseKeyResult::kParseKeyFailed;
158
  }
159
}
160
161
977
bool IsASN1Sequence(const unsigned char* data, size_t size,
162
                    size_t* data_offset, size_t* data_size) {
163

977
  if (size < 2 || data[0] != 0x30)
164
    return false;
165
166
977
  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
47
    *data_offset = 2;
179
47
    *data_size = std::min<size_t>(size - 2, data[1]);
180
  }
181
182
977
  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
943
bool IsEncryptedPrivateKeyInfo(const unsigned char* data, size_t size) {
203
  // Both PrivateKeyInfo and EncryptedPrivateKeyInfo start with a SEQUENCE.
204
  size_t offset, len;
205
943
  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
1886
  return len >= 1 &&
211
1886
         data[offset] != 2;
212
}
213
214
1460
ParseKeyResult ParsePrivateKey(EVPKeyPointer* pkey,
215
                               const PrivateKeyEncodingConfig& config,
216
                               const char* key,
217
                               size_t key_len) {
218
1460
  const ByteSource* passphrase = config.passphrase_.get();
219
220
1460
  if (config.format_ == kKeyFormatPEM) {
221
504
    BIOPointer bio(BIO_new_mem_buf(key, key_len));
222
504
    if (!bio)
223
      return ParseKeyResult::kParseKeyFailed;
224
225
504
    pkey->reset(PEM_read_bio_PrivateKey(bio.get(),
226
                                        nullptr,
227
                                        PasswordCallback,
228
                                        &passphrase));
229
  } else {
230
956
    CHECK_EQ(config.format_, kKeyFormatDER);
231
232
1912
    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
1886
    } else if (config.type_.ToChecked() == kKeyEncodingPKCS8) {
236
943
      BIOPointer bio(BIO_new_mem_buf(key, key_len));
237
943
      if (!bio)
238
        return ParseKeyResult::kParseKeyFailed;
239
240
943
      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
1852
        PKCS8Pointer p8inf(d2i_PKCS8_PRIV_KEY_INFO_bio(bio.get(), nullptr));
248
926
        if (p8inf)
249
926
          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
1460
  unsigned long err = ERR_peek_error();  // NOLINT(runtime/int)
260
1460
  if (err != 0)
261
21
    pkey->reset();
262
263
1460
  if (*pkey)
264
1439
    return ParseKeyResult::kParseKeyOk;
265

23
  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
19
  return ParseKeyResult::kParseKeyFailed;
271
}
272
273
130
MaybeLocal<Value> BIOToStringOrBuffer(
274
    Environment* env,
275
    BIO* bio,
276
    PKFormatType format) {
277
  BUF_MEM* bptr;
278
130
  BIO_get_mem_ptr(bio, &bptr);
279
130
  if (format == kKeyFormatPEM) {
280
    // PEM is an ASCII format, so we will return it as a string.
281
156
    return String::NewFromUtf8(env->isolate(), bptr->data,
282
                               NewStringType::kNormal,
283
156
                               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
62
MaybeLocal<Value> WritePrivateKey(
294
    Environment* env,
295
    EVP_PKEY* pkey,
296
    const PrivateKeyEncodingConfig& config) {
297
124
  BIOPointer bio(BIO_new(BIO_s_mem()));
298
62
  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
62
  char* pass = nullptr;
307
62
  size_t pass_len = 0;
308
62
  if (!config.passphrase_.IsEmpty()) {
309
12
    pass = const_cast<char*>(config.passphrase_->data<char>());
310
12
    pass_len = config.passphrase_->size();
311
12
    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
  bool err;
323
324
62
  PKEncodingType encoding_type = config.type_.ToChecked();
325
62
  if (encoding_type == kKeyEncodingPKCS1) {
326
    // PKCS#1 is only permitted for RSA keys.
327
12
    CHECK_EQ(EVP_PKEY_id(pkey), EVP_PKEY_RSA);
328
329
24
    RSAPointer rsa(EVP_PKEY_get1_RSA(pkey));
330
12
    if (config.format_ == kKeyFormatPEM) {
331
      // Encode PKCS#1 as PEM.
332
11
      err = PEM_write_bio_RSAPrivateKey(
333
11
                bio.get(), rsa.get(),
334
11
                config.cipher_,
335
                reinterpret_cast<unsigned char*>(pass),
336
                pass_len,
337
                nullptr, nullptr) != 1;
338
    } else {
339
      // Encode PKCS#1 as DER. This does not permit encryption.
340
1
      CHECK_EQ(config.format_, kKeyFormatDER);
341
1
      CHECK_NULL(config.cipher_);
342
1
      err = i2d_RSAPrivateKey_bio(bio.get(), rsa.get()) != 1;
343
    }
344
50
  } else if (encoding_type == kKeyEncodingPKCS8) {
345
46
    if (config.format_ == kKeyFormatPEM) {
346
      // Encode PKCS#8 as PEM.
347
23
      err = PEM_write_bio_PKCS8PrivateKey(
348
                bio.get(), pkey,
349
23
                config.cipher_,
350
                pass,
351
                pass_len,
352
                nullptr, nullptr) != 1;
353
    } else {
354
      // Encode PKCS#8 as DER.
355
23
      CHECK_EQ(config.format_, kKeyFormatDER);
356
23
      err = i2d_PKCS8PrivateKey_bio(
357
                bio.get(), pkey,
358
23
                config.cipher_,
359
                pass,
360
                pass_len,
361
                nullptr, nullptr) != 1;
362
    }
363
  } else {
364
4
    CHECK_EQ(encoding_type, kKeyEncodingSEC1);
365
366
    // SEC1 is only permitted for EC keys.
367
4
    CHECK_EQ(EVP_PKEY_id(pkey), EVP_PKEY_EC);
368
369
8
    ECKeyPointer ec_key(EVP_PKEY_get1_EC_KEY(pkey));
370
4
    if (config.format_ == kKeyFormatPEM) {
371
      // Encode SEC1 as PEM.
372
4
      err = PEM_write_bio_ECPrivateKey(
373
4
                bio.get(), ec_key.get(),
374
4
                config.cipher_,
375
                reinterpret_cast<unsigned char*>(pass),
376
                pass_len,
377
                nullptr, nullptr) != 1;
378
    } else {
379
      // Encode SEC1 as DER. This does not permit encryption.
380
      CHECK_EQ(config.format_, kKeyFormatDER);
381
      CHECK_NULL(config.cipher_);
382
      err = i2d_ECPrivateKey_bio(bio.get(), ec_key.get()) != 1;
383
    }
384
  }
385
386
62
  if (err) {
387
    ThrowCryptoError(env, ERR_get_error(), "Failed to encode private key");
388
    return MaybeLocal<Value>();
389
  }
390
62
  return BIOToStringOrBuffer(env, bio.get(), config.format_);
391
}
392
393
72
bool WritePublicKeyInner(EVP_PKEY* pkey,
394
                         const BIOPointer& bio,
395
                         const PublicKeyEncodingConfig& config) {
396
144
  if (config.type_.ToChecked() == kKeyEncodingPKCS1) {
397
    // PKCS#1 is only valid for RSA keys.
398
13
    CHECK_EQ(EVP_PKEY_id(pkey), EVP_PKEY_RSA);
399
26
    RSAPointer rsa(EVP_PKEY_get1_RSA(pkey));
400
13
    if (config.format_ == kKeyFormatPEM) {
401
      // Encode PKCS#1 as PEM.
402
7
      return PEM_write_bio_RSAPublicKey(bio.get(), rsa.get()) == 1;
403
    } else {
404
      // Encode PKCS#1 as DER.
405
6
      CHECK_EQ(config.format_, kKeyFormatDER);
406
6
      return i2d_RSAPublicKey_bio(bio.get(), rsa.get()) == 1;
407
    }
408
  } else {
409
118
    CHECK_EQ(config.type_.ToChecked(), kKeyEncodingSPKI);
410
59
    if (config.format_ == kKeyFormatPEM) {
411
      // Encode SPKI as PEM.
412
33
      return PEM_write_bio_PUBKEY(bio.get(), pkey) == 1;
413
    } else {
414
      // Encode SPKI as DER.
415
26
      CHECK_EQ(config.format_, kKeyFormatDER);
416
26
      return i2d_PUBKEY_bio(bio.get(), pkey) == 1;
417
    }
418
  }
419
}
420
421
72
MaybeLocal<Value> WritePublicKey(Environment* env,
422
                                 EVP_PKEY* pkey,
423
                                 const PublicKeyEncodingConfig& config) {
424
144
  BIOPointer bio(BIO_new(BIO_s_mem()));
425
72
  CHECK(bio);
426
427
72
  if (!WritePublicKeyInner(pkey, bio, config)) {
428
4
    ThrowCryptoError(env, ERR_get_error(), "Failed to encode public key");
429
4
    return MaybeLocal<Value>();
430
  }
431
68
  return BIOToStringOrBuffer(env, bio.get(), config.format_);
432
}
433
434
291
Maybe<bool> ExportJWKSecretKey(
435
    Environment* env,
436
    std::shared_ptr<KeyObjectData> key,
437
    Local<Object> target) {
438
291
  CHECK_EQ(key->GetKeyType(), kKeyTypeSecret);
439
440
  Local<Value> error;
441
  Local<Value> raw;
442
  MaybeLocal<Value> key_data =
443
      StringBytes::Encode(
444
          env->isolate(),
445
          key->GetSymmetricKey(),
446
          key->GetSymmetricKeySize(),
447
          BASE64URL,
448
291
          &error);
449
291
  if (key_data.IsEmpty()) {
450
    CHECK(!error.IsEmpty());
451
    env->isolate()->ThrowException(error);
452
    return Nothing<bool>();
453
  }
454
291
  if (!key_data.ToLocal(&raw))
455
    return Nothing<bool>();
456
457
582
  if (target->Set(
458
          env->context(),
459
          env->jwk_kty_string(),
460
1455
          env->jwk_oct_string()).IsNothing() ||
461
291
      target->Set(
462
          env->context(),
463
          env->jwk_k_string(),
464

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

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

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

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

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

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

6802
    if (IsAnyByteSource(args[*offset])) {
708

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


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


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


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

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

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

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

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

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

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


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


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

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