"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.clearSecureContextCache = exports.cacheSecureContext = exports.getCachedSecureContext = exports.secureContextCacheKey = void 0;
// Cache of SecureContexts built by the patched createSecureContext for a given trust set.
// OpenSSL 3's provider-based decoder makes parsing a CA set expensive, and that cost is otherwise
// paid on every TLS connection because a fresh context is built each time. Reusing one context per
// distinct trust set is the mitigation OpenSSL itself recommends ("load once, use multiple times",
// https://github.com/openssl/openssl/discussions/22900).
//
// The trust set is whichever of the caller `ca` and the injected additional-CA array are present —
// both are stable references in practice: `ca` is proxy-agent's `systemCA` carried by a cached
// undici Agent, and the additional-CA array comes from getOrLoadAdditionalCertificates, which caches
// and reuses it. The context is keyed on those two references, then on a signature of the few other
// context-affecting options the cache is willing to key on. Anything else (per-identity key material,
// a string `ca` that can't be referenced, crl/dhparam/...) disqualifies caching, so those callers get
// a fresh context exactly as before. The WeakMaps let contexts for a dropped array be collected.
//
// Cached contexts are shared across connections and must never be mutated after they have been stored.
const absentCerts = {}; // sentinel WeakMap key standing in for an absent ca / additional-CA array
let cache = new WeakMap();
/**
 * Context-affecting options the cache keys on. They are scalar options a client might reasonably
 * set, so differing values simply produce distinct cache entries.
 */
const keyedContextOptions = ['secureProtocol', 'minVersion', 'maxVersion', 'ciphers', 'sigalgs', 'ecdhCurve', 'secureOptions', 'honorCipherOrder'];
/**
 * Options whose presence disqualifies caching. Per-identity key material is unsafe to share across
 * connections; the rest (crl, dhparam, ...) are rare enough that building a fresh context — the same
 * cost as without the cache — is the simpler, safer choice. The trust roots (`ca` and the injected
 * additional-CA set) are deliberately NOT here: they are the trust material the cache keys on.
 */
const disqualifyingContextOptions = ['cert', 'key', 'pfx', 'passphrase', 'clientCertEngine', 'privateKeyEngine', 'privateKeyIdentifier', 'ticketKeys', 'crl', 'dhparam', 'sessionIdContext', 'sessionTimeout', 'allowPartialTrustChain'];
/**
 * Computes the cache key for the given options, or undefined when they are not cacheable. Per-socket
 * options (servername, session, ALPNProtocols, rejectUnauthorized, ...) do not affect the
 * SecureContext and are deliberately ignored so they cannot split the cache.
 *
 * Callers compute this once and pass it to the lookup and store below, so the option scan is not
 * repeated; a defined result also means the request is cacheable.
 */
function secureContextCacheKey(details) {
    var _a, _b;
    const options = details;
    for (const option of disqualifyingContextOptions) {
        if (options[option] !== undefined) {
            return undefined;
        }
    }
    const ca = options['ca'];
    const additional = options['_vscodeAdditionalCaCerts'];
    // WeakMap keys must be objects, so a string `ca` (single PEM) can't be keyed on. Arrays and
    // Buffers are objects. Without any trust material there is nothing expensive to cache.
    if (ca !== undefined && typeof ca !== 'object') {
        return undefined;
    }
    if (additional !== undefined && typeof additional !== 'object') {
        return undefined;
    }
    if (ca === undefined && additional === undefined) {
        return undefined;
    }
    const parts = [];
    for (const option of keyedContextOptions) {
        const value = options[option];
        if (value !== undefined && typeof value === 'object') {
            return undefined;
        }
        parts.push(value === undefined ? '' : String(value));
    }
    return {
        caKey: (_a = ca) !== null && _a !== void 0 ? _a : absentCerts,
        additionalKey: (_b = additional) !== null && _b !== void 0 ? _b : absentCerts,
        signature: parts.join('|'),
    };
}
exports.secureContextCacheKey = secureContextCacheKey;
/**
 * Returns the cached SecureContext for the given key, or undefined when nothing is stored for it yet.
 */
function getCachedSecureContext(key) {
    var _a, _b;
    return (_b = (_a = cache.get(key.caKey)) === null || _a === void 0 ? void 0 : _a.get(key.additionalKey)) === null || _b === void 0 ? void 0 : _b.get(key.signature);
}
exports.getCachedSecureContext = getCachedSecureContext;
/**
 * Stores a SecureContext under the given key. The context is shared with every later cache hit, so it
 * must not be mutated after being stored.
 */
function cacheSecureContext(key, context) {
    let byAdditional = cache.get(key.caKey);
    if (!byAdditional) {
        byAdditional = new WeakMap();
        cache.set(key.caKey, byAdditional);
    }
    let bySignature = byAdditional.get(key.additionalKey);
    if (!bySignature) {
        bySignature = new Map();
        byAdditional.set(key.additionalKey, bySignature);
    }
    bySignature.set(key.signature, context);
}
exports.cacheSecureContext = cacheSecureContext;
/**
 * Drops all cached SecureContexts. Called from resetCaches() so contexts built for a previous
 * certificate set cannot outlive it.
 */
function clearSecureContextCache() {
    cache = new WeakMap();
}
exports.clearSecureContextCache = clearSecureContextCache;//# sourceMappingURL=http://go/sourcemap/sourcemaps/31e8d61c448c7472e371505838a0fe34083dad50/node_modules/@vscode/proxy-agent/out/secureContextCache.js.map