GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/crypto/crypto_keys.cc Lines: 580 691 83.9 %
Date: 2020-12-12 04:11:07 Branches: 284 483 58.8 %

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_ecdh.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
2186
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
8744
  if (args[*offset]->IsUndefined()) {
50
237
    CHECK_EQ(context, kKeyContextGenerate);
51
948
    CHECK(args[*offset + 1]->IsUndefined());
52
237
    config->output_key_object_ = true;
53
  } else {
54
1949
    config->output_key_object_ = false;
55
56
5847
    CHECK(args[*offset]->IsInt32());
57
1949
    config->format_ = static_cast<PKFormatType>(
58
9745
        args[*offset].As<Int32>()->Value());
59
60
5847
    if (args[*offset + 1]->IsInt32()) {
61
1394
      config->type_ = Just<PKEncodingType>(static_cast<PKEncodingType>(
62
4182
          args[*offset + 1].As<Int32>()->Value()));
63
    } else {
64

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

345
  if (size < 2 || data[0] != 0x30)
159
    return false;
160
161
345
  if (data[1] & 0x80) {
162
    // Long form.
163
325
    size_t n_bytes = data[1] & ~0x80;
164

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

74
         data[offset + 1] == 1 &&
194
42
         !(data[offset + 2] & 0xfe);
195
}
196
197
313
bool IsEncryptedPrivateKeyInfo(const unsigned char* data, size_t size) {
198
  // Both PrivateKeyInfo and EncryptedPrivateKeyInfo start with a SEQUENCE.
199
  size_t offset, len;
200
313
  if (!IsASN1Sequence(data, size, &offset, &len))
201
    return false;
202
203
  // A PrivateKeyInfo sequence always starts with an integer whereas an
204
  // EncryptedPrivateKeyInfo starts with an AlgorithmIdentifier.
205

626
  return len >= 1 &&
206
626
         data[offset] != 2;
207
}
208
209
700
ParseKeyResult ParsePrivateKey(EVPKeyPointer* pkey,
210
                               const PrivateKeyEncodingConfig& config,
211
                               const char* key,
212
                               size_t key_len) {
213
700
  const ByteSource* passphrase = config.passphrase_.get();
214
215
700
  if (config.format_ == kKeyFormatPEM) {
216
752
    BIOPointer bio(BIO_new_mem_buf(key, key_len));
217
376
    if (!bio)
218
      return ParseKeyResult::kParseKeyFailed;
219
220
376
    pkey->reset(PEM_read_bio_PrivateKey(bio.get(),
221
                                        nullptr,
222
                                        PasswordCallback,
223
376
                                        &passphrase));
224
  } else {
225
324
    CHECK_EQ(config.format_, kKeyFormatDER);
226
227
648
    if (config.type_.ToChecked() == kKeyEncodingPKCS1) {
228
11
      const unsigned char* p = reinterpret_cast<const unsigned char*>(key);
229
11
      pkey->reset(d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &p, key_len));
230
626
    } else if (config.type_.ToChecked() == kKeyEncodingPKCS8) {
231
626
      BIOPointer bio(BIO_new_mem_buf(key, key_len));
232
313
      if (!bio)
233
        return ParseKeyResult::kParseKeyFailed;
234
235
313
      if (IsEncryptedPrivateKeyInfo(
236
              reinterpret_cast<const unsigned char*>(key), key_len)) {
237
17
        pkey->reset(d2i_PKCS8PrivateKey_bio(bio.get(),
238
                                            nullptr,
239
                                            PasswordCallback,
240
17
                                            &passphrase));
241
      } else {
242
592
        PKCS8Pointer p8inf(d2i_PKCS8_PRIV_KEY_INFO_bio(bio.get(), nullptr));
243
296
        if (p8inf)
244
296
          pkey->reset(EVP_PKCS82PKEY(p8inf.get()));
245
      }
246
    } else {
247
      CHECK_EQ(config.type_.ToChecked(), kKeyEncodingSEC1);
248
      const unsigned char* p = reinterpret_cast<const unsigned char*>(key);
249
      pkey->reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &p, key_len));
250
    }
251
  }
252
253
  // OpenSSL can fail to parse the key but still return a non-null pointer.
254
700
  unsigned long err = ERR_peek_error();  // NOLINT(runtime/int)
255
700
  if (err != 0)
256
22
    pkey->reset();
257
258
700
  if (*pkey)
259
678
    return ParseKeyResult::kParseKeyOk;
260

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

469
          env->jwk_oct_string()).IsNothing() ||
456
134
      target->Set(
457
          env->context(),
458
          env->jwk_k_string(),
459
335
          raw).IsNothing()) {
460
    return Nothing<bool>();
461
  }
462
463
67
  return Just(true);
