GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: crypto/crypto_common.cc Lines: 380 564 67.4 %
Date: 2021-10-01 04:12:33 Branches: 174 369 47.2 %

Line Branch Exec Source
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 "crypto/crypto_common.h"
7
#include "node.h"
8
#include "node_internals.h"
9
#include "node_url.h"
10
#include "string_bytes.h"
11
#include "memory_tracker-inl.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::ArrayBuffer;
30
using v8::ArrayBufferView;
31
using v8::BackingStore;
32
using v8::Context;
33
using v8::EscapableHandleScope;
34
using v8::Integer;
35
using v8::Local;
36
using v8::MaybeLocal;
37
using v8::NewStringType;
38
using v8::Object;
39
using v8::String;
40
using v8::Undefined;
41
using v8::Value;
42
43
namespace crypto {
44
static constexpr int X509_NAME_FLAGS =
45
    ASN1_STRFLGS_ESC_CTRL |
46
    ASN1_STRFLGS_UTF8_CONVERT |
47
    XN_FLAG_SEP_MULTILINE |
48
    XN_FLAG_FN_SN;
49
50
838
int SSL_CTX_get_issuer(SSL_CTX* ctx, X509* cert, X509** issuer) {
51
838
  X509_STORE* store = SSL_CTX_get_cert_store(ctx);
52
  DeleteFnPtr<X509_STORE_CTX, X509_STORE_CTX_free> store_ctx(
53
838
      X509_STORE_CTX_new());
54
1676
  return store_ctx.get() != nullptr &&
55

1676
         X509_STORE_CTX_init(store_ctx.get(), store, nullptr, nullptr) == 1 &&
56
1676
         X509_STORE_CTX_get1_issuer(issuer, store_ctx.get(), cert) == 1;
57
}
58
59
void LogSecret(
60
    const SSLPointer& ssl,
61
    const char* name,
62
    const unsigned char* secret,
63
    size_t secretlen) {
64
  auto keylog_cb = SSL_CTX_get_keylog_callback(SSL_get_SSL_CTX(ssl.get()));
65
  unsigned char crandom[32];
66
67
  if (keylog_cb == nullptr ||
68
      SSL_get_client_random(ssl.get(), crandom, 32) != 32) {
69
    return;
70
  }
71
72
  std::string line = name;
73
  line += " " + StringBytes::hex_encode(
74
      reinterpret_cast<const char*>(crandom), 32);
75
  line += " " + StringBytes::hex_encode(
76
      reinterpret_cast<const char*>(secret), secretlen);
77
  keylog_cb(ssl.get(), line.c_str());
78
}
79
80
bool SetALPN(const SSLPointer& ssl, const std::string& alpn) {
81
  return SSL_set_alpn_protos(
82
      ssl.get(),
83
      reinterpret_cast<const uint8_t*>(alpn.c_str()),
84
      alpn.length()) == 0;
85
}
86
87
39
bool SetALPN(const SSLPointer& ssl, Local<Value> alpn) {
88
39
  if (!alpn->IsArrayBufferView())
89
    return false;
90
39
  ArrayBufferViewContents<unsigned char> protos(alpn.As<ArrayBufferView>());
91
39
  return SSL_set_alpn_protos(ssl.get(), protos.data(), protos.length()) == 0;
92
}
93
94
4
MaybeLocal<Value> GetSSLOCSPResponse(
95
    Environment* env,
96
    SSL* ssl,
97
    Local<Value> default_value) {
98
  const unsigned char* resp;
99
4
  int len = SSL_get_tlsext_status_ocsp_resp(ssl, &resp);
100
4
  if (resp == nullptr)
101
2
    return default_value;
102
103
  Local<Value> ret;
104
  MaybeLocal<Object> maybe_buffer =
105
2
      Buffer::Copy(env, reinterpret_cast<const char*>(resp), len);
106
107
2
  if (!maybe_buffer.ToLocal(&ret))
108
    return MaybeLocal<Value>();
109
110
2
  return ret;
111
}
112
113
bool SetTLSSession(
114
    const SSLPointer& ssl,
115
    const unsigned char* buf,
116
    size_t length) {
117
  SSLSessionPointer s(d2i_SSL_SESSION(nullptr, &buf, length));
118
  return s == nullptr ? false : SetTLSSession(ssl, s);
119
}
120
121
96
bool SetTLSSession(
122
    const SSLPointer& ssl,
123
    const SSLSessionPointer& session) {
124

96
  return session != nullptr && SSL_set_session(ssl.get(), session.get()) == 1;
125
}
126
127
96
SSLSessionPointer GetTLSSession(Local<Value> val) {
128
96
  if (!val->IsArrayBufferView())
129
    return SSLSessionPointer();
130
96
  ArrayBufferViewContents<unsigned char> sbuf(val.As<ArrayBufferView>());
131
96
  return GetTLSSession(sbuf.data(), sbuf.length());
132
}
133
134
96
SSLSessionPointer GetTLSSession(const unsigned char* buf, size_t length) {
135
96
  return SSLSessionPointer(d2i_SSL_SESSION(nullptr, &buf, length));
136
}
137
138
std::unordered_multimap<std::string, std::string>
139
GetCertificateAltNames(X509* cert) {
140
  std::unordered_multimap<std::string, std::string> map;
141
  BIOPointer bio(BIO_new(BIO_s_mem()));
142
  BUF_MEM* mem;
143
  int idx = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1);
144
  if (idx < 0)  // There is no subject alt name
145
    return map;
146
147
  X509_EXTENSION* ext = X509_get_ext(cert, idx);
148
  CHECK_NOT_NULL(ext);
149
  const X509V3_EXT_METHOD* method = X509V3_EXT_get(ext);
150
  CHECK_EQ(method, X509V3_EXT_get_nid(NID_subject_alt_name));
151
152
  GENERAL_NAMES* names = static_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(ext));
153
  if (names == nullptr)  // There are no names
154
    return map;
