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 SetProtoMethod(isolate, templ, "export", Export);
912 SetProtoMethod(isolate, templ, "exportJwk", ExportJWK);
913 SetProtoMethod(isolate, templ, "initECRaw", InitECRaw);
914 SetProtoMethod(isolate, templ, "initEDRaw", InitEDRaw);
915 SetProtoMethod(isolate, templ, "initJwk", InitJWK);
916 SetProtoMethod(isolate, templ, "keyDetail", GetKeyDetail);
917 SetProtoMethod(isolate, templ, "equals", Equals);
918
919 env->set_crypto_key_object_handle_constructor(templ);
920 }
921 return templ->GetFunction(env->context()).ToLocalChecked();
922 }
923
RegisterExternalReferences(ExternalReferenceRegistry * registry)924 void KeyObjectHandle::RegisterExternalReferences(
925 ExternalReferenceRegistry* registry) {
926 registry->Register(New);
927 registry->Register(Init);
928 registry->Register(GetSymmetricKeySize);
929 registry->Register(GetAsymmetricKeyType);
930 registry->Register(Export);
931 registry->Register(ExportJWK);
932 registry->Register(InitECRaw);
933 registry->Register(InitEDRaw);
934 registry->Register(InitJWK);
935 registry->Register(GetKeyDetail);
936 registry->Register(Equals);
937 }
938
Create(Environment * env,std::shared_ptr<KeyObjectData> data)939 MaybeLocal<Object> KeyObjectHandle::Create(
940 Environment* env,
941 std::shared_ptr<KeyObjectData> data) {
942 Local<Object> obj;
943 Local<Function> ctor = KeyObjectHandle::Initialize(env);
944 CHECK(!env->crypto_key_object_handle_constructor().IsEmpty());
945 if (!ctor->NewInstance(env->context(), 0, nullptr).ToLocal(&obj))
946 return MaybeLocal<Object>();
947
948 KeyObjectHandle* key = Unwrap<KeyObjectHandle>(obj);
949 CHECK_NOT_NULL(key);
950 key->data_ = data;
951 return obj;
952 }
953
Data()954 const std::shared_ptr<KeyObjectData>& KeyObjectHandle::Data() {
955 return data_;
956 }
957
New(const FunctionCallbackInfo<Value> & args)958 void KeyObjectHandle::New(const FunctionCallbackInfo<Value>& args) {
959 CHECK(args.IsConstructCall());
960 Environment* env = Environment::GetCurrent(args);
961 new KeyObjectHandle(env, args.This());
962 }
963
KeyObjectHandle(Environment * env,Local<Object> wrap)964 KeyObjectHandle::KeyObjectHandle(Environment* env,
965 Local<Object> wrap)
966 : BaseObject(env, wrap) {
967 MakeWeak();
968 }
969
Init(const FunctionCallbackInfo<Value> & args)970 void KeyObjectHandle::Init(const FunctionCallbackInfo<Value>& args) {
971 KeyObjectHandle* key;
972 ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
973 MarkPopErrorOnReturn mark_pop_error_on_return;
974
975 CHECK(args[0]->IsInt32());
976 KeyType type = static_cast<KeyType>(args[0].As<Uint32>()->Value());
977
978 unsigned int offset;
979 ManagedEVPPKey pkey;
980
981 switch (type) {
982 case kKeyTypeSecret: {
983 CHECK_EQ(args.Length(), 2);
984 ArrayBufferOrViewContents<char> buf(args[1]);
985 key->data_ = KeyObjectData::CreateSecret(buf.ToCopy());
986 break;
987 }
988 case kKeyTypePublic: {
989 CHECK_EQ(args.Length(), 5);
990
991 offset = 1;
992 pkey = ManagedEVPPKey::GetPublicOrPrivateKeyFromJs(args, &offset);
993 if (!pkey)
994 return;
995 key->data_ = KeyObjectData::CreateAsymmetric(type, pkey);
996 break;
997 }
998 case kKeyTypePrivate: {
999 CHECK_EQ(args.Length(), 5);
1000
1001 offset = 1;
1002 pkey = ManagedEVPPKey::GetPrivateKeyFromJs(args, &offset, false);
1003 if (!pkey)
1004 return;
1005 key->data_ = KeyObjectData::CreateAsymmetric(type, pkey);
1006 break;
1007 }
1008 default:
1009 UNREACHABLE();
1010 }
1011 }
1012
InitJWK(const FunctionCallbackInfo<Value> & args)1013 void KeyObjectHandle::InitJWK(const FunctionCallbackInfo<Value>& args) {
1014 Environment* env = Environment::GetCurrent(args);
1015 KeyObjectHandle* key;
1016 ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1017 MarkPopErrorOnReturn mark_pop_error_on_return;
1018
1019 // The argument must be a JavaScript object that we will inspect
1020 // to get the JWK properties from.
1021 CHECK(args[0]->IsObject());
1022
1023 // Step one, Secret key or not?
1024 Local<Object> input = args[0].As<Object>();
1025
1026 Local<Value> kty;
1027 if (!input->Get(env->context(), env->jwk_kty_string()).ToLocal(&kty) ||
1028 !kty->IsString()) {
1029 return THROW_ERR_CRYPTO_INVALID_JWK(env);
1030 }
1031
1032 Utf8Value kty_string(env->isolate(), kty);
1033
1034 if (strcmp(*kty_string, "oct") == 0) {
1035 // Secret key
1036 key->data_ = ImportJWKSecretKey(env, input);
1037 if (!key->data_) {
1038 // ImportJWKSecretKey is responsible for throwing an appropriate error
1039 return;
1040 }
1041 } else {
1042 key->data_ = ImportJWKAsymmetricKey(env, input, *kty_string, args, 1);
1043 if (!key->data_) {
1044 // ImportJWKAsymmetricKey is responsible for throwing an appropriate error
1045 return;
1046 }
1047 }
1048
1049 args.GetReturnValue().Set(key->data_->GetKeyType());
1050 }
1051
InitECRaw(const FunctionCallbackInfo<Value> & args)1052 void KeyObjectHandle::InitECRaw(const FunctionCallbackInfo<Value>& args) {
1053 Environment* env = Environment::GetCurrent(args);
1054 KeyObjectHandle* key;
1055 ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1056
1057 CHECK(args[0]->IsString());
1058 Utf8Value name(env->isolate(), args[0]);
1059
1060 MarkPopErrorOnReturn mark_pop_error_on_return;
1061
1062 int id = OBJ_txt2nid(*name);
1063 ECKeyPointer eckey(EC_KEY_new_by_curve_name(id));
1064 if (!eckey)
1065 return args.GetReturnValue().Set(false);
1066
1067 const EC_GROUP* group = EC_KEY_get0_group(eckey.get());
1068 ECPointPointer pub(ECDH::BufferToPoint(env, group, args[1]));
1069
1070 if (!pub ||
1071 !eckey ||
1072 !EC_KEY_set_public_key(eckey.get(), pub.get())) {
1073 return args.GetReturnValue().Set(false);
1074 }
1075
1076 EVPKeyPointer pkey(EVP_PKEY_new());
1077 if (!EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get()))
1078 args.GetReturnValue().Set(false);
1079
1080 eckey.release(); // Release ownership of the key
1081
1082 key->data_ =
1083 KeyObjectData::CreateAsymmetric(
1084 kKeyTypePublic,
1085 ManagedEVPPKey(std::move(pkey)));
1086
1087 args.GetReturnValue().Set(true);
1088 }
1089
InitEDRaw(const FunctionCallbackInfo<Value> & args)1090 void KeyObjectHandle::InitEDRaw(const FunctionCallbackInfo<Value>& args) {
1091 Environment* env = Environment::GetCurrent(args);
1092 KeyObjectHandle* key;
1093 ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1094
1095 CHECK(args[0]->IsString());
1096 Utf8Value name(env->isolate(), args[0]);
1097
1098 ArrayBufferOrViewContents<unsigned char> key_data(args[1]);
1099 KeyType type = static_cast<KeyType>(args[2].As<Int32>()->Value());
1100
1101 MarkPopErrorOnReturn mark_pop_error_on_return;
1102
1103 typedef EVP_PKEY* (*new_key_fn)(int, ENGINE*, const unsigned char*, size_t);
1104 new_key_fn fn = type == kKeyTypePrivate
1105 ? EVP_PKEY_new_raw_private_key
1106 : EVP_PKEY_new_raw_public_key;
1107
1108 int id = GetOKPCurveFromName(*name);
1109
1110 switch (id) {
1111 case EVP_PKEY_X25519:
1112 case EVP_PKEY_X448:
1113 case EVP_PKEY_ED25519:
1114 case EVP_PKEY_ED448: {
1115 EVPKeyPointer pkey(fn(id, nullptr, key_data.data(), key_data.size()));
1116 if (!pkey)
1117 return args.GetReturnValue().Set(false);
1118 key->data_ =
1119 KeyObjectData::CreateAsymmetric(
1120 type,
1121 ManagedEVPPKey(std::move(pkey)));
1122 CHECK(key->data_);
1123 break;
1124 }
1125 default:
1126 UNREACHABLE();
1127 }
1128
1129 args.GetReturnValue().Set(true);
1130 }
1131
Equals(const FunctionCallbackInfo<Value> & args)1132 void KeyObjectHandle::Equals(const FunctionCallbackInfo<Value>& args) {
1133 KeyObjectHandle* self_handle;
1134 KeyObjectHandle* arg_handle;
1135 ASSIGN_OR_RETURN_UNWRAP(&self_handle, args.Holder());
1136 ASSIGN_OR_RETURN_UNWRAP(&arg_handle, args[0].As<Object>());
1137 std::shared_ptr<KeyObjectData> key = self_handle->Data();
1138 std::shared_ptr<KeyObjectData> key2 = arg_handle->Data();
1139
1140 KeyType key_type = key->GetKeyType();
1141 CHECK_EQ(key_type, key2->GetKeyType());
1142
1143 bool ret;
1144 switch (key_type) {
1145 case kKeyTypeSecret: {
1146 size_t size = key->GetSymmetricKeySize();
1147 if (size == key2->GetSymmetricKeySize()) {
1148 ret = CRYPTO_memcmp(
1149 key->GetSymmetricKey(),
1150 key2->GetSymmetricKey(),
1151 size) == 0;
1152 } else {
1153 ret = false;
1154 }
1155 break;
1156 }
1157 case kKeyTypePublic:
1158 case kKeyTypePrivate: {
1159 EVP_PKEY* pkey = key->GetAsymmetricKey().get();
1160 EVP_PKEY* pkey2 = key2->GetAsymmetricKey().get();
1161 #if OPENSSL_VERSION_MAJOR >= 3
1162 int ok = EVP_PKEY_eq(pkey, pkey2);
1163 #else
1164 int ok = EVP_PKEY_cmp(pkey, pkey2);
1165 #endif
1166 if (ok == -2) {
1167 Environment* env = Environment::GetCurrent(args);
1168 return THROW_ERR_CRYPTO_UNSUPPORTED_OPERATION(env);
1169 }
1170 ret = ok == 1;
1171 break;
1172 }
1173 default:
1174 UNREACHABLE("unsupported key type");
1175 }
1176
1177 args.GetReturnValue().Set(ret);
1178 }
1179
GetKeyDetail(const FunctionCallbackInfo<Value> & args)1180 void KeyObjectHandle::GetKeyDetail(const FunctionCallbackInfo<Value>& args) {
1181 Environment* env = Environment::GetCurrent(args);
1182 KeyObjectHandle* key;
1183 ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1184
1185 CHECK(args[0]->IsObject());
1186
1187 std::shared_ptr<KeyObjectData> data = key->Data();
1188
1189 switch (data->GetKeyType()) {
1190 case kKeyTypeSecret:
1191 if (GetSecretKeyDetail(env, data, args[0].As<Object>()).IsNothing())
1192 return;
1193 break;
1194 case kKeyTypePublic:
1195 // Fall through
1196 case kKeyTypePrivate:
1197 if (GetAsymmetricKeyDetail(env, data, args[0].As<Object>()).IsNothing())
1198 return;
1199 break;
1200 default:
1201 UNREACHABLE();
1202 }
1203
1204 args.GetReturnValue().Set(args[0]);
1205 }
1206
GetAsymmetricKeyType() const1207 Local<Value> KeyObjectHandle::GetAsymmetricKeyType() const {
1208 const ManagedEVPPKey& key = data_->GetAsymmetricKey();
1209 switch (EVP_PKEY_id(key.get())) {
1210 case EVP_PKEY_RSA:
1211 return env()->crypto_rsa_string();
1212 case EVP_PKEY_RSA_PSS:
1213 return env()->crypto_rsa_pss_string();
1214 case EVP_PKEY_DSA:
1215 return env()->crypto_dsa_string();
1216 case EVP_PKEY_DH:
1217 return env()->crypto_dh_string();
1218 case EVP_PKEY_EC:
1219 return env()->crypto_ec_string();
1220 case EVP_PKEY_ED25519:
1221 return env()->crypto_ed25519_string();
1222 case EVP_PKEY_ED448:
1223 return env()->crypto_ed448_string();
1224 case EVP_PKEY_X25519:
1225 return env()->crypto_x25519_string();
1226 case EVP_PKEY_X448:
1227 return env()->crypto_x448_string();
1228 default:
1229 return Undefined(env()->isolate());
1230 }
1231 }
1232
GetAsymmetricKeyType(const FunctionCallbackInfo<Value> & args)1233 void KeyObjectHandle::GetAsymmetricKeyType(
1234 const FunctionCallbackInfo<Value>& args) {
1235 KeyObjectHandle* key;
1236 ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1237
1238 args.GetReturnValue().Set(key->GetAsymmetricKeyType());
1239 }
1240
GetSymmetricKeySize(const FunctionCallbackInfo<Value> & args)1241 void KeyObjectHandle::GetSymmetricKeySize(
1242 const FunctionCallbackInfo<Value>& args) {
1243 KeyObjectHandle* key;
1244 ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1245 args.GetReturnValue().Set(
1246 static_cast<uint32_t>(key->Data()->GetSymmetricKeySize()));
1247 }
1248
Export(const FunctionCallbackInfo<Value> & args)1249 void KeyObjectHandle::Export(const FunctionCallbackInfo<Value>& args) {
1250 KeyObjectHandle* key;
1251 ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1252
1253 KeyType type = key->Data()->GetKeyType();
1254
1255 MaybeLocal<Value> result;
1256 if (type == kKeyTypeSecret) {
1257 result = key->ExportSecretKey();
1258 } else if (type == kKeyTypePublic) {
1259 unsigned int offset = 0;
1260 PublicKeyEncodingConfig config =
1261 ManagedEVPPKey::GetPublicKeyEncodingFromJs(
1262 args, &offset, kKeyContextExport);
1263 CHECK_EQ(offset, static_cast<unsigned int>(args.Length()));
1264 result = key->ExportPublicKey(config);
1265 } else {
1266 CHECK_EQ(type, kKeyTypePrivate);
1267 unsigned int offset = 0;
1268 NonCopyableMaybe<PrivateKeyEncodingConfig> config =
1269 ManagedEVPPKey::GetPrivateKeyEncodingFromJs(
1270 args, &offset, kKeyContextExport);
1271 if (config.IsEmpty())
1272 return;
1273 CHECK_EQ(offset, static_cast<unsigned int>(args.Length()));
1274 result = key->ExportPrivateKey(config.Release());
1275 }
1276
1277 if (!result.IsEmpty())
1278 args.GetReturnValue().Set(result.FromMaybe(Local<Value>()));
1279 }
1280
ExportSecretKey() const1281 MaybeLocal<Value> KeyObjectHandle::ExportSecretKey() const {
1282 const char* buf = data_->GetSymmetricKey();
1283 unsigned int len = data_->GetSymmetricKeySize();
1284 return Buffer::Copy(env(), buf, len).FromMaybe(Local<Value>());
1285 }
1286
ExportPublicKey(const PublicKeyEncodingConfig & config) const1287 MaybeLocal<Value> KeyObjectHandle::ExportPublicKey(
1288 const PublicKeyEncodingConfig& config) const {
1289 return WritePublicKey(env(), data_->GetAsymmetricKey().get(), config);
1290 }
1291
ExportPrivateKey(const PrivateKeyEncodingConfig & config) const1292 MaybeLocal<Value> KeyObjectHandle::ExportPrivateKey(
1293 const PrivateKeyEncodingConfig& config) const {
1294 return WritePrivateKey(env(), data_->GetAsymmetricKey().get(), config);
1295 }
1296
ExportJWK(const v8::FunctionCallbackInfo<v8::Value> & args)1297 void KeyObjectHandle::ExportJWK(
1298 const v8::FunctionCallbackInfo<v8::Value>& args) {
1299 Environment* env = Environment::GetCurrent(args);
1300 KeyObjectHandle* key;
1301 ASSIGN_OR_RETURN_UNWRAP(&key, args.Holder());
1302
1303 CHECK(args[0]->IsObject());
1304 CHECK(args[1]->IsBoolean());
1305
1306 ExportJWKInner(env, key->Data(), args[0], args[1]->IsTrue());
1307
1308 args.GetReturnValue().Set(args[0]);
1309 }
1310
Initialize(Environment * env,Local<Object> target)1311 void NativeKeyObject::Initialize(Environment* env, Local<Object> target) {
1312 SetMethod(env->context(),
1313 target,
1314 "createNativeKeyObjectClass",
1315 NativeKeyObject::CreateNativeKeyObjectClass);
1316 }
1317
RegisterExternalReferences(ExternalReferenceRegistry * registry)1318 void NativeKeyObject::RegisterExternalReferences(
1319 ExternalReferenceRegistry* registry) {
1320 registry->Register(NativeKeyObject::CreateNativeKeyObjectClass);
1321 registry->Register(NativeKeyObject::New);
1322 }
1323
New(const FunctionCallbackInfo<Value> & args)1324 void NativeKeyObject::New(const FunctionCallbackInfo<Value>& args) {
1325 Environment* env = Environment::GetCurrent(args);
1326 CHECK_EQ(args.Length(), 1);
1327 CHECK(args[0]->IsObject());
1328 KeyObjectHandle* handle = Unwrap<KeyObjectHandle>(args[0].As<Object>());
1329 new NativeKeyObject(env, args.This(), handle->Data());
1330 }
1331
CreateNativeKeyObjectClass(const FunctionCallbackInfo<Value> & args)1332 void NativeKeyObject::CreateNativeKeyObjectClass(
1333 const FunctionCallbackInfo<Value>& args) {
1334 Environment* env = Environment::GetCurrent(args);
1335 Isolate* isolate = env->isolate();
1336
1337 CHECK_EQ(args.Length(), 1);
1338 Local<Value> callback = args[0];
1339 CHECK(callback->IsFunction());
1340
1341 Local<FunctionTemplate> t =
1342 NewFunctionTemplate(isolate, NativeKeyObject::New);
1343 t->InstanceTemplate()->SetInternalFieldCount(
1344 KeyObjectHandle::kInternalFieldCount);
1345 t->Inherit(BaseObject::GetConstructorTemplate(env));
1346
1347 Local<Value> ctor;
1348 if (!t->GetFunction(env->context()).ToLocal(&ctor))
1349 return;
1350
1351 Local<Value> recv = Undefined(env->isolate());
1352 Local<Value> ret_v;
1353 if (!callback.As<Function>()->Call(
1354 env->context(), recv, 1, &ctor).ToLocal(&ret_v)) {
1355 return;
1356 }
1357 Local<Array> ret = ret_v.As<Array>();
1358 if (!ret->Get(env->context(), 1).ToLocal(&ctor)) return;
1359 env->set_crypto_key_object_secret_constructor(ctor.As<Function>());
1360 if (!ret->Get(env->context(), 2).ToLocal(&ctor)) return;
1361 env->set_crypto_key_object_public_constructor(ctor.As<Function>());
1362 if (!ret->Get(env->context(), 3).ToLocal(&ctor)) return;
1363 env->set_crypto_key_object_private_constructor(ctor.As<Function>());
1364 args.GetReturnValue().Set(ret);
1365 }
1366
Deserialize(Environment * env,Local<Context> context,std::unique_ptr<worker::TransferData> self)1367 BaseObjectPtr<BaseObject> NativeKeyObject::KeyObjectTransferData::Deserialize(
1368 Environment* env,
1369 Local<Context> context,
1370 std::unique_ptr<worker::TransferData> self) {
1371 if (context != env->context()) {
1372 THROW_ERR_MESSAGE_TARGET_CONTEXT_UNAVAILABLE(env);
1373 return {};
1374 }
1375
1376 Local<Value> handle;
1377 if (!KeyObjectHandle::Create(env, data_).ToLocal(&handle))
1378 return {};
1379
1380 Local<Function> key_ctor;
1381 Local<Value> arg = FIXED_ONE_BYTE_STRING(env->isolate(),
1382 "internal/crypto/keys");
1383 if (env->builtin_module_require()
1384 ->Call(context, Null(env->isolate()), 1, &arg)
1385 .IsEmpty()) {
1386 return {};
1387 }
1388 switch (data_->GetKeyType()) {
1389 case kKeyTypeSecret:
1390 key_ctor = env->crypto_key_object_secret_constructor();
1391 break;
1392 case kKeyTypePublic:
1393 key_ctor = env->crypto_key_object_public_constructor();
1394 break;
1395 case kKeyTypePrivate:
1396 key_ctor = env->crypto_key_object_private_constructor();
1397 break;
1398 default:
1399 UNREACHABLE();
1400 }
1401
1402 Local<Value> key;
1403 if (!key_ctor->NewInstance(context, 1, &handle).ToLocal(&key))
1404 return {};
1405
1406 return BaseObjectPtr<BaseObject>(Unwrap<KeyObjectHandle>(key.As<Object>()));
1407 }
1408
GetTransferMode() const1409 BaseObject::TransferMode NativeKeyObject::GetTransferMode() const {
1410 return BaseObject::TransferMode::kCloneable;
1411 }
1412
CloneForMessaging() const1413 std::unique_ptr<worker::TransferData> NativeKeyObject::CloneForMessaging()
1414 const {
1415 return std::make_unique<KeyObjectTransferData>(handle_data_);
1416 }
1417
PKEY_SPKI_Export(KeyObjectData * key_data,ByteSource * out)1418 WebCryptoKeyExportStatus PKEY_SPKI_Export(
1419 KeyObjectData* key_data,
1420 ByteSource* out) {
1421 CHECK_EQ(key_data->GetKeyType(), kKeyTypePublic);
1422 ManagedEVPPKey m_pkey = key_data->GetAsymmetricKey();
1423 Mutex::ScopedLock lock(*m_pkey.mutex());
1424 BIOPointer bio(BIO_new(BIO_s_mem()));
1425 CHECK(bio);
1426 if (!i2d_PUBKEY_bio(bio.get(), m_pkey.get()))
1427 return WebCryptoKeyExportStatus::FAILED;
1428
1429 *out = ByteSource::FromBIO(bio);
1430 return WebCryptoKeyExportStatus::OK;
1431 }
1432
PKEY_PKCS8_Export(KeyObjectData * key_data,ByteSource * out)1433 WebCryptoKeyExportStatus PKEY_PKCS8_Export(
1434 KeyObjectData* key_data,
1435 ByteSource* out) {
1436 CHECK_EQ(key_data->GetKeyType(), kKeyTypePrivate);
1437 ManagedEVPPKey m_pkey = key_data->GetAsymmetricKey();
1438 Mutex::ScopedLock lock(*m_pkey.mutex());
1439
1440 BIOPointer bio(BIO_new(BIO_s_mem()));
1441 CHECK(bio);
1442 PKCS8Pointer p8inf(EVP_PKEY2PKCS8(m_pkey.get()));
1443 if (!i2d_PKCS8_PRIV_KEY_INFO_bio(bio.get(), p8inf.get()))
1444 return WebCryptoKeyExportStatus::FAILED;
1445
1446 *out = ByteSource::FromBIO(bio);
1447 return WebCryptoKeyExportStatus::OK;
1448 }
1449
1450 namespace Keys {
Initialize(Environment * env,Local<Object> target)1451 void Initialize(Environment* env, Local<Object> target) {
1452 target->Set(env->context(),
1453 FIXED_ONE_BYTE_STRING(env->isolate(), "KeyObjectHandle"),
1454 KeyObjectHandle::Initialize(env)).Check();
1455
1456 NODE_DEFINE_CONSTANT(target, kWebCryptoKeyFormatRaw);
1457 NODE_DEFINE_CONSTANT(target, kWebCryptoKeyFormatPKCS8);
1458 NODE_DEFINE_CONSTANT(target, kWebCryptoKeyFormatSPKI);
1459 NODE_DEFINE_CONSTANT(target, kWebCryptoKeyFormatJWK);
1460
1461 NODE_DEFINE_CONSTANT(target, EVP_PKEY_ED25519);
1462 NODE_DEFINE_CONSTANT(target, EVP_PKEY_ED448);
1463 NODE_DEFINE_CONSTANT(target, EVP_PKEY_X25519);
1464 NODE_DEFINE_CONSTANT(target, EVP_PKEY_X448);
1465 NODE_DEFINE_CONSTANT(target, kKeyEncodingPKCS1);
1466 NODE_DEFINE_CONSTANT(target, kKeyEncodingPKCS8);
1467 NODE_DEFINE_CONSTANT(target, kKeyEncodingSPKI);
1468 NODE_DEFINE_CONSTANT(target, kKeyEncodingSEC1);
1469 NODE_DEFINE_CONSTANT(target, kKeyFormatDER);
1470 NODE_DEFINE_CONSTANT(target, kKeyFormatPEM);
1471 NODE_DEFINE_CONSTANT(target, kKeyFormatJWK);
1472 NODE_DEFINE_CONSTANT(target, kKeyTypeSecret);
1473 NODE_DEFINE_CONSTANT(target, kKeyTypePublic);
1474 NODE_DEFINE_CONSTANT(target, kKeyTypePrivate);
1475 NODE_DEFINE_CONSTANT(target, kSigEncDER);
1476 NODE_DEFINE_CONSTANT(target, kSigEncP1363);
1477 }
1478
RegisterExternalReferences(ExternalReferenceRegistry * registry)1479 void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
1480 KeyObjectHandle::RegisterExternalReferences(registry);
1481 }
1482 } // namespace Keys
1483
1484 } // namespace crypto
1485 } // namespace node
1486