#include "sslBuildFlags.h"
#include "sslDebug.h"
#include "sslMemory.h"
#include "symCipher.h"
#include "cipherSpecs.h"
#include "SSLRecordInternal.h"
#ifdef KERNEL
#include <corecrypto/ccaes.h>
#include <corecrypto/ccdes.h>
#include <corecrypto/ccmode.h>
#include <AssertMacros.h>
struct SymCipherContext {
const struct ccmode_cbc *cbc;
cccbc_ctx u[];
};
static inline
size_t CTX_SIZE(const struct ccmode_cbc *cbc)
{
#ifdef __CC_HAS_FIX_FOR_11468135__
return (sizeof(SymCipherContext) + (sizeof(cccbc_ctx) * (cc_ctx_n(cccbc_ctx, cbc->size) + cc_ctx_n(cccbc_iv, cbc->block_size))));
#else
return (sizeof(SymCipherContext) + sizeof(cccbc_ctx) + cbc->size);
#endif
}
static inline
cccbc_ctx *CTX_KEY(struct SymCipherContext *ctx)
{
return &ctx->u[0];
}
#ifdef __CC_HAS_FIX_FOR_11468135__
static inline
cccbc_iv *CTX_IV(struct SymCipherContext *ctx)
{
return (cccbc_iv *)&ctx->u[cc_ctx_n(cccbc_ctx, ctx->cbc->size)];
}
#endif
static
const void *ccmode(SSL_CipherAlgorithm alg, int enc)
{
switch(alg) {
case SSL_CipherAlgorithmAES_128_CBC:
case SSL_CipherAlgorithmAES_256_CBC:
return enc?ccaes_cbc_encrypt_mode():ccaes_cbc_decrypt_mode();
case SSL_CipherAlgorithm3DES_CBC:
return enc?ccdes3_cbc_encrypt_mode():ccdes3_cbc_decrypt_mode();
case SSL_CipherAlgorithmAES_128_GCM:
case SSL_CipherAlgorithmAES_256_GCM:
case SSL_CipherAlgorithmRC4_128:
default:
check(0);
return NULL;
}
}
static
int CCSymmInit(
const SSLSymmetricCipherParams *params,
int encrypting,
uint8_t *key,
uint8_t* iv,
SymCipherContext *cipherCtx)
{
check(cipherCtx!=NULL);
check(params);
SymCipherContext ctx = *cipherCtx;
if(ctx) {
sslFree(ctx);
ctx = NULL;
}
const struct ccmode_cbc *cbc = ccmode(params->keyAlg, encrypting);
ctx = sslMalloc(CTX_SIZE(cbc));
if(ctx==NULL) {
sslErrorLog("CCSymmInit: Can't allocate context\n");
return errSSLRecordInternal;
}
ctx->cbc = cbc;
#ifdef __CC_HAS_FIX_FOR_11468135__
cccbc_init(cbc, CTX_KEY(ctx), params->keySize, key);
cccbc_set_iv(cbc, CTX_IV(ctx), iv);
#else
cccbc_init(cbc, CTX_KEY(ctx), params->keySize, key, iv);
#endif
*cipherCtx = ctx;
return 0;
}
static
int CCSymmEncryptDecrypt(
const uint8_t *src,
uint8_t *dest,
size_t len,
SymCipherContext cipherCtx)
{
ASSERT(cipherCtx != NULL);
ASSERT(cipherCtx->cbc != NULL);
if(cipherCtx == NULL || cipherCtx->cbc == NULL) {
sslErrorLog("CCSymmEncryptDecrypt: NULL cipherCtx\n");
return errSSLRecordInternal;
}
ASSERT((len%cipherCtx->cbc->block_size)==0);
if(len%cipherCtx->cbc->block_size) {
sslErrorLog("CCSymmEncryptDecrypt: Invalid size\n");
return errSSLRecordInternal;
}
unsigned long nblocks = len/cipherCtx->cbc->block_size;
#ifdef __CC_HAS_FIX_FOR_11468135__
cccbc_update(cipherCtx->cbc, CTX_KEY(cipherCtx), CTX_IV(cipherCtx), nblocks, src, dest);
#else
cipherCtx->cbc->cbc(CTX_KEY(cipherCtx), nblocks, src, dest);
#endif
return 0;
}
static
int CCSymmFinish(
SymCipherContext cipherCtx)
{
if(cipherCtx) {
sslFree(cipherCtx);
}
return 0;
}
#else
#define ENABLE_RC4 1
#define ENABLE_3DES 1
#define ENABLE_AES 1
#define ENABLE_AES256 1
#include <CommonCrypto/CommonCryptor.h>
#include <CommonCrypto/CommonCryptorSPI.h>
#include <assert.h>
static
CCAlgorithm CCAlg(SSL_CipherAlgorithm alg)
{
switch(alg) {
case SSL_CipherAlgorithmAES_128_CBC:
case SSL_CipherAlgorithmAES_256_CBC:
case SSL_CipherAlgorithmAES_128_GCM:
case SSL_CipherAlgorithmAES_256_GCM:
return kCCAlgorithmAES128;
case SSL_CipherAlgorithm3DES_CBC:
return kCCAlgorithm3DES;
case SSL_CipherAlgorithmDES_CBC:
return kCCAlgorithmDES;
case SSL_CipherAlgorithmRC4_128:
return kCCAlgorithmRC4;
case SSL_CipherAlgorithmRC2_128:
return kCCAlgorithmRC2;
default:
assert(0);
return (CCAlgorithm)(-1);
}
}
static CCOptions CCOpt(CipherType cipherType)
{
#if 0
if(cipherType==aeadCipherType) return kCCModeGCM;
#endif
return 0;
}
static
int CCSymmInit(
const SSLSymmetricCipherParams *params,
int encrypting,
uint8_t *key,
uint8_t* iv,
SymCipherContext *cipherCtx)
{
assert(cipherCtx!=NULL);
CCCryptorStatus ccrtn;
CCOperation op = encrypting ? kCCEncrypt : kCCDecrypt;
CCCryptorRef cryptorRef = (CCCryptorRef)*cipherCtx;
if(cryptorRef) {
CCCryptorRelease(cryptorRef);
cryptorRef = NULL;
}
ccrtn = CCCryptorCreate(op, CCAlg(params->keyAlg),
CCOpt(params->cipherType),
key, params->keySize,
iv,
&cryptorRef);
if(ccrtn) {
sslErrorLog("CCCryptorCreate returned %d\n", (int)ccrtn);
return errSSLRecordInternal;
}
*cipherCtx = (SymCipherContext)cryptorRef;
return 0;
}
static
int CCSymmEncryptDecrypt(
const uint8_t *src,
uint8_t *dest,
size_t len,
SymCipherContext cipherCtx)
{
CCCryptorStatus ccrtn;
CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx;
ASSERT(cryptorRef != NULL);
if(cryptorRef == NULL) {
sslErrorLog("CCSymmEncryptDecrypt: NULL cryptorRef\n");
return errSSLRecordInternal;
}
size_t data_moved;
ccrtn = CCCryptorUpdate(cryptorRef, src, len,
dest, len, &data_moved);
assert(data_moved == len);
#if SSL_DEBUG
if(ccrtn) {
sslErrorLog("CCSymmEncryptDecrypt: returned %d\n", (int)ccrtn);
return errSSLRecordInternal;
}
#endif
return 0;
}
#if ENABLE_AES_GCM
static
int CCSymmAEADSetIV(
const uint8_t *iv,
size_t len,
SymCipherContext cipherCtx)
{
CCCryptorStatus ccrtn;
CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx;
ASSERT(cryptorRef != NULL);
if(cryptorRef == NULL) {
sslErrorLog("CCSymmAEADAddIV: NULL cryptorRef\n");
return errSecInternalComponent;
}
ccrtn = CCCryptorGCMAddIV(cryptorRef, iv, len);
#if SSL_DEBUG
if(ccrtn) {
sslErrorLog("CCSymmAEADAddIV: returned %d\n", (int)ccrtn);
return errSSLRecordInternal;
}
#endif
return 0;
}
static
int CCSymmAddADD(
const uint8_t *src,
size_t len,
SymCipherContext cipherCtx)
{
CCCryptorStatus ccrtn;
CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx;
ASSERT(cryptorRef != NULL);
if(cryptorRef == NULL) {
sslErrorLog("CCSymmAddADD: NULL cryptorRef\n");
return errSSLRecordInternal;
}
ccrtn = CCCryptorGCMAddADD(cryptorRef, src, len);
#if SSL_DEBUG
if(ccrtn) {
sslErrorLog("CCSymmAddADD: returned %d\n", (int)ccrtn);
return errSSLRecordInternal;
}
#endif
return 0;
}
static
int CCSymmAEADEncrypt(
const uint8_t *src,
uint8_t *dest,
size_t len,
SymCipherContext cipherCtx)
{
CCCryptorStatus ccrtn;
CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx;
ASSERT(cryptorRef != NULL);
if(cryptorRef == NULL) {
sslErrorLog("CCSymmAEADEncrypt: NULL cryptorRef\n");
return errSSLRecordInternal;
}
ccrtn = CCCryptorGCMEncrypt(cryptorRef, src, len, dest);
#if SSL_DEBUG
if(ccrtn) {
sslErrorLog("CCSymmAEADEncrypt: returned %d\n", (int)ccrtn);
return errSSLRecordInternal;
}
#endif
return 0;
}
static
int CCSymmAEADDecrypt(
const uint8_t *src,
uint8_t *dest,
size_t len,
SymCipherContext cipherCtx)
{
CCCryptorStatus ccrtn;
CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx;
ASSERT(cipherCtx != NULL);
ASSERT(cipherCtx->cryptorRef != NULL);
if(cipherCtx->cryptorRef == NULL) {
sslErrorLog("CCSymmAEADDecrypt: NULL cryptorRef\n");
return errSSLRecordInternal;
}
ccrtn = CCCryptorGCMDecrypt(cryptorRef, src, len, dest);
#if SSL_DEBUG
if(ccrtn) {
sslErrorLog("CCSymmAEADDecrypt: returned %d\n", (int)ccrtn);
return errSSLRecordInternal;
}
#endif
return 0;
}
static
int CCSymmAEADDone(
uint8_t *mac,
size_t *macLen,
SymCipherContext cipherCtx)
{
CCCryptorStatus ccrtn;
CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx;
ASSERT(cipherCtx != NULL);
ASSERT(cipherCtx->cryptorRef != NULL);
if(cipherCtx->cryptorRef == NULL) {
sslErrorLog("CCSymmAEADDone: NULL cryptorRef\n");
return errSSLRecordInternal;
}
ccrtn = CCCryptorGCMFinal(cipherCtx->cryptorRef, mac, macLen);
CCCryptorStatus ccrtn2 = CCCryptorGCMReset(cipherCtx->cryptorRef);
if (ccrtn == kCCSuccess)
ccrtn = ccrtn2;
#if SSL_DEBUG
if(ccrtn) {
sslErrorLog("CCSymmAEADDone: returned %d\n", (int)ccrtn);
return errSSLRecordInternal;
}
#endif
return 0;
}
#endif
static
int CCSymmFinish(
SymCipherContext cipherCtx)
{
CCCryptorRef cryptorRef = (CCCryptorRef)cipherCtx;
if(cryptorRef) {
CCCryptorRelease(cryptorRef);
}
return 0;
}
#endif
#if ENABLE_DES
const SSLSymmetricCipher SSLCipherDES_CBC = {
.params = &SSLCipherDES_CBCParams,
.c.cipher = {
.initialize = CCSymmInit,
.encrypt = CCSymmEncryptDecrypt,
.decrypt = CCSymmEncryptDecrypt
},
.finish = CCSymmFinish
};
#endif
#if ENABLE_3DES
const SSLSymmetricCipher SSLCipher3DES_CBC = {
.params = &SSLCipher3DES_CBCParams,
.c.cipher = {
.initialize = CCSymmInit,
.encrypt = CCSymmEncryptDecrypt,
.decrypt = CCSymmEncryptDecrypt
},
.finish = CCSymmFinish
};
#endif
#if ENABLE_RC4
const SSLSymmetricCipher SSLCipherRC4_128 = {
.params = &SSLCipherRC4_128Params,
.c.cipher = {
.initialize = CCSymmInit,
.encrypt = CCSymmEncryptDecrypt,
.decrypt = CCSymmEncryptDecrypt
},
.finish = CCSymmFinish
};
#endif
#if ENABLE_RC2
const SSLSymmetricCipher SSLCipherRC2_128 = {
.params = &SSLCipherRC2_128Params,
.c.cipher = {
.initialize = CCSymmInit,
.encrypt = CCSymmEncryptDecrypt,
.decrypt = CCSymmEncryptDecrypt
},
.finish = CCSymmFinish
};
#endif
#if ENABLE_AES
const SSLSymmetricCipher SSLCipherAES_128_CBC = {
.params = &SSLCipherAES_128_CBCParams,
.c.cipher = {
.initialize = CCSymmInit,
.encrypt = CCSymmEncryptDecrypt,
.decrypt = CCSymmEncryptDecrypt
},
.finish = CCSymmFinish
};
#endif
#if ENABLE_AES256
const SSLSymmetricCipher SSLCipherAES_256_CBC = {
.params = &SSLCipherAES_256_CBCParams,
.c.cipher = {
.initialize = CCSymmInit,
.encrypt = CCSymmEncryptDecrypt,
.decrypt = CCSymmEncryptDecrypt
},
.finish = CCSymmFinish
};
#endif
#if ENABLE_AES_GCM
const SSLSymmetricCipher SSLCipherAES_128_GCM = {
.params = &SSLCipherAES_128_GCMParams,
.c.aead = {
.initialize = CCSymmInit,
.setIV = CCSymmAEADSetIV,
.update = CCSymmAddADD,
.encrypt = CCSymmAEADEncrypt,
.decrypt = CCSymmAEADDecrypt,
.done = CCSymmAEADDone
},
.finish = CCSymmFinish
};
const SSLSymmetricCipher SSLCipherAES_256_GCM = {
.params = &SSLCipherAES_256_GCMParams,
.c.aead = {
.initialize = CCSymmInit,
.setIV = CCSymmAEADSetIV,
.update = CCSymmAddADD,
.encrypt = CCSymmAEADEncrypt,
.decrypt = CCSymmAEADDecrypt,
.done = CCSymmAEADDone
},
.finish = CCSymmFinish
};
#endif