GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/crypto/crypto_common.cc Lines: 374 560 66.8 %
Date: 2020-11-20 19:51:53 Branches: 192 407 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::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
static constexpr int X509_NAME_FLAGS =
44
    ASN1_STRFLGS_ESC_CTRL |
45
    ASN1_STRFLGS_UTF8_CONVERT |
46
    XN_FLAG_SEP_MULTILINE |
47
    XN_FLAG_FN_SN;
48
49
812
int SSL_CTX_get_issuer(SSL_CTX* ctx, X509* cert, X509** issuer) {
50
812
  X509_STORE* store = SSL_CTX_get_cert_store(ctx);
51
  DeleteFnPtr<X509_STORE_CTX, X509_STORE_CTX_free> store_ctx(
52
1624
      X509_STORE_CTX_new());
53
1624
  return store_ctx.get() != nullptr &&
54

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

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

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

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







423
  switch (err) {
301
1
    CASE_X509_ERR(UNABLE_TO_GET_ISSUER_CERT)
302
1
    CASE_X509_ERR(UNABLE_TO_GET_CRL)
303
    CASE_X509_ERR(UNABLE_TO_DECRYPT_CERT_SIGNATURE)
304
    CASE_X509_ERR(UNABLE_TO_DECRYPT_CRL_SIGNATURE)
305
    CASE_X509_ERR(UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY)
306
    CASE_X509_ERR(CERT_SIGNATURE_FAILURE)
307
    CASE_X509_ERR(CRL_SIGNATURE_FAILURE)
308
    CASE_X509_ERR(CERT_NOT_YET_VALID)
309
    CASE_X509_ERR(CERT_HAS_EXPIRED)
310
    CASE_X509_ERR(CRL_NOT_YET_VALID)
311
    CASE_X509_ERR(CRL_HAS_EXPIRED)
312
    CASE_X509_ERR(ERROR_IN_CERT_NOT_BEFORE_FIELD)
313
    CASE_X509_ERR(ERROR_IN_CERT_NOT_AFTER_FIELD)
314
    CASE_X509_ERR(ERROR_IN_CRL_LAST_UPDATE_FIELD)
315
    CASE_X509_ERR(ERROR_IN_CRL_NEXT_UPDATE_FIELD)
316
    CASE_X509_ERR(OUT_OF_MEM)
317
236
    CASE_X509_ERR(DEPTH_ZERO_SELF_SIGNED_CERT)
318
13
    CASE_X509_ERR(SELF_SIGNED_CERT_IN_CHAIN)
319
3
    CASE_X509_ERR(UNABLE_TO_GET_ISSUER_CERT_LOCALLY)
320
167
    CASE_X509_ERR(UNABLE_TO_VERIFY_LEAF_SIGNATURE)
321
    CASE_X509_ERR(CERT_CHAIN_TOO_LONG)
322
1
    CASE_X509_ERR(CERT_REVOKED)
323
    CASE_X509_ERR(INVALID_CA)
324
    CASE_X509_ERR(PATH_LENGTH_EXCEEDED)
325
1
    CASE_X509_ERR(INVALID_PURPOSE)
326
    CASE_X509_ERR(CERT_UNTRUSTED)
327
    CASE_X509_ERR(CERT_REJECTED)
328
    CASE_X509_ERR(HOSTNAME_MISMATCH)
329
  }
330
#undef CASE_X509_ERR
331
423
  return code;
332
}
333
334
MaybeLocal<Value> GetValidationErrorReason(Environment* env, int err) {
335
  if (err == 0)
336
    return Undefined(env->isolate());
337
  const char* reason = X509_verify_cert_error_string(err);
338
  return OneByteString(env->isolate(), reason);
339
}
340
341
MaybeLocal<Value> GetValidationErrorCode(Environment* env, int err) {
342
  if (err == 0)
343
    return Undefined(env->isolate());
344
  return OneByteString(env->isolate(), X509ErrorCode(err));
345
}
346
347
12
MaybeLocal<Value> GetCert(Environment* env, const SSLPointer& ssl) {
348
12
  ClearErrorOnReturn clear_error_on_return;
349
12
  X509* cert = SSL_get_certificate(ssl.get());
350
12
  if (cert == nullptr)
351
2
    return Undefined(env->isolate());
352
353
11
  MaybeLocal<Object> maybe_cert = X509ToObject(env, cert);
354
11
  return maybe_cert.FromMaybe<Value>(Local<Value>());
355
}
356
357
namespace {
358
template <typename T>
359
20684
bool Set(
360
    Local<Context> context,
361
    Local<Object> target,
362
    Local<Value> name,
363
    MaybeLocal<T> maybe_value) {
364
  Local<Value> value;
365


20684
  if (!maybe_value.ToLocal(&value))
366
    return false;
367
368
  // Undefined is ignored, but still considered successful
369


41368
  if (value->IsUndefined())
370
3337
    return true;
371
372
34694
  return !target->Set(context, name, value).IsNothing();
373
}
374
375
6841
Local<Value> ToV8Value(Environment* env, const BIOPointer& bio) {
376
  BUF_MEM* mem;
377
6841
  BIO_get_mem_ptr(bio.get(), &mem);
378
  MaybeLocal<String> ret =
379
      String::NewFromUtf8(
380
          env->isolate(),
381
6841
          mem->data,
382
          NewStringType::kNormal,
383
13682
          mem->length);
384
6841
  USE(BIO_reset(bio.get()));
385
6841
  return ret.FromMaybe(Local<Value>());
386
}
387
388
147
MaybeLocal<Value> GetCipherValue(Environment* env,
389
    const SSL_CIPHER* cipher,
390
    const char* (*getstr)(const SSL_CIPHER* cipher)) {
391
147
  if (cipher == nullptr)
392
    return Undefined(env->isolate());
393
394
294
  return OneByteString(env->isolate(), getstr(cipher));
395
}
396
397
49
MaybeLocal<Value> GetCipherName(Environment* env, const SSL_CIPHER* cipher) {
398
49
  return GetCipherValue(env, cipher, SSL_CIPHER_get_name);
399
}
400
401
49
MaybeLocal<Value> GetCipherStandardName(
402
    Environment* env,
403
    const SSL_CIPHER* cipher) {
404
49
  return GetCipherValue(env, cipher, SSL_CIPHER_standard_name);
405
}
406
407
49
MaybeLocal<Value> GetCipherVersion(Environment* env, const SSL_CIPHER* cipher) {
408
49
  return GetCipherValue(env, cipher, SSL_CIPHER_get_version);
409
}
410
411
388
StackOfX509 CloneSSLCerts(X509Pointer&& cert,
412
                          const STACK_OF(X509)* const ssl_certs) {
413
776
  StackOfX509 peer_certs(sk_X509_new(nullptr));
414
388
  if (cert)
415
    sk_X509_push(peer_certs.get(), cert.release());
416
1115
  for (int i = 0; i < sk_X509_num(ssl_certs); i++) {
417
1454
    X509Pointer cert(X509_dup(sk_X509_value(ssl_certs, i)));
418

727
    if (!cert || !sk_X509_push(peer_certs.get(), cert.get()))
419
      return StackOfX509();
420
    // `cert` is now managed by the stack.
421
727
    cert.release();
422
  }
423
388
  return peer_certs;
424
}
425
426
388
MaybeLocal<Object> AddIssuerChainToObject(
427
    X509Pointer* cert,
428
    Local<Object> object,
429
    StackOfX509&& peer_certs,
430
    Environment* const env) {
431
388
  Local<Context> context = env->isolate()->GetCurrentContext();
432
388
  cert->reset(sk_X509_delete(peer_certs.get(), 0));
433
  for (;;) {
434
    int i;
435
395
    for (i = 0; i < sk_X509_num(peer_certs.get()); i++) {
436
339
      X509* ca = sk_X509_value(peer_certs.get(), i);
437
339
      if (X509_check_issued(ca, cert->get()) != X509_V_OK)
438
2
        continue;
439
440
      Local<Object> ca_info;
441
337
      MaybeLocal<Object> maybe_ca_info = X509ToObject(env, ca);
442
337
      if (!maybe_ca_info.ToLocal(&ca_info))
443
        return MaybeLocal<Object>();
444
445
674
      if (!Set<Object>(context, object, env->issuercert_string(), ca_info))
446
        return MaybeLocal<Object>();
447
337
      object = ca_info;
448
449
      // NOTE: Intentionally freeing cert that is not used anymore.
450
      // Delete cert and continue aggregating issuers.
451
337
      cert->reset(sk_X509_delete(peer_certs.get(), i));
452
337
      break;
453
    }
454
455
    // Issuer not found, break out of the loop.
456
393
    if (i == sk_X509_num(peer_certs.get()))
457
388
      break;
458
5
  }
459
388
  return MaybeLocal<Object>(object);
460
}
461
462
388
MaybeLocal<Object> GetLastIssuedCert(
463
    X509Pointer* cert,
464
    const SSLPointer& ssl,
465
    Local<Object> issuer_chain,
466
    Environment* const env) {
467
388
  Local<Context> context = env->isolate()->GetCurrentContext();
468
1110
  while (X509_check_issued(cert->get(), cert->get()) != X509_V_OK) {
469
    X509* ca;
470
361
    if (SSL_CTX_get_issuer(SSL_get_SSL_CTX(ssl.get()), cert->get(), &ca) <= 0)
471
      break;
472
473
    Local<Object> ca_info;
474
361
    MaybeLocal<Object> maybe_ca_info = X509ToObject(env, ca);
475
361
    if (!maybe_ca_info.ToLocal(&ca_info))
476
      return MaybeLocal<Object>();
477
478
722
    if (!Set<Object>(context, issuer_chain, env->issuercert_string(), ca_info))
479
      return MaybeLocal<Object>();
480
361
    issuer_chain = ca_info;
481
482
    // Delete previous cert and continue aggregating issuers.
483
361
    cert->reset(ca);
484
  }
485
388
  return MaybeLocal<Object>(issuer_chain);
486
}
487
488
1141
MaybeLocal<Object> GetRawDERCertificate(Environment* env, X509* cert) {
489
1141
  int size = i2d_X509(cert, nullptr);
490
491
2282
  AllocatedBuffer buffer = AllocatedBuffer::AllocateManaged(env, size);
492
  unsigned char* serialized =
493
1141
      reinterpret_cast<unsigned char*>(buffer.data());
494
1141
  i2d_X509(cert, &serialized);
495
2282
  return buffer.ToBuffer();
496
}
497
498
1141
MaybeLocal<Value> GetSerialNumber(Environment* env, X509* cert) {
499
1141
  if (ASN1_INTEGER* serial_number = X509_get_serialNumber(cert)) {
500
1141
    BignumPointer bn(ASN1_INTEGER_to_BN(serial_number, nullptr));
501
1141
    if (bn) {
502
1141
      char* data = BN_bn2hex(bn.get());
503
1141
      ByteSource buf = ByteSource::Allocated(data, strlen(data));
504
1141
      if (buf)
505
2282
        return OneByteString(env->isolate(), buf.get());
506
    }
507
  }
508
509
  return Undefined(env->isolate());
510
}
511
512
1141
MaybeLocal<Value> GetKeyUsage(Environment* env, X509* cert) {
513
  StackOfASN1 eku(static_cast<STACK_OF(ASN1_OBJECT)*>(
514
2282
      X509_get_ext_d2i(cert, NID_ext_key_usage, nullptr, nullptr)));
515
1141
  if (eku) {
516
10
    const int count = sk_ASN1_OBJECT_num(eku.get());
517
20
    MaybeStackBuffer<Local<Value>, 16> ext_key_usage(count);
518
    char buf[256];
519
520
10
    int j = 0;
521
26
    for (int i = 0; i < count; i++) {
522
16
      if (OBJ_obj2txt(buf,
523
                      sizeof(buf),
524
16
                      sk_ASN1_OBJECT_value(eku.get(), i), 1) >= 0) {
525
32
        ext_key_usage[j++] = OneByteString(env->isolate(), buf);
526
      }
527
    }
528
529
20
    return Array::New(env->isolate(), ext_key_usage.out(), count);
530
  }
531
532
2262
  return Undefined(env->isolate());
533
}
534
535
2282
void AddFingerprintDigest(
536
    const unsigned char* md,
537
    unsigned int md_size,
538
    char (*fingerprint)[3 * EVP_MAX_MD_SIZE + 1]) {
539
  unsigned int i;
540
2282
  const char hex[] = "0123456789ABCDEF";
541
542
61614
  for (i = 0; i < md_size; i++) {
543
59332
    (*fingerprint)[3*i] = hex[(md[i] & 0xf0) >> 4];
544
59332
    (*fingerprint)[(3*i)+1] = hex[(md[i] & 0x0f)];
545
59332
    (*fingerprint)[(3*i)+2] = ':';
546
  }
547
548
2282
  if (md_size > 0) {
549
2282
    (*fingerprint)[(3*(md_size-1))+2] = '\0';
550
  } else {
551
    (*fingerprint)[0] = '\0';
552
  }
553
2282
}
554
555
76
bool SafeX509ExtPrint(const BIOPointer& out, X509_EXTENSION* ext) {
556
76
  const X509V3_EXT_METHOD* method = X509V3_EXT_get(ext);
557
558
76
  if (method != X509V3_EXT_get_nid(NID_subject_alt_name))
559
70
    return false;
560
561
6
  GENERAL_NAMES* names = static_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(ext));
562
6
  if (names == nullptr)
563
1
    return false;
564
565
20
  for (int i = 0; i < sk_GENERAL_NAME_num(names); i++) {
566
15
    GENERAL_NAME* gen = sk_GENERAL_NAME_value(names, i);
567
568
15
    if (i != 0)
569
10
      BIO_write(out.get(), ", ", 2);
570
571
15
    if (gen->type == GEN_DNS) {
572
12
      ASN1_IA5STRING* name = gen->d.dNSName;
573
574
12
      BIO_write(out.get(), "DNS:", 4);
575
12
      BIO_write(out.get(), name->data, name->length);
576
    } else {
577
      STACK_OF(CONF_VALUE)* nval = i2v_GENERAL_NAME(
578
3
          const_cast<X509V3_EXT_METHOD*>(method), gen, nullptr);
579
3
      if (nval == nullptr)
580
        return false;
581
3
      X509V3_EXT_val_prn(out.get(), nval, 0, 0);
582
3
      sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
583
    }
584
  }
585
5
  sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
586
587
5
  return true;
588
}
589
590
2282
MaybeLocal<Value> GetFingerprintDigest(
591
    Environment* env,
592
    const EVP_MD* method,
593
    X509* cert) {
594
  unsigned char md[EVP_MAX_MD_SIZE];
595
  unsigned int md_size;
596
  char fingerprint[EVP_MAX_MD_SIZE * 3 + 1];
597
598
2282
  if (X509_digest(cert, method, md, &md_size)) {
599
2282
    AddFingerprintDigest(md, md_size, &fingerprint);
600
4564
    return OneByteString(env->isolate(), fingerprint);
601
  }
602
  return Undefined(env->isolate());
603
}
604
605
1141
MaybeLocal<Value> GetValidTo(
606
    Environment* env,
607
    X509* cert,
608
    const BIOPointer& bio) {
609
1141
  ASN1_TIME_print(bio.get(), X509_get0_notAfter(cert));
610
2282
  return ToV8Value(env, bio);
611
}
612
613
1141
MaybeLocal<Value> GetValidFrom(
614
    Environment* env,
615
    X509* cert,
616
    const BIOPointer& bio) {
617
1141
  ASN1_TIME_print(bio.get(), X509_get0_notBefore(cert));
618
2282
  return ToV8Value(env, bio);
619
}
620
621
40
MaybeLocal<Value> GetCurveASN1Name(Environment* env, const int nid) {
622
40
  const char* nist = OBJ_nid2sn(nid);
623
  return nist != nullptr ?
624
      MaybeLocal<Value>(OneByteString(env->isolate(), nist)) :
625
80
      MaybeLocal<Value>(Undefined(env->isolate()));
626
}
627
628
40
MaybeLocal<Value> GetCurveNistName(Environment* env, const int nid) {
629
40
  const char* nist = EC_curve_nid2nist(nid);
630
  return nist != nullptr ?
631
      MaybeLocal<Value>(OneByteString(env->isolate(), nist)) :
632
80
      MaybeLocal<Value>(Undefined(env->isolate()));
633
}
634
635
40
MaybeLocal<Value> GetECPubKey(
636
    Environment* env,
637
    const EC_GROUP* group,
638
    const ECPointer& ec) {
639
40
  const EC_POINT* pubkey = EC_KEY_get0_public_key(ec.get());
640
40
  if (pubkey == nullptr)
641
    return Undefined(env->isolate());
642
643
80
  return ECPointToBuffer(
644
      env,
645
      group,
646
      pubkey,
647
40
      EC_KEY_get_conv_form(ec.get()),
648
120
      nullptr).FromMaybe(Local<Object>());
649
}
650
651
40
MaybeLocal<Value> GetECGroup(
652
    Environment* env,
653
    const EC_GROUP* group,
654
    const ECPointer& ec) {
655
40
  if (group == nullptr)
656
    return Undefined(env->isolate());
657
658
40
  int bits = EC_GROUP_order_bits(group);
659
40
  if (bits <= 0)
660
    return Undefined(env->isolate());
661
662
80
  return Integer::New(env->isolate(), bits);
663
}
664
665
1101
MaybeLocal<Object> GetPubKey(Environment* env, const RSAPointer& rsa) {
666
1101
  int size = i2d_RSA_PUBKEY(rsa.get(), nullptr);
667
1101
  CHECK_GE(size, 0);
668
669
2202
  AllocatedBuffer buffer = AllocatedBuffer::AllocateManaged(env, size);
670
  unsigned char* serialized =
671
1101
      reinterpret_cast<unsigned char*>(buffer.data());
672
1101
  i2d_RSA_PUBKEY(rsa.get(), &serialized);
673
2202
  return buffer.ToBuffer();
674
}
675
676
1101
MaybeLocal<Value> GetExponentString(
677
    Environment* env,
678
    const BIOPointer& bio,
679
    const BIGNUM* e) {
680
1101
  uint64_t exponent_word = static_cast<uint64_t>(BN_get_word(e));
681
1101
  uint32_t lo = static_cast<uint32_t>(exponent_word);
682
1101
  uint32_t hi = static_cast<uint32_t>(exponent_word >> 32);
683
1101
  if (hi == 0)
684
1101
    BIO_printf(bio.get(), "0x%x", lo);
685
  else
686
    BIO_printf(bio.get(), "0x%x%08x", hi, lo);
687
688
2202
  return ToV8Value(env, bio);
689
}
690
691
1101
Local<Value> GetBits(Environment* env, const BIGNUM* n) {
692
2202
  return Integer::New(env->isolate(), BN_num_bits(n));
693
}
694
695
1101
MaybeLocal<Value> GetModulusString(
696
    Environment* env,
697
    const BIOPointer& bio,
698
    const BIGNUM* n) {
699
1101
  BN_print(bio.get(), n);
700
2202
  return ToV8Value(env, bio);
701
}
702
703
template <int nid>
704
2282
MaybeLocal<Value> GetInfoString(
705
    Environment* env,
706
    const BIOPointer& bio,
707
    X509* cert) {
708
2282
  int index = X509_get_ext_by_NID(cert, nid, -1);
709

2282
  if (index < 0)
710
4412
    return Undefined(env->isolate());
711
712
76
  X509_EXTENSION* ext = X509_get_ext(cert, index);
713

76
  CHECK_NOT_NULL(ext);
714
715



147
  if (!SafeX509ExtPrint(bio, ext) &&
716
71
      X509V3_EXT_print(bio.get(), ext, 0, 0) != 1) {
717
1
    USE(BIO_reset(bio.get()));
718
2
    return Null(env->isolate());
719
  }
720
721
150
  return ToV8Value(env, bio);
722
}
723
724
1141
MaybeLocal<Value> GetIssuerString(
725
    Environment* env,
726
    const BIOPointer& bio,
727
    X509* cert) {
728
1141
  X509_NAME* issuer_name = X509_get_issuer_name(cert);
729
1141
  if (X509_NAME_print_ex(bio.get(), issuer_name, 0, X509_NAME_FLAGS) <= 0) {
730
    USE(BIO_reset(bio.get()));
731
    return Undefined(env->isolate());
732
  }
733
734
2282
  return ToV8Value(env, bio);
735
}
736
737
1141
MaybeLocal<Value> GetSubject(
738
    Environment* env,
739
    const BIOPointer& bio,
740
    X509* cert) {
741
1141
  if (X509_NAME_print_ex(
742
          bio.get(),
743
1141
          X509_get_subject_name(cert),
744
          0,
745
          X509_NAME_FLAGS) <= 0) {
746
    USE(BIO_reset(bio.get()));
747
    return Undefined(env->isolate());
748
  }
749
750
2282
  return ToV8Value(env, bio);
751
}
752
}  // namespace
753
754
49
MaybeLocal<Value> GetCipherName(Environment* env, const SSLPointer& ssl) {
755
49
  return GetCipherName(env, SSL_get_current_cipher(ssl.get()));
756
}
757
758
49
MaybeLocal<Value> GetCipherStandardName(
759
    Environment* env,
760
    const SSLPointer& ssl) {
761
49
  return GetCipherStandardName(env, SSL_get_current_cipher(ssl.get()));
762
}
763
764
49
MaybeLocal<Value> GetCipherVersion(Environment* env, const SSLPointer& ssl) {
765
49
  return GetCipherVersion(env, SSL_get_current_cipher(ssl.get()));
766
}
767
768
MaybeLocal<Array> GetClientHelloCiphers(
769
    Environment* env,
770
    const SSLPointer& ssl) {
771
  EscapableHandleScope scope(env->isolate());
772
  const unsigned char* buf;
773
  size_t len = SSL_client_hello_get0_ciphers(ssl.get(), &buf);
774
  size_t count = len / 2;
775
  MaybeStackBuffer<Local<Value>, 16> ciphers(count);
776
  int j = 0;
777
  for (size_t n = 0; n < len; n += 2) {
778
    const SSL_CIPHER* cipher = SSL_CIPHER_find(ssl.get(), buf);
779
    buf += 2;
780
    Local<Object> obj = Object::New(env->isolate());
781
    if (!Set(env->context(),
782
             obj,
783
             env->name_string(),
784
             GetCipherName(env, cipher)) ||
785
        !Set(env->context(),
786
             obj,
787
             env->standard_name_string(),
788
             GetCipherStandardName(env, cipher)) ||
789
        !Set(env->context(),
790
             obj,
791
             env->version_string(),
792
             GetCipherVersion(env, cipher))) {
793
      return MaybeLocal<Array>();
794
    }
795
    ciphers[j++] = obj;
796
  }
797
  Local<Array> ret = Array::New(env->isolate(), ciphers.out(), count);
798
  return scope.Escape(ret);
799
}
800
801
802
49
MaybeLocal<Object> GetCipherInfo(Environment* env, const SSLPointer& ssl) {
803
49
  if (SSL_get_current_cipher(ssl.get()) == nullptr)
804
    return MaybeLocal<Object>();
805
49
  EscapableHandleScope scope(env->isolate());
806
49
  Local<Object> info = Object::New(env->isolate());
807
808
196
  if (!Set<Value>(env->context(),
809
                  info,
810
                  env->name_string(),
811
49
                  GetCipherName(env, ssl)) ||
812
147
      !Set<Value>(env->context(),
813
                  info,
814
                  env->standard_name_string(),
815

98
                  GetCipherStandardName(env, ssl)) ||
816
147
      !Set<Value>(env->context(),
817
                  info,
818
                  env->version_string(),
819
                  GetCipherVersion(env, ssl))) {
820
    return MaybeLocal<Object>();
821
  }
822
823
49
  return scope.Escape(info);
824
}
825
826
815
MaybeLocal<Object> GetEphemeralKey(Environment* env, const SSLPointer& ssl) {
827
815
  CHECK_EQ(SSL_is_server(ssl.get()), 0);
828
  EVP_PKEY* raw_key;
829
830
815
  EscapableHandleScope scope(env->isolate());
831
815
  Local<Object> info = Object::New(env->isolate());
832
815
  if (!SSL_get_server_tmp_key(ssl.get(), &raw_key))
833
34
    return scope.Escape(info);
834
835
781
  Local<Context> context = env->context();
836
1562
  crypto::EVPKeyPointer key(raw_key);
837
838
781
  int kid = EVP_PKEY_id(key.get());
839
781
  int bits = EVP_PKEY_bits(key.get());
840
781
  switch (kid) {
841
    case EVP_PKEY_DH:
842

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

1548
                OneByteString(env->isolate(), curve_name)) ||
870
3096
            !Set<Integer>(context,
871
                 info,
872
                 env->size_string(),
873
                 Integer::New(env->isolate(), bits))) {
874
          return MaybeLocal<Object>();
875
        }
