CommonSymmetricKeywrap.c [plain text]
#include <CommonCrypto/CommonSymmetricKeywrap.h>
#include <CommonCrypto/CommonCryptor.h>
#include "CommonCryptorPriv.h"
#include <AssertMacros.h>
#include "ccdebug.h"
#include <corecrypto/ccwrap_priv.h>
static const uint8_t rfc3394_iv_data[] = {
0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6
};
const uint8_t * const CCrfc3394_iv = rfc3394_iv_data;
const size_t CCrfc3394_ivLen = sizeof(rfc3394_iv_data);
int
CCSymmetricKeyWrap(CCWrappingAlgorithm __unused algorithm,
const uint8_t *iv, const size_t ivLen,
const uint8_t *kek, size_t kekLen,
const uint8_t *rawKey, size_t rawKeyLen,
uint8_t *wrappedKey, size_t *wrappedKeyLen)
{
CC_DEBUG_LOG("Entering\n");
int err = kCCUnspecifiedError;
const struct ccmode_ecb *ccmode = getCipherMode(kCCAlgorithmAES128, kCCModeECB, kCCEncrypt).ecb;
ccecb_ctx_decl(ccmode->size, ctx);
require_action((kekLen == CCAES_KEY_SIZE_128 ||
kekLen == CCAES_KEY_SIZE_192 ||
kekLen == CCAES_KEY_SIZE_256),
out, err = kCCParamError);
require_action(wrappedKeyLen && (*wrappedKeyLen >= ccwrap_wrapped_size(rawKeyLen)), out, err = kCCParamError);
require_action((iv == NULL) || (ivLen >= CCWRAP_SEMIBLOCK), out, err = kCCParamError);
if (iv == NULL) {
iv = CCrfc3394_iv;
}
int ccrc = ccmode->init(ccmode, ctx, kekLen, kek);
require_action(ccrc == CCERR_OK, out, err = kCCParamError);
require_action(ccwrap_auth_encrypt_withiv(ccmode, ctx, rawKeyLen, rawKey, wrappedKeyLen, wrappedKey, iv) == CCERR_OK, out, err = kCCParamError);
err = kCCSuccess;
out:
if (err != kCCSuccess) {
cc_clear(*wrappedKeyLen, wrappedKey);
*wrappedKeyLen = 0;
}
ccecb_ctx_clear(ccmode->size, ctx);
return err;
}
int
CCSymmetricKeyUnwrap(CCWrappingAlgorithm __unused algorithm,
const uint8_t *iv, const size_t ivLen,
const uint8_t *kek, size_t kekLen,
const uint8_t *wrappedKey, size_t wrappedKeyLen,
uint8_t *rawKey, size_t *rawKeyLen)
{
CC_DEBUG_LOG("Entering\n");
int err = kCCUnspecifiedError;
const uint8_t *ivs[2] = { iv, CCrfc3394_iv };
int i;
size_t tmpRawKeyLen = 0;
void *tmpRawKey = NULL;
const struct ccmode_ecb *ccmode = getCipherMode(kCCAlgorithmAES128, kCCModeECB, kCCDecrypt).ecb;
ccecb_ctx_decl(ccmode->size, ctx);
require_action((kekLen == CCAES_KEY_SIZE_128 ||
kekLen == CCAES_KEY_SIZE_192 ||
kekLen == CCAES_KEY_SIZE_256),
out, err = kCCParamError);
require_action(rawKeyLen && (*rawKeyLen >= ccwrap_unwrapped_size(wrappedKeyLen)), out, err = kCCParamError);
require_action((iv == NULL) || (ivLen >= CCWRAP_SEMIBLOCK), out, err = kCCParamError);
int ccrc = ccmode->init(ccmode, ctx, kekLen, kek);
require_action(ccrc == CCERR_OK, out, err = kCCParamError);
tmpRawKey = malloc(*rawKeyLen);
require_action(tmpRawKey != NULL, out, err = kCCMemoryFailure);
err = kCCDecodeError;
for (i = 0; i < 2; i += 1) {
if (ivs[i] == NULL) {
continue;
}
tmpRawKeyLen = *rawKeyLen;
if (ccwrap_auth_decrypt_withiv(ccmode, ctx, wrappedKeyLen, wrappedKey, &tmpRawKeyLen, tmpRawKey, ivs[i]) == CCERR_OK) {
err = kCCSuccess;
break;
}
}
if (err == kCCSuccess) {
memcpy(rawKey, tmpRawKey, tmpRawKeyLen);
} else {
cc_clear(tmpRawKeyLen, rawKey);
}
cc_clear(*rawKeyLen, tmpRawKey);
free(tmpRawKey);
out:
*rawKeyLen = tmpRawKeyLen;
ccecb_ctx_clear(ccmode->size, ctx);
return err;
}
size_t
CCSymmetricWrappedSize(CCWrappingAlgorithm __unused algorithm, size_t rawKeyLen)
{
CC_DEBUG_LOG("Entering\n");
return ccwrap_wrapped_size(rawKeyLen);
}
size_t
CCSymmetricUnwrappedSize(CCWrappingAlgorithm __unused algorithm, size_t wrappedKeyLen)
{
CC_DEBUG_LOG("Entering\n");
return ccwrap_unwrapped_size(wrappedKeyLen);
}