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