#include <tls_ciphersuites.h>
#include "sslBuildFlags.h"
#include "sslDebug.h"
#include "sslMemory.h"
#include "symCipher.h"
#include "tls_types_private.h"
#include <string.h>
#include <AssertMacros.h>
#include <stddef.h>
#include <corecrypto/ccaes.h>
#include <corecrypto/ccmode.h>
#include <corecrypto/ccrng.h>
struct SymCipherContext {
const struct ccmode_gcm *gcm;
ccgcm_ctx *gcmCtx;
uint8_t gcmIV[TLS_AES_GCM_IMPLICIT_IV_SIZE+TLS_AES_GCM_EXPLICIT_IV_SIZE];
uint8_t *key;
size_t keySize;
};
static
int CCGCMSymmInit(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_gcm *gcm = encrypting ? ccaes_gcm_encrypt_mode() : ccaes_gcm_decrypt_mode();
ctx = sslMalloc(sizeof(struct SymCipherContext));
if (ctx == NULL) {
sslErrorLog("CCSymmInit: Can't allocate context\n");
return errSSLRecordInternal;
}
ctx->gcm = gcm;
ctx->gcmCtx = sslMalloc(gcm->size);
memcpy(ctx->gcmIV, iv, TLS_AES_GCM_IMPLICIT_IV_SIZE);
ccrng_generate(rng, TLS_AES_GCM_EXPLICIT_IV_SIZE, &ctx->gcmIV[TLS_AES_GCM_IMPLICIT_IV_SIZE]);
ctx->keySize = params->keySize;
ctx->key = sslMalloc(ctx->keySize);
memcpy(ctx->key, key, ctx->keySize);
*cipherCtx = ctx;
return 0;
}
static
int CCSymmAEADSetIV(const uint8_t *srcIV,
SymCipherContext cipherCtx)
{
int err = 0;
if (cipherCtx == NULL || cipherCtx->gcm == NULL) {
sslErrorLog("CCSymmAEADSetIV: NULL cipherCtx\n");
return errSSLRecordInternal;
}
memcpy(&cipherCtx->gcmIV[TLS_AES_GCM_IMPLICIT_IV_SIZE], srcIV, TLS_AES_GCM_EXPLICIT_IV_SIZE);
err = ccgcm_init_with_iv(cipherCtx->gcm, cipherCtx->gcmCtx, cipherCtx->keySize, cipherCtx->key, cipherCtx->gcmIV);
return err;
}
static
int CCSymmAEADGetIV(uint8_t *destIV,
SymCipherContext cipherCtx)
{
if (cipherCtx == NULL || cipherCtx->gcm == NULL) {
sslErrorLog("CCSymmAEADSetIV: NULL cipherCtx\n");
return errSSLRecordInternal;
}
memcpy(destIV, &cipherCtx->gcmIV[TLS_AES_GCM_IMPLICIT_IV_SIZE], TLS_AES_GCM_EXPLICIT_IV_SIZE);
return 0;
}
static
int CCSymmAEADEncrypt(const uint8_t *src,
uint8_t *dest,
size_t len,
SymCipherContext cipherCtx)
{
int err = 0;
if (cipherCtx == NULL || cipherCtx->gcm == NULL) {
sslErrorLog("CCSymmAEADEncrypt: NULL cipherCtx\n");
return errSSLRecordInternal;
}
err = ccgcm_update(cipherCtx->gcm, cipherCtx->gcmCtx, len-(TLS_AES_GCM_EXPLICIT_IV_SIZE+TLS_AES_GCM_TAG_SIZE),
src+TLS_AES_GCM_EXPLICIT_IV_SIZE, dest+TLS_AES_GCM_EXPLICIT_IV_SIZE);
err |= ccgcm_finalize(cipherCtx->gcm, cipherCtx->gcmCtx, TLS_AES_GCM_TAG_SIZE, &dest[len-TLS_AES_GCM_TAG_SIZE]);
err |= ccgcm_reset(cipherCtx->gcm, cipherCtx->gcmCtx);
err |= ccgcm_inc_iv(cipherCtx->gcm, cipherCtx->gcmCtx, cipherCtx->gcmIV);
return err;
}
static
int CCSymmAEADDecrypt(const uint8_t *src,
uint8_t *dest,
size_t len,
SymCipherContext cipherCtx)
{
int err = 0;
if (cipherCtx == NULL || cipherCtx->gcm == NULL) {
printf("CCSymmAEADDecrypt: NULL cipherCtx\n");
return -1;
}
uint8_t tagCopy[TLS_AES_GCM_TAG_SIZE];
memcpy(tagCopy, &src[len-TLS_AES_GCM_TAG_SIZE], TLS_AES_GCM_TAG_SIZE);
err = ccgcm_update(cipherCtx->gcm, cipherCtx->gcmCtx, len-TLS_AES_GCM_TAG_SIZE, src, dest);
err |= ccgcm_finalize(cipherCtx->gcm, cipherCtx->gcmCtx, TLS_AES_GCM_TAG_SIZE, tagCopy);
err |= ccgcm_reset(cipherCtx->gcm, cipherCtx->gcmCtx);
err |= ccgcm_inc_iv(cipherCtx->gcm, cipherCtx->gcmCtx, cipherCtx->gcmIV);
if (err != 0) {
cc_clear(len-TLS_AES_GCM_TAG_SIZE, dest);
}
return err;
}
static
int CCSymmAddADD(const uint8_t *src,
size_t len,
SymCipherContext cipherCtx)
{
if (cipherCtx == NULL || cipherCtx->gcm == NULL) {
sslErrorLog("CCSymmAddADD: NULL cipherCtx\n");
return errSSLRecordInternal;
}
return ccgcm_gmac(cipherCtx->gcm, cipherCtx->gcmCtx, len, src);
}
static
int CCSymmFinish(SymCipherContext cipherCtx)
{
if (cipherCtx) {
ccgcm_ctx_clear(cipherCtx->gcm->size, cipherCtx->gcmCtx);
sslFree(cipherCtx->gcmCtx);
cc_clear(cipherCtx->keySize, cipherCtx->key);
sslFree(cipherCtx->key);
sslFree(cipherCtx);
}
return 0;
}
const SSLSymmetricCipher SSLCipherAES_128_GCM = {
.params = &SSLCipherAES_128_GCMParams,
.c.aead = {
.initialize = CCGCMSymmInit,
.setIV = CCSymmAEADSetIV,
.getIV = CCSymmAEADGetIV,
.update = CCSymmAddADD,
.encrypt = CCSymmAEADEncrypt,
.decrypt = CCSymmAEADDecrypt,
},
.finish = CCSymmFinish
};
const SSLSymmetricCipher SSLCipherAES_256_GCM = {
.params = &SSLCipherAES_256_GCMParams,
.c.aead = {
.initialize = CCGCMSymmInit,
.setIV = CCSymmAEADSetIV,
.getIV = CCSymmAEADGetIV,
.update = CCSymmAddADD,
.encrypt = CCSymmAEADEncrypt,
.decrypt = CCSymmAEADDecrypt,
},
.finish = CCSymmFinish
};