464
}
465
466
20
std::shared_ptr<KeyObjectData> ImportJWKSecretKey(
467
    Environment* env,
468
    Local<Object> jwk) {
469
  Local<Value> key;
470

100
  if (!jwk->Get(env->context(), env->jwk_k_string()).ToLocal(&key) ||
471
40
      !key->IsString()) {
472
    THROW_ERR_CRYPTO_INVALID_JWK(env, "Invalid JWK secret key format");
473
    return std::shared_ptr<KeyObjectData>();
474
  }
475
476
40
  ByteSource key_data = ByteSource::FromEncodedString(env, key.As<String>());
477
20
  if (key_data.size() > INT_MAX) {
478
    THROW_ERR_CRYPTO_INVALID_KEYLEN(env);
479
    return std::shared_ptr<KeyObjectData>();
480
  }
481
482
20
  return KeyObjectData::CreateSecret(std::move(key_data));
483
}
484
485
230
Maybe<bool> ExportJWKAsymmetricKey(
486
    Environment* env,
487
    std::shared_ptr<KeyObjectData> key,
488
    Local<Object> target) {
489

230
  switch (EVP_PKEY_id(key->GetAsymmetricKey().get())) {
490
    case EVP_PKEY_RSA:
491
      // Fall through
492
152
    case EVP_PKEY_RSA_PSS: return ExportJWKRsaKey(env, key, target);
493
8
    case EVP_PKEY_DSA: return ExportJWKDsaKey(env, key, target);
494
70
    case EVP_PKEY_EC: return ExportJWKEcKey(env, key, target);
495
  }
496
  THROW_ERR_CRYPTO_INVALID_KEYTYPE(env);
497
  return Just(false);
498
}
499
500
254
std::shared_ptr<KeyObjectData> ImportJWKAsymmetricKey(
501
    Environment* env,
502
    Local<Object> jwk,
503
    const char* kty,
504
    const FunctionCallbackInfo<Value>& args,
505
    unsigned int offset) {
506
254
  if (strcmp(kty, "RSA") == 0) {
507
170
    return ImportJWKRsaKey(env, jwk, args, offset);
508
84
  } else if (strcmp(kty, "DSA") == 0) {
509
16
    return ImportJWKDsaKey(env, jwk, args, offset);
510
68
  } else if (strcmp(kty, "EC") == 0) {
511
68
    return ImportJWKEcKey(env, jwk, args, offset);
512
  }
513
514
  char msg[1024];
515
  snprintf(msg, sizeof(msg), "%s is not a support JWK key type", kty);
516
  THROW_ERR_CRYPTO_INVALID_JWK(env, msg);
517
  return std::shared_ptr<KeyObjectData>();
518
}
519
520
1499
Maybe<bool> GetSecretKeyDetail(
521
    Environment* env,
522
    std::shared_ptr<KeyObjectData> key,
523
    Local<Object> target) {
524
  // For the secret key detail, all we care about is the length,
525
  // converted to bits.
526
527
1499
  size_t length = key->GetSymmetricKeySize() * CHAR_BIT;
528
  return target->Set(
529
      env->context(),
530
      env->length_string(),
531
5996
      Number::New(env->isolate(), length));
532
}
533
534
830
Maybe<bool> GetAsymmetricKeyDetail(
535
  Environment* env,
536
  std::shared_ptr<KeyObjectData> key,
537
  Local<Object> target) {
538

830
  switch (EVP_PKEY_id(key->GetAsymmetricKey().get())) {
539
    case EVP_PKEY_RSA:
540
      // Fall through
541
601
    case EVP_PKEY_RSA_PSS: return GetRsaKeyDetail(env, key, target);
542
56
    case EVP_PKEY_DSA: return GetDsaKeyDetail(env, key, target);
543
170
    case EVP_PKEY_EC: return GetEcKeyDetail(env, key, target);
544
3
    case EVP_PKEY_DH: return GetDhKeyDetail(env, key, target);
545
  }
546
  THROW_ERR_CRYPTO_INVALID_KEYTYPE(env);
547
  return Nothing<bool>();
548
}
549
}  // namespace
550
551
2277
ManagedEVPPKey::ManagedEVPPKey(EVPKeyPointer&& pkey) : pkey_(std::move(pkey)) {}
552
553
5430
ManagedEVPPKey::ManagedEVPPKey(const ManagedEVPPKey& that) {
554
5430
  *this = that;
555
5428
}
556
557
6191
ManagedEVPPKey& ManagedEVPPKey::operator=(const ManagedEVPPKey& that) {
558
6191
  pkey_.reset(that.get());
559
560
6188
  if (pkey_)
561
6044
    EVP_PKEY_up_ref(pkey_.get());
562
563
6189
  return *this;
564
}
565
566
3403
ManagedEVPPKey::operator bool() const {
567
3403
  return !!pkey_;
568
}
569
570
16042
EVP_PKEY* ManagedEVPPKey::get() const {
571
16042
  return pkey_.get();
572
}
573
574
void ManagedEVPPKey::MemoryInfo(MemoryTracker* tracker) const {
575
  tracker->TrackFieldWithSize("pkey",
576
                              !pkey_ ? 0 : kSizeOf_EVP_PKEY +
577
                              size_of_private_key() +
578
                              size_of_public_key());
579
}
580
581
size_t ManagedEVPPKey::size_of_private_key() const {
582
  size_t len = 0;
583
  return (pkey_ && EVP_PKEY_get_raw_private_key(
584
      pkey_.get(), nullptr, &len) == 1) ? len : 0;
585
}
586
587
size_t ManagedEVPPKey::size_of_public_key() const {
588
  size_t len = 0;
589
  return (pkey_ && EVP_PKEY_get_raw_public_key(
590
      pkey_.get(), nullptr, &len) == 1) ? len : 0;
591
}
592
593
135
Maybe<bool> ManagedEVPPKey::ToEncodedPublicKey(
594
    Environment* env,
595
    ManagedEVPPKey key,
596
    const PublicKeyEncodingConfig& config,
597
    Local<Value>* out) {
598
135
  if (!key) return Nothing<bool>();
599
135
  if (config.output_key_object_) {
600
    // Note that this has the downside of containing sensitive data of the
601
    // private key.
602
    std::shared_ptr<KeyObjectData> data =
603
238
          KeyObjectData::CreateAsymmetric(kKeyTypePublic, std::move(key));
604
238
    return Just(KeyObjectHandle::Create(env, data).ToLocal(out));
605
  }
606
32
  return Just(WritePublicKey(env, key.get(), config).ToLocal(out));
607
}
608
609
135
Maybe<bool> ManagedEVPPKey::ToEncodedPrivateKey(
610
    Environment* env,
611
    ManagedEVPPKey key,
612
    const PrivateKeyEncodingConfig& config,
613
    Local<Value>* out) {
614
135
  if (!key) return Nothing<bool>();
615
135
  if (config.output_key_object_) {
616
    std::shared_ptr<KeyObjectData> data =
617
234
        KeyObjectData::CreateAsymmetric(kKeyTypePrivate, std::move(key));
618
234
    return Just(KeyObjectHandle::Create(env, data).ToLocal(out));
619
  }
620
621
36
  return Just(WritePrivateKey(env, key.get(), config).ToLocal(out));
622
}
623
624
NonCopyableMaybe<PrivateKeyEncodingConfig>
625
2035
ManagedEVPPKey::GetPrivateKeyEncodingFromJs(
626
    const FunctionCallbackInfo<Value>& args,
627
    unsigned int* offset,
628
    KeyEncodingContext context) {
629
2035
  Environment* env = Environment::GetCurrent(args);
630
631
4070
  PrivateKeyEncodingConfig result;
632
2035
  GetKeyFormatAndTypeFromJs(&result, args, offset, context);
633
634
2035
  if (result.output_key_object_) {
635
117
    if (context != kKeyContextInput)
636
117
      (*offset)++;
637
  } else {
638
1918
    bool needs_passphrase = false;
639
1918
    if (context != kKeyContextInput) {
640
124
      if (args[*offset]->IsString()) {
641
32
        Utf8Value cipher_name(env->isolate(), args[*offset]);
642
11
        result.cipher_ = EVP_get_cipherbyname(*cipher_name);
643
11
        if (result.cipher_ == nullptr) {
644
1
          THROW_ERR_CRYPTO_UNKNOWN_CIPHER(env);
645
1
          return NonCopyableMaybe<PrivateKeyEncodingConfig>();
646
        }
647
10
        needs_passphrase = true;
648
      } else {
649
80
        CHECK(args[*offset]->IsNullOrUndefined());
650
20
        result.cipher_ = nullptr;
651
      }
652
30
      (*offset)++;
653
    }
654
655
3834
    if (IsAnyByteSource(args[*offset])) {
656

94
      CHECK_IMPLIES(context != kKeyContextInput, result.cipher_ != nullptr);
657
282
      ArrayBufferOrViewContents<char> passphrase(args[*offset]);
658
94
      if (UNLIKELY(!passphrase.CheckSizeInt32())) {
659
        THROW_ERR_OUT_OF_RANGE(env, "passphrase is too big");
660
        return NonCopyableMaybe<PrivateKeyEncodingConfig>();
661
      }
662
188
      result.passphrase_ = NonCopyableMaybe<ByteSource>(
663
282
          passphrase.ToNullTerminatedCopy());
664
    } else {
665

7292
      CHECK(args[*offset]->IsNullOrUndefined() && !needs_passphrase);
666
    }
667
  }
668
669
2034
  (*offset)++;
670
2034
  return NonCopyableMaybe<PrivateKeyEncodingConfig>(std::move(result));
671
}
672
673
151
PublicKeyEncodingConfig ManagedEVPPKey::GetPublicKeyEncodingFromJs(
674
    const FunctionCallbackInfo<Value>& args,
675
    unsigned int* offset,
676
    KeyEncodingContext context) {
677
151
  PublicKeyEncodingConfig result;
678
151
  GetKeyFormatAndTypeFromJs(&result, args, offset, context);
679
151
  return result;
680
}
681
682
506
ManagedEVPPKey ManagedEVPPKey::GetPrivateKeyFromJs(
683
    const FunctionCallbackInfo<Value>& args,
684
    unsigned int* offset,
685
    bool allow_key_object) {
686

2530
  if (args[*offset]->IsString() || IsAnyByteSource(args[*offset])) {
687
473
    Environment* env = Environment::GetCurrent(args);
688
1419
    ByteSource key = ByteSource::FromStringOrBuffer(env, args[(*offset)++]);
689
    NonCopyableMaybe<PrivateKeyEncodingConfig> config =
690
946
        GetPrivateKeyEncodingFromJs(args, offset, kKeyContextInput);
691
473
    if (config.IsEmpty())
692
      return ManagedEVPPKey();
693
694
946
    EVPKeyPointer pkey;
695
    ParseKeyResult ret =
696
473
        ParsePrivateKey(&pkey, config.Release(), key.get(), key.size());
697
473
    return GetParsedKey(env, std::move(pkey), ret,
698
473
                        "Failed to read private key");
699
  } else {
700

99
    CHECK(args[*offset]->IsObject() && allow_key_object);
701
    KeyObjectHandle* key;
702
99
    ASSIGN_OR_RETURN_UNWRAP(&key, args[*offset].As<Object>(), ManagedEVPPKey());
703
33
    CHECK_EQ(key->Data()->GetKeyType(), kKeyTypePrivate);
704
33
    (*offset) += 4;
705
33
    return key->Data()->GetAsymmetricKey();
706
  }
707
}
708
709
1517
ManagedEVPPKey ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(
710
    const FunctionCallbackInfo<Value>& args,
711
    unsigned int* offset) {
712
3034
  if (IsAnyByteSource(args[*offset])) {
713
1414
    Environment* env = Environment::GetCurrent(args);
714
4242
    ArrayBufferOrViewContents<char> data(args[(*offset)++]);
715
1414
    if (UNLIKELY(!data.CheckSizeInt32())) {
716
      THROW_ERR_OUT_OF_RANGE(env, "keyData is too big");
717
      return ManagedEVPPKey();
718
    }
719
    NonCopyableMaybe<PrivateKeyEncodingConfig> config_ =
720
2828
        GetPrivateKeyEncodingFromJs(args, offset, kKeyContextInput);
721
1414
    if (config_.IsEmpty())
722
      return ManagedEVPPKey();
723
724
    ParseKeyResult ret;
725
2828
    PrivateKeyEncodingConfig config = config_.Release();
726
2828
    EVPKeyPointer pkey;
727
1414
    if (config.format_ == kKeyFormatPEM) {
728
      // For PEM, we can easily determine whether it is a public or private key
729
      // by looking for the respective PEM tags.
730
1075
      ret = ParsePublicKeyPEM(&pkey, data.data(), data.size());
731
1075
      if (ret == ParseKeyResult::kParseKeyNotRecognized) {
732
199
        ret = ParsePrivateKey(&pkey, config, data.data(), data.size());
733
      }
734
    } else {
735
      // For DER, the type determines how to parse it. SPKI, PKCS#8 and SEC1 are
736
      // easy, but PKCS#1 can be a public key or a private key.
737
      bool is_public;
738

339
      switch (config.type_.ToChecked()) {
739
        case kKeyEncodingPKCS1:
740
64
          is_public = !IsRSAPrivateKey(
741
32
              reinterpret_cast<const unsigned char*>(data.data()), data.size());
742
32
          break;
743
        case kKeyEncodingSPKI:
744
289
          is_public = true;
745
289
          break;
746
        case kKeyEncodingPKCS8:
747
        case kKeyEncodingSEC1:
748
18
          is_public = false;
749
18
          break;
750
        default:
751
          UNREACHABLE("Invalid key encoding type");
752
      }
753
754
339
      if (is_public) {
755
311
        ret = ParsePublicKey(&pkey, config, data.data(), data.size());
756
      } else {
757
28
        ret = ParsePrivateKey(&pkey, config, data.data(), data.size());
758
      }
759
    }
760
761
    return ManagedEVPPKey::GetParsedKey(
762
1414
        env, std::move(pkey), ret, "Failed to read asymmetric key");
763
  } else {
764
309
    CHECK(args[*offset]->IsObject());
765
309
    KeyObjectHandle* key = Unwrap<KeyObjectHandle>(args[*offset].As<Object>());
766
103
    CHECK_NOT_NULL(key);
767
103
    CHECK_NE(key->Data()->GetKeyType(), kKeyTypeSecret);
768
103
    (*offset) += 4;
769
103
    return key->Data()->GetAsymmetricKey();
770
  }
771
}
772
773
1887
ManagedEVPPKey ManagedEVPPKey::GetParsedKey(Environment* env,
774
                                            EVPKeyPointer&& pkey,
775
                                            ParseKeyResult ret,
776
                                            const char* default_msg) {
777
1887
  switch (ret) {
778
    case ParseKeyResult::kParseKeyOk:
779
1865
      CHECK(pkey);
780
1865
      break;
781
    case ParseKeyResult::kParseKeyNeedPassphrase:
782
      THROW_ERR_MISSING_PASSPHRASE(env,
783
11
                                   "Passphrase required for encrypted key");
784
11
      break;
785
    default:
786
11
      ThrowCryptoError(env, ERR_get_error(), default_msg);
787
  }
788
789
1887
  return ManagedEVPPKey(std::move(pkey));
790
}
791
792
1757
KeyObjectData::KeyObjectData(
793
1757
    ByteSource symmetric_key)
