/* -*- 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 PRUint32 kSSLSigSchemePolicy =
NSS_USE_ALG_IN_SSL_KX | NSS_USE_ALG_IN_ANY_SIGNATURE;
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
* bug 946147.
*/
{ 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->vrange.min < 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;
}
/* return true if the scheme is allowed by policy, This prevents
* failures later when our actual signatures are rejected by
* policy by either ssl code, or lower level NSS code */
static PRBool
ssl_SchemePolicyOK(SSLSignatureScheme scheme, PRUint32 require)
{
/* Hash policy. */
PRUint32 policy;
SECOidTag hashOID = ssl3_HashTypeToOID(ssl_SignatureSchemeToHashType(scheme));
SECOidTag sigOID;
/* policy bits needed to enable a SignatureScheme */
SECStatus rv = NSS_GetAlgorithmPolicy(hashOID, &policy);
if (rv == SECSuccess &&
(policy & require) != require) {
return PR_FALSE;
}
/* ssl_SignatureSchemeToAuthType reports rsa for rsa_pss_rsae, but we
* actually implement pss signatures when we sign, so just use RSA_PSS
* for all RSA PSS Siganture schemes */
if (ssl_IsRsaPssSignatureScheme(scheme)) {
sigOID = SEC_OID_PKCS1_RSA_PSS_SIGNATURE;
} else {
sigOID = ssl3_AuthTypeToOID(ssl_SignatureSchemeToAuthType(scheme));
}
/* Signature Policy. */
rv = NSS_GetAlgorithmPolicy(sigOID, &policy);
if (rv == SECSuccess &&
(policy & require) != require) {
return PR_FALSE;
}
return PR_TRUE;
}
/* 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;
}
}
return ssl_SchemePolicyOK(scheme, kSSLSigSchemePolicy);
}
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_AssertArg(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
* https://tools.ietf.org/html/rfc5246#section-6.2.3.3 for the definition of the
* 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
* to this function as the |includesVersion| argument. But, the |version|
* argument should be the record's version value.
*/
static SECStatus
ssl3_BuildRecordPseudoHeader(DTLSEpoch epoch,
sslSequenceNumber seqNum,
SSLContentType ct,
PRBool includesVersion,
SSL3ProtocolVersion version,
PRBool isDTLS,
int length,
sslBuffer *buf)
{
SECStatus rv;
if (isDTLS) {
rv = sslBuffer_AppendNumber(buf, epoch, 2);
if (rv != SECSuccess) {
return SECFailure;
}
rv = sslBuffer_AppendNumber(buf, seqNum, 6);
} else {
rv = sslBuffer_AppendNumber(buf, seqNum, 8);
}
if (rv != SECSuccess) {
return SECFailure;
}
rv = sslBuffer_AppendNumber(buf, ct, 1);
if (rv != SECSuccess) {
return SECFailure;
}
/* SSL3 MAC doesn't include the record's version field. */
if (includesVersion) {
/* TLS MAC and AEAD additional data include version. */
rv = sslBuffer_AppendNumber(buf, version, 2);
if (rv != SECSuccess) {
return SECFailure;
}
}
rv = sslBuffer_AppendNumber(buf, length, 2);
if (rv != SECSuccess) {
return SECFailure;
}
return SECSuccess;
}
/* Initialize encryption and MAC contexts for pending spec.
* Master Secret already is derived.
* Caller holds Spec write lock.
*/
static SECStatus
ssl3_InitPendingContexts(sslSocket *ss, ssl3CipherSpec *spec)
{
CK_MECHANISM_TYPE encMechanism;
CK_ATTRIBUTE_TYPE encMode;
SECItem macParam;
CK_ULONG macLength;
SECItem iv;
SSLCipherAlgorithm calg;
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
PORT_Assert(ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
calg = spec->cipherDef->calg;
PORT_Assert(alg2Mech[calg].calg == calg);
if (spec->cipherDef->type != type_aead) {
macLength = spec->macDef->mac_size;
/*
** Now setup the MAC contexts,
** crypto contexts are setup below.
*/
macParam.data = (unsigned char *)&macLength;
macParam.len = sizeof(macLength);
macParam.type = siBuffer;
spec->keyMaterial.macContext = PK11_CreateContextBySymKey(
spec->macDef->mmech, CKA_SIGN, spec->keyMaterial.macKey, &macParam);
if (!spec->keyMaterial.macContext) {
ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
return SECFailure;
}
}
/*
** Now setup the crypto contexts.
*/
if (calg == ssl_calg_null) {
spec->cipher = Null_Cipher;
return SECSuccess;
}
encMechanism = ssl3_Alg2Mech(calg);
encMode = (spec->direction == ssl_secret_write) ? CKA_ENCRYPT : CKA_DECRYPT;
if (spec->cipherDef->type == type_aead) {
encMode |= CKA_NSS_MESSAGE;
iv.data = NULL;
iv.len = 0;
} else {
spec->cipher = (SSLCipher)PK11_CipherOp;
iv.data = spec->keyMaterial.iv;
iv.len = spec->cipherDef->iv_size;
}
/*
* build the context
*/
spec->cipherContext = PK11_CreateContextBySymKey(encMechanism, encMode,
spec->keyMaterial.key,
&iv);
if (!spec->cipherContext) {
ssl_MapLowLevelError(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE);
return SECFailure;
}
return SECSuccess;
}
/* Complete the initialization of all keys, ciphers, MACs and their contexts
* for the pending Cipher Spec.
* Called from: ssl3_SendClientKeyExchange (for Full handshake)
* ssl3_HandleRSAClientKeyExchange (for Full handshake)
* ssl3_HandleServerHello (for session restart)
* ssl3_HandleClientHello (for session restart)
* Sets error code, but caller probably should override to disambiguate.
*
* If |secret| is a master secret from a previous connection is reused, |derive|
* is PR_FALSE. If the secret is a pre-master secret, then |derive| is PR_TRUE
* and the master secret is derived from |secret|.
*/
SECStatus
ssl3_InitPendingCipherSpecs(sslSocket *ss, PK11SymKey *secret, PRBool derive)
{
PK11SymKey *masterSecret;
ssl3CipherSpec *pwSpec;
ssl3CipherSpec *prSpec;
SECStatus rv;
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
PORT_Assert(secret);
ssl_GetSpecWriteLock(ss); /**************************************/
PORT_Assert(ss->ssl3.pwSpec);
PORT_Assert(ss->ssl3.cwSpec->epoch == ss->ssl3.crSpec->epoch);
prSpec = ss->ssl3.prSpec;
pwSpec = ss->ssl3.pwSpec;
if (ss->ssl3.cwSpec->epoch == PR_UINT16_MAX) {
/* The problem here is that we have rehandshaked too many
* times (you are not allowed to wrap the epoch). The
* spec says you should be discarding the connection
* and start over, so not much we can do here. */
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
goto loser;
}
if (derive) {
rv = ssl3_ComputeMasterSecret(ss, secret, &masterSecret);
if (rv != SECSuccess) {
goto loser;
}
} else {
masterSecret = secret;
}
PORT_Assert(masterSecret);
rv = ssl3_DeriveConnectionKeys(ss, masterSecret);
if (rv != SECSuccess) {
if (derive) {
/* masterSecret was created here. */
PK11_FreeSymKey(masterSecret);
}
goto loser;
}
/* Both cipher specs maintain a reference to the master secret, since each
* is managed and freed independently. */
prSpec->masterSecret = masterSecret;
pwSpec->masterSecret = PK11_ReferenceSymKey(masterSecret);
rv = ssl3_InitPendingContexts(ss, ss->ssl3.prSpec);
if (rv != SECSuccess) {
goto loser;
}
rv = ssl3_InitPendingContexts(ss, ss->ssl3.pwSpec);
if (rv != SECSuccess) {
goto loser;
}
ssl_ReleaseSpecWriteLock(ss); /******************************/
return SECSuccess;
loser:
ssl_ReleaseSpecWriteLock(ss); /******************************/
ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
return SECFailure;
}
/*
* 60 bytes is 3 times the maximum length MAC size that is supported.
*/
static const unsigned char mac_pad_1[60] = {
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36
};
static const unsigned char mac_pad_2[60] = {
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c
};
/* Called from: ssl3_SendRecord()
** Caller must already hold the SpecReadLock. (wish we could assert that!)
*/
static SECStatus
ssl3_ComputeRecordMAC(
ssl3CipherSpec *spec,
const unsigned char *header,
unsigned int headerLen,
const PRUint8 *input,
int inputLen,
unsigned char *outbuf,
unsigned int *outLen)
{
PK11Context *context;
int macSize = spec->macDef->mac_size;
SECStatus rv;
PRINT_BUF(95, (NULL, "frag hash1: header", header, headerLen));
PRINT_BUF(95, (NULL, "frag hash1: input", input, inputLen));
if (spec->macDef->mac == ssl_mac_null) {
*outLen = 0;
return SECSuccess;
}
context = spec->keyMaterial.macContext;
rv = PK11_DigestBegin(context);
rv |= PK11_DigestOp(context, header, headerLen);
rv |= PK11_DigestOp(context, input, inputLen);
rv |= PK11_DigestFinal(context, outbuf, outLen, macSize);
PORT_Assert(rv != SECSuccess || *outLen == (unsigned)macSize);
PRINT_BUF(95, (NULL, "frag hash2: result", outbuf, *outLen));
if (rv != SECSuccess) {
rv = SECFailure;
ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);
}
return rv;
}
/* Called from: ssl3_HandleRecord()
* Caller must already hold the SpecReadLock. (wish we could assert that!)
*
* On entry:
* originalLen >= inputLen >= MAC size
*/
static SECStatus
ssl3_ComputeRecordMACConstantTime(
ssl3CipherSpec *spec,
const unsigned char *header,
unsigned int headerLen,
const PRUint8 *input,
int inputLen,
int originalLen,
unsigned char *outbuf,
unsigned int *outLen)
{
CK_MECHANISM_TYPE macType;
CK_NSS_MAC_CONSTANT_TIME_PARAMS params;
SECItem param, inputItem, outputItem;
int macSize = spec->macDef->mac_size;
SECStatus rv;
PORT_Assert(inputLen >= spec->macDef->mac_size);
PORT_Assert(originalLen >= inputLen);
if (spec->macDef->mac == ssl_mac_null) {
*outLen = 0;
return SECSuccess;
}
macType = CKM_NSS_HMAC_CONSTANT_TIME;
if (spec->version == SSL_LIBRARY_VERSION_3_0) {
macType = CKM_NSS_SSL3_MAC_CONSTANT_TIME;
}
params.macAlg = spec->macDef->mmech;
params.ulBodyTotalLen = originalLen;
params.pHeader = (unsigned char *)header; /* const cast */
params.ulHeaderLen = headerLen;
param.data = (unsigned char *)¶ms;
param.len = sizeof(params);
param.type = 0;
inputItem.data = (unsigned char *)input;
inputItem.len = inputLen;
inputItem.type = 0;
outputItem.data = outbuf;
outputItem.len = *outLen;
outputItem.type = 0;
rv = PK11_SignWithSymKey(spec->keyMaterial.macKey, macType, ¶m,
&outputItem, &inputItem);
if (rv != SECSuccess) {
if (PORT_GetError() == SEC_ERROR_INVALID_ALGORITHM) {
/* ssl3_ComputeRecordMAC() expects the MAC to have been removed
* from the input length already. */
return ssl3_ComputeRecordMAC(spec, header, headerLen,
input, inputLen - macSize,
outbuf, outLen);
}
*outLen = 0;
rv = SECFailure;
ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);
return rv;
}
PORT_Assert(outputItem.len == (unsigned)macSize);
*outLen = outputItem.len;
return rv;
}
static PRBool
ssl3_ClientAuthTokenPresent(sslSessionID *sid)
{
PK11SlotInfo *slot = NULL;
PRBool isPresent = PR_TRUE;
/* we only care if we are doing client auth */
if (!sid || !sid->u.ssl3.clAuthValid) {
return PR_TRUE;
}
/* get the slot */
slot = SECMOD_LookupSlot(sid->u.ssl3.clAuthModuleID,
sid->u.ssl3.clAuthSlotID);
if (slot == NULL ||
!PK11_IsPresent(slot) ||
sid->u.ssl3.clAuthSeries != PK11_GetSlotSeries(slot) ||
sid->u.ssl3.clAuthSlotID != PK11_GetSlotID(slot) ||
sid->u.ssl3.clAuthModuleID != PK11_GetModuleID(slot) ||
(PK11_NeedLogin(slot) && !PK11_IsLoggedIn(slot, NULL))) {
isPresent = PR_FALSE;
}
if (slot) {
PK11_FreeSlot(slot);
}
return isPresent;
}
/* Caller must hold the spec read lock. */
SECStatus
ssl3_MACEncryptRecord(ssl3CipherSpec *cwSpec,
PRBool isServer,
PRBool isDTLS,
SSLContentType ct,
const PRUint8 *pIn,
PRUint32 contentLen,
sslBuffer *wrBuf)
{
SECStatus rv;
PRUint32 macLen = 0;
PRUint32 fragLen;
PRUint32 p1Len, p2Len, oddLen = 0;
unsigned int ivLen = 0;
unsigned char pseudoHeaderBuf[13];
sslBuffer pseudoHeader = SSL_BUFFER(pseudoHeaderBuf);
unsigned int len;
if (cwSpec->cipherDef->type == type_block &&
cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_1) {
/* Prepend the per-record explicit IV using technique 2b from
* RFC 4346 section 6.2.3.2: The IV is a cryptographically
* strong random number XORed with the CBC residue from the previous
* record.
*/
ivLen = cwSpec->cipherDef->iv_size;
if (ivLen > SSL_BUFFER_SPACE(wrBuf)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
rv = PK11_GenerateRandom(SSL_BUFFER_NEXT(wrBuf), ivLen);
if (rv != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_GENERATE_RANDOM_FAILURE);
return rv;
}
rv = cwSpec->cipher(cwSpec->cipherContext,
SSL_BUFFER_NEXT(wrBuf), /* output */
&len, /* outlen */
ivLen, /* max outlen */
SSL_BUFFER_NEXT(wrBuf), /* input */
ivLen); /* input len */
if (rv != SECSuccess || len != ivLen) {
PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
return SECFailure;
}
rv = sslBuffer_Skip(wrBuf, len, NULL);
PORT_Assert(rv == SECSuccess); /* Can't fail. */
}
rv = ssl3_BuildRecordPseudoHeader(
cwSpec->epoch, cwSpec->nextSeqNum, ct,
cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_0, cwSpec->recordVersion,
isDTLS, contentLen, &pseudoHeader);
PORT_Assert(rv == SECSuccess);
if (cwSpec->cipherDef->type == type_aead) {
const unsigned int nonceLen = cwSpec->cipherDef->explicit_nonce_size;
const unsigned int tagLen = cwSpec->cipherDef->tag_size;
unsigned int ivOffset = 0;
CK_GENERATOR_FUNCTION gen;
/* ivOut includes the iv and the nonce and is the internal iv/nonce
* for the AEAD function. On Encrypt, this is an in/out parameter */
unsigned char ivOut[MAX_IV_LENGTH];
ivLen = cwSpec->cipherDef->iv_size;
PORT_Assert((ivLen + nonceLen) <= MAX_IV_LENGTH);
PORT_Assert((ivLen + nonceLen) >= sizeof(sslSequenceNumber));
if (nonceLen + contentLen + tagLen > SSL_BUFFER_SPACE(wrBuf)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
if (nonceLen == 0) {
ivOffset = ivLen - sizeof(sslSequenceNumber);
gen = CKG_GENERATE_COUNTER_XOR;
} else {
ivOffset = ivLen;
gen = CKG_GENERATE_COUNTER;
}
ivOffset = tls13_SetupAeadIv(isDTLS, ivOut, cwSpec->keyMaterial.iv,
ivOffset, ivLen, cwSpec->epoch);
rv = tls13_AEAD(cwSpec->cipherContext,
PR_FALSE,
gen, ivOffset * BPB, /* iv generator params */
ivOut, /* iv in */
ivOut, /* iv out */
ivLen + nonceLen, /* full iv length */
NULL, 0, /* nonce is generated*/
SSL_BUFFER_BASE(&pseudoHeader), /* aad */
SSL_BUFFER_LEN(&pseudoHeader), /* aadlen */
SSL_BUFFER_NEXT(wrBuf) + nonceLen, /* output */
&len, /* out len */
SSL_BUFFER_SPACE(wrBuf) - nonceLen, /* max out */
tagLen,
pIn, contentLen); /* input */
if (rv != SECSuccess) {
PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
return SECFailure;
}
len += nonceLen; /* include the nonce at the beginning */
/* copy out the generated iv if we are using explict nonces */
if (nonceLen) {
PORT_Memcpy(SSL_BUFFER_NEXT(wrBuf), ivOut + ivLen, nonceLen);
}
rv = sslBuffer_Skip(wrBuf, len, NULL);
PORT_Assert(rv == SECSuccess); /* Can't fail. */
} else {
int blockSize = cwSpec->cipherDef->block_size;
/*
* Add the MAC
*/
rv = ssl3_ComputeRecordMAC(cwSpec, SSL_BUFFER_BASE(&pseudoHeader),
SSL_BUFFER_LEN(&pseudoHeader),
pIn, contentLen,
SSL_BUFFER_NEXT(wrBuf) + contentLen, &macLen);
if (rv != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_MAC_COMPUTATION_FAILURE);
return SECFailure;
}
p1Len = contentLen;
p2Len = macLen;
fragLen = contentLen + macLen; /* needs to be encrypted */
PORT_Assert(fragLen <= MAX_FRAGMENT_LENGTH + 1024);
/*
* Pad the text (if we're doing a block cipher)
* then Encrypt it
*/
if (cwSpec->cipherDef->type == type_block) {
unsigned char *pBuf;
int padding_length;
int i;
oddLen = contentLen % blockSize;
/* Assume blockSize is a power of two */
padding_length = blockSize - 1 - ((fragLen) & (blockSize - 1));
fragLen += padding_length + 1;
PORT_Assert((fragLen % blockSize) == 0);
/* Pad according to TLS rules (also acceptable to SSL3). */
pBuf = SSL_BUFFER_NEXT(wrBuf) + fragLen - 1;
for (i = padding_length + 1; i > 0; --i) {
*pBuf-- = padding_length;
}
/* now, if contentLen is not a multiple of block size, fix it */
p2Len = fragLen - p1Len;
}
if (p1Len < 256) {
oddLen = p1Len;
p1Len = 0;
} else {
p1Len -= oddLen;
}
if (oddLen) {
p2Len += oddLen;
PORT_Assert((blockSize < 2) ||
(p2Len % blockSize) == 0);
memmove(SSL_BUFFER_NEXT(wrBuf) + p1Len, pIn + p1Len, oddLen);
}
if (p1Len > 0) {
unsigned int cipherBytesPart1 = 0;
rv = cwSpec->cipher(cwSpec->cipherContext,
SSL_BUFFER_NEXT(wrBuf), /* output */
&cipherBytesPart1, /* actual outlen */
p1Len, /* max outlen */
pIn,
p1Len); /* input, and inputlen */
PORT_Assert(rv == SECSuccess && cipherBytesPart1 == p1Len);
if (rv != SECSuccess || cipherBytesPart1 != p1Len) {
PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
return SECFailure;
}
rv = sslBuffer_Skip(wrBuf, p1Len, NULL);
PORT_Assert(rv == SECSuccess);
}
if (p2Len > 0) {
unsigned int cipherBytesPart2 = 0;
rv = cwSpec->cipher(cwSpec->cipherContext,
SSL_BUFFER_NEXT(wrBuf),
&cipherBytesPart2, /* output and actual outLen */
p2Len, /* max outlen */
SSL_BUFFER_NEXT(wrBuf),
p2Len); /* input and inputLen*/
PORT_Assert(rv == SECSuccess && cipherBytesPart2 == p2Len);
if (rv != SECSuccess || cipherBytesPart2 != p2Len) {
PORT_SetError(SSL_ERROR_ENCRYPTION_FAILURE);
return SECFailure;
}
rv = sslBuffer_Skip(wrBuf, p2Len, NULL);
PORT_Assert(rv == SECSuccess);
}
}
return SECSuccess;
}
/* Note: though this can report failure, it shouldn't. */
SECStatus
ssl_InsertRecordHeader(const sslSocket *ss, ssl3CipherSpec *cwSpec,
SSLContentType contentType, sslBuffer *wrBuf,
PRBool *needsLength)
{
SECStatus rv;
#ifndef UNSAFE_FUZZER_MODE
if (cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_3 &&
cwSpec->epoch > TrafficKeyClearText) {
if (IS_DTLS(ss)) {
return dtls13_InsertCipherTextHeader(ss, cwSpec, wrBuf,
needsLength);
}
contentType = ssl_ct_application_data;
}
#endif
rv = sslBuffer_AppendNumber(wrBuf, contentType, 1);
if (rv != SECSuccess) {
return SECFailure;
}
rv = sslBuffer_AppendNumber(wrBuf, cwSpec->recordVersion, 2);
if (rv != SECSuccess) {
return SECFailure;
}
if (IS_DTLS(ss)) {
rv = sslBuffer_AppendNumber(wrBuf, cwSpec->epoch, 2);
if (rv != SECSuccess) {
return SECFailure;
}
rv = sslBuffer_AppendNumber(wrBuf, cwSpec->nextSeqNum, 6);
if (rv != SECSuccess) {
return SECFailure;
}
}
*needsLength = PR_TRUE;
return SECSuccess;
}
SECStatus
ssl_ProtectRecord(sslSocket *ss, ssl3CipherSpec *cwSpec, SSLContentType ct,
const PRUint8 *pIn, PRUint32 contentLen, sslBuffer *wrBuf)
{
PRBool needsLength;
unsigned int lenOffset;
SECStatus rv;
PORT_Assert(cwSpec->direction == ssl_secret_write);
PORT_Assert(SSL_BUFFER_LEN(wrBuf) == 0);
PORT_Assert(cwSpec->cipherDef->max_records <= RECORD_SEQ_MAX);
if (cwSpec->nextSeqNum >= cwSpec->cipherDef->max_records) {
PORT_Assert(cwSpec->version < SSL_LIBRARY_VERSION_TLS_1_3);
SSL_TRC(3, ("%d: SSL[-]: write sequence number at limit 0x%0llx",
SSL_GETPID(), cwSpec->nextSeqNum));
PORT_SetError(SSL_ERROR_TOO_MANY_RECORDS);
return SECFailure;
}
rv = ssl_InsertRecordHeader(ss, cwSpec, ct, wrBuf, &needsLength);
if (rv != SECSuccess) {
return SECFailure;
}
if (needsLength) {
rv = sslBuffer_Skip(wrBuf, 2, &lenOffset);
if (rv != SECSuccess) {
return SECFailure;
}
}
#ifdef UNSAFE_FUZZER_MODE
{
unsigned int len;
rv = Null_Cipher(NULL, SSL_BUFFER_NEXT(wrBuf), &len,
SSL_BUFFER_SPACE(wrBuf), pIn, contentLen);
if (rv != SECSuccess) {
return SECFailure; /* error was set */
}
rv = sslBuffer_Skip(wrBuf, len, NULL);
PORT_Assert(rv == SECSuccess); /* Can't fail. */
}
#else
if (cwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
PRUint8 *cipherText = SSL_BUFFER_NEXT(wrBuf);
unsigned int bufLen = SSL_BUFFER_LEN(wrBuf);
rv = tls13_ProtectRecord(ss, cwSpec, ct, pIn, contentLen, wrBuf);
if (rv != SECSuccess) {
return SECFailure;
}
if (IS_DTLS(ss)) {
bufLen = SSL_BUFFER_LEN(wrBuf) - bufLen;
rv = dtls13_MaskSequenceNumber(ss, cwSpec,
SSL_BUFFER_BASE(wrBuf),
cipherText, bufLen);
}
} else {
rv = ssl3_MACEncryptRecord(cwSpec, ss->sec.isServer, IS_DTLS(ss), ct,
pIn, contentLen, wrBuf);
}
#endif
if (rv != SECSuccess) {
return SECFailure; /* error was set */
}
if (needsLength) {
/* Insert the length. */
rv = sslBuffer_InsertLength(wrBuf, lenOffset, 2);
if (rv != SECSuccess) {
PORT_Assert(0); /* Can't fail. */
return SECFailure;
}
}
++cwSpec->nextSeqNum;
return SECSuccess;
}
SECStatus
ssl_ProtectNextRecord(sslSocket *ss, ssl3CipherSpec *spec, SSLContentType ct,
const PRUint8 *pIn, unsigned int nIn,
unsigned int *written)
{
sslBuffer *wrBuf = &ss->sec.writeBuf;
unsigned int contentLen;
unsigned int spaceNeeded;
SECStatus rv;
contentLen = PR_MIN(nIn, spec->recordSizeLimit);
spaceNeeded = contentLen + SSL3_BUFFER_FUDGE;
if (spec->version >= SSL_LIBRARY_VERSION_TLS_1_1 &&
spec->cipherDef->type == type_block) {
spaceNeeded += spec->cipherDef->iv_size;
}
if (spaceNeeded > SSL_BUFFER_SPACE(wrBuf)) {
rv = sslBuffer_Grow(wrBuf, spaceNeeded);
if (rv != SECSuccess) {
SSL_DBG(("%d: SSL3[%d]: failed to expand write buffer to %d",
SSL_GETPID(), ss->fd, spaceNeeded));
return SECFailure;
}
}
rv = ssl_ProtectRecord(ss, spec, ct, pIn, contentLen, wrBuf);
if (rv != SECSuccess) {
return SECFailure;
}
PRINT_BUF(50, (ss, "send (encrypted) record data:",
SSL_BUFFER_BASE(wrBuf), SSL_BUFFER_LEN(wrBuf)));
*written = contentLen;
return SECSuccess;
}
/* Process the plain text before sending it.
* Returns the number of bytes of plaintext that were successfully sent
* plus the number of bytes of plaintext that were copied into the
* output (write) buffer.
* Returns -1 on an error. PR_WOULD_BLOCK_ERROR is set if the error is blocking
* and not terminal.
*
* Notes on the use of the private ssl flags:
* (no private SSL flags)
* Attempt to make and send SSL records for all plaintext
* If non-blocking and a send gets WOULD_BLOCK,
* or if the pending (ciphertext) buffer is not empty,
* then buffer remaining bytes of ciphertext into pending buf,
* and continue to do that for all succssive records until all
* bytes are used.
* ssl_SEND_FLAG_FORCE_INTO_BUFFER
* As above, except this suppresses all write attempts, and forces
* all ciphertext into the pending ciphertext buffer.
* ssl_SEND_FLAG_USE_EPOCH (for DTLS)
* Forces the use of the provided epoch
*/
PRInt32
ssl3_SendRecord(sslSocket *ss,
ssl3CipherSpec *cwSpec, /* non-NULL for DTLS retransmits */
SSLContentType ct,
const PRUint8 *pIn, /* input buffer */
PRInt32 nIn, /* bytes of input */
PRInt32 flags)
{
sslBuffer *wrBuf = &ss->sec.writeBuf;
ssl3CipherSpec *spec;
SECStatus rv;
PRInt32 totalSent = 0;
SSL_TRC(3, ("%d: SSL3[%d] SendRecord type: %s nIn=%d",
SSL_GETPID(), ss->fd, ssl3_DecodeContentType(ct),
nIn));
PRINT_BUF(50, (ss, "Send record (plain text)", pIn, nIn));
PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
PORT_Assert(SSL_BUFFER_LEN(wrBuf) == 0);
if (ss->ssl3.fatalAlertSent) {
SSL_TRC(3, ("%d: SSL3[%d] Suppress write, fatal alert already sent",
SSL_GETPID(), ss->fd));
if (ct != ssl_ct_alert) {
/* If we are sending an alert, then we already have an
* error, so don't overwrite. */
PORT_SetError(SSL_ERROR_HANDSHAKE_FAILED);
}
return -1;
}
/* check for Token Presence */
if (!ssl3_ClientAuthTokenPresent(ss->sec.ci.sid)) {
PORT_SetError(SSL_ERROR_TOKEN_INSERTION_REMOVAL);
return -1;
}
if (ss->recordWriteCallback) {
PRUint16 epoch;
ssl_GetSpecReadLock(ss);
epoch = ss->ssl3.cwSpec->epoch;
ssl_ReleaseSpecReadLock(ss);
rv = ss->recordWriteCallback(ss->fd, epoch, ct, pIn, nIn,
ss->recordWriteCallbackArg);
if (rv != SECSuccess) {
return -1;
}
return nIn;
}
if (cwSpec) {
/* cwSpec can only be set for retransmissions of the DTLS handshake. */
PORT_Assert(IS_DTLS(ss) &&
(ct == ssl_ct_handshake ||
ct == ssl_ct_change_cipher_spec));
spec = cwSpec;
} else {
spec = ss->ssl3.cwSpec;
}
while (nIn > 0) {
unsigned int written = 0;
PRInt32 sent;
ssl_GetSpecReadLock(ss);
rv = ssl_ProtectNextRecord(ss, spec, ct, pIn, nIn, &written);
ssl_ReleaseSpecReadLock(ss);
if (rv != SECSuccess) {
goto loser;
}
PORT_Assert(written > 0);
/* DTLS should not fragment non-application data here. */
if (IS_DTLS(ss) && ct != ssl_ct_application_data) {
PORT_Assert(written == nIn);
}
pIn += written;
nIn -= written;
PORT_Assert(nIn >= 0);
/* If there's still some previously saved ciphertext,
* or the caller doesn't want us to send the data yet,
* then add all our new ciphertext to the amount previously saved.
*/
if ((ss->pendingBuf.len > 0) ||
(flags & ssl_SEND_FLAG_FORCE_INTO_BUFFER)) {
rv = ssl_SaveWriteData(ss, SSL_BUFFER_BASE(wrBuf),
SSL_BUFFER_LEN(wrBuf));
if (rv != SECSuccess) {
/* presumably a memory error, SEC_ERROR_NO_MEMORY */
goto loser;
}
if (!(flags & ssl_SEND_FLAG_FORCE_INTO_BUFFER)) {
ss->handshakeBegun = 1;
sent = ssl_SendSavedWriteData(ss);
if (sent < 0 && PR_GetError() != PR_WOULD_BLOCK_ERROR) {
ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE);
goto loser;
}
if (ss->pendingBuf.len) {
flags |= ssl_SEND_FLAG_FORCE_INTO_BUFFER;
}
}
} else {
PORT_Assert(SSL_BUFFER_LEN(wrBuf) > 0);
ss->handshakeBegun = 1;
sent = ssl_DefSend(ss, SSL_BUFFER_BASE(wrBuf),
SSL_BUFFER_LEN(wrBuf),
flags & ~ssl_SEND_FLAG_MASK);
if (sent < 0) {
if (PORT_GetError() != PR_WOULD_BLOCK_ERROR) {
ssl_MapLowLevelError(SSL_ERROR_SOCKET_WRITE_FAILURE);
goto loser;
}
/* we got PR_WOULD_BLOCK_ERROR, which means none was sent. */
sent = 0;
}
if (SSL_BUFFER_LEN(wrBuf) > (unsigned int)sent) {
if (IS_DTLS(ss)) {
/* DTLS just says no in this case. No buffering */
PORT_SetError(PR_WOULD_BLOCK_ERROR);
goto loser;
}
/* now take all the remaining unsent new ciphertext and
* append it to the buffer of previously unsent ciphertext.
*/
rv = ssl_SaveWriteData(ss, SSL_BUFFER_BASE(wrBuf) + sent,
SSL_BUFFER_LEN(wrBuf) - sent);
if (rv != SECSuccess) {
/* presumably a memory error, SEC_ERROR_NO_MEMORY */
goto loser;
}
}
}
wrBuf->len = 0;
totalSent += written;
}
return totalSent;
loser:
/* Don't leave bits of buffer lying around. */
wrBuf->len = 0;
return -1;
}
#define SSL3_PENDING_HIGH_WATER 1024
/* Attempt to send the content of "in" in an SSL application_data record.
* Returns "len" or -1 on failure.
*/
int
ssl3_SendApplicationData(sslSocket *ss, const unsigned char *in,
PRInt32 len, PRInt32 flags)
{
PRInt32 totalSent = 0;
PRInt32 discarded = 0;
PRBool splitNeeded = PR_FALSE;
PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
/* These flags for internal use only */
PORT_Assert(!(flags & ssl_SEND_FLAG_NO_RETRANSMIT));
if (len < 0 || !in) {
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
return -1;
}
if (ss->pendingBuf.len > SSL3_PENDING_HIGH_WATER &&
!ssl_SocketIsBlocking(ss)) {
PORT_Assert(!ssl_SocketIsBlocking(ss));
PORT_SetError(PR_WOULD_BLOCK_ERROR);
return -1;
}
if (ss->appDataBuffered && len) {
PORT_Assert(in[0] == (unsigned char)(ss->appDataBuffered));
if (in[0] != (unsigned char)(ss->appDataBuffered)) {
PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
return -1;
}
in++;
len--;
discarded = 1;
}
/* We will split the first byte of the record into its own record, as
* explained in the documentation for SSL_CBC_RANDOM_IV in ssl.h.
*/
if (len > 1 && ss->opt.cbcRandomIV &&
ss->version < SSL_LIBRARY_VERSION_TLS_1_1 &&
ss->ssl3.cwSpec->cipherDef->type == type_block /* CBC */) {
splitNeeded = PR_TRUE;
}
while (len > totalSent) {
PRInt32 sent, toSend;
if (totalSent > 0) {
/*
* The thread yield is intended to give the reader thread a
* chance to get some cycles while the writer thread is in
* the middle of a large application data write. (See
* Bugzilla bug 127740, comment #1.)
*/
ssl_ReleaseXmitBufLock(ss);
PR_Sleep(PR_INTERVAL_NO_WAIT); /* PR_Yield(); */
ssl_GetXmitBufLock(ss);
}
if (splitNeeded) {
toSend = 1;
splitNeeded = PR_FALSE;
} else {
toSend = PR_MIN(len - totalSent, MAX_FRAGMENT_LENGTH);
}
/*
* Note that the 0 epoch is OK because flags will never require
* its use, as guaranteed by the PORT_Assert above.
*/
sent = ssl3_SendRecord(ss, NULL, ssl_ct_application_data,
in + totalSent, toSend, flags);
if (sent < 0) {
if (totalSent > 0 && PR_GetError() == PR_WOULD_BLOCK_ERROR) {
PORT_Assert(ss->lastWriteBlocked);
break;
}
return -1; /* error code set by ssl3_SendRecord */
}
totalSent += sent;
if (ss->pendingBuf.len) {
/* must be a non-blocking socket */
PORT_Assert(!ssl_SocketIsBlocking(ss));
PORT_Assert(ss->lastWriteBlocked);
break;
}
}
if (ss->pendingBuf.len) {
/* Must be non-blocking. */
PORT_Assert(!ssl_SocketIsBlocking(ss));
if (totalSent > 0) {
ss->appDataBuffered = 0x100 | in[totalSent - 1];
}
totalSent = totalSent + discarded - 1;
if (totalSent <= 0) {
PORT_SetError(PR_WOULD_BLOCK_ERROR);
totalSent = SECFailure;
}
return totalSent;
}
ss->appDataBuffered = 0;
return totalSent + discarded;
}
/* Attempt to send buffered handshake messages.
* Always set sendBuf.len to 0, even when returning SECFailure.
*
* Depending on whether we are doing DTLS or not, this either calls
*
* - ssl3_FlushHandshakeMessages if non-DTLS
* - dtls_FlushHandshakeMessages if DTLS
*
* Called from SSL3_SendAlert(), ssl3_SendChangeCipherSpecs(),
* ssl3_AppendHandshake(), ssl3_SendClientHello(),
* ssl3_SendHelloRequest(), ssl3_SendServerHelloDone(),
* ssl3_SendFinished(),
*/
SECStatus
ssl3_FlushHandshake(sslSocket *ss, PRInt32 flags)
{
if (IS_DTLS(ss)) {
return dtls_FlushHandshakeMessages(ss, flags);
}
return ssl3_FlushHandshakeMessages(ss, flags);
}
/* Attempt to send the content of sendBuf buffer in an SSL handshake record.
* Always set sendBuf.len to 0, even when returning SECFailure.
*
* Called from ssl3_FlushHandshake
*/
static SECStatus
ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags)
{
static const PRInt32 allowedFlags = ssl_SEND_FLAG_FORCE_INTO_BUFFER;
PRInt32 count = -1;
SECStatus rv;
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
if (!ss->sec.ci.sendBuf.buf || !ss->sec.ci.sendBuf.len)
return SECSuccess;
/* only these flags are allowed */
PORT_Assert(!(flags & ~allowedFlags));
if ((flags & ~allowedFlags) != 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
count = ssl3_SendRecord(ss, NULL, ssl_ct_handshake,
ss->sec.ci.sendBuf.buf,
ss->sec.ci.sendBuf.len, flags);
if (count < 0) {
int err = PORT_GetError();
PORT_Assert(err != PR_WOULD_BLOCK_ERROR);
if (err == PR_WOULD_BLOCK_ERROR) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
}
rv = SECFailure;
} else if ((unsigned int)count < ss->sec.ci.sendBuf.len) {
/* short write should never happen */
PORT_Assert((unsigned int)count >= ss->sec.ci.sendBuf.len);
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
rv = SECFailure;
} else {
rv = SECSuccess;
}
/* Whether we succeeded or failed, toss the old handshake data. */
ss->sec.ci.sendBuf.len = 0;
return rv;
}
/*
* Called from ssl3_HandleAlert and from ssl3_HandleCertificate when
* the remote client sends a negative response to our certificate request.
* Returns SECFailure if the application has required client auth.
* SECSuccess otherwise.
*/
SECStatus
ssl3_HandleNoCertificate(sslSocket *ss)
{
ssl3_CleanupPeerCerts(ss);
/* If the server has required client-auth blindly but doesn't
* actually look at the certificate it won't know that no
* certificate was presented so we shutdown the socket to ensure
* an error. We only do this if we haven't already completed the
* first handshake because if we're redoing the handshake we
* know the server is paying attention to the certificate.
*/
if ((ss->opt.requireCertificate == SSL_REQUIRE_ALWAYS) ||
(!ss->firstHsDone &&
(ss->opt.requireCertificate == SSL_REQUIRE_FIRST_HANDSHAKE))) {
PRFileDesc *lower;
ssl_UncacheSessionID(ss);
if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
SSL3_SendAlert(ss, alert_fatal, certificate_required);
} else {
SSL3_SendAlert(ss, alert_fatal, bad_certificate);
}
lower = ss->fd->lower;
#ifdef _WIN32
lower->methods->shutdown(lower, PR_SHUTDOWN_SEND);
#else
lower->methods->shutdown(lower, PR_SHUTDOWN_BOTH);
#endif
PORT_SetError(SSL_ERROR_NO_CERTIFICATE);
return SECFailure;
}
return SECSuccess;
}
/************************************************************************
* Alerts
*/
/*
** Acquires both handshake and XmitBuf locks.
** Called from: ssl3_IllegalParameter <-
** ssl3_HandshakeFailure <-
** ssl3_HandleAlert <- ssl3_HandleRecord.
** ssl3_HandleChangeCipherSpecs <- ssl3_HandleRecord
** ssl3_ConsumeHandshakeVariable <-
** ssl3_HandleHelloRequest <-
** ssl3_HandleServerHello <-
** ssl3_HandleServerKeyExchange <-
** ssl3_HandleCertificateRequest <-
** ssl3_HandleServerHelloDone <-
** ssl3_HandleClientHello <-
** ssl3_HandleV2ClientHello <-
** ssl3_HandleCertificateVerify <-
** ssl3_HandleClientKeyExchange <-
** ssl3_HandleCertificate <-
** ssl3_HandleFinished <-
** ssl3_HandleHandshakeMessage <-
** ssl3_HandlePostHelloHandshakeMessage <-
** ssl3_HandleRecord <-
**
*/
SECStatus
SSL3_SendAlert(sslSocket *ss, SSL3AlertLevel level, SSL3AlertDescription desc)
{
PRUint8 bytes[2];
SECStatus rv;
PRBool needHsLock = !ssl_HaveSSL3HandshakeLock(ss);
/* Check that if I need the HS lock I also need the Xmit lock */
PORT_Assert(!needHsLock || !ssl_HaveXmitBufLock(ss));
SSL_TRC(3, ("%d: SSL3[%d]: send alert record, level=%d desc=%d",
SSL_GETPID(), ss->fd, level, desc));
bytes[0] = level;
bytes[1] = desc;
if (needHsLock) {
ssl_GetSSL3HandshakeLock(ss);
}
if (level == alert_fatal) {
if (ss->sec.ci.sid) {
ssl_UncacheSessionID(ss);
}
}
rv = tls13_SetAlertCipherSpec(ss);
if (rv != SECSuccess) {
if (needHsLock) {
ssl_ReleaseSSL3HandshakeLock(ss);
}
return rv;
}
ssl_GetXmitBufLock(ss);
rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER);
if (rv == SECSuccess) {
PRInt32 sent;
sent = ssl3_SendRecord(ss, NULL, ssl_ct_alert, bytes, 2,
(desc == no_certificate) ? ssl_SEND_FLAG_FORCE_INTO_BUFFER : 0);
rv = (sent >= 0) ? SECSuccess : (SECStatus)sent;
}
if (level == alert_fatal) {
ss->ssl3.fatalAlertSent = PR_TRUE;
}
ssl_ReleaseXmitBufLock(ss);
if (needHsLock) {
ssl_ReleaseSSL3HandshakeLock(ss);
}
if (rv == SECSuccess && ss->alertSentCallback) {
SSLAlert alert = { level, desc };
ss->alertSentCallback(ss->fd, ss->alertSentCallbackArg, &alert);
}
return rv; /* error set by ssl3_FlushHandshake or ssl3_SendRecord */
}
/*
* Send illegal_parameter alert. Set generic error number.
*/
static SECStatus
ssl3_IllegalParameter(sslSocket *ss)
{
(void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
PORT_SetError(ss->sec.isServer ? SSL_ERROR_BAD_CLIENT
: SSL_ERROR_BAD_SERVER);
return SECFailure;
}
/*
* Send handshake_Failure alert. Set generic error number.
*/
static SECStatus
ssl3_HandshakeFailure(sslSocket *ss)
{
(void)SSL3_SendAlert(ss, alert_fatal, handshake_failure);
PORT_SetError(ss->sec.isServer ? SSL_ERROR_BAD_CLIENT
: SSL_ERROR_BAD_SERVER);
return SECFailure;
}
void
ssl3_SendAlertForCertError(sslSocket *ss, PRErrorCode errCode)
{
SSL3AlertDescription desc = bad_certificate;
PRBool isTLS = ss->version >= SSL_LIBRARY_VERSION_3_1_TLS;
switch (errCode) {
case SEC_ERROR_LIBRARY_FAILURE:
desc = unsupported_certificate;
break;
case SEC_ERROR_EXPIRED_CERTIFICATE:
desc = certificate_expired;
break;
case SEC_ERROR_REVOKED_CERTIFICATE:
desc = certificate_revoked;
break;
case SEC_ERROR_INADEQUATE_KEY_USAGE:
case SEC_ERROR_INADEQUATE_CERT_TYPE:
desc = certificate_unknown;
break;
case SEC_ERROR_UNTRUSTED_CERT:
desc = isTLS ? access_denied : certificate_unknown;
break;
case SEC_ERROR_UNKNOWN_ISSUER:
case SEC_ERROR_UNTRUSTED_ISSUER:
desc = isTLS ? unknown_ca : certificate_unknown;
break;
case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
desc = isTLS ? unknown_ca : certificate_expired;
break;
case SEC_ERROR_CERT_NOT_IN_NAME_SPACE:
case SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID:
case SEC_ERROR_CA_CERT_INVALID:
case SEC_ERROR_BAD_SIGNATURE:
default:
desc = bad_certificate;
break;
}
SSL_DBG(("%d: SSL3[%d]: peer certificate is no good: error=%d",
SSL_GETPID(), ss->fd, errCode));
(void)SSL3_SendAlert(ss, alert_fatal, desc);
}
/*
* Send decode_error alert. Set generic error number.
*/
SECStatus
ssl3_DecodeError(sslSocket *ss)
{
(void)SSL3_SendAlert(ss, alert_fatal,
ss->version > SSL_LIBRARY_VERSION_3_0 ? decode_error
: illegal_parameter);
PORT_SetError(ss->sec.isServer ? SSL_ERROR_BAD_CLIENT
: SSL_ERROR_BAD_SERVER);
return SECFailure;
}
/* Called from ssl3_HandleRecord.
** Caller must hold both RecvBuf and Handshake locks.
*/
static SECStatus
ssl3_HandleAlert(sslSocket *ss, sslBuffer *buf)
{
SSL3AlertLevel level;
SSL3AlertDescription desc;
int error;
PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
SSL_TRC(3, ("%d: SSL3[%d]: handle alert record", SSL_GETPID(), ss->fd));
if (buf->len != 2) {
(void)ssl3_DecodeError(ss);
PORT_SetError(SSL_ERROR_RX_MALFORMED_ALERT);
return SECFailure;
}
level = (SSL3AlertLevel)buf->buf[0];
desc = (SSL3AlertDescription)buf->buf[1];
buf->len = 0;
SSL_TRC(5, ("%d: SSL3[%d] received alert, level = %d, description = %d",
SSL_GETPID(), ss->fd, level, desc));
if (ss->alertReceivedCallback) {
SSLAlert alert = { level, desc };
ss->alertReceivedCallback(ss->fd, ss->alertReceivedCallbackArg, &alert);
}
switch (desc) {
case close_notify:
ss->recvdCloseNotify = 1;
error = SSL_ERROR_CLOSE_NOTIFY_ALERT;
break;
case unexpected_message:
error = SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT;
break;
case bad_record_mac:
error = SSL_ERROR_BAD_MAC_ALERT;
break;
case decryption_failed_RESERVED:
error = SSL_ERROR_DECRYPTION_FAILED_ALERT;
break;
case record_overflow:
error = SSL_ERROR_RECORD_OVERFLOW_ALERT;
break;
case decompression_failure:
error = SSL_ERROR_DECOMPRESSION_FAILURE_ALERT;
break;
case handshake_failure:
error = SSL_ERROR_HANDSHAKE_FAILURE_ALERT;
break;
case no_certificate:
error = SSL_ERROR_NO_CERTIFICATE;
break;
case certificate_required:
error = SSL_ERROR_RX_CERTIFICATE_REQUIRED_ALERT;
break;
case bad_certificate:
error = SSL_ERROR_BAD_CERT_ALERT;
break;
case unsupported_certificate:
error = SSL_ERROR_UNSUPPORTED_CERT_ALERT;
break;
case certificate_revoked:
error = SSL_ERROR_REVOKED_CERT_ALERT;
break;
case certificate_expired:
error = SSL_ERROR_EXPIRED_CERT_ALERT;
break;
case certificate_unknown:
error = SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT;
break;
case illegal_parameter:
error = SSL_ERROR_ILLEGAL_PARAMETER_ALERT;
break;
case inappropriate_fallback:
error = SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT;
break;
/* All alerts below are TLS only. */
case unknown_ca:
error = SSL_ERROR_UNKNOWN_CA_ALERT;
break;
case access_denied:
error = SSL_ERROR_ACCESS_DENIED_ALERT;
break;
case decode_error:
error = SSL_ERROR_DECODE_ERROR_ALERT;
break;
case decrypt_error:
error = SSL_ERROR_DECRYPT_ERROR_ALERT;
break;
case export_restriction:
error = SSL_ERROR_EXPORT_RESTRICTION_ALERT;
break;
case protocol_version:
error = SSL_ERROR_PROTOCOL_VERSION_ALERT;
break;
case insufficient_security:
error = SSL_ERROR_INSUFFICIENT_SECURITY_ALERT;
break;
case internal_error:
error = SSL_ERROR_INTERNAL_ERROR_ALERT;
break;
case user_canceled:
error = SSL_ERROR_USER_CANCELED_ALERT;
break;
case no_renegotiation:
error = SSL_ERROR_NO_RENEGOTIATION_ALERT;
break;
/* Alerts for TLS client hello extensions */
case missing_extension:
error = SSL_ERROR_MISSING_EXTENSION_ALERT;
break;
case unsupported_extension:
error = SSL_ERROR_UNSUPPORTED_EXTENSION_ALERT;
break;
case certificate_unobtainable:
error = SSL_ERROR_CERTIFICATE_UNOBTAINABLE_ALERT;
break;
case unrecognized_name:
error = SSL_ERROR_UNRECOGNIZED_NAME_ALERT;
break;
case bad_certificate_status_response:
error = SSL_ERROR_BAD_CERT_STATUS_RESPONSE_ALERT;
break;
case bad_certificate_hash_value:
error = SSL_ERROR_BAD_CERT_HASH_VALUE_ALERT;
break;
case no_application_protocol:
error = SSL_ERROR_NEXT_PROTOCOL_NO_PROTOCOL;
break;
case ech_required:
error = SSL_ERROR_ECH_REQUIRED_ALERT;
break;
default:
error = SSL_ERROR_RX_UNKNOWN_ALERT;
break;
}
if ((ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) &&
(ss->ssl3.hs.ws != wait_server_hello)) {
/* TLS 1.3 requires all but "end of data" alerts to be
* treated as fatal. */
switch (desc) {
case close_notify:
case user_canceled:
break;
default:
level = alert_fatal;
}
}
if (level == alert_fatal) {
ssl_UncacheSessionID(ss);
if ((ss->ssl3.hs.ws == wait_server_hello) &&
(desc == handshake_failure)) {
/* XXX This is a hack. We're assuming that any handshake failure
* XXX on the client hello is a failure to match ciphers.
*/
error = SSL_ERROR_NO_CYPHER_OVERLAP;
}
PORT_SetError(error);
return SECFailure;
}
if ((desc == no_certificate) && (ss->ssl3.hs.ws == wait_client_cert)) {
/* I'm a server. I've requested a client cert. He hasn't got one. */
SECStatus rv;
PORT_Assert(ss->sec.isServer);
ss->ssl3.hs.ws = wait_client_key;
rv = ssl3_HandleNoCertificate(ss);
return rv;
}
return SECSuccess;
}
/*
* Change Cipher Specs
* Called from ssl3_HandleServerHelloDone,
* ssl3_HandleClientHello,
* and ssl3_HandleFinished
*
* Acquires and releases spec write lock, to protect switching the current
* and pending write spec pointers.
*/
SECStatus
ssl3_SendChangeCipherSpecsInt(sslSocket *ss)
{
PRUint8 change = change_cipher_spec_choice;
SECStatus rv;
SSL_TRC(3, ("%d: SSL3[%d]: send change_cipher_spec record",
SSL_GETPID(), ss->fd));
rv = ssl3_FlushHandshake(ss, ssl_SEND_FLAG_FORCE_INTO_BUFFER);
if (rv != SECSuccess) {
return SECFailure; /* error code set by ssl3_FlushHandshake */
}
if (!IS_DTLS(ss)) {
PRInt32 sent;
sent = ssl3_SendRecord(ss, NULL, ssl_ct_change_cipher_spec,
&change, 1, ssl_SEND_FLAG_FORCE_INTO_BUFFER);
if (sent < 0) {
return SECFailure; /* error code set by ssl3_SendRecord */
}
} else {
rv = dtls_QueueMessage(ss, ssl_ct_change_cipher_spec, &change, 1);
if (rv != SECSuccess) {
return SECFailure;
}
}
return SECSuccess;
}
static SECStatus
ssl3_SendChangeCipherSpecs(sslSocket *ss)
{
SECStatus rv;
PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
rv = ssl3_SendChangeCipherSpecsInt(ss);
if (rv != SECSuccess) {
return rv; /* Error code set. */
}
/* swap the pending and current write specs. */
ssl_GetSpecWriteLock(ss); /**************************************/
ssl_CipherSpecRelease(ss->ssl3.cwSpec);
ss->ssl3.cwSpec = ss->ssl3.pwSpec;
ss->ssl3.pwSpec = NULL;
SSL_TRC(3, ("%d: SSL3[%d] Set Current Write Cipher Suite to Pending",
SSL_GETPID(), ss->fd));
/* With DTLS, we need to set a holddown timer in case the final
* message got lost */
if (IS_DTLS(ss) && ss->ssl3.crSpec->epoch == ss->ssl3.cwSpec->epoch) {
rv = dtls_StartHolddownTimer(ss);
}
ssl_ReleaseSpecWriteLock(ss); /**************************************/
return rv;
}
/* Called from ssl3_HandleRecord.
** Caller must hold both RecvBuf and Handshake locks.
*
* Acquires and releases spec write lock, to protect switching the current
* and pending write spec pointers.
*/
static SECStatus
ssl3_HandleChangeCipherSpecs(sslSocket *ss, sslBuffer *buf)
{
SSL3WaitState ws = ss->ssl3.hs.ws;
SSL3ChangeCipherSpecChoice change;
PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
SSL_TRC(3, ("%d: SSL3[%d]: handle change_cipher_spec record",
SSL_GETPID(), ss->fd));
/* For DTLS: Ignore this if we aren't expecting it. Don't kill a connection
* as a result of receiving trash.
* For TLS: Maybe ignore, but only after checking format. */
if (ws != wait_change_cipher && IS_DTLS(ss)) {
/* Ignore this because it's out of order. */
SSL_TRC(3, ("%d: SSL3[%d]: discard out of order "
"DTLS change_cipher_spec",
SSL_GETPID(), ss->fd));
buf->len = 0;
return SECSuccess;
}
/* Handshake messages should not span ChangeCipherSpec. */
if (ss->ssl3.hs.header_bytes) {
(void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER);
return SECFailure;
}
if (buf->len != 1) {
(void)ssl3_DecodeError(ss);
PORT_SetError(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER);
return SECFailure;
}
change = (SSL3ChangeCipherSpecChoice)buf->buf[0];
if (change != change_cipher_spec_choice) {
/* illegal_parameter is correct here for both SSL3 and TLS. */
(void)ssl3_IllegalParameter(ss);
PORT_SetError(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER);
return SECFailure;
}
buf->len = 0;
if (ws != wait_change_cipher) {
/* Ignore a CCS for TLS 1.3. This only happens if the server sends a
* HelloRetryRequest. In other cases, the CCS will fail decryption and
* will be discarded by ssl3_HandleRecord(). */
if (ws == wait_server_hello &&
ss->version >= SSL_LIBRARY_VERSION_TLS_1_3 &&
ss->ssl3.hs.helloRetry) {
PORT_Assert(!ss->sec.isServer);
return SECSuccess;
}
/* Note: For a server, we can't test ss->ssl3.hs.helloRetry or
* ss->version because the server might be stateless (and so it won't
* have set either value yet). Set a flag so that at least we will
* guarantee that the server will treat any ClientHello properly. */
if (ws == wait_client_hello &&
ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3 &&
!ss->ssl3.hs.receivedCcs) {
PORT_Assert(ss->sec.isServer);
ss->ssl3.hs.receivedCcs = PR_TRUE;
return SECSuccess;
}
(void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER);
return SECFailure;
}
SSL_TRC(3, ("%d: SSL3[%d] Set Current Read Cipher Suite to Pending",
SSL_GETPID(), ss->fd));
ssl_GetSpecWriteLock(ss); /*************************************/
PORT_Assert(ss->ssl3.prSpec);
ssl_CipherSpecRelease(ss->ssl3.crSpec);
ss->ssl3.crSpec = ss->ssl3.prSpec;
ss->ssl3.prSpec = NULL;
ssl_ReleaseSpecWriteLock(ss); /*************************************/
ss->ssl3.hs.ws = wait_finished;
return SECSuccess;
}
static CK_MECHANISM_TYPE
ssl3_GetMgfMechanismByHashType(SSLHashType hash)
{
switch (hash) {
case ssl_hash_sha256:
return CKG_MGF1_SHA256;
case ssl_hash_sha384:
return CKG_MGF1_SHA384;
case ssl_hash_sha512:
return CKG_MGF1_SHA512;
default:
PORT_Assert(0);
}
return CKG_MGF1_SHA256;
}
/* Function valid for >= TLS 1.2, only. */
static CK_MECHANISM_TYPE
ssl3_GetHashMechanismByHashType(SSLHashType hashType)
{
switch (hashType) {
case ssl_hash_sha512:
return CKM_SHA512;
case ssl_hash_sha384:
return CKM_SHA384;
case ssl_hash_sha256:
case ssl_hash_none:
/* ssl_hash_none is for pre-1.2 suites, which use SHA-256. */
return CKM_SHA256;
case ssl_hash_sha1:
return CKM_SHA_1;
default:
PORT_Assert(0);
}
return CKM_SHA256;
}
/* Function valid for >= TLS 1.2, only. */
static CK_MECHANISM_TYPE
ssl3_GetPrfHashMechanism(sslSocket *ss)
{
return ssl3_GetHashMechanismByHashType(ss->ssl3.hs.suite_def->prf_hash);
}
static SSLHashType
ssl3_GetSuitePrfHash(sslSocket *ss)
{
/* ssl_hash_none is for pre-1.2 suites, which use SHA-256. */
if (ss->ssl3.hs.suite_def->prf_hash == ssl_hash_none) {
return ssl_hash_sha256;
}
return ss->ssl3.hs.suite_def->prf_hash;
}
/* This method completes the derivation of the MS from the PMS.
**
** 1. Derive the MS, if possible, else return an error.
**
** 2. Check the version if |pms_version| is non-zero and if wrong,
** return an error.
**
** 3. If |msp| is nonzero, return MS in |*msp|.
** Called from:
** ssl3_ComputeMasterSecretInt
** tls_ComputeExtendedMasterSecretInt
*/
static SECStatus
ssl3_ComputeMasterSecretFinish(sslSocket *ss,
CK_MECHANISM_TYPE master_derive,
CK_MECHANISM_TYPE key_derive,
CK_VERSION *pms_version,
SECItem *params, CK_FLAGS keyFlags,
PK11SymKey *pms, PK11SymKey **msp)
{
PK11SymKey *ms = NULL;
ms = PK11_DeriveWithFlags(pms, master_derive,
params, key_derive,
CKA_DERIVE, 0, keyFlags);
if (!ms) {
ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
return SECFailure;
}
if (pms_version && ss->opt.detectRollBack) {
SSL3ProtocolVersion client_version;
client_version = pms_version->major << 8 | pms_version->minor;
if (IS_DTLS(ss)) {
client_version = dtls_DTLSVersionToTLSVersion(client_version);
}
if (client_version != ss->clientHelloVersion) {
/* Destroy MS. Version roll-back detected. */
PK11_FreeSymKey(ms);
ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
return SECFailure;
}
}
if (msp) {
*msp = ms;
} else {
PK11_FreeSymKey(ms);
}
return SECSuccess;
}
/* Compute the ordinary (pre draft-ietf-tls-session-hash) master
** secret and return it in |*msp|.
**
** Called from: ssl3_ComputeMasterSecret
*/
static SECStatus
ssl3_ComputeMasterSecretInt(sslSocket *ss, PK11SymKey *pms,
PK11SymKey **msp)
{
PRBool isTLS = (PRBool)(ss->version > SSL_LIBRARY_VERSION_3_0);
PRBool isTLS12 = (PRBool)(ss->version >= SSL_LIBRARY_VERSION_TLS_1_2);
/*
* Whenever isDH is true, we need to use CKM_TLS_MASTER_KEY_DERIVE_DH
* which, unlike CKM_TLS_MASTER_KEY_DERIVE, converts arbitrary size
* data into a 48-byte value, and does not expect to return the version.
*/
PRBool isDH = (PRBool)((ss->ssl3.hs.kea_def->exchKeyType == ssl_kea_dh) ||
(ss->ssl3.hs.kea_def->exchKeyType == ssl_kea_ecdh));
CK_MECHANISM_TYPE master_derive;
CK_MECHANISM_TYPE key_derive;
SECItem params;
CK_FLAGS keyFlags;
CK_VERSION pms_version;
CK_VERSION *pms_version_ptr = NULL;
/* master_params may be used as a CK_SSL3_MASTER_KEY_DERIVE_PARAMS */
CK_TLS12_MASTER_KEY_DERIVE_PARAMS master_params;
unsigned int master_params_len;
if (isTLS12) {
if (isDH)
master_derive = CKM_TLS12_MASTER_KEY_DERIVE_DH;
else
master_derive = CKM_TLS12_MASTER_KEY_DERIVE;
key_derive = CKM_TLS12_KEY_AND_MAC_DERIVE;
keyFlags = CKF_SIGN | CKF_VERIFY;
} else if (isTLS) {
if (isDH)
master_derive = CKM_TLS_MASTER_KEY_DERIVE_DH;
else
master_derive = CKM_TLS_MASTER_KEY_DERIVE;
key_derive = CKM_TLS_KEY_AND_MAC_DERIVE;
keyFlags = CKF_SIGN | CKF_VERIFY;
} else {
if (isDH)
master_derive = CKM_SSL3_MASTER_KEY_DERIVE_DH;
else
master_derive = CKM_SSL3_MASTER_KEY_DERIVE;
key_derive = CKM_SSL3_KEY_AND_MAC_DERIVE;
keyFlags = 0;
}
if (!isDH) {
pms_version_ptr = &pms_version;
}
master_params.pVersion = pms_version_ptr;
master_params.RandomInfo.pClientRandom = ss->ssl3.hs.client_random;
master_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH;
master_params.RandomInfo.pServerRandom = ss->ssl3.hs.server_random;
master_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH;
if (isTLS12) {
master_params.prfHashMechanism = ssl3_GetPrfHashMechanism(ss);
master_params_len = sizeof(CK_TLS12_MASTER_KEY_DERIVE_PARAMS);
} else {
/* prfHashMechanism is not relevant with this PRF */
master_params_len = sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS);
}
params.data = (unsigned char *)&master_params;
params.len = master_params_len;
return ssl3_ComputeMasterSecretFinish(ss, master_derive, key_derive,
pms_version_ptr, ¶ms,
keyFlags, pms, msp);
}
/* Compute the draft-ietf-tls-session-hash master
** secret and return it in |*msp|.
**
** Called from: ssl3_ComputeMasterSecret
*/
static SECStatus
tls_ComputeExtendedMasterSecretInt(sslSocket *ss, PK11SymKey *pms,
PK11SymKey **msp)
{
ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec;
CK_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_PARAMS extended_master_params;
SSL3Hashes hashes;
/*
* Determine whether to use the DH/ECDH or RSA derivation modes.
*/
/*
* TODO(ekr@rtfm.com): Verify that the slot can handle this key expansion
* mode. Bug 1198298 */
PRBool isDH = (PRBool)((ss->ssl3.hs.kea_def->exchKeyType == ssl_kea_dh) ||
(ss->ssl3.hs.kea_def->exchKeyType == ssl_kea_ecdh));
CK_MECHANISM_TYPE master_derive;
CK_MECHANISM_TYPE key_derive;
SECItem params;
const CK_FLAGS keyFlags = CKF_SIGN | CKF_VERIFY;
CK_VERSION pms_version;
CK_VERSION *pms_version_ptr = NULL;
SECStatus rv;
rv = ssl3_ComputeHandshakeHashes(ss, pwSpec, &hashes, 0);
if (rv != SECSuccess) {
PORT_Assert(0); /* Should never fail */
ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
return SECFailure;
}
if (isDH) {
master_derive = CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH;
} else {
master_derive = CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE;
pms_version_ptr = &pms_version;
}
if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_2) {
/* TLS 1.2+ */
extended_master_params.prfHashMechanism = ssl3_GetPrfHashMechanism(ss);
key_derive = CKM_TLS12_KEY_AND_MAC_DERIVE;
} else {
/* TLS < 1.2 */
extended_master_params.prfHashMechanism = CKM_TLS_PRF;
key_derive = CKM_TLS_KEY_AND_MAC_DERIVE;
}
extended_master_params.pVersion = pms_version_ptr;
extended_master_params.pSessionHash = hashes.u.raw;
extended_master_params.ulSessionHashLen = hashes.len;
params.data = (unsigned char *)&extended_master_params;
params.len = sizeof extended_master_params;
return ssl3_ComputeMasterSecretFinish(ss, master_derive, key_derive,
pms_version_ptr, ¶ms,
keyFlags, pms, msp);
}
/* Wrapper method to compute the master secret and return it in |*msp|.
**
** Called from ssl3_ComputeMasterSecret
*/
static SECStatus
ssl3_ComputeMasterSecret(sslSocket *ss, PK11SymKey *pms,
PK11SymKey **msp)
{
PORT_Assert(pms != NULL);
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
if (ssl3_ExtensionNegotiated(ss, ssl_extended_master_secret_xtn)) {
return tls_ComputeExtendedMasterSecretInt(ss, pms, msp);
} else {
return ssl3_ComputeMasterSecretInt(ss, pms, msp);
}
}
/*
* Derive encryption and MAC Keys (and IVs) from master secret
* Sets a useful error code when returning SECFailure.
*
* Called only from ssl3_InitPendingCipherSpec(),
* which in turn is called from
* ssl3_SendRSAClientKeyExchange (for Full handshake)
* ssl3_SendDHClientKeyExchange (for Full handshake)
* ssl3_HandleClientKeyExchange (for Full handshake)
* ssl3_HandleServerHello (for session restart)
* ssl3_HandleClientHello (for session restart)
* Caller MUST hold the specWriteLock, and SSL3HandshakeLock.
* ssl3_InitPendingCipherSpec does that.
*
*/
static SECStatus
ssl3_DeriveConnectionKeys(sslSocket *ss, PK11SymKey *masterSecret)
{
ssl3CipherSpec *pwSpec = ss->ssl3.pwSpec;
ssl3CipherSpec *prSpec = ss->ssl3.prSpec;
ssl3CipherSpec *clientSpec;
ssl3CipherSpec *serverSpec;
PRBool isTLS = (PRBool)(ss->version > SSL_LIBRARY_VERSION_3_0);
PRBool isTLS12 =
(PRBool)(isTLS && ss->version >= SSL_LIBRARY_VERSION_TLS_1_2);
const ssl3BulkCipherDef *cipher_def = pwSpec->cipherDef;
PK11SlotInfo *slot = NULL;
PK11SymKey *derivedKeyHandle = NULL;
void *pwArg = ss->pkcs11PinArg;
int keySize;
CK_TLS12_KEY_MAT_PARAMS key_material_params; /* may be used as a
* CK_SSL3_KEY_MAT_PARAMS */
unsigned int key_material_params_len;
CK_SSL3_KEY_MAT_OUT returnedKeys;
CK_MECHANISM_TYPE key_derive;
CK_MECHANISM_TYPE bulk_mechanism;
SSLCipherAlgorithm calg;
SECItem params;
PRBool skipKeysAndIVs = (PRBool)(cipher_def->calg == ssl_calg_null);
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
PORT_Assert(ss->opt.noLocks || ssl_HaveSpecWriteLock(ss));
PORT_Assert(masterSecret);
/* These functions operate in terms of who is writing specs. */
if (ss->sec.isServer) {
clientSpec = prSpec;
serverSpec = pwSpec;
} else {
clientSpec = pwSpec;
serverSpec = prSpec;
}
/*
* generate the key material
*/
if (cipher_def->type == type_block &&
ss->version >= SSL_LIBRARY_VERSION_TLS_1_1) {
/* Block ciphers in >= TLS 1.1 use a per-record, explicit IV. */
key_material_params.ulIVSizeInBits = 0;
PORT_Memset(clientSpec->keyMaterial.iv, 0, cipher_def->iv_size);
PORT_Memset(serverSpec->keyMaterial.iv, 0, cipher_def->iv_size);
}
key_material_params.bIsExport = PR_FALSE;
key_material_params.RandomInfo.pClientRandom = ss->ssl3.hs.client_random;
key_material_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH;
key_material_params.RandomInfo.pServerRandom = ss->ssl3.hs.server_random;
key_material_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH;
key_material_params.pReturnedKeyMaterial = &returnedKeys;
if (skipKeysAndIVs) {
keySize = 0;
returnedKeys.pIVClient = NULL;
returnedKeys.pIVServer = NULL;
key_material_params.ulKeySizeInBits = 0;
key_material_params.ulIVSizeInBits = 0;
} else {
keySize = cipher_def->key_size;
returnedKeys.pIVClient = clientSpec->keyMaterial.iv;
returnedKeys.pIVServer = serverSpec->keyMaterial.iv;
key_material_params.ulKeySizeInBits = cipher_def->secret_key_size * BPB;
key_material_params.ulIVSizeInBits = cipher_def->iv_size * BPB;
}
key_material_params.ulMacSizeInBits = pwSpec->macDef->mac_size * BPB;
calg = cipher_def->calg;
bulk_mechanism = ssl3_Alg2Mech(calg);
if (isTLS12) {
key_derive = CKM_TLS12_KEY_AND_MAC_DERIVE;
key_material_params.prfHashMechanism = ssl3_GetPrfHashMechanism(ss);
key_material_params_len = sizeof(CK_TLS12_KEY_MAT_PARAMS);
} else if (isTLS) {
key_derive = CKM_TLS_KEY_AND_MAC_DERIVE;
key_material_params_len = sizeof(CK_SSL3_KEY_MAT_PARAMS);
} else {
key_derive = CKM_SSL3_KEY_AND_MAC_DERIVE;
key_material_params_len = sizeof(CK_SSL3_KEY_MAT_PARAMS);
}
params.data = (unsigned char *)&key_material_params;
params.len = key_material_params_len;
/* CKM_SSL3_KEY_AND_MAC_DERIVE is defined to set ENCRYPT, DECRYPT, and
* DERIVE by DEFAULT */
derivedKeyHandle = PK11_Derive(masterSecret, key_derive, ¶ms,
bulk_mechanism, CKA_ENCRYPT, keySize);
if (!derivedKeyHandle) {
ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
return SECFailure;
}
/* we really should use the actual mac'ing mechanism here, but we
* don't because these types are used to map keytype anyway and both
* mac's map to the same keytype.
*/
slot = PK11_GetSlotFromKey(derivedKeyHandle);
PK11_FreeSlot(slot); /* slot is held until the key is freed */
clientSpec->keyMaterial.macKey =
PK11_SymKeyFromHandle(slot, derivedKeyHandle, PK11_OriginDerive,
CKM_SSL3_SHA1_MAC, returnedKeys.hClientMacSecret,
PR_TRUE, pwArg);
if (clientSpec->keyMaterial.macKey == NULL) {
goto loser; /* loser sets err */
}
serverSpec->keyMaterial.macKey =
PK11_SymKeyFromHandle(slot, derivedKeyHandle, PK11_OriginDerive,
CKM_SSL3_SHA1_MAC, returnedKeys.hServerMacSecret,
PR_TRUE, pwArg);
if (serverSpec->keyMaterial.macKey == NULL) {
goto loser; /* loser sets err */
}
if (!skipKeysAndIVs) {
clientSpec->keyMaterial.key =
PK11_SymKeyFromHandle(slot, derivedKeyHandle, PK11_OriginDerive,
bulk_mechanism, returnedKeys.hClientKey,
PR_TRUE, pwArg);
if (clientSpec->keyMaterial.key == NULL) {
goto loser; /* loser sets err */
}
serverSpec->keyMaterial.key =
PK11_SymKeyFromHandle(slot, derivedKeyHandle, PK11_OriginDerive,
bulk_mechanism, returnedKeys.hServerKey,
PR_TRUE, pwArg);
if (serverSpec->keyMaterial.key == NULL) {
goto loser; /* loser sets err */
}
}
PK11_FreeSymKey(derivedKeyHandle);
return SECSuccess;
loser:
PK11_FreeSymKey(derivedKeyHandle);
ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);
return SECFailure;
}
void
ssl3_CoalesceEchHandshakeHashes(sslSocket *ss)
{
/* |sha| contains the CHOuter transcript, which is the singular
* transcript if not doing ECH. If the server responded with 1.2,
* contexts are not yet initialized. */
if (ss->ssl3.hs.echAccepted) {
if (ss->ssl3.hs.sha) {
PORT_Assert(ss->ssl3.hs.shaEchInner);
PK11_DestroyContext(ss->ssl3.hs.sha, PR_TRUE);
ss->ssl3.hs.sha = ss->ssl3.hs.shaEchInner;
ss->ssl3.hs.shaEchInner = NULL;
}
} else {
if (ss->ssl3.hs.shaEchInner) {
PK11_DestroyContext(ss->ssl3.hs.shaEchInner, PR_TRUE);
ss->ssl3.hs.shaEchInner = NULL;
}
}
}
/* ssl3_InitHandshakeHashes creates handshake hash contexts and hashes in
* buffered messages in ss->ssl3.hs.messages. Called from
* ssl3_NegotiateCipherSuite(), tls13_HandleClientHelloPart2(),
* and ssl3_HandleServerHello. */
SECStatus
ssl3_InitHandshakeHashes(sslSocket *ss)
{
SSL_TRC(30, ("%d: SSL3[%d]: start handshake hashes", SSL_GETPID(), ss->fd));
PORT_Assert(ss->ssl3.hs.hashType == handshake_hash_unknown);
if (ss->version == SSL_LIBRARY_VERSION_TLS_1_2) {
ss->ssl3.hs.hashType = handshake_hash_record;
} else {
PORT_Assert(!ss->ssl3.hs.md5 && !ss->ssl3.hs.sha);
/*
* note: We should probably lookup an SSL3 slot for these
* handshake hashes in hopes that we wind up with the same slots
* that the master secret will wind up in ...
*/
if (ss->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
/* determine the hash from the prf */
const SECOidData *hash_oid =
SECOID_FindOIDByMechanism(ssl3_GetPrfHashMechanism(ss));
/* Get the PKCS #11 mechanism for the Hash from the cipher suite (prf_hash)
* Convert that to the OidTag. We can then use that OidTag to create our
* PK11Context */
PORT_Assert(hash_oid != NULL);
if (hash_oid == NULL) {
ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
return SECFailure;
}
ss->ssl3.hs.sha = PK11_CreateDigestContext(hash_oid->offset);
if (ss->ssl3.hs.sha == NULL) {
ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
return SECFailure;
}
ss->ssl3.hs.hashType = handshake_hash_single;
if (PK11_DigestBegin(ss->ssl3.hs.sha) != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
return SECFailure;
}
/* Transcript hash used on ECH client. */
if (!ss->sec.isServer && ss->ssl3.hs.echHpkeCtx) {
ss->ssl3.hs.shaEchInner = PK11_CreateDigestContext(hash_oid->offset);
if (ss->ssl3.hs.shaEchInner == NULL) {
ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
return SECFailure;
}
if (PK11_DigestBegin(ss->ssl3.hs.shaEchInner) != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
return SECFailure;
}
}
} else {
/* Both ss->ssl3.hs.md5 and ss->ssl3.hs.sha should be NULL or
* created successfully. */
ss->ssl3.hs.md5 = PK11_CreateDigestContext(SEC_OID_MD5);
if (ss->ssl3.hs.md5 == NULL) {
ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
return SECFailure;
}
ss->ssl3.hs.sha = PK11_CreateDigestContext(SEC_OID_SHA1);
if (ss->ssl3.hs.sha == NULL) {
PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE);
ss->ssl3.hs.md5 = NULL;
ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
return SECFailure;
}
ss->ssl3.hs.hashType = handshake_hash_combo;
if (PK11_DigestBegin(ss->ssl3.hs.md5) != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
return SECFailure;
}
if (PK11_DigestBegin(ss->ssl3.hs.sha) != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
return SECFailure;
}
}
}
if (ss->ssl3.hs.hashType != handshake_hash_record &&
ss->ssl3.hs.messages.len > 0) {
/* When doing ECH, ssl3_UpdateHandshakeHashes will store outer messages
* into the both the outer and inner transcripts.
* ssl3_UpdateDefaultHandshakeHashes uses the default context which is
* the outer when doing client ECH. For ECH shared-mode or backend
* servers only the hs.messages buffer is used. */
if (ssl3_UpdateDefaultHandshakeHashes(ss, ss->ssl3.hs.messages.buf,
ss->ssl3.hs.messages.len) != SECSuccess) {
return SECFailure;
}
/* When doing ECH, deriving the accept_confirmation value requires all
* messages up to and including the ServerHello
* (see draft-ietf-tls-esni-14, Section 7.2).
*
* Don't free the transcript buffer until confirmation calculation. */
if (!ss->ssl3.hs.echHpkeCtx && !ss->opt.enableTls13BackendEch) {
sslBuffer_Clear(&ss->ssl3.hs.messages);
}
}
if (ss->ssl3.hs.shaEchInner &&
ss->ssl3.hs.echInnerMessages.len > 0) {
if (PK11_DigestOp(ss->ssl3.hs.shaEchInner, ss->ssl3.hs.echInnerMessages.buf,
ss->ssl3.hs.echInnerMessages.len) != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
return SECFailure;
}
if (!ss->ssl3.hs.echHpkeCtx) {
sslBuffer_Clear(&ss->ssl3.hs.echInnerMessages);
}
}
return SECSuccess;
}
void
ssl3_RestartHandshakeHashes(sslSocket *ss)
{
SSL_TRC(30, ("%d: SSL3[%d]: reset handshake hashes",
SSL_GETPID(), ss->fd));
ss->ssl3.hs.hashType = handshake_hash_unknown;
ss->ssl3.hs.messages.len = 0;
ss->ssl3.hs.echInnerMessages.len = 0;
if (ss->ssl3.hs.md5) {
PK11_DestroyContext(ss->ssl3.hs.md5, PR_TRUE);
ss->ssl3.hs.md5 = NULL;
}
if (ss->ssl3.hs.sha) {
PK11_DestroyContext(ss->ssl3.hs.sha, PR_TRUE);
ss->ssl3.hs.sha = NULL;
}
if (ss->ssl3.hs.shaEchInner) {
PK11_DestroyContext(ss->ssl3.hs.shaEchInner, PR_TRUE);
ss->ssl3.hs.shaEchInner = NULL;
}
if (ss->ssl3.hs.shaPostHandshake) {
PK11_DestroyContext(ss->ssl3.hs.shaPostHandshake, PR_TRUE);
ss->ssl3.hs.shaPostHandshake = NULL;
}
}
/* Add the provided bytes to the handshake hash context. When doing
* TLS 1.3 ECH, |target| may be provided to specify only the inner/outer
* transcript, else the input is added to both contexts. This happens
* only on the client. On the server, only the default context is used. */
SECStatus
ssl3_UpdateHandshakeHashesInt(sslSocket *ss, const unsigned char *b,
unsigned int l, sslBuffer *target)
{
SECStatus rv = SECSuccess;
PRBool explicit = (target != NULL);
PRBool appendToEchInner = !ss->sec.isServer &&
ss->ssl3.hs.echHpkeCtx &&
!explicit;
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
PORT_Assert(target != &ss->ssl3.hs.echInnerMessages ||
!ss->sec.isServer);
if (target == NULL) {
/* Default context. */
target = &ss->ssl3.hs.messages;
}
/* With TLS 1.3, and versions TLS.1.1 and older, we keep the hash(es)
* always up to date. However, we must initially buffer the handshake
* messages, until we know what to do.
* If ss->ssl3.hs.hashType != handshake_hash_unknown,
* it means we know what to do. We calculate (hash our input),
* and we stop appending to the buffer.
*
* With TLS 1.2, we always append all handshake messages,
* and never update the hash, because the hash function we must use for
* certificate_verify might be different from the hash function we use
* when signing other handshake hashes. */
if (ss->ssl3.hs.hashType == handshake_hash_unknown ||
ss->ssl3.hs.hashType == handshake_hash_record) {
rv = sslBuffer_Append(target, b, l);
if (rv != SECSuccess) {
return SECFailure;
}
if (appendToEchInner) {
return sslBuffer_Append(&ss->ssl3.hs.echInnerMessages, b, l);
}
return SECSuccess;
}
PRINT_BUF(90, (ss, "handshake hash input:", b, l));
if (ss->ssl3.hs.hashType == handshake_hash_single) {
PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
if (target == &ss->ssl3.hs.messages) {
rv = PK11_DigestOp(ss->ssl3.hs.sha, b, l);
if (rv != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
return rv;
}
}
if (ss->ssl3.hs.shaEchInner &&
(target == &ss->ssl3.hs.echInnerMessages || !explicit)) {
rv = PK11_DigestOp(ss->ssl3.hs.shaEchInner, b, l);
if (rv != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
return rv;
}
}
} else if (ss->ssl3.hs.hashType == handshake_hash_combo) {
rv = PK11_DigestOp(ss->ssl3.hs.md5, b, l);
if (rv != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
return rv;
}
rv = PK11_DigestOp(ss->ssl3.hs.sha, b, l);
if (rv != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
return rv;
}
}
return rv;
}
static SECStatus
ssl3_UpdateDefaultHandshakeHashes(sslSocket *ss, const unsigned char *b,
unsigned int l)
{
return ssl3_UpdateHandshakeHashesInt(ss, b, l,
&ss->ssl3.hs.messages);
}
static SECStatus
ssl3_UpdateInnerHandshakeHashes(sslSocket *ss, const unsigned char *b,
unsigned int l)
{
return ssl3_UpdateHandshakeHashesInt(ss, b, l,
&ss->ssl3.hs.echInnerMessages);
}
/*
* Handshake messages
*/
/* Called from ssl3_InitHandshakeHashes()
** ssl3_AppendHandshake()
** ssl3_HandleV2ClientHello()
** ssl3_HandleHandshakeMessage()
** Caller must hold the ssl3Handshake lock.
*/
SECStatus
ssl3_UpdateHandshakeHashes(sslSocket *ss, const unsigned char *b, unsigned int l)
{
return ssl3_UpdateHandshakeHashesInt(ss, b, l, NULL);
}
SECStatus
ssl3_UpdatePostHandshakeHashes(sslSocket *ss, const unsigned char *b, unsigned int l)
{
SECStatus rv = SECSuccess;
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
PRINT_BUF(90, (ss, "post handshake hash input:", b, l));
PORT_Assert(ss->ssl3.hs.hashType == handshake_hash_single);
PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
rv = PK11_DigestOp(ss->ssl3.hs.shaPostHandshake, b, l);
if (rv != SECSuccess) {
PORT_SetError(SSL_ERROR_DIGEST_FAILURE);
}
return rv;
}
SECStatus
ssl3_AppendHandshakeHeader(sslSocket *ss, SSLHandshakeType t, PRUint32 length)
{
SECStatus rv;
/* If we already have a message in place, we need to enqueue it.
* This empties the buffer. This is a convenient place to call
* dtls_StageHandshakeMessage to mark the message boundary.
*/
if (IS_DTLS(ss)) {
rv = dtls_StageHandshakeMessage(ss);
if (rv != SECSuccess) {
return rv;
}
}
SSL_TRC(30, ("%d: SSL3[%d]: append handshake header: type %s",
SSL_GETPID(), ss->fd, ssl3_DecodeHandshakeType(t)));
rv = ssl3_AppendHandshakeNumber(ss, t, 1);
if (rv != SECSuccess) {
return rv; /* error code set by AppendHandshake, if applicable. */
}
rv = ssl3_AppendHandshakeNumber(ss, length, 3);
if (rv != SECSuccess) {
return rv; /* error code set by AppendHandshake, if applicable. */
}
if (IS_DTLS(ss)) {
/* Note that we make an unfragmented message here. We fragment in the
* transmission code, if necessary */
rv = ssl3_AppendHandshakeNumber(ss, ss->ssl3.hs.sendMessageSeq, 2);
if (rv != SECSuccess) {
return rv; /* error code set by AppendHandshake, if applicable. */
}
ss->ssl3.hs.sendMessageSeq++;
/* 0 is the fragment offset, because it's not fragmented yet */
rv = ssl3_AppendHandshakeNumber(ss, 0, 3);
if (rv != SECSuccess) {
return rv; /* error code set by AppendHandshake, if applicable. */
}
/* Fragment length -- set to the packet length because not fragmented */
rv = ssl3_AppendHandshakeNumber(ss, length, 3);
if (rv != SECSuccess) {
return rv; /* error code set by AppendHandshake, if applicable. */
}
}
return rv; /* error code set by AppendHandshake, if applicable. */
}
/**************************************************************************
* Consume Handshake functions.
*
* All data used in these functions is protected by two locks,
* the RecvBufLock and the SSL3HandshakeLock
**************************************************************************/
/* Read up the next "bytes" number of bytes from the (decrypted) input
* stream "b" (which is *length bytes long). Copy them into buffer "v".
* Reduces *length by bytes. Advances *b by bytes.
*
* If this function returns SECFailure, it has already sent an alert,
* and has set a generic error code. The caller should probably
* override the generic error code by setting another.
*/
SECStatus
ssl3_ConsumeHandshake(sslSocket *ss, void *v, PRUint32 bytes, PRUint8 **b,
PRUint32 *length)
{
PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
if ((PRUint32)bytes > *length) {
return ssl3_DecodeError(ss);
}
PORT_Memcpy(v, *b, bytes);
PRINT_BUF(60, (ss, "consume bytes:", *b, bytes));
*b += bytes;
*length -= bytes;
return SECSuccess;
}
/* Read up the next "bytes" number of bytes from the (decrypted) input
* stream "b" (which is *length bytes long), and interpret them as an
* integer in network byte order. Sets *num to the received value.
* Reduces *length by bytes. Advances *b by bytes.
*
* On error, an alert has been sent, and a generic error code has been set.
*/
SECStatus
ssl3_ConsumeHandshakeNumber64(sslSocket *ss, PRUint64 *num, PRUint32 bytes,
PRUint8 **b, PRUint32 *length)
{
PRUint8 *buf = *b;
PRUint32 i;
PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
*num = 0;
if (bytes > sizeof(*num)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
if (bytes > *length) {
return ssl3_DecodeError(ss);
}
PRINT_BUF(60, (ss, "consume bytes:", *b, bytes));
for (i = 0; i < bytes; i++) {
*num = (*num << 8) + buf[i];
}
*b += bytes;
*length -= bytes;
return SECSuccess;
}
SECStatus
ssl3_ConsumeHandshakeNumber(sslSocket *ss, PRUint32 *num, PRUint32 bytes,
PRUint8 **b, PRUint32 *length)
{
PRUint64 num64;
SECStatus rv;
PORT_Assert(bytes <= sizeof(*num));
if (bytes > sizeof(*num)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
rv = ssl3_ConsumeHandshakeNumber64(ss, &num64, bytes, b, length);
if (rv != SECSuccess) {
return SECFailure;
}
*num = num64 & 0xffffffff;
return SECSuccess;
}
/* Read in two values from the incoming decrypted byte stream "b", which is
* *length bytes long. The first value is a number whose size is "bytes"
* bytes long. The second value is a byte-string whose size is the value
* of the first number received. The latter byte-string, and its length,
* is returned in the SECItem i.
*
* Returns SECFailure (-1) on failure.
* On error, an alert has been sent, and a generic error code has been set.
*
* RADICAL CHANGE for NSS 3.11. All callers of this function make copies
* of the data returned in the SECItem *i, so making a copy of it here
* is simply wasteful. So, This function now just sets SECItem *i to
* point to the values in the buffer **b.
*/
SECStatus
ssl3_ConsumeHandshakeVariable(sslSocket *ss, SECItem *i, PRUint32 bytes,
PRUint8 **b, PRUint32 *length)
{
PRUint32 count;
SECStatus rv;
PORT_Assert(bytes <= 3);
i->len = 0;
i->data = NULL;
i->type = siBuffer;
rv = ssl3_ConsumeHandshakeNumber(ss, &count, bytes, b, length);
if (rv != SECSuccess) {
return SECFailure;
}
if (count > 0) {
if (count > *length) {
return ssl3_DecodeError(ss);
}
i->data = *b;
i->len = count;
*b += count;
*length -= count;
}
return SECSuccess;
}
/* ssl3_TLSHashAlgorithmToOID converts a TLS hash identifier into an OID value.
* If the hash is not recognised, SEC_OID_UNKNOWN is returned.
*
* See https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
SECOidTag
ssl3_HashTypeToOID(SSLHashType hashType)
{
switch (hashType) {
case ssl_hash_sha1:
return SEC_OID_SHA1;
case ssl_hash_sha256:
return SEC_OID_SHA256;
case ssl_hash_sha384:
return SEC_OID_SHA384;
case ssl_hash_sha512:
return SEC_OID_SHA512;
default:
break;
}
return SEC_OID_UNKNOWN;
}
SECOidTag
ssl3_AuthTypeToOID(SSLAuthType authType)
{
switch (authType) {
case ssl_auth_rsa_sign:
return SEC_OID_PKCS1_RSA_ENCRYPTION;
case ssl_auth_rsa_pss:
return SEC_OID_PKCS1_RSA_PSS_SIGNATURE;
case ssl_auth_ecdsa:
return SEC_OID_ANSIX962_EC_PUBLIC_KEY;
case ssl_auth_dsa:
return SEC_OID_ANSIX9_DSA_SIGNATURE;
default:
break;
}
/* shouldn't ever get there */
PORT_Assert(0);
return SEC_OID_UNKNOWN;
}
SSLHashType
ssl_SignatureSchemeToHashType(SSLSignatureScheme scheme)
{
switch (scheme) {
case ssl_sig_rsa_pkcs1_sha1:
case ssl_sig_dsa_sha1:
case ssl_sig_ecdsa_sha1:
return ssl_hash_sha1;
case ssl_sig_rsa_pkcs1_sha256:
case ssl_sig_ecdsa_secp256r1_sha256:
case ssl_sig_rsa_pss_rsae_sha256:
case ssl_sig_rsa_pss_pss_sha256:
case ssl_sig_dsa_sha256:
return ssl_hash_sha256;
case ssl_sig_rsa_pkcs1_sha384:
case ssl_sig_ecdsa_secp384r1_sha384:
case ssl_sig_rsa_pss_rsae_sha384:
case ssl_sig_rsa_pss_pss_sha384:
case ssl_sig_dsa_sha384:
return ssl_hash_sha384;
case ssl_sig_rsa_pkcs1_sha512:
case ssl_sig_ecdsa_secp521r1_sha512:
case ssl_sig_rsa_pss_rsae_sha512:
case ssl_sig_rsa_pss_pss_sha512:
case ssl_sig_dsa_sha512:
return ssl_hash_sha512;
case ssl_sig_rsa_pkcs1_sha1md5:
return ssl_hash_none; /* Special for TLS 1.0/1.1. */
case ssl_sig_none:
case ssl_sig_ed25519:
case ssl_sig_ed448:
break;
}
PORT_Assert(0);
return ssl_hash_none;
}
static PRBool
ssl_SignatureSchemeMatchesSpkiOid(SSLSignatureScheme scheme, SECOidTag spkiOid)
{
SECOidTag authOid = ssl3_AuthTypeToOID(ssl_SignatureSchemeToAuthType(scheme));
if (spkiOid == authOid) {
return PR_TRUE;
}
if ((authOid == SEC_OID_PKCS1_RSA_ENCRYPTION) &&
(spkiOid == SEC_OID_X500_RSA_ENCRYPTION)) {
return PR_TRUE;
}
return PR_FALSE;
}
/* Validate that the signature scheme works for the given key type. */
PRBool
ssl_SignatureSchemeValid(SSLSignatureScheme scheme, SECOidTag spkiOid,
PRBool isTls13)
{
if (!ssl_IsSupportedSignatureScheme(scheme)) {
return PR_FALSE;
}
/* if we are purposefully passed SEC_OID_UNKNOWN, it means
* we not checking the scheme against a potential key, so skip
* the call */
if ((spkiOid != SEC_OID_UNKNOWN) &&
!ssl_SignatureSchemeMatchesSpkiOid(scheme, spkiOid)) {
return PR_FALSE;
}
if (isTls13) {
if (ssl_SignatureSchemeToHashType(scheme) == ssl_hash_sha1) {
return PR_FALSE;
}
if (ssl_IsRsaPkcs1SignatureScheme(scheme)) {
return PR_FALSE;
}
if (ssl_IsDsaSignatureScheme(scheme)) {
return PR_FALSE;
}
/* With TLS 1.3, EC keys should have been selected based on calling
* ssl_SignatureSchemeFromSpki(), reject them otherwise. */
return spkiOid != SEC_OID_ANSIX962_EC_PUBLIC_KEY;
}
return PR_TRUE;
}
static SECStatus
ssl_SignatureSchemeFromPssSpki(const CERTSubjectPublicKeyInfo *spki,
SSLSignatureScheme *scheme)
{
SECKEYRSAPSSParams pssParam = { 0 };
PORTCheapArenaPool arena;
SECStatus rv;
/* The key doesn't have parameters, boo. */
if (!spki->algorithm.parameters.len) {
*scheme = ssl_sig_none;
return SECSuccess;
}
PORT_InitCheapArena(&arena, DER_DEFAULT_CHUNKSIZE);
rv = SEC_QuickDERDecodeItem(&arena.arena, &pssParam,
SEC_ASN1_GET(SECKEY_RSAPSSParamsTemplate),
&spki->algorithm.parameters);
if (rv != SECSuccess) {
goto loser;
}
/* Not having hashAlg means SHA-1 and we don't accept that. */
if (!pssParam.hashAlg) {
goto loser;
}
switch (SECOID_GetAlgorithmTag(pssParam.hashAlg)) {
case SEC_OID_SHA256:
*scheme = ssl_sig_rsa_pss_pss_sha256;
break;
case SEC_OID_SHA384:
*scheme = ssl_sig_rsa_pss_pss_sha384;
break;
case SEC_OID_SHA512:
*scheme = ssl_sig_rsa_pss_pss_sha512;
break;
default:
goto loser;
}
PORT_DestroyCheapArena(&arena);
return SECSuccess;
loser:
PORT_DestroyCheapArena(&arena);
PORT_SetError(SSL_ERROR_BAD_CERTIFICATE);
return SECFailure;
}
static SECStatus
ssl_SignatureSchemeFromEcSpki(const CERTSubjectPublicKeyInfo *spki,
SSLSignatureScheme *scheme)
{
const sslNamedGroupDef *group;
SECKEYPublicKey *key;
key = SECKEY_ExtractPublicKey(spki);
if (!key) {
PORT_SetError(SSL_ERROR_BAD_CERTIFICATE);
return SECFailure;
}
group = ssl_ECPubKey2NamedGroup(key);
SECKEY_DestroyPublicKey(key);
if (!group) {
PORT_SetError(SSL_ERROR_BAD_CERTIFICATE);
return SECFailure;
}
switch (group->name) {
case ssl_grp_ec_secp256r1:
*scheme = ssl_sig_ecdsa_secp256r1_sha256;
return SECSuccess;
case ssl_grp_ec_secp384r1:
*scheme = ssl_sig_ecdsa_secp384r1_sha384;
return SECSuccess;
case ssl_grp_ec_secp521r1:
*scheme = ssl_sig_ecdsa_secp521r1_sha512;
return SECSuccess;
default:
break;
}
PORT_SetError(SSL_ERROR_BAD_CERTIFICATE);
return SECFailure;
}
/* Newer signature schemes are designed so that a single SPKI can be used with
* that scheme. This determines that scheme from the SPKI. If the SPKI doesn't
* have a single scheme, |*scheme| is set to ssl_sig_none. */
SECStatus
ssl_SignatureSchemeFromSpki(const CERTSubjectPublicKeyInfo *spki,
PRBool isTls13, SSLSignatureScheme *scheme)
{
SECOidTag spkiOid = SECOID_GetAlgorithmTag(&spki->algorithm);
if (spkiOid == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
return ssl_SignatureSchemeFromPssSpki(spki, scheme);
}
/* Only do this lookup for TLS 1.3, where the scheme can be determined from
* the SPKI alone because the ECDSA key size determines the hash. Earlier
* TLS versions allow the same EC key to be used with different hashes. */
if (isTls13 && spkiOid == SEC_OID_ANSIX962_EC_PUBLIC_KEY) {
return ssl_SignatureSchemeFromEcSpki(spki, scheme);
}
*scheme = ssl_sig_none;
return SECSuccess;
}
/* Check that a signature scheme is enabled by configuration. */
PRBool
ssl_SignatureSchemeEnabled(const sslSocket *ss, SSLSignatureScheme scheme)
{
unsigned int i;
for (i = 0; i < ss->ssl3.signatureSchemeCount; ++i) {
if (scheme == ss->ssl3.signatureSchemes[i]) {
return PR_TRUE;
}
}
return PR_FALSE;
}
static PRBool
ssl_SignatureKeyMatchesSpkiOid(const ssl3KEADef *keaDef, SECOidTag spkiOid)
{
switch (spkiOid) {
case SEC_OID_X500_RSA_ENCRYPTION:
case SEC_OID_PKCS1_RSA_ENCRYPTION:
case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
return keaDef->signKeyType == rsaKey;
case SEC_OID_ANSIX9_DSA_SIGNATURE:
return keaDef->signKeyType == dsaKey;
case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
return keaDef->signKeyType == ecKey;
default:
break;
}
return PR_FALSE;
}
/* ssl3_CheckSignatureSchemeConsistency checks that the signature algorithm
* identifier in |scheme| is consistent with the public key in |spki|. It also
* checks the hash algorithm against the configured signature algorithms. If
* all the tests pass, SECSuccess is returned. Otherwise, PORT_SetError is
* called and SECFailure is returned. */
SECStatus
ssl_CheckSignatureSchemeConsistency(sslSocket *ss, SSLSignatureScheme scheme,
CERTSubjectPublicKeyInfo *spki)
{
SSLSignatureScheme spkiScheme;
PRBool isTLS13 = ss->version == SSL_LIBRARY_VERSION_TLS_1_3;
SECOidTag spkiOid;
SECStatus rv;
rv = ssl_SignatureSchemeFromSpki(spki, isTLS13, &spkiScheme);
if (rv != SECSuccess) {
return SECFailure;
}
if (spkiScheme != ssl_sig_none) {
/* The SPKI in the certificate can only be used for a single scheme. */
if (spkiScheme != scheme ||
!ssl_SignatureSchemeEnabled(ss, scheme)) {
PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
return SECFailure;
}
return SECSuccess;
}
spkiOid = SECOID_GetAlgorithmTag(&spki->algorithm);
/* If we're a client, check that the signature algorithm matches the signing
* key type of the cipher suite. */
if (!isTLS13 && !ss->sec.isServer) {
if (!ssl_SignatureKeyMatchesSpkiOid(ss->ssl3.hs.kea_def, spkiOid)) {
PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
return SECFailure;
}
}
/* Verify that the signature scheme matches the signing key. */
if ((spkiOid == SEC_OID_UNKNOWN) ||
!ssl_SignatureSchemeValid(scheme, spkiOid, isTLS13)) {
PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
return SECFailure;
}
if (!ssl_SignatureSchemeEnabled(ss, scheme)) {
PORT_SetError(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
return SECFailure;
}
return SECSuccess;
}
PRBool
ssl_IsSupportedSignatureScheme(SSLSignatureScheme scheme)
{
switch (scheme) {
case ssl_sig_rsa_pkcs1_sha1:
case ssl_sig_rsa_pkcs1_sha256:
case ssl_sig_rsa_pkcs1_sha384:
case ssl_sig_rsa_pkcs1_sha512:
case ssl_sig_rsa_pss_rsae_sha256:
case ssl_sig_rsa_pss_rsae_sha384:
case ssl_sig_rsa_pss_rsae_sha512:
case ssl_sig_rsa_pss_pss_sha256:
case ssl_sig_rsa_pss_pss_sha384:
case ssl_sig_rsa_pss_pss_sha512:
case ssl_sig_ecdsa_secp256r1_sha256:
case ssl_sig_ecdsa_secp384r1_sha384:
case ssl_sig_ecdsa_secp521r1_sha512:
case ssl_sig_dsa_sha1:
case ssl_sig_dsa_sha256:
case ssl_sig_dsa_sha384:
case ssl_sig_dsa_sha512:
case ssl_sig_ecdsa_sha1:
return ssl_SchemePolicyOK(scheme, kSSLSigSchemePolicy);
break;
case ssl_sig_rsa_pkcs1_sha1md5:
case ssl_sig_none:
case ssl_sig_ed25519:
case ssl_sig_ed448:
return PR_FALSE;
}
return PR_FALSE;
}
PRBool
ssl_IsRsaPssSignatureScheme(SSLSignatureScheme scheme)
{
switch (scheme) {
case ssl_sig_rsa_pss_rsae_sha256:
case ssl_sig_rsa_pss_rsae_sha384:
case ssl_sig_rsa_pss_rsae_sha512:
case ssl_sig_rsa_pss_pss_sha256:
case ssl_sig_rsa_pss_pss_sha384:
case ssl_sig_rsa_pss_pss_sha512:
return PR_TRUE;
default:
return PR_FALSE;
}
return PR_FALSE;
}
PRBool
ssl_IsRsaeSignatureScheme(SSLSignatureScheme scheme)
{
switch (scheme) {
case ssl_sig_rsa_pss_rsae_sha256:
case ssl_sig_rsa_pss_rsae_sha384:
case ssl_sig_rsa_pss_rsae_sha512:
return PR_TRUE;
default:
return PR_FALSE;
}
return PR_FALSE;
}
PRBool
ssl_IsRsaPkcs1SignatureScheme(SSLSignatureScheme scheme)
{
switch (scheme) {
case ssl_sig_rsa_pkcs1_sha256:
case ssl_sig_rsa_pkcs1_sha384:
case ssl_sig_rsa_pkcs1_sha512:
case ssl_sig_rsa_pkcs1_sha1:
return PR_TRUE;
default:
return PR_FALSE;
}
return PR_FALSE;
}
PRBool
ssl_IsDsaSignatureScheme(SSLSignatureScheme scheme)
{
switch (scheme) {
case ssl_sig_dsa_sha256:
case ssl_sig_dsa_sha384:
case ssl_sig_dsa_sha512:
case ssl_sig_dsa_sha1:
return PR_TRUE;
default:
return PR_FALSE;
}
return PR_FALSE;
}
SSLAuthType
ssl_SignatureSchemeToAuthType(SSLSignatureScheme scheme)
{
switch (scheme) {
case ssl_sig_rsa_pkcs1_sha1:
case ssl_sig_rsa_pkcs1_sha1md5:
case ssl_sig_rsa_pkcs1_sha256:
case ssl_sig_rsa_pkcs1_sha384:
case ssl_sig_rsa_pkcs1_sha512:
/* We report based on the key type for PSS signatures. */
case ssl_sig_rsa_pss_rsae_sha256:
case ssl_sig_rsa_pss_rsae_sha384:
case ssl_sig_rsa_pss_rsae_sha512:
return ssl_auth_rsa_sign;
case ssl_sig_rsa_pss_pss_sha256:
case ssl_sig_rsa_pss_pss_sha384:
case ssl_sig_rsa_pss_pss_sha512:
return ssl_auth_rsa_pss;
case ssl_sig_ecdsa_secp256r1_sha256:
case ssl_sig_ecdsa_secp384r1_sha384:
case ssl_sig_ecdsa_secp521r1_sha512:
case ssl_sig_ecdsa_sha1:
return ssl_auth_ecdsa;
case ssl_sig_dsa_sha1:
case ssl_sig_dsa_sha256:
case ssl_sig_dsa_sha384:
case ssl_sig_dsa_sha512:
return ssl_auth_dsa;
default:
PORT_Assert(0);
}
return ssl_auth_null;
}
/* ssl_ConsumeSignatureScheme reads a SSLSignatureScheme (formerly
* SignatureAndHashAlgorithm) structure from |b| and puts the resulting value
* into |out|. |b| and |length| are updated accordingly.
*
* See https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
SECStatus
ssl_ConsumeSignatureScheme(sslSocket *ss, PRUint8 **b,
PRUint32 *length, SSLSignatureScheme *out)
{
PRUint32 tmp;
SECStatus rv;
rv = ssl3_ConsumeHandshakeNumber(ss, &tmp, 2, b, length);
if (rv != SECSuccess) {
return SECFailure; /* Alert sent, Error code set already. */
}
if (!ssl_IsSupportedSignatureScheme((SSLSignatureScheme)tmp)) {
SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
PORT_SetError(SSL_ERROR_UNSUPPORTED_SIGNATURE_ALGORITHM);
return SECFailure;
}
*out = (SSLSignatureScheme)tmp;
return SECSuccess;
}
/**************************************************************************
* end of Consume Handshake functions.
**************************************************************************/
static SECStatus
ssl3_ComputeHandshakeHash(unsigned char *buf, unsigned int len,
SSLHashType hashAlg, SSL3Hashes *hashes)
{
SECStatus rv = SECFailure;
PK11Context *hashContext = PK11_CreateDigestContext(
ssl3_HashTypeToOID(hashAlg));
if (!hashContext) {
return rv;
}
rv = PK11_DigestBegin(hashContext);
if (rv == SECSuccess) {
rv = PK11_DigestOp(hashContext, buf, len);
}
if (rv == SECSuccess) {
rv = PK11_DigestFinal(hashContext, hashes->u.raw, &hashes->len,
sizeof(hashes->u.raw));
}
if (rv == SECSuccess) {
hashes->hashAlg = hashAlg;
}
PK11_DestroyContext(hashContext, PR_TRUE);
return rv;
}
/* Extract the hashes of handshake messages to this point.
* Called from ssl3_SendCertificateVerify
* ssl3_SendFinished
* ssl3_HandleHandshakeMessage
*
* Caller must hold the SSL3HandshakeLock.
* Caller must hold a read or write lock on the Spec R/W lock.
* (There is presently no way to assert on a Read lock.)
*/
SECStatus
ssl3_ComputeHandshakeHashes(sslSocket *ss,
ssl3CipherSpec *spec, /* uses ->master_secret */
SSL3Hashes *hashes, /* output goes here. */
PRUint32 sender)
{
SECStatus rv = SECSuccess;
PRBool isTLS = (PRBool)(spec->version > SSL_LIBRARY_VERSION_3_0);
unsigned int outLength;
PRUint8 md5_inner[MAX_MAC_LENGTH];
PRUint8 sha_inner[MAX_MAC_LENGTH];
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
if (ss->ssl3.hs.hashType == handshake_hash_unknown) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
hashes->hashAlg = ssl_hash_none;
if (ss->ssl3.hs.hashType == handshake_hash_single) {
PK11Context *h;
unsigned int stateLen;
unsigned char stackBuf[1024];
unsigned char *stateBuf = NULL;
h = ss->ssl3.hs.sha;
stateBuf = PK11_SaveContextAlloc(h, stackBuf,
sizeof(stackBuf), &stateLen);
if (stateBuf == NULL) {
ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
rv = SECFailure;
goto tls12_loser;
}
rv |= PK11_DigestFinal(h, hashes->u.raw, &hashes->len,
sizeof(hashes->u.raw));
if (rv != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
rv = SECFailure;
goto tls12_loser;
}
hashes->hashAlg = ssl3_GetSuitePrfHash(ss);
tls12_loser:
if (stateBuf) {
if (PK11_RestoreContext(h, stateBuf, stateLen) != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_DIGEST_FAILURE);
rv = SECFailure;
}
if (stateBuf != stackBuf) {
PORT_ZFree(stateBuf, stateLen);
}
}
} else if (ss->ssl3.hs.hashType == handshake_hash_record) {
rv = ssl3_ComputeHandshakeHash(ss->ssl3.hs.messages.buf,
ss->ssl3.hs.messages.len,
ssl3_GetSuitePrfHash(ss),
hashes);
} else {
PK11Context *md5;
PK11Context *sha = NULL;
unsigned char *md5StateBuf = NULL;
unsigned char *shaStateBuf = NULL;
unsigned int md5StateLen, shaStateLen;
unsigned char md5StackBuf[256];
unsigned char shaStackBuf[512];
const int md5Pad = ssl_GetMacDefByAlg(ssl_mac_md5)->pad_size;
const int shaPad = ssl_GetMacDefByAlg(ssl_mac_sha)->pad_size;
md5StateBuf = PK11_SaveContextAlloc(ss->ssl3.hs.md5, md5StackBuf,
sizeof md5StackBuf, &md5StateLen);
if (md5StateBuf == NULL) {
ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
rv = SECFailure;
goto loser;
}
md5 = ss->ssl3.hs.md5;
shaStateBuf = PK11_SaveContextAlloc(ss->ssl3.hs.sha, shaStackBuf,
sizeof shaStackBuf, &shaStateLen);
if (shaStateBuf == NULL) {
ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
rv = SECFailure;
goto loser;
}
sha = ss->ssl3.hs.sha;
if (!isTLS) {
/* compute hashes for SSL3. */
unsigned char s[4];
if (!spec->masterSecret) {
PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE);
rv = SECFailure;
goto loser;
}
s[0] = (unsigned char)(sender >> 24);
s[1] = (unsigned char)(sender >> 16);
s[2] = (unsigned char)(sender >> 8);
s[3] = (unsigned char)sender;
if (sender != 0) {
rv |= PK11_DigestOp(md5, s, 4);
PRINT_BUF(95, (NULL, "MD5 inner: sender", s, 4));
}
PRINT_BUF(95, (NULL, "MD5 inner: MAC Pad 1", mac_pad_1, md5Pad));
rv |= PK11_DigestKey(md5, spec->masterSecret);
rv |= PK11_DigestOp(md5, mac_pad_1, md5Pad);
rv |= PK11_DigestFinal(md5, md5_inner, &outLength, MD5_LENGTH);
PORT_Assert(rv != SECSuccess || outLength == MD5_LENGTH);
if (rv != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
rv = SECFailure;
goto loser;
}
PRINT_BUF(95, (NULL, "MD5 inner: result", md5_inner, outLength));
if (sender != 0) {
rv |= PK11_DigestOp(sha, s, 4);
PRINT_BUF(95, (NULL, "SHA inner: sender", s, 4));
}
PRINT_BUF(95, (NULL, "SHA inner: MAC Pad 1", mac_pad_1, shaPad));
rv |= PK11_DigestKey(sha, spec->masterSecret);
rv |= PK11_DigestOp(sha, mac_pad_1, shaPad);
rv |= PK11_DigestFinal(sha, sha_inner, &outLength, SHA1_LENGTH);
PORT_Assert(rv != SECSuccess || outLength == SHA1_LENGTH);
if (rv != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
rv = SECFailure;
goto loser;
}
PRINT_BUF(95, (NULL, "SHA inner: result", sha_inner, outLength));
PRINT_BUF(95, (NULL, "MD5 outer: MAC Pad 2", mac_pad_2, md5Pad));
PRINT_BUF(95, (NULL, "MD5 outer: MD5 inner", md5_inner, MD5_LENGTH));
rv |= PK11_DigestBegin(md5);
rv |= PK11_DigestKey(md5, spec->masterSecret);
rv |= PK11_DigestOp(md5, mac_pad_2, md5Pad);
rv |= PK11_DigestOp(md5, md5_inner, MD5_LENGTH);
}
rv |= PK11_DigestFinal(md5, hashes->u.s.md5, &outLength, MD5_LENGTH);
PORT_Assert(rv != SECSuccess || outLength == MD5_LENGTH);
if (rv != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
rv = SECFailure;
goto loser;
}
PRINT_BUF(60, (NULL, "MD5 outer: result", hashes->u.s.md5, MD5_LENGTH));
if (!isTLS) {
PRINT_BUF(95, (NULL, "SHA outer: MAC Pad 2", mac_pad_2, shaPad));
PRINT_BUF(95, (NULL, "SHA outer: SHA inner", sha_inner, SHA1_LENGTH));
rv |= PK11_DigestBegin(sha);
rv |= PK11_DigestKey(sha, spec->masterSecret);
rv |= PK11_DigestOp(sha, mac_pad_2, shaPad);
rv |= PK11_DigestOp(sha, sha_inner, SHA1_LENGTH);
}
rv |= PK11_DigestFinal(sha, hashes->u.s.sha, &outLength, SHA1_LENGTH);
PORT_Assert(rv != SECSuccess || outLength == SHA1_LENGTH);
if (rv != SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
rv = SECFailure;
goto loser;
}
PRINT_BUF(60, (NULL, "SHA outer: result", hashes->u.s.sha, SHA1_LENGTH));
hashes->len = MD5_LENGTH + SHA1_LENGTH;
loser:
if (md5StateBuf) {
if (PK11_RestoreContext(ss->ssl3.hs.md5, md5StateBuf, md5StateLen) !=
SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_MD5_DIGEST_FAILURE);
rv = SECFailure;
}
if (md5StateBuf != md5StackBuf) {
PORT_ZFree(md5StateBuf, md5StateLen);
}
}
if (shaStateBuf) {
if (PK11_RestoreContext(ss->ssl3.hs.sha, shaStateBuf, shaStateLen) !=
SECSuccess) {
ssl_MapLowLevelError(SSL_ERROR_SHA_DIGEST_FAILURE);
rv = SECFailure;
}
if (shaStateBuf != shaStackBuf) {
PORT_ZFree(shaStateBuf, shaStateLen);
}
}
}
return rv;
}
/**************************************************************************
* end of Handshake Hash functions.
* Begin Send and Handle functions for handshakes.
**************************************************************************/
#ifdef TRACE
#define CHTYPE(t) \
case client_hello_##t: \
return #t;
static const char *
ssl_ClientHelloTypeName(sslClientHelloType type)
{
switch (type) {
CHTYPE(initial);
CHTYPE(retry);
CHTYPE(retransmit); /* DTLS only */
CHTYPE(renegotiation); /* TLS <= 1.2 only */
}
PORT_Assert(0);
return NULL;
}
#undef CHTYPE
#endif
PR_STATIC_ASSERT(SSL3_SESSIONID_BYTES == SSL3_RANDOM_LENGTH);
static void
ssl_MakeFakeSid(sslSocket *ss, PRUint8 *buf)
{
PRUint8 x = 0x5a;
int i;
for (i = 0; i < SSL3_SESSIONID_BYTES; ++i) {
x += ss->ssl3.hs.client_random[i];
buf[i] = x;
}
}
/* Set the version fields of the cipher spec for a ClientHello. */
static void
ssl_SetClientHelloSpecVersion(sslSocket *ss, ssl3CipherSpec *spec)
{
ssl_GetSpecWriteLock(ss);
PORT_Assert(spec->cipherDef->cipher == cipher_null);
/* This is - a best guess - but it doesn't matter here. */
spec->version = ss->vrange.max;
if (IS_DTLS(ss)) {
spec->recordVersion = SSL_LIBRARY_VERSION_DTLS_1_0_WIRE;
} else {
/* For new connections, cap the record layer version number of TLS
* ClientHello to { 3, 1 } (TLS 1.0). Some TLS 1.0 servers (which seem
* to use F5 BIG-IP) ignore ClientHello.client_version and use the
* record layer version number (TLSPlaintext.version) instead when
* negotiating protocol versions. In addition, if the record layer
* version number of ClientHello is { 3, 2 } (TLS 1.1) or higher, these
* servers reset the TCP connections. Lastly, some F5 BIG-IP servers
* hang if a record containing a ClientHello has a version greater than
* { 3, 1 } and a length greater than 255. Set this flag to work around
* such servers.
*
* The final version is set when a version is negotiated.
*/
spec->recordVersion = PR_MIN(SSL_LIBRARY_VERSION_TLS_1_0,
ss->vrange.max);
}
ssl_ReleaseSpecWriteLock(ss);
}
SECStatus
ssl3_InsertChHeaderSize(const sslSocket *ss, sslBuffer *preamble, const sslBuffer *extensions)
{
SECStatus rv;
unsigned int msgLen = preamble->len;
msgLen += extensions->len ? (2 + extensions->len) : 0;
unsigned int headerLen = IS_DTLS(ss) ? 12 : 4;
/* Record the message length. */
rv = sslBuffer_InsertNumber(preamble, 1, msgLen - headerLen, 3);
if (rv != SECSuccess) {
return SECFailure; /* code set */
}
if (IS_DTLS(ss)) {
/* Record the (unfragmented) fragment length. */
unsigned int offset = 1 /* ch */ + 3 /* len */ +
2 /* seq */ + 3 /* fragment offset */;
rv = sslBuffer_InsertNumber(preamble, offset, msgLen - headerLen, 3);
if (rv != SECSuccess) {
return SECFailure; /* code set */
}
}
return SECSuccess;
}
static SECStatus
ssl3_AppendCipherSuites(sslSocket *ss, PRBool fallbackSCSV, sslBuffer *buf)
{
SECStatus rv;
unsigned int offset;
unsigned int i;
unsigned int saveLen;
rv = sslBuffer_Skip(buf, 2, &offset);
if (rv != SECSuccess) {
return SECFailure;
}
if (ss->ssl3.hs.sendingSCSV) {
/* Add the actual SCSV */
rv = sslBuffer_AppendNumber(buf, TLS_EMPTY_RENEGOTIATION_INFO_SCSV,
sizeof(ssl3CipherSuite));
if (rv != SECSuccess) {
return SECFailure;
}
}
if (fallbackSCSV) {
rv = sslBuffer_AppendNumber(buf, TLS_FALLBACK_SCSV,
sizeof(ssl3CipherSuite));
if (rv != SECSuccess) {
return SECFailure;
}
}
saveLen = SSL_BUFFER_LEN(buf);
/* CipherSuites are appended to Hello message here */
for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {
ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i];
if (ssl3_config_match(suite, ss->ssl3.policy, &ss->vrange, ss)) {
rv = sslBuffer_AppendNumber(buf, suite->cipher_suite,
sizeof(ssl3CipherSuite));
if (rv != SECSuccess) {
return SECFailure;
}
}
}
/* GREASE CipherSuites:
* A client MAY select one or more GREASE cipher suite values and advertise
* them in the "cipher_suites" field [RFC8701, Section 3.1]. */
if (ss->opt.enableGrease && ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3) {
rv = sslBuffer_AppendNumber(buf, ss->ssl3.hs.grease->idx[grease_cipher],
sizeof(ssl3CipherSuite));
if (rv != SECSuccess) {
return SECFailure;
}
}
if (SSL_ALL_VERSIONS_DISABLED(&ss->vrange) ||
(SSL_BUFFER_LEN(buf) - saveLen) == 0) {
PORT_SetError(SSL_ERROR_SSL_DISABLED);
return SECFailure;
}
return sslBuffer_InsertLength(buf, offset, 2);
}
SECStatus
ssl3_CreateClientHelloPreamble(sslSocket *ss, const sslSessionID *sid,
PRBool realSid, PRUint16 version, PRBool isEchInner,
const sslBuffer *extensions, sslBuffer *preamble)
{
SECStatus rv;
sslBuffer constructed = SSL_BUFFER_EMPTY;
const PRUint8 *client_random = isEchInner ? ss->ssl3.hs.client_inner_random : ss->ssl3.hs.client_random;
PORT_Assert(sid);
PRBool fallbackSCSV = ss->opt.enableFallbackSCSV && !isEchInner &&
(!realSid || version < sid->version);
rv = sslBuffer_AppendNumber(&constructed, ssl_hs_client_hello, 1);
if (rv != SECSuccess) {
goto loser;
}
rv = sslBuffer_Skip(&constructed, 3, NULL);
if (rv != SECSuccess) {
goto loser;
}
if (IS_DTLS(ss)) {
/* Note that we make an unfragmented message here. We fragment in the
* transmission code, if necessary */
rv = sslBuffer_AppendNumber(&constructed, ss->ssl3.hs.sendMessageSeq, 2);
if (rv != SECSuccess) {
goto loser;
}
ss->ssl3.hs.sendMessageSeq++;
/* 0 is the fragment offset, because it's not fragmented yet */
rv = sslBuffer_AppendNumber(&constructed, 0, 3);
if (rv != SECSuccess) {
goto loser;
}
/* Fragment length -- set to the packet length because not fragmented */
rv = sslBuffer_Skip(&constructed, 3, NULL);
if (rv != SECSuccess) {
goto loser;
}
}
if (ss->firstHsDone) {
/* The client hello version must stay unchanged to work around
* the Windows SChannel bug described in ssl3_SendClientHello. */
PORT_Assert(version == ss->clientHelloVersion);
}
ss->clientHelloVersion = PR_MIN(version, SSL_LIBRARY_VERSION_TLS_1_2);
if (IS_DTLS(ss)) {
PRUint16 dtlsVersion = dtls_TLSVersionToDTLSVersion(ss->clientHelloVersion);
rv = sslBuffer_AppendNumber(&constructed, dtlsVersion, 2);
} else {
rv = sslBuffer_AppendNumber(&constructed, ss->clientHelloVersion, 2);
}
if (rv != SECSuccess) {
goto loser;
}
rv = sslBuffer_Append(&constructed, client_random, SSL3_RANDOM_LENGTH);
if (rv != SECSuccess) {
goto loser;
}
if (sid->version < SSL_LIBRARY_VERSION_TLS_1_3 && !isEchInner) {
rv = sslBuffer_AppendVariable(&constructed, sid->u.ssl3.sessionID,
sid->u.ssl3.sessionIDLength, 1);
} else if (ss->opt.enableTls13CompatMode && !IS_DTLS(ss)) {
/* We're faking session resumption, so rather than create new
* randomness, just mix up the client random a little. */
PRUint8 buf[SSL3_SESSIONID_BYTES];
ssl_MakeFakeSid(ss, buf);
rv = sslBuffer_AppendVariable(&constructed, buf, SSL3_SESSIONID_BYTES, 1);
} else {
rv = sslBuffer_AppendNumber(&constructed, 0, 1);
}
if (rv != SECSuccess) {
goto loser;
}
if (IS_DTLS(ss)) {
/* This cookieLen applies to the cookie that appears in the DTLS
* ClientHello, which isn't used in DTLS 1.3. */
rv = sslBuffer_AppendVariable(&constructed, ss->ssl3.hs.cookie.data,
ss->ssl3.hs.helloRetry ? 0 : ss->ssl3.hs.cookie.len,
1);
if (rv != SECSuccess) {
goto loser;
}
}
rv = ssl3_AppendCipherSuites(ss, fallbackSCSV, &constructed);
if (rv != SECSuccess) {
goto loser;
}
/* Compression methods: count is always 1, null compression. */
rv = sslBuffer_AppendNumber(&constructed, 1, 1);
if (rv != SECSuccess) {
goto loser;
}
rv = sslBuffer_AppendNumber(&constructed, ssl_compression_null, 1);
if (rv != SECSuccess) {
goto loser;
}
rv = ssl3_InsertChHeaderSize(ss, &constructed, extensions);
if (rv != SECSuccess) {
goto loser;
}
*preamble = constructed;
return SECSuccess;
loser:
sslBuffer_Clear(&constructed);
return SECFailure;
}
/* Called from ssl3_HandleHelloRequest(),
* ssl3_RedoHandshake()
* ssl_BeginClientHandshake (when resuming ssl3 session)
* dtls_HandleHelloVerifyRequest(with resending=PR_TRUE)
*
* The |type| argument indicates what is going on here:
* - client_hello_initial is set for the very first ClientHello
* - client_hello_retry indicates that this is a second attempt after receiving
* a HelloRetryRequest (in TLS 1.3)
* - client_hello_retransmit is used in DTLS when resending
* - client_hello_renegotiation is used to renegotiate (in TLS <1.3)
*/
SECStatus
ssl3_SendClientHello(sslSocket *ss, sslClientHelloType type)
{
sslSessionID *sid;
SECStatus rv;
PRBool isTLS = PR_FALSE;
PRBool requestingResume = PR_FALSE;
PRBool unlockNeeded = PR_FALSE;
sslBuffer extensionBuf = SSL_BUFFER_EMPTY;
PRUint16 version = ss->vrange.max;
PRInt32 flags;
sslBuffer chBuf = SSL_BUFFER_EMPTY;
SSL_TRC(3, ("%d: SSL3[%d]: send %s ClientHello handshake", SSL_GETPID(),
ss->fd, ssl_ClientHelloTypeName(type)));
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss));
/* shouldn't get here if SSL3 is disabled, but ... */
if (SSL_ALL_VERSIONS_DISABLED(&ss->vrange)) {
PR_NOT_REACHED("No versions of SSL 3.0 or later are enabled");
PORT_SetError(SSL_ERROR_SSL_DISABLED);
return SECFailure;
}
/* If we are responding to a HelloRetryRequest, don't reinitialize. We need
* to maintain the handshake hashes. */
if (!ss->ssl3.hs.helloRetry) {
ssl3_RestartHandshakeHashes(ss);
}
PORT_Assert(!ss->ssl3.hs.helloRetry || type == client_hello_retry);
if (type == client_hello_initial) {
ssl_SetClientHelloSpecVersion(ss, ss->ssl3.cwSpec);
}
/* These must be reset every handshake. */
ssl3_ResetExtensionData(&ss->xtnData, ss);
ss->ssl3.hs.sendingSCSV = PR_FALSE;
ss->ssl3.hs.preliminaryInfo = 0;
PORT_Assert(IS_DTLS(ss) || type != client_hello_retransmit);
SECITEM_FreeItem(&ss->ssl3.hs.newSessionTicket.ticket, PR_FALSE);
ss->ssl3.hs.receivedNewSessionTicket = PR_FALSE;
/* How many suites does our PKCS11 support (regardless of policy)? */
if (ssl3_config_match_init(ss) == 0) {
return SECFailure; /* ssl3_config_match_init has set error code. */
}
/*
* During a renegotiation, ss->clientHelloVersion will be used again to
* work around a Windows SChannel bug. Ensure that it is still enabled.
*/
if (ss->firstHsDone) {
PORT_Assert(type != client_hello_initial);
if (SSL_ALL_VERSIONS_DISABLED(&ss->vrange)) {
PORT_SetError(SSL_ERROR_SSL_DISABLED);
return SECFailure;
}
if (ss->clientHelloVersion < ss->vrange.min ||
ss->clientHelloVersion > ss->vrange.max) {
PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
return SECFailure;
}
}
/* Check if we have a ss->sec.ci.sid.
* Check that it's not expired.
* If we have an sid and it comes from an external cache, we use it. */
if (ss->sec.ci.sid && ss->sec.ci.sid->cached == in_external_cache) {
PORT_Assert(!ss->sec.isServer);
sid = ssl_ReferenceSID(ss->sec.ci.sid);
SSL_TRC(3, ("%d: SSL3[%d]: using external resumption token in ClientHello",
SSL_GETPID(), ss->fd));
} else if (ss->sec.ci.sid && ss->statelessResume && type == client_hello_retry) {
/* If we are sending a second ClientHello, reuse the same SID
* as the original one. */
sid = ssl_ReferenceSID(ss->sec.ci.sid);
} else if (!ss->opt.noCache) {
/* We ignore ss->sec.ci.sid here, and use ssl_Lookup because Lookup
* handles expired entries and other details.
* XXX If we've been called from ssl_BeginClientHandshake, then
* this lookup is duplicative and wasteful.
*/
sid = ssl_LookupSID(ssl_Time(ss), &ss->sec.ci.peer,
ss->sec.ci.port, ss->peerID, ss->url);
} else {
sid = NULL;
}
/* We can't resume based on a different token. If the sid exists,
* make sure the token that holds the master secret still exists ...
* If we previously did client-auth, make sure that the token that holds
* the private key still exists, is logged in, hasn't been removed, etc.
*/
if (sid) {
PRBool sidOK = PR_TRUE;
if (sid->version >= SSL_LIBRARY_VERSION_TLS_1_3) {
if (!tls13_ResumptionCompatible(ss, sid->u.ssl3.cipherSuite)) {
sidOK = PR_FALSE;
}
} else {
/* Check that the cipher suite we need is enabled. */
const ssl3CipherSuiteCfg *suite =
ssl_LookupCipherSuiteCfg(sid->u.ssl3.cipherSuite,
ss->cipherSuites);
SSLVersionRange vrange = { sid->version, sid->version };
if (!suite || !ssl3_config_match(suite, ss->ssl3.policy, &vrange, ss)) {
sidOK = PR_FALSE;
}
/* Check that no (valid) ECHConfigs are setup in combination with a
* (resumable) TLS < 1.3 session id. */
if (!PR_CLIST_IS_EMPTY(&ss->echConfigs)) {
/* If there are ECH configs, the client must not resume but
* offer ECH. */
sidOK = PR_FALSE;
}
}
/* Check that we can recover the master secret. */
if (sidOK) {
PK11SlotInfo *slot = NULL;
if (sid->u.ssl3.masterValid) {
slot = SECMOD_LookupSlot(sid->u.ssl3.masterModuleID,
sid->u.ssl3.masterSlotID);
}
if (slot == NULL) {
sidOK = PR_FALSE;
} else {
PK11SymKey *wrapKey = NULL;
if (!PK11_IsPresent(slot) ||
((wrapKey = PK11_GetWrapKey(slot,
sid->u.ssl3.masterWrapIndex,
sid->u.ssl3.masterWrapMech,
sid->u.ssl3.masterWrapSeries,
ss->pkcs11PinArg)) == NULL)) {
sidOK = PR_FALSE;
}
if (wrapKey)
PK11_FreeSymKey(wrapKey);
PK11_FreeSlot(slot);
slot = NULL;
}
}
/* If we previously did client-auth, make sure that the token that
** holds the private key still exists, is logged in, hasn't been
** removed, etc.
*/
if (sidOK && !ssl3_ClientAuthTokenPresent(sid)) {
sidOK = PR_FALSE;
}
if (sidOK) {
/* Set version based on the sid. */
if (ss->firstHsDone) {
/*
* Windows SChannel compares the client_version inside the RSA
* EncryptedPreMasterSecret of a renegotiation with the
* client_version of the initial ClientHello rather than the
* ClientHello in the renegotiation. To work around this bug, we
* continue to use the client_version used in the initial
* ClientHello when renegotiating.
*
* The client_version of the initial ClientHello is still
* available in ss->clientHelloVersion. Ensure that
* sid->version is bounded within
* [ss->vrange.min, ss->clientHelloVersion], otherwise we
* can't use sid.
*/
if (sid->version >= ss->vrange.min &&
sid->version <= ss->clientHelloVersion) {
version = ss->clientHelloVersion;
} else {
sidOK = PR_FALSE;
}
} else {
/*
* Check sid->version is OK first.
* Previously, we would cap the version based on sid->version,
* but that prevents negotiation of a higher version if the
* previous session was reduced (e.g., with version fallback)
*/
if (sid->version < ss->vrange.min ||
sid->version > ss->vrange.max) {
sidOK = PR_FALSE;
}
}
}
if (!sidOK) {
SSL_AtomicIncrementLong(&ssl3stats.sch_sid_cache_not_ok);
ssl_UncacheSessionID(ss);
ssl_FreeSID(sid);
sid = NULL;
}
}
if (sid) {
requestingResume = PR_TRUE;
SSL_AtomicIncrementLong(&ssl3stats.sch_sid_cache_hits);
PRINT_BUF(4, (ss, "client, found session-id:", sid->u.ssl3.sessionID,
sid->u.ssl3.sessionIDLength));
ss->ssl3.policy = sid->u.ssl3.policy;
} else {
SSL_AtomicIncrementLong(&ssl3stats.sch_sid_cache_misses);
/*
* Windows SChannel compares the client_version inside the RSA
* EncryptedPreMasterSecret of a renegotiation with the
* client_version of the initial ClientHello rather than the
* ClientHello in the renegotiation. To work around this bug, we
* continue to use the client_version used in the initial
* ClientHello when renegotiating.
*/
if (ss->firstHsDone) {
version = ss->clientHelloVersion;
}
sid = ssl3_NewSessionID(ss, PR_FALSE);
if (!sid) {
return SECFailure; /* memory error is set */
}
/* ss->version isn't set yet, but the sid needs a sane value. */
sid->version = version;
}
isTLS = (version > SSL_LIBRARY_VERSION_3_0);
ssl_GetSpecWriteLock(ss);
if (ss->ssl3.cwSpec->macDef->mac == ssl_mac_null) {
/* SSL records are not being MACed. */
ss->ssl3.cwSpec->version = version;
}
ssl_ReleaseSpecWriteLock(ss);
ssl_FreeSID(ss->sec.ci.sid); /* release the old sid */
ss->sec.ci.sid = sid;
/* HACK for SCSV in SSL 3.0. On initial handshake, prepend SCSV,
* only if TLS is disabled.
*/
if (!ss->firstHsDone && !isTLS) {
/* Must set this before calling Hello Extension Senders,
* to suppress sending of empty RI extension.
*/
ss->ssl3.hs.sendingSCSV = PR_TRUE;
}
/* When we attempt session resumption (only), we must lock the sid to
* prevent races with other resumption connections that receive a
* NewSessionTicket that will cause the ticket in the sid to be replaced.
* Once we've copied the session ticket into our ClientHello message, it
* is OK for the ticket to change, so we just need to make sure we hold
* the lock across the calls to ssl_ConstructExtensions.
*/
if (sid->u.ssl3.lock) {
unlockNeeded = PR_TRUE;
PR_RWLock_Rlock(sid->u.ssl3.lock);
}
/* Generate a new random if this is the first attempt or renegotiation. */
if (type == client_hello_initial ||
type == client_hello_renegotiation) {
rv = ssl3_GetNewRandom(ss->ssl3.hs.client_random);
if (rv != SECSuccess) {
goto loser; /* err set by GetNewRandom. */
}
}
if (ss->vrange.max >= SSL_LIBRARY_VERSION_TLS_1_3) {
rv = tls13_SetupClientHello(ss, type);
if (rv != SECSuccess) {
goto loser;
}
}
/* Setup TLS ClientHello Extension Permutation? */
if (type == client_hello_initial &&
ss->vrange.max > SSL_LIBRARY_VERSION_3_0 &&
ss->opt.enableChXtnPermutation) {
rv = tls_ClientHelloExtensionPermutationSetup(ss);
if (rv != SECSuccess) {
goto loser;
}
}
if (isTLS || (ss->firstHsDone && ss->peerRequestedProtection)) {
rv = ssl_ConstructExtensions(ss, &extensionBuf, ssl_hs_client_hello);
if (rv != SECSuccess) {
goto loser;
}
}
if (IS_DTLS(ss)) {
ssl3_DisableNonDTLSSuites(ss);
}
rv = ssl3_CreateClientHelloPreamble(ss, sid, requestingResume, version,
PR_FALSE, &extensionBuf, &chBuf);
if (rv != SECSuccess) {
goto loser; /* err set by ssl3_CreateClientHelloPreamble. */
}
if (!ss->ssl3.hs.echHpkeCtx) {
if (extensionBuf.len) {
rv = tls13_MaybeGreaseEch(ss, &chBuf, &extensionBuf);
if (rv != SECSuccess) {
goto loser; /* err set by tls13_MaybeGreaseEch. */
}
rv = ssl_InsertPaddingExtension(ss, chBuf.len, &extensionBuf);
if (rv != SECSuccess) {
goto loser; /* err set by ssl_InsertPaddingExtension. */
}
rv = ssl3_InsertChHeaderSize(ss, &chBuf, &extensionBuf);
if (rv != SECSuccess) {
goto loser; /* err set by ssl3_InsertChHeaderSize. */
}
/* If we are sending a PSK binder, replace the dummy value. */
if (ssl3_ExtensionAdvertised(ss, ssl_tls13_pre_shared_key_xtn)) {
rv = tls13_WriteExtensionsWithBinder(ss, &extensionBuf, &chBuf);
} else {
rv = sslBuffer_AppendNumber(&chBuf, extensionBuf.len, 2);
if (rv != SECSuccess) {
goto loser;
}
rv = sslBuffer_AppendBuffer(&chBuf, &extensionBuf);
}
if (rv != SECSuccess) {
goto loser; /* err set by sslBuffer_Append*. */
}
}
/* If we already have a message in place, we need to enqueue it.
* This empties the buffer. This is a convenient place to call
* dtls_StageHandshakeMessage to mark the message boundary. */
if (IS_DTLS(ss)) {
rv = dtls_StageHandshakeMessage(ss);
if (rv != SECSuccess) {
goto loser;
}
}
rv = ssl3_AppendHandshake(ss, chBuf.buf, chBuf.len);
} else {
rv = tls13_ConstructClientHelloWithEch(ss, sid, !requestingResume, &chBuf, &extensionBuf);
if (rv != SECSuccess) {
goto loser; /* code set */
}
rv = ssl3_UpdateDefaultHandshakeHashes(ss, chBuf.buf, chBuf.len);
if (rv != SECSuccess) {
goto loser; /* code set */
}
if (IS_DTLS(ss)) {
rv = dtls_StageHandshakeMessage(ss);
if (rv != SECSuccess) {
goto loser;
}
}
/* By default, all messagess are added to both the inner and
* outer transcripts. For CH (or CH2 if HRR), that's problematic. */
rv = ssl3_AppendHandshakeSuppressHash(ss, chBuf.buf, chBuf.len);
}
if (rv != SECSuccess) {
goto loser;
}
if (unlockNeeded) {
/* Note: goto loser can't be used past this point. */
PR_RWLock_Unlock(sid->u.ssl3.lock);
}
if (ss->xtnData.sentSessionTicketInClientHello) {
SSL_AtomicIncrementLong(&ssl3stats.sch_sid_stateless_resumes);
}
if (ss->ssl3.hs.sendingSCSV) {
/* Since we sent the SCSV, pretend we sent empty RI extension. */
TLSExtensionData *xtnData = &ss->xtnData;
xtnData->advertised[xtnData->numAdvertised++] =
ssl_renegotiation_info_xtn;
}
flags = 0;
rv = ssl3_FlushHandshake(ss, flags);
if (rv != SECSuccess) {
return rv; /* error code set by ssl3_FlushHandshake */
}
if (version >= SSL_LIBRARY_VERSION_TLS_1_3) {
rv = tls13_MaybeDo0RTTHandshake(ss);
if (rv != SECSuccess) {
return SECFailure; /* error code set already. */
}
}
ss->ssl3.hs.ws = wait_server_hello;
sslBuffer_Clear(&chBuf);
sslBuffer_Clear(&extensionBuf);
return SECSuccess;
loser:
if (unlockNeeded) {
PR_RWLock_Unlock(sid->u.ssl3.lock);
}
sslBuffer_Clear(&chBuf);
sslBuffer_Clear(&extensionBuf);
return SECFailure;
}
/* Called from ssl3_HandlePostHelloHandshakeMessage() when it has deciphered a
* complete ssl3 Hello Request.
* Caller must hold Handshake and RecvBuf locks.
*/
static SECStatus
ssl3_HandleHelloRequest(sslSocket *ss)
{
sslSessionID *sid = ss->sec.ci.sid;
SECStatus rv;
SSL_TRC(3, ("%d: SSL3[%d]: handle hello_request handshake",
SSL_GETPID(), ss->fd));
PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss));
PORT_Assert(ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
PORT_Assert(ss->version < SSL_LIBRARY_VERSION_TLS_1_3);
if (ss->ssl3.hs.ws == wait_server_hello)
return SECSuccess;
if (ss->ssl3.hs.ws != idle_handshake || ss->sec.isServer) {
(void)SSL3_SendAlert(ss, alert_fatal, unexpected_message);
PORT_SetError(SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST);
return SECFailure;
}
if (ss->opt.enableRenegotiation == SSL_RENEGOTIATE_NEVER) {
(void)SSL3_SendAlert(ss, alert_warning, no_renegotiation);
PORT_SetError(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED);
return SECFailure;
}
if (sid) {
ssl_UncacheSessionID(ss);
ssl_FreeSID(sid);
ss->sec.ci.sid = NULL;
}
if (IS_DTLS(ss)) {
dtls_RehandshakeCleanup(ss);
}
ssl_GetXmitBufLock(ss);
rv = ssl3_SendClientHello(ss, client_hello_renegotiation);
ssl_ReleaseXmitBufLock(ss);
return rv;
}
static const CK_MECHANISM_TYPE wrapMechanismList[SSL_NUM_WRAP_MECHS] = {
CKM_DES3_ECB,
CKM_CAST5_ECB,
CKM_DES_ECB,
CKM_KEY_WRAP_LYNKS,
CKM_IDEA_ECB,
CKM_CAST3_ECB,
CKM_CAST_ECB,
CKM_RC5_ECB,
CKM_RC2_ECB,
CKM_CDMF_ECB,
CKM_SKIPJACK_WRAP,
CKM_SKIPJACK_CBC64,
CKM_AES_ECB,
CKM_CAMELLIA_ECB,
CKM_SEED_ECB
};
static SECStatus
ssl_FindIndexByWrapMechanism(CK_MECHANISM_TYPE mech, unsigned int *wrapMechIndex)
{
unsigned int i;
for (i = 0; i < SSL_NUM_WRAP_MECHS; ++i) {
if (wrapMechanismList[i] == mech) {
*wrapMechIndex = i;
return SECSuccess;
}
}
PORT_Assert(0);
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
/* Each process sharing the server session ID cache has its own array of SymKey
* pointers for the symmetric wrapping keys that are used to wrap the master
* secrets. There is one key for each authentication type. These Symkeys
* correspond to the wrapped SymKeys kept in the server session cache.
*/
const SSLAuthType ssl_wrap_key_auth_type[SSL_NUM_WRAP_KEYS]