155
156
  for (int i = 0; i < sk_GENERAL_NAME_num(names); i++) {
157
    USE(BIO_reset(bio.get()));
158
    GENERAL_NAME* gen = sk_GENERAL_NAME_value(names, i);
159
    if (gen->type == GEN_DNS) {
160
      ASN1_IA5STRING* name = gen->d.dNSName;
161
      BIO_write(bio.get(), name->data, name->length);
162
      BIO_get_mem_ptr(bio.get(), &mem);
163
      map.emplace("dns", std::string(mem->data, mem->length));
164
    } else {
165
      STACK_OF(CONF_VALUE)* nval = i2v_GENERAL_NAME(
166
          const_cast<X509V3_EXT_METHOD*>(method), gen, nullptr);
167
      if (nval == nullptr)
168
        continue;
169
      X509V3_EXT_val_prn(bio.get(), nval, 0, 0);
170
      sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
171
      BIO_get_mem_ptr(bio.get(), &mem);
172
      std::string value(mem->data, mem->length);
173
      if (value.compare(0, 11, "IP Address:") == 0) {
174
        map.emplace("ip", value.substr(11));
175
      } else if (value.compare(0, 4, "URI:") == 0) {
176
        url::URL url(value.substr(4));
177
        if (url.flags() & url::URL_FLAGS_CANNOT_BE_BASE ||
178
            url.flags() & url::URL_FLAGS_FAILED) {
179
          continue;  // Skip this one
180
        }
181
        map.emplace("uri", url.host());
182
      }
183
    }
184
  }
185
  sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
186
  return map;
