Source code

Revision control

Other Tools

/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* SSL3 Protocol
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* TODO(ekr): Implement HelloVerifyRequest on server side. OK for now. */
#include "cert.h"
#include "ssl.h"
#include "cryptohi.h" /* for DSAU_ stuff */
#include "keyhi.h"
#include "secder.h"
#include "secitem.h"
#include "sechash.h"
#include "sslimpl.h"
#include "sslproto.h"
#include "sslerr.h"
#include "ssl3ext.h"
#include "ssl3exthandle.h"
#include "tls13ech.h"
#include "tls13exthandle.h"
#include "tls13psk.h"
#include "tls13subcerts.h"
#include "prtime.h"
#include "prinrval.h"
#include "prerror.h"
#include "pratom.h"
#include "prthread.h"
#include "nss.h"
#include "nssoptions.h"
#include "pk11func.h"
#include "secmod.h"
#include "blapi.h"
#include <stdio.h>
static PK11SymKey *ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec,
PK11SlotInfo *serverKeySlot);
static SECStatus ssl3_ComputeMasterSecret(sslSocket *ss, PK11SymKey *pms,
PK11SymKey **msp);
static SECStatus ssl3_DeriveConnectionKeys(sslSocket *ss,
PK11SymKey *masterSecret);
static SECStatus ssl3_HandshakeFailure(sslSocket *ss);
static SECStatus ssl3_SendCertificate(sslSocket *ss);
static SECStatus ssl3_SendCertificateRequest(sslSocket *ss);
static SECStatus ssl3_SendNextProto(sslSocket *ss);
static SECStatus ssl3_SendFinished(sslSocket *ss, PRInt32 flags);
static SECStatus ssl3_SendServerHelloDone(sslSocket *ss);
static SECStatus ssl3_SendServerKeyExchange(sslSocket *ss);
static SECStatus ssl3_HandleClientHelloPart2(sslSocket *ss,
SECItem *suites,
sslSessionID *sid,
const PRUint8 *msg,
unsigned int len);
static SECStatus ssl3_HandleServerHelloPart2(sslSocket *ss,
const SECItem *sidBytes,
int *retErrCode);
static SECStatus ssl3_HandlePostHelloHandshakeMessage(sslSocket *ss,
PRUint8 *b,
PRUint32 length);
static SECStatus ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags);
static CK_MECHANISM_TYPE ssl3_GetHashMechanismByHashType(SSLHashType hashType);
static CK_MECHANISM_TYPE ssl3_GetMgfMechanismByHashType(SSLHashType hash);
PRBool ssl_IsRsaPssSignatureScheme(SSLSignatureScheme scheme);
PRBool ssl_IsRsaeSignatureScheme(SSLSignatureScheme scheme);
PRBool ssl_IsRsaPkcs1SignatureScheme(SSLSignatureScheme scheme);
PRBool ssl_IsDsaSignatureScheme(SSLSignatureScheme scheme);
static SECStatus ssl3_UpdateDefaultHandshakeHashes(sslSocket *ss,
const unsigned char *b,
unsigned int l);
const PRUint8 ssl_hello_retry_random[] = {
0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11,
0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91,
0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E,
0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C
};
PR_STATIC_ASSERT(PR_ARRAY_SIZE(ssl_hello_retry_random) == SSL3_RANDOM_LENGTH);
/* This list of SSL3 cipher suites is sorted in descending order of
* precedence (desirability). It only includes cipher suites we implement.
* This table is modified by SSL3_SetPolicy(). The ordering of cipher suites
* in this table must match the ordering in SSL_ImplementedCiphers (sslenum.c)
*
* Important: See bug 946147 before enabling, reordering, or adding any cipher
* suites to this list.
*/
/* clang-format off */
static ssl3CipherSuiteCfg cipherSuites[ssl_V3_SUITES_IMPLEMENTED] = {
/* cipher_suite policy enabled isPresent */
/* Special TLS 1.3 suites. */
{ TLS_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE },
{ TLS_CHACHA20_POLY1305_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE },
{ TLS_AES_256_GCM_SHA384, SSL_ALLOWED, PR_TRUE, PR_FALSE },
{ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, SSL_ALLOWED, PR_TRUE, PR_FALSE},
/* TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA is out of order to work around
*/
{ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_ECDHE_RSA_WITH_RC4_128_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,SSL_ALLOWED,PR_TRUE, PR_FALSE},
{ TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_DHE_RSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_DHE_RSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_DHE_DSS_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_DHE_DSS_WITH_RC4_128_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_ECDH_ECDSA_WITH_RC4_128_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_ECDH_RSA_WITH_RC4_128_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
/* RSA */
{ TLS_RSA_WITH_AES_128_GCM_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_RSA_WITH_AES_256_GCM_SHA384, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_RSA_WITH_AES_128_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_RSA_WITH_AES_128_CBC_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_RSA_WITH_AES_256_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_RSA_WITH_AES_256_CBC_SHA256, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_RSA_WITH_SEED_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_RSA_WITH_3DES_EDE_CBC_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_RSA_WITH_RC4_128_SHA, SSL_ALLOWED, PR_TRUE, PR_FALSE},
{ TLS_RSA_WITH_RC4_128_MD5, SSL_ALLOWED, PR_TRUE, PR_FALSE},
/* 56-bit DES "domestic" cipher suites */
{ TLS_DHE_RSA_WITH_DES_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_DHE_DSS_WITH_DES_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_RSA_WITH_DES_CBC_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
/* ciphersuites with no encryption */
{ TLS_ECDHE_ECDSA_WITH_NULL_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_ECDHE_RSA_WITH_NULL_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_ECDH_RSA_WITH_NULL_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_ECDH_ECDSA_WITH_NULL_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_RSA_WITH_NULL_SHA, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_RSA_WITH_NULL_SHA256, SSL_ALLOWED, PR_FALSE, PR_FALSE},
{ TLS_RSA_WITH_NULL_MD5, SSL_ALLOWED, PR_FALSE, PR_FALSE},
};
/* clang-format on */
/* This is the default supported set of signature schemes. The order of the
* hashes here is all that is important, since that will (sometimes) determine
* which hash we use. The key pair (i.e., cert) is the primary thing that
* determines what we use and this doesn't affect how we select key pairs. The
* order of signature types is based on the same rules for ordering we use for
* cipher suites just for consistency.
*/
static const SSLSignatureScheme defaultSignatureSchemes[] = {
ssl_sig_ecdsa_secp256r1_sha256,
ssl_sig_ecdsa_secp384r1_sha384,
ssl_sig_ecdsa_secp521r1_sha512,
ssl_sig_ecdsa_sha1,
ssl_sig_rsa_pss_rsae_sha256,
ssl_sig_rsa_pss_rsae_sha384,
ssl_sig_rsa_pss_rsae_sha512,
ssl_sig_rsa_pkcs1_sha256,
ssl_sig_rsa_pkcs1_sha384,
ssl_sig_rsa_pkcs1_sha512,
ssl_sig_rsa_pkcs1_sha1,
ssl_sig_dsa_sha256,
ssl_sig_dsa_sha384,
ssl_sig_dsa_sha512,
ssl_sig_dsa_sha1
};
PR_STATIC_ASSERT(PR_ARRAY_SIZE(defaultSignatureSchemes) <=
MAX_SIGNATURE_SCHEMES);
/* Verify that SSL_ImplementedCiphers and cipherSuites are in consistent order.
*/
#ifdef DEBUG
void
ssl3_CheckCipherSuiteOrderConsistency()
{
unsigned int i;
PORT_Assert(SSL_NumImplementedCiphers == PR_ARRAY_SIZE(cipherSuites));
for (i = 0; i < PR_ARRAY_SIZE(cipherSuites); ++i) {
PORT_Assert(SSL_ImplementedCiphers[i] == cipherSuites[i].cipher_suite);
}
}
#endif
static const /*SSL3ClientCertificateType */ PRUint8 certificate_types[] = {
ct_RSA_sign,
ct_ECDSA_sign,
ct_DSS_sign,
};
static SSL3Statistics ssl3stats;
static const ssl3KEADef kea_defs[] =
{
/* indexed by SSL3KeyExchangeAlgorithm */
/* kea exchKeyType signKeyType authKeyType ephemeral oid */
{ kea_null, ssl_kea_null, nullKey, ssl_auth_null, PR_FALSE, 0 },
{ kea_rsa, ssl_kea_rsa, nullKey, ssl_auth_rsa_decrypt, PR_FALSE, SEC_OID_TLS_RSA },
{ kea_dh_dss, ssl_kea_dh, dsaKey, ssl_auth_dsa, PR_FALSE, SEC_OID_TLS_DH_DSS },
{ kea_dh_rsa, ssl_kea_dh, rsaKey, ssl_auth_rsa_sign, PR_FALSE, SEC_OID_TLS_DH_RSA },
{ kea_dhe_dss, ssl_kea_dh, dsaKey, ssl_auth_dsa, PR_TRUE, SEC_OID_TLS_DHE_DSS },
{ kea_dhe_rsa, ssl_kea_dh, rsaKey, ssl_auth_rsa_sign, PR_TRUE, SEC_OID_TLS_DHE_RSA },
{ kea_dh_anon, ssl_kea_dh, nullKey, ssl_auth_null, PR_TRUE, SEC_OID_TLS_DH_ANON },
{ kea_ecdh_ecdsa, ssl_kea_ecdh, nullKey, ssl_auth_ecdh_ecdsa, PR_FALSE, SEC_OID_TLS_ECDH_ECDSA },
{ kea_ecdhe_ecdsa, ssl_kea_ecdh, ecKey, ssl_auth_ecdsa, PR_TRUE, SEC_OID_TLS_ECDHE_ECDSA },
{ kea_ecdh_rsa, ssl_kea_ecdh, nullKey, ssl_auth_ecdh_rsa, PR_FALSE, SEC_OID_TLS_ECDH_RSA },
{ kea_ecdhe_rsa, ssl_kea_ecdh, rsaKey, ssl_auth_rsa_sign, PR_TRUE, SEC_OID_TLS_ECDHE_RSA },
{ kea_ecdh_anon, ssl_kea_ecdh, nullKey, ssl_auth_null, PR_TRUE, SEC_OID_TLS_ECDH_ANON },
{ kea_ecdhe_psk, ssl_kea_ecdh_psk, nullKey, ssl_auth_psk, PR_TRUE, SEC_OID_TLS_ECDHE_PSK },
{ kea_dhe_psk, ssl_kea_dh_psk, nullKey, ssl_auth_psk, PR_TRUE, SEC_OID_TLS_DHE_PSK },
{ kea_tls13_any, ssl_kea_tls13_any, nullKey, ssl_auth_tls13_any, PR_TRUE, SEC_OID_TLS13_KEA_ANY },
};
/* must use ssl_LookupCipherSuiteDef to access */
static const ssl3CipherSuiteDef cipher_suite_defs[] =
{
/* cipher_suite bulk_cipher_alg mac_alg key_exchange_alg prf_hash */
/* Note that the prf_hash_alg is the hash function used by the PRF, see sslimpl.h. */
{ TLS_NULL_WITH_NULL_NULL, cipher_null, ssl_mac_null, kea_null, ssl_hash_none },
{ TLS_RSA_WITH_NULL_MD5, cipher_null, ssl_mac_md5, kea_rsa, ssl_hash_none },
{ TLS_RSA_WITH_NULL_SHA, cipher_null, ssl_mac_sha, kea_rsa, ssl_hash_none },
{ TLS_RSA_WITH_NULL_SHA256, cipher_null, ssl_hmac_sha256, kea_rsa, ssl_hash_sha256 },
{ TLS_RSA_WITH_RC4_128_MD5, cipher_rc4, ssl_mac_md5, kea_rsa, ssl_hash_none },
{ TLS_RSA_WITH_RC4_128_SHA, cipher_rc4, ssl_mac_sha, kea_rsa, ssl_hash_none },
{ TLS_RSA_WITH_DES_CBC_SHA, cipher_des, ssl_mac_sha, kea_rsa, ssl_hash_none },
{ TLS_RSA_WITH_3DES_EDE_CBC_SHA, cipher_3des, ssl_mac_sha, kea_rsa, ssl_hash_none },
{ TLS_DHE_DSS_WITH_DES_CBC_SHA, cipher_des, ssl_mac_sha, kea_dhe_dss, ssl_hash_none },
{ TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
cipher_3des, ssl_mac_sha, kea_dhe_dss, ssl_hash_none },
{ TLS_DHE_DSS_WITH_RC4_128_SHA, cipher_rc4, ssl_mac_sha, kea_dhe_dss, ssl_hash_none },
{ TLS_DHE_RSA_WITH_DES_CBC_SHA, cipher_des, ssl_mac_sha, kea_dhe_rsa, ssl_hash_none },
{ TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
cipher_3des, ssl_mac_sha, kea_dhe_rsa, ssl_hash_none },
/* New TLS cipher suites */
{ TLS_RSA_WITH_AES_128_CBC_SHA, cipher_aes_128, ssl_mac_sha, kea_rsa, ssl_hash_none },
{ TLS_RSA_WITH_AES_128_CBC_SHA256, cipher_aes_128, ssl_hmac_sha256, kea_rsa, ssl_hash_sha256 },
{ TLS_DHE_DSS_WITH_AES_128_CBC_SHA, cipher_aes_128, ssl_mac_sha, kea_dhe_dss, ssl_hash_none },
{ TLS_DHE_RSA_WITH_AES_128_CBC_SHA, cipher_aes_128, ssl_mac_sha, kea_dhe_rsa, ssl_hash_none },
{ TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, cipher_aes_128, ssl_hmac_sha256, kea_dhe_rsa, ssl_hash_sha256 },
{ TLS_RSA_WITH_AES_256_CBC_SHA, cipher_aes_256, ssl_mac_sha, kea_rsa, ssl_hash_none },
{ TLS_RSA_WITH_AES_256_CBC_SHA256, cipher_aes_256, ssl_hmac_sha256, kea_rsa, ssl_hash_sha256 },
{ TLS_DHE_DSS_WITH_AES_256_CBC_SHA, cipher_aes_256, ssl_mac_sha, kea_dhe_dss, ssl_hash_none },
{ TLS_DHE_RSA_WITH_AES_256_CBC_SHA, cipher_aes_256, ssl_mac_sha, kea_dhe_rsa, ssl_hash_none },
{ TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, cipher_aes_256, ssl_hmac_sha256, kea_dhe_rsa, ssl_hash_sha256 },
{ TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, cipher_aes_256_gcm, ssl_mac_aead, kea_dhe_rsa, ssl_hash_sha384 },
{ TLS_RSA_WITH_SEED_CBC_SHA, cipher_seed, ssl_mac_sha, kea_rsa, ssl_hash_none },
{ TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, cipher_camellia_128, ssl_mac_sha, kea_rsa, ssl_hash_none },
{ TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA,
cipher_camellia_128, ssl_mac_sha, kea_dhe_dss, ssl_hash_none },
{ TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
cipher_camellia_128, ssl_mac_sha, kea_dhe_rsa, ssl_hash_none },
{ TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, cipher_camellia_256, ssl_mac_sha, kea_rsa, ssl_hash_none },
{ TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA,
cipher_camellia_256, ssl_mac_sha, kea_dhe_dss, ssl_hash_none },
{ TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
cipher_camellia_256, ssl_mac_sha, kea_dhe_rsa, ssl_hash_none },
{ TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, ssl_mac_aead, kea_dhe_rsa, ssl_hash_sha256 },
{ TLS_RSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, ssl_mac_aead, kea_rsa, ssl_hash_sha256 },
{ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, ssl_mac_aead, kea_ecdhe_rsa, ssl_hash_sha256 },
{ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, ssl_mac_aead, kea_ecdhe_ecdsa, ssl_hash_sha256 },
{ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, cipher_aes_256_gcm, ssl_mac_aead, kea_ecdhe_ecdsa, ssl_hash_sha384 },
{ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, cipher_aes_256_gcm, ssl_mac_aead, kea_ecdhe_rsa, ssl_hash_sha384 },
{ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, cipher_aes_256, ssl_hmac_sha384, kea_ecdhe_ecdsa, ssl_hash_sha384 },
{ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, cipher_aes_256, ssl_hmac_sha384, kea_ecdhe_rsa, ssl_hash_sha384 },
{ TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, cipher_aes_128_gcm, ssl_mac_aead, kea_dhe_dss, ssl_hash_sha256 },
{ TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, cipher_aes_128, ssl_hmac_sha256, kea_dhe_dss, ssl_hash_sha256 },
{ TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, cipher_aes_256, ssl_hmac_sha256, kea_dhe_dss, ssl_hash_sha256 },
{ TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, cipher_aes_256_gcm, ssl_mac_aead, kea_dhe_dss, ssl_hash_sha384 },
{ TLS_RSA_WITH_AES_256_GCM_SHA384, cipher_aes_256_gcm, ssl_mac_aead, kea_rsa, ssl_hash_sha384 },
{ TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, cipher_chacha20, ssl_mac_aead, kea_dhe_rsa, ssl_hash_sha256 },
{ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, cipher_chacha20, ssl_mac_aead, kea_ecdhe_rsa, ssl_hash_sha256 },
{ TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, cipher_chacha20, ssl_mac_aead, kea_ecdhe_ecdsa, ssl_hash_sha256 },
{ TLS_ECDH_ECDSA_WITH_NULL_SHA, cipher_null, ssl_mac_sha, kea_ecdh_ecdsa, ssl_hash_none },
{ TLS_ECDH_ECDSA_WITH_RC4_128_SHA, cipher_rc4, ssl_mac_sha, kea_ecdh_ecdsa, ssl_hash_none },
{ TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, cipher_3des, ssl_mac_sha, kea_ecdh_ecdsa, ssl_hash_none },
{ TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, cipher_aes_128, ssl_mac_sha, kea_ecdh_ecdsa, ssl_hash_none },
{ TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, cipher_aes_256, ssl_mac_sha, kea_ecdh_ecdsa, ssl_hash_none },
{ TLS_ECDHE_ECDSA_WITH_NULL_SHA, cipher_null, ssl_mac_sha, kea_ecdhe_ecdsa, ssl_hash_none },
{ TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, cipher_rc4, ssl_mac_sha, kea_ecdhe_ecdsa, ssl_hash_none },
{ TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, cipher_3des, ssl_mac_sha, kea_ecdhe_ecdsa, ssl_hash_none },
{ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, cipher_aes_128, ssl_mac_sha, kea_ecdhe_ecdsa, ssl_hash_none },
{ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, cipher_aes_128, ssl_hmac_sha256, kea_ecdhe_ecdsa, ssl_hash_sha256 },
{ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, cipher_aes_256, ssl_mac_sha, kea_ecdhe_ecdsa, ssl_hash_none },
{ TLS_ECDH_RSA_WITH_NULL_SHA, cipher_null, ssl_mac_sha, kea_ecdh_rsa, ssl_hash_none },
{ TLS_ECDH_RSA_WITH_RC4_128_SHA, cipher_rc4, ssl_mac_sha, kea_ecdh_rsa, ssl_hash_none },
{ TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, cipher_3des, ssl_mac_sha, kea_ecdh_rsa, ssl_hash_none },
{ TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, cipher_aes_128, ssl_mac_sha, kea_ecdh_rsa, ssl_hash_none },
{ TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, cipher_aes_256, ssl_mac_sha, kea_ecdh_rsa, ssl_hash_none },
{ TLS_ECDHE_RSA_WITH_NULL_SHA, cipher_null, ssl_mac_sha, kea_ecdhe_rsa, ssl_hash_none },
{ TLS_ECDHE_RSA_WITH_RC4_128_SHA, cipher_rc4, ssl_mac_sha, kea_ecdhe_rsa, ssl_hash_none },
{ TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, cipher_3des, ssl_mac_sha, kea_ecdhe_rsa, ssl_hash_none },
{ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, cipher_aes_128, ssl_mac_sha, kea_ecdhe_rsa, ssl_hash_none },
{ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, cipher_aes_128, ssl_hmac_sha256, kea_ecdhe_rsa, ssl_hash_sha256 },
{ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, cipher_aes_256, ssl_mac_sha, kea_ecdhe_rsa, ssl_hash_none },
{ TLS_AES_128_GCM_SHA256, cipher_aes_128_gcm, ssl_mac_aead, kea_tls13_any, ssl_hash_sha256 },
{ TLS_CHACHA20_POLY1305_SHA256, cipher_chacha20, ssl_mac_aead, kea_tls13_any, ssl_hash_sha256 },
{ TLS_AES_256_GCM_SHA384, cipher_aes_256_gcm, ssl_mac_aead, kea_tls13_any, ssl_hash_sha384 },
};
static const CK_MECHANISM_TYPE auth_alg_defs[] = {
CKM_INVALID_MECHANISM, /* ssl_auth_null */
CKM_RSA_PKCS, /* ssl_auth_rsa_decrypt */
CKM_DSA, /* ? _SHA1 */ /* ssl_auth_dsa */
CKM_INVALID_MECHANISM, /* ssl_auth_kea (unused) */
CKM_ECDSA, /* ssl_auth_ecdsa */
CKM_ECDH1_DERIVE, /* ssl_auth_ecdh_rsa */
CKM_ECDH1_DERIVE, /* ssl_auth_ecdh_ecdsa */
CKM_RSA_PKCS, /* ssl_auth_rsa_sign */
CKM_RSA_PKCS_PSS, /* ssl_auth_rsa_pss */
CKM_NSS_HKDF_SHA256, /* ssl_auth_psk (just check for HKDF) */
CKM_INVALID_MECHANISM /* ssl_auth_tls13_any */
};
PR_STATIC_ASSERT(PR_ARRAY_SIZE(auth_alg_defs) == ssl_auth_size);
static const CK_MECHANISM_TYPE kea_alg_defs[] = {
CKM_INVALID_MECHANISM, /* ssl_kea_null */
CKM_RSA_PKCS, /* ssl_kea_rsa */
CKM_DH_PKCS_DERIVE, /* ssl_kea_dh */
CKM_INVALID_MECHANISM, /* ssl_kea_fortezza (unused) */
CKM_ECDH1_DERIVE, /* ssl_kea_ecdh */
CKM_ECDH1_DERIVE, /* ssl_kea_ecdh_psk */
CKM_DH_PKCS_DERIVE, /* ssl_kea_dh_psk */
CKM_INVALID_MECHANISM, /* ssl_kea_tls13_any */
};
PR_STATIC_ASSERT(PR_ARRAY_SIZE(kea_alg_defs) == ssl_kea_size);
typedef struct SSLCipher2MechStr {
SSLCipherAlgorithm calg;
CK_MECHANISM_TYPE cmech;
} SSLCipher2Mech;
/* indexed by type SSLCipherAlgorithm */
static const SSLCipher2Mech alg2Mech[] = {
/* calg, cmech */
{ ssl_calg_null, CKM_INVALID_MECHANISM },
{ ssl_calg_rc4, CKM_RC4 },
{ ssl_calg_rc2, CKM_RC2_CBC },
{ ssl_calg_des, CKM_DES_CBC },
{ ssl_calg_3des, CKM_DES3_CBC },
{ ssl_calg_idea, CKM_IDEA_CBC },
{ ssl_calg_fortezza, CKM_SKIPJACK_CBC64 },
{ ssl_calg_aes, CKM_AES_CBC },
{ ssl_calg_camellia, CKM_CAMELLIA_CBC },
{ ssl_calg_seed, CKM_SEED_CBC },
{ ssl_calg_aes_gcm, CKM_AES_GCM },
{ ssl_calg_chacha20, CKM_CHACHA20_POLY1305 },
};
const PRUint8 tls12_downgrade_random[] = { 0x44, 0x4F, 0x57, 0x4E,
0x47, 0x52, 0x44, 0x01 };
const PRUint8 tls1_downgrade_random[] = { 0x44, 0x4F, 0x57, 0x4E,
0x47, 0x52, 0x44, 0x00 };
PR_STATIC_ASSERT(sizeof(tls12_downgrade_random) ==
sizeof(tls1_downgrade_random));
/* The ECCWrappedKeyInfo structure defines how various pieces of
* information are laid out within wrappedSymmetricWrappingkey
* for ECDH key exchange. Since wrappedSymmetricWrappingkey is
* a 512-byte buffer (see sslimpl.h), the variable length field
* in ECCWrappedKeyInfo can be at most (512 - 8) = 504 bytes.
*
* XXX For now, NSS only supports named elliptic curves of size 571 bits
* or smaller. The public value will fit within 145 bytes and EC params
* will fit within 12 bytes. We'll need to revisit this when NSS
* supports arbitrary curves.
*/
#define MAX_EC_WRAPPED_KEY_BUFLEN 504
typedef struct ECCWrappedKeyInfoStr {
PRUint16 size; /* EC public key size in bits */
PRUint16 encodedParamLen; /* length (in bytes) of DER encoded EC params */
PRUint16 pubValueLen; /* length (in bytes) of EC public value */
PRUint16 wrappedKeyLen; /* length (in bytes) of the wrapped key */
PRUint8 var[MAX_EC_WRAPPED_KEY_BUFLEN]; /* this buffer contains the */
/* EC public-key params, the EC public value and the wrapped key */
} ECCWrappedKeyInfo;
CK_MECHANISM_TYPE
ssl3_Alg2Mech(SSLCipherAlgorithm calg)
{
PORT_Assert(alg2Mech[calg].calg == calg);
return alg2Mech[calg].cmech;
}
#if defined(TRACE)
static char *
ssl3_DecodeHandshakeType(int msgType)
{
char *rv;
static char line[40];
switch (msgType) {
case ssl_hs_hello_request:
rv = "hello_request (0)";
break;
case ssl_hs_client_hello:
rv = "client_hello (1)";
break;
case ssl_hs_server_hello:
rv = "server_hello (2)";
break;
case ssl_hs_hello_verify_request:
rv = "hello_verify_request (3)";
break;
case ssl_hs_new_session_ticket:
rv = "new_session_ticket (4)";
break;
case ssl_hs_end_of_early_data:
rv = "end_of_early_data (5)";
break;
case ssl_hs_hello_retry_request:
rv = "hello_retry_request (6)";
break;
case ssl_hs_encrypted_extensions:
rv = "encrypted_extensions (8)";
break;
case ssl_hs_certificate:
rv = "certificate (11)";
break;
case ssl_hs_server_key_exchange:
rv = "server_key_exchange (12)";
break;
case ssl_hs_certificate_request:
rv = "certificate_request (13)";
break;
case ssl_hs_server_hello_done:
rv = "server_hello_done (14)";
break;
case ssl_hs_certificate_verify:
rv = "certificate_verify (15)";
break;
case ssl_hs_client_key_exchange:
rv = "client_key_exchange (16)";
break;
case ssl_hs_finished:
rv = "finished (20)";
break;
case ssl_hs_certificate_status:
rv = "certificate_status (22)";
break;
case ssl_hs_key_update:
rv = "key_update (24)";
break;
default:
sprintf(line, "*UNKNOWN* handshake type! (%d)", msgType);
rv = line;
}
return rv;
}
static char *
ssl3_DecodeContentType(int msgType)
{
char *rv;
static char line[40];
switch (msgType) {
case ssl_ct_change_cipher_spec:
rv = "change_cipher_spec (20)";
break;
case ssl_ct_alert:
rv = "alert (21)";
break;
case ssl_ct_handshake:
rv = "handshake (22)";
break;
case ssl_ct_application_data:
rv = "application_data (23)";
break;
case ssl_ct_ack:
rv = "ack (26)";
break;
default:
sprintf(line, "*UNKNOWN* record type! (%d)", msgType);
rv = line;
}
return rv;
}
#endif
SSL3Statistics *
SSL_GetStatistics(void)
{
return &ssl3stats;
}
typedef struct tooLongStr {
#if defined(IS_LITTLE_ENDIAN)
PRInt32 low;
PRInt32 high;
#else
PRInt32 high;
PRInt32 low;
#endif
} tooLong;
void
SSL_AtomicIncrementLong(long *x)
{
if ((sizeof *x) == sizeof(PRInt32)) {
PR_ATOMIC_INCREMENT((PRInt32 *)x);
} else {
tooLong *tl = (tooLong *)x;
if (PR_ATOMIC_INCREMENT(&tl->low) == 0)
PR_ATOMIC_INCREMENT(&tl->high);
}
}
PRBool
ssl3_CipherSuiteAllowedForVersionRange(ssl3CipherSuite cipherSuite,
const SSLVersionRange *vrange)
{
switch (cipherSuite) {
case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
case TLS_RSA_WITH_AES_256_CBC_SHA256:
case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
case TLS_RSA_WITH_AES_128_CBC_SHA256:
case TLS_RSA_WITH_AES_128_GCM_SHA256:
case TLS_RSA_WITH_AES_256_GCM_SHA384:
case TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
case TLS_RSA_WITH_NULL_SHA256:
case TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
case TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
return vrange->max >= SSL_LIBRARY_VERSION_TLS_1_2 &&
vrange->min < SSL_LIBRARY_VERSION_TLS_1_3;
/* RFC 4492: ECC cipher suites need TLS extensions to negotiate curves and
* point formats.*/
case TLS_ECDH_ECDSA_WITH_NULL_SHA:
case TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
case TLS_ECDHE_ECDSA_WITH_NULL_SHA:
case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
case TLS_ECDH_RSA_WITH_NULL_SHA:
case TLS_ECDH_RSA_WITH_RC4_128_SHA:
case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
case TLS_ECDHE_RSA_WITH_NULL_SHA:
case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
return vrange->max >= SSL_LIBRARY_VERSION_TLS_1_0 &&
vrange->min < SSL_LIBRARY_VERSION_TLS_1_3;
case TLS_AES_128_GCM_SHA256:
case TLS_AES_256_GCM_SHA384:
case TLS_CHACHA20_POLY1305_SHA256:
return vrange->max >= SSL_LIBRARY_VERSION_TLS_1_3;
default:
return vrange->min < SSL_LIBRARY_VERSION_TLS_1_3;
}
}
/* return pointer to ssl3CipherSuiteDef for suite, or NULL */
/* XXX This does a linear search. A binary search would be better. */
const ssl3CipherSuiteDef *
ssl_LookupCipherSuiteDef(ssl3CipherSuite suite)
{
int cipher_suite_def_len =
sizeof(cipher_suite_defs) / sizeof(cipher_suite_defs[0]);
int i;
for (i = 0; i < cipher_suite_def_len; i++) {
if (cipher_suite_defs[i].cipher_suite == suite)
return &cipher_suite_defs[i];
}
PORT_Assert(PR_FALSE); /* We should never get here. */
PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);
return NULL;
}
/* Find the cipher configuration struct associate with suite */
/* XXX This does a linear search. A binary search would be better. */
static ssl3CipherSuiteCfg *
ssl_LookupCipherSuiteCfgMutable(ssl3CipherSuite suite,
ssl3CipherSuiteCfg *suites)
{
int i;
for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
if (suites[i].cipher_suite == suite)
return &suites[i];
}
/* return NULL and let the caller handle it. */
PORT_SetError(SSL_ERROR_UNKNOWN_CIPHER_SUITE);
return NULL;
}
const ssl3CipherSuiteCfg *
ssl_LookupCipherSuiteCfg(ssl3CipherSuite suite, const ssl3CipherSuiteCfg *suites)
{
return ssl_LookupCipherSuiteCfgMutable(suite,
CONST_CAST(ssl3CipherSuiteCfg, suites));
}
static PRBool
ssl_NamedGroupTypeEnabled(const sslSocket *ss, SSLKEAType keaType)
{
unsigned int i;
for (i = 0; i < SSL_NAMED_GROUP_COUNT; ++i) {
if (ss->namedGroupPreferences[i] &&
ss->namedGroupPreferences[i]->keaType == keaType) {
return PR_TRUE;
}
}
return PR_FALSE;
}
static PRBool
ssl_KEAEnabled(const sslSocket *ss, SSLKEAType keaType)
{
switch (keaType) {
case ssl_kea_rsa:
return PR_TRUE;
case ssl_kea_dh:
case ssl_kea_dh_psk: {
if (ss->sec.isServer && !ss->opt.enableServerDhe) {
return PR_FALSE;
}
if (ss->sec.isServer) {
/* If the server requires named FFDHE groups, then the client
* must have included an FFDHE group. peerSupportsFfdheGroups
* is set to true in ssl_HandleSupportedGroupsXtn(). */
if (ss->opt.requireDHENamedGroups &&
!ss->xtnData.peerSupportsFfdheGroups) {
return PR_FALSE;
}
/* We can use the weak DH group if all of these are true:
* 1. We don't require named groups.
* 2. The peer doesn't support named groups.
* 3. This isn't TLS 1.3.
* 4. The weak group is enabled. */
if (!ss->opt.requireDHENamedGroups &&
!ss->xtnData.peerSupportsFfdheGroups &&
ss->version < SSL_LIBRARY_VERSION_TLS_1_3 &&
ss->ssl3.dheWeakGroupEnabled) {
return PR_TRUE;
}
} else {
if (ss->version < SSL_LIBRARY_VERSION_TLS_1_3 &&
!ss->opt.requireDHENamedGroups) {
/* The client enables DHE cipher suites even if no DHE groups
* are enabled. Only if this isn't TLS 1.3 and named groups
* are not required. */
return PR_TRUE;
}
}
return ssl_NamedGroupTypeEnabled(ss, ssl_kea_dh);
}
case ssl_kea_ecdh:
case ssl_kea_ecdh_psk:
return ssl_NamedGroupTypeEnabled(ss, ssl_kea_ecdh);
case ssl_kea_tls13_any:
return PR_TRUE;
case ssl_kea_fortezza:
default:
PORT_Assert(0);
}
return PR_FALSE;
}
static PRBool
ssl_HasCert(const sslSocket *ss, PRUint16 maxVersion, SSLAuthType authType)
{
PRCList *cursor;
if (authType == ssl_auth_null || authType == ssl_auth_psk || authType == ssl_auth_tls13_any) {
return PR_TRUE;
}
for (cursor = PR_NEXT_LINK(&ss->serverCerts);
cursor != &ss->serverCerts;
cursor = PR_NEXT_LINK(cursor)) {
sslServerCert *cert = (sslServerCert *)cursor;
if (!cert->serverKeyPair ||
!cert->serverKeyPair->privKey ||
!cert->serverCertChain ||
!SSL_CERT_IS(cert, authType)) {
continue;
}
/* When called from ssl3_config_match_init(), all the EC curves will be
* enabled, so this will essentially do nothing (unless we implement
* curve configuration). However, once we have seen the
* supported_groups extension and this is called from config_match(),
* this will filter out certificates with an unsupported curve.
*
* If we might negotiate TLS 1.3, skip this test as group configuration
* doesn't affect choices in TLS 1.3.
*/
if (maxVersion < SSL_LIBRARY_VERSION_TLS_1_3 &&
(authType == ssl_auth_ecdsa ||
authType == ssl_auth_ecdh_ecdsa ||
authType == ssl_auth_ecdh_rsa) &&
!ssl_NamedGroupEnabled(ss, cert->namedCurve)) {
continue;
}
return PR_TRUE;
}
if (authType == ssl_auth_rsa_sign) {
return ssl_HasCert(ss, maxVersion, ssl_auth_rsa_pss);
}
return PR_FALSE;
}
/* Check that a signature scheme is accepted.
* Both by policy and by having a token that supports it. */
static PRBool
ssl_SignatureSchemeAccepted(PRUint16 minVersion,
SSLSignatureScheme scheme,
PRBool forCert)
{
/* Disable RSA-PSS schemes if there are no tokens to verify them. */
if (ssl_IsRsaPssSignatureScheme(scheme)) {
if (!PK11_TokenExists(auth_alg_defs[ssl_auth_rsa_pss])) {
return PR_FALSE;
}
} else if (!forCert && ssl_IsRsaPkcs1SignatureScheme(scheme)) {
/* Disable PKCS#1 signatures if we are limited to TLS 1.3.
* We still need to advertise PKCS#1 signatures in CH and CR
* for certificate signatures.
*/
if (minVersion >= SSL_LIBRARY_VERSION_TLS_1_3) {
return PR_FALSE;
}
} else if (ssl_IsDsaSignatureScheme(scheme)) {
/* DSA: not in TLS 1.3, and check policy. */
if (minVersion >= SSL_LIBRARY_VERSION_TLS_1_3) {
return PR_FALSE;
}
PRUint32 dsaPolicy;
SECStatus rv = NSS_GetAlgorithmPolicy(SEC_OID_ANSIX9_DSA_SIGNATURE,
&dsaPolicy);
if (rv == SECSuccess && (dsaPolicy & NSS_USE_ALG_IN_SSL_KX) == 0) {
return PR_FALSE;
}
}
/* Hash policy. */
PRUint32 hashPolicy;
SSLHashType hashType = ssl_SignatureSchemeToHashType(scheme);
SECOidTag hashOID = ssl3_HashTypeToOID(hashType);
SECStatus rv = NSS_GetAlgorithmPolicy(hashOID, &hashPolicy);
if (rv == SECSuccess && (hashPolicy & NSS_USE_ALG_IN_SSL_KX) == 0) {
return PR_FALSE;
}
return PR_TRUE;
}
static SECStatus
ssl_CheckSignatureSchemes(sslSocket *ss)
{
if (ss->vrange.max < SSL_LIBRARY_VERSION_TLS_1_2) {
return SECSuccess;
}
/* If this is a server using TLS 1.3, we just need to have one signature
* scheme for which we have a usable certificate.
*
* Note: Certificates for earlier TLS versions are checked along with the
* cipher suite in ssl3_config_match_init. */
if (ss->sec.isServer && ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3) {
PRBool foundCert = PR_FALSE;
for (unsigned int i = 0; i < ss->ssl3.signatureSchemeCount; ++i) {
SSLAuthType authType =
ssl_SignatureSchemeToAuthType(ss->ssl3.signatureSchemes[i]);
if (ssl_HasCert(ss, ss->vrange.max, authType)) {
foundCert = PR_TRUE;
break;
}
}
if (!foundCert) {
PORT_SetError(SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM);
return SECFailure;
}
}
/* Ensure that there is a signature scheme that can be accepted.*/
for (unsigned int i = 0; i < ss->ssl3.signatureSchemeCount; ++i) {
if (ssl_SignatureSchemeAccepted(ss->vrange.min,
ss->ssl3.signatureSchemes[i],
PR_FALSE /* forCert */)) {
return SECSuccess;
}
}
PORT_SetError(SSL_ERROR_NO_SUPPORTED_SIGNATURE_ALGORITHM);
return SECFailure;
}
/* For a server, check that a signature scheme that can be used with the
* provided authType is both enabled and usable. */
static PRBool
ssl_HasSignatureScheme(const sslSocket *ss, SSLAuthType authType)
{
PORT_Assert(ss->sec.isServer);
PORT_Assert(ss->ssl3.hs.preliminaryInfo & ssl_preinfo_version);
PORT_Assert(authType != ssl_auth_null);
PORT_Assert(authType != ssl_auth_tls13_any);
if (ss->version < SSL_LIBRARY_VERSION_TLS_1_2 ||
authType == ssl_auth_rsa_decrypt ||
authType == ssl_auth_ecdh_rsa ||
authType == ssl_auth_ecdh_ecdsa) {
return PR_TRUE;
}
for (unsigned int i = 0; i < ss->ssl3.signatureSchemeCount; ++i) {
SSLSignatureScheme scheme = ss->ssl3.signatureSchemes[i];
SSLAuthType schemeAuthType = ssl_SignatureSchemeToAuthType(scheme);
PRBool acceptable = authType == schemeAuthType ||
(schemeAuthType == ssl_auth_rsa_pss &&
authType == ssl_auth_rsa_sign);
if (acceptable && ssl_SignatureSchemeAccepted(ss->version, scheme, PR_FALSE /* forCert */)) {
return PR_TRUE;
}
}
return PR_FALSE;
}
/* Initialize the suite->isPresent value for config_match
* Returns count of enabled ciphers supported by extant tokens,
* regardless of policy or user preference.
* If this returns zero, the user cannot do SSL v3.
*/
unsigned int
ssl3_config_match_init(sslSocket *ss)
{
ssl3CipherSuiteCfg *suite;
const ssl3CipherSuiteDef *cipher_def;
SSLCipherAlgorithm cipher_alg;
CK_MECHANISM_TYPE cipher_mech;
SSLAuthType authType;
SSLKEAType keaType;
unsigned int i;
unsigned int numPresent = 0;
unsigned int numEnabled = 0;
PORT_Assert(ss);
if (!ss) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return 0;
}
if (SSL_ALL_VERSIONS_DISABLED(&ss->vrange)) {
return 0;
}
if (ss->sec.isServer && ss->psk &&
PR_CLIST_IS_EMPTY(&ss->serverCerts) &&
(ss->opt.requestCertificate || ss->opt.requireCertificate)) {
/* PSK and certificate auth cannot be combined. */
PORT_SetError(SSL_ERROR_NO_CERTIFICATE);
return 0;
}
if (ssl_CheckSignatureSchemes(ss) != SECSuccess) {
return 0; /* Code already set. */
}
ssl_FilterSupportedGroups(ss);
for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
suite = &ss->cipherSuites[i];
if (suite->enabled) {
++numEnabled;
/* We need the cipher defs to see if we have a token that can handle
* this cipher. It isn't part of the static definition.
*/
cipher_def = ssl_LookupCipherSuiteDef(suite->cipher_suite);
if (!cipher_def) {
suite->isPresent = PR_FALSE;
continue;
}
cipher_alg = ssl_GetBulkCipherDef(cipher_def)->calg;
cipher_mech = ssl3_Alg2Mech(cipher_alg);
/* Mark the suites that are backed by real tokens, certs and keys */
suite->isPresent = PR_TRUE;
authType = kea_defs[cipher_def->key_exchange_alg].authKeyType;
if (authType != ssl_auth_null && authType != ssl_auth_tls13_any) {
if (ss->sec.isServer &&
!(ssl_HasCert(ss, ss->vrange.max, authType) &&
ssl_HasSignatureScheme(ss, authType))) {
suite->isPresent = PR_FALSE;
} else if (!PK11_TokenExists(auth_alg_defs[authType])) {
suite->isPresent = PR_FALSE;
}
}
keaType = kea_defs[cipher_def->key_exchange_alg].exchKeyType;
if (keaType != ssl_kea_null &&
keaType != ssl_kea_tls13_any &&
!PK11_TokenExists(kea_alg_defs[keaType])) {
suite->isPresent = PR_FALSE;
}
if (cipher_alg != ssl_calg_null &&
!PK11_TokenExists(cipher_mech)) {
suite->isPresent = PR_FALSE;
}
if (suite->isPresent) {
++numPresent;
}
}
}
PORT_Assert(numPresent > 0 || numEnabled == 0);
if (numPresent == 0) {
PORT_SetError(SSL_ERROR_NO_CIPHERS_SUPPORTED);
}
return numPresent;
}
/* Return PR_TRUE if suite is usable. This if the suite is permitted by policy,
* enabled, has a certificate (as needed), has a viable key agreement method, is
* usable with the negotiated TLS version, and is otherwise usable. */
PRBool
ssl3_config_match(const ssl3CipherSuiteCfg *suite, PRUint8 policy,
const SSLVersionRange *vrange, const sslSocket *ss)
{
const ssl3CipherSuiteDef *cipher_def;
const ssl3KEADef *kea_def;
if (!suite) {
PORT_Assert(suite);
return PR_FALSE;
}
PORT_Assert(policy != SSL_NOT_ALLOWED);
if (policy == SSL_NOT_ALLOWED)
return PR_FALSE;
if (!suite->enabled || !suite->isPresent)
return PR_FALSE;
if ((suite->policy == SSL_NOT_ALLOWED) ||
(suite->policy > policy))
return PR_FALSE;
PORT_Assert(ss != NULL);
cipher_def = ssl_LookupCipherSuiteDef(suite->cipher_suite);
PORT_Assert(cipher_def != NULL);
kea_def = &kea_defs[cipher_def->key_exchange_alg];
PORT_Assert(kea_def != NULL);
if (!ssl_KEAEnabled(ss, kea_def->exchKeyType)) {
return PR_FALSE;
}
if (ss->sec.isServer && !ssl_HasCert(ss, vrange->max, kea_def->authKeyType)) {
return PR_FALSE;
}
/* If a PSK is selected, disable suites that use a different hash than
* the PSK. We advertise non-PSK-compatible suites in the CH, as we could
* fallback to certificate auth. The client handler will check hash
* compatibility before committing to use the PSK. */
if (ss->xtnData.selectedPsk) {
if (ss->xtnData.selectedPsk->hash != cipher_def->prf_hash) {
return PR_FALSE;
}
}
return ssl3_CipherSuiteAllowedForVersionRange(suite->cipher_suite, vrange);
}
/* For TLS 1.3, when resuming, check for a ciphersuite that is both compatible
* with the identified ciphersuite and enabled. */
static PRBool
tls13_ResumptionCompatible(sslSocket *ss, ssl3CipherSuite suite)
{
SSLVersionRange vrange = { SSL_LIBRARY_VERSION_TLS_1_3,
SSL_LIBRARY_VERSION_TLS_1_3 };
SSLHashType hash = tls13_GetHashForCipherSuite(suite);
for (unsigned int i = 0; i < PR_ARRAY_SIZE(cipher_suite_defs); i++) {
if (cipher_suite_defs[i].prf_hash == hash) {
const ssl3CipherSuiteCfg *suiteCfg =
ssl_LookupCipherSuiteCfg(cipher_suite_defs[i].cipher_suite,
ss->cipherSuites);
if (suite && ssl3_config_match(suiteCfg, ss->ssl3.policy, &vrange, ss)) {
return PR_TRUE;
}
}
}
return PR_FALSE;
}
/*
* Null compression, mac and encryption functions
*/
SECStatus
Null_Cipher(void *ctx, unsigned char *output, unsigned int *outputLen, unsigned int maxOutputLen,
const unsigned char *input, unsigned int inputLen)
{
if (inputLen > maxOutputLen) {
*outputLen = 0; /* Match PK11_CipherOp in setting outputLen */
PORT_SetError(SEC_ERROR_OUTPUT_LEN);
return SECFailure;
}
*outputLen = inputLen;
if (inputLen > 0 && input != output) {
PORT_Memcpy(output, input, inputLen);
}
return SECSuccess;
}
/*
* SSL3 Utility functions
*/
static void
ssl_SetSpecVersions(sslSocket *ss, ssl3CipherSpec *spec)
{
spec->version = ss->version;
if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
tls13_SetSpecRecordVersion(ss, spec);
} else if (IS_DTLS(ss)) {
spec->recordVersion = dtls_TLSVersionToDTLSVersion(ss->version);
} else {
spec->recordVersion = ss->version;
}
}
/* allowLargerPeerVersion controls whether the function will select the
* highest enabled SSL version or fail when peerVersion is greater than the
* highest enabled version.
*
* If allowLargerPeerVersion is true, peerVersion is the peer's highest
* enabled version rather than the peer's selected version.
*/
SECStatus
ssl3_NegotiateVersion(sslSocket *ss, SSL3ProtocolVersion peerVersion,
PRBool allowLargerPeerVersion)
{
SSL3ProtocolVersion negotiated;
/* Prevent negotiating to a lower version in response to a TLS 1.3 HRR. */
if (ss->ssl3.hs.helloRetry) {
PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION);
return SECFailure;
}
if (SSL_ALL_VERSIONS_DISABLED(&ss->vrange)) {
PORT_SetError(SSL_ERROR_SSL_DISABLED);
return SECFailure;
}
if (peerVersion < ss->vrange.min ||
(peerVersion > ss->vrange.max && !allowLargerPeerVersion)) {
PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION);
return SECFailure;
}
negotiated = PR_MIN(peerVersion, ss->vrange.max);
PORT_Assert(ssl3_VersionIsSupported(ss->protocolVariant, negotiated));
if (ss->firstHsDone && ss->version != negotiated) {
PORT_SetError(SSL_ERROR_UNSUPPORTED_VERSION);
return SECFailure;
}
ss->version = negotiated;
return SECSuccess;
}
/* Used by the client when the server produces a version number.
* This reads, validates, and normalizes the value. */
SECStatus
ssl_ClientReadVersion(sslSocket *ss, PRUint8 **b, unsigned int *len,
SSL3ProtocolVersion *version)
{
SSL3ProtocolVersion v;
PRUint32 temp;
SECStatus rv;
rv = ssl3_ConsumeHandshakeNumber(ss, &temp, 2, b, len);
if (rv != SECSuccess) {
return SECFailure; /* alert has been sent */
}
v = (SSL3ProtocolVersion)temp;
if (IS_DTLS(ss)) {
v = dtls_DTLSVersionToTLSVersion(v);
/* Check for failure. */
if (!v || v > SSL_LIBRARY_VERSION_MAX_SUPPORTED) {
SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
return SECFailure;
}
}
/* You can't negotiate TLS 1.3 this way. */
if (v >= SSL_LIBRARY_VERSION_TLS_1_3) {
SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
return SECFailure;
}
*version = v;
return SECSuccess;
}
SECStatus
ssl3_GetNewRandom(SSL3Random random)
{
SECStatus rv;
rv = PK11_GenerateRandom(random, SSL3_RANDOM_LENGTH);
if (rv != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_GENERATE_RANDOM_FAILURE);
}
return rv;
}
SECStatus
ssl3_SignHashesWithPrivKey(SSL3Hashes *hash, SECKEYPrivateKey *key,
SSLSignatureScheme scheme, PRBool isTls, SECItem *buf)
{
SECStatus rv = SECFailure;
PRBool doDerEncode = PR_FALSE;
PRBool useRsaPss = ssl_IsRsaPssSignatureScheme(scheme);
SECItem hashItem;
buf->data = NULL;
switch (SECKEY_GetPrivateKeyType(key)) {
case rsaKey:
hashItem.data = hash->u.raw;
hashItem.len = hash->len;
break;
case dsaKey:
doDerEncode = isTls;
/* ssl_hash_none is used to specify the MD5/SHA1 concatenated hash.
* In that case, we use just the SHA1 part. */
if (hash->hashAlg == ssl_hash_none) {
hashItem.data = hash->u.s.sha;
hashItem.len = sizeof(hash->u.s.sha);
} else {
hashItem.data = hash->u.raw;
hashItem.len = hash->len;
}
break;
case ecKey:
doDerEncode = PR_TRUE;
/* ssl_hash_none is used to specify the MD5/SHA1 concatenated hash.
* In that case, we use just the SHA1 part. */
if (hash->hashAlg == ssl_hash_none) {
hashItem.data = hash->u.s.sha;
hashItem.len = sizeof(hash->u.s.sha);
} else {
hashItem.data = hash->u.raw;
hashItem.len = hash->len;
}
break;
default:
PORT_SetError(SEC_ERROR_INVALID_KEY);
goto done;
}
PRINT_BUF(60, (NULL, "hash(es) to be signed", hashItem.data, hashItem.len));
if (useRsaPss || hash->hashAlg == ssl_hash_none) {
CK_MECHANISM_TYPE mech = PK11_MapSignKeyType(key->keyType);
int signatureLen = PK11_SignatureLen(key);
SECItem *params = NULL;
CK_RSA_PKCS_PSS_PARAMS pssParams;
SECItem pssParamsItem = { siBuffer,
(unsigned char *)&pssParams,
sizeof(pssParams) };
if (signatureLen <= 0) {
PORT_SetError(SEC_ERROR_INVALID_KEY);
goto done;
}
buf->len = (unsigned)signatureLen;
buf->data = (unsigned char *)PORT_Alloc(signatureLen);
if (!buf->data)
goto done; /* error code was set. */
if (useRsaPss) {
pssParams.hashAlg = ssl3_GetHashMechanismByHashType(hash->hashAlg);
pssParams.mgf = ssl3_GetMgfMechanismByHashType(hash->hashAlg);
pssParams.sLen = hashItem.len;
params = &pssParamsItem;
mech = CKM_RSA_PKCS_PSS;
}
rv = PK11_SignWithMechanism(key, mech, params, buf, &hashItem);
} else {
SECOidTag hashOID = ssl3_HashTypeToOID(hash->hashAlg);
rv = SGN_Digest(key, hashOID, buf, &hashItem);
}
if (rv != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_SIGN_HASHES_FAILURE);
} else if (doDerEncode) {
SECItem derSig = { siBuffer, NULL, 0 };
/* This also works for an ECDSA signature */
rv = DSAU_EncodeDerSigWithLen(&derSig, buf, buf->len);
if (rv == SECSuccess) {
PORT_Free(buf->data); /* discard unencoded signature. */
*buf = derSig; /* give caller encoded signature. */
} else if (derSig.data) {
PORT_Free(derSig.data);
}
}
PRINT_BUF(60, (NULL, "signed hashes", (unsigned char *)buf->data, buf->len));
done:
if (rv != SECSuccess && buf->data) {
PORT_Free(buf->data);
buf->data = NULL;
}
return rv;
}
/* Called by ssl3_SendServerKeyExchange and ssl3_SendCertificateVerify */
SECStatus
ssl3_SignHashes(sslSocket *ss, SSL3Hashes *hash, SECKEYPrivateKey *key,
SECItem *buf)
{
SECStatus rv = SECFailure;
PRBool isTLS = (PRBool)(ss->version > SSL_LIBRARY_VERSION_3_0);
SSLSignatureScheme scheme = ss->ssl3.hs.signatureScheme;
rv = ssl3_SignHashesWithPrivKey(hash, key, scheme, isTLS, buf);
if (rv != SECSuccess) {
return SECFailure;
}
if (ss->sec.isServer) {
ss->sec.signatureScheme = scheme;
ss->sec.authType = ssl_SignatureSchemeToAuthType(scheme);
}
return SECSuccess;
}
/* Called from ssl3_VerifySignedHashes and tls13_HandleCertificateVerify. */
SECStatus
ssl_VerifySignedHashesWithPubKey(sslSocket *ss, SECKEYPublicKey *key,
SSLSignatureScheme scheme,
SSL3Hashes *hash, SECItem *buf)
{
SECItem *signature = NULL;
SECStatus rv = SECFailure;
SECItem hashItem;
SECOidTag encAlg;
SECOidTag hashAlg;
void *pwArg = ss->pkcs11PinArg;
PRBool isRsaPssScheme = ssl_IsRsaPssSignatureScheme(scheme);
PRINT_BUF(60, (NULL, "check signed hashes", buf->data, buf->len));
hashAlg = ssl3_HashTypeToOID(hash->hashAlg);
switch (SECKEY_GetPublicKeyType(key)) {
case rsaKey:
encAlg = SEC_OID_PKCS1_RSA_ENCRYPTION;
hashItem.data = hash->u.raw;
hashItem.len = hash->len;
if (scheme == ssl_sig_none) {
scheme = ssl_sig_rsa_pkcs1_sha1md5;
}
break;
case dsaKey:
encAlg = SEC_OID_ANSIX9_DSA_SIGNATURE;
/* ssl_hash_none is used to specify the MD5/SHA1 concatenated hash.
* In that case, we use just the SHA1 part. */
if (hash->hashAlg == ssl_hash_none) {
hashItem.data = hash->u.s.sha;
hashItem.len = sizeof(hash->u.s.sha);
} else {
hashItem.data = hash->u.raw;
hashItem.len = hash->len;
}
/* Allow DER encoded DSA signatures in SSL 3.0 */
if (ss->ssl3.prSpec->version > SSL_LIBRARY_VERSION_3_0 ||
buf->len != SECKEY_SignatureLen(key)) {
signature = DSAU_DecodeDerSigToLen(buf, SECKEY_SignatureLen(key));
if (!signature) {
PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
goto loser;
}
buf = signature;
}
if (scheme == ssl_sig_none) {
scheme = ssl_sig_dsa_sha1;
}
break;
case ecKey:
encAlg = SEC_OID_ANSIX962_EC_PUBLIC_KEY;
/* ssl_hash_none is used to specify the MD5/SHA1 concatenated hash.
* In that case, we use just the SHA1 part.
* ECDSA signatures always encode the integers r and s using ASN.1
* (unlike DSA where ASN.1 encoding is used with TLS but not with
* SSL3). So we can use VFY_VerifyDigestDirect for ECDSA.
*/
if (hash->hashAlg == ssl_hash_none) {
hashAlg = SEC_OID_SHA1;
hashItem.data = hash->u.s.sha;
hashItem.len = sizeof(hash->u.s.sha);
} else {
hashItem.data = hash->u.raw;
hashItem.len = hash->len;
}
if (scheme == ssl_sig_none) {
scheme = ssl_sig_ecdsa_sha1;
}
break;
default:
PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
goto loser;
}
PRINT_BUF(60, (NULL, "hash(es) to be verified",
hashItem.data, hashItem.len));
if (isRsaPssScheme ||
hashAlg == SEC_OID_UNKNOWN ||
SECKEY_GetPublicKeyType(key) == dsaKey) {
/* VFY_VerifyDigestDirect requires DSA signatures to be DER-encoded.
* DSA signatures are DER-encoded in TLS but not in SSL3 and the code
* above always removes the DER encoding of DSA signatures when
* present. Thus DSA signatures are always verified with PK11_Verify.
*/
CK_MECHANISM_TYPE mech = PK11_MapSignKeyType(key->keyType);
SECItem *params = NULL;
CK_RSA_PKCS_PSS_PARAMS pssParams;
SECItem pssParamsItem = { siBuffer,
(unsigned char *)&pssParams,
sizeof(pssParams) };
if (isRsaPssScheme) {
pssParams.hashAlg = ssl3_GetHashMechanismByHashType(hash->hashAlg);
pssParams.mgf = ssl3_GetMgfMechanismByHashType(hash->hashAlg);
pssParams.sLen = hashItem.len;
params = &pssParamsItem;
mech = CKM_RSA_PKCS_PSS;
}
rv = PK11_VerifyWithMechanism(key, mech, params, buf, &hashItem, pwArg);
} else {
rv = VFY_VerifyDigestDirect(&hashItem, key, buf, encAlg, hashAlg,
pwArg);
}
if (signature) {
SECITEM_FreeItem(signature, PR_TRUE);
}
if (rv != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);
}
if (!ss->sec.isServer) {
ss->sec.signatureScheme = scheme;
ss->sec.authType = ssl_SignatureSchemeToAuthType(scheme);
}
loser:
#ifdef UNSAFE_FUZZER_MODE
rv = SECSuccess;
PORT_SetError(0);
#endif
return rv;
}
/* Called from ssl3_HandleServerKeyExchange, ssl3_HandleCertificateVerify */
SECStatus
ssl3_VerifySignedHashes(sslSocket *ss, SSLSignatureScheme scheme, SSL3Hashes *hash,
SECItem *buf)
{
SECKEYPublicKey *pubKey =
SECKEY_ExtractPublicKey(&ss->sec.peerCert->subjectPublicKeyInfo);
if (pubKey == NULL) {
ssl_MapLowLevelError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);
return SECFailure;
}
SECStatus rv = ssl_VerifySignedHashesWithPubKey(ss, pubKey, scheme,
hash, buf);
SECKEY_DestroyPublicKey(pubKey);
return rv;
}
/* Caller must set hiLevel error code. */
/* Called from ssl3_ComputeDHKeyHash
* which are called from ssl3_HandleServerKeyExchange.
*
* hashAlg: ssl_hash_none indicates the pre-1.2, MD5/SHA1 combination hash.
*/
SECStatus
ssl3_ComputeCommonKeyHash(SSLHashType hashAlg,
PRUint8 *hashBuf, unsigned int bufLen,
SSL3Hashes *hashes)
{
SECStatus rv;
SECOidTag hashOID;
PRUint32 policy;
if (hashAlg == ssl_hash_none) {
if ((NSS_GetAlgorithmPolicy(SEC_OID_SHA1, &policy) == SECSuccess) &&
!(policy & NSS_USE_ALG_IN_SSL_KX)) {
ssl_MapLowLevelError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM);
return SECFailure;
}
rv = PK11_HashBuf(SEC_OID_MD5, hashes->u.s.md5, hashBuf, bufLen);
if (rv != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
return rv;
}
rv = PK11_HashBuf(SEC_OID_SHA1, hashes->u.s.sha, hashBuf, bufLen);
if (rv != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
return rv;
}
hashes->len = MD5_LENGTH + SHA1_LENGTH;
} else {
hashOID = ssl3_HashTypeToOID(hashAlg);
if ((NSS_GetAlgorithmPolicy(hashOID, &policy) == SECSuccess) &&
!(policy & NSS_USE_ALG_IN_SSL_KX)) {
ssl_MapLowLevelError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM);
return SECFailure;
}
hashes->len = HASH_ResultLenByOidTag(hashOID);
if (hashes->len == 0 || hashes->len > sizeof(hashes->u.raw)) {
ssl_MapLowLevelError(SSL_ERROR_UNSUPPORTED_HASH_ALGORITHM);
return SECFailure;
}
rv = PK11_HashBuf(hashOID, hashes->u.raw, hashBuf, bufLen);
if (rv != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
return rv;
}
}
hashes->hashAlg = hashAlg;
return SECSuccess;
}
/* Caller must set hiLevel error code. */
/* Called from ssl3_HandleServerKeyExchange. */
static SECStatus
ssl3_ComputeDHKeyHash(sslSocket *ss, SSLHashType hashAlg, SSL3Hashes *hashes,
SECItem dh_p, SECItem dh_g, SECItem dh_Ys, PRBool padY)
{
sslBuffer buf = SSL_BUFFER_EMPTY;
SECStatus rv;
unsigned int yLen;
unsigned int i;
PORT_Assert(dh_p.data);
PORT_Assert(dh_g.data);
PORT_Assert(dh_Ys.data);
rv = sslBuffer_Append(&buf, ss->ssl3.hs.client_random, SSL3_RANDOM_LENGTH);
if (rv != SECSuccess) {
goto loser;
}
rv = sslBuffer_Append(&buf, ss->ssl3.hs.server_random, SSL3_RANDOM_LENGTH);
if (rv != SECSuccess) {
goto loser;
}
/* p */
rv = sslBuffer_AppendVariable(&buf, dh_p.data, dh_p.len, 2);
if (rv != SECSuccess) {
goto loser;
}
/* g */
rv = sslBuffer_AppendVariable(&buf, dh_g.data, dh_g.len, 2);
if (rv != SECSuccess) {
goto loser;
}
/* y - complicated by padding */
yLen = padY ? dh_p.len : dh_Ys.len;
rv = sslBuffer_AppendNumber(&buf, yLen, 2);
if (rv != SECSuccess) {
goto loser;
}
/* If we're padding Y, dh_Ys can't be longer than dh_p. */
PORT_Assert(!padY || dh_p.len >= dh_Ys.len);
for (i = dh_Ys.len; i < yLen; ++i) {
rv = sslBuffer_AppendNumber(&buf, 0, 1);
if (rv != SECSuccess) {
goto loser;
}
}
rv = sslBuffer_Append(&buf, dh_Ys.data, dh_Ys.len);
if (rv != SECSuccess) {
goto loser;
}
rv = ssl3_ComputeCommonKeyHash(hashAlg, SSL_BUFFER_BASE(&buf),
SSL_BUFFER_LEN(&buf), hashes);
if (rv != SECSuccess) {
goto loser;
}
PRINT_BUF(95, (NULL, "DHkey hash: ", SSL_BUFFER_BASE(&buf),
SSL_BUFFER_LEN(&buf)));
if (hashAlg == ssl_hash_none) {
PRINT_BUF(95, (NULL, "DHkey hash: MD5 result",
hashes->u.s.md5, MD5_LENGTH));
PRINT_BUF(95, (NULL, "DHkey hash: SHA1 result",
hashes->u.s.sha, SHA1_LENGTH));
} else {
PRINT_BUF(95, (NULL, "DHkey hash: result",
hashes->u.raw, hashes->len));
}
sslBuffer_Clear(&buf);
return SECSuccess;
loser:
sslBuffer_Clear(&buf);
return SECFailure;
}
static SECStatus
ssl3_SetupPendingCipherSpec(sslSocket *ss, SSLSecretDirection direction,
const ssl3CipherSuiteDef *suiteDef,
ssl3CipherSpec **specp)
{
ssl3CipherSpec *spec;
const ssl3CipherSpec *prev;
prev = (direction == ssl_secret_write) ? ss->ssl3.cwSpec : ss->ssl3.crSpec;
if (prev->epoch == PR_UINT16_MAX) {
PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
return SECFailure;
}
spec = ssl_CreateCipherSpec(ss, direction);
if (!spec) {
return SECFailure;
}
spec->cipherDef = ssl_GetBulkCipherDef(suiteDef);
spec->macDef = ssl_GetMacDef(ss, suiteDef);
spec->epoch = prev->epoch + 1;
spec->nextSeqNum = 0;
if (IS_DTLS(ss) && direction == ssl_secret_read) {
dtls_InitRecvdRecords(&spec->recvdRecords);
}
ssl_SetSpecVersions(ss, spec);
ssl_SaveCipherSpec(ss, spec);
*specp = spec;
return SECSuccess;
}
/* Fill in the pending cipher spec with info from the selected ciphersuite.
** This is as much initialization as we can do without having key material.
** Called from ssl3_HandleServerHello(), ssl3_SendServerHello()
** Caller must hold the ssl3 handshake lock.
** Acquires & releases SpecWriteLock.
*/
SECStatus
ssl3_SetupBothPendingCipherSpecs(sslSocket *ss)
{
ssl3CipherSuite suite = ss->ssl3.hs.cipher_suite;
SSL3KeyExchangeAlgorithm kea;
const ssl3CipherSuiteDef *suiteDef;
SECStatus rv;
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3);
ssl_GetSpecWriteLock(ss); /*******************************/
/* This hack provides maximal interoperability with SSL 3 servers. */
if (ss->ssl3.cwSpec->macDef->mac == ssl_mac_null) {
/* SSL records are not being MACed. */
ss->ssl3.cwSpec->version = ss->version;
}
SSL_TRC(3, ("%d: SSL3[%d]: Set XXX Pending Cipher Suite to 0x%04x",
SSL_GETPID(), ss->fd, suite));
suiteDef = ssl_LookupCipherSuiteDef(suite);
if (suiteDef == NULL) {
goto loser;
}
if (IS_DTLS(ss)) {
/* Double-check that we did not pick an RC4 suite */
PORT_Assert(suiteDef->bulk_cipher_alg != cipher_rc4);
}
ss->ssl3.hs.suite_def = suiteDef;
kea = suiteDef->key_exchange_alg;
ss->ssl3.hs.kea_def = &kea_defs[kea];
PORT_Assert(ss->ssl3.hs.kea_def->kea == kea);
rv = ssl3_SetupPendingCipherSpec(ss, ssl_secret_read, suiteDef,
&ss->ssl3.prSpec);
if (rv != SECSuccess) {
goto loser;
}
rv = ssl3_SetupPendingCipherSpec(ss, ssl_secret_write, suiteDef,
&ss->ssl3.pwSpec);
if (rv != SECSuccess) {
goto loser;
}
if (ssl3_ExtensionNegotiated(ss, ssl_record_size_limit_xtn)) {
ss->ssl3.prSpec->recordSizeLimit = PR_MIN(MAX_FRAGMENT_LENGTH,
ss->opt.recordSizeLimit);
ss->ssl3.pwSpec->recordSizeLimit = PR_MIN(MAX_FRAGMENT_LENGTH,
ss->xtnData.recordSizeLimit);
}
ssl_ReleaseSpecWriteLock(ss); /*******************************/
return SECSuccess;
loser:
ssl_ReleaseSpecWriteLock(ss);
return SECFailure;
}
/* ssl3_BuildRecordPseudoHeader writes the SSL/TLS pseudo-header (the data which
* is included in the MAC or AEAD additional data) to |buf|. See
* AEAD additional data.
*
* TLS pseudo-header includes the record's version field, SSL's doesn't. Which
* pseudo-header definition to use should be decided based on the version of
* the protocol that was negotiated when the cipher spec became current, NOT
* based on the version value in the record itself, and the decision is passed