GCC Code Coverage Report
Directory: ../ Exec Total Coverage
File: /home/iojs/build/workspace/node-test-commit-linux-coverage-daily/nodes/benchmark/out/../src/node_crypto_common.cc Lines: 371 558 66.5 %
Date: 2020-05-27 22:15:15 Branches: 192 407 47.2 %

Line Branch Exec Source
1
#include "base_object-inl.h"
2
#include "env-inl.h"
3
#include "node_buffer.h"
4
#include "node_crypto.h"
5
#include "node_crypto_common.h"
6
#include "node.h"
7
#include "node_internals.h"
8
#include "node_url.h"
9
#include "string_bytes.h"
10
#include "v8.h"
11
12
#include <openssl/ec.h>
13
#include <openssl/ecdh.h>
14
#include <openssl/evp.h>
15
#include <openssl/pem.h>
16
#include <openssl/x509v3.h>
17
#include <openssl/hmac.h>
18
#include <openssl/rand.h>
19
#include <openssl/pkcs12.h>
20
21
#include <string>
22
#include <unordered_map>
23
24
namespace node {
25
26
using v8::Array;
27
using v8::ArrayBufferView;
28
using v8::Context;
29
using v8::EscapableHandleScope;
30
using v8::Integer;
31
using v8::Local;
32
using v8::MaybeLocal;
33
using v8::NewStringType;
34
using v8::Null;
35
using v8::Object;
36
using v8::String;
37
using v8::Undefined;
38
using v8::Value;
39
40
namespace crypto {
41
42
static constexpr int X509_NAME_FLAGS =
43
    ASN1_STRFLGS_ESC_CTRL |
44
    ASN1_STRFLGS_UTF8_CONVERT |
45
    XN_FLAG_SEP_MULTILINE |
46
    XN_FLAG_FN_SN;
47
48
796
int SSL_CTX_get_issuer(SSL_CTX* ctx, X509* cert, X509** issuer) {
49
796
  X509_STORE* store = SSL_CTX_get_cert_store(ctx);
50
  DeleteFnPtr<X509_STORE_CTX, X509_STORE_CTX_free> store_ctx(
51
1592
      X509_STORE_CTX_new());
52
1592
  return store_ctx.get() != nullptr &&
53

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

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

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

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







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


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


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

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

2266
  if (index < 0)
713
4392
    return Undefined(env->isolate());
714
715
70
  X509_EXTENSION* ext = X509_get_ext(cert, index);
716

70
  CHECK_NOT_NULL(ext);
717
718



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

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

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

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


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

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

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

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

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

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

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

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