• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "base_object-inl.h"
2 #include "env-inl.h"
3 #include "node_buffer.h"
4 #include "node_crypto.h"
5 #include "node_crypto_common.h"
6 #include "node.h"
7 #include "node_internals.h"
8 #include "node_url.h"
9 #include "string_bytes.h"
10 #include "v8.h"
11 
12 #include <openssl/ec.h>
13 #include <openssl/ecdh.h>
14 #include <openssl/evp.h>
15 #include <openssl/pem.h>
16 #include <openssl/x509v3.h>
17 #include <openssl/hmac.h>
18 #include <openssl/rand.h>
19 #include <openssl/pkcs12.h>
20 
21 #include <string>
22 #include <unordered_map>
23 
24 namespace node {
25 
26 using v8::Array;
27 using v8::ArrayBufferView;
28 using v8::Context;
29 using v8::EscapableHandleScope;
30 using v8::Integer;
31 using v8::Local;
32 using v8::MaybeLocal;
33 using v8::NewStringType;
34 using v8::Null;
35 using v8::Object;
36 using v8::String;
37 using v8::Undefined;
38 using v8::Value;
39 
40 namespace crypto {
41 
42 static constexpr int X509_NAME_FLAGS =
43     ASN1_STRFLGS_ESC_CTRL |
44     ASN1_STRFLGS_UTF8_CONVERT |
45     XN_FLAG_SEP_MULTILINE |
46     XN_FLAG_FN_SN;
47 
SSL_CTX_get_issuer(SSL_CTX * ctx,X509 * cert,X509 ** issuer)48 int SSL_CTX_get_issuer(SSL_CTX* ctx, X509* cert, X509** issuer) {
49   X509_STORE* store = SSL_CTX_get_cert_store(ctx);
50   DeleteFnPtr<X509_STORE_CTX, X509_STORE_CTX_free> store_ctx(
51       X509_STORE_CTX_new());
52   return store_ctx.get() != nullptr &&
53          X509_STORE_CTX_init(store_ctx.get(), store, nullptr, nullptr) == 1 &&
54          X509_STORE_CTX_get1_issuer(issuer, store_ctx.get(), cert) == 1;
55 }
56 
LogSecret(const SSLPointer & ssl,const char * name,const unsigned char * secret,size_t secretlen)57 void LogSecret(
58     const SSLPointer& ssl,
59     const char* name,
60     const unsigned char* secret,
61     size_t secretlen) {
62   auto keylog_cb = SSL_CTX_get_keylog_callback(SSL_get_SSL_CTX(ssl.get()));
63   unsigned char crandom[32];
64 
65   if (keylog_cb == nullptr ||
66       SSL_get_client_random(ssl.get(), crandom, 32) != 32) {
67     return;
68   }
69 
70   std::string line = name;
71   line += " " + StringBytes::hex_encode(
72       reinterpret_cast<const char*>(crandom), 32);
73   line += " " + StringBytes::hex_encode(
74       reinterpret_cast<const char*>(secret), secretlen);
75   keylog_cb(ssl.get(), line.c_str());
76 }
77 
SetALPN(const SSLPointer & ssl,const std::string & alpn)78 bool SetALPN(const SSLPointer& ssl, const std::string& alpn) {
79   return SSL_set_alpn_protos(
80       ssl.get(),
81       reinterpret_cast<const uint8_t*>(alpn.c_str()),
82       alpn.length()) == 0;
83 }
84 
SetALPN(const SSLPointer & ssl,Local<Value> alpn)85 bool SetALPN(const SSLPointer& ssl, Local<Value> alpn) {
86   if (!alpn->IsArrayBufferView())
87     return false;
88   ArrayBufferViewContents<unsigned char> protos(alpn.As<ArrayBufferView>());
89   return SSL_set_alpn_protos(ssl.get(), protos.data(), protos.length()) == 0;
90 }
91 
GetSSLOCSPResponse(Environment * env,SSL * ssl,Local<Value> default_value)92 MaybeLocal<Value> GetSSLOCSPResponse(
93     Environment* env,
94     SSL* ssl,
95     Local<Value> default_value) {
96   const unsigned char* resp;
97   int len = SSL_get_tlsext_status_ocsp_resp(ssl, &resp);
98   if (resp == nullptr)
99     return default_value;
100 
101   Local<Value> ret;
102   MaybeLocal<Object> maybe_buffer =
103       Buffer::Copy(env, reinterpret_cast<const char*>(resp), len);
104 
105   if (!maybe_buffer.ToLocal(&ret))
106     return MaybeLocal<Value>();
107 
108   return ret;
109 }
110 
SetTLSSession(const SSLPointer & ssl,const unsigned char * buf,size_t length)111 bool SetTLSSession(
112     const SSLPointer& ssl,
113     const unsigned char* buf,
114     size_t length) {
115   SSLSessionPointer s(d2i_SSL_SESSION(nullptr, &buf, length));
116   return s == nullptr ? false : SetTLSSession(ssl, s);
117 }
118 
SetTLSSession(const SSLPointer & ssl,const SSLSessionPointer & session)119 bool SetTLSSession(
120     const SSLPointer& ssl,
121     const SSLSessionPointer& session) {
122   return session != nullptr && SSL_set_session(ssl.get(), session.get()) == 1;
123 }
124 
GetTLSSession(Local<Value> val)125 SSLSessionPointer GetTLSSession(Local<Value> val) {
126   if (!val->IsArrayBufferView())
127     return SSLSessionPointer();
128   ArrayBufferViewContents<unsigned char> sbuf(val.As<ArrayBufferView>());
129   return GetTLSSession(sbuf.data(), sbuf.length());
130 }
131 
GetTLSSession(const unsigned char * buf,size_t length)132 SSLSessionPointer GetTLSSession(const unsigned char* buf, size_t length) {
133   return SSLSessionPointer(d2i_SSL_SESSION(nullptr, &buf, length));
134 }
135 
136 std::unordered_multimap<std::string, std::string>
GetCertificateAltNames(X509 * cert)137 GetCertificateAltNames(X509* cert) {
138   std::unordered_multimap<std::string, std::string> map;
139   BIOPointer bio(BIO_new(BIO_s_mem()));
140   BUF_MEM* mem;
141   int idx = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
142   if (idx < 0)  // There is no subject alt name
143     return map;
144 
145   X509_EXTENSION* ext = X509_get_ext(cert, idx);
146   CHECK_NOT_NULL(ext);
147   const X509V3_EXT_METHOD* method = X509V3_EXT_get(ext);
148   CHECK_EQ(method, X509V3_EXT_get_nid(NID_subject_alt_name));
149 
150   GENERAL_NAMES* names = static_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(ext));
151   if (names == nullptr)  // There are no names
152     return map;
153 
154   for (int i = 0; i < sk_GENERAL_NAME_num(names); i++) {
155     USE(BIO_reset(bio.get()));
156     GENERAL_NAME* gen = sk_GENERAL_NAME_value(names, i);
157     if (gen->type == GEN_DNS) {
158       ASN1_IA5STRING* name = gen->d.dNSName;
159       BIO_write(bio.get(), name->data, name->length);
160       BIO_get_mem_ptr(bio.get(), &mem);
161       map.emplace("dns", std::string(mem->data, mem->length));
162     } else {
163       STACK_OF(CONF_VALUE)* nval = i2v_GENERAL_NAME(
164           const_cast<X509V3_EXT_METHOD*>(method), gen, nullptr);
165       if (nval == nullptr)
166         continue;
167       X509V3_EXT_val_prn(bio.get(), nval, 0, 0);
168       sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
169       BIO_get_mem_ptr(bio.get(), &mem);
170       std::string value(mem->data, mem->length);
171       if (value.compare(0, 11, "IP Address:") == 0) {
172         map.emplace("ip", value.substr(11));
173       } else if (value.compare(0, 4, "URI:") == 0) {
174         url::URL url(value.substr(4));
175         if (url.flags() & url::URL_FLAGS_CANNOT_BE_BASE ||
176             url.flags() & url::URL_FLAGS_FAILED) {
177           continue;  // Skip this one
178         }
179         map.emplace("uri", url.host());
180       }
181     }
182   }
183   sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
184   return map;
185 }
186 
GetCertificateCN(X509 * cert)187 std::string GetCertificateCN(X509* cert) {
188   X509_NAME* subject = X509_get_subject_name(cert);
189   if (subject != nullptr) {
190     int nid = OBJ_txt2nid("CN");
191     int idx = X509_NAME_get_index_by_NID(subject, nid, -1);
192     if (idx != -1) {
193       X509_NAME_ENTRY* cn = X509_NAME_get_entry(subject, idx);
194       if (cn != nullptr) {
195         ASN1_STRING* cn_str = X509_NAME_ENTRY_get_data(cn);
196         if (cn_str != nullptr) {
197           return std::string(reinterpret_cast<const char*>(
198               ASN1_STRING_get0_data(cn_str)));
199         }
200       }
201     }
202   }
203   return std::string();
204 }
205 
VerifyPeerCertificate(const SSLPointer & ssl,long def)206 long VerifyPeerCertificate(  // NOLINT(runtime/int)
207     const SSLPointer& ssl,
208     long def) {  // NOLINT(runtime/int)
209   long err = def;  // NOLINT(runtime/int)
210   if (X509* peer_cert = SSL_get_peer_certificate(ssl.get())) {
211     X509_free(peer_cert);
212     err = SSL_get_verify_result(ssl.get());
213   } else {
214     const SSL_CIPHER* curr_cipher = SSL_get_current_cipher(ssl.get());
215     const SSL_SESSION* sess = SSL_get_session(ssl.get());
216     // Allow no-cert for PSK authentication in TLS1.2 and lower.
217     // In TLS1.3 check that session was reused because TLS1.3 PSK
218     // looks like session resumption.
219     if (SSL_CIPHER_get_auth_nid(curr_cipher) == NID_auth_psk ||
220         (SSL_SESSION_get_protocol_version(sess) == TLS1_3_VERSION &&
221          SSL_session_reused(ssl.get()))) {
222       return X509_V_OK;
223     }
224   }
225   return err;
226 }
227 
UseSNIContext(const SSLPointer & ssl,BaseObjectPtr<SecureContext> context)228 int UseSNIContext(const SSLPointer& ssl, BaseObjectPtr<SecureContext> context) {
229   SSL_CTX* ctx = context->ctx_.get();
230   X509* x509 = SSL_CTX_get0_certificate(ctx);
231   EVP_PKEY* pkey = SSL_CTX_get0_privatekey(ctx);
232   STACK_OF(X509)* chain;
233 
234   int err = SSL_CTX_get0_chain_certs(ctx, &chain);
235   if (err == 1) err = SSL_use_certificate(ssl.get(), x509);
236   if (err == 1) err = SSL_use_PrivateKey(ssl.get(), pkey);
237   if (err == 1 && chain != nullptr) err = SSL_set1_chain(ssl.get(), chain);
238   return err;
239 }
240 
GetClientHelloALPN(const SSLPointer & ssl)241 const char* GetClientHelloALPN(const SSLPointer& ssl) {
242   const unsigned char* buf;
243   size_t len;
244   size_t rem;
245 
246   if (!SSL_client_hello_get0_ext(
247           ssl.get(),
248           TLSEXT_TYPE_application_layer_protocol_negotiation,
249           &buf,
250           &rem) ||
251       rem < 2) {
252     return nullptr;
253   }
254 
255   len = (buf[0] << 8) | buf[1];
256   if (len + 2 != rem) return nullptr;
257   return reinterpret_cast<const char*>(buf + 3);
258 }
259 
GetClientHelloServerName(const SSLPointer & ssl)260 const char* GetClientHelloServerName(const SSLPointer& ssl) {
261   const unsigned char* buf;
262   size_t len;
263   size_t rem;
264 
265   if (!SSL_client_hello_get0_ext(
266           ssl.get(),
267           TLSEXT_TYPE_server_name,
268           &buf,
269           &rem) || rem <= 2) {
270     return nullptr;
271   }
272 
273   len = (*buf << 8) | *(buf + 1);
274   if (len + 2 != rem)
275     return nullptr;
276   rem = len;
277 
278   if (rem == 0 || *(buf + 2) != TLSEXT_NAMETYPE_host_name) return nullptr;
279   rem--;
280   if (rem <= 2)
281     return nullptr;
282   len = (*(buf + 3) << 8) | *(buf + 4);
283   if (len + 2 > rem)
284     return nullptr;
285   return reinterpret_cast<const char*>(buf + 5);
286 }
287 
GetServerName(SSL * ssl)288 const char* GetServerName(SSL* ssl) {
289   return SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
290 }
291 
SetGroups(SecureContext * sc,const char * groups)292 bool SetGroups(SecureContext* sc, const char* groups) {
293   return SSL_CTX_set1_groups_list(**sc, groups) == 1;
294 }
295 
X509ErrorCode(long err)296 const char* X509ErrorCode(long err) {  // NOLINT(runtime/int)
297   const char* code = "UNSPECIFIED";
298 #define CASE_X509_ERR(CODE) case X509_V_ERR_##CODE: code = #CODE; break;
299   switch (err) {
300     CASE_X509_ERR(UNABLE_TO_GET_ISSUER_CERT)
301     CASE_X509_ERR(UNABLE_TO_GET_CRL)
302     CASE_X509_ERR(UNABLE_TO_DECRYPT_CERT_SIGNATURE)
303     CASE_X509_ERR(UNABLE_TO_DECRYPT_CRL_SIGNATURE)
304     CASE_X509_ERR(UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY)
305     CASE_X509_ERR(CERT_SIGNATURE_FAILURE)
306     CASE_X509_ERR(CRL_SIGNATURE_FAILURE)
307     CASE_X509_ERR(CERT_NOT_YET_VALID)
308     CASE_X509_ERR(CERT_HAS_EXPIRED)
309     CASE_X509_ERR(CRL_NOT_YET_VALID)
310     CASE_X509_ERR(CRL_HAS_EXPIRED)
311     CASE_X509_ERR(ERROR_IN_CERT_NOT_BEFORE_FIELD)
312     CASE_X509_ERR(ERROR_IN_CERT_NOT_AFTER_FIELD)
313     CASE_X509_ERR(ERROR_IN_CRL_LAST_UPDATE_FIELD)
314     CASE_X509_ERR(ERROR_IN_CRL_NEXT_UPDATE_FIELD)
315     CASE_X509_ERR(OUT_OF_MEM)
316     CASE_X509_ERR(DEPTH_ZERO_SELF_SIGNED_CERT)
317     CASE_X509_ERR(SELF_SIGNED_CERT_IN_CHAIN)
318     CASE_X509_ERR(UNABLE_TO_GET_ISSUER_CERT_LOCALLY)
319     CASE_X509_ERR(UNABLE_TO_VERIFY_LEAF_SIGNATURE)
320     CASE_X509_ERR(CERT_CHAIN_TOO_LONG)
321     CASE_X509_ERR(CERT_REVOKED)
322     CASE_X509_ERR(INVALID_CA)
323     CASE_X509_ERR(PATH_LENGTH_EXCEEDED)
324     CASE_X509_ERR(INVALID_PURPOSE)
325     CASE_X509_ERR(CERT_UNTRUSTED)
326     CASE_X509_ERR(CERT_REJECTED)
327     CASE_X509_ERR(HOSTNAME_MISMATCH)
328   }
329 #undef CASE_X509_ERR
330   return code;
331 }
332 
GetValidationErrorReason(Environment * env,int err)333 MaybeLocal<Value> GetValidationErrorReason(Environment* env, int err) {
334   if (err == 0)
335     return Undefined(env->isolate());
336   const char* reason = X509_verify_cert_error_string(err);
337   return OneByteString(env->isolate(), reason);
338 }
339 
GetValidationErrorCode(Environment * env,int err)340 MaybeLocal<Value> GetValidationErrorCode(Environment* env, int err) {
341   if (err == 0)
342     return Undefined(env->isolate());
343   return OneByteString(env->isolate(), X509ErrorCode(err));
344 }
345 
GetCert(Environment * env,const SSLPointer & ssl)346 MaybeLocal<Value> GetCert(Environment* env, const SSLPointer& ssl) {
347   ClearErrorOnReturn clear_error_on_return;
348   X509* cert = SSL_get_certificate(ssl.get());
349   if (cert == nullptr)
350     return Undefined(env->isolate());
351 
352   MaybeLocal<Object> maybe_cert = X509ToObject(env, cert);
353   return maybe_cert.FromMaybe<Value>(Local<Value>());
354 }
355 
356 namespace {
357 template <typename T>
Set(Local<Context> context,Local<Object> target,Local<Value> name,MaybeLocal<T> maybe_value)358 bool Set(
359     Local<Context> context,
360     Local<Object> target,
361     Local<Value> name,
362     MaybeLocal<T> maybe_value) {
363   Local<Value> value;
364   if (!maybe_value.ToLocal(&value))
365     return false;
366 
367   // Undefined is ignored, but still considered successful
368   if (value->IsUndefined())
369     return true;
370 
371   return !target->Set(context, name, value).IsNothing();
372 }
373 
ToV8Value(Environment * env,const BIOPointer & bio)374 Local<Value> ToV8Value(Environment* env, const BIOPointer& bio) {
375   BUF_MEM* mem;
376   BIO_get_mem_ptr(bio.get(), &mem);
377   MaybeLocal<String> ret =
378       String::NewFromUtf8(
379           env->isolate(),
380           mem->data,
381           NewStringType::kNormal,
382           mem->length);
383   USE(BIO_reset(bio.get()));
384   return ret.FromMaybe(Local<Value>());
385 }
386 
GetCipherValue(Environment * env,const SSL_CIPHER * cipher,const char * (* getstr)(const SSL_CIPHER * cipher))387 MaybeLocal<Value> GetCipherValue(Environment* env,
388     const SSL_CIPHER* cipher,
389     const char* (*getstr)(const SSL_CIPHER* cipher)) {
390   if (cipher == nullptr)
391     return Undefined(env->isolate());
392 
393   return OneByteString(env->isolate(), getstr(cipher));
394 }
395 
GetCipherName(Environment * env,const SSL_CIPHER * cipher)396 MaybeLocal<Value> GetCipherName(Environment* env, const SSL_CIPHER* cipher) {
397   return GetCipherValue(env, cipher, SSL_CIPHER_get_name);
398 }
399 
GetCipherStandardName(Environment * env,const SSL_CIPHER * cipher)400 MaybeLocal<Value> GetCipherStandardName(
401     Environment* env,
402     const SSL_CIPHER* cipher) {
403   return GetCipherValue(env, cipher, SSL_CIPHER_standard_name);
404 }
405 
GetCipherVersion(Environment * env,const SSL_CIPHER * cipher)406 MaybeLocal<Value> GetCipherVersion(Environment* env, const SSL_CIPHER* cipher) {
407   return GetCipherValue(env, cipher, SSL_CIPHER_get_version);
408 }
409 
CloneSSLCerts(X509Pointer && cert,const STACK_OF (X509)* const ssl_certs)410 StackOfX509 CloneSSLCerts(X509Pointer&& cert,
411                           const STACK_OF(X509)* const ssl_certs) {
412   StackOfX509 peer_certs(sk_X509_new(nullptr));
413   if (cert)
414     sk_X509_push(peer_certs.get(), cert.release());
415   for (int i = 0; i < sk_X509_num(ssl_certs); i++) {
416     X509Pointer cert(X509_dup(sk_X509_value(ssl_certs, i)));
417     if (!cert || !sk_X509_push(peer_certs.get(), cert.get()))
418       return StackOfX509();
419     // `cert` is now managed by the stack.
420     cert.release();
421   }
422   return peer_certs;
423 }
424 
AddIssuerChainToObject(X509Pointer * cert,Local<Object> object,StackOfX509 && peer_certs,Environment * const env)425 MaybeLocal<Object> AddIssuerChainToObject(
426     X509Pointer* cert,
427     Local<Object> object,
428     StackOfX509&& peer_certs,
429     Environment* const env) {
430   Local<Context> context = env->isolate()->GetCurrentContext();
431   cert->reset(sk_X509_delete(peer_certs.get(), 0));
432   for (;;) {
433     int i;
434     for (i = 0; i < sk_X509_num(peer_certs.get()); i++) {
435       X509* ca = sk_X509_value(peer_certs.get(), i);
436       if (X509_check_issued(ca, cert->get()) != X509_V_OK)
437         continue;
438 
439       Local<Object> ca_info;
440       MaybeLocal<Object> maybe_ca_info = X509ToObject(env, ca);
441       if (!maybe_ca_info.ToLocal(&ca_info))
442         return MaybeLocal<Object>();
443 
444       if (!Set<Object>(context, object, env->issuercert_string(), ca_info))
445         return MaybeLocal<Object>();
446       object = ca_info;
447 
448       // NOTE: Intentionally freeing cert that is not used anymore.
449       // Delete cert and continue aggregating issuers.
450       cert->reset(sk_X509_delete(peer_certs.get(), i));
451       break;
452     }
453 
454     // Issuer not found, break out of the loop.
455     if (i == sk_X509_num(peer_certs.get()))
456       break;
457   }
458   return MaybeLocal<Object>(object);
459 }
460 
GetLastIssuedCert(X509Pointer * cert,const SSLPointer & ssl,Local<Object> issuer_chain,Environment * const env)461 MaybeLocal<Object> GetLastIssuedCert(
462     X509Pointer* cert,
463     const SSLPointer& ssl,
464     Local<Object> issuer_chain,
465     Environment* const env) {
466   Local<Context> context = env->isolate()->GetCurrentContext();
467   while (X509_check_issued(cert->get(), cert->get()) != X509_V_OK) {
468     X509* ca;
469     if (SSL_CTX_get_issuer(SSL_get_SSL_CTX(ssl.get()), cert->get(), &ca) <= 0)
470       break;
471 
472     Local<Object> ca_info;
473     MaybeLocal<Object> maybe_ca_info = X509ToObject(env, ca);
474     if (!maybe_ca_info.ToLocal(&ca_info))
475       return MaybeLocal<Object>();
476 
477     if (!Set<Object>(context, issuer_chain, env->issuercert_string(), ca_info))
478       return MaybeLocal<Object>();
479     issuer_chain = ca_info;
480 
481     // Delete previous cert and continue aggregating issuers.
482     cert->reset(ca);
483   }
484   return MaybeLocal<Object>(issuer_chain);
485 }
486 
GetRawDERCertificate(Environment * env,X509 * cert)487 MaybeLocal<Object> GetRawDERCertificate(Environment* env, X509* cert) {
488   int size = i2d_X509(cert, nullptr);
489 
490   AllocatedBuffer buffer = env->AllocateManaged(size);
491   unsigned char* serialized =
492       reinterpret_cast<unsigned char*>(buffer.data());
493   i2d_X509(cert, &serialized);
494   return buffer.ToBuffer();
495 }
496 
GetSerialNumber(Environment * env,X509 * cert)497 MaybeLocal<Value> GetSerialNumber(Environment* env, X509* cert) {
498   if (ASN1_INTEGER* serial_number = X509_get_serialNumber(cert)) {
499     BignumPointer bn(ASN1_INTEGER_to_BN(serial_number, nullptr));
500     if (bn) {
501       OpenSSLBuffer buf(BN_bn2hex(bn.get()));
502       if (buf)
503         return OneByteString(env->isolate(), buf.get());
504     }
505   }
506 
507   return Undefined(env->isolate());
508 }
509 
GetKeyUsage(Environment * env,X509 * cert)510 MaybeLocal<Value> GetKeyUsage(Environment* env, X509* cert) {
511   StackOfASN1 eku(static_cast<STACK_OF(ASN1_OBJECT)*>(
512       X509_get_ext_d2i(cert, NID_ext_key_usage, nullptr, nullptr)));
513   if (eku) {
514     const int count = sk_ASN1_OBJECT_num(eku.get());
515     MaybeStackBuffer<Local<Value>, 16> ext_key_usage(count);
516     char buf[256];
517 
518     int j = 0;
519     for (int i = 0; i < count; i++) {
520       if (OBJ_obj2txt(buf,
521                       sizeof(buf),
522                       sk_ASN1_OBJECT_value(eku.get(), i), 1) >= 0) {
523         ext_key_usage[j++] = OneByteString(env->isolate(), buf);
524       }
525     }
526 
527     return Array::New(env->isolate(), ext_key_usage.out(), count);
528   }
529 
530   return Undefined(env->isolate());
531 }
532 
AddFingerprintDigest(const unsigned char * md,unsigned int md_size,char (* fingerprint)[3* EVP_MAX_MD_SIZE+1])533 void AddFingerprintDigest(
534     const unsigned char* md,
535     unsigned int md_size,
536     char (*fingerprint)[3 * EVP_MAX_MD_SIZE + 1]) {
537   unsigned int i;
538   const char hex[] = "0123456789ABCDEF";
539 
540   for (i = 0; i < md_size; i++) {
541     (*fingerprint)[3*i] = hex[(md[i] & 0xf0) >> 4];
542     (*fingerprint)[(3*i)+1] = hex[(md[i] & 0x0f)];
543     (*fingerprint)[(3*i)+2] = ':';
544   }
545 
546   if (md_size > 0) {
547     (*fingerprint)[(3*(md_size-1))+2] = '\0';
548   } else {
549     (*fingerprint)[0] = '\0';
550   }
551 }
552 
SafeX509ExtPrint(const BIOPointer & out,X509_EXTENSION * ext)553 bool SafeX509ExtPrint(const BIOPointer& out, X509_EXTENSION* ext) {
554   const X509V3_EXT_METHOD* method = X509V3_EXT_get(ext);
555 
556   if (method != X509V3_EXT_get_nid(NID_subject_alt_name))
557     return false;
558 
559   GENERAL_NAMES* names = static_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(ext));
560   if (names == nullptr)
561     return false;
562 
563   for (int i = 0; i < sk_GENERAL_NAME_num(names); i++) {
564     GENERAL_NAME* gen = sk_GENERAL_NAME_value(names, i);
565 
566     if (i != 0)
567       BIO_write(out.get(), ", ", 2);
568 
569     if (gen->type == GEN_DNS) {
570       ASN1_IA5STRING* name = gen->d.dNSName;
571 
572       BIO_write(out.get(), "DNS:", 4);
573       BIO_write(out.get(), name->data, name->length);
574     } else {
575       STACK_OF(CONF_VALUE)* nval = i2v_GENERAL_NAME(
576           const_cast<X509V3_EXT_METHOD*>(method), gen, nullptr);
577       if (nval == nullptr)
578         return false;
579       X509V3_EXT_val_prn(out.get(), nval, 0, 0);
580       sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
581     }
582   }
583   sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
584 
585   return true;
586 }
587 
GetFingerprintDigest(Environment * env,const EVP_MD * method,X509 * cert)588 MaybeLocal<Value> GetFingerprintDigest(
589     Environment* env,
590     const EVP_MD* method,
591     X509* cert) {
592   unsigned char md[EVP_MAX_MD_SIZE];
593   unsigned int md_size;
594   char fingerprint[EVP_MAX_MD_SIZE * 3 + 1];
595 
596   if (X509_digest(cert, method, md, &md_size)) {
597     AddFingerprintDigest(md, md_size, &fingerprint);
598     return OneByteString(env->isolate(), fingerprint);
599   }
600   return Undefined(env->isolate());
601 }
602 
GetValidTo(Environment * env,X509 * cert,const BIOPointer & bio)603 MaybeLocal<Value> GetValidTo(
604     Environment* env,
605     X509* cert,
606     const BIOPointer& bio) {
607   ASN1_TIME_print(bio.get(), X509_get0_notAfter(cert));
608   return ToV8Value(env, bio);
609 }
610 
GetValidFrom(Environment * env,X509 * cert,const BIOPointer & bio)611 MaybeLocal<Value> GetValidFrom(
612     Environment* env,
613     X509* cert,
614     const BIOPointer& bio) {
615   ASN1_TIME_print(bio.get(), X509_get0_notBefore(cert));
616   return ToV8Value(env, bio);
617 }
618 
GetCurveASN1Name(Environment * env,const int nid)619 MaybeLocal<Value> GetCurveASN1Name(Environment* env, const int nid) {
620   const char* nist = OBJ_nid2sn(nid);
621   return nist != nullptr ?
622       MaybeLocal<Value>(OneByteString(env->isolate(), nist)) :
623       MaybeLocal<Value>(Undefined(env->isolate()));
624 }
625 
GetCurveNistName(Environment * env,const int nid)626 MaybeLocal<Value> GetCurveNistName(Environment* env, const int nid) {
627   const char* nist = EC_curve_nid2nist(nid);
628   return nist != nullptr ?
629       MaybeLocal<Value>(OneByteString(env->isolate(), nist)) :
630       MaybeLocal<Value>(Undefined(env->isolate()));
631 }
632 
GetECPubKey(Environment * env,const EC_GROUP * group,const ECPointer & ec)633 MaybeLocal<Value> GetECPubKey(
634     Environment* env,
635     const EC_GROUP* group,
636     const ECPointer& ec) {
637   const EC_POINT* pubkey = EC_KEY_get0_public_key(ec.get());
638   if (pubkey == nullptr)
639     return Undefined(env->isolate());
640 
641   return ECPointToBuffer(
642       env,
643       group,
644       pubkey,
645       EC_KEY_get_conv_form(ec.get()),
646       nullptr).FromMaybe(Local<Object>());
647 }
648 
GetECGroup(Environment * env,const EC_GROUP * group,const ECPointer & ec)649 MaybeLocal<Value> GetECGroup(
650     Environment* env,
651     const EC_GROUP* group,
652     const ECPointer& ec) {
653   if (group == nullptr)
654     return Undefined(env->isolate());
655 
656   int bits = EC_GROUP_order_bits(group);
657   if (bits <= 0)
658     return Undefined(env->isolate());
659 
660   return Integer::New(env->isolate(), bits);
661 }
662 
GetPubKey(Environment * env,const RSAPointer & rsa)663 MaybeLocal<Object> GetPubKey(Environment* env, const RSAPointer& rsa) {
664   int size = i2d_RSA_PUBKEY(rsa.get(), nullptr);
665   CHECK_GE(size, 0);
666 
667   AllocatedBuffer buffer = env->AllocateManaged(size);
668   unsigned char* serialized =
669       reinterpret_cast<unsigned char*>(buffer.data());
670   i2d_RSA_PUBKEY(rsa.get(), &serialized);
671   return buffer.ToBuffer();
672 }
673 
GetExponentString(Environment * env,const BIOPointer & bio,const BIGNUM * e)674 MaybeLocal<Value> GetExponentString(
675     Environment* env,
676     const BIOPointer& bio,
677     const BIGNUM* e) {
678   uint64_t exponent_word = static_cast<uint64_t>(BN_get_word(e));
679   uint32_t lo = static_cast<uint32_t>(exponent_word);
680   uint32_t hi = static_cast<uint32_t>(exponent_word >> 32);
681   if (hi == 0)
682     BIO_printf(bio.get(), "0x%x", lo);
683   else
684     BIO_printf(bio.get(), "0x%x%08x", hi, lo);
685 
686   return ToV8Value(env, bio);
687 }
688 
GetBits(Environment * env,const BIGNUM * n)689 Local<Value> GetBits(Environment* env, const BIGNUM* n) {
690   return Integer::New(env->isolate(), BN_num_bits(n));
691 }
692 
GetModulusString(Environment * env,const BIOPointer & bio,const BIGNUM * n)693 MaybeLocal<Value> GetModulusString(
694     Environment* env,
695     const BIOPointer& bio,
696     const BIGNUM* n) {
697   BN_print(bio.get(), n);
698   return ToV8Value(env, bio);
699 }
700 
701 template <int nid>
GetInfoString(Environment * env,const BIOPointer & bio,X509 * cert)702 MaybeLocal<Value> GetInfoString(
703     Environment* env,
704     const BIOPointer& bio,
705     X509* cert) {
706   int index = X509_get_ext_by_NID(cert, nid, -1);
707   if (index < 0)
708     return Undefined(env->isolate());
709 
710   X509_EXTENSION* ext = X509_get_ext(cert, index);
711   CHECK_NOT_NULL(ext);
712 
713   if (!SafeX509ExtPrint(bio, ext) &&
714       X509V3_EXT_print(bio.get(), ext, 0, 0) != 1) {
715     USE(BIO_reset(bio.get()));
716     return Null(env->isolate());
717   }
718 
719   return ToV8Value(env, bio);
720 }
721 
GetIssuerString(Environment * env,const BIOPointer & bio,X509 * cert)722 MaybeLocal<Value> GetIssuerString(
723     Environment* env,
724     const BIOPointer& bio,
725     X509* cert) {
726   X509_NAME* issuer_name = X509_get_issuer_name(cert);
727   if (X509_NAME_print_ex(bio.get(), issuer_name, 0, X509_NAME_FLAGS) <= 0) {
728     USE(BIO_reset(bio.get()));
729     return Undefined(env->isolate());
730   }
731 
732   return ToV8Value(env, bio);
733 }
734 
GetSubject(Environment * env,const BIOPointer & bio,X509 * cert)735 MaybeLocal<Value> GetSubject(
736     Environment* env,
737     const BIOPointer& bio,
738     X509* cert) {
739   if (X509_NAME_print_ex(
740           bio.get(),
741           X509_get_subject_name(cert),
742           0,
743           X509_NAME_FLAGS) <= 0) {
744     USE(BIO_reset(bio.get()));
745     return Undefined(env->isolate());
746   }
747 
748   return ToV8Value(env, bio);
749 }
750 }  // namespace
751 
GetCipherName(Environment * env,const SSLPointer & ssl)752 MaybeLocal<Value> GetCipherName(Environment* env, const SSLPointer& ssl) {
753   return GetCipherName(env, SSL_get_current_cipher(ssl.get()));
754 }
755 
GetCipherStandardName(Environment * env,const SSLPointer & ssl)756 MaybeLocal<Value> GetCipherStandardName(
757     Environment* env,
758     const SSLPointer& ssl) {
759   return GetCipherStandardName(env, SSL_get_current_cipher(ssl.get()));
760 }
761 
GetCipherVersion(Environment * env,const SSLPointer & ssl)762 MaybeLocal<Value> GetCipherVersion(Environment* env, const SSLPointer& ssl) {
763   return GetCipherVersion(env, SSL_get_current_cipher(ssl.get()));
764 }
765 
GetClientHelloCiphers(Environment * env,const SSLPointer & ssl)766 MaybeLocal<Array> GetClientHelloCiphers(
767     Environment* env,
768     const SSLPointer& ssl) {
769   EscapableHandleScope scope(env->isolate());
770   const unsigned char* buf;
771   size_t len = SSL_client_hello_get0_ciphers(ssl.get(), &buf);
772   size_t count = len / 2;
773   MaybeStackBuffer<Local<Value>, 16> ciphers(count);
774   int j = 0;
775   for (size_t n = 0; n < len; n += 2) {
776     const SSL_CIPHER* cipher = SSL_CIPHER_find(ssl.get(), buf);
777     buf += 2;
778     Local<Object> obj = Object::New(env->isolate());
779     if (!Set(env->context(),
780              obj,
781              env->name_string(),
782              GetCipherName(env, cipher)) ||
783         !Set(env->context(),
784              obj,
785              env->standard_name_string(),
786              GetCipherStandardName(env, cipher)) ||
787         !Set(env->context(),
788              obj,
789              env->version_string(),
790              GetCipherVersion(env, cipher))) {
791       return MaybeLocal<Array>();
792     }
793     ciphers[j++] = obj;
794   }
795   Local<Array> ret = Array::New(env->isolate(), ciphers.out(), count);
796   return scope.Escape(ret);
797 }
798 
799 
GetCipherInfo(Environment * env,const SSLPointer & ssl)800 MaybeLocal<Object> GetCipherInfo(Environment* env, const SSLPointer& ssl) {
801   EscapableHandleScope scope(env->isolate());
802   Local<Object> info = Object::New(env->isolate());
803 
804   if (!Set<Value>(env->context(),
805                   info,
806                   env->name_string(),
807                   GetCipherName(env, ssl)) ||
808       !Set<Value>(env->context(),
809                   info,
810                   env->standard_name_string(),
811                   GetCipherStandardName(env, ssl)) ||
812       !Set<Value>(env->context(),
813                   info,
814                   env->version_string(),
815                   GetCipherVersion(env, ssl))) {
816     return MaybeLocal<Object>();
817   }
818 
819   return scope.Escape(info);
820 }
821 
GetEphemeralKey(Environment * env,const SSLPointer & ssl)822 MaybeLocal<Object> GetEphemeralKey(Environment* env, const SSLPointer& ssl) {
823   CHECK_EQ(SSL_is_server(ssl.get()), 0);
824   EVP_PKEY* raw_key;
825 
826   EscapableHandleScope scope(env->isolate());
827   Local<Object> info = Object::New(env->isolate());
828   if (!SSL_get_server_tmp_key(ssl.get(), &raw_key))
829     return scope.Escape(info);
830 
831   Local<Context> context = env->context();
832   crypto::EVPKeyPointer key(raw_key);
833 
834   int kid = EVP_PKEY_id(key.get());
835   int bits = EVP_PKEY_bits(key.get());
836   switch (kid) {
837     case EVP_PKEY_DH:
838       if (!Set<String>(context, info, env->type_string(), env->dh_string()) ||
839           !Set<Integer>(context,
840                info,
841                env->size_string(),
842                Integer::New(env->isolate(), bits))) {
843         return MaybeLocal<Object>();
844       }
845       break;
846     case EVP_PKEY_EC:
847     case EVP_PKEY_X25519:
848     case EVP_PKEY_X448:
849       {
850         const char* curve_name;
851         if (kid == EVP_PKEY_EC) {
852           ECKeyPointer ec(EVP_PKEY_get1_EC_KEY(key.get()));
853           int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec.get()));
854           curve_name = OBJ_nid2sn(nid);
855         } else {
856           curve_name = OBJ_nid2sn(kid);
857         }
858         if (!Set<String>(context,
859                          info,
860                          env->type_string(),
861                          env->ecdh_string()) ||
862             !Set<String>(context,
863                 info,
864                 env->name_string(),
865                 OneByteString(env->isolate(), curve_name)) ||
866             !Set<Integer>(context,
867                  info,
868                  env->size_string(),
869                  Integer::New(env->isolate(), bits))) {
870           return MaybeLocal<Object>();
871         }
872       }
873       break;
874   }
875 
876   return scope.Escape(info);
877 }
878 
ECPointToBuffer(Environment * env,const EC_GROUP * group,const EC_POINT * point,point_conversion_form_t form,const char ** error)879 MaybeLocal<Object> ECPointToBuffer(Environment* env,
880                                    const EC_GROUP* group,
881                                    const EC_POINT* point,
882                                    point_conversion_form_t form,
883                                    const char** error) {
884   size_t len = EC_POINT_point2oct(group, point, form, nullptr, 0, nullptr);
885   if (len == 0) {
886     if (error != nullptr) *error = "Failed to get public key length";
887     return MaybeLocal<Object>();
888   }
889   AllocatedBuffer buf = env->AllocateManaged(len);
890   len = EC_POINT_point2oct(group,
891                            point,
892                            form,
893                            reinterpret_cast<unsigned char*>(buf.data()),
894                            buf.size(),
895                            nullptr);
896   if (len == 0) {
897     if (error != nullptr) *error = "Failed to get public key";
898     return MaybeLocal<Object>();
899   }
900   return buf.ToBuffer();
901 }
902 
GetPeerCert(Environment * env,const SSLPointer & ssl,bool abbreviated,bool is_server)903 MaybeLocal<Value> GetPeerCert(
904     Environment* env,
905     const SSLPointer& ssl,
906     bool abbreviated,
907     bool is_server) {
908   ClearErrorOnReturn clear_error_on_return;
909   Local<Object> result;
910   MaybeLocal<Object> maybe_cert;
911 
912   // NOTE: This is because of the odd OpenSSL behavior. On client `cert_chain`
913   // contains the `peer_certificate`, but on server it doesn't.
914   X509Pointer cert(is_server ? SSL_get_peer_certificate(ssl.get()) : nullptr);
915   STACK_OF(X509)* ssl_certs = SSL_get_peer_cert_chain(ssl.get());
916   if (!cert && (ssl_certs == nullptr || sk_X509_num(ssl_certs) == 0))
917     return Undefined(env->isolate());
918 
919   // Short result requested.
920   if (abbreviated) {
921     maybe_cert =
922         X509ToObject(env, cert ? cert.get() : sk_X509_value(ssl_certs, 0));
923     return maybe_cert.ToLocal(&result) ? result : MaybeLocal<Value>();
924   }
925 
926   StackOfX509 peer_certs = CloneSSLCerts(std::move(cert), ssl_certs);
927   if (peer_certs == nullptr)
928     return Undefined(env->isolate());
929 
930   // First and main certificate.
931   X509Pointer first_cert(sk_X509_value(peer_certs.get(), 0));
932   CHECK(first_cert);
933   maybe_cert = X509ToObject(env, first_cert.release()).ToLocalChecked();
934   if (!maybe_cert.ToLocal(&result))
935     return MaybeLocal<Value>();
936 
937   Local<Object> issuer_chain;
938   MaybeLocal<Object> maybe_issuer_chain;
939 
940   maybe_issuer_chain =
941       AddIssuerChainToObject(
942           &cert,
943           result,
944           std::move(peer_certs),
945           env);
946   if (!maybe_issuer_chain.ToLocal(&issuer_chain))
947     return MaybeLocal<Value>();
948 
949   maybe_issuer_chain =
950       GetLastIssuedCert(
951           &cert,
952           ssl,
953           issuer_chain,
954           env);
955 
956   issuer_chain.Clear();
957   if (!maybe_issuer_chain.ToLocal(&issuer_chain))
958     return MaybeLocal<Value>();
959 
960   // Last certificate should be self-signed.
961   if (X509_check_issued(cert.get(), cert.get()) == X509_V_OK &&
962       !Set<Object>(env->context(),
963            issuer_chain,
964            env->issuercert_string(),
965            issuer_chain)) {
966     return MaybeLocal<Value>();
967   }
968 
969   return result;
970 }
971 
X509ToObject(Environment * env,X509 * cert)972 MaybeLocal<Object> X509ToObject(Environment* env, X509* cert) {
973   EscapableHandleScope scope(env->isolate());
974   Local<Context> context = env->context();
975   Local<Object> info = Object::New(env->isolate());
976 
977   BIOPointer bio(BIO_new(BIO_s_mem()));
978 
979   if (!Set<Value>(context,
980                   info,
981                   env->subject_string(),
982                   GetSubject(env, bio, cert)) ||
983       !Set<Value>(context,
984                   info,
985                   env->issuer_string(),
986                   GetIssuerString(env, bio, cert)) ||
987       !Set<Value>(context,
988                   info,
989                   env->subjectaltname_string(),
990                   GetInfoString<NID_subject_alt_name>(env, bio, cert)) ||
991       !Set<Value>(context,
992                   info,
993                   env->infoaccess_string(),
994                   GetInfoString<NID_info_access>(env, bio, cert))) {
995     return MaybeLocal<Object>();
996   }
997 
998   EVPKeyPointer pkey(X509_get_pubkey(cert));
999   RSAPointer rsa;
1000   ECPointer ec;
1001   if (pkey) {
1002     switch (EVP_PKEY_id(pkey.get())) {
1003       case EVP_PKEY_RSA:
1004         rsa.reset(EVP_PKEY_get1_RSA(pkey.get()));
1005         break;
1006       case EVP_PKEY_EC:
1007         ec.reset(EVP_PKEY_get1_EC_KEY(pkey.get()));
1008         break;
1009     }
1010   }
1011 
1012   if (rsa) {
1013     const BIGNUM* n;
1014     const BIGNUM* e;
1015     RSA_get0_key(rsa.get(), &n, &e, nullptr);
1016     if (!Set<Value>(context,
1017                     info,
1018                     env->modulus_string(),
1019                     GetModulusString(env, bio, n)) ||
1020         !Set<Value>(context, info, env->bits_string(), GetBits(env, n)) ||
1021         !Set<Value>(context,
1022                     info,
1023                     env->exponent_string(),
1024                     GetExponentString(env, bio, e)) ||
1025         !Set<Object>(context,
1026                      info,
1027                      env->pubkey_string(),
1028                      GetPubKey(env, rsa))) {
1029       return MaybeLocal<Object>();
1030     }
1031   } else if (ec) {
1032     const EC_GROUP* group = EC_KEY_get0_group(ec.get());
1033 
1034     if (!Set<Value>(context,
1035                     info,
1036                     env->bits_string(),
1037                     GetECGroup(env, group, ec)) ||
1038         !Set<Value>(context,
1039                     info,
1040                     env->pubkey_string(),
1041                     GetECPubKey(env, group, ec))) {
1042       return MaybeLocal<Object>();
1043     }
1044 
1045     const int nid = EC_GROUP_get_curve_name(group);
1046     if (nid != 0) {
1047       // Curve is well-known, get its OID and NIST nick-name (if it has one).
1048 
1049       if (!Set<Value>(context,
1050                       info,
1051                       env->asn1curve_string(),
1052                       GetCurveASN1Name(env, nid)) ||
1053           !Set<Value>(context,
1054                       info,
1055                       env->nistcurve_string(),
1056                       GetCurveNistName(env, nid))) {
1057         return MaybeLocal<Object>();
1058       }
1059     } else {
1060       // Unnamed curves can be described by their mathematical properties,
1061       // but aren't used much (at all?) with X.509/TLS. Support later if needed.
1062     }
1063   }
1064 
1065   // pkey, rsa, and ec pointers are no longer needed.
1066   pkey.reset();
1067   rsa.reset();
1068   ec.reset();
1069 
1070   if (!Set<Value>(context,
1071                   info,
1072                   env->valid_from_string(),
1073                   GetValidFrom(env, cert, bio)) ||
1074       !Set<Value>(context,
1075                   info,
1076                   env->valid_to_string(),
1077                   GetValidTo(env, cert, bio))) {
1078     return MaybeLocal<Object>();
1079   }
1080 
1081   // bio is no longer needed
1082   bio.reset();
1083 
1084   if (!Set<Value>(context,
1085                   info,
1086                   env->fingerprint_string(),
1087                   GetFingerprintDigest(env, EVP_sha1(), cert)) ||
1088       !Set<Value>(context,
1089                   info,
1090                   env->fingerprint256_string(),
1091                   GetFingerprintDigest(env, EVP_sha256(), cert)) ||
1092       !Set<Value>(context,
1093                   info,
1094                   env->ext_key_usage_string(),
1095                   GetKeyUsage(env, cert)) ||
1096       !Set<Value>(context,
1097                   info,
1098                   env->serial_number_string(),
1099                   GetSerialNumber(env, cert)) ||
1100       !Set<Object>(context,
1101                    info,
1102                    env->raw_string(),
1103                    GetRawDERCertificate(env, cert))) {
1104     return MaybeLocal<Object>();
1105   }
1106 
1107   return scope.Escape(info);
1108 }
1109 
1110 }  // namespace crypto
1111 }  // namespace node
1112