#include "sslContext.h"
#include "cryptType.h"
#include "symCipher.h"
#include "cipherSpecs.h"
#include "sslDebug.h"
#include "sslMemory.h"
#include "sslDebug.h"
#include "sslUtils.h"
#include "sslPriv.h"
#include "appleCdsa.h"
#include <string.h>
#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
#define ENABLE_3DES 1
#define ENABLE_RC4 1
#define ENABLE_DES 1
#define ENABLE_RC2 1
#define ENABLE_RSA_DES_SHA_NONEXPORT ENABLE_DES
#define ENABLE_RSA_DES_MD5_NONEXPORT ENABLE_DES
#define ENABLE_RSA_DES_SHA_EXPORT ENABLE_DES
#define ENABLE_RSA_RC4_MD5_EXPORT ENABLE_RC4
#define ENABLE_RSA_RC4_MD5_NONEXPORT ENABLE_RC4
#define ENABLE_RSA_RC4_SHA_NONEXPORT ENABLE_RC4
#define ENABLE_RSA_RC2_MD5_EXPORT ENABLE_RC2
#define ENABLE_RSA_RC2_MD5_NONEXPORT ENABLE_RC2
#define ENABLE_RSA_3DES_SHA ENABLE_3DES
#define ENABLE_RSA_3DES_MD5 ENABLE_3DES
#if APPLE_DH
#define ENABLE_DH_ANON 1
#define ENABLE_DH_EPHEM_RSA 1
#define ENABLE_DH_EPHEM_DSA 1
#else
#define ENABLE_DH_ANON 0
#define ENABLE_DH_EPHEM_RSA 0
#define ENABLE_DH_EPHEM_DSA 0
#endif
extern "C" {
extern const SSLSymmetricCipher SSLCipherNull;
}
#if ENABLE_DES
static const SSLSymmetricCipher SSLCipherDES_CBC = {
8,
8,
8,
8,
CSSM_ALGID_DES,
CSSM_ALGID_DES,
CSSM_ALGMODE_CBC_IV8,
CSSM_PADDING_NONE,
CDSASymmInit,
CDSASymmEncrypt,
CDSASymmDecrypt,
CDSASymmFinish
};
static const SSLSymmetricCipher SSLCipherDES40_CBC = {
8,
5,
8,
8,
CSSM_ALGID_DES,
CSSM_ALGID_DES,
CSSM_ALGMODE_CBC_IV8,
CSSM_PADDING_NONE,
CDSASymmInit,
CDSASymmEncrypt,
CDSASymmDecrypt,
CDSASymmFinish
};
#endif
#if ENABLE_3DES
static const SSLSymmetricCipher SSLCipher3DES_CBC = {
24,
24,
8,
8,
CSSM_ALGID_3DES_3KEY, CSSM_ALGID_3DES_3KEY_EDE,
CSSM_ALGMODE_CBC_IV8,
CSSM_PADDING_NONE,
CDSASymmInit,
CDSASymmEncrypt,
CDSASymmDecrypt,
CDSASymmFinish
};
#endif
#if ENABLE_RC4
static const SSLSymmetricCipher SSLCipherRC4_40 = {
16,
5,
0,
0,
CSSM_ALGID_RC4,
CSSM_ALGID_RC4,
CSSM_ALGMODE_NONE,
CSSM_PADDING_NONE,
CDSASymmInit,
CDSASymmEncrypt,
CDSASymmDecrypt,
CDSASymmFinish
};
static const SSLSymmetricCipher SSLCipherRC4_128 = {
16,
16,
0,
0,
CSSM_ALGID_RC4,
CSSM_ALGID_RC4,
CSSM_ALGMODE_NONE,
CSSM_PADDING_NONE,
CDSASymmInit,
CDSASymmEncrypt,
CDSASymmDecrypt,
CDSASymmFinish
};
#endif
#if ENABLE_RC2
static const SSLSymmetricCipher SSLCipherRC2_40 = {
16,
5,
8,
8,
CSSM_ALGID_RC2,
CSSM_ALGID_RC2,
CSSM_ALGMODE_CBC_IV8,
CSSM_PADDING_NONE,
CDSASymmInit,
CDSASymmEncrypt,
CDSASymmDecrypt,
CDSASymmFinish
};
static const SSLSymmetricCipher SSLCipherRC2_128 = {
16,
16,
8,
8,
CSSM_ALGID_RC2,
CSSM_ALGID_RC2,
CSSM_ALGMODE_CBC_IV8,
CSSM_PADDING_NONE,
CDSASymmInit,
CDSASymmEncrypt,
CDSASymmDecrypt,
CDSASymmFinish
};
#endif
const SSLCipherSpec SSL_NULL_WITH_NULL_NULL_CipherSpec =
{ SSL_NULL_WITH_NULL_NULL,
Exportable,
SSL_NULL_auth,
&HashHmacNull,
&SSLCipherNull
};
static const SSLCipherSpec KnownCipherSpecs[] =
{
#if ENABLE_RSA_RC4_SHA_NONEXPORT
{
SSL_RSA_WITH_RC4_128_SHA,
NotExportable,
SSL_RSA,
&HashHmacSHA1,
&SSLCipherRC4_128
},
#endif
#if ENABLE_RSA_RC4_MD5_NONEXPORT
{
SSL_RSA_WITH_RC4_128_MD5,
NotExportable,
SSL_RSA,
&HashHmacMD5,
&SSLCipherRC4_128
},
#endif
#if ENABLE_RSA_3DES_SHA
{
SSL_RSA_WITH_3DES_EDE_CBC_SHA,
NotExportable,
SSL_RSA,
&HashHmacSHA1,
&SSLCipher3DES_CBC
},
#endif
#if ENABLE_RSA_3DES_MD5
{
SSL_RSA_WITH_3DES_EDE_CBC_MD5,
NotExportable,
SSL_RSA,
&HashHmacMD5,
&SSLCipher3DES_CBC
},
#endif
#if ENABLE_RSA_DES_SHA_NONEXPORT
{
SSL_RSA_WITH_DES_CBC_SHA,
NotExportable,
SSL_RSA,
&HashHmacSHA1,
&SSLCipherDES_CBC
},
#endif
#if ENABLE_RSA_DES_MD5_NONEXPORT
{
SSL_RSA_WITH_DES_CBC_MD5,
NotExportable,
SSL_RSA,
&HashHmacMD5,
&SSLCipherDES_CBC
},
#endif
#if ENABLE_RSA_RC4_MD5_EXPORT
{
SSL_RSA_EXPORT_WITH_RC4_40_MD5,
Exportable,
SSL_RSA_EXPORT,
&HashHmacMD5,
&SSLCipherRC4_40
},
#endif
#if ENABLE_RSA_DES_SHA_EXPORT
{
SSL_RSA_EXPORT_WITH_DES40_CBC_SHA,
Exportable,
SSL_RSA_EXPORT,
&HashHmacSHA1,
&SSLCipherDES40_CBC
},
#endif
#if ENABLE_RSA_RC2_MD5_EXPORT
{
SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5,
Exportable,
SSL_RSA_EXPORT,
&HashHmacMD5,
&SSLCipherRC2_40
},
#endif
#if ENABLE_RSA_RC2_MD5_NONEXPORT
{
SSL_RSA_WITH_RC2_CBC_MD5,
NotExportable,
SSL_RSA,
&HashHmacMD5,
&SSLCipherRC2_128
},
#endif
{
SSL_RSA_WITH_NULL_MD5,
Exportable,
SSL_RSA,
&HashHmacMD5,
&SSLCipherNull
},
#if ENABLE_DH_EPHEM_RSA
{
SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA,
NotExportable,
SSL_DHE_RSA,
&HashHmacSHA1,
&SSLCipher3DES_CBC
},
{
SSL_DHE_RSA_WITH_DES_CBC_SHA,
NotExportable,
SSL_DHE_RSA,
&HashHmacSHA1,
&SSLCipherDES_CBC
},
{
SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA,
Exportable,
SSL_DHE_RSA,
&HashHmacSHA1,
&SSLCipherDES40_CBC
},
#endif
#if ENABLE_DH_EPHEM_DSA
{
SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA,
NotExportable,
SSL_DHE_DSS,
&HashHmacSHA1,
&SSLCipher3DES_CBC
},
{
SSL_DHE_DSS_WITH_DES_CBC_SHA,
NotExportable,
SSL_DHE_DSS,
&HashHmacSHA1,
&SSLCipherDES_CBC
},
{
SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA,
Exportable,
SSL_DHE_DSS,
&HashHmacSHA1,
&SSLCipherDES40_CBC
},
#endif
#if ENABLE_DH_ANON
{
SSL_DH_anon_WITH_RC4_128_MD5,
NotExportable,
SSL_DH_anon,
&HashHmacMD5,
&SSLCipherRC4_128
},
{
SSL_DH_anon_WITH_3DES_EDE_CBC_SHA,
NotExportable,
SSL_DH_anon,
&HashHmacSHA1,
&SSLCipher3DES_CBC
},
{
SSL_DH_anon_WITH_DES_CBC_SHA,
NotExportable,
SSL_DH_anon,
&HashHmacSHA1,
&SSLCipherDES_CBC
},
{
SSL_DH_anon_EXPORT_WITH_RC4_40_MD5,
Exportable,
SSL_DH_anon,
&HashHmacMD5,
&SSLCipherRC4_40
},
{
SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA,
Exportable,
SSL_DH_anon,
&HashHmacSHA1,
&SSLCipherDES40_CBC
},
#endif
};
static const unsigned CipherSpecCount = sizeof(KnownCipherSpecs) / sizeof(SSLCipherSpec);
OSStatus sslBuildCipherSpecArray(SSLContext *ctx)
{
unsigned size;
assert(ctx != NULL);
assert(ctx->validCipherSpecs == NULL);
ctx->numValidCipherSpecs = CipherSpecCount;
size = CipherSpecCount * sizeof(SSLCipherSpec);
ctx->validCipherSpecs = (SSLCipherSpec *)sslMalloc(size);
if(ctx->validCipherSpecs == NULL) {
ctx->numValidCipherSpecs = 0;
return memFullErr;
}
memmove(ctx->validCipherSpecs, KnownCipherSpecs, size);
return noErr;
}
static OSStatus
cipherSpecsToCipherSuites(
UInt32 numCipherSpecs,
const SSLCipherSpec *cipherSpecs,
SSLCipherSuite *ciphers,
UInt32 *numCiphers)
{
unsigned dex;
if(*numCiphers < numCipherSpecs) {
return errSSLBufferOverflow;
}
for(dex=0; dex<numCipherSpecs; dex++) {
ciphers[dex] = cipherSpecs[dex].cipherSpec;
}
*numCiphers = numCipherSpecs;
return noErr;
}
OSStatus
SSLGetNumberSupportedCiphers (SSLContextRef ctx,
UInt32 *numCiphers)
{
if((ctx == NULL) || (numCiphers == NULL)) {
return paramErr;
}
*numCiphers = CipherSpecCount;
return noErr;
}
OSStatus
SSLGetSupportedCiphers (SSLContextRef ctx,
SSLCipherSuite *ciphers,
UInt32 *numCiphers)
{
if((ctx == NULL) || (ciphers == NULL) || (numCiphers == NULL)) {
return paramErr;
}
return cipherSpecsToCipherSuites(CipherSpecCount,
KnownCipherSpecs,
ciphers,
numCiphers);
}
OSStatus
SSLSetEnabledCiphers (SSLContextRef ctx,
const SSLCipherSuite *ciphers,
UInt32 numCiphers)
{
unsigned size;
unsigned callerDex;
unsigned tableDex;
if((ctx == NULL) || (ciphers == NULL) || (numCiphers == 0)) {
return paramErr;
}
if(sslIsSessionActive(ctx)) {
return badReqErr;
}
size = numCiphers * sizeof(SSLCipherSpec);
ctx->validCipherSpecs = (SSLCipherSpec *)sslMalloc(size);
if(ctx->validCipherSpecs == NULL) {
ctx->numValidCipherSpecs = 0;
return memFullErr;
}
for(callerDex=0; callerDex<numCiphers; callerDex++) {
int foundOne = 0;
for(tableDex=0; tableDex<CipherSpecCount; tableDex++) {
if(ciphers[callerDex] == KnownCipherSpecs[tableDex].cipherSpec) {
ctx->validCipherSpecs[callerDex] = KnownCipherSpecs[tableDex];
foundOne = 1;
break;
}
}
if(!foundOne) {
sslFree(ctx->validCipherSpecs);
ctx->validCipherSpecs = NULL;
return errSSLBadCipherSuite;
}
}
ctx->numValidCipherSpecs = numCiphers;
return noErr;
}
OSStatus
SSLGetNumberEnabledCiphers (SSLContextRef ctx,
UInt32 *numCiphers)
{
if((ctx == NULL) || (numCiphers == NULL)) {
return paramErr;
}
if(ctx->validCipherSpecs == NULL) {
*numCiphers = CipherSpecCount;
}
else {
*numCiphers = ctx->numValidCipherSpecs;
}
return noErr;
}
OSStatus
SSLGetEnabledCiphers (SSLContextRef ctx,
SSLCipherSuite *ciphers,
UInt32 *numCiphers)
{
if((ctx == NULL) || (ciphers == NULL) || (numCiphers == NULL)) {
return paramErr;
}
if(ctx->validCipherSpecs == NULL) {
return cipherSpecsToCipherSuites(CipherSpecCount,
KnownCipherSpecs,
ciphers,
numCiphers);
}
else {
return cipherSpecsToCipherSuites(ctx->numValidCipherSpecs,
ctx->validCipherSpecs,
ciphers,
numCiphers);
}
}
OSStatus
FindCipherSpec(SSLContext *ctx)
{
unsigned i;
assert(ctx != NULL);
assert(ctx->validCipherSpecs != NULL);
ctx->selectedCipherSpec = NULL;
for (i=0; i<ctx->numValidCipherSpecs; i++)
{ if (ctx->validCipherSpecs[i].cipherSpec == ctx->selectedCipher) {
ctx->selectedCipherSpec = &ctx->validCipherSpecs[i];
break;
}
}
if (ctx->selectedCipherSpec == NULL)
return errSSLNegotiation;
return sslVerifyNegotiatedCipher(ctx);
}