876
      }
877
774
      break;
878
  }
879
880
781
  return scope.Escape(info);
881
}
882
883
66
MaybeLocal<Object> ECPointToBuffer(Environment* env,
884
                                   const EC_GROUP* group,
885
                                   const EC_POINT* point,
886
                                   point_conversion_form_t form,
887
                                   const char** error) {
888
66
  size_t len = EC_POINT_point2oct(group, point, form, nullptr, 0, nullptr);
889
66
  if (len == 0) {
890
    if (error != nullptr) *error = "Failed to get public key length";
891
    return MaybeLocal<Object>();
892
  }
893
132
  AllocatedBuffer buf = AllocatedBuffer::AllocateManaged(env, len);
894
66
  len = EC_POINT_point2oct(group,
895
                           point,
896
                           form,
897
66
                           reinterpret_cast<unsigned char*>(buf.data()),
898
                           buf.size(),
899
66
                           nullptr);
900
66
  if (len == 0) {
901
    if (error != nullptr) *error = "Failed to get public key";
902
    return MaybeLocal<Object>();
903
  }
904
66
  return buf.ToBuffer();
905
}
906
907
437
MaybeLocal<Value> GetPeerCert(
908
    Environment* env,
909
    const SSLPointer& ssl,
910
    bool abbreviated,
911
    bool is_server) {
912
437
  ClearErrorOnReturn clear_error_on_return;
913
  Local<Object> result;
914
  MaybeLocal<Object> maybe_cert;
915
916
  // NOTE: This is because of the odd OpenSSL behavior. On client `cert_chain`
917
  // contains the `peer_certificate`, but on server it doesn't.
918
874
  X509Pointer cert(is_server ? SSL_get_peer_certificate(ssl.get()) : nullptr);
919
437
  STACK_OF(X509)* ssl_certs = SSL_get_peer_cert_chain(ssl.get());
920


437
  if (!cert && (ssl_certs == nullptr || sk_X509_num(ssl_certs) == 0))
921
10
    return Undefined(env->isolate());
922
923
  // Short result requested.
924
432
  if (abbreviated) {
925
    maybe_cert =
926
44
        X509ToObject(env, cert ? cert.get() : sk_X509_value(ssl_certs, 0));
927
88
    return maybe_cert.ToLocal(&result) ? result : MaybeLocal<Value>();
928
  }
929
930
776
  StackOfX509 peer_certs = CloneSSLCerts(std::move(cert), ssl_certs);
931
388
  if (peer_certs == nullptr)
932
    return Undefined(env->isolate());
933
934
  // First and main certificate.
935
776
  X509Pointer first_cert(sk_X509_value(peer_certs.get(), 0));
936
388
  CHECK(first_cert);
937
388
  maybe_cert = X509ToObject(env, first_cert.release());
938
388
  if (!maybe_cert.ToLocal(&result))
939
    return MaybeLocal<Value>();
940
941
  Local<Object> issuer_chain;
942
  MaybeLocal<Object> maybe_issuer_chain;
943
944
  maybe_issuer_chain =
945
      AddIssuerChainToObject(
946
          &cert,
947
          result,
948
388
          std::move(peer_certs),
949
388
          env);
950
388
  if (!maybe_issuer_chain.ToLocal(&issuer_chain))
951
    return MaybeLocal<Value>();
952
953
  maybe_issuer_chain =
954
      GetLastIssuedCert(
955
          &cert,
956
          ssl,
957
          issuer_chain,
958
388
          env);
959
960
  issuer_chain.Clear();
961
388
  if (!maybe_issuer_chain.ToLocal(&issuer_chain))
962
    return MaybeLocal<Value>();
963
964
  // Last certificate should be self-signed.
965

1164
  if (X509_check_issued(cert.get(), cert.get()) == X509_V_OK &&
966
1164
      !Set<Object>(env->context(),
967
           issuer_chain,
968
           env->issuercert_string(),
969
           issuer_chain)) {
970
    return MaybeLocal<Value>();
971
  }
972
973
388
  return result;
974
}
975
976
1141
MaybeLocal<Object> X509ToObject(Environment* env, X509* cert) {
977
1141
  EscapableHandleScope scope(env->isolate());
978
1141
  Local<Context> context = env->context();
979
1141
  Local<Object> info = Object::New(env->isolate());
980
981
2282
  BIOPointer bio(BIO_new(BIO_s_mem()));
982
983
4564
  if (!Set<Value>(context,
984
                  info,
985
                  env->subject_string(),
986
1141
                  GetSubject(env, bio, cert)) ||
987
3423
      !Set<Value>(context,
988
                  info,
989
                  env->issuer_string(),
990
1141
                  GetIssuerString(env, bio, cert)) ||
991
3423
      !Set<Value>(context,
992
                  info,
993
                  env->subjectaltname_string(),
994

2282
                  GetInfoString<NID_subject_alt_name>(env, bio, cert)) ||
995
3423
      !Set<Value>(context,
996
                  info,
997
                  env->infoaccess_string(),
998
                  GetInfoString<NID_info_access>(env, bio, cert))) {
999
    return MaybeLocal<Object>();
1000
  }
1001
1002
2282
  EVPKeyPointer pkey(X509_get_pubkey(cert));
1003
2282
  RSAPointer rsa;
1004
2282
  ECPointer ec;
1005
1141
  if (pkey) {
1006
1141
    switch (EVP_PKEY_id(pkey.get())) {
1007
      case EVP_PKEY_RSA:
1008
1101
        rsa.reset(EVP_PKEY_get1_RSA(pkey.get()));
1009
1101
        break;
1010
      case EVP_PKEY_EC:
1011
40
        ec.reset(EVP_PKEY_get1_EC_KEY(pkey.get()));
1012
40
        break;
1013
    }
1014
  }
1015
1016
1141
  if (rsa) {
1017
    const BIGNUM* n;
1018
    const BIGNUM* e;
1019
1101
    RSA_get0_key(rsa.get(), &n, &e, nullptr);
1020
4404
    if (!Set<Value>(context,
1021
                    info,
1022
                    env->modulus_string(),
1023
1101
                    GetModulusString(env, bio, n)) ||
1024
5505
        !Set<Value>(context, info, env->bits_string(), GetBits(env, n)) ||
1025
3303
        !Set<Value>(context,
1026
                    info,
1027
                    env->exponent_string(),
1028

2202
                    GetExponentString(env, bio, e)) ||
1029
3303
        !Set<Object>(context,
1030
                     info,
1031
                     env->pubkey_string(),
1032
                     GetPubKey(env, rsa))) {
1033
      return MaybeLocal<Object>();
1034
    }
1035
40
  } else if (ec) {
1036
40
    const EC_GROUP* group = EC_KEY_get0_group(ec.get());
1037
1038
160
    if (!Set<Value>(context,
1039
                    info,
1040
                    env->bits_string(),
1041

80
                    GetECGroup(env, group, ec)) ||
1042
120
        !Set<Value>(context,
1043
                    info,
1044
                    env->pubkey_string(),
1045
                    GetECPubKey(env, group, ec))) {
1046
      return MaybeLocal<Object>();
1047
    }
1048
1049
40
    const int nid = EC_GROUP_get_curve_name(group);
1050
40
    if (nid != 0) {
1051
      // Curve is well-known, get its OID and NIST nick-name (if it has one).
1052
1053
160
      if (!Set<Value>(context,
1054
                      info,
1055
                      env->asn1curve_string(),
1056

80
                      GetCurveASN1Name(env, nid)) ||
1057
120
          !Set<Value>(context,
1058
                      info,
1059
                      env->nistcurve_string(),
1060
                      GetCurveNistName(env, nid))) {
1061
        return MaybeLocal<Object>();
1062
      }
1063
    } else {
1064
      // Unnamed curves can be described by their mathematical properties,
1065
      // but aren't used much (at all?) with X.509/TLS. Support later if needed.
1066
    }
1067
  }
1068
1069
  // pkey, rsa, and ec pointers are no longer needed.
1070
1141
  pkey.reset();
1071
1141
  rsa.reset();
1072
1141
  ec.reset();
1073
1074
4564
  if (!Set<Value>(context,
1075
                  info,
1076
                  env->valid_from_string(),
1077

2282
                  GetValidFrom(env, cert, bio)) ||
1078
3423
      !Set<Value>(context,
1079
                  info,
1080
                  env->valid_to_string(),
1081
                  GetValidTo(env, cert, bio))) {
1082
    return MaybeLocal<Object>();
1083
  }
1084
1085
  // bio is no longer needed
1086
1141
  bio.reset();
1087
1088
4564
  if (!Set<Value>(context,
1089
                  info,
1090
                  env->fingerprint_string(),
1091
1141
                  GetFingerprintDigest(env, EVP_sha1(), cert)) ||
1092
3423
      !Set<Value>(context,
1093
                  info,
1094
                  env->fingerprint256_string(),
1095
1141
                  GetFingerprintDigest(env, EVP_sha256(), cert)) ||
1096
3423
      !Set<Value>(context,
1097
                  info,
1098
                  env->ext_key_usage_string(),
1099
1141
                  GetKeyUsage(env, cert)) ||
1100
3423
      !Set<Value>(context,
1101
                  info,
1102
                  env->serial_number_string(),
1103

2282
                  GetSerialNumber(env, cert)) ||
1104
3423
      !Set<Object>(context,
1105
                   info,
1106
                   env->raw_string(),
1107
                   GetRawDERCertificate(env, cert))) {
1108
    return MaybeLocal<Object>();
1109
  }
1110
1111
1141
  return scope.Escape(info);
1112
}
1113
1114
}  // namespace crypto
1115

14034
}  // namespace node