#include <tls_ciphersuites.h>
#include "sslBuildFlags.h"
#include "sslDebug.h"
#include "sslMemory.h"
#include "symCipher.h"
#include "tls_types_private.h"
#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)
{
return (sizeof(struct SymCipherContext) + (sizeof(cccbc_ctx) * (cc_ctx_n(cccbc_ctx, cbc->size) + cc_ctx_n(cccbc_iv, cbc->block_size))));
}
static inline
cccbc_ctx *CTX_KEY(struct SymCipherContext *ctx)
{
return &ctx->u[0];
}
static inline
cccbc_iv *CTX_IV(struct SymCipherContext *ctx)
{
return (cccbc_iv *)&ctx->u[cc_ctx_n(cccbc_ctx, ctx->cbc->size)];
}
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_CipherAlgorithmRC4_128:
case SSL_CipherAlgorithmAES_128_GCM:
case SSL_CipherAlgorithmAES_256_GCM:
default:
check(0);
return NULL;
}
}
static
int CCSymmInit(
const SSLSymmetricCipherParams *params,
int encrypting,
uint8_t *key,
uint8_t* iv,
struct ccrng_state *rng,
SymCipherContext *cipherCtx)
{
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;
int error = 0;
require_noerr((error = cccbc_init(cbc, CTX_KEY(ctx), params->keySize, key)), cleanup);
require_noerr((error = cccbc_set_iv(cbc, CTX_IV(ctx), iv)), cleanup);
*cipherCtx = ctx;
return 0;
cleanup:
sslFree(ctx);
return error;
}
static
int CCSymmEncryptDecrypt(
const uint8_t *src,
uint8_t *dest,
size_t len,
SymCipherContext cipherCtx)
{
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;
return cccbc_update(cipherCtx->cbc, CTX_KEY(cipherCtx), CTX_IV(cipherCtx), nblocks, src, dest);
}
static
int CCSymmFinish(
SymCipherContext cipherCtx)
{
if (cipherCtx) {
cc_clear(CTX_SIZE(cipherCtx->cbc), cipherCtx);
sslFree(cipherCtx);
}
return 0;
}
#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_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