#include "sslBuildFlags.h"
#include "CipherSuite.h"
#include "sslCipherSpecs.h"
#include "sslDebug.h"
#include "sslMemory.h"
#include "sslDebug.h"
#include "sslUtils.h"
#include "tls_handshake_priv.h"
#include <string.h>
#include <assert.h>
#include <TargetConditionals.h>
#define ENABLE_AES_GCM 1
#define ENABLE_PSK 1
const uint16_t KnownCipherSuites[] = {
#if ENABLE_AES_GCM
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
#endif
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA,
#if ENABLE_AES_GCM
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
#endif
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
#if ENABLE_AES_GCM
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
#endif // ENABLE_AES_GCM
TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
#if ENABLE_AES_GCM
TLS_RSA_WITH_AES_256_GCM_SHA384,
TLS_RSA_WITH_AES_128_GCM_SHA256,
#endif
TLS_RSA_WITH_AES_256_CBC_SHA256,
TLS_RSA_WITH_AES_128_CBC_SHA256,
TLS_RSA_WITH_AES_256_CBC_SHA,
TLS_RSA_WITH_AES_128_CBC_SHA,
SSL_RSA_WITH_3DES_EDE_CBC_SHA,
#if ENABLE_RC4
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
TLS_ECDHE_RSA_WITH_RC4_128_SHA,
SSL_RSA_WITH_RC4_128_SHA,
SSL_RSA_WITH_RC4_128_MD5,
#endif
};
const unsigned CipherSuiteCount = sizeof(KnownCipherSuites)/sizeof(KnownCipherSuites[0]);
const uint16_t KnownCurves[] = {
tls_curve_secp256r1,
tls_curve_secp384r1,
tls_curve_secp521r1
};
const unsigned CurvesCount = sizeof(KnownCurves)/sizeof(KnownCurves[0]);
const tls_signature_and_hash_algorithm KnownSigAlgs[] = {
{tls_hash_algorithm_SHA256, tls_signature_algorithm_RSA},
{tls_hash_algorithm_SHA1, tls_signature_algorithm_RSA},
{tls_hash_algorithm_SHA384, tls_signature_algorithm_RSA},
{tls_hash_algorithm_SHA512, tls_signature_algorithm_RSA},
{tls_hash_algorithm_SHA256, tls_signature_algorithm_ECDSA},
{tls_hash_algorithm_SHA1, tls_signature_algorithm_ECDSA},
{tls_hash_algorithm_SHA384, tls_signature_algorithm_ECDSA},
{tls_hash_algorithm_SHA512, tls_signature_algorithm_ECDSA},
};
const unsigned SigAlgsCount = sizeof(KnownSigAlgs)/sizeof(KnownSigAlgs[0]);
void sslAnalyzeCipherSpecs(tls_handshake_t ctx)
{
unsigned dex;
const uint16_t *cipherSuite;
cipherSuite = &ctx->enabledCipherSuites[0];
ctx->ecdsaEnable = false;
for(dex=0; dex<ctx->numEnabledCipherSuites; dex++, cipherSuite++) {
switch(sslCipherSuiteGetKeyExchangeMethod(*cipherSuite)) {
case SSL_ECDHE_ECDSA:
case SSL_ECDHE_RSA:
case SSL_ECDH_anon:
ctx->ecdsaEnable = true;
break;
default:
break;
}
}
}
void InitCipherSpecParams(tls_handshake_t ctx)
{
SSLCipherSpecParams *dst = &ctx->selectedCipherSpecParams;
dst->cipherSpec = ctx->selectedCipher;
dst->macSize = sslCipherSuiteGetMacSize(ctx->selectedCipher);
dst->macAlg = sslCipherSuiteGetMacAlgorithm(ctx->selectedCipher);
dst->keySize = sslCipherSuiteGetSymmetricCipherKeySize(ctx->selectedCipher);
dst->blockSize = sslCipherSuiteGetSymmetricCipherBlockIvSize(ctx->selectedCipher);
dst->ivSize = dst->blockSize;
dst->keyExchangeMethod = sslCipherSuiteGetKeyExchangeMethod(ctx->selectedCipher);
};
bool cipherSuiteInSet(uint16_t cs, uint16_t *ciphersuites, size_t numCiphersuites)
{
size_t i;
for(i=0; i<numCiphersuites; i++) {
if(ciphersuites[i]==cs)
return true;
}
return false;
}
static bool
verifyCipherSuite(tls_handshake_t ctx, uint16_t cs)
{
KeyExchangeMethod kem = sslCipherSuiteGetKeyExchangeMethod(cs);
switch (kem) {
case SSL_RSA:
case SSL_DHE_RSA:
case SSL_ECDHE_RSA:
return ((ctx->signingPrivKeyRef) && (ctx->signingPrivKeyRef->desc.type == tls_private_key_type_rsa));
break;
case SSL_ECDHE_ECDSA:
return ((ctx->signingPrivKeyRef) && (ctx->signingPrivKeyRef->desc.type == tls_private_key_type_ecdsa));
break;
default:
return true;
}
}
int
SelectNewCiphersuite(tls_handshake_t ctx)
{
int i;
assert(ctx->isServer);
for (i=0; i<ctx->numEnabledCipherSuites; i++) {
if(cipherSuiteInSet(ctx->enabledCipherSuites[i], ctx->requestedCipherSuites, ctx->numRequestedCipherSuites) &&
verifyCipherSuite(ctx, ctx->enabledCipherSuites[i]))
{
ctx->selectedCipher = ctx->enabledCipherSuites[i];
sslLogNegotiateDebug("TLS server: selected ciphersuite 0x%04x", (unsigned)ctx->selectedCipher);
InitCipherSpecParams(ctx);
return 0;
}
}
return errSSLNegotiation;
}
int
ValidateSelectedCiphersuite(tls_handshake_t ctx)
{
unsigned i;
assert(!ctx->isServer);
assert(ctx->selectedCipher != 0);
for (i=0; i<ctx->numEnabledCipherSuites; i++)
{
if (ctx->enabledCipherSuites[i] == ctx->selectedCipher) {
InitCipherSpecParams(ctx);
return errSSLSuccess; }
}
return errSSLNegotiation;
}
static
bool tls_handshake_kem_is_supported(bool server, KeyExchangeMethod kem)
{
switch(kem) {
case SSL_RSA:
case SSL_DHE_RSA:
case SSL_DH_anon:
case TLS_PSK:
case SSL_ECDHE_ECDSA:
case SSL_ECDHE_RSA:
case SSL_ECDH_anon:
return true;
default:
return false;
}
}
static
bool tls_handshake_kem_is_allowed(tls_handshake_config_t config, KeyExchangeMethod kem)
{
switch(config) {
case tls_handshake_config_none:
return true;
case tls_handshake_config_ATSv1:
return (kem == SSL_ECDHE_ECDSA || kem == SSL_ECDHE_RSA);
case tls_handshake_config_legacy_DHE:
return (kem==SSL_RSA || kem == SSL_DHE_RSA || kem == SSL_ECDHE_ECDSA || kem == SSL_ECDHE_RSA);
case tls_handshake_config_ATSv1_noPFS:
case tls_handshake_config_default:
case tls_handshake_config_standard:
case tls_handshake_config_RC4_fallback:
case tls_handshake_config_TLSv1_fallback:
case tls_handshake_config_TLSv1_RC4_fallback:
case tls_handshake_config_legacy:
case tls_handshake_config_3DES_fallback:
case tls_handshake_config_TLSv1_3DES_fallback:
return (kem==SSL_RSA || kem == SSL_ECDHE_ECDSA || kem == SSL_ECDHE_RSA);
case tls_handshake_config_anonymous:
return (kem==SSL_ECDH_anon || kem == SSL_DH_anon);
}
return (kem==SSL_RSA || kem == SSL_ECDHE_ECDSA || kem == SSL_ECDHE_RSA);
}
static
bool tls_handshake_kem_is_valid(tls_handshake_t ctx, KeyExchangeMethod kem)
{
switch(kem) {
case SSL_RSA:
case SSL_DH_RSA:
case SSL_DHE_RSA:
case SSL_DH_anon:
case TLS_PSK:
return true;
case SSL_ECDHE_ECDSA:
case SSL_ECDHE_RSA:
case SSL_ECDH_anon:
return ctx->maxProtocolVersion!=tls_protocol_version_SSL_3; default:
return false;
}
}
static
bool tls_handshake_sym_is_supported(bool dtls, SSL_CipherAlgorithm sym)
{
switch (sym) {
case SSL_CipherAlgorithmNull:
case SSL_CipherAlgorithmAES_128_CBC:
case SSL_CipherAlgorithm3DES_CBC:
case SSL_CipherAlgorithmAES_256_CBC:
case SSL_CipherAlgorithmAES_256_GCM:
case SSL_CipherAlgorithmAES_128_GCM:
return true;
case SSL_CipherAlgorithmRC4_128:
return !dtls;
default:
return false;
}
}
static
bool tls_handshake_sym_is_allowed(tls_handshake_config_t config, SSL_CipherAlgorithm sym)
{
switch(config) {
case tls_handshake_config_none:
return true;
case tls_handshake_config_ATSv1:
case tls_handshake_config_ATSv1_noPFS:
case tls_handshake_config_anonymous:
case tls_handshake_config_standard:
return (sym>=SSL_CipherAlgorithmAES_128_CBC);
case tls_handshake_config_default:
case tls_handshake_config_TLSv1_fallback:
case tls_handshake_config_3DES_fallback:
case tls_handshake_config_TLSv1_3DES_fallback:
return (sym>=SSL_CipherAlgorithm3DES_CBC);
case tls_handshake_config_legacy:
case tls_handshake_config_RC4_fallback:
case tls_handshake_config_TLSv1_RC4_fallback:
case tls_handshake_config_legacy_DHE:
return (sym==SSL_CipherAlgorithmRC4_128) || (sym>=SSL_CipherAlgorithm3DES_CBC);
}
return (sym>=SSL_CipherAlgorithm3DES_CBC);
}
static
bool tls_handshake_sym_is_valid(tls_handshake_t ctx, SSL_CipherAlgorithm sym)
{
switch (sym) {
case SSL_CipherAlgorithmNull:
case SSL_CipherAlgorithmRC4_128:
return true;
case SSL_CipherAlgorithmAES_128_CBC:
case SSL_CipherAlgorithm3DES_CBC:
case SSL_CipherAlgorithmAES_256_CBC:
return !(ctx->maxProtocolVersion==tls_protocol_version_SSL_3 && ctx->fallback);
case SSL_CipherAlgorithmAES_256_GCM:
case SSL_CipherAlgorithmAES_128_GCM:
return ctx->maxProtocolVersion==tls_protocol_version_TLS_1_2;
default:
return false;
}
}
static
bool tls_handshake_mac_is_supported(HMAC_Algs mac)
{
switch (mac){
case HA_Null:
case HA_MD5:
case HA_SHA1:
case HA_SHA256:
case HA_SHA384:
return true;
default:
return false;
}
}
static
bool tls_handshake_mac_is_allowed(tls_handshake_config_t config, HMAC_Algs mac)
{
switch(config) {
case tls_handshake_config_none:
return true;
case tls_handshake_config_ATSv1:
case tls_handshake_config_ATSv1_noPFS:
case tls_handshake_config_anonymous:
return (mac>=HA_SHA1);
case tls_handshake_config_default:
case tls_handshake_config_legacy:
case tls_handshake_config_RC4_fallback:
case tls_handshake_config_TLSv1_RC4_fallback:
case tls_handshake_config_standard:
case tls_handshake_config_TLSv1_fallback:
case tls_handshake_config_legacy_DHE:
case tls_handshake_config_3DES_fallback:
case tls_handshake_config_TLSv1_3DES_fallback:
return (mac>=HA_MD5);
}
return (mac>=HA_MD5);
}
static
bool tls_handshake_mac_is_valid(tls_handshake_t ctx, HMAC_Algs mac)
{
return true;
}
bool tls_handshake_ciphersuite_is_supported(bool server, bool dtls, uint16_t ciphersuite)
{
uint16_t cs = ciphersuite;
KeyExchangeMethod kem = sslCipherSuiteGetKeyExchangeMethod(cs);
SSL_CipherAlgorithm sym = sslCipherSuiteGetSymmetricCipherAlgorithm(cs);
HMAC_Algs mac = sslCipherSuiteGetMacAlgorithm(cs);
return tls_handshake_kem_is_supported(server, kem)
&& tls_handshake_sym_is_supported(dtls, sym)
&& tls_handshake_mac_is_supported(mac);
}
bool tls_handshake_ciphersuite_is_allowed(tls_handshake_config_t config, uint16_t ciphersuite)
{
uint16_t cs = ciphersuite;
KeyExchangeMethod kem = sslCipherSuiteGetKeyExchangeMethod(cs);
SSL_CipherAlgorithm sym = sslCipherSuiteGetSymmetricCipherAlgorithm(cs);
HMAC_Algs mac = sslCipherSuiteGetMacAlgorithm(cs);
return tls_handshake_kem_is_allowed(config,kem)
&& tls_handshake_sym_is_allowed(config, sym)
&& tls_handshake_mac_is_allowed(config, mac);
}
bool tls_handshake_ciphersuite_is_valid(tls_handshake_t ctx, uint16_t ciphersuite)
{
uint16_t cs = ciphersuite;
KeyExchangeMethod kem = sslCipherSuiteGetKeyExchangeMethod(cs);
SSL_CipherAlgorithm sym = sslCipherSuiteGetSymmetricCipherAlgorithm(cs);
HMAC_Algs mac = sslCipherSuiteGetMacAlgorithm(cs);
return tls_handshake_kem_is_valid(ctx,kem)
&& tls_handshake_sym_is_valid(ctx, sym)
&& tls_handshake_mac_is_valid(ctx, mac);
}
bool tls_handshake_curve_is_supported(uint16_t curve)
{
switch(curve) {
case tls_curve_secp256r1:
case tls_curve_secp384r1:
case tls_curve_secp521r1:
return true;
default:
return false;
}
}
bool tls_handshake_sigalg_is_supported(tls_signature_and_hash_algorithm sigalg)
{
bool hash_supported;
bool sig_supported;
switch(sigalg.hash) {
case tls_hash_algorithm_SHA1:
case tls_hash_algorithm_SHA256:
case tls_hash_algorithm_SHA384:
case tls_hash_algorithm_SHA512:
hash_supported = true;
break;
default:
hash_supported = false;
}
switch(sigalg.signature) {
case tls_signature_algorithm_RSA:
case tls_signature_algorithm_ECDSA:
sig_supported = true;
break;
default:
sig_supported = false;
}
return sig_supported && hash_supported;
}