#include "sslBuildFlags.h"
#include "sslContext.h"
#include "sslCipherSpecs.h"
#include "sslDebug.h"
#include "sslMemory.h"
#include "sslDebug.h"
#include "sslPriv.h"
#include <tls_handshake.h>
#include <string.h>
#include <assert.h>
#include <Security/SecBase.h>
#include <TargetConditionals.h>
#define ENABLE_ECDH 1
#define ENABLE_AES_GCM 1
#define ENABLE_PSK 1
#define ENABLE_CHACHA20_POLY1305 1
#define ENABLE_AES_CCM 0
static const uint16_t STKnownCipherSuites[] = {
#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_ECDH
#if ENABLE_AES_GCM
TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
#endif
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384,
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256,
TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA,
TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA,
TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA,
#if ENABLE_AES_GCM
TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384,
TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256,
#endif
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384,
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256,
TLS_ECDH_RSA_WITH_AES_256_CBC_SHA,
TLS_ECDH_RSA_WITH_AES_128_CBC_SHA,
TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA,
#endif
#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_AES_GCM
TLS_AES_128_GCM_SHA256,
TLS_AES_256_GCM_SHA384,
#endif
#if ENABLE_CHACHA20_POLY1305
TLS_CHACHA20_POLY1305_SHA256,
#endif
#if ENABLE_AES_CCM
TLS_AES_128_CCM_SHA256,
TLS_AES_128_CCM_8_SHA256,
#endif
#if ENABLE_AES_GCM
TLS_DH_anon_WITH_AES_256_GCM_SHA384,
TLS_DH_anon_WITH_AES_128_GCM_SHA256,
#endif
TLS_DH_anon_WITH_AES_128_CBC_SHA256,
TLS_DH_anon_WITH_AES_256_CBC_SHA256,
TLS_DH_anon_WITH_AES_128_CBC_SHA,
TLS_DH_anon_WITH_AES_256_CBC_SHA,
SSL_DH_anon_WITH_3DES_EDE_CBC_SHA,
TLS_ECDHE_ECDSA_WITH_NULL_SHA,
TLS_ECDHE_RSA_WITH_NULL_SHA,
#if ENABLE_ECDH
TLS_ECDH_ECDSA_WITH_NULL_SHA,
TLS_ECDH_RSA_WITH_NULL_SHA,
#endif
#if ENABLE_PSK
TLS_PSK_WITH_AES_256_CBC_SHA384,
TLS_PSK_WITH_AES_128_CBC_SHA256,
TLS_PSK_WITH_AES_256_CBC_SHA,
TLS_PSK_WITH_AES_128_CBC_SHA,
TLS_PSK_WITH_3DES_EDE_CBC_SHA,
TLS_PSK_WITH_NULL_SHA384,
TLS_PSK_WITH_NULL_SHA256,
TLS_PSK_WITH_NULL_SHA,
#endif
TLS_RSA_WITH_NULL_SHA256,
SSL_RSA_WITH_NULL_SHA,
SSL_RSA_WITH_NULL_MD5
};
static const unsigned STCipherSuiteCount = sizeof(STKnownCipherSuites)/sizeof(STKnownCipherSuites[0]);
#define CiphersuitesTLS13 \
TLS_AES_128_GCM_SHA256, \
TLS_AES_256_GCM_SHA384, \
TLS_CHACHA20_POLY1305_SHA256
#define CiphersuitesPFS \
TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, \
TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, \
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_CHACHA20_POLY1305_SHA256, \
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, \
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, \
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_CHACHA20_POLY1305_SHA256
#define CiphersuitesNonPFS \
TLS_RSA_WITH_AES_256_GCM_SHA384, \
TLS_RSA_WITH_AES_128_GCM_SHA256, \
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
#define CiphersuitesTLS10 \
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, \
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, \
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, \
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, \
TLS_RSA_WITH_AES_256_CBC_SHA, \
TLS_RSA_WITH_AES_128_CBC_SHA
#define CiphersuitesTLS10_3DES \
TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, \
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, \
SSL_RSA_WITH_3DES_EDE_CBC_SHA
#define CiphersuitesDHE \
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, \
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, \
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
#define DefineTLSCiphersuiteGroupList(XXX, ...) \
static const SSLCipherSuite List##XXX[] = { \
__VA_ARGS__ \
};
DefineTLSCiphersuiteGroupList(kSSLCiphersuiteGroupDefault,
CiphersuitesTLS13,
CiphersuitesPFS);
DefineTLSCiphersuiteGroupList(kSSLCiphersuiteGroupCompatibility,
CiphersuitesNonPFS,
CiphersuitesTLS10,
CiphersuitesTLS10_3DES);
DefineTLSCiphersuiteGroupList(kSSLCiphersuiteGroupLegacy,
CiphersuitesDHE);
DefineTLSCiphersuiteGroupList(kSSLCiphersuiteGroupATS,
CiphersuitesTLS13,
CiphersuitesPFS);
DefineTLSCiphersuiteGroupList(kSSLCiphersuiteGroupATSCompatibility,
CiphersuitesNonPFS);
typedef struct tls_ciphersuite_definition {
SSLCipherSuite ciphersuite;
SSLProtocol min_version;
SSLProtocol max_version;
char ciphersuite_name[64];
} *tls_ciphersuite_definition_t;
#define DefineTLSCiphersuiteDefinition(XXX, MIN_VERSION, MAX_VERSION) \
{ \
.ciphersuite = XXX, \
.ciphersuite_name = "##XXX", \
.min_version = MIN_VERSION, \
.max_version = MAX_VERSION, \
}
static const struct tls_ciphersuite_definition tls_ciphersuite_definitions[] = {
DefineTLSCiphersuiteDefinition(TLS_AES_128_GCM_SHA256, kTLSProtocol13, kTLSProtocolMaxSupported),
DefineTLSCiphersuiteDefinition(TLS_AES_256_GCM_SHA384, kTLSProtocol13, kTLSProtocolMaxSupported),
DefineTLSCiphersuiteDefinition(TLS_CHACHA20_POLY1305_SHA256, kTLSProtocol13, kTLSProtocolMaxSupported),
DefineTLSCiphersuiteDefinition(TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, kTLSProtocol12, kTLSProtocol12),
DefineTLSCiphersuiteDefinition(TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, kTLSProtocol12, kTLSProtocol12),
DefineTLSCiphersuiteDefinition(TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, kTLSProtocol12, kTLSProtocol12),
DefineTLSCiphersuiteDefinition(TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, kTLSProtocol12, kTLSProtocol12),
DefineTLSCiphersuiteDefinition(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, kTLSProtocol12, kTLSProtocol12),
DefineTLSCiphersuiteDefinition(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, kTLSProtocol12, kTLSProtocol12),
DefineTLSCiphersuiteDefinition(TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, kTLSProtocol12, kTLSProtocol12),
DefineTLSCiphersuiteDefinition(TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, kTLSProtocol12, kTLSProtocol12),
DefineTLSCiphersuiteDefinition(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, kTLSProtocol12, kTLSProtocol12),
DefineTLSCiphersuiteDefinition(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, kTLSProtocol12, kTLSProtocol12),
DefineTLSCiphersuiteDefinition(TLS_RSA_WITH_AES_256_GCM_SHA384, kTLSProtocol12, kTLSProtocol12),
DefineTLSCiphersuiteDefinition(TLS_RSA_WITH_AES_128_GCM_SHA256, kTLSProtocol12, kTLSProtocol12),
DefineTLSCiphersuiteDefinition(TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, kTLSProtocol12, kTLSProtocol12),
DefineTLSCiphersuiteDefinition(TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, kTLSProtocol12, kTLSProtocol12),
DefineTLSCiphersuiteDefinition(TLS_RSA_WITH_AES_256_CBC_SHA256, kTLSProtocol12, kTLSProtocol12),
DefineTLSCiphersuiteDefinition(TLS_RSA_WITH_AES_128_CBC_SHA256, kTLSProtocol12, kTLSProtocol12),
DefineTLSCiphersuiteDefinition(SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, kTLSProtocol12, kTLSProtocol12),
DefineTLSCiphersuiteDefinition(SSL_RSA_WITH_3DES_EDE_CBC_SHA, kTLSProtocol12, kTLSProtocol12),
DefineTLSCiphersuiteDefinition(TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, kTLSProtocol12, kTLSProtocol12),
DefineTLSCiphersuiteDefinition(TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, kTLSProtocol12, kTLSProtocol12),
DefineTLSCiphersuiteDefinition(TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, kTLSProtocol1, kTLSProtocol11),
DefineTLSCiphersuiteDefinition(TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, kTLSProtocol1, kTLSProtocol11),
DefineTLSCiphersuiteDefinition(TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, kTLSProtocol1, kTLSProtocol11),
DefineTLSCiphersuiteDefinition(TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, kTLSProtocol1, kTLSProtocol11),
DefineTLSCiphersuiteDefinition(TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, kTLSProtocol1, kTLSProtocol11),
DefineTLSCiphersuiteDefinition(TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, kTLSProtocol1, kTLSProtocol11),
DefineTLSCiphersuiteDefinition(TLS_RSA_WITH_AES_256_CBC_SHA, kTLSProtocol1, kTLSProtocol11),
DefineTLSCiphersuiteDefinition(TLS_RSA_WITH_AES_128_CBC_SHA, kTLSProtocol1, kTLSProtocol11),
DefineTLSCiphersuiteDefinition(TLS_RSA_WITH_AES_256_CBC_SHA, kTLSProtocol1, kTLSProtocol11),
DefineTLSCiphersuiteDefinition(TLS_DHE_RSA_WITH_AES_256_CBC_SHA, kTLSProtocol1, kTLSProtocol11),
DefineTLSCiphersuiteDefinition(TLS_RSA_WITH_AES_128_CBC_SHA, kTLSProtocol1, kTLSProtocol11),
DefineTLSCiphersuiteDefinition(TLS_DHE_RSA_WITH_AES_128_CBC_SHA, kTLSProtocol1, kTLSProtocol11),
DefineTLSCiphersuiteDefinition(TLS_DHE_RSA_WITH_AES_256_CBC_SHA, kTLSProtocol1, kTLSProtocol11),
DefineTLSCiphersuiteDefinition(TLS_DHE_RSA_WITH_AES_128_CBC_SHA, kTLSProtocol1, kTLSProtocol11),
};
static const size_t tls_ciphersuite_definitions_length = \
sizeof(tls_ciphersuite_definitions) / sizeof(struct tls_ciphersuite_definition);
#undef CiphersuitesTLS13
#undef CiphersuitesPFS
#undef CiphersuitesNonPFS
#undef CiphersuitesTLS10_3DES
#undef CiphersuitesTLS10
#undef CiphersuitesDHE
#undef DefineTLSCiphersuiteGroupList
#undef DefineTLSCiphersuiteDefinition
const SSLCipherSuite *
SSLCiphersuiteGroupToCiphersuiteList(SSLCiphersuiteGroup group, size_t *listSize)
{
if (listSize == NULL) {
return NULL;
}
const SSLCipherSuite *ciphersuites = NULL;
size_t count = 0;
#define CASE_CONFIG(GROUPNAME) \
case GROUPNAME: \
ciphersuites = List##GROUPNAME; \
count = sizeof(List##GROUPNAME) / sizeof(SSLCipherSuite); \
break;
switch (group) {
CASE_CONFIG(kSSLCiphersuiteGroupDefault);
CASE_CONFIG(kSSLCiphersuiteGroupCompatibility);
CASE_CONFIG(kSSLCiphersuiteGroupLegacy);
CASE_CONFIG(kSSLCiphersuiteGroupATS);
CASE_CONFIG(kSSLCiphersuiteGroupATSCompatibility);
}
#undef CASE_CONFIG
if (ciphersuites != NULL) {
*listSize = count;
return ciphersuites;
}
*listSize = 0;
return NULL;
}
SSLProtocol
SSLCiphersuiteMinimumTLSVersion(SSLCipherSuite ciphersuite)
{
for (size_t i = 0; i < tls_ciphersuite_definitions_length; i++) {
if (tls_ciphersuite_definitions[i].ciphersuite == ciphersuite) {
return tls_ciphersuite_definitions[i].min_version;
}
}
return kSSLProtocolUnknown;
}
SSLProtocol
SSLCiphersuiteMaximumTLSVersion(SSLCipherSuite ciphersuite)
{
for (size_t i = 0; i < tls_ciphersuite_definitions_length; i++) {
if (tls_ciphersuite_definitions[i].ciphersuite == ciphersuite) {
return tls_ciphersuite_definitions[i].max_version;
}
}
return kSSLProtocolUnknown;
}
static OSStatus
cipherSuitesToCipherSuites(
size_t numCipherSuites,
const uint16_t *cipherSuites,
SSLCipherSuite *ciphers,
size_t *numCiphers)
{
size_t i;
if(*numCiphers < numCipherSuites) {
return errSSLBufferOverflow;
}
for(i=0;i<numCipherSuites; i++) {
ciphers[i]=cipherSuites[i];
}
*numCiphers = numCipherSuites;
return errSecSuccess;
}
OSStatus
SSLGetNumberSupportedCiphers (SSLContextRef ctx,
size_t *numCiphers)
{
if((ctx == NULL) || (numCiphers == NULL)) {
return errSecParam;
}
*numCiphers = STCipherSuiteCount;
return errSecSuccess;
}
OSStatus
SSLGetSupportedCiphers (SSLContextRef ctx,
SSLCipherSuite *ciphers,
size_t *numCiphers)
{
if((ctx == NULL) || (ciphers == NULL) || (numCiphers == NULL)) {
return errSecParam;
}
return cipherSuitesToCipherSuites(STCipherSuiteCount,
STKnownCipherSuites,
ciphers,
numCiphers);
}
OSStatus
SSLSetEnabledCiphers (SSLContextRef ctx,
const SSLCipherSuite *ciphers,
size_t numCiphers)
{
uint16_t *cs;
if((ctx == NULL) || (ciphers == NULL) || (numCiphers == 0)) {
return errSecParam;
}
if(sslIsSessionActive(ctx)) {
return errSecBadReq;
}
int matchCount = 0;
for(int i=0; i<numCiphers; i++) {
for (int j=0; j < STCipherSuiteCount; j++) {
if (STKnownCipherSuites[j] == ciphers[i]) {
matchCount++;
break;
}
}
}
if (matchCount == 0) {
return errSecParam;
}
cs = (uint16_t *)sslMalloc(matchCount * sizeof(uint16_t));
if(cs == NULL) {
return errSecAllocate;
}
matchCount = 0;
for(int i=0; i<numCiphers; i++) {
for (int j=0; j < STCipherSuiteCount; j++) {
if (STKnownCipherSuites[j] == ciphers[i]) {
cs[matchCount++] = ciphers[i];
break;
}
}
}
OSStatus result = tls_handshake_set_ciphersuites(ctx->hdsk, cs, (unsigned) matchCount);
sslFree(cs);
return result;
}
OSStatus
SSLGetNumberEnabledCiphers (SSLContextRef ctx,
size_t *numCiphers)
{
if((ctx == NULL) || (numCiphers == NULL)) {
return errSecParam;
}
unsigned n;
const uint16_t *ciphersuites;
int err;
err = tls_handshake_get_ciphersuites(ctx->hdsk, &ciphersuites, &n);
if(err) {
return err;
} else {
*numCiphers = n;
return errSecSuccess;
}
}
OSStatus
SSLGetEnabledCiphers (SSLContextRef ctx,
SSLCipherSuite *ciphers,
size_t *numCiphers)
{
if((ctx == NULL) || (ciphers == NULL) || (numCiphers == NULL)) {
return errSecParam;
}
unsigned n;
const uint16_t *ciphersuites;
int err;
err = tls_handshake_get_ciphersuites(ctx->hdsk, &ciphersuites, &n);
if(err) {
return err;
} else {
return cipherSuitesToCipherSuites(n,
ciphersuites,
ciphers,
numCiphers);
}
}
OSStatus
SSLSetSessionTicketsEnabled (SSLContextRef context,
Boolean enabled)
{
if (context == NULL) {
return errSecParam;
}
return tls_handshake_set_session_ticket_enabled(context->hdsk, enabled);
}