794
    : key_type_(KeyType::kKeyTypeSecret),
795
1757
      symmetric_key_(std::move(symmetric_key)),
796
1757
      symmetric_key_len_(symmetric_key_.size()),
797
5271
      asymmetric_key_() {}
798
799
1110
KeyObjectData::KeyObjectData(
800
    KeyType type,
801
1110
    const ManagedEVPPKey& pkey)
802
    : key_type_(type),
803
      symmetric_key_(),
804
      symmetric_key_len_(0),
805
1110
      asymmetric_key_{pkey} {}
806
807
void KeyObjectData::MemoryInfo(MemoryTracker* tracker) const {
808
  switch (GetKeyType()) {
809
    case kKeyTypeSecret:
810
      tracker->TrackFieldWithSize("symmetric_key", symmetric_key_.size());
811
      break;
812
    case kKeyTypePrivate:
813
      // Fall through
814
    case kKeyTypePublic:
815
      tracker->TrackFieldWithSize("key", asymmetric_key_);
816
      break;
817
    default:
818
      UNREACHABLE();
819
  }
820
}
821
822
std::shared_ptr<KeyObjectData> KeyObjectData::CreateSecret(
823
    const ArrayBufferOrViewContents<char>& buf) {
824
  return CreateSecret(buf.ToCopy());
825
}
826
827
1757
std::shared_ptr<KeyObjectData> KeyObjectData::CreateSecret(ByteSource key) {
828
1757
  CHECK(key);
829
1757
  return std::shared_ptr<KeyObjectData>(new KeyObjectData(std::move(key)));
830
}
831
832
1110
std::shared_ptr<KeyObjectData> KeyObjectData::CreateAsymmetric(
833
    KeyType key_type,
834
    const ManagedEVPPKey& pkey) {
835
1110
  CHECK(pkey);
836
1110
  return std::shared_ptr<KeyObjectData>(new KeyObjectData(key_type, pkey));
837
}
838
839
7312
KeyType KeyObjectData::GetKeyType() const {
840
7312
  return key_type_;
841
}
842
843
3795
ManagedEVPPKey KeyObjectData::GetAsymmetricKey() const {
844
3795
  CHECK_NE(key_type_, kKeyTypeSecret);
845
3795
  return asymmetric_key_;
846
}
847
848
3385
const char* KeyObjectData::GetSymmetricKey() const {
849
3385
  CHECK_EQ(key_type_, kKeyTypeSecret);
850
3385
  return symmetric_key_.get();
851
}
852
853
4818
size_t KeyObjectData::GetSymmetricKeySize() const {
854
4818
  CHECK_EQ(key_type_, kKeyTypeSecret);
855
4818
  return symmetric_key_len_;
856
}
857
858
982
v8::Local<v8::Function> KeyObjectHandle::Initialize(Environment* env) {
859
982
  Local<Function> templ = env->crypto_key_object_handle_constructor();
860
982
  if (!templ.IsEmpty()) {
861
326
    return templ;
862
  }
863
656
  Local<FunctionTemplate> t = env->NewFunctionTemplate(New);
864
1968
  t->InstanceTemplate()->SetInternalFieldCount(
865
656
      KeyObjectHandle::kInternalFieldCount);
866
1312
  t->Inherit(BaseObject::GetConstructorTemplate(env));
867
868
656
  env->SetProtoMethod(t, "init", Init);
869
  env->SetProtoMethodNoSideEffect(t, "getSymmetricKeySize",
870
656
                                  GetSymmetricKeySize);
871
  env->SetProtoMethodNoSideEffect(t, "getAsymmetricKeyType",
872
656
                                  GetAsymmetricKeyType);
873
656
  env->SetProtoMethod(t, "export", Export);
874
656
  env->SetProtoMethod(t, "exportJwk", ExportJWK);
875
656
  env->SetProtoMethod(t, "initECRaw", InitECRaw);
876
656
  env->SetProtoMethod(t, "initJwk", InitJWK);
877
656
  env->SetProtoMethod(t, "keyDetail", GetKeyDetail);
878
879
1968
  auto function = t->GetFunction(env->context()).ToLocalChecked();
880
656
  env->set_crypto_key_object_handle_constructor(function);
881
656
  return function;
882
}
883
884
326
MaybeLocal<Object> KeyObjectHandle::Create(
885
    Environment* env,
886
    std::shared_ptr<KeyObjectData> data) {
887
  Local<Object> obj;
888
326
  Local<Function> ctor = KeyObjectHandle::Initialize(env);
889
652
  CHECK(!env->crypto_key_object_handle_constructor().IsEmpty());
890
978
  if (!ctor->NewInstance(env->context(), 0, nullptr).ToLocal(&obj))
891
    return MaybeLocal<Object>();
892
893
326
  KeyObjectHandle* key = Unwrap<KeyObjectHandle>(obj);
894
326
  CHECK_NOT_NULL(key);
895
326
  key->data_ = data;
896
326
  return obj;
897
}
898
899
10203
const std::shared_ptr<KeyObjectData>& KeyObjectHandle::Data() {
900
10203
  return data_;
901
}
902
903
2880
void KeyObjectHandle::New(const FunctionCallbackInfo<Value>& args) {
904
2880
  CHECK(args.IsConstructCall());
905
2880
  Environment* env = Environment::GetCurrent(args);
906
2880
  new KeyObjectHandle(env, args.This());
907
2880
}
908
909
2880
KeyObjectHandle::KeyObjectHandle(Environment* env,
910
2880
                                 Local<Object> wrap)