187
}
188
189
std::string GetCertificateCN(X509* cert) {
190
  X509_NAME* subject = X509_get_subject_name(cert);
191
  if (subject != nullptr) {
192
    int nid = OBJ_txt2nid("CN");
193
    int idx = X509_NAME_get_index_by_NID(subject, nid, -1);
194
    if (idx != -1) {
195
      X509_NAME_ENTRY* cn = X509_NAME_get_entry(subject, idx);
196
      if (cn != nullptr) {
197
        ASN1_STRING* cn_str = X509_NAME_ENTRY_get_data(cn);
198
        if (cn_str != nullptr) {
199
          return std::string(reinterpret_cast<const char*>(
200
              ASN1_STRING_get0_data(cn_str)));
201
        }
202
      }
203
    }
204
  }
205
  return std::string();
206
}
207
208
894
long VerifyPeerCertificate(  // NOLINT(runtime/int)
209
    const SSLPointer& ssl,
210
    long def) {  // NOLINT(runtime/int)
211
894
  long err = def;  // NOLINT(runtime/int)
212
894
  if (X509* peer_cert = SSL_get_peer_certificate(ssl.get())) {
213
886
    X509_free(peer_cert);
214
886
    err = SSL_get_verify_result(ssl.get());
215
  } else {
216
8
    const SSL_CIPHER* curr_cipher = SSL_get_current_cipher(ssl.get());
217
8
    const SSL_SESSION* sess = SSL_get_session(ssl.get());
218
    // Allow no-cert for PSK authentication in TLS1.2 and lower.
219
    // In TLS1.3 check that session was reused because TLS1.3 PSK
220
    // looks like session resumption.
221

20
    if (SSL_CIPHER_get_auth_nid(curr_cipher) == NID_auth_psk ||
222
12
        (SSL_SESSION_get_protocol_version(sess) == TLS1_3_VERSION &&
223
6
         SSL_session_reused(ssl.get()))) {
224
7
      return X509_V_OK;
225
    }
226
  }
227
887
  return err;
228
}
229
230
12
int UseSNIContext(const SSLPointer& ssl, BaseObjectPtr<SecureContext> context) {
231
12
  SSL_CTX* ctx = context->ctx_.get();
232
12
  X509* x509 = SSL_CTX_get0_certificate(ctx);
233
12
  EVP_PKEY* pkey = SSL_CTX_get0_privatekey(ctx);
234
  STACK_OF(X509)* chain;
235
236
12
  int err = SSL_CTX_get0_chain_certs(ctx, &chain);
237
12
  if (err == 1) err = SSL_use_certificate(ssl.get(), x509);
238
12
  if (err == 1) err = SSL_use_PrivateKey(ssl.get(), pkey);
239

12
  if (err == 1 && chain != nullptr) err = SSL_set1_chain(ssl.get(), chain);
240
12
  return err;
241
}
242
243
const char* GetClientHelloALPN(const SSLPointer& ssl) {
244
  const unsigned char* buf;
245
  size_t len;
246
  size_t rem;
247
248
  if (!SSL_client_hello_get0_ext(
249
          ssl.get(),
250
          TLSEXT_TYPE_application_layer_protocol_negotiation,
251
          &buf,
252
          &rem) ||
253
      rem < 2) {
254
    return nullptr;
255
  }
256
257
  len = (buf[0] << 8) | buf[1];
258
  if (len + 2 != rem) return nullptr;
259
  return reinterpret_cast<const char*>(buf + 3);
260
}
261
262
const char* GetClientHelloServerName(const SSLPointer& ssl) {
263
  const unsigned char* buf;
264
  size_t len;
265
  size_t rem;
266
267
  if (!SSL_client_hello_get0_ext(
268
          ssl.get(),
269
          TLSEXT_TYPE_server_name,
270
          &buf,
271
          &rem) || rem <= 2) {
272
    return nullptr;
273
  }
274
275
  len = (*buf << 8) | *(buf + 1);
276
  if (len + 2 != rem)
277
    return nullptr;
278
  rem = len;
279
280
  if (rem == 0 || *(buf + 2) != TLSEXT_NAMETYPE_host_name) return nullptr;
281
  rem--;
282
  if (rem <= 2)
283
    return nullptr;
284
  len = (*(buf + 3) << 8) | *(buf + 4);
285
  if (len + 2 > rem)
286
    return nullptr;
287
  return reinterpret_cast<const char*>(buf + 5);
288
}
289
290
25
const char* GetServerName(SSL* ssl) {
291
25
  return SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
292
}
293
294
bool SetGroups(SecureContext* sc, const char* groups) {
295
  return SSL_CTX_set1_groups_list(**sc, groups) == 1;
296
}
297
298
434
const char* X509ErrorCode(long err) {  // NOLINT(runtime/int)
299
434
  const char* code = "UNSPECIFIED";
300
#define CASE_X509_ERR(CODE) case X509_V_ERR_##CODE: code = #CODE; break;
301







434
  switch (err) {
302
    // if you modify anything in here, *please* update the respective section in
303
    // doc/api/tls.md as well
304
1
    CASE_X509_ERR(UNABLE_TO_GET_ISSUER_CERT)
305
1
    CASE_X509_ERR(UNABLE_TO_GET_CRL)
306
    CASE_X509_ERR(UNABLE_TO_DECRYPT_CERT_SIGNATURE)
307
    CASE_X509_ERR(UNABLE_TO_DECRYPT_CRL_SIGNATURE)
308
    CASE_X509_ERR(UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY)
309
    CASE_X509_ERR(CERT_SIGNATURE_FAILURE)
310
    CASE_X509_ERR(CRL_SIGNATURE_FAILURE)
311
    CASE_X509_ERR(CERT_NOT_YET_VALID)
312
    CASE_X509_ERR(CERT_HAS_EXPIRED)
313
    CASE_X509_ERR(CRL_NOT_YET_VALID)
314
    CASE_X509_ERR(CRL_HAS_EXPIRED)
315
    CASE_X509_ERR(ERROR_IN_CERT_NOT_BEFORE_FIELD)
316
    CASE_X509_ERR(ERROR_IN_CERT_NOT_AFTER_FIELD)
317
    CASE_X509_ERR(ERROR_IN_CRL_LAST_UPDATE_FIELD)
318
    CASE_X509_ERR(ERROR_IN_CRL_NEXT_UPDATE_FIELD)
319
    CASE_X509_ERR(OUT_OF_MEM)
320
240
    CASE_X509_ERR(DEPTH_ZERO_SELF_SIGNED_CERT)
321
18
    CASE_X509_ERR(SELF_SIGNED_CERT_IN_CHAIN)
322
4
    CASE_X509_ERR(UNABLE_TO_GET_ISSUER_CERT_LOCALLY)
323
168
    CASE_X509_ERR(UNABLE_TO_VERIFY_LEAF_SIGNATURE)
324
    CASE_X509_ERR(CERT_CHAIN_TOO_LONG)
325
1
    CASE_X509_ERR(CERT_REVOKED)
326
    CASE_X509_ERR(INVALID_CA)
327
    CASE_X509_ERR(PATH_LENGTH_EXCEEDED)
328
1
    CASE_X509_ERR(INVALID_PURPOSE)
329
    CASE_X509_ERR(CERT_UNTRUSTED)
330
    CASE_X509_ERR(CERT_REJECTED)
331
    CASE_X509_ERR(HOSTNAME_MISMATCH)
332
  }
333
#undef CASE_X509_ERR
334
434
  return code;
335
}
336
337
MaybeLocal<Value> GetValidationErrorReason(Environment* env, int err) {
338
  if (err == 0)
339
    return Undefined(env->isolate());
340
  const char* reason = X509_verify_cert_error_string(err);
341
  return OneByteString(env->isolate(), reason);
342
}
343
344
MaybeLocal<Value> GetValidationErrorCode(Environment* env, int err) {
345
  if (err == 0)
346
    return Undefined(env->isolate());
347
  return OneByteString(env->isolate(), X509ErrorCode(err));
348
}
349
350
12
MaybeLocal<Value> GetCert(Environment* env, const SSLPointer& ssl) {
351
12
  ClearErrorOnReturn clear_error_on_return;
352
12
  X509* cert = SSL_get_certificate(ssl.get());
353
12
  if (cert == nullptr)
354
2
    return Undefined(env->isolate());
355
356
11
  MaybeLocal<Object> maybe_cert = X509ToObject(env, cert);
357
11
  return maybe_cert.FromMaybe<Value>(Local<Value>());
358
}
359
360
6939
Local<Value> ToV8Value(Environment* env, const BIOPointer& bio) {
361
  BUF_MEM* mem;
362
6939
  BIO_get_mem_ptr(bio.get(), &mem);
363
  MaybeLocal<String> ret =
364
      String::NewFromUtf8(
365
          env->isolate(),
366
6939
          mem->data,
367
          NewStringType::kNormal,
368
6939
          mem->length);
369
6939
  USE(BIO_reset(bio.get()));
370
6939
  return ret.FromMaybe(Local<Value>());
371
}
372
373
namespace {
374
template <typename T>
375
41864
bool Set(
376
    Local<Context> context,
377
    Local<Object> target,
378
    Local<Value> name,
379
    MaybeLocal<T> maybe_value) {
380
  Local<Value> value;
381
41864
  if (!maybe_value.ToLocal(&value))
382
    return false;
383
384
  // Undefined is ignored, but still considered successful
385
83728
  if (value->IsUndefined())
386
6754
    return true;
387
388
70220
  return !target->Set(context, name, value).IsNothing();
389
}
390
391
159
MaybeLocal<Value> GetCipherValue(Environment* env,
392
    const SSL_CIPHER* cipher,
393
    const char* (*getstr)(const SSL_CIPHER* cipher)) {
394
159
  if (cipher == nullptr)
395
    return Undefined(env->isolate());
396
397
318
  return OneByteString(env->isolate(), getstr(cipher));
398
}
399
400
53
MaybeLocal<Value> GetCipherName(Environment* env, const SSL_CIPHER* cipher) {
401
53
  return GetCipherValue(env, cipher, SSL_CIPHER_get_name);
402
}
403
404
53
MaybeLocal<Value> GetCipherStandardName(
405
    Environment* env,
406
    const SSL_CIPHER* cipher) {
407
53
  return GetCipherValue(env, cipher, SSL_CIPHER_standard_name);
408
}
409
410
53
MaybeLocal<Value> GetCipherVersion(Environment* env, const SSL_CIPHER* cipher) {
411
53
  return GetCipherValue(env, cipher, SSL_CIPHER_get_version);
412
}
413
414
395
StackOfX509 CloneSSLCerts(X509Pointer&& cert,
415
                          const STACK_OF(X509)* const ssl_certs) {
416
790
  StackOfX509 peer_certs(sk_X509_new(nullptr));
417
395
  if (cert)
418
    sk_X509_push(peer_certs.get(), cert.release());
419
1128
  for (int i = 0; i < sk_X509_num(ssl_certs); i++) {
420
733
    X509Pointer cert(X509_dup(sk_X509_value(ssl_certs, i)));
421

733
    if (!cert || !sk_X509_push(peer_certs.get(), cert.get()))
422
      return StackOfX509();
423
    // `cert` is now managed by the stack.
424
733
    cert.release();
425
  }
426
395
  return peer_certs;
427
}
428
429
395
MaybeLocal<Object> AddIssuerChainToObject(
430
    X509Pointer* cert,
431
    Local<Object> object,
432
    StackOfX509&& peer_certs,
433
    Environment* const env) {
434
395
  Local<Context> context = env->isolate()->GetCurrentContext();
435
395
  cert->reset(sk_X509_delete(peer_certs.get(), 0));
436
  for (;;) {
437
    int i;
438
399
    for (i = 0; i < sk_X509_num(peer_certs.get()); i++) {
439
338
      X509* ca = sk_X509_value(peer_certs.get(), i);
440
338
      if (X509_check_issued(ca, cert->get()) != X509_V_OK)
441
2
        continue;
442
443
      Local<Object> ca_info;
444
336
      MaybeLocal<Object> maybe_ca_info = X509ToObject(env, ca);
445
336
      if (!maybe_ca_info.ToLocal(&ca_info))
446
        return MaybeLocal<Object>();
447
448
672
      if (!Set<Object>(context, object, env->issuercert_string(), ca_info))
449
        return MaybeLocal<Object>();
450
336
      object = ca_info;
451
452
      // NOTE: Intentionally freeing cert that is not used anymore.
453
      // Delete cert and continue aggregating issuers.
454
336
      cert->reset(sk_X509_delete(peer_certs.get(), i));
455
336
      break;
456
    }
457
458
    // Issuer not found, break out of the loop.
459
397
    if (i == sk_X509_num(peer_certs.get()))
460
395
      break;
461
2
  }
462
395
  return MaybeLocal<Object>(object);
463
}
464
465
395
MaybeLocal<Object> GetLastIssuedCert(
466
    X509Pointer* cert,
467
    const SSLPointer& ssl,
468
    Local<Object> issuer_chain,
469
    Environment* const env) {
470
395
  Local<Context> context = env->isolate()->GetCurrentContext();
471
761
  while (X509_check_issued(cert->get(), cert->get()) != X509_V_OK) {
472
    X509* ca;
473
367
    if (SSL_CTX_get_issuer(SSL_get_SSL_CTX(ssl.get()), cert->get(), &ca) <= 0)
474
1
      break;
475
476
    Local<Object> ca_info;
477
367
    MaybeLocal<Object> maybe_ca_info = X509ToObject(env, ca);
478
367
    if (!maybe_ca_info.ToLocal(&ca_info))
479
      return MaybeLocal<Object>();
480
481
734
    if (!Set<Object>(context, issuer_chain, env->issuercert_string(), ca_info))
482
      return MaybeLocal<Object>();
483
367
    issuer_chain = ca_info;
484
485
    // Take the value of cert->get() before the call to cert->reset()
486
    // in order to compare it to ca after and provide a way to exit this loop
487
    // in case it gets stuck.
488
367
    X509* value_before_reset = cert->get();
489
490
    // Delete previous cert and continue aggregating issuers.
491
367
    cert->reset(ca);
492
493
367
    if (value_before_reset == ca)
494
1
      break;
495
  }
496
395
  return MaybeLocal<Object>(issuer_chain);
497
}
498
499
2310
void AddFingerprintDigest(
500
    const unsigned char* md,
501
    unsigned int md_size,
502
    char (*fingerprint)[3 * EVP_MAX_MD_SIZE + 1]) {
503
  unsigned int i;
504
2310
  const char hex[] = "0123456789ABCDEF";
505
506
62370
  for (i = 0; i < md_size; i++) {
507
60060
    (*fingerprint)[3*i] = hex[(md[i] & 0xf0) >> 4];
508
60060
    (*fingerprint)[(3*i)+1] = hex[(md[i] & 0x0f)];
509
60060
    (*fingerprint)[(3*i)+2] = ':';
510
  }
511
512
2310
  if (md_size > 0) {
513
2310
    (*fingerprint)[(3*(md_size-1))+2] = '\0';
514
  } else {
515
    (*fingerprint)[0] = '\0';
516
  }
517
2310
}
518
519
33
MaybeLocal<Value> GetCurveASN1Name(Environment* env, const int nid) {
520
33
  const char* nist = OBJ_nid2sn(nid);
521
  return nist != nullptr ?
522
      MaybeLocal<Value>(OneByteString(env->isolate(), nist)) :
523
66
      MaybeLocal<Value>(Undefined(env->isolate()));
524
}
525
526
33
MaybeLocal<Value> GetCurveNistName(Environment* env, const int nid) {
527
33
  const char* nist = EC_curve_nid2nist(nid);
528
  return nist != nullptr ?
529
      MaybeLocal<Value>(OneByteString(env->isolate(), nist)) :
530
66
      MaybeLocal<Value>(Undefined(env->isolate()));
531
}
532
533
33
MaybeLocal<Value> GetECPubKey(
534
    Environment* env,
535
    const EC_GROUP* group,
536
    const ECPointer& ec) {
537
33
  const EC_POINT* pubkey = EC_KEY_get0_public_key(ec.get());
538
33
  if (pubkey == nullptr)
539
    return Undefined(env->isolate());
540
541
33
  return ECPointToBuffer(
542
      env,
543
      group,
544
      pubkey,
545
33
      EC_KEY_get_conv_form(ec.get()),
546
66
      nullptr).FromMaybe(Local<Object>());
547
}
548
549
33
MaybeLocal<Value> GetECGroup(
550
    Environment* env,
551
    const EC_GROUP* group,
552
    const ECPointer& ec) {
553
33
  if (group == nullptr)
554
    return Undefined(env->isolate());
555
556
33
  int bits = EC_GROUP_order_bits(group);
557
33
  if (bits <= 0)
558
    return Undefined(env->isolate());
559
560
66
  return Integer::New(env->isolate(), bits);
561
}
562
563
1121
MaybeLocal<Object> GetPubKey(Environment* env, const RSAPointer& rsa) {
564
1121
  int size = i2d_RSA_PUBKEY(rsa.get(), nullptr);
565
1121
  CHECK_GE(size, 0);
566
567
2242
  std::unique_ptr<BackingStore> bs;
568
  {
569
1121
    NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
570
1121
    bs = ArrayBuffer::NewBackingStore(env->isolate(), size);
571
  }
572
573
1121
  unsigned char* serialized = reinterpret_cast<unsigned char*>(bs->Data());
574
1121
  CHECK_GE(i2d_RSA_PUBKEY(rsa.get(), &serialized), 0);
575
576
1121
  Local<ArrayBuffer> ab = ArrayBuffer::New(env->isolate(), std::move(bs));
577
2242
  return Buffer::New(env, ab, 0, ab->ByteLength()).FromMaybe(Local<Object>());
578
}
579
580
1121
MaybeLocal<Value> GetExponentString(
581
    Environment* env,
582
    const BIOPointer& bio,
583
    const BIGNUM* e) {
584
1121
  uint64_t exponent_word = static_cast<uint64_t>(BN_get_word(e));
585
1121
  uint32_t lo = static_cast<uint32_t>(exponent_word);
586
1121
  uint32_t hi = static_cast<uint32_t>(exponent_word >> 32);
587
1121
  if (hi == 0)
588
1121
    BIO_printf(bio.get(), "0x%x", lo);
589
  else
590
    BIO_printf(bio.get(), "0x%x%08x", hi, lo);
591
592
2242
  return ToV8Value(env, bio);
593
}
594
595
1121
Local<Value> GetBits(Environment* env, const BIGNUM* n) {
596
2242
  return Integer::New(env->isolate(), BN_num_bits(n));
597
}
598
599
1121
MaybeLocal<Value> GetModulusString(
600
    Environment* env,
601
    const BIOPointer& bio,
602
    const BIGNUM* n) {
603
1121
  BN_print(bio.get(), n);
604
2242
  return ToV8Value(env, bio);
605
}
606
}  // namespace
607
608
1156
MaybeLocal<Object> GetRawDERCertificate(Environment* env, X509* cert) {
609
1156
  int size = i2d_X509(cert, nullptr);
610
611
2312
  std::unique_ptr<BackingStore> bs;
612
  {
613
1156
    NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
614
1156
    bs = ArrayBuffer::NewBackingStore(env->isolate(), size);
615
  }
616
617
1156
  unsigned char* serialized = reinterpret_cast<unsigned char*>(bs->Data());
618
1156
  CHECK_GE(i2d_X509(cert, &serialized), 0);
619
620
1156
  Local<ArrayBuffer> ab = ArrayBuffer::New(env->isolate(), std::move(bs));
621
2312
  return Buffer::New(env, ab, 0, ab->ByteLength()).FromMaybe(Local<Object>());
622
}
623
624
1157
MaybeLocal<Value> GetSerialNumber(Environment* env, X509* cert) {
625
1157
  if (ASN1_INTEGER* serial_number = X509_get_serialNumber(cert)) {
626
1157
    BignumPointer bn(ASN1_INTEGER_to_BN(serial_number, nullptr));
627
1157
    if (bn) {
628
1157
      char* data = BN_bn2hex(bn.get());
629
1157
      ByteSource buf = ByteSource::Allocated(data, strlen(data));
630
1157
      if (buf)
631
2314
        return OneByteString(env->isolate(), buf.get());
632
    }
633
  }
634
635
  return Undefined(env->isolate());
636
}
637
638
1155
MaybeLocal<Value> GetKeyUsage(Environment* env, X509* cert) {
639
  StackOfASN1 eku(static_cast<STACK_OF(ASN1_OBJECT)*>(
640
2310
      X509_get_ext_d2i(cert, NID_ext_key_usage, nullptr, nullptr)));
641
1155
  if (eku) {
642
9
    const int count = sk_ASN1_OBJECT_num(eku.get());
643
9
    MaybeStackBuffer<Local<Value>, 16> ext_key_usage(count);
644
    char buf[256];
645
646
9
    int j = 0;
647
20
    for (int i = 0; i < count; i++) {
648
11
      if (OBJ_obj2txt(buf,
649
                      sizeof(buf),
650
22
                      sk_ASN1_OBJECT_value(eku.get(), i), 1) >= 0) {
651
22
        ext_key_usage[j++] = OneByteString(env->isolate(), buf);
652
      }
653
    }
654
655
18
    return Array::New(env->isolate(), ext_key_usage.out(), count);
656
  }
657
658
2292
  return Undefined(env->isolate());
659
}
660
661
2310
MaybeLocal<Value> GetFingerprintDigest(
662
    Environment* env,
663
    const EVP_MD* method,
664
    X509* cert) {
665
  unsigned char md[EVP_MAX_MD_SIZE];
666
  unsigned int md_size;
667
  char fingerprint[EVP_MAX_MD_SIZE * 3 + 1];
668
669
2310
  if (X509_digest(cert, method, md, &md_size)) {
670
2310
    AddFingerprintDigest(md, md_size, &fingerprint);
671
4620
    return OneByteString(env->isolate(), fingerprint);
672
  }
673
  return Undefined(env->isolate());
674
}
675
676
1155
MaybeLocal<Value> GetValidTo(
677
    Environment* env,
678
    X509* cert,
679
    const BIOPointer& bio) {
680
1155
  ASN1_TIME_print(bio.get(), X509_get0_notAfter(cert));
681
2310
  return ToV8Value(env, bio);
682
}
683
684
1155
MaybeLocal<Value> GetValidFrom(
685
    Environment* env,
686
    X509* cert,
687
    const BIOPointer& bio) {
688
1155
  ASN1_TIME_print(bio.get(), X509_get0_notBefore(cert));
689
2310
  return ToV8Value(env, bio);
690
}
691
692
77
bool SafeX509ExtPrint(const BIOPointer& out, X509_EXTENSION* ext) {
693
77
  const X509V3_EXT_METHOD* method = X509V3_EXT_get(ext);
694
695
77
  if (method != X509V3_EXT_get_nid(NID_subject_alt_name))
696
70
    return false;
697
698
7
  GENERAL_NAMES* names = static_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(ext));
