Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/runtime/networking/fetch.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,8 @@ await fetch("https://example.com", {

This avoids SSL errors with self-signed certificates, but it disables TLS validation, so use it with caution.

Like Node.js, Bun rejects a server's certificate chain when any certificate in it, including the `ca` it chains up to, has an RSA key shorter than 2048 bits or an EC key shorter than 224 bits. `fetch` reports this as a `CA_KEY_TOO_SMALL` or `EE_KEY_TOO_SMALL` error.

### Request options

In addition to the standard fetch options, Bun provides several extensions:
Expand Down
75 changes: 74 additions & 1 deletion packages/bun-usockets/src/crypto/openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1076,6 +1076,64 @@ void us_internal_ssl_set_inline_reject(SSL *ssl) {
SSL_set_verify(ssl, SSL_VERIFY_PEER, us_inline_reject_verify_callback);
}

/* ── Chain policy on top of X509_verify_cert ─────────────────────────────── */

/* BoringSSL's verifier has no security levels: it verifies a chain built
* through an RSA-512 CA (factorable in hours) as cleanly as one through an
* RSA-4096 CA, and its evp.h leaves bounding key sizes to the caller. Node gets
* OpenSSL's default level, 2 = 112-bit keys (RSA-2048 / P-224), applied to the
* leaf and then to every issuer up to and including the trust anchor:
* https://github.com/openssl/openssl/blob/openssl-3.5.0/crypto/x509/x509_vfy.c#L188-L205
* https://github.com/openssl/openssl/blob/openssl-3.5.0/crypto/x509/x509_vfy.c#L3674-L3702 */
#define US_MIN_RSA_KEY_BITS 2048
#define US_MIN_EC_KEY_BITS 224

static int us_x509_key_too_small(const X509 *cert) {
const EVP_PKEY *key = X509_get0_pubkey(cert);
if (!key) return 1;
switch (EVP_PKEY_id(key)) {
case EVP_PKEY_RSA:
case EVP_PKEY_RSA_PSS:
return EVP_PKEY_bits(key) < US_MIN_RSA_KEY_BITS;
case EVP_PKEY_EC:
return EVP_PKEY_bits(key) < US_MIN_EC_KEY_BITS;
}
/* Ed25519, ML-DSA, ...: fixed-size keys, all at or above 128-bit security. */
return 0;
}

/* chain[0] is the end-entity certificate, chain[n-1] the trust anchor. */
static int us_x509_chain_policy_error(X509_STORE_CTX *ctx) {
const STACK_OF(X509) *chain = X509_STORE_CTX_get0_chain(ctx);
size_t n = chain ? sk_X509_num(chain) : 0;
for (size_t i = 0; i < n; i++) {
if (us_x509_key_too_small(sk_X509_value(chain, i))) {
return i == 0 ? US_X509_V_ERR_EE_KEY_TOO_SMALL : US_X509_V_ERR_CA_KEY_TOO_SMALL;
}
}
return X509_V_OK;
}

int us_internal_x509_verify_cert(X509_STORE_CTX *ctx) {
if (!X509_verify_cert(ctx)) return 0;
/* A verify callback already let an error through; that verdict stands. */
if (X509_STORE_CTX_get_error(ctx) != X509_V_OK) return 1;
int err = us_x509_chain_policy_error(ctx);
if (err == X509_V_OK) return 1;
X509_STORE_CTX_set_error(ctx, err);
/* Surface it exactly like one of X509_verify_cert's own failures: the
* connection's verify callback records it (inline reject) and decides whether
* the handshake continues (us_verify_callback) or fails here. A ctx without a
* connection behind it (the QUIC client) has no callback and just fails. */
SSL *ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
int (*verify_cb)(int, X509_STORE_CTX *) = ssl ? SSL_get_verify_callback(ssl) : NULL;
return verify_cb ? verify_cb(0, ctx) : 0;
}

static int us_ssl_ctx_verify_cert(X509_STORE_CTX *ctx, void *arg) {
return us_internal_x509_verify_cert(ctx);
}

/* Drop the strdup'd passphrase. Called as soon as private-key load completes
* (the only consumer of the passwd_cb), so the secret never outlives ctx
* construction and SSL_CTX_free() is sufficient on every later path. Also
Expand Down Expand Up @@ -1110,6 +1168,10 @@ SSL_CTX *us_ssl_ctx_build_raw(struct us_bun_socket_context_options_t options,
/* Default options we rely on — changing these breaks the BIO logic. */
SSL_CTX_set_read_ahead(ssl_context, 1);
SSL_CTX_set_mode(ssl_context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
/* Peer chains (server certs on clients, client certs on servers) go through
* us_internal_x509_verify_cert; the verify modes and callbacks configured
* below and per socket keep deciding what happens with the result. */
SSL_CTX_set_cert_verify_callback(ssl_context, us_ssl_ctx_verify_cert, NULL);
/* BoringSSL ships with SSL_MODE_NO_AUTO_CHAIN set; Node clears it so a
* leaf-only `cert` presents the intermediates found in the context's store
* (crypto_context.cc#L1640). It only runs when the configured chain is 1. */
Expand Down Expand Up @@ -1683,12 +1745,23 @@ static long us_internal_verify_peer_certificate(const SSL *ssl, long def) {
return err;
}

/* OpenSSL's wording for its X509_V_ERR_{EE,CA}_KEY_TOO_SMALL, so the messages
* match node's. The code matches too: node has no name for these either and
* reports UNSPECIFIED, which is us_X509_error_code's default. */
static const char *us_X509_error_reason(long err) {
switch (err) {
case US_X509_V_ERR_EE_KEY_TOO_SMALL: return "EE certificate key too weak";
case US_X509_V_ERR_CA_KEY_TOO_SMALL: return "CA certificate key too weak";
}
return X509_verify_cert_error_string(err);
}

struct us_bun_verify_error_t us_ssl_socket_verify_error_from_ssl(SSL *ssl) {
long x509_verify_error =
us_internal_verify_peer_certificate(ssl, X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT);
if (x509_verify_error == X509_V_OK)
return (struct us_bun_verify_error_t){.error = 0, .code = NULL, .reason = NULL};
const char *reason = X509_verify_cert_error_string(x509_verify_error);
const char *reason = us_X509_error_reason(x509_verify_error);
const char *code = us_X509_error_code(x509_verify_error);
return (struct us_bun_verify_error_t){.error = x509_verify_error, .code = code, .reason = reason};
}
Expand Down
5 changes: 5 additions & 0 deletions packages/bun-usockets/src/internal/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,11 @@ void us_internal_listen_socket_ssl_free(struct us_listen_socket_t *ls);
/* Opaque SSL_CTX_up_ref/SSL_CTX_free so context.c needn't include OpenSSL. */
void us_internal_ssl_ctx_up_ref(struct ssl_ctx_st *ssl_ctx);
void us_internal_ssl_ctx_unref(struct ssl_ctx_st *ssl_ctx);
/* X509_verify_cert plus the chain policy BoringSSL's verifier lacks (minimum
* key sizes). Every peer chain, TCP or QUIC, must be verified through this so
* the policy applies uniformly; same contract as X509_verify_cert. */
struct x509_store_ctx_st;
int us_internal_x509_verify_cert(struct x509_store_ctx_st *ctx);
/* TCP-level FIN, bypassing the SSL layer (used by ssl_on_end). */
void us_internal_socket_raw_shutdown(us_socket_r s);

Expand Down
8 changes: 8 additions & 0 deletions packages/bun-usockets/src/libusockets.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,14 @@ struct us_bun_verify_error_t {
const char* reason;
};

/* Verify results uSockets adds on top of BoringSSL's X509_V_ERR_* values (which
* end at 67): the peer's chain verified, but the end-entity (EE) certificate or
* one of the CA certificates above it has a public key below the minimum size
* (see us_internal_x509_verify_cert in crypto/openssl.c). The numbers are
* mirrored by get_cert_error_from_no in src/http/lib.rs. */
#define US_X509_V_ERR_EE_KEY_TOO_SMALL 1001
#define US_X509_V_ERR_CA_KEY_TOO_SMALL 1002

/* Immutable callback table. ~20 instances total (one per kind), all static
* const / .rodata. Nullable entries are skipped by dispatch. */
struct us_socket_vtable_t {
Expand Down
6 changes: 3 additions & 3 deletions packages/bun-usockets/src/quic.c
Original file line number Diff line number Diff line change
Expand Up @@ -1157,8 +1157,8 @@ static enum ssl_verify_result_t us_quic_client_verify(SSL *ssl, uint8_t *out_ale
if (!qs) return ssl_verify_invalid;
if (!qs->reject_unauthorized) return ssl_verify_ok;

/* custom_verify bypasses BoringSSL's built-in chain check, so run
* X509_verify_cert against the SSL_CTX store ourselves, then match the
/* custom_verify bypasses BoringSSL's built-in chain check, so run the
* chain verification against the SSL_CTX store ourselves, then match the
* leaf against the SNI hostname. */
STACK_OF(X509) *chain = SSL_get_peer_full_cert_chain(ssl);
if (!chain || sk_X509_num(chain) == 0) return ssl_verify_invalid;
Expand All @@ -1169,7 +1169,7 @@ static enum ssl_verify_result_t us_quic_client_verify(SSL *ssl, uint8_t *out_ale
int ok = 0;
if (X509_STORE_CTX_init(vctx, store, leaf, chain) == 1) {
X509_STORE_CTX_set_default(vctx, "ssl_server");
ok = X509_verify_cert(vctx) == 1;
ok = us_internal_x509_verify_cert(vctx) == 1;
}
X509_STORE_CTX_free(vctx);
if (!ok) return ssl_verify_invalid;
Expand Down
4 changes: 4 additions & 0 deletions src/http/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,10 @@ pub enum CertError {
STORE_LOOKUP,
#[error("NAME_CONSTRAINTS_WITHOUT_SANS")]
NAME_CONSTRAINTS_WITHOUT_SANS,
#[error("EE_KEY_TOO_SMALL")]
EE_KEY_TOO_SMALL,
#[error("CA_KEY_TOO_SMALL")]
CA_KEY_TOO_SMALL,
#[error("UNKNOWN_CERTIFICATE_VERIFICATION_ERROR")]
UNKNOWN_CERTIFICATE_VERIFICATION_ERROR,
}
Expand Down
7 changes: 5 additions & 2 deletions src/http/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1512,8 +1512,9 @@ fn write_to_socket_with_buffer_fallback<const IS_SSL: bool>(
/// (e.g. `CERT_HAS_EXPIRED`). JS-side `error.code` matches on this exact
/// string, so do NOT substitute `X509_verify_cert_error_string` output here.
// constants are the BoringSSL `X509_V_ERR_*` values from
// `<openssl/x509.h>`. Inlined as literals so
// this file doesn't grow a dep on a header-generated const set.
// `<openssl/x509.h>`, plus uSockets' own `US_X509_V_ERR_*` (libusockets.h).
// Inlined as literals so this file doesn't grow a dep on a header-generated
// const set.
Comment thread
robobun marked this conversation as resolved.
Outdated
pub(crate) fn get_cert_error_from_no(error_no: i32) -> crate::Error {
use crate::error::CertError;
crate::Error::Cert(match error_no {
Expand Down Expand Up @@ -1583,6 +1584,8 @@ pub(crate) fn get_cert_error_from_no(error_no: i32) -> crate::Error {
65 => CertError::INVALID_CALL,
66 => CertError::STORE_LOOKUP,
67 => CertError::NAME_CONSTRAINTS_WITHOUT_SANS,
1001 => CertError::EE_KEY_TOO_SMALL,
1002 => CertError::CA_KEY_TOO_SMALL,
_ => CertError::UNKNOWN_CERTIFICATE_VERIFICATION_ERROR,
})
}
Expand Down
6 changes: 6 additions & 0 deletions src/runtime/webcore/fetch/FetchTasklet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1564,6 +1564,12 @@ impl FetchTasklet {
http::Error::Cert(http::CertError::NAME_CONSTRAINTS_WITHOUT_SANS) => {
BunString::static_("Issuer has name constraints but leaf has no SANs")
}
http::Error::Cert(http::CertError::EE_KEY_TOO_SMALL) => {
BunString::static_("EE certificate key too weak")
}
http::Error::Cert(http::CertError::CA_KEY_TOO_SMALL) => {
BunString::static_("CA certificate key too weak")
}
http::Error::Cert(http::CertError::UNKNOWN_CERTIFICATE_VERIFICATION_ERROR) => {
BunString::static_("unknown certificate verification error")
}
Expand Down
41 changes: 40 additions & 1 deletion test/js/node/tls/fetch-tls-cert.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { expect, it } from "bun:test";
import { describe, expect, it } from "bun:test";
import { readFileSync } from "fs";
import { once } from "node:events";
import tls from "node:tls";
Expand Down Expand Up @@ -277,6 +277,45 @@ it("Server sent their CA, wrongly, but its OK since we know the CA locally.", as
});
});

// Same chains as the "weak public key" tests in node-tls-cert.test.ts (which
// documents the fixtures): fetch names the failing certificate in its code where
// node:tls mirrors node's UNSPECIFIED.
describe("certificate chains containing a weak public key", () => {
const fixture = (name: string) => readFileSync(join(import.meta.dir, "fixtures", name), "utf8");
const root = fixture("weak-key-root-cert.pem");
const leafKey = fixture("weak-key-leaf-key.pem");

it("still fetches from a server whose chain is all RSA-2048", async () => {
await connect({
client: { ca: root },
server: { key: leafKey, cert: fixture("weak-key-ok-chain.pem") },
});
});

it.each([
[
"an RSA-512 intermediate CA",
{ key: leafKey, cert: fixture("weak-key-ca512-chain.pem") },
root,
{ code: "CA_KEY_TOO_SMALL", message: "CA certificate key too weak" },
],
[
"an RSA-1024 end-entity certificate",
{ key: fixture("weak-key-ee1024-key.pem"), cert: fixture("weak-key-ee1024-cert.pem") },
root,
{ code: "EE_KEY_TOO_SMALL", message: "EE certificate key too weak" },
],
[
"an RSA-1024 trust anchor",
{ key: leafKey, cert: fixture("weak-key-under-root1024-cert.pem") },
fixture("weak-key-root1024-cert.pem"),
{ code: "CA_KEY_TOO_SMALL", message: "CA certificate key too weak" },
],
])("rejects a server chain with %s", async (_, identity, ca, error) => {
await expect(connect({ client: { ca }, server: identity })).rejects.toMatchObject(error);
});
});

// Known gap: "BEGIN TRUSTED CERTIFICATE" PEM blocks aren't parsed as CA input, so
// the client cannot verify the server (UNABLE_TO_GET_ISSUER_CERT_LOCALLY).
it.todo('Confirm client support for "BEGIN TRUSTED CERTIFICATE".', async () => {
Expand Down
80 changes: 43 additions & 37 deletions test/js/node/tls/fixtures/agent10-cert.pem
Original file line number Diff line number Diff line change
@@ -1,41 +1,47 @@
-----BEGIN CERTIFICATE-----
MIIDjjCCAnagAwIBAgITMVaZ0eX5Kp8NI4vaKFVI592wTjANBgkqhkiG9w0BAQsF
ADCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEfMB0G
A1UECgwWVGhlIE5vZGUuanMgRm91bmRhdGlvbjEQMA4GA1UECwwHTm9kZS5qczEM
MAoGA1UEAwwDY2E0MR4wHAYJKoZIhvcNAQkBFg9jYTRAZXhhbXBsZS5vcmcwIBcN
MjIwOTAzMjE0MDM3WhgPMjI5NjA2MTcyMTQwMzdaMHgxCzAJBgNVBAYTAlVTMQsw
CQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxHzAdBgNVBAoMFlRoZSBOb2RlLmpzIEZv
dW5kYXRpb24xEDAOBgNVBAsMB05vZGUuanMxHDAaBgNVBAMME2FnZW50MTAuZXhh
bXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDP49yjMES5
1sfYG4ac06jR7DnSizMDgW+0V6CFPguv6p1D08aBA60mhY8+tjsbin3DYRiTB2HN
7C9svZ2cAffKK9W/40G6+jfJuB6I8g+LtdZ9hViw2RC0k4PFLzpG3VsJRpM4Wfos
/ubZqBuNGLN+K68sAFU0jbUra4dtJQXMi7SlFlJIUx2g10OF312uJcREfFVgNAw4
EIZ2H7bmGtpE0p3UfBir4HTy5nz4ruYCbbzNWDuX7RIGZSXtqaQc7P9QPvuLzspl
feI8S2oRTLRIgDEatXJFlIWzGu1kF7XjftOrnFHwRWICK6joqSzdLhSS02qfqIRF
JFVZ8QNq11bhAgMBAAEwDQYJKoZIhvcNAQELBQADggEBACenzaglCUisBHiI7H/v
tOF/75jxDUO8FmV3mksh33EpTmzoBiQD1DiTFQu/EEJ/iAbdTRJ1PVnJsMTFH0Bm
7SmkYOCpETleXjU1MwHZIvh/gGa/CjLZhop26FkK2oqENl7iaM9vvqxxQ8H4Niit
ay3cn+aB9o8MjTH9Ki9iH0LS6bwtqqRimXXX0sx3HTUnFxD/7tzE7s6t7ayk+rIJ
6mBeQAw3UjNzjtLTvSxHoPFto7z5imF+6/v236UlOTdQpkbRS1KlxA8wm/NisWeq
TLjPh5BkZof+CwTUoAFK+WILsIHuvVY9SZBNcsQvsBao/whRR2Z8bU1HDAh8jHnk
4wo=
MIIDijCCAnICFAa1gku/rBMKem53dr6+kaDTIvSCMA0GCSqGSIb3DQEBCwUAMIGI
MQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExCzAJBgNVBAcMAlNGMR8wHQYDVQQK
DBZUaGUgTm9kZS5qcyBGb3VuZGF0aW9uMRAwDgYDVQQLDAdOb2RlLmpzMQwwCgYD
VQQDDANjYTQxHjAcBgkqhkiG9w0BCQEWD2NhNEBleGFtcGxlLm9yZzAgFw0yNDA4
MjcyMjU4NDRaGA8yMjk4MDYxMTIyNTg0NFoweDELMAkGA1UEBhMCVVMxCzAJBgNV
BAgMAkNBMQswCQYDVQQHDAJTRjEfMB0GA1UECgwWVGhlIE5vZGUuanMgRm91bmRh
dGlvbjEQMA4GA1UECwwHTm9kZS5qczEcMBoGA1UEAwwTYWdlbnQxMC5leGFtcGxl
LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM/j3KMwRLnWx9gb
hpzTqNHsOdKLMwOBb7RXoIU+C6/qnUPTxoEDrSaFjz62OxuKfcNhGJMHYc3sL2y9
nZwB98or1b/jQbr6N8m4HojyD4u11n2FWLDZELSTg8UvOkbdWwlGkzhZ+iz+5tmo
G40Ys34rrywAVTSNtStrh20lBcyLtKUWUkhTHaDXQ4XfXa4lxER8VWA0DDgQhnYf
tuYa2kTSndR8GKvgdPLmfPiu5gJtvM1YO5ftEgZlJe2ppBzs/1A++4vOymV94jxL
ahFMtEiAMRq1ckWUhbMa7WQXteN+06ucUfBFYgIrqOipLN0uFJLTap+ohEUkVVnx
A2rXVuECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAy0rm8E+PR+ZuaQsz8Q3s0Y7I
fNICuwEyByMcwiwCjvMM2FwNZbnmagmSQ2eo+jD0GMAcBLS61AWhC8tPqO6DfFOj
7L07NYJWTKQMqAsv3n6Nl0uXd8Aa4iGDhsMeTZXXk4E/GsZZ8T4pDmE8TtY6285Y
ONU7uKKFcnIfQwtcEUnpwqSAYmQxKa+rhQ974rW3hBCxvtrwNRXsMjCoPyfkIuOz
9P6ThZfMWlmuKg852Yi2VglaOrxakQInQGz4Q0JHyROd/e9m3J+t/QFR9VqtRnX8
UEOlxD8iazk//VFd7WrO2jzqjXFIzBNrdvmsNsP+8uIjrGJtHdKeHL7v5V687A==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDFzCCAoCgAwIBAgIJAJHwBmNgafKfMA0GCSqGSIb3DQEBCwUAMHoxCzAJBgNV
BAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0YxDzANBgNVBAoMBkpveWVu
dDEQMA4GA1UECwwHTm9kZS5qczEMMAoGA1UEAwwDY2EyMSAwHgYJKoZIhvcNAQkB
FhFyeUB0aW55Y2xvdWRzLm9yZzAgFw0yMjA5MDMxNDQ2NTFaGA8yMjk2MDYxNzE0
NDY1MVowgYgxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTELMAkGA1UEBwwCU0Yx
HzAdBgNVBAoMFlRoZSBOb2RlLmpzIEZvdW5kYXRpb24xEDAOBgNVBAsMB05vZGUu
anMxDDAKBgNVBAMMA2NhNDEeMBwGCSqGSIb3DQEJARYPY2E0QGV4YW1wbGUub3Jn
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0HnUahyfA25t8kaziu0i
vVMkTWntm0pJ8oemeO7yCGaY4QHEwN+QUzrzO7y7ngl2Dt76eEvj0mrgaW8Ao7Ns
ePfp3663g8RrBsb4cR1da2Tc8kpXCqgwbcTlm8HI/7OAdHGA2YDLNv7iyVk9meHM
gYfO9dVgrZ7RxfnGwNMJdNjYJrd02xeU6euoKl9j/ZWCG5xHAM2xAXOKHGm8toIm
+Ss6iZXY8kypy7Fjwyv7jMT8V+pzIWu24xd3Y3s07r59nkFmQ29nHMTaLP7Tf3TY
MBI5mp8fet732aBoywpQ/w05LR9gdM1jpUvIlmhj4qGskv17AMEmRecwic3opq/b
yQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4GBADsFOR+N
Bcm2FyHOutoFpQn70qAFg0xlO3NTH87uubbs6rf3LDrsskhjskfs6wpUk56IJOoU
H7+F7aDDtSrnxzxxC5eZeGyaN05T5N01OdK3xvqUnr7mg/Ce0jnxrZhxHI8SHOqs
Kwrg4fRasUHGhH286Y13xOj2pLSrVoSbkXsA
MIIEaDCCA1CgAwIBAgIUDxaIwCfB2vttbQL/LlnVg4mwMUAwDQYJKoZIhvcNAQEL
BQAwejELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEPMA0G
A1UECgwGSm95ZW50MRAwDgYDVQQLDAdOb2RlLmpzMQwwCgYDVQQDDANjYTIxIDAe
BgkqhkiG9w0BCQEWEXJ5QHRpbnljbG91ZHMub3JnMCAXDTI0MDgyNzIyNTg0NFoY
DzIyOTgwNjExMjI1ODQ0WjCBiDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMQsw
CQYDVQQHDAJTRjEfMB0GA1UECgwWVGhlIE5vZGUuanMgRm91bmRhdGlvbjEQMA4G
A1UECwwHTm9kZS5qczEMMAoGA1UEAwwDY2E0MR4wHAYJKoZIhvcNAQkBFg9jYTRA
ZXhhbXBsZS5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDQedRq
HJ8Dbm3yRrOK7SK9UyRNae2bSknyh6Z47vIIZpjhAcTA35BTOvM7vLueCXYO3vp4
S+PSauBpbwCjs2x49+nfrreDxGsGxvhxHV1rZNzySlcKqDBtxOWbwcj/s4B0cYDZ
gMs2/uLJWT2Z4cyBh8711WCtntHF+cbA0wl02Ngmt3TbF5Tp66gqX2P9lYIbnEcA
zbEBc4ocaby2gib5KzqJldjyTKnLsWPDK/uMxPxX6nMha7bjF3djezTuvn2eQWZD
b2ccxNos/tN/dNgwEjmanx963vfZoGjLClD/DTktH2B0zWOlS8iWaGPioayS/XsA
wSZF5zCJzeimr9vJAgMBAAGjgdQwgdEwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQU
Tc8o3KouldTCYNQHvW09ZBv9sW0wgaEGA1UdIwSBmTCBlqF+pHwwejELMAkGA1UE
BhMCVVMxCzAJBgNVBAgMAkNBMQswCQYDVQQHDAJTRjEPMA0GA1UECgwGSm95ZW50
MRAwDgYDVQQLDAdOb2RlLmpzMQwwCgYDVQQDDANjYTIxIDAeBgkqhkiG9w0BCQEW
EXJ5QHRpbnljbG91ZHMub3JnghRsoeMhBMOB34RpWIz6SD/UwaqquzANBgkqhkiG
9w0BAQsFAAOCAQEAKtd7q+5123jVDzpydg4o3FO84u/1gzlkQ9gAc0q48/ePD/0g
GTeTLz3fODq84l0Nx0g2XbcnrnH/07dzykZokAI6TFhv9qioeMmZa5UhwLSFynXJ
tqP26jA2/dpofGrVV2up/dJ9nw/jmvsRTigvIjkPyofFyxyssNmUIOXgEB6szthQ
mg0VKqgcF3yPDFiSMNh7YnxKd6Rsw1uujtRR+dbkLJs3m0sk+MNra7+LIfqVU5Iv
UyieguUmYYtW9rWTjxVCEl84teryIFJK81GlX/wiq1Nx3DZj+DCSwJMdl5DDzvH8
EnE1L+MapqCnP0eAmNdWwF5SVxfKUwtt6uPpYw==
-----END CERTIFICATE-----
35 changes: 19 additions & 16 deletions test/js/node/tls/fixtures/agent3-cert.pem
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
-----BEGIN CERTIFICATE-----
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
-----END CERTIFICATE-----
Loading