911
2880
    : BaseObject(env, wrap) {
912
2880
  MakeWeak();
913
2880
}
914
915
2280
void KeyObjectHandle::Init(const FunctionCallbackInfo<Value>& args) {
916
  KeyObjectHandle* key;
917
2285
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
918
4555
  MarkPopErrorOnReturn mark_pop_error_on_return;
919
920
4560
  CHECK(args[0]->IsInt32());
921
6840
  KeyType type = static_cast<KeyType>(args[0].As<Uint32>()->Value());
922
923
  unsigned int offset;
924
4555
  ManagedEVPPKey pkey;
925
926

2280
  switch (type) {
927
  case kKeyTypeSecret: {
928
1655
    CHECK_EQ(args.Length(), 2);
929
3310
    ArrayBufferOrViewContents<char> buf(args[1]);
930
1655
    key->data_ = KeyObjectData::CreateSecret(buf.ToCopy());
931
1655
    break;
932
  }
933
  case kKeyTypePublic: {
934
312
    CHECK_EQ(args.Length(), 4);
935
936
312
    offset = 1;
937
312
    pkey = ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(args, &offset);
938
312
    if (!pkey)
939
      return;
940
312
    key->data_ = KeyObjectData::CreateAsymmetric(type, pkey);
941
312
    break;
942
  }
943
  case kKeyTypePrivate: {
944
313
    CHECK_EQ(args.Length(), 5);
945
946
313
    offset = 1;
947
313
    pkey = ManagedEVPPKey::GetPrivateKeyFromJs(args, &offset, false);
948
313
    if (!pkey)
949
5
      return;
950
308
    key->data_ = KeyObjectData::CreateAsymmetric(type, pkey);
951
308
    break;
952
  }
953
  default:
954
    UNREACHABLE();
955
  }
956
}
957
958
274
void KeyObjectHandle::InitJWK(const FunctionCallbackInfo<Value>& args) {
959
274
  Environment* env = Environment::GetCurrent(args);
960
  KeyObjectHandle* key;
961
274
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
962
548
  MarkPopErrorOnReturn mark_pop_error_on_return;
963
964
  // The argument must be a JavaScript object that we will inspect
965
  // to get the JWK properties from.
966
548
  CHECK(args[0]->IsObject());
967
968
  // Step one, Secret key or not?
969
548
  Local<Object> input = args[0].As<Object>();
970
971
  Local<Value> kty;
972

1370
  if (!input->Get(env->context(), env->jwk_kty_string()).ToLocal(&kty) ||
973
548
      !kty->IsString()) {
974
    return THROW_ERR_CRYPTO_INVALID_JWK(env);
975
  }
976
977
548
  Utf8Value kty_string(env->isolate(), kty);
978
979
274
  if (strcmp(*kty_string, "oct") == 0) {
980
    // Secret key
981
20
    key->data_ = ImportJWKSecretKey(env, input);
982
20
    if (!key->data_) {
983
      // ImportJWKSecretKey is responsible for throwing an appropriate error
984
      return;
985
    }
986
  } else {
987
254
    key->data_ = ImportJWKAsymmetricKey(env, input, *kty_string, args, 1);
988
254
    if (!key->data_) {
989
      // ImportJWKAsymmetricKey is responsible for throwing an appropriate error
990
      return;
991
    }
992
  }
993
994
822
  args.GetReturnValue().Set(key->data_->GetKeyType());
995
}
996
997
void KeyObjectHandle::InitECRaw(const FunctionCallbackInfo<Value>& args) {
998
  Environment* env = Environment::GetCurrent(args);
999
  KeyObjectHandle* key;
1000
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1001
1002
  CHECK(args[0]->IsString());
1003
  Utf8Value name(env->isolate(), args[0]);
1004
1005
  MarkPopErrorOnReturn mark_pop_error_on_return;
1006
1007
  int id = OBJ_txt2nid(*name);
1008
  ECKeyPointer eckey(EC_KEY_new_by_curve_name(id));
1009
  if (!eckey)
1010
    return args.GetReturnValue().Set(false);
1011
1012
  const EC_GROUP* group = EC_KEY_get0_group(eckey.get());
1013
  ECPointPointer pub(ECDH::BufferToPoint(env, group, args[1]));
1014
1015
  if (!pub ||
1016
      !eckey ||
1017
      !EC_KEY_set_public_key(eckey.get(), pub.get())) {
1018
    return args.GetReturnValue().Set(false);
1019
  }
1020
1021
  EVPKeyPointer pkey(EVP_PKEY_new());
1022
  if (!EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()))
