• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "allocated_buffer-inl.h"
2 #include "base_object-inl.h"
3 #include "env-inl.h"
4 #include "node_buffer.h"
5 #include "node_crypto.h"
6 #include "node_crypto_common.h"
7 #include "node.h"
8 #include "node_internals.h"
9 #include "node_revert.h"
10 #include "node_url.h"
11 #include "string_bytes.h"
12 #include "v8.h"
13 
14 #include <openssl/ec.h>
15 #include <openssl/ecdh.h>
16 #include <openssl/evp.h>
17 #include <openssl/pem.h>
18 #include <openssl/x509v3.h>
19 #include <openssl/hmac.h>
20 #include <openssl/rand.h>
21 #include <openssl/pkcs12.h>
22 
23 #include <string>
24 #include <unordered_map>
25 
26 namespace node {
27 
28 using v8::Array;
29 using v8::ArrayBufferView;
30 using v8::Context;
31 using v8::EscapableHandleScope;
32 using v8::Integer;
33 using v8::Local;
34 using v8::MaybeLocal;
35 using v8::NewStringType;
36 using v8::Null;
37 using v8::Object;
38 using v8::String;
39 using v8::Undefined;
40 using v8::Value;
41 
42 namespace crypto {
43 
44 static constexpr int X509_NAME_FLAGS =
45     ASN1_STRFLGS_ESC_2253 |
46     ASN1_STRFLGS_ESC_CTRL |
47     ASN1_STRFLGS_UTF8_CONVERT |
48     XN_FLAG_SEP_MULTILINE |
49     XN_FLAG_FN_SN;
50 
SSL_CTX_get_issuer(SSL_CTX * ctx,X509 * cert,X509 ** issuer)51 int SSL_CTX_get_issuer(SSL_CTX* ctx, X509* cert, X509** issuer) {
52   X509_STORE* store = SSL_CTX_get_cert_store(ctx);
53   DeleteFnPtr<X509_STORE_CTX, X509_STORE_CTX_free> store_ctx(
54       X509_STORE_CTX_new());
55   return store_ctx.get() != nullptr &&
56          X509_STORE_CTX_init(store_ctx.get(), store, nullptr, nullptr) == 1 &&
57          X509_STORE_CTX_get1_issuer(issuer, store_ctx.get(), cert) == 1;
58 }
59 
LogSecret(const SSLPointer & ssl,const char * name,const unsigned char * secret,size_t secretlen)60 void LogSecret(
61     const SSLPointer& ssl,
62     const char* name,
63     const unsigned char* secret,
64     size_t secretlen) {
65   auto keylog_cb = SSL_CTX_get_keylog_callback(SSL_get_SSL_CTX(ssl.get()));
66   unsigned char crandom[32];
67 
68   if (keylog_cb == nullptr ||
69       SSL_get_client_random(ssl.get(), crandom, 32) != 32) {
70     return;
71   }
72 
73   std::string line = name;
74   line += " " + StringBytes::hex_encode(
75       reinterpret_cast<const char*>(crandom), 32);
76   line += " " + StringBytes::hex_encode(
77       reinterpret_cast<const char*>(secret), secretlen);
78   keylog_cb(ssl.get(), line.c_str());
79 }
80 
SetALPN(const SSLPointer & ssl,const std::string & alpn)81 bool SetALPN(const SSLPointer& ssl, const std::string& alpn) {
82   return SSL_set_alpn_protos(
83       ssl.get(),
84       reinterpret_cast<const uint8_t*>(alpn.c_str()),
85       alpn.length()) == 0;
86 }
87 
SetALPN(const SSLPointer & ssl,Local<Value> alpn)88 bool SetALPN(const SSLPointer& ssl, Local<Value> alpn) {
89   if (!alpn->IsArrayBufferView())
90     return false;
91   ArrayBufferViewContents<unsigned char> protos(alpn.As<ArrayBufferView>());
92   return SSL_set_alpn_protos(ssl.get(), protos.data(), protos.length()) == 0;
93 }
94 
GetSSLOCSPResponse(Environment * env,SSL * ssl,Local<Value> default_value)95 MaybeLocal<Value> GetSSLOCSPResponse(
96     Environment* env,
97     SSL* ssl,
98     Local<Value> default_value) {
99   const unsigned char* resp;
100   int len = SSL_get_tlsext_status_ocsp_resp(ssl, &resp);
101   if (resp == nullptr)
102     return default_value;
103 
104   Local<Value> ret;
105   MaybeLocal<Object> maybe_buffer =
106       Buffer::Copy(env, reinterpret_cast<const char*>(resp), len);
107 
108   if (!maybe_buffer.ToLocal(&ret))
109     return MaybeLocal<Value>();
110 
111   return ret;
112 }
113 
SetTLSSession(const SSLPointer & ssl,const unsigned char * buf,size_t length)114 bool SetTLSSession(
115     const SSLPointer& ssl,
116     const unsigned char* buf,
117     size_t length) {
118   SSLSessionPointer s(d2i_SSL_SESSION(nullptr, &buf, length));
119   return s == nullptr ? false : SetTLSSession(ssl, s);
120 }
121 
SetTLSSession(const SSLPointer & ssl,const SSLSessionPointer & session)122 bool SetTLSSession(
123     const SSLPointer& ssl,
124     const SSLSessionPointer& session) {
125   return session != nullptr && SSL_set_session(ssl.get(), session.get()) == 1;
126 }
127 
GetTLSSession(Local<Value> val)128 SSLSessionPointer GetTLSSession(Local<Value> val) {
129   if (!val->IsArrayBufferView())
130     return SSLSessionPointer();
131   ArrayBufferViewContents<unsigned char> sbuf(val.As<ArrayBufferView>());
132   return GetTLSSession(sbuf.data(), sbuf.length());
133 }
134 
GetTLSSession(const unsigned char * buf,size_t length)135 SSLSessionPointer GetTLSSession(const unsigned char* buf, size_t length) {
136   return SSLSessionPointer(d2i_SSL_SESSION(nullptr, &buf, length));
137 }
138 
VerifyPeerCertificate(const SSLPointer & ssl,long def)139 long VerifyPeerCertificate(  // NOLINT(runtime/int)
140     const SSLPointer& ssl,
141     long def) {  // NOLINT(runtime/int)
142   long err = def;  // NOLINT(runtime/int)
143   if (X509* peer_cert = SSL_get_peer_certificate(ssl.get())) {
144     X509_free(peer_cert);
145     err = SSL_get_verify_result(ssl.get());
146   } else {
147     const SSL_CIPHER* curr_cipher = SSL_get_current_cipher(ssl.get());
148     const SSL_SESSION* sess = SSL_get_session(ssl.get());
149     // Allow no-cert for PSK authentication in TLS1.2 and lower.
150     // In TLS1.3 check that session was reused because TLS1.3 PSK
151     // looks like session resumption.
152     if (SSL_CIPHER_get_auth_nid(curr_cipher) == NID_auth_psk ||
153         (SSL_SESSION_get_protocol_version(sess) == TLS1_3_VERSION &&
154          SSL_session_reused(ssl.get()))) {
155       return X509_V_OK;
156     }
157   }
158   return err;
159 }
160 
UseSNIContext(const SSLPointer & ssl,BaseObjectPtr<SecureContext> context)161 int UseSNIContext(const SSLPointer& ssl, BaseObjectPtr<SecureContext> context) {
162   SSL_CTX* ctx = context->ctx_.get();
163   X509* x509 = SSL_CTX_get0_certificate(ctx);
164   EVP_PKEY* pkey = SSL_CTX_get0_privatekey(ctx);
165   STACK_OF(X509)* chain;
166 
167   int err = SSL_CTX_get0_chain_certs(ctx, &chain);
168   if (err == 1) err = SSL_use_certificate(ssl.get(), x509);
169   if (err == 1) err = SSL_use_PrivateKey(ssl.get(), pkey);
170   if (err == 1 && chain != nullptr) err = SSL_set1_chain(ssl.get(), chain);
171   return err;
172 }
173 
GetClientHelloALPN(const SSLPointer & ssl)174 const char* GetClientHelloALPN(const SSLPointer& ssl) {
175   const unsigned char* buf;
176   size_t len;
177   size_t rem;
178 
179   if (!SSL_client_hello_get0_ext(
180           ssl.get(),
181           TLSEXT_TYPE_application_layer_protocol_negotiation,
182           &buf,
183           &rem) ||
184       rem < 2) {
185     return nullptr;
186   }
187 
188   len = (buf[0] << 8) | buf[1];
189   if (len + 2 != rem) return nullptr;
190   return reinterpret_cast<const char*>(buf + 3);
191 }
192 
GetClientHelloServerName(const SSLPointer & ssl)193 const char* GetClientHelloServerName(const SSLPointer& ssl) {
194   const unsigned char* buf;
195   size_t len;
196   size_t rem;
197 
198   if (!SSL_client_hello_get0_ext(
199           ssl.get(),
200           TLSEXT_TYPE_server_name,
201           &buf,
202           &rem) || rem <= 2) {
203     return nullptr;
204   }
205 
206   len = (*buf << 8) | *(buf + 1);
207   if (len + 2 != rem)
208     return nullptr;
209   rem = len;
210 
211   if (rem == 0 || *(buf + 2) != TLSEXT_NAMETYPE_host_name) return nullptr;
212   rem--;
213   if (rem <= 2)
214     return nullptr;
215   len = (*(buf + 3) << 8) | *(buf + 4);
216   if (len + 2 > rem)
217     return nullptr;
218   return reinterpret_cast<const char*>(buf + 5);
219 }
220 
GetServerName(SSL * ssl)221 const char* GetServerName(SSL* ssl) {
222   return SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
223 }
224 
SetGroups(SecureContext * sc,const char * groups)225 bool SetGroups(SecureContext* sc, const char* groups) {
226   return SSL_CTX_set1_groups_list(**sc, groups) == 1;
227 }
228 
X509ErrorCode(long err)229 const char* X509ErrorCode(long err) {  // NOLINT(runtime/int)
230   const char* code = "UNSPECIFIED";
231 #define CASE_X509_ERR(CODE) case X509_V_ERR_##CODE: code = #CODE; break;
232   switch (err) {
233     CASE_X509_ERR(UNABLE_TO_GET_ISSUER_CERT)
234     CASE_X509_ERR(UNABLE_TO_GET_CRL)
235     CASE_X509_ERR(UNABLE_TO_DECRYPT_CERT_SIGNATURE)
236     CASE_X509_ERR(UNABLE_TO_DECRYPT_CRL_SIGNATURE)
237     CASE_X509_ERR(UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY)
238     CASE_X509_ERR(CERT_SIGNATURE_FAILURE)
239     CASE_X509_ERR(CRL_SIGNATURE_FAILURE)
240     CASE_X509_ERR(CERT_NOT_YET_VALID)
241     CASE_X509_ERR(CERT_HAS_EXPIRED)
242     CASE_X509_ERR(CRL_NOT_YET_VALID)
243     CASE_X509_ERR(CRL_HAS_EXPIRED)
244     CASE_X509_ERR(ERROR_IN_CERT_NOT_BEFORE_FIELD)
245     CASE_X509_ERR(ERROR_IN_CERT_NOT_AFTER_FIELD)
246     CASE_X509_ERR(ERROR_IN_CRL_LAST_UPDATE_FIELD)
247     CASE_X509_ERR(ERROR_IN_CRL_NEXT_UPDATE_FIELD)
248     CASE_X509_ERR(OUT_OF_MEM)
249     CASE_X509_ERR(DEPTH_ZERO_SELF_SIGNED_CERT)
250     CASE_X509_ERR(SELF_SIGNED_CERT_IN_CHAIN)
251     CASE_X509_ERR(UNABLE_TO_GET_ISSUER_CERT_LOCALLY)
252     CASE_X509_ERR(UNABLE_TO_VERIFY_LEAF_SIGNATURE)
253     CASE_X509_ERR(CERT_CHAIN_TOO_LONG)
254     CASE_X509_ERR(CERT_REVOKED)
255     CASE_X509_ERR(INVALID_CA)
256     CASE_X509_ERR(PATH_LENGTH_EXCEEDED)
257     CASE_X509_ERR(INVALID_PURPOSE)
258     CASE_X509_ERR(CERT_UNTRUSTED)
259     CASE_X509_ERR(CERT_REJECTED)
260     CASE_X509_ERR(HOSTNAME_MISMATCH)
261   }
262 #undef CASE_X509_ERR
263   return code;
264 }
265 
GetValidationErrorReason(Environment * env,int err)266 MaybeLocal<Value> GetValidationErrorReason(Environment* env, int err) {
267   if (err == 0)
268     return Undefined(env->isolate());
269   const char* reason = X509_verify_cert_error_string(err);
270   return OneByteString(env->isolate(), reason);
271 }
272 
GetValidationErrorCode(Environment * env,int err)273 MaybeLocal<Value> GetValidationErrorCode(Environment* env, int err) {
274   if (err == 0)
275     return Undefined(env->isolate());
276   return OneByteString(env->isolate(), X509ErrorCode(err));
277 }
278 
GetCert(Environment * env,const SSLPointer & ssl)279 MaybeLocal<Value> GetCert(Environment* env, const SSLPointer& ssl) {
280   ClearErrorOnReturn clear_error_on_return;
281   X509* cert = SSL_get_certificate(ssl.get());
282   if (cert == nullptr)
283     return Undefined(env->isolate());
284 
285   MaybeLocal<Object> maybe_cert = X509ToObject(env, cert);
286   return maybe_cert.FromMaybe<Value>(Local<Value>());
287 }
288 
289 namespace {
290 template <typename T>
Set(Local<Context> context,Local<Object> target,Local<Value> name,MaybeLocal<T> maybe_value)291 bool Set(
292     Local<Context> context,
293     Local<Object> target,
294     Local<Value> name,
295     MaybeLocal<T> maybe_value) {
296   Local<Value> value;
297   if (!maybe_value.ToLocal(&value))
298     return false;
299 
300   // Undefined is ignored, but still considered successful
301   if (value->IsUndefined())
302     return true;
303 
304   return !target->Set(context, name, value).IsNothing();
305 }
306 
ToV8Value(Environment * env,const BIOPointer & bio)307 Local<Value> ToV8Value(Environment* env, const BIOPointer& bio) {
308   BUF_MEM* mem;
309   BIO_get_mem_ptr(bio.get(), &mem);
310   MaybeLocal<String> ret =
311       String::NewFromUtf8(
312           env->isolate(),
313           mem->data,
314           NewStringType::kNormal,
315           mem->length);
316   USE(BIO_reset(bio.get()));
317   return ret.FromMaybe(Local<Value>());
318 }
319 
GetCipherValue(Environment * env,const SSL_CIPHER * cipher,const char * (* getstr)(const SSL_CIPHER * cipher))320 MaybeLocal<Value> GetCipherValue(Environment* env,
321     const SSL_CIPHER* cipher,
322     const char* (*getstr)(const SSL_CIPHER* cipher)) {
323   if (cipher == nullptr)
324     return Undefined(env->isolate());
325 
326   return OneByteString(env->isolate(), getstr(cipher));
327 }
328 
GetCipherName(Environment * env,const SSL_CIPHER * cipher)329 MaybeLocal<Value> GetCipherName(Environment* env, const SSL_CIPHER* cipher) {
330   return GetCipherValue(env, cipher, SSL_CIPHER_get_name);
331 }
332 
GetCipherStandardName(Environment * env,const SSL_CIPHER * cipher)333 MaybeLocal<Value> GetCipherStandardName(
334     Environment* env,
335     const SSL_CIPHER* cipher) {
336   return GetCipherValue(env, cipher, SSL_CIPHER_standard_name);
337 }
338 
GetCipherVersion(Environment * env,const SSL_CIPHER * cipher)339 MaybeLocal<Value> GetCipherVersion(Environment* env, const SSL_CIPHER* cipher) {
340   return GetCipherValue(env, cipher, SSL_CIPHER_get_version);
341 }
342 
CloneSSLCerts(X509Pointer && cert,const STACK_OF (X509)* const ssl_certs)343 StackOfX509 CloneSSLCerts(X509Pointer&& cert,
344                           const STACK_OF(X509)* const ssl_certs) {
345   StackOfX509 peer_certs(sk_X509_new(nullptr));
346   if (cert)
347     sk_X509_push(peer_certs.get(), cert.release());
348   for (int i = 0; i < sk_X509_num(ssl_certs); i++) {
349     X509Pointer cert(X509_dup(sk_X509_value(ssl_certs, i)));
350     if (!cert || !sk_X509_push(peer_certs.get(), cert.get()))
351       return StackOfX509();
352     // `cert` is now managed by the stack.
353     cert.release();
354   }
355   return peer_certs;
356 }
357 
AddIssuerChainToObject(X509Pointer * cert,Local<Object> object,StackOfX509 && peer_certs,Environment * const env)358 MaybeLocal<Object> AddIssuerChainToObject(
359     X509Pointer* cert,
360     Local<Object> object,
361     StackOfX509&& peer_certs,
362     Environment* const env) {
363   Local<Context> context = env->isolate()->GetCurrentContext();
364   cert->reset(sk_X509_delete(peer_certs.get(), 0));
365   for (;;) {
366     int i;
367     for (i = 0; i < sk_X509_num(peer_certs.get()); i++) {
368       X509* ca = sk_X509_value(peer_certs.get(), i);
369       if (X509_check_issued(ca, cert->get()) != X509_V_OK)
370         continue;
371 
372       Local<Object> ca_info;
373       MaybeLocal<Object> maybe_ca_info = X509ToObject(env, ca);
374       if (!maybe_ca_info.ToLocal(&ca_info))
375         return MaybeLocal<Object>();
376 
377       if (!Set<Object>(context, object, env->issuercert_string(), ca_info))
378         return MaybeLocal<Object>();
379       object = ca_info;
380 
381       // NOTE: Intentionally freeing cert that is not used anymore.
382       // Delete cert and continue aggregating issuers.
383       cert->reset(sk_X509_delete(peer_certs.get(), i));
384       break;
385     }
386 
387     // Issuer not found, break out of the loop.
388     if (i == sk_X509_num(peer_certs.get()))
389       break;
390   }
391   return MaybeLocal<Object>(object);
392 }
393 
GetLastIssuedCert(X509Pointer * cert,const SSLPointer & ssl,Local<Object> issuer_chain,Environment * const env)394 MaybeLocal<Object> GetLastIssuedCert(
395     X509Pointer* cert,
396     const SSLPointer& ssl,
397     Local<Object> issuer_chain,
398     Environment* const env) {
399   Local<Context> context = env->isolate()->GetCurrentContext();
400   while (X509_check_issued(cert->get(), cert->get()) != X509_V_OK) {
401     X509* ca;
402     if (SSL_CTX_get_issuer(SSL_get_SSL_CTX(ssl.get()), cert->get(), &ca) <= 0)
403       break;
404 
405     Local<Object> ca_info;
406     MaybeLocal<Object> maybe_ca_info = X509ToObject(env, ca);
407     if (!maybe_ca_info.ToLocal(&ca_info))
408       return MaybeLocal<Object>();
409 
410     if (!Set<Object>(context, issuer_chain, env->issuercert_string(), ca_info))
411       return MaybeLocal<Object>();
412     issuer_chain = ca_info;
413 
414     // Delete previous cert and continue aggregating issuers.
415     cert->reset(ca);
416   }
417   return MaybeLocal<Object>(issuer_chain);
418 }
419 
GetRawDERCertificate(Environment * env,X509 * cert)420 MaybeLocal<Object> GetRawDERCertificate(Environment* env, X509* cert) {
421   int size = i2d_X509(cert, nullptr);
422 
423   AllocatedBuffer buffer = AllocatedBuffer::AllocateManaged(env, size);
424   unsigned char* serialized =
425       reinterpret_cast<unsigned char*>(buffer.data());
426   i2d_X509(cert, &serialized);
427   return buffer.ToBuffer();
428 }
429 
GetSerialNumber(Environment * env,X509 * cert)430 MaybeLocal<Value> GetSerialNumber(Environment* env, X509* cert) {
431   if (ASN1_INTEGER* serial_number = X509_get_serialNumber(cert)) {
432     BignumPointer bn(ASN1_INTEGER_to_BN(serial_number, nullptr));
433     if (bn) {
434       OpenSSLBuffer buf(BN_bn2hex(bn.get()));
435       if (buf)
436         return OneByteString(env->isolate(), buf.get());
437     }
438   }
439 
440   return Undefined(env->isolate());
441 }
442 
GetKeyUsage(Environment * env,X509 * cert)443 MaybeLocal<Value> GetKeyUsage(Environment* env, X509* cert) {
444   StackOfASN1 eku(static_cast<STACK_OF(ASN1_OBJECT)*>(
445       X509_get_ext_d2i(cert, NID_ext_key_usage, nullptr, nullptr)));
446   if (eku) {
447     const int count = sk_ASN1_OBJECT_num(eku.get());
448     MaybeStackBuffer<Local<Value>, 16> ext_key_usage(count);
449     char buf[256];
450 
451     int j = 0;
452     for (int i = 0; i < count; i++) {
453       if (OBJ_obj2txt(buf,
454                       sizeof(buf),
455                       sk_ASN1_OBJECT_value(eku.get(), i), 1) >= 0) {
456         ext_key_usage[j++] = OneByteString(env->isolate(), buf);
457       }
458     }
459 
460     return Array::New(env->isolate(), ext_key_usage.out(), count);
461   }
462 
463   return Undefined(env->isolate());
464 }
465 
AddFingerprintDigest(const unsigned char * md,unsigned int md_size,char (* fingerprint)[3* EVP_MAX_MD_SIZE+1])466 void AddFingerprintDigest(
467     const unsigned char* md,
468     unsigned int md_size,
469     char (*fingerprint)[3 * EVP_MAX_MD_SIZE + 1]) {
470   unsigned int i;
471   const char hex[] = "0123456789ABCDEF";
472 
473   for (i = 0; i < md_size; i++) {
474     (*fingerprint)[3*i] = hex[(md[i] & 0xf0) >> 4];
475     (*fingerprint)[(3*i)+1] = hex[(md[i] & 0x0f)];
476     (*fingerprint)[(3*i)+2] = ':';
477   }
478 
479   if (md_size > 0) {
480     (*fingerprint)[(3*(md_size-1))+2] = '\0';
481   } else {
482     (*fingerprint)[0] = '\0';
483   }
484 }
485 
486 // deprecated, only used for security revert
SafeX509ExtPrint(const BIOPointer & out,X509_EXTENSION * ext)487 bool SafeX509ExtPrint(const BIOPointer& out, X509_EXTENSION* ext) {
488   const X509V3_EXT_METHOD* method = X509V3_EXT_get(ext);
489 
490   if (method != X509V3_EXT_get_nid(NID_subject_alt_name))
491     return false;
492 
493   GENERAL_NAMES* names = static_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(ext));
494   if (names == nullptr)
495     return false;
496 
497   for (int i = 0; i < sk_GENERAL_NAME_num(names); i++) {
498     GENERAL_NAME* gen = sk_GENERAL_NAME_value(names, i);
499 
500     if (i != 0)
501       BIO_write(out.get(), ", ", 2);
502 
503     if (gen->type == GEN_DNS) {
504       ASN1_IA5STRING* name = gen->d.dNSName;
505 
506       BIO_write(out.get(), "DNS:", 4);
507       BIO_write(out.get(), name->data, name->length);
508     } else {
509       STACK_OF(CONF_VALUE)* nval = i2v_GENERAL_NAME(
510           const_cast<X509V3_EXT_METHOD*>(method), gen, nullptr);
511       if (nval == nullptr) {
512         sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
513         return false;
514       }
515       X509V3_EXT_val_prn(out.get(), nval, 0, 0);
516       sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
517     }
518   }
519   sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
520 
521   return true;
522 }
523 
IsSafeAltName(const char * name,size_t length,bool utf8)524 static inline bool IsSafeAltName(const char* name, size_t length, bool utf8) {
525   for (size_t i = 0; i < length; i++) {
526     char c = name[i];
527     switch (c) {
528     case '"':
529     case '\\':
530       // These mess with encoding rules.
531       // Fall through.
532     case ',':
533       // Commas make it impossible to split the list of subject alternative
534       // names unambiguously, which is why we have to escape.
535       // Fall through.
536     case '\'':
537       // Single quotes are unlikely to appear in any legitimate values, but they
538       // could be used to make a value look like it was escaped (i.e., enclosed
539       // in single/double quotes).
540       return false;
541     default:
542       if (utf8) {
543         // In UTF8 strings, we require escaping for any ASCII control character,
544         // but NOT for non-ASCII characters. Note that all bytes of any code
545         // point that consists of more than a single byte have their MSB set.
546         if (static_cast<unsigned char>(c) < ' ' || c == '\x7f') {
547           return false;
548         }
549       } else {
550         // Check if the char is a control character or non-ASCII character. Note
551         // that char may or may not be a signed type. Regardless, non-ASCII
552         // values will always be outside of this range.
553         if (c < ' ' || c > '~') {
554           return false;
555         }
556       }
557     }
558   }
559   return true;
560 }
561 
PrintAltName(const BIOPointer & out,const char * name,size_t length,bool utf8,const char * safe_prefix)562 static inline void PrintAltName(const BIOPointer& out, const char* name,
563                                 size_t length, bool utf8,
564                                 const char* safe_prefix) {
565   if (IsSafeAltName(name, length, utf8)) {
566     // For backward-compatibility, append "safe" names without any
567     // modifications.
568     if (safe_prefix != nullptr) {
569       BIO_printf(out.get(), "%s:", safe_prefix);
570     }
571     BIO_write(out.get(), name, length);
572   } else {
573     // If a name is not "safe", we cannot embed it without special
574     // encoding. This does not usually happen, but we don't want to hide
575     // it from the user either. We use JSON compatible escaping here.
576     BIO_write(out.get(), "\"", 1);
577     if (safe_prefix != nullptr) {
578       BIO_printf(out.get(), "%s:", safe_prefix);
579     }
580     for (size_t j = 0; j < length; j++) {
581       char c = static_cast<char>(name[j]);
582       if (c == '\\') {
583         BIO_write(out.get(), "\\\\", 2);
584       } else if (c == '"') {
585         BIO_write(out.get(), "\\\"", 2);
586       } else if ((c >= ' ' && c != ',' && c <= '~') || (utf8 && (c & 0x80))) {
587         // Note that the above condition explicitly excludes commas, which means
588         // that those are encoded as Unicode escape sequences in the "else"
589         // block. That is not strictly necessary, and Node.js itself would parse
590         // it correctly either way. We only do this to account for third-party
591         // code that might be splitting the string at commas (as Node.js itself
592         // used to do).
593         BIO_write(out.get(), &c, 1);
594       } else {
595         // Control character or non-ASCII character. We treat everything as
596         // Latin-1, which corresponds to the first 255 Unicode code points.
597         const char hex[] = "0123456789abcdef";
598         char u[] = { '\\', 'u', '0', '0', hex[(c & 0xf0) >> 4], hex[c & 0x0f] };
599         BIO_write(out.get(), u, sizeof(u));
600       }
601     }
602     BIO_write(out.get(), "\"", 1);
603   }
604 }
605 
PrintLatin1AltName(const BIOPointer & out,const ASN1_IA5STRING * name,const char * safe_prefix=nullptr)606 static inline void PrintLatin1AltName(const BIOPointer& out,
607                                       const ASN1_IA5STRING* name,
608                                       const char* safe_prefix = nullptr) {
609   PrintAltName(out, reinterpret_cast<const char*>(name->data), name->length,
610                false, safe_prefix);
611 }
612 
PrintUtf8AltName(const BIOPointer & out,const ASN1_UTF8STRING * name,const char * safe_prefix=nullptr)613 static inline void PrintUtf8AltName(const BIOPointer& out,
614                                     const ASN1_UTF8STRING* name,
615                                     const char* safe_prefix = nullptr) {
616   PrintAltName(out, reinterpret_cast<const char*>(name->data), name->length,
617                true, safe_prefix);
618 }
619 
620 // This function currently emulates the behavior of i2v_GENERAL_NAME in a safer
621 // and less ambiguous way.
622 // TODO(tniessen): gradually improve the format in the next major version(s)
PrintGeneralName(const BIOPointer & out,const GENERAL_NAME * gen)623 static bool PrintGeneralName(const BIOPointer& out, const GENERAL_NAME* gen) {
624   if (gen->type == GEN_DNS) {
625     ASN1_IA5STRING* name = gen->d.dNSName;
626     BIO_write(out.get(), "DNS:", 4);
627     // Note that the preferred name syntax (see RFCs 5280 and 1034) with
628     // wildcards is a subset of what we consider "safe", so spec-compliant DNS
629     // names will never need to be escaped.
630     PrintLatin1AltName(out, name);
631   } else if (gen->type == GEN_EMAIL) {
632     ASN1_IA5STRING* name = gen->d.rfc822Name;
633     BIO_write(out.get(), "email:", 6);
634     PrintLatin1AltName(out, name);
635   } else if (gen->type == GEN_URI) {
636     ASN1_IA5STRING* name = gen->d.uniformResourceIdentifier;
637     BIO_write(out.get(), "URI:", 4);
638     // The set of "safe" names was designed to include just about any URI,
639     // with a few exceptions, most notably URIs that contains commas (see
640     // RFC 2396). In other words, most legitimate URIs will not require
641     // escaping.
642     PrintLatin1AltName(out, name);
643   } else if (gen->type == GEN_DIRNAME) {
644     // For backward compatibility, use X509_NAME_oneline to print the
645     // X509_NAME object. The format is non standard and should be avoided
646     // elsewhere, but conveniently, the function produces ASCII and the output
647     // is unlikely to contains commas or other characters that would require
648     // escaping. With that in mind, note that it SHOULD NOT produce ASCII
649     // output since an RFC5280 AttributeValue may be a UTF8String.
650     // TODO(tniessen): switch to RFC2253 rules in a major release
651     BIO_printf(out.get(), "DirName:");
652     char oline[256];
653     if (X509_NAME_oneline(gen->d.dirn, oline, sizeof(oline)) != nullptr) {
654       PrintAltName(out, oline, strlen(oline), false, nullptr);
655     } else {
656       return false;
657     }
658   } else if (gen->type == GEN_IPADD) {
659     BIO_printf(out.get(), "IP Address:");
660     const ASN1_OCTET_STRING* ip = gen->d.ip;
661     const unsigned char* b = ip->data;
662     if (ip->length == 4) {
663       BIO_printf(out.get(), "%d.%d.%d.%d", b[0], b[1], b[2], b[3]);
664     } else if (ip->length == 16) {
665       for (unsigned int j = 0; j < 8; j++) {
666         uint16_t pair = (b[2 * j] << 8) | b[2 * j + 1];
667         BIO_printf(out.get(), (j == 0) ? "%X" : ":%X", pair);
668       }
669     } else {
670 #if OPENSSL_VERSION_MAJOR >= 3
671       BIO_printf(out.get(), "<invalid length=%d>", ip->length);
672 #else
673       BIO_printf(out.get(), "<invalid>");
674 #endif
675     }
676   } else if (gen->type == GEN_RID) {
677     // TODO(tniessen): unlike OpenSSL's default implementation, never print the
678     // OID as text and instead always print its numeric representation, which is
679     // backward compatible in practice and more future proof (see OBJ_obj2txt).
680     char oline[256];
681     i2t_ASN1_OBJECT(oline, sizeof(oline), gen->d.rid);
682     BIO_printf(out.get(), "Registered ID:%s", oline);
683   } else if (gen->type == GEN_OTHERNAME) {
684     // TODO(tniessen): the format that is used here is based on OpenSSL's
685     // implementation of i2v_GENERAL_NAME (as of OpenSSL 3.0.1), mostly for
686     // backward compatibility. It is somewhat awkward, especially when passed to
687     // translatePeerCertificate, and should be changed in the future, probably
688     // to the format used by GENERAL_NAME_print (in a major release).
689     bool unicode = true;
690     const char* prefix = nullptr;
691     // OpenSSL 1.1.1 does not support othername in i2v_GENERAL_NAME and may not
692     // define these NIDs.
693 #if OPENSSL_VERSION_MAJOR >= 3
694     int nid = OBJ_obj2nid(gen->d.otherName->type_id);
695     switch (nid) {
696       case NID_id_on_SmtpUTF8Mailbox:
697         prefix = " SmtpUTF8Mailbox:";
698         break;
699       case NID_XmppAddr:
700         prefix = " XmppAddr:";
701         break;
702       case NID_SRVName:
703         prefix = " SRVName:";
704         unicode = false;
705         break;
706       case NID_ms_upn:
707         prefix = " UPN:";
708         break;
709       case NID_NAIRealm:
710         prefix = " NAIRealm:";
711         break;
712     }
713 #endif  // OPENSSL_VERSION_MAJOR >= 3
714     int val_type = gen->d.otherName->value->type;
715     if (prefix == nullptr ||
716         (unicode && val_type != V_ASN1_UTF8STRING) ||
717         (!unicode && val_type != V_ASN1_IA5STRING)) {
718       BIO_printf(out.get(), "othername:<unsupported>");
719     } else {
720       BIO_printf(out.get(), "othername:");
721       if (unicode) {
722         PrintUtf8AltName(out, gen->d.otherName->value->value.utf8string,
723                          prefix);
724       } else {
725         PrintLatin1AltName(out, gen->d.otherName->value->value.ia5string,
726                            prefix);
727       }
728     }
729   } else if (gen->type == GEN_X400) {
730     // TODO(tniessen): this is what OpenSSL does, implement properly instead
731     BIO_printf(out.get(), "X400Name:<unsupported>");
732   } else if (gen->type == GEN_EDIPARTY) {
733     // TODO(tniessen): this is what OpenSSL does, implement properly instead
734     BIO_printf(out.get(), "EdiPartyName:<unsupported>");
735   } else {
736     // This is safe because X509V3_EXT_d2i would have returned nullptr in this
737     // case already.
738     UNREACHABLE();
739   }
740 
741   return true;
742 }
743 
SafeX509SubjectAltNamePrint(const BIOPointer & out,X509_EXTENSION * ext)744 bool SafeX509SubjectAltNamePrint(const BIOPointer& out, X509_EXTENSION* ext) {
745   const X509V3_EXT_METHOD* method = X509V3_EXT_get(ext);
746   CHECK(method == X509V3_EXT_get_nid(NID_subject_alt_name));
747 
748   if (IsReverted(SECURITY_REVERT_CVE_2021_44532)) {
749     return  SafeX509ExtPrint(out, ext);
750   }
751 
752   GENERAL_NAMES* names = static_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(ext));
753   if (names == nullptr)
754     return false;
755 
756   bool ok = true;
757 
758   for (int i = 0; i < sk_GENERAL_NAME_num(names); i++) {
759     GENERAL_NAME* gen = sk_GENERAL_NAME_value(names, i);
760 
761     if (i != 0)
762       BIO_write(out.get(), ", ", 2);
763 
764     if (!(ok = PrintGeneralName(out, gen))) {
765       break;
766     }
767   }
768   sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
769 
770   return ok;
771 }
772 
SafeX509InfoAccessPrint(const BIOPointer & out,X509_EXTENSION * ext)773 bool SafeX509InfoAccessPrint(const BIOPointer& out, X509_EXTENSION* ext) {
774   const X509V3_EXT_METHOD* method = X509V3_EXT_get(ext);
775   CHECK(method == X509V3_EXT_get_nid(NID_info_access));
776 
777   if (IsReverted(SECURITY_REVERT_CVE_2021_44532)) {
778     return (X509V3_EXT_print(out.get(), ext, 0, 0) == 1);
779   }
780 
781   AUTHORITY_INFO_ACCESS* descs =
782       static_cast<AUTHORITY_INFO_ACCESS*>(X509V3_EXT_d2i(ext));
783   if (descs == nullptr)
784     return false;
785 
786   bool ok = true;
787 
788   for (int i = 0; i < sk_ACCESS_DESCRIPTION_num(descs); i++) {
789     ACCESS_DESCRIPTION* desc = sk_ACCESS_DESCRIPTION_value(descs, i);
790 
791     if (i != 0)
792       BIO_write(out.get(), "\n", 1);
793 
794     char objtmp[80];
795     i2t_ASN1_OBJECT(objtmp, sizeof(objtmp), desc->method);
796     BIO_printf(out.get(), "%s - ", objtmp);
797     if (!(ok = PrintGeneralName(out, desc->location))) {
798       break;
799     }
800   }
801   sk_ACCESS_DESCRIPTION_pop_free(descs, ACCESS_DESCRIPTION_free);
802 
803 #if OPENSSL_VERSION_MAJOR < 3
804   BIO_write(out.get(), "\n", 1);
805 #endif
806 
807   return ok;
808 }
809 
GetSubjectAltNameString(Environment * env,const BIOPointer & bio,X509 * cert)810 v8::MaybeLocal<v8::Value> GetSubjectAltNameString(
811     Environment* env,
812     const BIOPointer& bio,
813     X509* cert) {
814   int index = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
815   if (index < 0)
816     return Undefined(env->isolate());
817 
818   X509_EXTENSION* ext = X509_get_ext(cert, index);
819   CHECK_NOT_NULL(ext);
820 
821   if (!SafeX509SubjectAltNamePrint(bio, ext)) {
822     USE(BIO_reset(bio.get()));
823     return v8::Null(env->isolate());
824   }
825 
826   return ToV8Value(env, bio);
827 }
828 
GetInfoAccessString(Environment * env,const BIOPointer & bio,X509 * cert)829 v8::MaybeLocal<v8::Value> GetInfoAccessString(
830     Environment* env,
831     const BIOPointer& bio,
832     X509* cert) {
833   int index = X509_get_ext_by_NID(cert, NID_info_access, -1);
834   if (index < 0)
835     return Undefined(env->isolate());
836 
837   X509_EXTENSION* ext = X509_get_ext(cert, index);
838   CHECK_NOT_NULL(ext);
839 
840   if (!SafeX509InfoAccessPrint(bio, ext)) {
841     USE(BIO_reset(bio.get()));
842     return v8::Null(env->isolate());
843   }
844 
845   return ToV8Value(env, bio);
846 }
847 
848 template <X509_NAME* get_name(const X509*)>
GetX509NameObject(Environment * env,X509 * cert)849 static MaybeLocal<Value> GetX509NameObject(Environment* env, X509* cert) {
850   X509_NAME* name = get_name(cert);
851   CHECK_NOT_NULL(name);
852 
853   int cnt = X509_NAME_entry_count(name);
854   CHECK_GE(cnt, 0);
855 
856   Local<Object> result =
857       Object::New(env->isolate(), Null(env->isolate()), nullptr, nullptr, 0);
858   if (result.IsEmpty()) {
859     return MaybeLocal<Value>();
860   }
861 
862   for (int i = 0; i < cnt; i++) {
863     X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, i);
864     CHECK_NOT_NULL(entry);
865 
866     // We intentionally ignore the value of X509_NAME_ENTRY_set because the
867     // representation as an object does not allow grouping entries into sets
868     // anyway, and multi-value RDNs are rare, i.e., the vast majority of
869     // Relative Distinguished Names contains a single type-value pair only.
870     const ASN1_OBJECT* type = X509_NAME_ENTRY_get_object(entry);
871     const ASN1_STRING* value = X509_NAME_ENTRY_get_data(entry);
872 
873     // If OpenSSL knows the type, use the short name of the type as the key, and
874     // the numeric representation of the type's OID otherwise.
875     int type_nid = OBJ_obj2nid(type);
876     char type_buf[80];
877     const char* type_str;
878     if (type_nid != NID_undef) {
879       type_str = OBJ_nid2sn(type_nid);
880       CHECK_NOT_NULL(type_str);
881     } else {
882       OBJ_obj2txt(type_buf, sizeof(type_buf), type, true);
883       type_str = type_buf;
884     }
885 
886     Local<String> v8_name;
887     if (!String::NewFromUtf8(env->isolate(), type_str,
888                              NewStringType::kNormal).ToLocal(&v8_name)) {
889       return MaybeLocal<Value>();
890     }
891 
892     // The previous implementation used X509_NAME_print_ex, which escapes some
893     // characters in the value. The old implementation did not decode/unescape
894     // values correctly though, leading to ambiguous and incorrect
895     // representations. The new implementation only converts to Unicode and does
896     // not escape anything.
897     unsigned char* value_str;
898     int value_str_size = ASN1_STRING_to_UTF8(&value_str, value);
899     if (value_str_size < 0) {
900       return Undefined(env->isolate());
901     }
902 
903     Local<String> v8_value;
904     if (!String::NewFromUtf8(env->isolate(),
905                              reinterpret_cast<const char*>(value_str),
906                              NewStringType::kNormal,
907                              value_str_size).ToLocal(&v8_value)) {
908       OPENSSL_free(value_str);
909       return MaybeLocal<Value>();
910     }
911 
912     OPENSSL_free(value_str);
913 
914     // For backward compatibility, we only create arrays if multiple values
915     // exist for the same key. That is not great but there is not much we can
916     // change here without breaking things. Note that this creates nested data
917     // structures, yet still does not allow representing Distinguished Names
918     // accurately.
919     if (result->HasOwnProperty(env->context(), v8_name).ToChecked()) {
920       Local<Value> accum =
921           result->Get(env->context(), v8_name).ToLocalChecked();
922       if (!accum->IsArray()) {
923         accum = Array::New(env->isolate(), &accum, 1);
924         result->Set(env->context(), v8_name, accum).Check();
925       }
926       Local<Array> array = accum.As<Array>();
927       array->Set(env->context(), array->Length(), v8_value).Check();
928     } else {
929       result->Set(env->context(), v8_name, v8_value).Check();
930     }
931   }
932 
933   return result;
934 }
935 
GetFingerprintDigest(Environment * env,const EVP_MD * method,X509 * cert)936 MaybeLocal<Value> GetFingerprintDigest(
937     Environment* env,
938     const EVP_MD* method,
939     X509* cert) {
940   unsigned char md[EVP_MAX_MD_SIZE];
941   unsigned int md_size;
942   char fingerprint[EVP_MAX_MD_SIZE * 3 + 1];
943 
944   if (X509_digest(cert, method, md, &md_size)) {
945     AddFingerprintDigest(md, md_size, &fingerprint);
946     return OneByteString(env->isolate(), fingerprint);
947   }
948   return Undefined(env->isolate());
949 }
950 
GetValidTo(Environment * env,X509 * cert,const BIOPointer & bio)951 MaybeLocal<Value> GetValidTo(
952     Environment* env,
953     X509* cert,
954     const BIOPointer& bio) {
955   ASN1_TIME_print(bio.get(), X509_get0_notAfter(cert));
956   return ToV8Value(env, bio);
957 }
958 
GetValidFrom(Environment * env,X509 * cert,const BIOPointer & bio)959 MaybeLocal<Value> GetValidFrom(
960     Environment* env,
961     X509* cert,
962     const BIOPointer& bio) {
963   ASN1_TIME_print(bio.get(), X509_get0_notBefore(cert));
964   return ToV8Value(env, bio);
965 }
966 
GetCurveASN1Name(Environment * env,const int nid)967 MaybeLocal<Value> GetCurveASN1Name(Environment* env, const int nid) {
968   const char* nist = OBJ_nid2sn(nid);
969   return nist != nullptr ?
970       MaybeLocal<Value>(OneByteString(env->isolate(), nist)) :
971       MaybeLocal<Value>(Undefined(env->isolate()));
972 }
973 
GetCurveNistName(Environment * env,const int nid)974 MaybeLocal<Value> GetCurveNistName(Environment* env, const int nid) {
975   const char* nist = EC_curve_nid2nist(nid);
976   return nist != nullptr ?
977       MaybeLocal<Value>(OneByteString(env->isolate(), nist)) :
978       MaybeLocal<Value>(Undefined(env->isolate()));
979 }
980 
GetECPubKey(Environment * env,const EC_GROUP * group,const ECPointer & ec)981 MaybeLocal<Value> GetECPubKey(
982     Environment* env,
983     const EC_GROUP* group,
984     const ECPointer& ec) {
985   const EC_POINT* pubkey = EC_KEY_get0_public_key(ec.get());
986   if (pubkey == nullptr)
987     return Undefined(env->isolate());
988 
989   return ECPointToBuffer(
990       env,
991       group,
992       pubkey,
993       EC_KEY_get_conv_form(ec.get()),
994       nullptr).FromMaybe(Local<Object>());
995 }
996 
GetECGroup(Environment * env,const EC_GROUP * group,const ECPointer & ec)997 MaybeLocal<Value> GetECGroup(
998     Environment* env,
999     const EC_GROUP* group,
1000     const ECPointer& ec) {
1001   if (group == nullptr)
1002     return Undefined(env->isolate());
1003 
1004   int bits = EC_GROUP_order_bits(group);
1005   if (bits <= 0)
1006     return Undefined(env->isolate());
1007 
1008   return Integer::New(env->isolate(), bits);
1009 }
1010 
GetPubKey(Environment * env,const RSAPointer & rsa)1011 MaybeLocal<Object> GetPubKey(Environment* env, const RSAPointer& rsa) {
1012   int size = i2d_RSA_PUBKEY(rsa.get(), nullptr);
1013   CHECK_GE(size, 0);
1014 
1015   AllocatedBuffer buffer = AllocatedBuffer::AllocateManaged(env, size);
1016   unsigned char* serialized =
1017       reinterpret_cast<unsigned char*>(buffer.data());
1018   i2d_RSA_PUBKEY(rsa.get(), &serialized);
1019   return buffer.ToBuffer();
1020 }
1021 
GetExponentString(Environment * env,const BIOPointer & bio,const BIGNUM * e)1022 MaybeLocal<Value> GetExponentString(
1023     Environment* env,
1024     const BIOPointer& bio,
1025     const BIGNUM* e) {
1026   uint64_t exponent_word = static_cast<uint64_t>(BN_get_word(e));
1027   uint32_t lo = static_cast<uint32_t>(exponent_word);
1028   uint32_t hi = static_cast<uint32_t>(exponent_word >> 32);
1029   if (hi == 0)
1030     BIO_printf(bio.get(), "0x%x", lo);
1031   else
1032     BIO_printf(bio.get(), "0x%x%08x", hi, lo);
1033 
1034   return ToV8Value(env, bio);
1035 }
1036 
GetBits(Environment * env,const BIGNUM * n)1037 Local<Value> GetBits(Environment* env, const BIGNUM* n) {
1038   return Integer::New(env->isolate(), BN_num_bits(n));
1039 }
1040 
GetModulusString(Environment * env,const BIOPointer & bio,const BIGNUM * n)1041 MaybeLocal<Value> GetModulusString(
1042     Environment* env,
1043     const BIOPointer& bio,
1044     const BIGNUM* n) {
1045   BN_print(bio.get(), n);
1046   return ToV8Value(env, bio);
1047 }
1048 
GetIssuerString(Environment * env,const BIOPointer & bio,X509 * cert)1049 MaybeLocal<Value> GetIssuerString(
1050     Environment* env,
1051     const BIOPointer& bio,
1052     X509* cert) {
1053   X509_NAME* issuer_name = X509_get_issuer_name(cert);
1054   if (X509_NAME_print_ex(bio.get(), issuer_name, 0, X509_NAME_FLAGS) <= 0) {
1055     USE(BIO_reset(bio.get()));
1056     return Undefined(env->isolate());
1057   }
1058 
1059   return ToV8Value(env, bio);
1060 }
1061 
GetSubject(Environment * env,const BIOPointer & bio,X509 * cert)1062 MaybeLocal<Value> GetSubject(
1063     Environment* env,
1064     const BIOPointer& bio,
1065     X509* cert) {
1066   if (X509_NAME_print_ex(
1067           bio.get(),
1068           X509_get_subject_name(cert),
1069           0,
1070           X509_NAME_FLAGS) <= 0) {
1071     USE(BIO_reset(bio.get()));
1072     return Undefined(env->isolate());
1073   }
1074 
1075   return ToV8Value(env, bio);
1076 }
1077 }  // namespace
1078 
GetCipherName(Environment * env,const SSLPointer & ssl)1079 MaybeLocal<Value> GetCipherName(Environment* env, const SSLPointer& ssl) {
1080   return GetCipherName(env, SSL_get_current_cipher(ssl.get()));
1081 }
1082 
GetCipherStandardName(Environment * env,const SSLPointer & ssl)1083 MaybeLocal<Value> GetCipherStandardName(
1084     Environment* env,
1085     const SSLPointer& ssl) {
1086   return GetCipherStandardName(env, SSL_get_current_cipher(ssl.get()));
1087 }
1088 
GetCipherVersion(Environment * env,const SSLPointer & ssl)1089 MaybeLocal<Value> GetCipherVersion(Environment* env, const SSLPointer& ssl) {
1090   return GetCipherVersion(env, SSL_get_current_cipher(ssl.get()));
1091 }
1092 
GetClientHelloCiphers(Environment * env,const SSLPointer & ssl)1093 MaybeLocal<Array> GetClientHelloCiphers(
1094     Environment* env,
1095     const SSLPointer& ssl) {
1096   EscapableHandleScope scope(env->isolate());
1097   const unsigned char* buf;
1098   size_t len = SSL_client_hello_get0_ciphers(ssl.get(), &buf);
1099   size_t count = len / 2;
1100   MaybeStackBuffer<Local<Value>, 16> ciphers(count);
1101   int j = 0;
1102   for (size_t n = 0; n < len; n += 2) {
1103     const SSL_CIPHER* cipher = SSL_CIPHER_find(ssl.get(), buf);
1104     buf += 2;
1105     Local<Object> obj = Object::New(env->isolate());
1106     if (!Set(env->context(),
1107              obj,
1108              env->name_string(),
1109              GetCipherName(env, cipher)) ||
1110         !Set(env->context(),
1111              obj,
1112              env->standard_name_string(),
1113              GetCipherStandardName(env, cipher)) ||
1114         !Set(env->context(),
1115              obj,
1116              env->version_string(),
1117              GetCipherVersion(env, cipher))) {
1118       return MaybeLocal<Array>();
1119     }
1120     ciphers[j++] = obj;
1121   }
1122   Local<Array> ret = Array::New(env->isolate(), ciphers.out(), count);
1123   return scope.Escape(ret);
1124 }
1125 
1126 
GetCipherInfo(Environment * env,const SSLPointer & ssl)1127 MaybeLocal<Object> GetCipherInfo(Environment* env, const SSLPointer& ssl) {
1128   EscapableHandleScope scope(env->isolate());
1129   Local<Object> info = Object::New(env->isolate());
1130 
1131   if (!Set<Value>(env->context(),
1132                   info,
1133                   env->name_string(),
1134                   GetCipherName(env, ssl)) ||
1135       !Set<Value>(env->context(),
1136                   info,
1137                   env->standard_name_string(),
1138                   GetCipherStandardName(env, ssl)) ||
1139       !Set<Value>(env->context(),
1140                   info,
1141                   env->version_string(),
1142                   GetCipherVersion(env, ssl))) {
1143     return MaybeLocal<Object>();
1144   }
1145 
1146   return scope.Escape(info);
1147 }
1148 
GetEphemeralKey(Environment * env,const SSLPointer & ssl)1149 MaybeLocal<Object> GetEphemeralKey(Environment* env, const SSLPointer& ssl) {
1150   CHECK_EQ(SSL_is_server(ssl.get()), 0);
1151   EVP_PKEY* raw_key;
1152 
1153   EscapableHandleScope scope(env->isolate());
1154   Local<Object> info = Object::New(env->isolate());
1155   if (!SSL_get_server_tmp_key(ssl.get(), &raw_key))
1156     return scope.Escape(info);
1157 
1158   Local<Context> context = env->context();
1159   crypto::EVPKeyPointer key(raw_key);
1160 
1161   int kid = EVP_PKEY_id(key.get());
1162   int bits = EVP_PKEY_bits(key.get());
1163   switch (kid) {
1164     case EVP_PKEY_DH:
1165       if (!Set<String>(context, info, env->type_string(), env->dh_string()) ||
1166           !Set<Integer>(context,
1167                info,
1168                env->size_string(),
1169                Integer::New(env->isolate(), bits))) {
1170         return MaybeLocal<Object>();
1171       }
1172       break;
1173     case EVP_PKEY_EC:
1174     case EVP_PKEY_X25519:
1175     case EVP_PKEY_X448:
1176       {
1177         const char* curve_name;
1178         if (kid == EVP_PKEY_EC) {
1179           ECKeyPointer ec(EVP_PKEY_get1_EC_KEY(key.get()));
1180           int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec.get()));
1181           curve_name = OBJ_nid2sn(nid);
1182         } else {
1183           curve_name = OBJ_nid2sn(kid);
1184         }
1185         if (!Set<String>(context,
1186                          info,
1187                          env->type_string(),
1188                          env->ecdh_string()) ||
1189             !Set<String>(context,
1190                 info,
1191                 env->name_string(),
1192                 OneByteString(env->isolate(), curve_name)) ||
1193             !Set<Integer>(context,
1194                  info,
1195                  env->size_string(),
1196                  Integer::New(env->isolate(), bits))) {
1197           return MaybeLocal<Object>();
1198         }
1199       }
1200       break;
1201   }
1202 
1203   return scope.Escape(info);
1204 }
1205 
ECPointToBuffer(Environment * env,const EC_GROUP * group,const EC_POINT * point,point_conversion_form_t form,const char ** error)1206 MaybeLocal<Object> ECPointToBuffer(Environment* env,
1207                                    const EC_GROUP* group,
1208                                    const EC_POINT* point,
1209                                    point_conversion_form_t form,
1210                                    const char** error) {
1211   size_t len = EC_POINT_point2oct(group, point, form, nullptr, 0, nullptr);
1212   if (len == 0) {
1213     if (error != nullptr) *error = "Failed to get public key length";
1214     return MaybeLocal<Object>();
1215   }
1216   AllocatedBuffer buf = AllocatedBuffer::AllocateManaged(env, len);
1217   len = EC_POINT_point2oct(group,
1218                            point,
1219                            form,
1220                            reinterpret_cast<unsigned char*>(buf.data()),
1221                            buf.size(),
1222                            nullptr);
1223   if (len == 0) {
1224     if (error != nullptr) *error = "Failed to get public key";
1225     return MaybeLocal<Object>();
1226   }
1227   return buf.ToBuffer();
1228 }
1229 
GetPeerCert(Environment * env,const SSLPointer & ssl,bool abbreviated,bool is_server)1230 MaybeLocal<Value> GetPeerCert(
1231     Environment* env,
1232     const SSLPointer& ssl,
1233     bool abbreviated,
1234     bool is_server) {
1235   ClearErrorOnReturn clear_error_on_return;
1236   Local<Object> result;
1237   MaybeLocal<Object> maybe_cert;
1238 
1239   // NOTE: This is because of the odd OpenSSL behavior. On client `cert_chain`
1240   // contains the `peer_certificate`, but on server it doesn't.
1241   X509Pointer cert(is_server ? SSL_get_peer_certificate(ssl.get()) : nullptr);
1242   STACK_OF(X509)* ssl_certs = SSL_get_peer_cert_chain(ssl.get());
1243   if (!cert && (ssl_certs == nullptr || sk_X509_num(ssl_certs) == 0))
1244     return Undefined(env->isolate());
1245 
1246   // Short result requested.
1247   if (abbreviated) {
1248     maybe_cert =
1249         X509ToObject(env, cert ? cert.get() : sk_X509_value(ssl_certs, 0));
1250     return maybe_cert.ToLocal(&result) ? result : MaybeLocal<Value>();
1251   }
1252 
1253   StackOfX509 peer_certs = CloneSSLCerts(std::move(cert), ssl_certs);
1254   if (peer_certs == nullptr)
1255     return Undefined(env->isolate());
1256 
1257   // First and main certificate.
1258   X509Pointer first_cert(sk_X509_value(peer_certs.get(), 0));
1259   CHECK(first_cert);
1260   maybe_cert = X509ToObject(env, first_cert.release()).ToLocalChecked();
1261   if (!maybe_cert.ToLocal(&result))
1262     return MaybeLocal<Value>();
1263 
1264   Local<Object> issuer_chain;
1265   MaybeLocal<Object> maybe_issuer_chain;
1266 
1267   maybe_issuer_chain =
1268       AddIssuerChainToObject(
1269           &cert,
1270           result,
1271           std::move(peer_certs),
1272           env);
1273   if (!maybe_issuer_chain.ToLocal(&issuer_chain))
1274     return MaybeLocal<Value>();
1275 
1276   maybe_issuer_chain =
1277       GetLastIssuedCert(
1278           &cert,
1279           ssl,
1280           issuer_chain,
1281           env);
1282 
1283   issuer_chain.Clear();
1284   if (!maybe_issuer_chain.ToLocal(&issuer_chain))
1285     return MaybeLocal<Value>();
1286 
1287   // Last certificate should be self-signed.
1288   if (X509_check_issued(cert.get(), cert.get()) == X509_V_OK &&
1289       !Set<Object>(env->context(),
1290            issuer_chain,
1291            env->issuercert_string(),
1292            issuer_chain)) {
1293     return MaybeLocal<Value>();
1294   }
1295 
1296   return result;
1297 }
1298 
X509ToObject(Environment * env,X509 * cert,bool names_as_string)1299 MaybeLocal<Object> X509ToObject(
1300     Environment* env,
1301     X509* cert,
1302     bool names_as_string) {
1303   EscapableHandleScope scope(env->isolate());
1304   Local<Context> context = env->context();
1305   Local<Object> info = Object::New(env->isolate());
1306 
1307   BIOPointer bio(BIO_new(BIO_s_mem()));
1308 
1309   if (names_as_string) {
1310     // TODO(tniessen): this branch should not have to exist. It is only here
1311     // because toLegacyObject() does not actually return a legacy object, and
1312     // instead represents subject and issuer as strings.
1313     if (!Set<Value>(context,
1314                     info,
1315                     env->subject_string(),
1316                     GetSubject(env, bio, cert)) ||
1317         !Set<Value>(context,
1318                     info,
1319                     env->issuer_string(),
1320                     GetIssuerString(env, bio, cert))) {
1321       return MaybeLocal<Object>();
1322     }
1323   } else {
1324     if (!Set<Value>(context,
1325                     info,
1326                     env->subject_string(),
1327                     GetX509NameObject<X509_get_subject_name>(env, cert)) ||
1328         !Set<Value>(context,
1329                     info,
1330                     env->issuer_string(),
1331                     GetX509NameObject<X509_get_issuer_name>(env, cert))) {
1332       return MaybeLocal<Object>();
1333     }
1334   }
1335 
1336   if (!Set<Value>(context,
1337                   info,
1338                   env->subjectaltname_string(),
1339                   GetSubjectAltNameString(env, bio, cert)) ||
1340       !Set<Value>(context,
1341                   info,
1342                   env->infoaccess_string(),
1343                   GetInfoAccessString(env, bio, cert))) {
1344     return MaybeLocal<Object>();
1345   }
1346 
1347   EVPKeyPointer pkey(X509_get_pubkey(cert));
1348   RSAPointer rsa;
1349   ECPointer ec;
1350   if (pkey) {
1351     switch (EVP_PKEY_id(pkey.get())) {
1352       case EVP_PKEY_RSA:
1353         rsa.reset(EVP_PKEY_get1_RSA(pkey.get()));
1354         break;
1355       case EVP_PKEY_EC:
1356         ec.reset(EVP_PKEY_get1_EC_KEY(pkey.get()));
1357         break;
1358     }
1359   }
1360 
1361   if (rsa) {
1362     const BIGNUM* n;
1363     const BIGNUM* e;
1364     RSA_get0_key(rsa.get(), &n, &e, nullptr);
1365     if (!Set<Value>(context,
1366                     info,
1367                     env->modulus_string(),
1368                     GetModulusString(env, bio, n)) ||
1369         !Set<Value>(context, info, env->bits_string(), GetBits(env, n)) ||
1370         !Set<Value>(context,
1371                     info,
1372                     env->exponent_string(),
1373                     GetExponentString(env, bio, e)) ||
1374         !Set<Object>(context,
1375                      info,
1376                      env->pubkey_string(),
1377                      GetPubKey(env, rsa))) {
1378       return MaybeLocal<Object>();
1379     }
1380   } else if (ec) {
1381     const EC_GROUP* group = EC_KEY_get0_group(ec.get());
1382 
1383     if (!Set<Value>(context,
1384                     info,
1385                     env->bits_string(),
1386                     GetECGroup(env, group, ec)) ||
1387         !Set<Value>(context,
1388                     info,
1389                     env->pubkey_string(),
1390                     GetECPubKey(env, group, ec))) {
1391       return MaybeLocal<Object>();
1392     }
1393 
1394     const int nid = EC_GROUP_get_curve_name(group);
1395     if (nid != 0) {
1396       // Curve is well-known, get its OID and NIST nick-name (if it has one).
1397 
1398       if (!Set<Value>(context,
1399                       info,
1400                       env->asn1curve_string(),
1401                       GetCurveASN1Name(env, nid)) ||
1402           !Set<Value>(context,
1403                       info,
1404                       env->nistcurve_string(),
1405                       GetCurveNistName(env, nid))) {
1406         return MaybeLocal<Object>();
1407       }
1408     } else {
1409       // Unnamed curves can be described by their mathematical properties,
1410       // but aren't used much (at all?) with X.509/TLS. Support later if needed.
1411     }
1412   }
1413 
1414   // pkey, rsa, and ec pointers are no longer needed.
1415   pkey.reset();
1416   rsa.reset();
1417   ec.reset();
1418 
1419   if (!Set<Value>(context,
1420                   info,
1421                   env->valid_from_string(),
1422                   GetValidFrom(env, cert, bio)) ||
1423       !Set<Value>(context,
1424                   info,
1425                   env->valid_to_string(),
1426                   GetValidTo(env, cert, bio))) {
1427     return MaybeLocal<Object>();
1428   }
1429 
1430   // bio is no longer needed
1431   bio.reset();
1432 
1433   if (!Set<Value>(context,
1434                   info,
1435                   env->fingerprint_string(),
1436                   GetFingerprintDigest(env, EVP_sha1(), cert)) ||
1437       !Set<Value>(context,
1438                   info,
1439                   env->fingerprint256_string(),
1440                   GetFingerprintDigest(env, EVP_sha256(), cert)) ||
1441       !Set<Value>(context,
1442                   info,
1443                   env->ext_key_usage_string(),
1444                   GetKeyUsage(env, cert)) ||
1445       !Set<Value>(context,
1446                   info,
1447                   env->serial_number_string(),
1448                   GetSerialNumber(env, cert)) ||
1449       !Set<Object>(context,
1450                    info,
1451                    env->raw_string(),
1452                    GetRawDERCertificate(env, cert))) {
1453     return MaybeLocal<Object>();
1454   }
1455 
1456   return scope.Escape(info);
1457 }
1458 
1459 }  // namespace crypto
1460 }  // namespace node
1461