xref: /third_party/node/src/crypto/crypto_x509.cc (revision 1cb0ef41)
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