1023
    args.GetReturnValue().Set(false);
1024
1025
  eckey.release();  // Release ownership of the key
1026
1027
  key->data_ =
1028
      KeyObjectData::CreateAsymmetric(
1029
          kKeyTypePublic,
1030
          ManagedEVPPKey(std::move(pkey)));
1031
1032
  args.GetReturnValue().Set(true);
1033
}
1034
1035
2329
void KeyObjectHandle::GetKeyDetail(const FunctionCallbackInfo<Value>& args) {
1036
2329
  Environment* env = Environment::GetCurrent(args);
1037
  KeyObjectHandle* key;
1038
2329
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1039
1040
4658
  CHECK(args[0]->IsObject());
1041
1042
4658
  std::shared_ptr<KeyObjectData> data = key->Data();
1043
1044
2329
  switch (data->GetKeyType()) {
1045
    case kKeyTypeSecret:
1046
4497
      if (GetSecretKeyDetail(env, data, args[0].As<Object>()).IsNothing())
1047
        return;
1048
1499
      break;
1049
    case kKeyTypePublic:
1050
      // Fall through
1051
    case kKeyTypePrivate:
1052
2490
      if (GetAsymmetricKeyDetail(env, data, args[0].As<Object>()).IsNothing())
1053
        return;
1054
830
      break;
1055
    default:
1056
      UNREACHABLE();
1057
  }
1058
1059
4658
  args.GetReturnValue().Set(args[0]);
1060
}
1061
1062
88
Local<Value> KeyObjectHandle::GetAsymmetricKeyType() const {
1063
176
  const ManagedEVPPKey& key = data_->GetAsymmetricKey();
1064


88
  switch (EVP_PKEY_id(key.get())) {
1065
  case EVP_PKEY_RSA:
1066
40
    return env()->crypto_rsa_string();
1067
  case EVP_PKEY_RSA_PSS:
1068
16
    return env()->crypto_rsa_pss_string();
1069
  case EVP_PKEY_DSA:
1070
4
    return env()->crypto_dsa_string();
1071
  case EVP_PKEY_DH:
1072
44
    return env()->crypto_dh_string();
1073
  case EVP_PKEY_EC:
1074
12
    return env()->crypto_ec_string();
1075
  case EVP_PKEY_ED25519:
1076
10
    return env()->crypto_ed25519_string();
1077
  case EVP_PKEY_ED448:
1078
10
    return env()->crypto_ed448_string();
1079
  case EVP_PKEY_X25519:
1080
20
    return env()->crypto_x25519_string();
1081
  case EVP_PKEY_X448:
1082
20
    return env()->crypto_x448_string();
1083
  default:
1084
    return Undefined(env()->isolate());
1085
  }
1086
}
1087
1088
88
void KeyObjectHandle::GetAsymmetricKeyType(
1089
    const FunctionCallbackInfo<Value>& args) {
1090
  KeyObjectHandle* key;
1091
88
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1092
1093
264
  args.GetReturnValue().Set(key->GetAsymmetricKeyType());
1094
}
1095
1096
1
void KeyObjectHandle::GetSymmetricKeySize(
1097
    const FunctionCallbackInfo<Value>& args) {
1098
  KeyObjectHandle* key;
1099
1
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1100
3
  args.GetReturnValue().Set(
1101
1
      static_cast<uint32_t>(key->Data()->GetSymmetricKeySize()));
1102
}
1103
1104
2459
void KeyObjectHandle::Export(const FunctionCallbackInfo<Value>& args) {
1105
  KeyObjectHandle* key;
1106
2459
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1107
1108
2459
  KeyType type = key->Data()->GetKeyType();
1109
1110
  MaybeLocal<Value> result;
1111
2459
  if (type == kKeyTypeSecret) {
1112
2434
    result = key->ExportSecretKey();
1113
25
  } else if (type == kKeyTypePublic) {
1114
14
    unsigned int offset = 0;
1115
    PublicKeyEncodingConfig config =
1116
        ManagedEVPPKey::GetPublicKeyEncodingFromJs(
1117
14
            args, &offset, kKeyContextExport);
1118
14
    CHECK_EQ(offset, static_cast<unsigned int>(args.Length()));
1119
14
    result = key->ExportPublicKey(config);
1120
  } else {
1121
11
    CHECK_EQ(type, kKeyTypePrivate);
1122
11
    unsigned int offset = 0;
1123
    NonCopyableMaybe<PrivateKeyEncodingConfig> config =
1124
        ManagedEVPPKey::GetPrivateKeyEncodingFromJs(
1125
22
            args, &offset, kKeyContextExport);
1126
11
    if (config.IsEmpty())
1127
      return;
1128
11
    CHECK_EQ(offset, static_cast<unsigned int>(args.Length()));
1129
11
    result = key->ExportPrivateKey(config.Release());
1130
  }
1131
1132
2459
  if (!result.IsEmpty())
1133
4918
    args.GetReturnValue().Set(result.FromMaybe(Local<Value>()));
1134
}
1135
1136
2434
MaybeLocal<Value> KeyObjectHandle::ExportSecretKey() const {
1137
2434
  const char* buf = data_->GetSymmetricKey();
1138
2434
  unsigned int len = data_->GetSymmetricKeySize();
1139
4868
  return Buffer::Copy(env(), buf, len).FromMaybe(Local<Value>());
1140
}
1141
1142
14
MaybeLocal<Value> KeyObjectHandle::ExportPublicKey(
1143
    const PublicKeyEncodingConfig& config) const {
1144
14
  return WritePublicKey(env(), data_->GetAsymmetricKey().get(), config);
1145
}
1146
1147
11
MaybeLocal<Value> KeyObjectHandle::ExportPrivateKey(
1148
    const PrivateKeyEncodingConfig& config) const {
1149
11
  return WritePrivateKey(env(), data_->GetAsymmetricKey().get(), config);
1150
}
1151
1152
297
void KeyObjectHandle::ExportJWK(
1153
    const v8::FunctionCallbackInfo<v8::Value>& args) {
1154
297
  Environment* env = Environment::GetCurrent(args);
1155
  KeyObjectHandle* key;
1156
297
  ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1157
1158
594
  CHECK(args[0]->IsObject());
1159
1160
297
  switch (key->Data()->GetKeyType()) {
1161
    case kKeyTypeSecret:
1162
201
      if (ExportJWKSecretKey(env, key->Data(), args[0].As<Object>())
1163
              .IsNothing()) {
1164
        return;
1165
      }
1166
67
      break;
1167
    case kKeyTypePublic:
1168
      // Fall through
1169
    case kKeyTypePrivate:
1170
690
      if (ExportJWKAsymmetricKey(env, key->Data(), args[0].As<Object>())
1171
              .IsNothing()) {
1172
        return;
1173
      }
1174
230
      break;
1175
    default:
1176
      UNREACHABLE();
1177
  }
1178
1179
594
  args.GetReturnValue().Set(args[0]);
1180
}
1181
1182
656
void NativeKeyObject::Initialize(Environment* env, Local<Object> target) {
1183
  env->SetMethod(target, "createNativeKeyObjectClass",
1184
656
                 NativeKeyObject::CreateNativeKeyObjectClass);
1185
656
}
1186
1187
2875
void NativeKeyObject::New(const FunctionCallbackInfo<Value>& args) {
1188
2875
  Environment* env = Environment::GetCurrent(args);
1189
2875
  CHECK_EQ(args.Length(), 1);
1190
5750
  CHECK(args[0]->IsObject());
1191
5750
  KeyObjectHandle* handle = Unwrap<KeyObjectHandle>(args[0].As<Object>());
1192
2875
  new NativeKeyObject(env, args.This(), handle->Data());
1193
2875
}
1194
1195
654
void NativeKeyObject::CreateNativeKeyObjectClass(
1196
    const FunctionCallbackInfo<Value>& args) {
1197
654
  Environment* env = Environment::GetCurrent(args);
1198
1199
654
  CHECK_EQ(args.Length(), 1);
1200
654
  Local<Value> callback = args[0];
1201
654
  CHECK(callback->IsFunction());
1202
1203
654
  Local<FunctionTemplate> t = env->NewFunctionTemplate(NativeKeyObject::New);
1204
1962
  t->InstanceTemplate()->SetInternalFieldCount(
1205
654
      KeyObjectHandle::kInternalFieldCount);
1206
1308
  t->Inherit(BaseObject::GetConstructorTemplate(env));
1207
1208
  Local<Value> ctor;
1209
1962
  if (!t->GetFunction(env->context()).ToLocal(&ctor))
1210
    return;
1211
1212
654
  Local<Value> recv = Undefined(env->isolate());
1213
  Local<Value> ret_v;
1214
1962
  if (!callback.As<Function>()->Call(
1215
1962
          env->context(), recv, 1, &ctor).ToLocal(&ret_v)) {
1216
    return;
1217
  }
1218
654
  Local<Array> ret = ret_v.As<Array>();
1219
1962
  if (!ret->Get(env->context(), 1).ToLocal(&ctor)) return;
1220
654
  env->set_crypto_key_object_secret_constructor(ctor.As<Function>());
1221
1962
  if (!ret->Get(env->context(), 2).ToLocal(&ctor)) return;
1222
654
  env->set_crypto_key_object_public_constructor(ctor.As<Function>());
1223
1962
  if (!ret->Get(env->context(), 3).ToLocal(&ctor)) return;
1224
654
  env->set_crypto_key_object_private_constructor(ctor.As<Function>());
1225
1308
  args.GetReturnValue().Set(ret);
1226
}
1227
1228
11
BaseObjectPtr<BaseObject> NativeKeyObject::KeyObjectTransferData::Deserialize(
1229
        Environment* env,
1230
        Local<Context> context,
1231
        std::unique_ptr<worker::TransferData> self) {
1232
22
  if (context != env->context()) {
1233
3
    THROW_ERR_MESSAGE_TARGET_CONTEXT_UNAVAILABLE(env);
1234
3
    return {};
1235
  }
1236
1237
  Local<Value> handle;
1238
16
  if (!KeyObjectHandle::Create(env, data_).ToLocal(&handle))
1239
    return {};
1240
1241
  Local<Function> key_ctor;
1242
  Local<Value> arg = FIXED_ONE_BYTE_STRING(env->isolate(),
1243
8
                                           "internal/crypto/keys");
1244
32
  if (env->native_module_require()->
1245
32
      Call(context, Null(env->isolate()), 1, &arg).IsEmpty()) {
1246
    return {};
1247
  }
1248

8
  switch (data_->GetKeyType()) {
1249
    case kKeyTypeSecret:
1250
4
      key_ctor = env->crypto_key_object_secret_constructor();
1251
4
      break;
1252
    case kKeyTypePublic:
1253
2
      key_ctor = env->crypto_key_object_public_constructor();
1254
2
      break;
1255
    case kKeyTypePrivate:
1256
2
      key_ctor = env->crypto_key_object_private_constructor();
1257
2
      break;
1258
    default:
1259
      CHECK(false);
1260
  }
1261
1262
  Local<Value> key;
1263
16
  if (!key_ctor->NewInstance(context, 1, &handle).ToLocal(&key))
1264
    return {};
1265
1266
8
  return BaseObjectPtr<BaseObject>(Unwrap<KeyObjectHandle>(key.As<Object>()));
1267
}
1268
1269
11
BaseObject::TransferMode NativeKeyObject::GetTransferMode() const {
1270
11
  return BaseObject::TransferMode::kCloneable;
1271
}
1272
1273
11
std::unique_ptr<worker::TransferData> NativeKeyObject::CloneForMessaging()
1274
    const {
1275
11
  return std::make_unique<KeyObjectTransferData>(handle_data_);
1276
}
1277
1278
117
WebCryptoKeyExportStatus PKEY_SPKI_Export(
1279
    KeyObjectData* key_data,
1280
    ByteSource* out) {
1281
117
  CHECK_EQ(key_data->GetKeyType(), kKeyTypePublic);
1282
234
  BIOPointer bio(BIO_new(BIO_s_mem()));
1283
117
  if (!i2d_PUBKEY_bio(bio.get(), key_data->GetAsymmetricKey().get()))
1284
    return WebCryptoKeyExportStatus::FAILED;
1285
1286
117
  *out = ByteSource::FromBIO(bio);
1287
117
  return WebCryptoKeyExportStatus::OK;
1288
}
1289
1290
107
WebCryptoKeyExportStatus PKEY_PKCS8_Export(
1291
    KeyObjectData* key_data,
1292
    ByteSource* out) {
1293
107
  CHECK_EQ(key_data->GetKeyType(), kKeyTypePrivate);
1294
214
  BIOPointer bio(BIO_new(BIO_s_mem()));
1295
214
  PKCS8Pointer p8inf(EVP_PKEY2PKCS8(key_data->GetAsymmetricKey().get()));
1296
107
  if (!i2d_PKCS8_PRIV_KEY_INFO_bio(bio.get(), p8inf.get()))
1297
    return WebCryptoKeyExportStatus::FAILED;
1298
1299
107
  *out = ByteSource::FromBIO(bio);
1300
107
  return WebCryptoKeyExportStatus::OK;
1301
}
1302
1303
namespace Keys {
1304
656
void Initialize(Environment* env, Local<Object> target) {
1305
1312
  target->Set(env->context(),
1306
              FIXED_ONE_BYTE_STRING(env->isolate(), "KeyObjectHandle"),
1307
3280
              KeyObjectHandle::Initialize(env)).Check();
1308
1309
1312
  NODE_DEFINE_CONSTANT(target, kWebCryptoKeyFormatRaw);
1310
656
  NODE_DEFINE_CONSTANT(target, kWebCryptoKeyFormatPKCS8);
1311
1968
  NODE_DEFINE_CONSTANT(target, kWebCryptoKeyFormatSPKI);
1312
3280
  NODE_DEFINE_CONSTANT(target, kWebCryptoKeyFormatJWK);
1313
4592
1314
3936
  NODE_DEFINE_CONSTANT(target, EVP_PKEY_ED25519);
1315
3936
  NODE_DEFINE_CONSTANT(target, EVP_PKEY_ED448);
1316
4592
  NODE_DEFINE_CONSTANT(target, EVP_PKEY_X25519);
1317
4592
  NODE_DEFINE_CONSTANT(target, EVP_PKEY_X448);
1318
5904
  NODE_DEFINE_CONSTANT(target, kKeyEncodingPKCS1);
1319
5904
  NODE_DEFINE_CONSTANT(target, kKeyEncodingPKCS8);
1320
6560
  NODE_DEFINE_CONSTANT(target, kKeyEncodingSPKI);
1321
6560
  NODE_DEFINE_CONSTANT(target, kKeyEncodingSEC1);
1322
6560
  NODE_DEFINE_CONSTANT(target, kKeyFormatDER);
1323
6560
  NODE_DEFINE_CONSTANT(target, kKeyFormatPEM);
1324
5904
  NODE_DEFINE_CONSTANT(target, kKeyTypeSecret);
1325
5904
  NODE_DEFINE_CONSTANT(target, kKeyTypePublic);
1326
5904
  NODE_DEFINE_CONSTANT(target, kKeyTypePrivate);
1327
5904
  NODE_DEFINE_CONSTANT(target, kSigEncDER);
1328
5904
  NODE_DEFINE_CONSTANT(target, kSigEncP1363);
1329
5904
}
1330
3936
}  // namespace Keys
1331
3280
1332
1312
}  // namespace crypto
1333

14073
}  // namespace node