699
7
  if (names == nullptr)
700
1
    return false;
701
702
24
  for (int i = 0; i < sk_GENERAL_NAME_num(names); i++) {
703
18
    GENERAL_NAME* gen = sk_GENERAL_NAME_value(names, i);
704
705
18
    if (i != 0)
706
12
      BIO_write(out.get(), ", ", 2);
707
708
18
    if (gen->type == GEN_DNS) {
709
12
      ASN1_IA5STRING* name = gen->d.dNSName;
710
711
12
      BIO_write(out.get(), "DNS:", 4);
712
12
      BIO_write(out.get(), name->data, name->length);
713
    } else {
714
6
      STACK_OF(CONF_VALUE)* nval = i2v_GENERAL_NAME(
715
          const_cast<X509V3_EXT_METHOD*>(method), gen, nullptr);
716
6
      if (nval == nullptr)
717
        return false;
718
6
      X509V3_EXT_val_prn(out.get(), nval, 0, 0);
719
6
      sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
720
    }
721
  }
722
6
  sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
723
724
6
  return true;
725
}
726
727
1155
MaybeLocal<Value> GetIssuerString(
728
    Environment* env,
729
    const BIOPointer& bio,
730
    X509* cert) {
731
1155
  X509_NAME* issuer_name = X509_get_issuer_name(cert);
732
1155
  if (X509_NAME_print_ex(bio.get(), issuer_name, 0, X509_NAME_FLAGS) <= 0) {
733
    USE(BIO_reset(bio.get()));
734
    return Undefined(env->isolate());
735
  }
736
737
2310
  return ToV8Value(env, bio);
738
}
739
740
1155
MaybeLocal<Value> GetSubject(
741
    Environment* env,
742
    const BIOPointer& bio,
743
    X509* cert) {
744
1155
  if (X509_NAME_print_ex(
745
          bio.get(),
746
1155
          X509_get_subject_name(cert),
747
          0,
748
1155
          X509_NAME_FLAGS) <= 0) {
749
    USE(BIO_reset(bio.get()));
750
    return Undefined(env->isolate());
751
  }
752
753
2310
  return ToV8Value(env, bio);
754
}
755
756
53
MaybeLocal<Value> GetCipherName(Environment* env, const SSLPointer& ssl) {
757
53
  return GetCipherName(env, SSL_get_current_cipher(ssl.get()));
758
}
759
760
53
MaybeLocal<Value> GetCipherStandardName(
761
    Environment* env,
762
    const SSLPointer& ssl) {
763
53
  return GetCipherStandardName(env, SSL_get_current_cipher(ssl.get()));
764
}
765
766
53
MaybeLocal<Value> GetCipherVersion(Environment* env, const SSLPointer& ssl) {
767
53
  return GetCipherVersion(env, SSL_get_current_cipher(ssl.get()));
768
}
769
770
MaybeLocal<Array> GetClientHelloCiphers(
771
    Environment* env,
772
    const SSLPointer& ssl) {
773
  EscapableHandleScope scope(env->isolate());
774
  const unsigned char* buf;
775
  size_t len = SSL_client_hello_get0_ciphers(ssl.get(), &buf);
776
  size_t count = len / 2;
777
  MaybeStackBuffer<Local<Value>, 16> ciphers(count);
778
  int j = 0;
779
  for (size_t n = 0; n < len; n += 2) {
780
    const SSL_CIPHER* cipher = SSL_CIPHER_find(ssl.get(), buf);
781
    buf += 2;
782
    Local<Object> obj = Object::New(env->isolate());
783
    if (!Set(env->context(),
784
             obj,
785
             env->name_string(),
786
             GetCipherName(env, cipher)) ||
787
        !Set(env->context(),
788
             obj,
789
             env->standard_name_string(),
790
             GetCipherStandardName(env, cipher)) ||
791
        !Set(env->context(),
792
             obj,
793
             env->version_string(),
794
             GetCipherVersion(env, cipher))) {
795
      return MaybeLocal<Array>();
796
    }
797
    ciphers[j++] = obj;
798
  }
799
  Local<Array> ret = Array::New(env->isolate(), ciphers.out(), count);
800
  return scope.Escape(ret);
801
}
802
803
804
53
MaybeLocal<Object> GetCipherInfo(Environment* env, const SSLPointer& ssl) {
805
53
  if (SSL_get_current_cipher(ssl.get()) == nullptr)
806
    return MaybeLocal<Object>();
807
53
  EscapableHandleScope scope(env->isolate());
808
53
  Local<Object> info = Object::New(env->isolate());
809
810
106
  if (!Set<Value>(env->context(),
811
                  info,
812
                  env->name_string(),
813
53
                  GetCipherName(env, ssl)) ||
814
106
      !Set<Value>(env->context(),
815
                  info,
816
                  env->standard_name_string(),
817
106
                  GetCipherStandardName(env, ssl)) ||
818

159
      !Set<Value>(env->context(),
819
                  info,
820
                  env->version_string(),
821
                  GetCipherVersion(env, ssl))) {
822
    return MaybeLocal<Object>();
823
  }
824
825
53
  return scope.Escape(info);
826
}
827
828
821
MaybeLocal<Object> GetEphemeralKey(Environment* env, const SSLPointer& ssl) {
829
821
  CHECK_EQ(SSL_is_server(ssl.get()), 0);
830
  EVP_PKEY* raw_key;
831
832
821
  EscapableHandleScope scope(env->isolate());
833
821
  Local<Object> info = Object::New(env->isolate());
834
821
  if (!SSL_get_server_tmp_key(ssl.get(), &raw_key))
835
30
    return scope.Escape(info);
836
837
791
  Local<Context> context = env->context();
838
1582
  crypto::EVPKeyPointer key(raw_key);
839
840
791
  int kid = EVP_PKEY_id(key.get());
841
791
  int bits = EVP_PKEY_bits(key.get());
842
791
  switch (kid) {
843
7
    case EVP_PKEY_DH:
844
28
      if (!Set<String>(context, info, env->type_string(), env->dh_string()) ||
845

28
          !Set<Integer>(context,
846
               info,
847
               env->size_string(),
848
               Integer::New(env->isolate(), bits))) {
849
        return MaybeLocal<Object>();
850
      }
851
7
      break;
852
784
    case EVP_PKEY_EC:
853
    case EVP_PKEY_X25519:
854
    case EVP_PKEY_X448:
855
      {
856
        const char* curve_name;
857
784
        if (kid == EVP_PKEY_EC) {
858
10
          ECKeyPointer ec(EVP_PKEY_get1_EC_KEY(key.get()));
859
5
          int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec.get()));
860
5
          curve_name = OBJ_nid2sn(nid);
861
        } else {
862
779
          curve_name = OBJ_nid2sn(kid);
863
        }
864
2352
        if (!Set<String>(context,
865
                         info,
866
                         env->type_string(),
867
784
                         env->ecdh_string()) ||
868
2352
            !Set<String>(context,
869
                info,
870
                env->name_string(),
871
1568
                OneByteString(env->isolate(), curve_name)) ||
872

3136
            !Set<Integer>(context,
873
                 info,
874
                 env->size_string(),
875
                 Integer::New(env->isolate(), bits))) {
876
          return MaybeLocal<Object>();
877
784
        }
878
      }
