CommonCryptorGCM.c [plain text]
#include "ccdebug.h"
#include <CommonCrypto/CommonCryptor.h>
#include <CommonCrypto/CommonCryptorSPI.h>
#include "CommonCryptorPriv.h"
#include <corecrypto/ccn.h>
#include "CommonCryptorPriv.h"
#define decl_cryptor() CCCryptor *cryptor = getRealCryptor(cryptorRef, 0); \
CC_DEBUG_LOG("Entering\n"); \
if(!cryptor) return kCCParamError;
static inline CCCryptorStatus translate_err_code(int err)
{
switch (err) {
case CCERR_OK:
return kCCSuccess;
case CCERR_PARAMETER:
return kCCParamError;
default:
return kCCUnspecifiedError;
}
}
CCCryptorStatus
CCCryptorGCMAddIV(CCCryptorRef cryptorRef,
const void *iv,
size_t ivLen)
{
decl_cryptor();
if(ivLen!=0 && iv==NULL) return kCCParamError;
int rc = ccgcm_set_iv_legacy(cryptor->symMode[cryptor->op].gcm,cryptor->ctx[cryptor->op].gcm, ivLen, iv);
return translate_err_code(rc);
}
CCCryptorStatus
CCCryptorGCMSetIV(CCCryptorRef cryptorRef,
const void *iv,
size_t ivLen)
{
decl_cryptor();
if(ivLen<AESGCM_MIN_IV_LEN || iv==NULL) return kCCParamError;
int rc = ccgcm_set_iv(cryptor->symMode[cryptor->op].gcm,cryptor->ctx[cryptor->op].gcm, ivLen, iv);
return translate_err_code(rc);
}
CCCryptorStatus
CCCryptorGCMAddAAD(CCCryptorRef cryptorRef,
const void *aData,
size_t aDataLen)
{
decl_cryptor();
if(aDataLen!=0 && aData==NULL) return kCCParamError;
int rc = ccgcm_aad(cryptor->symMode[cryptor->op].gcm,cryptor->ctx[cryptor->op].gcm, aDataLen, aData);
return translate_err_code(rc);
}
CCCryptorStatus
CCCryptorGCMAddADD(CCCryptorRef cryptorRef,
const void *aData,
size_t aDataLen)
{
return CCCryptorGCMAddAAD(cryptorRef, aData, aDataLen);
}
CCCryptorStatus
CCCryptorGCMaddAAD(CCCryptorRef cryptorRef,
const void *aData,
size_t aDataLen)
{
return CCCryptorGCMAddAAD(cryptorRef, aData, aDataLen);
}
static CCCryptorStatus gcm_update(CCCryptorRef cryptorRef,
const void *dataIn, size_t dataInLength,
void *dataOut)
{
decl_cryptor();
if(dataInLength!=0 && dataIn==NULL) return kCCParamError;
if(dataOut == NULL) return kCCParamError;
int rc = ccgcm_update(cryptor->symMode[cryptor->op].gcm,cryptor->ctx[cryptor->op].gcm, dataInLength, dataIn, dataOut);
return translate_err_code(rc);
}
CCCryptorStatus CCCryptorGCMEncrypt(CCCryptorRef cryptorRef,
const void *dataIn, size_t dataInLength,
void *dataOut)
{
return gcm_update(cryptorRef, dataIn, dataInLength, dataOut);
}
CCCryptorStatus CCCryptorGCMDecrypt(CCCryptorRef cryptorRef,
const void *dataIn, size_t dataInLength,
void *dataOut)
{
return gcm_update(cryptorRef, dataIn, dataInLength, dataOut);
}
CCCryptorStatus CCCryptorGCMFinal(CCCryptorRef cryptorRef,
void *tagOut, size_t *tagLength)
{
decl_cryptor();
if(tagOut == NULL || tagLength == NULL) return kCCParamError;
int rc = ccgcm_finalize(cryptor->symMode[cryptor->op].gcm,cryptor->ctx[cryptor->op].gcm, *tagLength, (void *) tagOut);
if(rc == -1)
return kCCUnspecifiedError;
else
return kCCSuccess;
}
CCCryptorStatus CCCryptorGCMFinalize(CCCryptorRef cryptorRef,
void *tag, size_t tagLength)
{
decl_cryptor();
if(tag==NULL || tagLength<AESGCM_MIN_TAG_LEN || tagLength>AESGCM_BLOCK_LEN) return kCCParamError;
if(cryptorRef->op!=kCCEncrypt && cryptorRef->op!=kCCDecrypt) return kCCParamError;
char dec_tag[tagLength];
if(cryptorRef->op == kCCDecrypt){
memcpy(dec_tag, tag, sizeof(dec_tag));
tag = dec_tag;
}
int rc = ccgcm_finalize(cryptor->symMode[cryptor->op].gcm,cryptor->ctx[cryptor->op].gcm, tagLength, tag);
CCCryptorStatus rv = rc == 0 ? kCCSuccess : kCCUnspecifiedError;
if(cryptorRef->op == kCCDecrypt)
cc_clear(sizeof dec_tag, dec_tag);
return rv;
}
CCCryptorStatus CCCryptorGCMReset(CCCryptorRef cryptorRef)
{
decl_cryptor();
int rc = ccgcm_reset(cryptor->symMode[cryptor->op].gcm,cryptor->ctx[cryptor->op].gcm);
return translate_err_code(rc);
}
CCCryptorStatus CCCryptorGCM(CCOperation op,
CCAlgorithm alg,
const void *key, size_t keyLength,
const void *iv, size_t ivLen,
const void *aData, size_t aDataLen,
const void *dataIn, size_t dataInLength,
void *dataOut,
void *tagOut, size_t *tagLength)
{
CCCryptorRef cryptorRef;
CCCryptorStatus retval;
CC_DEBUG_LOG("Entering Op: %d Cipher: %d\n", op, alg);
retval = CCCryptorCreateWithMode(op, kCCModeGCM, alg, 0, NULL, key, keyLength,
NULL, 0, 0, 0, &cryptorRef);
if(retval) return retval;
retval = CCCryptorGCMAddIV(cryptorRef, iv, ivLen);
if(retval) return retval;
retval = CCCryptorGCMaddAAD(cryptorRef, aData, aDataLen);
if(retval) return retval;
retval = gcm_update(cryptorRef, dataIn, dataInLength, dataOut);
if(retval) return retval;
retval = CCCryptorGCMFinal(cryptorRef, tagOut, tagLength);
CCCryptorRelease(cryptorRef);
return retval;
}
static CCCryptorStatus validate_gcm_params(CCAlgorithm alg, CCOperation op, const void *key, size_t keyLength,
const void *iv, size_t ivLen,
const void *aData, size_t aDataLen,
const void *dataIn, size_t dataInLength,
void *dataOut,
const void *tag, size_t tagLength){
(void)aData; (void)aDataLen;
(void)dataIn; (void)dataInLength;
(void) op;
if(alg!=kCCAlgorithmAES)
return kCCParamError;
if (keyLength != kCCKeySizeAES128 && keyLength != kCCKeySizeAES192 && keyLength != kCCKeySizeAES256) {
return kCCKeySizeError;
}
if(tagLength<AESGCM_MIN_TAG_LEN || tagLength>AESGCM_BLOCK_LEN)
return kCCParamError;
if(keyLength<AESGCM_BLOCK_LEN || ivLen<AESGCM_MIN_IV_LEN)
return kCCParamError;
if(key==NULL || iv==NULL || tag==NULL || dataOut==NULL)
return kCCParamError;
return kCCSuccess;
}
CCCryptorStatus CCCryptorGCMOneshotEncrypt(CCAlgorithm alg, const void *key, size_t keyLength,
const void *iv, size_t ivLen,
const void *aData, size_t aDataLen,
const void *dataIn, size_t dataInLength,
void *dataOut,
void *tagOut, size_t tagLength)
{
CCCryptorStatus rv = validate_gcm_params(alg, kCCEncrypt, key, keyLength, iv, ivLen, aData, aDataLen, dataIn, dataInLength, dataOut, tagOut, tagLength);
if(rv!=kCCSuccess)
return rv;
int rc = ccgcm_one_shot(ccaes_gcm_encrypt_mode(), keyLength, key, ivLen, iv, aDataLen, aData, dataInLength, dataIn, dataOut, tagLength, tagOut);
return translate_err_code(rc);
}
CCCryptorStatus CCCryptorGCMOneshotDecrypt(CCAlgorithm alg, const void *key, size_t keyLength,
const void *iv, size_t ivLen,
const void *aData, size_t aDataLen,
const void *dataIn, size_t dataInLength,
void *dataOut,
const void *tagIn, size_t tagLength)
{
CCCryptorStatus rv = validate_gcm_params(alg, kCCDecrypt, key, keyLength, iv, ivLen, aData, aDataLen, dataIn, dataInLength, dataOut, tagIn, tagLength);
if(rv!=kCCSuccess)
return rv;
char tag[tagLength]; memcpy(tag, tagIn, sizeof(tag));
int rc = ccgcm_one_shot(ccaes_gcm_decrypt_mode(), keyLength, key, ivLen, iv, aDataLen, aData, dataInLength, dataIn, dataOut, tagLength, tag);
if (rc != CCERR_OK) {
cc_clear(dataInLength, dataOut);
}
cc_clear(sizeof tag, tag);
return translate_err_code(rc);
}