corecrypto/corecrypto_test/lib/ccsymmetric.c

468 lines
17 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Copyright (c) (2012,2014-2016,2018-2020) Apple Inc. All rights reserved.
*
* corecrypto is licensed under Apple Inc.s Internal Use License Agreement (which
* is contained in the License.txt file distributed with corecrypto) and only to
* people who accept that license. IMPORTANT: Any license rights granted to you by
* Apple Inc. (if any) are limited to internal use within your organization only on
* devices and computers you own or control, for the sole purpose of verifying the
* security characteristics and correct functioning of the Apple Software. You may
* not, directly or indirectly, redistribute the Apple Software or any portions thereof.
*/
#include <stdbool.h>
#include "ccsymmetric.h"
#include "testmore.h"
int cc_get_ciphermode(cc_cipher_select cipher, cc_mode_select mode, cc_direction direction, cc_ciphermode_descriptor desc)
{
desc->cipher = cipher;
desc->mode = mode;
desc->direction = direction;
desc->ciphermode.data = NULL;
int op = direction == cc_Encrypt; // save editting flip-flop logic
switch (cipher) {
case cc_cipherAES:
switch (mode) {
case cc_ModeECB:
desc->ciphermode.ecb = (op) ? ccaes_ecb_encrypt_mode() : ccaes_ecb_decrypt_mode();
break;
case cc_ModeCBC:
desc->ciphermode.cbc = (op) ? ccaes_cbc_encrypt_mode() : ccaes_cbc_decrypt_mode();
break;
case cc_ModeCFB:
desc->ciphermode.cfb = (op) ? ccaes_cfb_encrypt_mode() : ccaes_cfb_decrypt_mode();
break;
case cc_ModeCTR:
desc->ciphermode.ctr = ccaes_ctr_crypt_mode();
break;
case cc_ModeOFB:
desc->ciphermode.ofb = ccaes_ofb_crypt_mode();
break;
case cc_ModeXTS:
desc->ciphermode.xts = (op) ? ccaes_xts_encrypt_mode() : ccaes_xts_decrypt_mode();
break;
case cc_ModeCFB8:
desc->ciphermode.cfb8 = (op) ? ccaes_cfb8_encrypt_mode() : ccaes_cfb8_decrypt_mode();
break;
case cc_ModeGCM:
desc->ciphermode.gcm = (op) ? ccaes_gcm_encrypt_mode() : ccaes_gcm_decrypt_mode();
break;
case cc_ModeCCM:
desc->ciphermode.ccm = (op) ? ccaes_ccm_encrypt_mode() : ccaes_ccm_decrypt_mode();
break;
}
break;
case cc_cipherDES:
switch (mode) {
case cc_ModeECB:
desc->ciphermode.ecb = (op) ? ccdes_ecb_encrypt_mode() : ccdes_ecb_decrypt_mode();
break;
case cc_ModeCBC:
desc->ciphermode.cbc = (op) ? ccdes_cbc_encrypt_mode() : ccdes_cbc_decrypt_mode();
break;
case cc_ModeCFB:
desc->ciphermode.cfb = (op) ? ccdes_cfb_encrypt_mode() : ccdes_cfb_decrypt_mode();
break;
case cc_ModeCTR:
desc->ciphermode.ctr = ccdes_ctr_crypt_mode();
break;
case cc_ModeOFB:
desc->ciphermode.ofb = ccdes_ofb_crypt_mode();
break;
case cc_ModeCFB8:
desc->ciphermode.cfb8 = (op) ? ccdes_cfb8_encrypt_mode() : ccdes_cfb8_decrypt_mode();
break;
}
break;
case cc_cipher3DES:
switch (mode) {
case cc_ModeECB:
desc->ciphermode.ecb = (op) ? ccdes3_ecb_encrypt_mode() : ccdes3_ecb_decrypt_mode();
break;
case cc_ModeCBC:
desc->ciphermode.cbc = (op) ? ccdes3_cbc_encrypt_mode() : ccdes3_cbc_decrypt_mode();
break;
case cc_ModeCFB:
desc->ciphermode.cfb = (op) ? ccdes3_cfb_encrypt_mode() : ccdes3_cfb_decrypt_mode();
break;
case cc_ModeCTR:
desc->ciphermode.ctr = ccdes3_ctr_crypt_mode();
break;
case cc_ModeOFB:
desc->ciphermode.ofb = ccdes3_ofb_crypt_mode();
break;
case cc_ModeCFB8:
desc->ciphermode.cfb8 = (op) ? ccdes3_cfb8_encrypt_mode() : ccdes3_cfb8_decrypt_mode();
break;
}
break;
case cc_cipherCAST:
switch (mode) {
case cc_ModeECB:
desc->ciphermode.ecb = (op) ? cccast_ecb_encrypt_mode() : cccast_ecb_decrypt_mode();
break;
case cc_ModeCBC:
desc->ciphermode.cbc = (op) ? cccast_cbc_encrypt_mode() : cccast_cbc_decrypt_mode();
break;
case cc_ModeCFB:
desc->ciphermode.cfb = (op) ? cccast_cfb_encrypt_mode() : cccast_cfb_decrypt_mode();
break;
case cc_ModeCTR:
desc->ciphermode.ctr = cccast_ctr_crypt_mode();
break;
case cc_ModeOFB:
desc->ciphermode.ofb = cccast_ofb_crypt_mode();
break;
case cc_ModeCFB8:
desc->ciphermode.cfb8 = (op) ? cccast_cfb8_encrypt_mode() : cccast_cfb8_decrypt_mode();
break;
}
break;
case cc_cipherRC2:
switch (mode) {
case cc_ModeECB:
desc->ciphermode.ecb = (op) ? ccrc2_ecb_encrypt_mode() : ccrc2_ecb_decrypt_mode();
break;
case cc_ModeCBC:
desc->ciphermode.cbc = (op) ? ccrc2_cbc_encrypt_mode() : ccrc2_cbc_decrypt_mode();
break;
case cc_ModeCFB:
desc->ciphermode.cfb = (op) ? ccrc2_cfb_encrypt_mode() : ccrc2_cfb_decrypt_mode();
break;
case cc_ModeCTR:
desc->ciphermode.ctr = ccrc2_ctr_crypt_mode();
break;
case cc_ModeOFB:
desc->ciphermode.ofb = ccrc2_ofb_crypt_mode();
break;
case cc_ModeCFB8:
desc->ciphermode.cfb8 = (op) ? ccrc2_cfb8_encrypt_mode() : ccrc2_cfb8_decrypt_mode();
break;
}
break;
case cc_cipherBlowfish:
switch (mode) {
case cc_ModeECB:
desc->ciphermode.ecb = (op) ? ccblowfish_ecb_encrypt_mode() : ccblowfish_ecb_decrypt_mode();
break;
case cc_ModeCBC:
desc->ciphermode.cbc = (op) ? ccblowfish_cbc_encrypt_mode() : ccblowfish_cbc_decrypt_mode();
break;
case cc_ModeCFB:
desc->ciphermode.cfb = (op) ? ccblowfish_cfb_encrypt_mode() : ccblowfish_cfb_decrypt_mode();
break;
case cc_ModeCTR:
desc->ciphermode.ctr = ccblowfish_ctr_crypt_mode();
break;
case cc_ModeOFB:
desc->ciphermode.ofb = ccblowfish_ofb_crypt_mode();
break;
case cc_ModeCFB8:
desc->ciphermode.cfb8 = (op) ? ccblowfish_cfb8_encrypt_mode() : ccblowfish_cfb8_decrypt_mode();
break;
}
break;
}
if (desc->ciphermode.data == NULL)
return CC_FAILURE;
return CC_SUCCESS;
}
int cc_get_C_ciphermode(cc_cipher_select cipher, cc_mode_select mode, cc_direction direction, cc_ciphermode_descriptor desc)
{
desc->cipher = cipher;
desc->mode = mode;
desc->direction = direction;
desc->ciphermode.data = NULL;
return CC_UNIMPLEMENTED;
}
static bool verify_and_ok_duplicate_key(const void *key, size_t keylen)
{
if (keylen != 24) {
return false;
}
if (memcmp(key, key+8, 8) == 0 || memcmp(key, key+16, 8) == 0 || memcmp(key+8, key+16, 8) == 0) {
return true;
}
return false;
}
int cc_symmetric_setup(cc_ciphermode_descriptor cm, const void *key, size_t keylen, const void *iv, cc_symmetric_context_p ctx)
{
int rc;
switch (cm->mode) {
case cc_ModeECB:
rc = cm->ciphermode.ecb->init(cm->ciphermode.ecb, ctx->ctx.ecb, keylen, key);
break;
case cc_ModeCBC:
rc = cm->ciphermode.cbc->init(cm->ciphermode.cbc, ctx->ctx.cbc, keylen, key);
break;
case cc_ModeCFB:
rc = cm->ciphermode.cfb->init(cm->ciphermode.cfb, ctx->ctx.cfb, keylen, key, iv);
break;
case cc_ModeCTR:
rc = cm->ciphermode.ctr->init(cm->ciphermode.ctr, ctx->ctx.ctr, keylen, key, iv);
break;
case cc_ModeOFB:
rc = cm->ciphermode.ofb->init(cm->ciphermode.ofb, ctx->ctx.ofb, keylen, key, iv);
break;
case cc_ModeCFB8:
rc = cm->ciphermode.cfb8->init(cm->ciphermode.cfb8, ctx->ctx.cfb8, keylen, key, iv);
break;
default:
return CC_FAILURE;
}
// 3DES was modified to return an error of -1 on a 3DES key setup which repeated any of the sub-keys
// However, we still want to test these historic test vectors. So if we get a fail on setup we verify that it is
// for a repeated key in 3DES, and if so, we continue with the test.
if ((rc == -1) && (cm->cipher == cc_cipher3DES)) {
rc = verify_and_ok_duplicate_key(key, keylen) ? 0 : rc;
}
return (rc == 0) ? CC_SUCCESS : CC_FAILURE;
}
int cc_symmetric_setup_tweaked(cc_ciphermode_descriptor cm,
const void *key,
size_t keylen,
const void *tweak,
CC_UNUSED const void *iv,
cc_symmetric_context_p ctx)
{
switch (cm->mode) {
case cc_ModeXTS:
if (cm->ciphermode.xts->init(cm->ciphermode.xts, ctx->ctx.xts, keylen, key, tweak) == 0) {
return CC_SUCCESS;
}
}
return CC_FAILURE;
}
int cc_symmetric_setup_authenticated(cc_ciphermode_descriptor cm,
const void *key,
size_t keylen,
const void *iv,
size_t iv_len,
const void *adata,
size_t adata_len,
const void *adata2,
size_t adata2_len,
size_t data_len,
size_t tag_len,
cc_symmetric_context_p ctx)
{
int rc;
switch (cm->mode) {
case cc_ModeGCM:
rc = ccgcm_init(cm->ciphermode.gcm, ctx->ctx.gcm, keylen, key);
if (rc == 0)
rc = ccgcm_set_iv(cm->ciphermode.gcm, ctx->ctx.gcm, iv_len, iv);
if (rc == 0)
rc = ccgcm_aad(cm->ciphermode.gcm, ctx->ctx.gcm, adata_len, adata);
break;
case cc_ModeCCM:
rc = ccccm_init(cm->ciphermode.ccm, ctx->ctx.ccm, keylen, key);
if (rc == 0)
rc =
ccccm_set_iv(cm->ciphermode.ccm, ctx->ctx.ccm, ctx->xtra_ctx.ccm_nonce, iv_len, iv, tag_len, adata_len, data_len);
if (rc == 0)
rc = ccccm_cbcmac(cm->ciphermode.ccm, ctx->ctx.ccm, ctx->xtra_ctx.ccm_nonce, adata_len, adata);
break;
case cc_ModeSIV:
rc = ccsiv_init(cm->ciphermode.siv, ctx->ctx.siv, keylen, key);
if (rc == 0)
rc = ccsiv_aad(cm->ciphermode.siv, ctx->ctx.siv, adata_len, adata);
if (rc == 0)
rc = ccsiv_aad(cm->ciphermode.siv, ctx->ctx.siv, adata2_len, adata2);
if (rc == 0)
rc = ccsiv_set_nonce(cm->ciphermode.siv, ctx->ctx.siv, iv_len, iv);
break;
case cc_ModeSIV_HMAC:
rc = ccsiv_hmac_init(cm->ciphermode.siv_hmac, ctx->ctx.siv_hmac, keylen, key, tag_len);
if (adata_len == 0){
is(ccsiv_hmac_aad(cm->ciphermode.siv_hmac, ctx->ctx.siv_hmac, adata_len, adata), CCMODE_AD_EMPTY, "Empty associated data not reported as error.");
}
if (rc == 0 && adata_len != 0)
rc = ccsiv_hmac_aad(cm->ciphermode.siv_hmac, ctx->ctx.siv_hmac, adata_len, adata);
if (rc == 0 && adata2_len != 0)
rc = ccsiv_hmac_aad(cm->ciphermode.siv_hmac, ctx->ctx.siv_hmac, adata2_len, adata2);
if (iv_len == 0){
is(ccsiv_hmac_set_nonce(cm->ciphermode.siv_hmac, ctx->ctx.siv_hmac, iv_len, iv), CCMODE_NONCE_EMPTY, "Empty nonce data not reported as error.");
}
if (rc == 0 && iv_len != 0)
rc = ccsiv_hmac_set_nonce(cm->ciphermode.siv_hmac, ctx->ctx.siv_hmac, iv_len, iv);
break;
default:
return CC_FAILURE;
}
return rc;
}
int cc_symmetric_crypt(cc_symmetric_context_p ctx, const void *iv, const void *in, void *out, size_t len)
{
int rc;
switch (ctx->mode_desc->mode) {
case cc_ModeECB:
rc = ctx->mode_desc->ciphermode.ecb->ecb(ctx->ctx.ecb, len / ctx->mode_desc->ciphermode.ecb->block_size, in, out);
break;
case cc_ModeCBC: {
cccbc_iv_decl(ctx->mode_desc->ciphermode.cbc->block_size, cbciv);
if ((rc = cccbc_set_iv(ctx->mode_desc->ciphermode.cbc, cbciv, iv))) {
return rc;
}
if ((rc = ctx->mode_desc->ciphermode.cbc->cbc(
ctx->ctx.cbc, cbciv, len / ctx->mode_desc->ciphermode.cbc->block_size, in, out))) {
return rc;
}
} break;
case cc_ModeCFB:
rc = ctx->mode_desc->ciphermode.cfb->cfb(ctx->ctx.cfb, len / ctx->mode_desc->ciphermode.cfb->block_size, in, out);
break;
case cc_ModeCTR:
rc = ctx->mode_desc->ciphermode.ctr->ctr(ctx->ctx.ctr, len / ctx->mode_desc->ciphermode.ctr->block_size, in, out);
break;
case cc_ModeOFB:
rc = ctx->mode_desc->ciphermode.ofb->ofb(ctx->ctx.ofb, len / ctx->mode_desc->ciphermode.ofb->block_size, in, out);
break;
case cc_ModeCFB8:
rc = ctx->mode_desc->ciphermode.cfb8->cfb8(ctx->ctx.cfb8, len / ctx->mode_desc->ciphermode.cfb8->block_size, in, out);
break;
case cc_ModeXTS: {
ccxts_tweak_decl(ctx->mode_desc->ciphermode.xts->tweak_size, xts_iv);
if ((rc = ccxts_set_tweak(ctx->mode_desc->ciphermode.xts, ctx->ctx.xts, xts_iv, iv))) {
return rc;
}
if (ctx->mode_desc->ciphermode.xts->xts(
ctx->ctx.xts, xts_iv, len / ctx->mode_desc->ciphermode.xts->block_size, in, out) == NULL) {
return -1;
}
} break;
case cc_ModeGCM:
rc =
ccgcm_update(ctx->mode_desc->ciphermode.gcm, ctx->ctx.gcm, len / ctx->mode_desc->ciphermode.gcm->block_size, in, out);
break;
case cc_ModeCCM:
rc = ccccm_update(ctx->mode_desc->ciphermode.ccm,
ctx->ctx.ccm,
ctx->xtra_ctx.ccm_nonce,
len / ctx->mode_desc->ciphermode.ccm->block_size,
in,
out);
break;
case cc_ModeSIV:
rc = ccsiv_crypt(ctx->mode_desc->ciphermode.siv, ctx->ctx.siv, len / ctx->mode_desc->ciphermode.siv->block_size, in, out);
break;
case cc_ModeSIV_HMAC:
rc = ccsiv_hmac_crypt(ctx->mode_desc->ciphermode.siv_hmac, ctx->ctx.siv_hmac, len, in, out);
break;
default:
return CC_FAILURE;
}
return rc;
}
void cc_symmetric_final(CC_UNUSED cc_symmetric_context_p ctx)
{
}
int cc_symmetric_authenticated_finalize(cc_symmetric_context_p ctx, char *tag, size_t tag_len)
{
int rc;
switch (ctx->mode_desc->mode) {
case cc_ModeGCM:
rc = ctx->mode_desc->ciphermode.gcm->finalize(ctx->ctx.gcm, tag_len, tag);
break;
case cc_ModeCCM:
rc = ctx->mode_desc->ciphermode.ccm->finalize(ctx->ctx.ccm, ctx->xtra_ctx.ccm_nonce, tag);
break;
default:
return CC_FAILURE;
}
return rc;
}
int cc_symmetric_oneshot(cc_ciphermode_descriptor cm,
const void *key,
size_t keylen,
const void *iv,
const void *in,
void *out,
size_t len)
{
int rc;
switch (cm->mode) {
case cc_ModeECB:
rc = ccecb_one_shot(cm->ciphermode.ecb, keylen, key, len / cm->ciphermode.ecb->block_size, in, out);
break;
case cc_ModeCBC:
rc = cccbc_one_shot(cm->ciphermode.cbc, keylen, key, iv, len / cm->ciphermode.cbc->block_size, in, out);
break;
case cc_ModeCFB:
rc = cccfb_one_shot(cm->ciphermode.cfb, keylen, key, iv, len / cm->ciphermode.cfb->block_size, in, out);
break;
case cc_ModeCTR:
rc = ccctr_one_shot(cm->ciphermode.ctr, keylen, key, iv, len / cm->ciphermode.ctr->block_size, in, out);
break;
case cc_ModeOFB:
rc = ccofb_one_shot(cm->ciphermode.ofb, keylen, key, iv, len / cm->ciphermode.ofb->block_size, in, out);
break;
case cc_ModeCFB8:
rc = cccfb8_one_shot(cm->ciphermode.cfb8, keylen, key, iv, len / cm->ciphermode.cfb8->block_size, in, out);
break;
default:
return CC_FAILURE;
}
return rc;
}
int cc_symmetric_reset(cc_symmetric_context_p ctx)
{
int rc;
switch (ctx->mode_desc->mode) {
case cc_ModeGCM:
rc = ccgcm_reset(ctx->mode_desc->ciphermode.gcm, ctx->ctx.gcm);
break;
case cc_ModeCCM:
rc = ccccm_reset(ctx->mode_desc->ciphermode.ccm, ctx->ctx.ccm, ctx->xtra_ctx.ccm_nonce);
break;
case cc_ModeSIV:
rc = ccsiv_reset(ctx->mode_desc->ciphermode.siv, ctx->ctx.siv);
break;
default:
rc = CC_FAILURE;
}
return rc;
}
size_t cc_symmetric_bloc_size(cc_ciphermode_descriptor cm)
{
size_t block_size = 0;
switch (cm->mode) {
case cc_ModeECB:
block_size = cm->ciphermode.ecb->block_size;
break;
case cc_ModeCBC:
block_size = cm->ciphermode.cbc->block_size;
break;
case cc_ModeCFB:
block_size = cm->ciphermode.cfb->block_size;
break;
case cc_ModeCTR:
block_size = cm->ciphermode.ctr->block_size;
break;
case cc_ModeOFB:
block_size = cm->ciphermode.ofb->block_size;
break;
case cc_ModeCFB8:
block_size = cm->ciphermode.cfb8->block_size;
break;
default:
return 0;
}
return block_size;
}