• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 namespace node {
17 
18 using v8::ArrayBufferView;
19 using v8::Context;
20 using v8::EscapableHandleScope;
21 using v8::Function;
22 using v8::FunctionCallbackInfo;
23 using v8::FunctionTemplate;
24 using v8::Isolate;
25 using v8::Local;
26 using v8::MaybeLocal;
27 using v8::Object;
28 using v8::Uint32;
29 using v8::Value;
30 
31 namespace crypto {
32 
ManagedX509(X509Pointer && cert)33 ManagedX509::ManagedX509(X509Pointer&& cert) : cert_(std::move(cert)) {}
34 
ManagedX509(const ManagedX509 & that)35 ManagedX509::ManagedX509(const ManagedX509& that) {
36   *this = that;
37 }
38 
operator =(const ManagedX509 & that)39 ManagedX509& 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 
MemoryInfo(MemoryTracker * tracker) const48 void 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 
54 namespace {
55 template <const EVP_MD* (*algo)()>
Fingerprint(const FunctionCallbackInfo<Value> & args)56 void 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 
GetConstructorTemplate(Environment * env)66 Local<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 
HasInstance(Environment * env,Local<Object> object)105 bool X509Certificate::HasInstance(Environment* env, Local<Object> object) {
106   return GetConstructorTemplate(env)->HasInstance(object);
107 }
108 
New(Environment * env,X509Pointer cert,STACK_OF (X509)* issuer_chain)109 MaybeLocal<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 
New(Environment * env,std::shared_ptr<ManagedX509> cert,STACK_OF (X509)* issuer_chain)117 MaybeLocal<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 
GetCert(Environment * env,const SSLPointer & ssl)134 MaybeLocal<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 
GetPeerCert(Environment * env,const SSLPointer & ssl,GetPeerCertificateFlag flag)146 MaybeLocal<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 
Parse(const FunctionCallbackInfo<Value> & args)173 void 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 
207 template <MaybeLocal<Value> Property(
208     Environment* env, X509* cert, const BIOPointer& bio)>
ReturnPropertyThroughBIO(const FunctionCallbackInfo<Value> & args)209 static 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 
Subject(const FunctionCallbackInfo<Value> & args)220 void X509Certificate::Subject(const FunctionCallbackInfo<Value>& args) {
221   ReturnPropertyThroughBIO<GetSubject>(args);
222 }
223 
Issuer(const FunctionCallbackInfo<Value> & args)224 void X509Certificate::Issuer(const FunctionCallbackInfo<Value>& args) {
225   ReturnPropertyThroughBIO<GetIssuerString>(args);
226 }
227 
SubjectAltName(const FunctionCallbackInfo<Value> & args)228 void X509Certificate::SubjectAltName(const FunctionCallbackInfo<Value>& args) {
229   ReturnPropertyThroughBIO<GetSubjectAltNameString>(args);
230 }
231 
InfoAccess(const FunctionCallbackInfo<Value> & args)232 void X509Certificate::InfoAccess(const FunctionCallbackInfo<Value>& args) {
233   ReturnPropertyThroughBIO<GetInfoAccessString>(args);
234 }
235 
ValidFrom(const FunctionCallbackInfo<Value> & args)236 void X509Certificate::ValidFrom(const FunctionCallbackInfo<Value>& args) {
237   ReturnPropertyThroughBIO<GetValidFrom>(args);
238 }
239 
ValidTo(const FunctionCallbackInfo<Value> & args)240 void X509Certificate::ValidTo(const FunctionCallbackInfo<Value>& args) {
241   ReturnPropertyThroughBIO<GetValidTo>(args);
242 }
243 
244 template <MaybeLocal<Value> Property(Environment* env, X509* cert)>
ReturnProperty(const FunctionCallbackInfo<Value> & args)245 static 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 
KeyUsage(const FunctionCallbackInfo<Value> & args)253 void X509Certificate::KeyUsage(const FunctionCallbackInfo<Value>& args) {
254   ReturnProperty<GetKeyUsage>(args);
255 }
256 
SerialNumber(const FunctionCallbackInfo<Value> & args)257 void X509Certificate::SerialNumber(const FunctionCallbackInfo<Value>& args) {
258   ReturnProperty<GetSerialNumber>(args);
259 }
260 
Raw(const FunctionCallbackInfo<Value> & args)261 void X509Certificate::Raw(const FunctionCallbackInfo<Value>& args) {
262   ReturnProperty<GetRawDERCertificate>(args);
263 }
264 
PublicKey(const FunctionCallbackInfo<Value> & args)265 void 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 
Pem(const FunctionCallbackInfo<Value> & args)284 void 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 
CheckCA(const FunctionCallbackInfo<Value> & args)294 void 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 
CheckHost(const FunctionCallbackInfo<Value> & args)301 void 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 
CheckEmail(const FunctionCallbackInfo<Value> & args)336 void 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 
CheckIP(const FunctionCallbackInfo<Value> & args)363 void 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 
CheckIssued(const FunctionCallbackInfo<Value> & args)386 void 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 
CheckPrivateKey(const FunctionCallbackInfo<Value> & args)403 void 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 
Verify(const FunctionCallbackInfo<Value> & args)420 void 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 
ToLegacy(const FunctionCallbackInfo<Value> & args)437 void 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 
GetIssuerCert(const FunctionCallbackInfo<Value> & args)447 void 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 
X509Certificate(Environment * env,Local<Object> object,std::shared_ptr<ManagedX509> cert,STACK_OF (X509)* issuer_chain)454 X509Certificate::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 
MemoryInfo(MemoryTracker * tracker) const475 void X509Certificate::MemoryInfo(MemoryTracker* tracker) const {
476   tracker->TrackField("cert", cert_);
477 }
478 
479 BaseObjectPtr<BaseObject>
Deserialize(Environment * env,Local<Context> context,std::unique_ptr<worker::TransferData> self)480 X509Certificate::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 
GetTransferMode() const498 BaseObject::TransferMode X509Certificate::GetTransferMode() const {
499   return BaseObject::TransferMode::kCloneable;
500 }
501 
CloneForMessaging() const502 std::unique_ptr<worker::TransferData> X509Certificate::CloneForMessaging()
503     const {
504   return std::make_unique<X509CertificateTransferData>(cert_);
505 }
506 
507 
Initialize(Environment * env,Local<Object> target)508 void 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 
RegisterExternalReferences(ExternalReferenceRegistry * registry)519 void 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