1#include "base_object-inl.h" 2#include "crypto_x509.h" 3#include "crypto_common.h" 4#include "crypto_context.h" 5#include "crypto_keys.h" 6#include "crypto_bio.h" 7#include "env-inl.h" 8#include "memory_tracker-inl.h" 9#include "node_errors.h" 10#include "util-inl.h" 11#include "v8.h" 12 13#include <string> 14#include <vector> 15 16namespace node { 17 18using v8::ArrayBufferView; 19using v8::Context; 20using v8::EscapableHandleScope; 21using v8::Function; 22using v8::FunctionCallbackInfo; 23using v8::FunctionTemplate; 24using v8::Isolate; 25using v8::Local; 26using v8::MaybeLocal; 27using v8::Object; 28using v8::Uint32; 29using v8::Value; 30 31namespace crypto { 32 33ManagedX509::ManagedX509(X509Pointer&& cert) : cert_(std::move(cert)) {} 34 35ManagedX509::ManagedX509(const ManagedX509& that) { 36 *this = that; 37} 38 39ManagedX509& ManagedX509::operator=(const ManagedX509& that) { 40 cert_.reset(that.get()); 41 42 if (cert_) 43 X509_up_ref(cert_.get()); 44 45 return *this; 46} 47 48void ManagedX509::MemoryInfo(MemoryTracker* tracker) const { 49 // This is an approximation based on the der encoding size. 50 int size = i2d_X509(cert_.get(), nullptr); 51 tracker->TrackFieldWithSize("cert", size); 52} 53 54namespace { 55template <const EVP_MD* (*algo)()> 56void Fingerprint(const FunctionCallbackInfo<Value>& args) { 57 Environment* env = Environment::GetCurrent(args); 58 X509Certificate* cert; 59 ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); 60 Local<Value> ret; 61 if (GetFingerprintDigest(env, algo(), cert->get()).ToLocal(&ret)) 62 args.GetReturnValue().Set(ret); 63} 64} // namespace 65 66Local<FunctionTemplate> X509Certificate::GetConstructorTemplate( 67 Environment* env) { 68 Local<FunctionTemplate> tmpl = env->x509_constructor_template(); 69 if (tmpl.IsEmpty()) { 70 Isolate* isolate = env->isolate(); 71 tmpl = NewFunctionTemplate(isolate, nullptr); 72 tmpl->InstanceTemplate()->SetInternalFieldCount( 73 BaseObject::kInternalFieldCount); 74 tmpl->Inherit(BaseObject::GetConstructorTemplate(env)); 75 tmpl->SetClassName( 76 FIXED_ONE_BYTE_STRING(env->isolate(), "X509Certificate")); 77 SetProtoMethod(isolate, tmpl, "subject", Subject); 78 SetProtoMethod(isolate, tmpl, "subjectAltName", SubjectAltName); 79 SetProtoMethod(isolate, tmpl, "infoAccess", InfoAccess); 80 SetProtoMethod(isolate, tmpl, "issuer", Issuer); 81 SetProtoMethod(isolate, tmpl, "validTo", ValidTo); 82 SetProtoMethod(isolate, tmpl, "validFrom", ValidFrom); 83 SetProtoMethod(isolate, tmpl, "fingerprint", Fingerprint<EVP_sha1>); 84 SetProtoMethod(isolate, tmpl, "fingerprint256", Fingerprint<EVP_sha256>); 85 SetProtoMethod(isolate, tmpl, "fingerprint512", Fingerprint<EVP_sha512>); 86 SetProtoMethod(isolate, tmpl, "keyUsage", KeyUsage); 87 SetProtoMethod(isolate, tmpl, "serialNumber", SerialNumber); 88 SetProtoMethod(isolate, tmpl, "pem", Pem); 89 SetProtoMethod(isolate, tmpl, "raw", Raw); 90 SetProtoMethod(isolate, tmpl, "publicKey", PublicKey); 91 SetProtoMethod(isolate, tmpl, "checkCA", CheckCA); 92 SetProtoMethod(isolate, tmpl, "checkHost", CheckHost); 93 SetProtoMethod(isolate, tmpl, "checkEmail", CheckEmail); 94 SetProtoMethod(isolate, tmpl, "checkIP", CheckIP); 95 SetProtoMethod(isolate, tmpl, "checkIssued", CheckIssued); 96 SetProtoMethod(isolate, tmpl, "checkPrivateKey", CheckPrivateKey); 97 SetProtoMethod(isolate, tmpl, "verify", Verify); 98 SetProtoMethod(isolate, tmpl, "toLegacy", ToLegacy); 99 SetProtoMethod(isolate, tmpl, "getIssuerCert", GetIssuerCert); 100 env->set_x509_constructor_template(tmpl); 101 } 102 return tmpl; 103} 104 105bool X509Certificate::HasInstance(Environment* env, Local<Object> object) { 106 return GetConstructorTemplate(env)->HasInstance(object); 107} 108 109MaybeLocal<Object> X509Certificate::New( 110 Environment* env, 111 X509Pointer cert, 112 STACK_OF(X509)* issuer_chain) { 113 std::shared_ptr<ManagedX509> mcert(new ManagedX509(std::move(cert))); 114 return New(env, std::move(mcert), issuer_chain); 115} 116 117MaybeLocal<Object> X509Certificate::New( 118 Environment* env, 119 std::shared_ptr<ManagedX509> cert, 120 STACK_OF(X509)* issuer_chain) { 121 EscapableHandleScope scope(env->isolate()); 122 Local<Function> ctor; 123 if (!GetConstructorTemplate(env)->GetFunction(env->context()).ToLocal(&ctor)) 124 return MaybeLocal<Object>(); 125 126 Local<Object> obj; 127 if (!ctor->NewInstance(env->context()).ToLocal(&obj)) 128 return MaybeLocal<Object>(); 129 130 new X509Certificate(env, obj, std::move(cert), issuer_chain); 131 return scope.Escape(obj); 132} 133 134MaybeLocal<Object> X509Certificate::GetCert( 135 Environment* env, 136 const SSLPointer& ssl) { 137 ClearErrorOnReturn clear_error_on_return; 138 X509* cert = SSL_get_certificate(ssl.get()); 139 if (cert == nullptr) 140 return MaybeLocal<Object>(); 141 142 X509Pointer ptr(X509_dup(cert)); 143 return New(env, std::move(ptr)); 144} 145 146MaybeLocal<Object> X509Certificate::GetPeerCert( 147 Environment* env, 148 const SSLPointer& ssl, 149 GetPeerCertificateFlag flag) { 150 ClearErrorOnReturn clear_error_on_return; 151 MaybeLocal<Object> maybe_cert; 152 153 bool is_server = 154 static_cast<int>(flag) & static_cast<int>(GetPeerCertificateFlag::SERVER); 155 156 X509Pointer cert(is_server ? SSL_get_peer_certificate(ssl.get()) : nullptr); 157 STACK_OF(X509)* ssl_certs = SSL_get_peer_cert_chain(ssl.get()); 158 if (!cert && (ssl_certs == nullptr || sk_X509_num(ssl_certs) == 0)) 159 return MaybeLocal<Object>(); 160 161 std::vector<Local<Value>> certs; 162 163 if (!cert) { 164 cert.reset(sk_X509_value(ssl_certs, 0)); 165 sk_X509_delete(ssl_certs, 0); 166 } 167 168 return sk_X509_num(ssl_certs) 169 ? New(env, std::move(cert), ssl_certs) 170 : New(env, std::move(cert)); 171} 172 173void X509Certificate::Parse(const FunctionCallbackInfo<Value>& args) { 174 Environment* env = Environment::GetCurrent(args); 175 176 CHECK(args[0]->IsArrayBufferView()); 177 ArrayBufferViewContents<unsigned char> buf(args[0].As<ArrayBufferView>()); 178 const unsigned char* data = buf.data(); 179 unsigned data_len = buf.length(); 180 181 ClearErrorOnReturn clear_error_on_return; 182 BIOPointer bio(LoadBIO(env, args[0])); 183 if (!bio) 184 return ThrowCryptoError(env, ERR_get_error()); 185 186 Local<Object> cert; 187 188 X509Pointer pem(PEM_read_bio_X509_AUX( 189 bio.get(), nullptr, NoPasswordCallback, nullptr)); 190 if (!pem) { 191 // Try as DER, but return the original PEM failure if it isn't DER. 192 MarkPopErrorOnReturn mark_here; 193 194 X509Pointer der(d2i_X509(nullptr, &data, data_len)); 195 if (!der) 196 return ThrowCryptoError(env, ERR_get_error()); 197 198 if (!X509Certificate::New(env, std::move(der)).ToLocal(&cert)) 199 return; 200 } else if (!X509Certificate::New(env, std::move(pem)).ToLocal(&cert)) { 201 return; 202 } 203 204 args.GetReturnValue().Set(cert); 205} 206 207template <MaybeLocal<Value> Property( 208 Environment* env, X509* cert, const BIOPointer& bio)> 209static void ReturnPropertyThroughBIO(const FunctionCallbackInfo<Value>& args) { 210 Environment* env = Environment::GetCurrent(args); 211 X509Certificate* cert; 212 ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); 213 BIOPointer bio(BIO_new(BIO_s_mem())); 214 CHECK(bio); 215 Local<Value> ret; 216 if (Property(env, cert->get(), bio).ToLocal(&ret)) 217 args.GetReturnValue().Set(ret); 218} 219 220void X509Certificate::Subject(const FunctionCallbackInfo<Value>& args) { 221 ReturnPropertyThroughBIO<GetSubject>(args); 222} 223 224void X509Certificate::Issuer(const FunctionCallbackInfo<Value>& args) { 225 ReturnPropertyThroughBIO<GetIssuerString>(args); 226} 227 228void X509Certificate::SubjectAltName(const FunctionCallbackInfo<Value>& args) { 229 ReturnPropertyThroughBIO<GetSubjectAltNameString>(args); 230} 231 232void X509Certificate::InfoAccess(const FunctionCallbackInfo<Value>& args) { 233 ReturnPropertyThroughBIO<GetInfoAccessString>(args); 234} 235 236void X509Certificate::ValidFrom(const FunctionCallbackInfo<Value>& args) { 237 ReturnPropertyThroughBIO<GetValidFrom>(args); 238} 239 240void X509Certificate::ValidTo(const FunctionCallbackInfo<Value>& args) { 241 ReturnPropertyThroughBIO<GetValidTo>(args); 242} 243 244template <MaybeLocal<Value> Property(Environment* env, X509* cert)> 245static void ReturnProperty(const FunctionCallbackInfo<Value>& args) { 246 Environment* env = Environment::GetCurrent(args); 247 X509Certificate* cert; 248 ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); 249 Local<Value> ret; 250 if (Property(env, cert->get()).ToLocal(&ret)) args.GetReturnValue().Set(ret); 251} 252 253void X509Certificate::KeyUsage(const FunctionCallbackInfo<Value>& args) { 254 ReturnProperty<GetKeyUsage>(args); 255} 256 257void X509Certificate::SerialNumber(const FunctionCallbackInfo<Value>& args) { 258 ReturnProperty<GetSerialNumber>(args); 259} 260 261void X509Certificate::Raw(const FunctionCallbackInfo<Value>& args) { 262 ReturnProperty<GetRawDERCertificate>(args); 263} 264 265void X509Certificate::PublicKey(const FunctionCallbackInfo<Value>& args) { 266 Environment* env = Environment::GetCurrent(args); 267 X509Certificate* cert; 268 ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); 269 270 // TODO(tniessen): consider checking X509_get_pubkey() when the 271 // X509Certificate object is being created. 272 ClearErrorOnReturn clear_error_on_return; 273 EVPKeyPointer pkey(X509_get_pubkey(cert->get())); 274 if (!pkey) return ThrowCryptoError(env, ERR_get_error()); 275 ManagedEVPPKey epkey(std::move(pkey)); 276 std::shared_ptr<KeyObjectData> key_data = 277 KeyObjectData::CreateAsymmetric(kKeyTypePublic, epkey); 278 279 Local<Value> ret; 280 if (KeyObjectHandle::Create(env, key_data).ToLocal(&ret)) 281 args.GetReturnValue().Set(ret); 282} 283 284void X509Certificate::Pem(const FunctionCallbackInfo<Value>& args) { 285 Environment* env = Environment::GetCurrent(args); 286 X509Certificate* cert; 287 ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); 288 BIOPointer bio(BIO_new(BIO_s_mem())); 289 CHECK(bio); 290 if (PEM_write_bio_X509(bio.get(), cert->get())) 291 args.GetReturnValue().Set(ToV8Value(env, bio)); 292} 293 294void X509Certificate::CheckCA(const FunctionCallbackInfo<Value>& args) { 295 X509Certificate* cert; 296 ClearErrorOnReturn clear_error_on_return; 297 ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); 298 args.GetReturnValue().Set(X509_check_ca(cert->get()) == 1); 299} 300 301void X509Certificate::CheckHost(const FunctionCallbackInfo<Value>& args) { 302 Environment* env = Environment::GetCurrent(args); 303 X509Certificate* cert; 304 ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); 305 306 CHECK(args[0]->IsString()); // name 307 CHECK(args[1]->IsUint32()); // flags 308 309 Utf8Value name(env->isolate(), args[0]); 310 uint32_t flags = args[1].As<Uint32>()->Value(); 311 char* peername; 312 313 switch (X509_check_host( 314 cert->get(), 315 *name, 316 name.length(), 317 flags, 318 &peername)) { 319 case 1: { // Match! 320 Local<Value> ret = args[0]; 321 if (peername != nullptr) { 322 ret = OneByteString(env->isolate(), peername); 323 OPENSSL_free(peername); 324 } 325 return args.GetReturnValue().Set(ret); 326 } 327 case 0: // No Match! 328 return; // No return value is set 329 case -2: // Error! 330 return THROW_ERR_INVALID_ARG_VALUE(env, "Invalid name"); 331 default: // Error! 332 return THROW_ERR_CRYPTO_OPERATION_FAILED(env); 333 } 334} 335 336void X509Certificate::CheckEmail(const FunctionCallbackInfo<Value>& args) { 337 Environment* env = Environment::GetCurrent(args); 338 X509Certificate* cert; 339 ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); 340 341 CHECK(args[0]->IsString()); // name 342 CHECK(args[1]->IsUint32()); // flags 343 344 Utf8Value name(env->isolate(), args[0]); 345 uint32_t flags = args[1].As<Uint32>()->Value(); 346 347 switch (X509_check_email( 348 cert->get(), 349 *name, 350 name.length(), 351 flags)) { 352 case 1: // Match! 353 return args.GetReturnValue().Set(args[0]); 354 case 0: // No Match! 355 return; // No return value is set 356 case -2: // Error! 357 return THROW_ERR_INVALID_ARG_VALUE(env, "Invalid name"); 358 default: // Error! 359 return THROW_ERR_CRYPTO_OPERATION_FAILED(env); 360 } 361} 362 363void X509Certificate::CheckIP(const FunctionCallbackInfo<Value>& args) { 364 Environment* env = Environment::GetCurrent(args); 365 X509Certificate* cert; 366 ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); 367 368 CHECK(args[0]->IsString()); // IP 369 CHECK(args[1]->IsUint32()); // flags 370 371 Utf8Value name(env->isolate(), args[0]); 372 uint32_t flags = args[1].As<Uint32>()->Value(); 373 374 switch (X509_check_ip_asc(cert->get(), *name, flags)) { 375 case 1: // Match! 376 return args.GetReturnValue().Set(args[0]); 377 case 0: // No Match! 378 return; // No return value is set 379 case -2: // Error! 380 return THROW_ERR_INVALID_ARG_VALUE(env, "Invalid IP"); 381 default: // Error! 382 return THROW_ERR_CRYPTO_OPERATION_FAILED(env); 383 } 384} 385 386void X509Certificate::CheckIssued(const FunctionCallbackInfo<Value>& args) { 387 Environment* env = Environment::GetCurrent(args); 388 X509Certificate* cert; 389 ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); 390 391 CHECK(args[0]->IsObject()); 392 CHECK(X509Certificate::HasInstance(env, args[0].As<Object>())); 393 394 X509Certificate* issuer; 395 ASSIGN_OR_RETURN_UNWRAP(&issuer, args[0]); 396 397 ClearErrorOnReturn clear_error_on_return; 398 399 args.GetReturnValue().Set( 400 X509_check_issued(issuer->get(), cert->get()) == X509_V_OK); 401} 402 403void X509Certificate::CheckPrivateKey(const FunctionCallbackInfo<Value>& args) { 404 X509Certificate* cert; 405 ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); 406 407 CHECK(args[0]->IsObject()); 408 KeyObjectHandle* key; 409 ASSIGN_OR_RETURN_UNWRAP(&key, args[0]); 410 CHECK_EQ(key->Data()->GetKeyType(), kKeyTypePrivate); 411 412 ClearErrorOnReturn clear_error_on_return; 413 414 args.GetReturnValue().Set( 415 X509_check_private_key( 416 cert->get(), 417 key->Data()->GetAsymmetricKey().get()) == 1); 418} 419 420void X509Certificate::Verify(const FunctionCallbackInfo<Value>& args) { 421 X509Certificate* cert; 422 ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); 423 424 CHECK(args[0]->IsObject()); 425 KeyObjectHandle* key; 426 ASSIGN_OR_RETURN_UNWRAP(&key, args[0]); 427 CHECK_EQ(key->Data()->GetKeyType(), kKeyTypePublic); 428 429 ClearErrorOnReturn clear_error_on_return; 430 431 args.GetReturnValue().Set( 432 X509_verify( 433 cert->get(), 434 key->Data()->GetAsymmetricKey().get()) > 0); 435} 436 437void X509Certificate::ToLegacy(const FunctionCallbackInfo<Value>& args) { 438 Environment* env = Environment::GetCurrent(args); 439 X509Certificate* cert; 440 ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); 441 ClearErrorOnReturn clear_error_on_return; 442 Local<Value> ret; 443 if (X509ToObject(env, cert->get()).ToLocal(&ret)) 444 args.GetReturnValue().Set(ret); 445} 446 447void X509Certificate::GetIssuerCert(const FunctionCallbackInfo<Value>& args) { 448 X509Certificate* cert; 449 ASSIGN_OR_RETURN_UNWRAP(&cert, args.Holder()); 450 if (cert->issuer_cert_) 451 args.GetReturnValue().Set(cert->issuer_cert_->object()); 452} 453 454X509Certificate::X509Certificate( 455 Environment* env, 456 Local<Object> object, 457 std::shared_ptr<ManagedX509> cert, 458 STACK_OF(X509)* issuer_chain) 459 : BaseObject(env, object), 460 cert_(std::move(cert)) { 461 MakeWeak(); 462 463 if (issuer_chain != nullptr && sk_X509_num(issuer_chain)) { 464 X509Pointer cert(X509_dup(sk_X509_value(issuer_chain, 0))); 465 sk_X509_delete(issuer_chain, 0); 466 Local<Object> obj = sk_X509_num(issuer_chain) 467 ? X509Certificate::New(env, std::move(cert), issuer_chain) 468 .ToLocalChecked() 469 : X509Certificate::New(env, std::move(cert)) 470 .ToLocalChecked(); 471 issuer_cert_.reset(Unwrap<X509Certificate>(obj)); 472 } 473} 474 475void X509Certificate::MemoryInfo(MemoryTracker* tracker) const { 476 tracker->TrackField("cert", cert_); 477} 478 479BaseObjectPtr<BaseObject> 480X509Certificate::X509CertificateTransferData::Deserialize( 481 Environment* env, 482 Local<Context> context, 483 std::unique_ptr<worker::TransferData> self) { 484 if (context != env->context()) { 485 THROW_ERR_MESSAGE_TARGET_CONTEXT_UNAVAILABLE(env); 486 return {}; 487 } 488 489 Local<Value> handle; 490 if (!X509Certificate::New(env, data_).ToLocal(&handle)) 491 return {}; 492 493 return BaseObjectPtr<BaseObject>( 494 Unwrap<X509Certificate>(handle.As<Object>())); 495} 496 497 498BaseObject::TransferMode X509Certificate::GetTransferMode() const { 499 return BaseObject::TransferMode::kCloneable; 500} 501 502std::unique_ptr<worker::TransferData> X509Certificate::CloneForMessaging() 503 const { 504 return std::make_unique<X509CertificateTransferData>(cert_); 505} 506 507 508void X509Certificate::Initialize(Environment* env, Local<Object> target) { 509 SetMethod(env->context(), target, "parseX509", X509Certificate::Parse); 510 511 NODE_DEFINE_CONSTANT(target, X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT); 512 NODE_DEFINE_CONSTANT(target, X509_CHECK_FLAG_NEVER_CHECK_SUBJECT); 513 NODE_DEFINE_CONSTANT(target, X509_CHECK_FLAG_NO_WILDCARDS); 514 NODE_DEFINE_CONSTANT(target, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); 515 NODE_DEFINE_CONSTANT(target, X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS); 516 NODE_DEFINE_CONSTANT(target, X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS); 517} 518 519void X509Certificate::RegisterExternalReferences( 520 ExternalReferenceRegistry* registry) { 521 registry->Register(X509Certificate::Parse); 522 registry->Register(Subject); 523 registry->Register(SubjectAltName); 524 registry->Register(InfoAccess); 525 registry->Register(Issuer); 526 registry->Register(ValidTo); 527 registry->Register(ValidFrom); 528 registry->Register(Fingerprint<EVP_sha1>); 529 registry->Register(Fingerprint<EVP_sha256>); 530 registry->Register(Fingerprint<EVP_sha512>); 531 registry->Register(KeyUsage); 532 registry->Register(SerialNumber); 533 registry->Register(Pem); 534 registry->Register(Raw); 535 registry->Register(PublicKey); 536 registry->Register(CheckCA); 537 registry->Register(CheckHost); 538 registry->Register(CheckEmail); 539 registry->Register(CheckIP); 540 registry->Register(CheckIssued); 541 registry->Register(CheckPrivateKey); 542 registry->Register(Verify); 543 registry->Register(ToLegacy); 544 registry->Register(GetIssuerCert); 545} 546} // namespace crypto 547} // namespace node 548