• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "crypto/crypto_keys.h"
2 #include "crypto/crypto_common.h"
3 #include "crypto/crypto_dsa.h"
4 #include "crypto/crypto_ec.h"
5 #include "crypto/crypto_dh.h"
6 #include "crypto/crypto_rsa.h"
7 #include "crypto/crypto_util.h"
8 #include "async_wrap-inl.h"
9 #include "base_object-inl.h"
10 #include "env-inl.h"
11 #include "memory_tracker-inl.h"
12 #include "node.h"
13 #include "node_buffer.h"
14 #include "string_bytes.h"
15 #include "threadpoolwork-inl.h"
16 #include "util-inl.h"
17 #include "v8.h"
18 
19 namespace node {
20 
21 using v8::Array;
22 using v8::Context;
23 using v8::Function;
24 using v8::FunctionCallbackInfo;
25 using v8::FunctionTemplate;
26 using v8::Int32;
27 using v8::Isolate;
28 using v8::Just;
29 using v8::Local;
30 using v8::Maybe;
31 using v8::MaybeLocal;
32 using v8::NewStringType;
33 using v8::Nothing;
34 using v8::Number;
35 using v8::Object;
36 using v8::String;
37 using v8::Uint32;
38 using v8::Undefined;
39 using v8::Value;
40 
41 namespace crypto {
42 namespace {
GetKeyFormatAndTypeFromJs(AsymmetricKeyEncodingConfig * config,const FunctionCallbackInfo<Value> & args,unsigned int * offset,KeyEncodingContext context)43 void GetKeyFormatAndTypeFromJs(
44     AsymmetricKeyEncodingConfig* config,
45     const FunctionCallbackInfo<Value>& args,
46     unsigned int* offset,
47     KeyEncodingContext context) {
48   // During key pair generation, it is possible not to specify a key encoding,
49   // which will lead to a key object being returned.
50   if (args[*offset]->IsUndefined()) {
51     CHECK_EQ(context, kKeyContextGenerate);
52     CHECK(args[*offset + 1]->IsUndefined());
53     config->output_key_object_ = true;
54   } else {
55     config->output_key_object_ = false;
56 
57     CHECK(args[*offset]->IsInt32());
58     config->format_ = static_cast<PKFormatType>(
59         args[*offset].As<Int32>()->Value());
60 
61     if (args[*offset + 1]->IsInt32()) {
62       config->type_ = Just<PKEncodingType>(static_cast<PKEncodingType>(
63           args[*offset + 1].As<Int32>()->Value()));
64     } else {
65       CHECK(
66           (context == kKeyContextInput &&
67            config->format_ == kKeyFormatPEM) ||
68           (context == kKeyContextGenerate &&
69            config->format_ == kKeyFormatJWK));
70       CHECK(args[*offset + 1]->IsNullOrUndefined());
71       config->type_ = Nothing<PKEncodingType>();
72     }
73   }
74 
75   *offset += 2;
76 }
77 
TryParsePublicKey(EVPKeyPointer * pkey,const BIOPointer & bp,const char * name,const std::function<EVP_PKEY * (const unsigned char ** p,long l)> & parse)78 ParseKeyResult TryParsePublicKey(
79     EVPKeyPointer* pkey,
80     const BIOPointer& bp,
81     const char* name,
82     // NOLINTNEXTLINE(runtime/int)
83     const std::function<EVP_PKEY*(const unsigned char** p, long l)>& parse) {
84   unsigned char* der_data;
85   long der_len;  // NOLINT(runtime/int)
86 
87   // This skips surrounding data and decodes PEM to DER.
88   {
89     MarkPopErrorOnReturn mark_pop_error_on_return;
90     if (PEM_bytes_read_bio(&der_data, &der_len, nullptr, name,
91                            bp.get(), nullptr, nullptr) != 1)
92       return ParseKeyResult::kParseKeyNotRecognized;
93   }
94 
95   // OpenSSL might modify the pointer, so we need to make a copy before parsing.
96   const unsigned char* p = der_data;
97   pkey->reset(parse(&p, der_len));
98   OPENSSL_clear_free(der_data, der_len);
99 
100   return *pkey ? ParseKeyResult::kParseKeyOk :
101                  ParseKeyResult::kParseKeyFailed;
102 }
103 
ParsePublicKeyPEM(EVPKeyPointer * pkey,const char * key_pem,int key_pem_len)104 ParseKeyResult ParsePublicKeyPEM(EVPKeyPointer* pkey,
105                                  const char* key_pem,
106                                  int key_pem_len) {
107   BIOPointer bp(BIO_new_mem_buf(const_cast<char*>(key_pem), key_pem_len));
108   if (!bp)
109     return ParseKeyResult::kParseKeyFailed;
110 
111   ParseKeyResult ret;
112 
113   // Try parsing as a SubjectPublicKeyInfo first.
114   ret = TryParsePublicKey(pkey, bp, "PUBLIC KEY",
115       [](const unsigned char** p, long l) {  // NOLINT(runtime/int)
116         return d2i_PUBKEY(nullptr, p, l);
117       });
118   if (ret != ParseKeyResult::kParseKeyNotRecognized)
119     return ret;
120 
121   // Maybe it is PKCS#1.
122   CHECK(BIO_reset(bp.get()));
123   ret = TryParsePublicKey(pkey, bp, "RSA PUBLIC KEY",
124       [](const unsigned char** p, long l) {  // NOLINT(runtime/int)
125         return d2i_PublicKey(EVP_PKEY_RSA, nullptr, p, l);
126       });
127   if (ret != ParseKeyResult::kParseKeyNotRecognized)
128     return ret;
129 
130   // X.509 fallback.
131   CHECK(BIO_reset(bp.get()));
132   return TryParsePublicKey(pkey, bp, "CERTIFICATE",
133       [](const unsigned char** p, long l) {  // NOLINT(runtime/int)
134         X509Pointer x509(d2i_X509(nullptr, p, l));
135         return x509 ? X509_get_pubkey(x509.get()) : nullptr;
136       });
137 }
138 
ParsePublicKey(EVPKeyPointer * pkey,const PublicKeyEncodingConfig & config,const char * key,size_t key_len)139 ParseKeyResult ParsePublicKey(EVPKeyPointer* pkey,
140                               const PublicKeyEncodingConfig& config,
141                               const char* key,
142                               size_t key_len) {
143   if (config.format_ == kKeyFormatPEM) {
144     return ParsePublicKeyPEM(pkey, key, key_len);
145   } else {
146     CHECK_EQ(config.format_, kKeyFormatDER);
147 
148     const unsigned char* p = reinterpret_cast<const unsigned char*>(key);
149     if (config.type_.ToChecked() == kKeyEncodingPKCS1) {
150       pkey->reset(d2i_PublicKey(EVP_PKEY_RSA, nullptr, &p, key_len));
151     } else {
152       CHECK_EQ(config.type_.ToChecked(), kKeyEncodingSPKI);
153       pkey->reset(d2i_PUBKEY(nullptr, &p, key_len));
154     }
155 
156     return *pkey ? ParseKeyResult::kParseKeyOk :
157                    ParseKeyResult::kParseKeyFailed;
158   }
159 }
160 
IsASN1Sequence(const unsigned char * data,size_t size,size_t * data_offset,size_t * data_size)161 bool IsASN1Sequence(const unsigned char* data, size_t size,
162                     size_t* data_offset, size_t* data_size) {
163   if (size < 2 || data[0] != 0x30)
164     return false;
165 
166   if (data[1] & 0x80) {
167     // Long form.
168     size_t n_bytes = data[1] & ~0x80;
169     if (n_bytes + 2 > size || n_bytes > sizeof(size_t))
170       return false;
171     size_t length = 0;
172     for (size_t i = 0; i < n_bytes; i++)
173       length = (length << 8) | data[i + 2];
174     *data_offset = 2 + n_bytes;
175     *data_size = std::min(size - 2 - n_bytes, length);
176   } else {
177     // Short form.
178     *data_offset = 2;
179     *data_size = std::min<size_t>(size - 2, data[1]);
180   }
181 
182   return true;
183 }
184 
IsRSAPrivateKey(const unsigned char * data,size_t size)185 bool IsRSAPrivateKey(const unsigned char* data, size_t size) {
186   // Both RSAPrivateKey and RSAPublicKey structures start with a SEQUENCE.
187   size_t offset, len;
188   if (!IsASN1Sequence(data, size, &offset, &len))
189     return false;
190 
191   // An RSAPrivateKey sequence always starts with a single-byte integer whose
192   // value is either 0 or 1, whereas an RSAPublicKey starts with the modulus
193   // (which is the product of two primes and therefore at least 4), so we can
194   // decide the type of the structure based on the first three bytes of the
195   // sequence.
196   return len >= 3 &&
197          data[offset] == 2 &&
198          data[offset + 1] == 1 &&
199          !(data[offset + 2] & 0xfe);
200 }
201 
IsEncryptedPrivateKeyInfo(const unsigned char * data,size_t size)202 bool IsEncryptedPrivateKeyInfo(const unsigned char* data, size_t size) {
203   // Both PrivateKeyInfo and EncryptedPrivateKeyInfo start with a SEQUENCE.
204   size_t offset, len;
205   if (!IsASN1Sequence(data, size, &offset, &len))
206     return false;
207 
208   // A PrivateKeyInfo sequence always starts with an integer whereas an
209   // EncryptedPrivateKeyInfo starts with an AlgorithmIdentifier.
210   return len >= 1 &&
211          data[offset] != 2;
212 }
213 
ParsePrivateKey(EVPKeyPointer * pkey,const PrivateKeyEncodingConfig & config,const char * key,size_t key_len)214 ParseKeyResult ParsePrivateKey(EVPKeyPointer* pkey,
215                                const PrivateKeyEncodingConfig& config,
216                                const char* key,
217                                size_t key_len) {
218   const ByteSource* passphrase = config.passphrase_.get();
219 
220   if (config.format_ == kKeyFormatPEM) {
221     BIOPointer bio(BIO_new_mem_buf(key, key_len));
222     if (!bio)
223       return ParseKeyResult::kParseKeyFailed;
224 
225     pkey->reset(PEM_read_bio_PrivateKey(bio.get(),
226                                         nullptr,
227                                         PasswordCallback,
228                                         &passphrase));
229   } else {
230     CHECK_EQ(config.format_, kKeyFormatDER);
231 
232     if (config.type_.ToChecked() == kKeyEncodingPKCS1) {
233       const unsigned char* p = reinterpret_cast<const unsigned char*>(key);
234       pkey->reset(d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &p, key_len));
235     } else if (config.type_.ToChecked() == kKeyEncodingPKCS8) {
236       BIOPointer bio(BIO_new_mem_buf(key, key_len));
237       if (!bio)
238         return ParseKeyResult::kParseKeyFailed;
239 
240       if (IsEncryptedPrivateKeyInfo(
241               reinterpret_cast<const unsigned char*>(key), key_len)) {
242         pkey->reset(d2i_PKCS8PrivateKey_bio(bio.get(),
243                                             nullptr,
244                                             PasswordCallback,
245                                             &passphrase));
246       } else {
247         PKCS8Pointer p8inf(d2i_PKCS8_PRIV_KEY_INFO_bio(bio.get(), nullptr));
248         if (p8inf)
249           pkey->reset(EVP_PKCS82PKEY(p8inf.get()));
250       }
251     } else {
252       CHECK_EQ(config.type_.ToChecked(), kKeyEncodingSEC1);
253       const unsigned char* p = reinterpret_cast<const unsigned char*>(key);
254       pkey->reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &p, key_len));
255     }
256   }
257 
258   // OpenSSL can fail to parse the key but still return a non-null pointer.
259   unsigned long err = ERR_peek_error();  // NOLINT(runtime/int)
260   if (err != 0)
261     pkey->reset();
262 
263   if (*pkey)
264     return ParseKeyResult::kParseKeyOk;
265   if (ERR_GET_LIB(err) == ERR_LIB_PEM &&
266       ERR_GET_REASON(err) == PEM_R_BAD_PASSWORD_READ) {
267     if (config.passphrase_.IsEmpty())
268       return ParseKeyResult::kParseKeyNeedPassphrase;
269   }
270   return ParseKeyResult::kParseKeyFailed;
271 }
272 
BIOToStringOrBuffer(Environment * env,BIO * bio,PKFormatType format)273 MaybeLocal<Value> BIOToStringOrBuffer(
274     Environment* env,
275     BIO* bio,
276     PKFormatType format) {
277   BUF_MEM* bptr;
278   BIO_get_mem_ptr(bio, &bptr);
279   if (format == kKeyFormatPEM) {
280     // PEM is an ASCII format, so we will return it as a string.
281     return String::NewFromUtf8(env->isolate(), bptr->data,
282                                NewStringType::kNormal,
283                                bptr->length).FromMaybe(Local<Value>());
284   } else {
285     CHECK_EQ(format, kKeyFormatDER);
286     // DER is binary, return it as a buffer.
287     return Buffer::Copy(env, bptr->data, bptr->length)
288         .FromMaybe(Local<Value>());
289   }
290 }
291 
292 
WritePrivateKey(Environment * env,EVP_PKEY * pkey,const PrivateKeyEncodingConfig & config)293 MaybeLocal<Value> WritePrivateKey(
294     Environment* env,
295     EVP_PKEY* pkey,
296     const PrivateKeyEncodingConfig& config) {
297   BIOPointer bio(BIO_new(BIO_s_mem()));
298   CHECK(bio);
299 
300   // If an empty string was passed as the passphrase, the ByteSource might
301   // contain a null pointer, which OpenSSL will ignore, causing it to invoke its
302   // default passphrase callback, which would block the thread until the user
303   // manually enters a passphrase. We could supply our own passphrase callback
304   // to handle this special case, but it is easier to avoid passing a null
305   // pointer to OpenSSL.
306   char* pass = nullptr;
307   size_t pass_len = 0;
308   if (!config.passphrase_.IsEmpty()) {
309     pass = const_cast<char*>(config.passphrase_->data<char>());
310     pass_len = config.passphrase_->size();
311     if (pass == nullptr) {
312       // OpenSSL will not actually dereference this pointer, so it can be any
313       // non-null pointer. We cannot assert that directly, which is why we
314       // intentionally use a pointer that will likely cause a segmentation fault
315       // when dereferenced.
316       CHECK_EQ(pass_len, 0);
317       pass = reinterpret_cast<char*>(-1);
318       CHECK_NE(pass, nullptr);
319     }
320   }
321 
322   MarkPopErrorOnReturn mark_pop_error_on_return;
323   bool err;
324 
325   PKEncodingType encoding_type = config.type_.ToChecked();
326   if (encoding_type == kKeyEncodingPKCS1) {
327     // PKCS#1 is only permitted for RSA keys.
328     CHECK_EQ(EVP_PKEY_id(pkey), EVP_PKEY_RSA);
329 
330     RSAPointer rsa(EVP_PKEY_get1_RSA(pkey));
331     if (config.format_ == kKeyFormatPEM) {
332       // Encode PKCS#1 as PEM.
333       err = PEM_write_bio_RSAPrivateKey(
334                 bio.get(), rsa.get(),
335                 config.cipher_,
336                 reinterpret_cast<unsigned char*>(pass),
337                 pass_len,
338                 nullptr, nullptr) != 1;
339     } else {
340       // Encode PKCS#1 as DER. This does not permit encryption.
341       CHECK_EQ(config.format_, kKeyFormatDER);
342       CHECK_NULL(config.cipher_);
343       err = i2d_RSAPrivateKey_bio(bio.get(), rsa.get()) != 1;
344     }
345   } else if (encoding_type == kKeyEncodingPKCS8) {
346     if (config.format_ == kKeyFormatPEM) {
347       // Encode PKCS#8 as PEM.
348       err = PEM_write_bio_PKCS8PrivateKey(
349                 bio.get(), pkey,
350                 config.cipher_,
351                 pass,
352                 pass_len,
353                 nullptr, nullptr) != 1;
354     } else {
355       // Encode PKCS#8 as DER.
356       CHECK_EQ(config.format_, kKeyFormatDER);
357       err = i2d_PKCS8PrivateKey_bio(
358                 bio.get(), pkey,
359                 config.cipher_,
360                 pass,
361                 pass_len,
362                 nullptr, nullptr) != 1;
363     }
364   } else {
365     CHECK_EQ(encoding_type, kKeyEncodingSEC1);
366 
367     // SEC1 is only permitted for EC keys.
368     CHECK_EQ(EVP_PKEY_id(pkey), EVP_PKEY_EC);
369 
370     ECKeyPointer ec_key(EVP_PKEY_get1_EC_KEY(pkey));
371     if (config.format_ == kKeyFormatPEM) {
372       // Encode SEC1 as PEM.
373       err = PEM_write_bio_ECPrivateKey(
374                 bio.get(), ec_key.get(),
375                 config.cipher_,
376                 reinterpret_cast<unsigned char*>(pass),
377                 pass_len,
378                 nullptr, nullptr) != 1;
379     } else {
380       // Encode SEC1 as DER. This does not permit encryption.
381       CHECK_EQ(config.format_, kKeyFormatDER);
382       CHECK_NULL(config.cipher_);
383       err = i2d_ECPrivateKey_bio(bio.get(), ec_key.get()) != 1;
384     }
385   }
386 
387   if (err) {
388     ThrowCryptoError(env, ERR_get_error(), "Failed to encode private key");
389     return MaybeLocal<Value>();
390   }
391   return BIOToStringOrBuffer(env, bio.get(), config.format_);
392 }
393 
WritePublicKeyInner(EVP_PKEY * pkey,const BIOPointer & bio,const PublicKeyEncodingConfig & config)394 bool WritePublicKeyInner(EVP_PKEY* pkey,
395                          const BIOPointer& bio,
396                          const PublicKeyEncodingConfig& config) {
397   if (config.type_.ToChecked() == kKeyEncodingPKCS1) {
398     // PKCS#1 is only valid for RSA keys.
399     CHECK_EQ(EVP_PKEY_id(pkey), EVP_PKEY_RSA);
400     RSAPointer rsa(EVP_PKEY_get1_RSA(pkey));
401     if (config.format_ == kKeyFormatPEM) {
402       // Encode PKCS#1 as PEM.
403       return PEM_write_bio_RSAPublicKey(bio.get(), rsa.get()) == 1;
404     } else {
405       // Encode PKCS#1 as DER.
406       CHECK_EQ(config.format_, kKeyFormatDER);
407       return i2d_RSAPublicKey_bio(bio.get(), rsa.get()) == 1;
408     }
409   } else {
410     CHECK_EQ(config.type_.ToChecked(), kKeyEncodingSPKI);
411     if (config.format_ == kKeyFormatPEM) {
412       // Encode SPKI as PEM.
413       return PEM_write_bio_PUBKEY(bio.get(), pkey) == 1;
414     } else {
415       // Encode SPKI as DER.
416       CHECK_EQ(config.format_, kKeyFormatDER);
417       return i2d_PUBKEY_bio(bio.get(), pkey) == 1;
418     }
419   }
420 }
421 
WritePublicKey(Environment * env,EVP_PKEY * pkey,const PublicKeyEncodingConfig & config)422 MaybeLocal<Value> WritePublicKey(Environment* env,
423                                  EVP_PKEY* pkey,
424                                  const PublicKeyEncodingConfig& config) {
425   BIOPointer bio(BIO_new(BIO_s_mem()));
426   CHECK(bio);
427 
428   if (!WritePublicKeyInner(pkey, bio, config)) {
429     ThrowCryptoError(env, ERR_get_error(), "Failed to encode public key");
430     return MaybeLocal<Value>();
431   }
432   return BIOToStringOrBuffer(env, bio.get(), config.format_);
433 }
434 
ExportJWKSecretKey(Environment * env,std::shared_ptr<KeyObjectData> key,Local<Object> target)435 Maybe<bool> ExportJWKSecretKey(
436     Environment* env,
437     std::shared_ptr<KeyObjectData> key,
438     Local<Object> target) {
439   CHECK_EQ(key->GetKeyType(), kKeyTypeSecret);
440 
441   Local<Value> error;
442   Local<Value> raw;
443   MaybeLocal<Value> key_data =
444       StringBytes::Encode(
445           env->isolate(),
446           key->GetSymmetricKey(),
447           key->GetSymmetricKeySize(),
448           BASE64URL,
449           &error);
450   if (key_data.IsEmpty()) {
451     CHECK(!error.IsEmpty());
452     env->isolate()->ThrowException(error);
453     return Nothing<bool>();
454   }
455   if (!key_data.ToLocal(&raw))
456     return Nothing<bool>();
457 
458   if (target->Set(
459           env->context(),
460           env->jwk_kty_string(),
461           env->jwk_oct_string()).IsNothing() ||
462       target->Set(
463           env->context(),
464           env->jwk_k_string(),
465           raw).IsNothing()) {
466     return Nothing<bool>();
467   }
468 
469   return Just(true);
470 }
471 
ImportJWKSecretKey(Environment * env,Local<Object> jwk)472 std::shared_ptr<KeyObjectData> ImportJWKSecretKey(
473     Environment* env,
474     Local<Object> jwk) {
475   Local<Value> key;
476   if (!jwk->Get(env->context(), env->jwk_k_string()).ToLocal(&key) ||
477       !key->IsString()) {
478     THROW_ERR_CRYPTO_INVALID_JWK(env, "Invalid JWK secret key format");
479     return std::shared_ptr<KeyObjectData>();
480   }
481 
482   static_assert(String::kMaxLength <= INT_MAX);
483   ByteSource key_data = ByteSource::FromEncodedString(env, key.As<String>());
484   return KeyObjectData::CreateSecret(std::move(key_data));
485 }
486 
ExportJWKAsymmetricKey(Environment * env,std::shared_ptr<KeyObjectData> key,Local<Object> target,bool handleRsaPss)487 Maybe<bool> ExportJWKAsymmetricKey(
488     Environment* env,
489     std::shared_ptr<KeyObjectData> key,
490     Local<Object> target,
491     bool handleRsaPss) {
492   switch (EVP_PKEY_id(key->GetAsymmetricKey().get())) {
493     case EVP_PKEY_RSA_PSS: {
494       if (handleRsaPss) return ExportJWKRsaKey(env, key, target);
495       break;
496     }
497     case EVP_PKEY_RSA: return ExportJWKRsaKey(env, key, target);
498     case EVP_PKEY_EC: return ExportJWKEcKey(env, key, target).IsJust() ?
499                                Just(true) : Nothing<bool>();
500     case EVP_PKEY_ED25519:
501       // Fall through
502     case EVP_PKEY_ED448:
503       // Fall through
504     case EVP_PKEY_X25519:
505       // Fall through
506     case EVP_PKEY_X448: return ExportJWKEdKey(env, key, target);
507   }
508   THROW_ERR_CRYPTO_JWK_UNSUPPORTED_KEY_TYPE(env);
509   return Just(false);
510 }
511 
ImportJWKAsymmetricKey(Environment * env,Local<Object> jwk,const char * kty,const FunctionCallbackInfo<Value> & args,unsigned int offset)512 std::shared_ptr<KeyObjectData> ImportJWKAsymmetricKey(
513     Environment* env,
514     Local<Object> jwk,
515     const char* kty,
516     const FunctionCallbackInfo<Value>& args,
517     unsigned int offset) {
518   if (strcmp(kty, "RSA") == 0) {
519     return ImportJWKRsaKey(env, jwk, args, offset);
520   } else if (strcmp(kty, "EC") == 0) {
521     return ImportJWKEcKey(env, jwk, args, offset);
522   }
523 
524   THROW_ERR_CRYPTO_INVALID_JWK(env, "%s is not a supported JWK key type", kty);
525   return std::shared_ptr<KeyObjectData>();
526 }
527 
GetSecretKeyDetail(Environment * env,std::shared_ptr<KeyObjectData> key,Local<Object> target)528 Maybe<bool> GetSecretKeyDetail(
529     Environment* env,
530     std::shared_ptr<KeyObjectData> key,
531     Local<Object> target) {
532   // For the secret key detail, all we care about is the length,
533   // converted to bits.
534 
535   size_t length = key->GetSymmetricKeySize() * CHAR_BIT;
536   return target->Set(env->context(),
537                      env->length_string(),
538                      Number::New(env->isolate(), static_cast<double>(length)));
539 }
540 
GetAsymmetricKeyDetail(Environment * env,std::shared_ptr<KeyObjectData> key,Local<Object> target)541 Maybe<bool> GetAsymmetricKeyDetail(
542   Environment* env,
543   std::shared_ptr<KeyObjectData> key,
544   Local<Object> target) {
545   switch (EVP_PKEY_id(key->GetAsymmetricKey().get())) {
546     case EVP_PKEY_RSA:
547       // Fall through
548     case EVP_PKEY_RSA_PSS: return GetRsaKeyDetail(env, key, target);
549     case EVP_PKEY_DSA: return GetDsaKeyDetail(env, key, target);
550     case EVP_PKEY_EC: return GetEcKeyDetail(env, key, target);
551     case EVP_PKEY_DH: return GetDhKeyDetail(env, key, target);
552   }
553   THROW_ERR_CRYPTO_INVALID_KEYTYPE(env);
554   return Nothing<bool>();
555 }
556 }  // namespace
557 
ManagedEVPPKey(EVPKeyPointer && pkey)558 ManagedEVPPKey::ManagedEVPPKey(EVPKeyPointer&& pkey) : pkey_(std::move(pkey)),
559     mutex_(std::make_shared<Mutex>()) {}
560 
ManagedEVPPKey(const ManagedEVPPKey & that)561 ManagedEVPPKey::ManagedEVPPKey(const ManagedEVPPKey& that) {
562   *this = that;
563 }
564 
operator =(const ManagedEVPPKey & that)565 ManagedEVPPKey& ManagedEVPPKey::operator=(const ManagedEVPPKey& that) {
566   Mutex::ScopedLock lock(*that.mutex_);
567 
568   pkey_.reset(that.get());
569 
570   if (pkey_)
571     EVP_PKEY_up_ref(pkey_.get());
572 
573   mutex_ = that.mutex_;
574 
575   return *this;
576 }
577 
operator bool() const578 ManagedEVPPKey::operator bool() const {
579   return !!pkey_;
580 }
581 
get() const582 EVP_PKEY* ManagedEVPPKey::get() const {
583   return pkey_.get();
584 }
585 
mutex() const586 Mutex* ManagedEVPPKey::mutex() const {
587   return mutex_.get();
588 }
589 
MemoryInfo(MemoryTracker * tracker) const590 void ManagedEVPPKey::MemoryInfo(MemoryTracker* tracker) const {
591   tracker->TrackFieldWithSize("pkey",
592                               !pkey_ ? 0 : kSizeOf_EVP_PKEY +
593                               size_of_private_key() +
594                               size_of_public_key());
595 }
596 
size_of_private_key() const597 size_t ManagedEVPPKey::size_of_private_key() const {
598   size_t len = 0;
599   return (pkey_ && EVP_PKEY_get_raw_private_key(
600       pkey_.get(), nullptr, &len) == 1) ? len : 0;
601 }
602 
size_of_public_key() const603 size_t ManagedEVPPKey::size_of_public_key() const {
604   size_t len = 0;
605   return (pkey_ && EVP_PKEY_get_raw_public_key(
606       pkey_.get(), nullptr, &len) == 1) ? len : 0;
607 }
608 
609 // This maps true to Just<bool>(true) and false to Nothing<bool>().
Tristate(bool b)610 static inline Maybe<bool> Tristate(bool b) {
611   return b ? Just(true) : Nothing<bool>();
612 }
613 
ExportJWKInner(Environment * env,std::shared_ptr<KeyObjectData> key,Local<Value> result,bool handleRsaPss)614 Maybe<bool> ExportJWKInner(Environment* env,
615                            std::shared_ptr<KeyObjectData> key,
616                            Local<Value> result,
617                            bool handleRsaPss) {
618   switch (key->GetKeyType()) {
619     case kKeyTypeSecret:
620       return ExportJWKSecretKey(env, key, result.As<Object>());
621     case kKeyTypePublic:
622       // Fall through
623     case kKeyTypePrivate:
624       return ExportJWKAsymmetricKey(
625         env, key, result.As<Object>(), handleRsaPss);
626     default:
627       UNREACHABLE();
628   }
629 }
630 
ToEncodedPublicKey(Environment * env,const PublicKeyEncodingConfig & config,Local<Value> * out)631 Maybe<bool> ManagedEVPPKey::ToEncodedPublicKey(
632     Environment* env,
633     const PublicKeyEncodingConfig& config,
634     Local<Value>* out) {
635   if (!*this) return Nothing<bool>();
636   if (config.output_key_object_) {
637     // Note that this has the downside of containing sensitive data of the
638     // private key.
639     std::shared_ptr<KeyObjectData> data =
640         KeyObjectData::CreateAsymmetric(kKeyTypePublic, *this);
641     return Tristate(KeyObjectHandle::Create(env, data).ToLocal(out));
642   } else if (config.format_ == kKeyFormatJWK) {
643     std::shared_ptr<KeyObjectData> data =
644         KeyObjectData::CreateAsymmetric(kKeyTypePublic, *this);
645     *out = Object::New(env->isolate());
646     return ExportJWKInner(env, data, *out, false);
647   }
648 
649   return Tristate(WritePublicKey(env, get(), config).ToLocal(out));
650 }
651 
ToEncodedPrivateKey(Environment * env,const PrivateKeyEncodingConfig & config,Local<Value> * out)652 Maybe<bool> ManagedEVPPKey::ToEncodedPrivateKey(
653     Environment* env,
654     const PrivateKeyEncodingConfig& config,
655     Local<Value>* out) {
656   if (!*this) return Nothing<bool>();
657   if (config.output_key_object_) {
658     std::shared_ptr<KeyObjectData> data =
659         KeyObjectData::CreateAsymmetric(kKeyTypePrivate, *this);
660     return Tristate(KeyObjectHandle::Create(env, data).ToLocal(out));
661   } else if (config.format_ == kKeyFormatJWK) {
662     std::shared_ptr<KeyObjectData> data =
663         KeyObjectData::CreateAsymmetric(kKeyTypePrivate, *this);
664     *out = Object::New(env->isolate());
665     return ExportJWKInner(env, data, *out, false);
666   }
667 
668   return Tristate(WritePrivateKey(env, get(), config).ToLocal(out));
669 }
670 
671 NonCopyableMaybe<PrivateKeyEncodingConfig>
GetPrivateKeyEncodingFromJs(const FunctionCallbackInfo<Value> & args,unsigned int * offset,KeyEncodingContext context)672 ManagedEVPPKey::GetPrivateKeyEncodingFromJs(
673     const FunctionCallbackInfo<Value>& args,
674     unsigned int* offset,
675     KeyEncodingContext context) {
676   Environment* env = Environment::GetCurrent(args);
677 
678   PrivateKeyEncodingConfig result;
679   GetKeyFormatAndTypeFromJs(&result, args, offset, context);
680 
681   if (result.output_key_object_) {
682     if (context != kKeyContextInput)
683       (*offset)++;
684   } else {
685     bool needs_passphrase = false;
686     if (context != kKeyContextInput) {
687       if (args[*offset]->IsString()) {
688         Utf8Value cipher_name(env->isolate(), args[*offset]);
689         result.cipher_ = EVP_get_cipherbyname(*cipher_name);
690         if (result.cipher_ == nullptr) {
691           THROW_ERR_CRYPTO_UNKNOWN_CIPHER(env);
692           return NonCopyableMaybe<PrivateKeyEncodingConfig>();
693         }
694         needs_passphrase = true;
695       } else {
696         CHECK(args[*offset]->IsNullOrUndefined());
697         result.cipher_ = nullptr;
698       }
699       (*offset)++;
700     }
701 
702     if (IsAnyByteSource(args[*offset])) {
703       CHECK_IMPLIES(context != kKeyContextInput, result.cipher_ != nullptr);
704       ArrayBufferOrViewContents<char> passphrase(args[*offset]);
705       if (UNLIKELY(!passphrase.CheckSizeInt32())) {
706         THROW_ERR_OUT_OF_RANGE(env, "passphrase is too big");
707         return NonCopyableMaybe<PrivateKeyEncodingConfig>();
708       }
709       result.passphrase_ = NonCopyableMaybe<ByteSource>(
710           passphrase.ToNullTerminatedCopy());
711     } else {
712       CHECK(args[*offset]->IsNullOrUndefined() && !needs_passphrase);
713     }
714   }
715 
716   (*offset)++;
717   return NonCopyableMaybe<PrivateKeyEncodingConfig>(std::move(result));
718 }
719 
GetPublicKeyEncodingFromJs(const FunctionCallbackInfo<Value> & args,unsigned int * offset,KeyEncodingContext context)720 PublicKeyEncodingConfig ManagedEVPPKey::GetPublicKeyEncodingFromJs(
721     const FunctionCallbackInfo<Value>& args,
722     unsigned int* offset,
723     KeyEncodingContext context) {
724   PublicKeyEncodingConfig result;
725   GetKeyFormatAndTypeFromJs(&result, args, offset, context);
726   return result;
727 }
728 
GetPrivateKeyFromJs(const FunctionCallbackInfo<Value> & args,unsigned int * offset,bool allow_key_object)729 ManagedEVPPKey ManagedEVPPKey::GetPrivateKeyFromJs(
730     const FunctionCallbackInfo<Value>& args,
731     unsigned int* offset,
732     bool allow_key_object) {
733   if (args[*offset]->IsString() || IsAnyByteSource(args[*offset])) {
734     Environment* env = Environment::GetCurrent(args);
735     ByteSource key = ByteSource::FromStringOrBuffer(env, args[(*offset)++]);
736     NonCopyableMaybe<PrivateKeyEncodingConfig> config =
737         GetPrivateKeyEncodingFromJs(args, offset, kKeyContextInput);
738     if (config.IsEmpty())
739       return ManagedEVPPKey();
740 
741     EVPKeyPointer pkey;
742     ParseKeyResult ret =
743         ParsePrivateKey(&pkey, config.Release(), key.data<char>(), key.size());
744     return GetParsedKey(env, std::move(pkey), ret,
745                         "Failed to read private key");
746   } else {
747     CHECK(args[*offset]->IsObject() && allow_key_object);
748     KeyObjectHandle* key;
749     ASSIGN_OR_RETURN_UNWRAP(&key, args[*offset].As<Object>(), ManagedEVPPKey());
750     CHECK_EQ(key->Data()->GetKeyType(), kKeyTypePrivate);
751     (*offset) += 4;
752     return key->Data()->GetAsymmetricKey();
753   }
754 }
755 
GetPublicOrPrivateKeyFromJs(const FunctionCallbackInfo<Value> & args,unsigned int * offset)756 ManagedEVPPKey ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(
757     const FunctionCallbackInfo<Value>& args,
758     unsigned int* offset) {
759   if (IsAnyByteSource(args[*offset])) {
760     Environment* env = Environment::GetCurrent(args);
761     ArrayBufferOrViewContents<char> data(args[(*offset)++]);
762     if (UNLIKELY(!data.CheckSizeInt32())) {
763       THROW_ERR_OUT_OF_RANGE(env, "keyData is too big");
764       return ManagedEVPPKey();
765     }
766     NonCopyableMaybe<PrivateKeyEncodingConfig> config_ =
767         GetPrivateKeyEncodingFromJs(args, offset, kKeyContextInput);
768     if (config_.IsEmpty())
769       return ManagedEVPPKey();
770 
771     ParseKeyResult ret;
772     PrivateKeyEncodingConfig config = config_.Release();
773     EVPKeyPointer pkey;
774     if (config.format_ == kKeyFormatPEM) {
775       // For PEM, we can easily determine whether it is a public or private key
776       // by looking for the respective PEM tags.
777       ret = ParsePublicKeyPEM(&pkey, data.data(), data.size());
778       if (ret == ParseKeyResult::kParseKeyNotRecognized) {
779         ret = ParsePrivateKey(&pkey, config, data.data(), data.size());
780       }
781     } else {
782       // For DER, the type determines how to parse it. SPKI, PKCS#8 and SEC1 are
783       // easy, but PKCS#1 can be a public key or a private key.
784       bool is_public;
785       switch (config.type_.ToChecked()) {
786         case kKeyEncodingPKCS1:
787           is_public = !IsRSAPrivateKey(
788               reinterpret_cast<const unsigned char*>(data.data()), data.size());
789           break;
790         case kKeyEncodingSPKI:
791           is_public = true;
792           break;
793         case kKeyEncodingPKCS8:
794         case kKeyEncodingSEC1:
795           is_public = false;
796           break;
797         default:
798           UNREACHABLE("Invalid key encoding type");
799       }
800 
801       if (is_public) {
802         ret = ParsePublicKey(&pkey, config, data.data(), data.size());
803       } else {
804         ret = ParsePrivateKey(&pkey, config, data.data(), data.size());
805       }
806     }
807 
808     return ManagedEVPPKey::GetParsedKey(
809         env, std::move(pkey), ret, "Failed to read asymmetric key");
810   } else {
811     CHECK(args[*offset]->IsObject());
812     KeyObjectHandle* key = Unwrap<KeyObjectHandle>(args[*offset].As<Object>());
813     CHECK_NOT_NULL(key);
814     CHECK_NE(key->Data()->GetKeyType(), kKeyTypeSecret);
815     (*offset) += 4;
816     return key->Data()->GetAsymmetricKey();
817   }
818 }
819 
GetParsedKey(Environment * env,EVPKeyPointer && pkey,ParseKeyResult ret,const char * default_msg)820 ManagedEVPPKey ManagedEVPPKey::GetParsedKey(Environment* env,
821                                             EVPKeyPointer&& pkey,
822                                             ParseKeyResult ret,
823                                             const char* default_msg) {
824   switch (ret) {
825     case ParseKeyResult::kParseKeyOk:
826       CHECK(pkey);
827       break;
828     case ParseKeyResult::kParseKeyNeedPassphrase:
829       THROW_ERR_MISSING_PASSPHRASE(env,
830                                    "Passphrase required for encrypted key");
831       break;
832     default:
833       ThrowCryptoError(env, ERR_get_error(), default_msg);
834   }
835 
836   return ManagedEVPPKey(std::move(pkey));
837 }
838 
KeyObjectData(ByteSource symmetric_key)839 KeyObjectData::KeyObjectData(ByteSource symmetric_key)
840     : key_type_(KeyType::kKeyTypeSecret),
841       symmetric_key_(std::move(symmetric_key)),
842       asymmetric_key_() {}
843 
KeyObjectData(KeyType type,const ManagedEVPPKey & pkey)844 KeyObjectData::KeyObjectData(KeyType type, const ManagedEVPPKey& pkey)
845     : key_type_(type), symmetric_key_(), asymmetric_key_{pkey} {}
846 
MemoryInfo(MemoryTracker * tracker) const847 void KeyObjectData::MemoryInfo(MemoryTracker* tracker) const {
848   switch (GetKeyType()) {
849     case kKeyTypeSecret:
850       tracker->TrackFieldWithSize("symmetric_key", symmetric_key_.size());
851       break;
852     case kKeyTypePrivate:
853       // Fall through
854     case kKeyTypePublic:
855       tracker->TrackFieldWithSize("key", asymmetric_key_);
856       break;
857     default:
858       UNREACHABLE();
859   }
860 }
861 
CreateSecret(ByteSource key)862 std::shared_ptr<KeyObjectData> KeyObjectData::CreateSecret(ByteSource key) {
863   return std::shared_ptr<KeyObjectData>(new KeyObjectData(std::move(key)));
864 }
865 
CreateAsymmetric(KeyType key_type,const ManagedEVPPKey & pkey)866 std::shared_ptr<KeyObjectData> KeyObjectData::CreateAsymmetric(
867     KeyType key_type,
868     const ManagedEVPPKey& pkey) {
869   CHECK(pkey);
870   return std::shared_ptr<KeyObjectData>(new KeyObjectData(key_type, pkey));
871 }
872 
GetKeyType() const873 KeyType KeyObjectData::GetKeyType() const {
874   return key_type_;
875 }
876 
GetAsymmetricKey() const877 ManagedEVPPKey KeyObjectData::GetAsymmetricKey() const {
878   CHECK_NE(key_type_, kKeyTypeSecret);
879   return asymmetric_key_;
880 }
881 
GetSymmetricKey() const882 const char* KeyObjectData::GetSymmetricKey() const {
883   CHECK_EQ(key_type_, kKeyTypeSecret);
884   return symmetric_key_.data<char>();
885 }
886 
GetSymmetricKeySize() const887 size_t KeyObjectData::GetSymmetricKeySize() const {
888   CHECK_EQ(key_type_, kKeyTypeSecret);
889   return symmetric_key_.size();
890 }
891 
HasInstance(Environment * env,Local<Value> value)892 bool KeyObjectHandle::HasInstance(Environment* env, Local<Value> value) {
893   Local<FunctionTemplate> t = env->crypto_key_object_handle_constructor();
894   return !t.IsEmpty() && t->HasInstance(value);
895 }
896 
Initialize(Environment * env)897 v8::Local<v8::Function> KeyObjectHandle::Initialize(Environment* env) {
898   Local<FunctionTemplate> templ = env->crypto_key_object_handle_constructor();
899   if (templ.IsEmpty()) {
900     Isolate* isolate = env->isolate();
901     templ = NewFunctionTemplate(isolate, New);
902     templ->InstanceTemplate()->SetInternalFieldCount(
903         KeyObjectHandle::kInternalFieldCount);
904     templ->Inherit(BaseObject::GetConstructorTemplate(env));
905 
906     SetProtoMethod(isolate, templ, "init", Init);
907     SetProtoMethodNoSideEffect(
908         isolate, templ, "getSymmetricKeySize", GetSymmetricKeySize);
909     SetProtoMethodNoSideEffect(
910         isolate, templ, "getAsymmetricKeyType", GetAsymmetricKeyType);
911     SetProtoMethodNoSideEffect(
912         isolate, templ, "checkEcKeyData", CheckEcKeyData);
913     SetProtoMethod(isolate, templ, "export", Export);
914     SetProtoMethod(isolate, templ, "exportJwk", ExportJWK);
915     SetProtoMethod(isolate, templ, "initECRaw", InitECRaw);
916     SetProtoMethod(isolate, templ, "initEDRaw", InitEDRaw);
917     SetProtoMethod(isolate, templ, "initJwk", InitJWK);
918     SetProtoMethod(isolate, templ, "keyDetail", GetKeyDetail);
919     SetProtoMethod(isolate, templ, "equals", Equals);
920 
921     env->set_crypto_key_object_handle_constructor(templ);
922   }
923   return templ->GetFunction(env->context()).ToLocalChecked();
924 }
925 
RegisterExternalReferences(ExternalReferenceRegistry * registry)926 void KeyObjectHandle::RegisterExternalReferences(
927     ExternalReferenceRegistry* registry) {
928   registry->Register(New);
929   registry->Register(Init);
930   registry->Register(GetSymmetricKeySize);
931   registry->Register(GetAsymmetricKeyType);
932   registry->Register(CheckEcKeyData);
933   registry->Register(Export);
934   registry->Register(ExportJWK);
935   registry->Register(InitECRaw);
936   registry->Register(InitEDRaw);
937   registry->Register(InitJWK);
938   registry->Register(GetKeyDetail);
939   registry->Register(Equals);
940 }
941 
Create(Environment * env,std::shared_ptr<KeyObjectData> data)942 MaybeLocal<Object> KeyObjectHandle::Create(
943     Environment* env,
944     std::shared_ptr<KeyObjectData> data) {
945   Local<Object> obj;
946   Local<Function> ctor = KeyObjectHandle::Initialize(env);
947   CHECK(!env->crypto_key_object_handle_constructor().IsEmpty());
948   if (!ctor->NewInstance(env->context(), 0, nullptr).ToLocal(&obj))
949     return MaybeLocal<Object>();
950 
951   KeyObjectHandle* key = Unwrap<KeyObjectHandle>(obj);
952   CHECK_NOT_NULL(key);
953   key->data_ = data;
954   return obj;
955 }
956 
Data()957 const std::shared_ptr<KeyObjectData>& KeyObjectHandle::Data() {
958   return data_;
959 }
960 
New(const FunctionCallbackInfo<Value> & args)961 void KeyObjectHandle::New(const FunctionCallbackInfo<Value>& args) {
962   CHECK(args.IsConstructCall());
963   Environment* env = Environment::GetCurrent(args);
964   new KeyObjectHandle(env, args.This());
965 }
966 
KeyObjectHandle(Environment * env,Local<Object> wrap)967 KeyObjectHandle::KeyObjectHandle(Environment* env,
968                                  Local<Object> wrap)
969     : BaseObject(env, wrap) {
970   MakeWeak();
971 }
972 
Init(const FunctionCallbackInfo<Value> & args)973 void KeyObjectHandle::Init(const FunctionCallbackInfo<Value>& args) {
974   KeyObjectHandle* key;
975   ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
976   MarkPopErrorOnReturn mark_pop_error_on_return;
977 
978   CHECK(args[0]->IsInt32());
979   KeyType type = static_cast<KeyType>(args[0].As<Uint32>()->Value());
980 
981   unsigned int offset;
982   ManagedEVPPKey pkey;
983 
984   switch (type) {
985   case kKeyTypeSecret: {
986     CHECK_EQ(args.Length(), 2);
987     ArrayBufferOrViewContents<char> buf(args[1]);
988     key->data_ = KeyObjectData::CreateSecret(buf.ToCopy());
989     break;
990   }
991   case kKeyTypePublic: {
992     CHECK_EQ(args.Length(), 5);
993 
994     offset = 1;
995     pkey = ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(args, &offset);
996     if (!pkey)
997       return;
998     key->data_ = KeyObjectData::CreateAsymmetric(type, pkey);
999     break;
1000   }
1001   case kKeyTypePrivate: {
1002     CHECK_EQ(args.Length(), 5);
1003 
1004     offset = 1;
1005     pkey = ManagedEVPPKey::GetPrivateKeyFromJs(args, &offset, false);
1006     if (!pkey)
1007       return;
1008     key->data_ = KeyObjectData::CreateAsymmetric(type, pkey);
1009     break;
1010   }
1011   default:
1012     UNREACHABLE();
1013   }
1014 }
1015 
InitJWK(const FunctionCallbackInfo<Value> & args)1016 void KeyObjectHandle::InitJWK(const FunctionCallbackInfo<Value>& args) {
1017   Environment* env = Environment::GetCurrent(args);
1018   KeyObjectHandle* key;
1019   ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1020   MarkPopErrorOnReturn mark_pop_error_on_return;
1021 
1022   // The argument must be a JavaScript object that we will inspect
1023   // to get the JWK properties from.
1024   CHECK(args[0]->IsObject());
1025 
1026   // Step one, Secret key or not?
1027   Local<Object> input = args[0].As<Object>();
1028 
1029   Local<Value> kty;
1030   if (!input->Get(env->context(), env->jwk_kty_string()).ToLocal(&kty) ||
1031       !kty->IsString()) {
1032     return THROW_ERR_CRYPTO_INVALID_JWK(env);
1033   }
1034 
1035   Utf8Value kty_string(env->isolate(), kty);
1036 
1037   if (strcmp(*kty_string, "oct") == 0) {
1038     // Secret key
1039     key->data_ = ImportJWKSecretKey(env, input);
1040     if (!key->data_) {
1041       // ImportJWKSecretKey is responsible for throwing an appropriate error
1042       return;
1043     }
1044   } else {
1045     key->data_ = ImportJWKAsymmetricKey(env, input, *kty_string, args, 1);
1046     if (!key->data_) {
1047       // ImportJWKAsymmetricKey is responsible for throwing an appropriate error
1048       return;
1049     }
1050   }
1051 
1052   args.GetReturnValue().Set(key->data_->GetKeyType());
1053 }
1054 
InitECRaw(const FunctionCallbackInfo<Value> & args)1055 void KeyObjectHandle::InitECRaw(const FunctionCallbackInfo<Value>& args) {
1056   Environment* env = Environment::GetCurrent(args);
1057   KeyObjectHandle* key;
1058   ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1059 
1060   CHECK(args[0]->IsString());
1061   Utf8Value name(env->isolate(), args[0]);
1062 
1063   MarkPopErrorOnReturn mark_pop_error_on_return;
1064 
1065   int id = OBJ_txt2nid(*name);
1066   ECKeyPointer eckey(EC_KEY_new_by_curve_name(id));
1067   if (!eckey)
1068     return args.GetReturnValue().Set(false);
1069 
1070   const EC_GROUP* group = EC_KEY_get0_group(eckey.get());
1071   ECPointPointer pub(ECDH::BufferToPoint(env, group, args[1]));
1072 
1073   if (!pub ||
1074       !eckey ||
1075       !EC_KEY_set_public_key(eckey.get(), pub.get())) {
1076     return args.GetReturnValue().Set(false);
1077   }
1078 
1079   EVPKeyPointer pkey(EVP_PKEY_new());
1080   if (!EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()))
1081     args.GetReturnValue().Set(false);
1082 
1083   eckey.release();  // Release ownership of the key
1084 
1085   key->data_ =
1086       KeyObjectData::CreateAsymmetric(
1087           kKeyTypePublic,
1088           ManagedEVPPKey(std::move(pkey)));
1089 
1090   args.GetReturnValue().Set(true);
1091 }
1092 
InitEDRaw(const FunctionCallbackInfo<Value> & args)1093 void KeyObjectHandle::InitEDRaw(const FunctionCallbackInfo<Value>& args) {
1094   Environment* env = Environment::GetCurrent(args);
1095   KeyObjectHandle* key;
1096   ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1097 
1098   CHECK(args[0]->IsString());
1099   Utf8Value name(env->isolate(), args[0]);
1100 
1101   ArrayBufferOrViewContents<unsigned char> key_data(args[1]);
1102   KeyType type = static_cast<KeyType>(args[2].As<Int32>()->Value());
1103 
1104   MarkPopErrorOnReturn mark_pop_error_on_return;
1105 
1106   typedef EVP_PKEY* (*new_key_fn)(int, ENGINE*, const unsigned char*, size_t);
1107   new_key_fn fn = type == kKeyTypePrivate
1108       ? EVP_PKEY_new_raw_private_key
1109       : EVP_PKEY_new_raw_public_key;
1110 
1111   int id = GetOKPCurveFromName(*name);
1112 
1113   switch (id) {
1114     case EVP_PKEY_X25519:
1115     case EVP_PKEY_X448:
1116     case EVP_PKEY_ED25519:
1117     case EVP_PKEY_ED448: {
1118       EVPKeyPointer pkey(fn(id, nullptr, key_data.data(), key_data.size()));
1119       if (!pkey)
1120         return args.GetReturnValue().Set(false);
1121       key->data_ =
1122           KeyObjectData::CreateAsymmetric(
1123               type,
1124               ManagedEVPPKey(std::move(pkey)));
1125       CHECK(key->data_);
1126       break;
1127     }
1128     default:
1129       UNREACHABLE();
1130   }
1131 
1132   args.GetReturnValue().Set(true);
1133 }
1134 
Equals(const FunctionCallbackInfo<Value> & args)1135 void KeyObjectHandle::Equals(const FunctionCallbackInfo<Value>& args) {
1136   KeyObjectHandle* self_handle;
1137   KeyObjectHandle* arg_handle;
1138   ASSIGN_OR_RETURN_UNWRAP(&self_handle, args.Holder());
1139   ASSIGN_OR_RETURN_UNWRAP(&arg_handle, args[0].As<Object>());
1140   std::shared_ptr<KeyObjectData> key = self_handle->Data();
1141   std::shared_ptr<KeyObjectData> key2 = arg_handle->Data();
1142 
1143   KeyType key_type = key->GetKeyType();
1144   CHECK_EQ(key_type, key2->GetKeyType());
1145 
1146   bool ret;
1147   switch (key_type) {
1148     case kKeyTypeSecret: {
1149       size_t size = key->GetSymmetricKeySize();
1150       if (size == key2->GetSymmetricKeySize()) {
1151         ret = CRYPTO_memcmp(
1152           key->GetSymmetricKey(),
1153           key2->GetSymmetricKey(),
1154           size) == 0;
1155       } else {
1156         ret = false;
1157       }
1158       break;
1159     }
1160     case kKeyTypePublic:
1161     case kKeyTypePrivate: {
1162       EVP_PKEY* pkey = key->GetAsymmetricKey().get();
1163       EVP_PKEY* pkey2 = key2->GetAsymmetricKey().get();
1164 #if OPENSSL_VERSION_MAJOR >= 3
1165       int ok = EVP_PKEY_eq(pkey, pkey2);
1166 #else
1167       int ok = EVP_PKEY_cmp(pkey, pkey2);
1168 #endif
1169       if (ok == -2) {
1170         Environment* env = Environment::GetCurrent(args);
1171         return THROW_ERR_CRYPTO_UNSUPPORTED_OPERATION(env);
1172       }
1173       ret = ok == 1;
1174       break;
1175     }
1176     default:
1177       UNREACHABLE("unsupported key type");
1178   }
1179 
1180   args.GetReturnValue().Set(ret);
1181 }
1182 
GetKeyDetail(const FunctionCallbackInfo<Value> & args)1183 void KeyObjectHandle::GetKeyDetail(const FunctionCallbackInfo<Value>& args) {
1184   Environment* env = Environment::GetCurrent(args);
1185   KeyObjectHandle* key;
1186   ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1187 
1188   CHECK(args[0]->IsObject());
1189 
1190   std::shared_ptr<KeyObjectData> data = key->Data();
1191 
1192   switch (data->GetKeyType()) {
1193     case kKeyTypeSecret:
1194       if (GetSecretKeyDetail(env, data, args[0].As<Object>()).IsNothing())
1195         return;
1196       break;
1197     case kKeyTypePublic:
1198       // Fall through
1199     case kKeyTypePrivate:
1200       if (GetAsymmetricKeyDetail(env, data, args[0].As<Object>()).IsNothing())
1201         return;
1202       break;
1203     default:
1204       UNREACHABLE();
1205   }
1206 
1207   args.GetReturnValue().Set(args[0]);
1208 }
1209 
GetAsymmetricKeyType() const1210 Local<Value> KeyObjectHandle::GetAsymmetricKeyType() const {
1211   const ManagedEVPPKey& key = data_->GetAsymmetricKey();
1212   switch (EVP_PKEY_id(key.get())) {
1213   case EVP_PKEY_RSA:
1214     return env()->crypto_rsa_string();
1215   case EVP_PKEY_RSA_PSS:
1216     return env()->crypto_rsa_pss_string();
1217   case EVP_PKEY_DSA:
1218     return env()->crypto_dsa_string();
1219   case EVP_PKEY_DH:
1220     return env()->crypto_dh_string();
1221   case EVP_PKEY_EC:
1222     return env()->crypto_ec_string();
1223   case EVP_PKEY_ED25519:
1224     return env()->crypto_ed25519_string();
1225   case EVP_PKEY_ED448:
1226     return env()->crypto_ed448_string();
1227   case EVP_PKEY_X25519:
1228     return env()->crypto_x25519_string();
1229   case EVP_PKEY_X448:
1230     return env()->crypto_x448_string();
1231   default:
1232     return Undefined(env()->isolate());
1233   }
1234 }
1235 
GetAsymmetricKeyType(const FunctionCallbackInfo<Value> & args)1236 void KeyObjectHandle::GetAsymmetricKeyType(
1237     const FunctionCallbackInfo<Value>& args) {
1238   KeyObjectHandle* key;
1239   ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1240 
1241   args.GetReturnValue().Set(key->GetAsymmetricKeyType());
1242 }
1243 
CheckEcKeyData() const1244 bool KeyObjectHandle::CheckEcKeyData() const {
1245   MarkPopErrorOnReturn mark_pop_error_on_return;
1246 
1247   const ManagedEVPPKey& key = data_->GetAsymmetricKey();
1248   KeyType type = data_->GetKeyType();
1249   CHECK_NE(type, kKeyTypeSecret);
1250   EVPKeyCtxPointer ctx(EVP_PKEY_CTX_new(key.get(), nullptr));
1251   CHECK(ctx);
1252   CHECK_EQ(EVP_PKEY_id(key.get()), EVP_PKEY_EC);
1253 
1254   if (type == kKeyTypePrivate) {
1255     return EVP_PKEY_check(ctx.get()) == 1;
1256   }
1257 
1258 #if OPENSSL_VERSION_MAJOR >= 3
1259   return EVP_PKEY_public_check_quick(ctx.get()) == 1;
1260 #else
1261   return EVP_PKEY_public_check(ctx.get()) == 1;
1262 #endif
1263 }
1264 
CheckEcKeyData(const FunctionCallbackInfo<Value> & args)1265 void KeyObjectHandle::CheckEcKeyData(const FunctionCallbackInfo<Value>& args) {
1266   KeyObjectHandle* key;
1267   ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1268 
1269   args.GetReturnValue().Set(key->CheckEcKeyData());
1270 }
1271 
GetSymmetricKeySize(const FunctionCallbackInfo<Value> & args)1272 void KeyObjectHandle::GetSymmetricKeySize(
1273     const FunctionCallbackInfo<Value>& args) {
1274   KeyObjectHandle* key;
1275   ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1276   args.GetReturnValue().Set(
1277       static_cast<uint32_t>(key->Data()->GetSymmetricKeySize()));
1278 }
1279 
Export(const FunctionCallbackInfo<Value> & args)1280 void KeyObjectHandle::Export(const FunctionCallbackInfo<Value>& args) {
1281   KeyObjectHandle* key;
1282   ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1283 
1284   KeyType type = key->Data()->GetKeyType();
1285 
1286   MaybeLocal<Value> result;
1287   if (type == kKeyTypeSecret) {
1288     result = key->ExportSecretKey();
1289   } else if (type == kKeyTypePublic) {
1290     unsigned int offset = 0;
1291     PublicKeyEncodingConfig config =
1292         ManagedEVPPKey::GetPublicKeyEncodingFromJs(
1293             args, &offset, kKeyContextExport);
1294     CHECK_EQ(offset, static_cast<unsigned int>(args.Length()));
1295     result = key->ExportPublicKey(config);
1296   } else {
1297     CHECK_EQ(type, kKeyTypePrivate);
1298     unsigned int offset = 0;
1299     NonCopyableMaybe<PrivateKeyEncodingConfig> config =
1300         ManagedEVPPKey::GetPrivateKeyEncodingFromJs(
1301             args, &offset, kKeyContextExport);
1302     if (config.IsEmpty())
1303       return;
1304     CHECK_EQ(offset, static_cast<unsigned int>(args.Length()));
1305     result = key->ExportPrivateKey(config.Release());
1306   }
1307 
1308   if (!result.IsEmpty())
1309     args.GetReturnValue().Set(result.FromMaybe(Local<Value>()));
1310 }
1311 
ExportSecretKey() const1312 MaybeLocal<Value> KeyObjectHandle::ExportSecretKey() const {
1313   const char* buf = data_->GetSymmetricKey();
1314   unsigned int len = data_->GetSymmetricKeySize();
1315   return Buffer::Copy(env(), buf, len).FromMaybe(Local<Value>());
1316 }
1317 
ExportPublicKey(const PublicKeyEncodingConfig & config) const1318 MaybeLocal<Value> KeyObjectHandle::ExportPublicKey(
1319     const PublicKeyEncodingConfig& config) const {
1320   return WritePublicKey(env(), data_->GetAsymmetricKey().get(), config);
1321 }
1322 
ExportPrivateKey(const PrivateKeyEncodingConfig & config) const1323 MaybeLocal<Value> KeyObjectHandle::ExportPrivateKey(
1324     const PrivateKeyEncodingConfig& config) const {
1325   return WritePrivateKey(env(), data_->GetAsymmetricKey().get(), config);
1326 }
1327 
ExportJWK(const v8::FunctionCallbackInfo<v8::Value> & args)1328 void KeyObjectHandle::ExportJWK(
1329     const v8::FunctionCallbackInfo<v8::Value>& args) {
1330   Environment* env = Environment::GetCurrent(args);
1331   KeyObjectHandle* key;
1332   ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1333 
1334   CHECK(args[0]->IsObject());
1335   CHECK(args[1]->IsBoolean());
1336 
1337   ExportJWKInner(env, key->Data(), args[0], args[1]->IsTrue());
1338 
1339   args.GetReturnValue().Set(args[0]);
1340 }
1341 
Initialize(Environment * env,Local<Object> target)1342 void NativeKeyObject::Initialize(Environment* env, Local<Object> target) {
1343   SetMethod(env->context(),
1344             target,
1345             "createNativeKeyObjectClass",
1346             NativeKeyObject::CreateNativeKeyObjectClass);
1347 }
1348 
RegisterExternalReferences(ExternalReferenceRegistry * registry)1349 void NativeKeyObject::RegisterExternalReferences(
1350     ExternalReferenceRegistry* registry) {
1351   registry->Register(NativeKeyObject::CreateNativeKeyObjectClass);
1352   registry->Register(NativeKeyObject::New);
1353 }
1354 
New(const FunctionCallbackInfo<Value> & args)1355 void NativeKeyObject::New(const FunctionCallbackInfo<Value>& args) {
1356   Environment* env = Environment::GetCurrent(args);
1357   CHECK_EQ(args.Length(), 1);
1358   CHECK(args[0]->IsObject());
1359   KeyObjectHandle* handle = Unwrap<KeyObjectHandle>(args[0].As<Object>());
1360   new NativeKeyObject(env, args.This(), handle->Data());
1361 }
1362 
CreateNativeKeyObjectClass(const FunctionCallbackInfo<Value> & args)1363 void NativeKeyObject::CreateNativeKeyObjectClass(
1364     const FunctionCallbackInfo<Value>& args) {
1365   Environment* env = Environment::GetCurrent(args);
1366   Isolate* isolate = env->isolate();
1367 
1368   CHECK_EQ(args.Length(), 1);
1369   Local<Value> callback = args[0];
1370   CHECK(callback->IsFunction());
1371 
1372   Local<FunctionTemplate> t =
1373       NewFunctionTemplate(isolate, NativeKeyObject::New);
1374   t->InstanceTemplate()->SetInternalFieldCount(
1375       KeyObjectHandle::kInternalFieldCount);
1376   t->Inherit(BaseObject::GetConstructorTemplate(env));
1377 
1378   Local<Value> ctor;
1379   if (!t->GetFunction(env->context()).ToLocal(&ctor))
1380     return;
1381 
1382   Local<Value> recv = Undefined(env->isolate());
1383   Local<Value> ret_v;
1384   if (!callback.As<Function>()->Call(
1385           env->context(), recv, 1, &ctor).ToLocal(&ret_v)) {
1386     return;
1387   }
1388   Local<Array> ret = ret_v.As<Array>();
1389   if (!ret->Get(env->context(), 1).ToLocal(&ctor)) return;
1390   env->set_crypto_key_object_secret_constructor(ctor.As<Function>());
1391   if (!ret->Get(env->context(), 2).ToLocal(&ctor)) return;
1392   env->set_crypto_key_object_public_constructor(ctor.As<Function>());
1393   if (!ret->Get(env->context(), 3).ToLocal(&ctor)) return;
1394   env->set_crypto_key_object_private_constructor(ctor.As<Function>());
1395   args.GetReturnValue().Set(ret);
1396 }
1397 
Deserialize(Environment * env,Local<Context> context,std::unique_ptr<worker::TransferData> self)1398 BaseObjectPtr<BaseObject> NativeKeyObject::KeyObjectTransferData::Deserialize(
1399         Environment* env,
1400         Local<Context> context,
1401         std::unique_ptr<worker::TransferData> self) {
1402   if (context != env->context()) {
1403     THROW_ERR_MESSAGE_TARGET_CONTEXT_UNAVAILABLE(env);
1404     return {};
1405   }
1406 
1407   Local<Value> handle;
1408   if (!KeyObjectHandle::Create(env, data_).ToLocal(&handle))
1409     return {};
1410 
1411   Local<Function> key_ctor;
1412   Local<Value> arg = FIXED_ONE_BYTE_STRING(env->isolate(),
1413                                            "internal/crypto/keys");
1414   if (env->builtin_module_require()
1415           ->Call(context, Null(env->isolate()), 1, &arg)
1416           .IsEmpty()) {
1417     return {};
1418   }
1419   switch (data_->GetKeyType()) {
1420     case kKeyTypeSecret:
1421       key_ctor = env->crypto_key_object_secret_constructor();
1422       break;
1423     case kKeyTypePublic:
1424       key_ctor = env->crypto_key_object_public_constructor();
1425       break;
1426     case kKeyTypePrivate:
1427       key_ctor = env->crypto_key_object_private_constructor();
1428       break;
1429     default:
1430       UNREACHABLE();
1431   }
1432 
1433   Local<Value> key;
1434   if (!key_ctor->NewInstance(context, 1, &handle).ToLocal(&key))
1435     return {};
1436 
1437   return BaseObjectPtr<BaseObject>(Unwrap<KeyObjectHandle>(key.As<Object>()));
1438 }
1439 
GetTransferMode() const1440 BaseObject::TransferMode NativeKeyObject::GetTransferMode() const {
1441   return BaseObject::TransferMode::kCloneable;
1442 }
1443 
CloneForMessaging() const1444 std::unique_ptr<worker::TransferData> NativeKeyObject::CloneForMessaging()
1445     const {
1446   return std::make_unique<KeyObjectTransferData>(handle_data_);
1447 }
1448 
PKEY_SPKI_Export(KeyObjectData * key_data,ByteSource * out)1449 WebCryptoKeyExportStatus PKEY_SPKI_Export(
1450     KeyObjectData* key_data,
1451     ByteSource* out) {
1452   CHECK_EQ(key_data->GetKeyType(), kKeyTypePublic);
1453   ManagedEVPPKey m_pkey = key_data->GetAsymmetricKey();
1454   Mutex::ScopedLock lock(*m_pkey.mutex());
1455   BIOPointer bio(BIO_new(BIO_s_mem()));
1456   CHECK(bio);
1457   if (!i2d_PUBKEY_bio(bio.get(), m_pkey.get()))
1458     return WebCryptoKeyExportStatus::FAILED;
1459 
1460   *out = ByteSource::FromBIO(bio);
1461   return WebCryptoKeyExportStatus::OK;
1462 }
1463 
PKEY_PKCS8_Export(KeyObjectData * key_data,ByteSource * out)1464 WebCryptoKeyExportStatus PKEY_PKCS8_Export(
1465     KeyObjectData* key_data,
1466     ByteSource* out) {
1467   CHECK_EQ(key_data->GetKeyType(), kKeyTypePrivate);
1468   ManagedEVPPKey m_pkey = key_data->GetAsymmetricKey();
1469   Mutex::ScopedLock lock(*m_pkey.mutex());
1470 
1471   BIOPointer bio(BIO_new(BIO_s_mem()));
1472   CHECK(bio);
1473   PKCS8Pointer p8inf(EVP_PKEY2PKCS8(m_pkey.get()));
1474   if (!i2d_PKCS8_PRIV_KEY_INFO_bio(bio.get(), p8inf.get()))
1475     return WebCryptoKeyExportStatus::FAILED;
1476 
1477   *out = ByteSource::FromBIO(bio);
1478   return WebCryptoKeyExportStatus::OK;
1479 }
1480 
1481 namespace Keys {
Initialize(Environment * env,Local<Object> target)1482 void Initialize(Environment* env, Local<Object> target) {
1483   target->Set(env->context(),
1484               FIXED_ONE_BYTE_STRING(env->isolate(), "KeyObjectHandle"),
1485               KeyObjectHandle::Initialize(env)).Check();
1486 
1487   NODE_DEFINE_CONSTANT(target, kWebCryptoKeyFormatRaw);
1488   NODE_DEFINE_CONSTANT(target, kWebCryptoKeyFormatPKCS8);
1489   NODE_DEFINE_CONSTANT(target, kWebCryptoKeyFormatSPKI);
1490   NODE_DEFINE_CONSTANT(target, kWebCryptoKeyFormatJWK);
1491 
1492   NODE_DEFINE_CONSTANT(target, EVP_PKEY_ED25519);
1493   NODE_DEFINE_CONSTANT(target, EVP_PKEY_ED448);
1494   NODE_DEFINE_CONSTANT(target, EVP_PKEY_X25519);
1495   NODE_DEFINE_CONSTANT(target, EVP_PKEY_X448);
1496   NODE_DEFINE_CONSTANT(target, kKeyEncodingPKCS1);
1497   NODE_DEFINE_CONSTANT(target, kKeyEncodingPKCS8);
1498   NODE_DEFINE_CONSTANT(target, kKeyEncodingSPKI);
1499   NODE_DEFINE_CONSTANT(target, kKeyEncodingSEC1);
1500   NODE_DEFINE_CONSTANT(target, kKeyFormatDER);
1501   NODE_DEFINE_CONSTANT(target, kKeyFormatPEM);
1502   NODE_DEFINE_CONSTANT(target, kKeyFormatJWK);
1503   NODE_DEFINE_CONSTANT(target, kKeyTypeSecret);
1504   NODE_DEFINE_CONSTANT(target, kKeyTypePublic);
1505   NODE_DEFINE_CONSTANT(target, kKeyTypePrivate);
1506   NODE_DEFINE_CONSTANT(target, kSigEncDER);
1507   NODE_DEFINE_CONSTANT(target, kSigEncP1363);
1508 }
1509 
RegisterExternalReferences(ExternalReferenceRegistry * registry)1510 void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
1511   KeyObjectHandle::RegisterExternalReferences(registry);
1512 }
1513 }  // namespace Keys
1514 
1515 }  // namespace crypto
1516 }  // namespace node
1517