879
784
      break;
880
  }
881
882
791
  return scope.Escape(info);
883
}
884
885
59
MaybeLocal<Object> ECPointToBuffer(Environment* env,
886
                                   const EC_GROUP* group,
887
                                   const EC_POINT* point,
888
                                   point_conversion_form_t form,
889
                                   const char** error) {
890
59
  size_t len = EC_POINT_point2oct(group, point, form, nullptr, 0, nullptr);
891
59
  if (len == 0) {
892
    if (error != nullptr) *error = "Failed to get public key length";
893
    return MaybeLocal<Object>();
894
  }
895
896
59
  std::unique_ptr<BackingStore> bs;
897
  {
898
59
    NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data());
899
59
    bs = ArrayBuffer::NewBackingStore(env->isolate(), len);
900
  }
901
902
118
  len = EC_POINT_point2oct(group,
903
                           point,
904
                           form,
905
59
                           reinterpret_cast<unsigned char*>(bs->Data()),
906
                           bs->ByteLength(),
907
                           nullptr);
908
59
  if (len == 0) {
909
    if (error != nullptr) *error = "Failed to get public key";
910
    return MaybeLocal<Object>();
911
  }
912
913
59
  Local<ArrayBuffer> ab = ArrayBuffer::New(env->isolate(), std::move(bs));
