/* Copyright (c) 2003, Roger Dingledine.
* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
* Copyright (c) 2007-2019, The Tor Project, Inc. */
/* See LICENSE for licensing information */
/**
* \file tortls_nss.c
* \brief Wrapper functions to present a consistent interface to
* TLS and SSL X.509 functions from NSS.
**/
#include "orconfig.h"
#define TORTLS_PRIVATE
#define TOR_X509_PRIVATE
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#endif
#include "lib/crypt_ops/crypto_cipher.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "lib/crypt_ops/crypto_dh.h"
#include "lib/crypt_ops/crypto_util.h"
#include "lib/crypt_ops/crypto_nss_mgt.h"
#include "lib/string/printf.h"
#include "lib/tls/x509.h"
#include "lib/tls/x509_internal.h"
#include "lib/tls/tortls.h"
#include "lib/tls/tortls_st.h"
#include "lib/tls/tortls_internal.h"
#include "lib/tls/nss_countbytes.h"
#include "lib/log/util_bug.h"
DISABLE_GCC_WARNING(strict-prototypes)
#include <prio.h>
// For access to rar sockets.
#include <private/pprio.h>
#include <ssl.h>
#include <sslt.h>
#include <sslproto.h>
#include <certt.h>
ENABLE_GCC_WARNING(strict-prototypes)
static SECStatus always_accept_cert_cb(void *, PRFileDesc *, PRBool, PRBool);
MOCK_IMPL(void,
try_to_extract_certs_from_tls,(int severity, tor_tls_t *tls,
tor_x509_cert_impl_t **cert_out,
tor_x509_cert_impl_t **id_cert_out))
{
tor_assert(tls);
tor_assert(cert_out);
tor_assert(id_cert_out);
(void) severity;
*cert_out = *id_cert_out = NULL;
CERTCertificate *peer = SSL_PeerCertificate(tls->ssl);
if (!peer)
return;
*cert_out = peer; /* Now owns pointer. */
CERTCertList *chain = SSL_PeerCertificateChain(tls->ssl);
CERTCertListNode *c = CERT_LIST_HEAD(chain);
for (; !CERT_LIST_END(c, chain); c = CERT_LIST_NEXT(c)) {
if (CERT_CompareCerts(c->cert, peer) == PR_FALSE) {
*id_cert_out = CERT_DupCertificate(c->cert);
break;
}
}
CERT_DestroyCertList(chain);
}
static bool
we_like_ssl_cipher(SSLCipherAlgorithm ca)
{
switch (ca) {
case ssl_calg_null: return false;
case ssl_calg_rc4: return false;
case ssl_calg_rc2: return false;
case ssl_calg_des: return false;
case ssl_calg_3des: return false; /* ???? */
case ssl_calg_idea: return false;
case ssl_calg_fortezza: return false;
case ssl_calg_camellia: return false;
case ssl_calg_seed: return false;
case ssl_calg_aes: return true;
case ssl_calg_aes_gcm: return true;
case ssl_calg_chacha20: return true;
default: return true;
}
}
static bool
we_like_ssl_kea(SSLKEAType kt)
{
switch (kt) {
case ssl_kea_null: return false;
case ssl_kea_rsa: return false; /* ??? */
case ssl_kea_fortezza: return false;
case ssl_kea_ecdh_psk: return false;
case ssl_kea_dh_psk: return false;
case ssl_kea_dh: return true;
case ssl_kea_ecdh: return true;
case ssl_kea_tls13_any: return true;
case ssl_kea_size: return true; /* prevent a warning. */
default: return true;
}
}
static bool
we_like_mac_algorithm(SSLMACAlgorithm ma)
{
switch (ma) {
case ssl_mac_null: return false;
case ssl_mac_md5: return false;
case ssl_hmac_md5: return false;
case ssl_mac_sha: return true;
case ssl_hmac_sha: return true;
case ssl_hmac_sha256: return true;
case ssl_mac_aead: return true;
case ssl_hmac_sha384: return true;
default: return true;
}
}
static bool
we_like_auth_type(SSLAuthType at)
{
switch (at) {
case ssl_auth_null: return false;
case ssl_auth_rsa_decrypt: return false;
case ssl_auth_dsa: return false;
case ssl_auth_kea: return false;
case ssl_auth_ecdsa: return true;
case ssl_auth_ecdh_rsa: return true;
case ssl_auth_ecdh_ecdsa: return true;
case ssl_auth_rsa_sign: return true;
case ssl_auth_rsa_pss: return true;
case ssl_auth_psk: return true;
case ssl_auth_tls13_any: return true;
case ssl_auth_size: return true; /* prevent a warning. */
default: return true;
}
}
/**
* Return true iff this ciphersuite will be hit by a mozilla bug 1312976,
* which makes TLS key exporters not work with TLS 1.2 non-SHA256
* ciphersuites.
**/
static bool
ciphersuite_has_nss_export_bug(const SSLCipherSuiteInfo