GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: crypto/crypto_keys.cc Lines: 718 815 88.1 %
Date: 2022-06-23 04:15:39 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::Just;
28
using v8::Local;
29
using v8::Maybe;
30
using v8::MaybeLocal;
31
using v8::NewStringType;
32
using v8::Nothing;
33
using v8::Number;
34
using v8::Object;
35
using v8::String;
36
using v8::Uint32;
37
using v8::Undefined;
38
using v8::Value;
39
40
namespace crypto {
41
namespace {
42
4010
void GetKeyFormatAndTypeFromJs(
43
    AsymmetricKeyEncodingConfig* config,
44
    const FunctionCallbackInfo<Value>& args,
45
    unsigned int* offset,
46
    KeyEncodingContext context) {
47
  // During key pair generation, it is possible not to specify a key encoding,
48
  // which will lead to a key object being returned.
49

12030
  if (args[*offset]->IsUndefined()) {
50
524
    CHECK_EQ(context, kKeyContextGenerate);
51

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

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

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



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

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

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

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

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

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

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

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

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

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

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

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

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

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


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


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


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

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

5648
  if (IsAnyByteSource(args[*offset])) {
764
2198
    Environment* env = Environment::GetCurrent(args);
765
6594
    ArrayBufferOrViewContents<char> data(args[(*offset)++]);
766
2198
    if (UNLIKELY(!data.CheckSizeInt32())) {
767
      THROW_ERR_OUT_OF_RANGE(env, "keyData is too big");
768
      return ManagedEVPPKey();
769
    }
770
    NonCopyableMaybe<PrivateKeyEncodingConfig> config_ =
771
4396
        GetPrivateKeyEncodingFromJs(args, offset, kKeyContextInput);
772
2198
    if (config_.IsEmpty())
773
      return ManagedEVPPKey();
774
775
    ParseKeyResult ret;
776
4396
    PrivateKeyEncodingConfig config = config_.Release();
777
2198
    EVPKeyPointer pkey;
778
2198
    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
1229
      ret = ParsePublicKeyPEM(&pkey, data.data(), data.size());
782
1229
      if (ret == ParseKeyResult::kParseKeyNotRecognized) {
783
262
        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

969
      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
878
        case kKeyEncodingSPKI:
795
878
          is_public = true;
796
878
          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
969
      if (is_public) {
806
900
        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
2198
        env, std::move(pkey), ret, "Failed to read asymmetric key");
814
  } else {
815

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

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

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


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


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

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