914
118
  return Buffer::New(env, ab, 0, ab->ByteLength()).FromMaybe(Local<Object>());
915
}
916
917
444
MaybeLocal<Value> GetPeerCert(
918
    Environment* env,
919
    const SSLPointer& ssl,
920
    bool abbreviated,
921
    bool is_server) {
922
444
  ClearErrorOnReturn clear_error_on_return;
923
  Local<Object> result;
924
  MaybeLocal<Object> maybe_cert;
925
926
  // NOTE: This is because of the odd OpenSSL behavior. On client `cert_chain`
927
  // contains the `peer_certificate`, but on server it doesn't.
928
888
  X509Pointer cert(is_server ? SSL_get_peer_certificate(ssl.get()) : nullptr);
929
444
  STACK_OF(X509)* ssl_certs = SSL_get_peer_cert_chain(ssl.get());
930


444
  if (!cert && (ssl_certs == nullptr || sk_X509_num(ssl_certs) == 0))
931
10
    return Undefined(env->isolate());
932
933
  // Short result requested.
934
439
  if (abbreviated) {
935
    maybe_cert =
936
44
        X509ToObject(env, cert ? cert.get() : sk_X509_value(ssl_certs, 0));
937
88
    return maybe_cert.ToLocal(&result) ? result : MaybeLocal<Value>();
938
  }
939
940
790
  StackOfX509 peer_certs = CloneSSLCerts(std::move(cert), ssl_certs);
941
395
  if (peer_certs == nullptr)
942
    return Undefined(env->isolate());
943
944
  // First and main certificate.
945
790
  X509Pointer first_cert(sk_X509_value(peer_certs.get(), 0));
946
395
  CHECK(first_cert);
947
395
  maybe_cert = X509ToObject(env, first_cert.release());
948
395
  if (!maybe_cert.ToLocal(&result))
949
    return MaybeLocal<Value>();
950
951
  Local<Object> issuer_chain;
952
  MaybeLocal<Object> maybe_issuer_chain;
953
954
  maybe_issuer_chain =
955
      AddIssuerChainToObject(
956
          &cert,
957
          result,
958
395
          std::move(peer_certs),
959
395
          env);
960
395
  if (!maybe_issuer_chain.ToLocal(&issuer_chain))
961
    return MaybeLocal<Value>();
962
963
  maybe_issuer_chain =
964
      GetLastIssuedCert(
965
          &cert,
966
          ssl,
967
          issuer_chain,
968
395
          env);
969
970
  issuer_chain.Clear();
971
395
  if (!maybe_issuer_chain.ToLocal(&issuer_chain))
972
    return MaybeLocal<Value>();
973
974
  // Last certificate should be self-signed.
975
789
  if (X509_check_issued(cert.get(), cert.get()) == X509_V_OK &&
976

1183
      !Set<Object>(env->context(),
977
           issuer_chain,
978
           env->issuercert_string(),
979
           issuer_chain)) {
980
    return MaybeLocal<Value>();
981
  }
982
983
395
  return result;
984
}
985
986
1154
MaybeLocal<Object> X509ToObject(Environment* env, X509* cert) {
987
1154
  EscapableHandleScope scope(env->isolate());
988
1154
  Local<Context> context = env->context();
989
1154
  Local<Object> info = Object::New(env->isolate());
990
991
2308
  BIOPointer bio(BIO_new(BIO_s_mem()));
992
993
2308
  if (!Set<Value>(context,
994
                  info,
995
                  env->subject_string(),
996
1154
                  GetSubject(env, bio, cert)) ||
997
2308
      !Set<Value>(context,
998
                  info,
999
                  env->issuer_string(),
1000
1154
                  GetIssuerString(env, bio, cert)) ||
1001
2308
      !Set<Value>(context,
1002
                  info,
1003
                  env->subjectaltname_string(),
1004
2308
                  GetInfoString<NID_subject_alt_name>(env, bio, cert)) ||
1005

3462
      !Set<Value>(context,
1006
                  info,
1007
                  env->infoaccess_string(),
1008
                  GetInfoString<NID_info_access>(env, bio, cert))) {
1009
    return MaybeLocal<Object>();
1010
  }
1011
1012
2308
  EVPKeyPointer pkey(X509_get_pubkey(cert));
1013
1154
  RSAPointer rsa;
1014
1154
  ECPointer ec;
1015
1154
  if (pkey) {
1016
1154
    switch (EVP_PKEY_id(pkey.get())) {
1017
1121
      case EVP_PKEY_RSA:
1018
1121
        rsa.reset(EVP_PKEY_get1_RSA(pkey.get()));
1019
1121
        break;
1020
33
      case EVP_PKEY_EC:
1021
33
        ec.reset(EVP_PKEY_get1_EC_KEY(pkey.get()));
1022
33
        break;
1023
    }
1024
  }
1025
1026
1154
  if (rsa) {
1027
    const BIGNUM* n;
1028
    const BIGNUM* e;
1029
1121
    RSA_get0_key(rsa.get(), &n, &e, nullptr);
1030
2242
    if (!Set<Value>(context,
1031
                    info,
1032
                    env->modulus_string(),
1033
1121
                    GetModulusString(env, bio, n)) ||
1034
3363
        !Set<Value>(context, info, env->bits_string(), GetBits(env, n)) ||
1035
2242
        !Set<Value>(context,
1036
                    info,
1037
                    env->exponent_string(),
1038
2242
                    GetExponentString(env, bio, e)) ||
1039

3363
        !Set<Object>(context,
1040
                     info,
1041
                     env->pubkey_string(),
1042
                     GetPubKey(env, rsa))) {
1043
      return MaybeLocal<Object>();
1044
    }
1045
33
  } else if (ec) {
1046
33
    const EC_GROUP* group = EC_KEY_get0_group(ec.get());
1047
1048
66
    if (!Set<Value>(context,
1049
                    info,
1050
                    env->bits_string(),
1051
66
                    GetECGroup(env, group, ec)) ||
1052

99
        !Set<Value>(context,
1053
                    info,
1054
                    env->pubkey_string(),
1055
                    GetECPubKey(env, group, ec))) {
1056
      return MaybeLocal<Object>();
1057
    }
1058
1059
33
    const int nid = EC_GROUP_get_curve_name(group);
1060
33
    if (nid != 0) {
1061
      // Curve is well-known, get its OID and NIST nick-name (if it has one).
1062
1063
66
      if (!Set<Value>(context,
1064
                      info,
1065
                      env->asn1curve_string(),
1066
66
                      GetCurveASN1Name(env, nid)) ||
1067

99
          !Set<Value>(context,
1068
                      info,
1069
                      env->nistcurve_string(),
1070
                      GetCurveNistName(env, nid))) {
1071
        return MaybeLocal<Object>();
1072
      }
1073
    } else {
1074
      // Unnamed curves can be described by their mathematical properties,
1075
      // but aren't used much (at all?) with X.509/TLS. Support later if needed.
1076
    }
1077
  }
1078
1079
  // pkey, rsa, and ec pointers are no longer needed.
1080
1154
  pkey.reset();
1081
1154
  rsa.reset();
1082
1154
  ec.reset();
1083
1084
2308
  if (!Set<Value>(context,
1085
                  info,
1086
                  env->valid_from_string(),
1087
2308
                  GetValidFrom(env, cert, bio)) ||
1088

3462
      !Set<Value>(context,
1089
                  info,
1090
                  env->valid_to_string(),
1091
                  GetValidTo(env, cert, bio))) {
1092
    return MaybeLocal<Object>();
1093
  }
1094
1095
  // bio is no longer needed
1096
1154
  bio.reset();
1097
1098
2308
  if (!Set<Value>(context,
1099
                  info,
1100
                  env->fingerprint_string(),
1101
1154
                  GetFingerprintDigest(env, EVP_sha1(), cert)) ||
1102
2308
      !Set<Value>(context,
1103
                  info,
1104
                  env->fingerprint256_string(),
1105
1154
                  GetFingerprintDigest(env, EVP_sha256(), cert)) ||
1106
2308
      !Set<Value>(context,
1107
                  info,
1108
                  env->ext_key_usage_string(),
1109
1154
                  GetKeyUsage(env, cert)) ||
1110
2308
      !Set<Value>(context,
1111
                  info,
1112
                  env->serial_number_string(),
1113
2308
                  GetSerialNumber(env, cert)) ||
1114

3462
      !Set<Object>(context,
1115
                   info,
1116
                   env->raw_string(),
1117
                   GetRawDERCertificate(env, cert))) {
1118
    return MaybeLocal<Object>();
1119
  }
1120
1121
1154
  return scope.Escape(info);
1122
}
1123
1124
}  // namespace crypto
1125
}  // namespace node