#include "cpa.h"
#include "cpa_cy_sym.h"
#include "icp_adf_init.h"
#include "icp_adf_transport.h"
#include "icp_accel_devices.h"
#include "icp_adf_debug.h"
#include "icp_qat_fw_la.h"
#include "lac_sym_cipher.h"
#include "lac_session.h"
#include "lac_mem.h"
#include "lac_common.h"
#include "lac_list.h"
#include "lac_sym.h"
#include "lac_sym_key.h"
#include "lac_sym_qat_hash_defs_lookup.h"
#include "lac_sal_types_crypto.h"
#include "lac_sal.h"
#include "lac_sal_ctrl.h"
#include "lac_sym_cipher_defs.h"
#include "lac_sym_cipher.h"
#include "lac_sym_stats.h"
#include "lac_sym.h"
#include "lac_sym_qat_cipher.h"
#include "lac_log.h"
#include "lac_buffer_desc.h"
#include "sal_hw_gen.h"
CpaStatus
LacCipher_PerformIvCheck(sal_service_t *pService,
lac_sym_bulk_cookie_t *pCbCookie,
Cpa32U qatPacketType,
Cpa8U **ppIvBuffer)
{
const CpaCySymOpData *pOpData = pCbCookie->pOpData;
lac_session_desc_t *pSessionDesc =
LAC_SYM_SESSION_DESC_FROM_CTX_GET(pOpData->sessionCtx);
CpaCySymCipherAlgorithm algorithm = pSessionDesc->cipherAlgorithm;
unsigned ivLenInBytes = 0;
switch (algorithm) {
case CPA_CY_SYM_CIPHER_AES_CTR:
case CPA_CY_SYM_CIPHER_3DES_CTR:
case CPA_CY_SYM_CIPHER_SM4_CTR:
case CPA_CY_SYM_CIPHER_AES_CCM:
case CPA_CY_SYM_CIPHER_AES_GCM:
case CPA_CY_SYM_CIPHER_CHACHA:
case CPA_CY_SYM_CIPHER_AES_CBC:
case CPA_CY_SYM_CIPHER_DES_CBC:
case CPA_CY_SYM_CIPHER_3DES_CBC:
case CPA_CY_SYM_CIPHER_SM4_CBC:
case CPA_CY_SYM_CIPHER_AES_F8:
case CPA_CY_SYM_CIPHER_AES_XTS: {
ivLenInBytes = LacSymQat_CipherIvSizeBytesGet(algorithm);
LAC_CHECK_NULL_PARAM(pOpData->pIv);
if (pOpData->ivLenInBytes != ivLenInBytes) {
if (!(
(LAC_CIPHER_IS_GCM(algorithm) &&
pOpData->ivLenInBytes ==
LAC_CIPHER_IV_SIZE_GCM_12) ||
LAC_CIPHER_IS_CCM(algorithm))) {
LAC_INVALID_PARAM_LOG("invalid cipher IV size");
return CPA_STATUS_INVALID_PARAM;
}
}
if (ICP_QAT_FW_LA_PARTIAL_NONE == qatPacketType) {
*ppIvBuffer = pOpData->pIv;
} else {
*ppIvBuffer = pSessionDesc->cipherPartialOpState;
if ((ICP_QAT_FW_LA_PARTIAL_START == qatPacketType) ||
(ICP_QAT_FW_LA_PARTIAL_MID == qatPacketType)) {
pCbCookie->updateUserIvOnRecieve = CPA_TRUE;
if (ICP_QAT_FW_LA_PARTIAL_START ==
qatPacketType) {
pCbCookie->updateSessionIvOnSend =
CPA_TRUE;
}
}
}
} break;
case CPA_CY_SYM_CIPHER_KASUMI_F8: {
LAC_CHECK_NULL_PARAM(pOpData->pIv);
if (pOpData->ivLenInBytes != LAC_CIPHER_KASUMI_F8_IV_LENGTH) {
LAC_INVALID_PARAM_LOG("invalid cipher IV size");
return CPA_STATUS_INVALID_PARAM;
}
*ppIvBuffer = pOpData->pIv;
} break;
case CPA_CY_SYM_CIPHER_SNOW3G_UEA2: {
LAC_CHECK_NULL_PARAM(pOpData->pIv);
if (pOpData->ivLenInBytes != ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ) {
LAC_INVALID_PARAM_LOG("invalid cipher IV size");
return CPA_STATUS_INVALID_PARAM;
}
*ppIvBuffer = pOpData->pIv;
} break;
case CPA_CY_SYM_CIPHER_ARC4: {
if (ICP_QAT_FW_LA_PARTIAL_NONE == qatPacketType) {
*ppIvBuffer = pSessionDesc->cipherARC4InitialState;
} else {
*ppIvBuffer = pSessionDesc->cipherPartialOpState;
if (ICP_QAT_FW_LA_PARTIAL_START == qatPacketType) {
pCbCookie->updateSessionIvOnSend = CPA_TRUE;
}
}
} break;
case CPA_CY_SYM_CIPHER_ZUC_EEA3: {
LAC_CHECK_NULL_PARAM(pOpData->pIv);
if (pOpData->ivLenInBytes != ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ) {
LAC_INVALID_PARAM_LOG("invalid cipher IV size");
return CPA_STATUS_INVALID_PARAM;
}
*ppIvBuffer = pOpData->pIv;
} break;
default:
*ppIvBuffer = NULL;
}
return CPA_STATUS_SUCCESS;
}
CpaStatus
LacCipher_SessionSetupDataCheck(const CpaCySymCipherSetupData *pCipherSetupData,
Cpa32U capabilitiesMask)
{
if (!LAC_CIPHER_IS_NULL(pCipherSetupData->cipherAlgorithm)) {
LAC_CHECK_NULL_PARAM(pCipherSetupData->pCipherKey);
switch (pCipherSetupData->cipherAlgorithm) {
case CPA_CY_SYM_CIPHER_ARC4:
if (pCipherSetupData->cipherKeyLenInBytes >
ICP_QAT_HW_ARC4_KEY_SZ) {
LAC_INVALID_PARAM_LOG(
"Invalid ARC4 cipher key length");
return CPA_STATUS_INVALID_PARAM;
}
break;
case CPA_CY_SYM_CIPHER_AES_CCM:
if (!LAC_CIPHER_AES_V2(capabilitiesMask) &&
pCipherSetupData->cipherKeyLenInBytes !=
ICP_QAT_HW_AES_128_KEY_SZ) {
LAC_INVALID_PARAM_LOG(
"Invalid AES CCM cipher key length");
return CPA_STATUS_INVALID_PARAM;
}
break;
case CPA_CY_SYM_CIPHER_AES_XTS:
if ((pCipherSetupData->cipherKeyLenInBytes !=
ICP_QAT_HW_AES_128_XTS_KEY_SZ) &&
(pCipherSetupData->cipherKeyLenInBytes !=
ICP_QAT_HW_AES_256_XTS_KEY_SZ) &&
(pCipherSetupData->cipherKeyLenInBytes !=
ICP_QAT_HW_UCS_AES_128_XTS_KEY_SZ) &&
(pCipherSetupData->cipherKeyLenInBytes !=
ICP_QAT_HW_UCS_AES_256_XTS_KEY_SZ)) {
LAC_INVALID_PARAM_LOG(
"Invalid AES XTS cipher key length");
return CPA_STATUS_INVALID_PARAM;
}
break;
case CPA_CY_SYM_CIPHER_AES_ECB:
case CPA_CY_SYM_CIPHER_AES_CBC:
case CPA_CY_SYM_CIPHER_AES_CTR:
case CPA_CY_SYM_CIPHER_AES_GCM:
if ((pCipherSetupData->cipherKeyLenInBytes !=
ICP_QAT_HW_AES_128_KEY_SZ) &&
(pCipherSetupData->cipherKeyLenInBytes !=
ICP_QAT_HW_AES_192_KEY_SZ) &&
(pCipherSetupData->cipherKeyLenInBytes !=
ICP_QAT_HW_AES_256_KEY_SZ)) {
LAC_INVALID_PARAM_LOG(
"Invalid AES cipher key length");
return CPA_STATUS_INVALID_PARAM;
}
break;
case CPA_CY_SYM_CIPHER_AES_F8:
if ((pCipherSetupData->cipherKeyLenInBytes !=
ICP_QAT_HW_AES_128_F8_KEY_SZ) &&
(pCipherSetupData->cipherKeyLenInBytes !=
ICP_QAT_HW_AES_192_F8_KEY_SZ) &&
(pCipherSetupData->cipherKeyLenInBytes !=
ICP_QAT_HW_AES_256_F8_KEY_SZ)) {
LAC_INVALID_PARAM_LOG(
"Invalid AES cipher key length");
return CPA_STATUS_INVALID_PARAM;
}
break;
case CPA_CY_SYM_CIPHER_DES_ECB:
case CPA_CY_SYM_CIPHER_DES_CBC:
if (pCipherSetupData->cipherKeyLenInBytes !=
ICP_QAT_HW_DES_KEY_SZ) {
LAC_INVALID_PARAM_LOG(
"Invalid DES cipher key length");
return CPA_STATUS_INVALID_PARAM;
}
break;
case CPA_CY_SYM_CIPHER_3DES_ECB:
case CPA_CY_SYM_CIPHER_3DES_CBC:
case CPA_CY_SYM_CIPHER_3DES_CTR:
if (pCipherSetupData->cipherKeyLenInBytes !=
ICP_QAT_HW_3DES_KEY_SZ) {
LAC_INVALID_PARAM_LOG(
"Invalid Triple-DES cipher key length");
return CPA_STATUS_INVALID_PARAM;
}
break;
case CPA_CY_SYM_CIPHER_KASUMI_F8:
if (pCipherSetupData->cipherKeyLenInBytes !=
ICP_QAT_HW_KASUMI_KEY_SZ) {
LAC_INVALID_PARAM_LOG(
"Invalid Kasumi cipher key length");
return CPA_STATUS_INVALID_PARAM;
}
break;
case CPA_CY_SYM_CIPHER_SNOW3G_UEA2:
if (pCipherSetupData->cipherKeyLenInBytes !=
ICP_QAT_HW_SNOW_3G_UEA2_KEY_SZ) {
LAC_INVALID_PARAM_LOG(
"Invalid Snow_3G cipher key length");
return CPA_STATUS_INVALID_PARAM;
}
break;
case CPA_CY_SYM_CIPHER_ZUC_EEA3:
if (pCipherSetupData->cipherKeyLenInBytes !=
ICP_QAT_HW_ZUC_3G_EEA3_KEY_SZ) {
LAC_INVALID_PARAM_LOG(
"Invalid ZUC cipher key length");
return CPA_STATUS_INVALID_PARAM;
}
break;
case CPA_CY_SYM_CIPHER_CHACHA:
if (pCipherSetupData->cipherKeyLenInBytes !=
ICP_QAT_HW_CHACHAPOLY_KEY_SZ) {
LAC_INVALID_PARAM_LOG(
"Invalid CHACHAPOLY cipher key length");
return CPA_STATUS_INVALID_PARAM;
}
break;
case CPA_CY_SYM_CIPHER_SM4_ECB:
case CPA_CY_SYM_CIPHER_SM4_CBC:
case CPA_CY_SYM_CIPHER_SM4_CTR:
if (pCipherSetupData->cipherKeyLenInBytes !=
ICP_QAT_HW_SM4_KEY_SZ) {
LAC_INVALID_PARAM_LOG(
"Invalid SM4 cipher key length");
return CPA_STATUS_INVALID_PARAM;
}
break;
default:
LAC_INVALID_PARAM_LOG("Invalid cipher algorithm");
return CPA_STATUS_INVALID_PARAM;
}
}
return CPA_STATUS_SUCCESS;
}
CpaStatus
LacCipher_PerformParamCheck(CpaCySymCipherAlgorithm algorithm,
const CpaCySymOpData *pOpData,
const Cpa64U packetLen)
{
CpaStatus status = CPA_STATUS_SUCCESS;
if ((pOpData->messageLenToCipherInBytes +
pOpData->cryptoStartSrcOffsetInBytes) > packetLen) {
LAC_INVALID_PARAM_LOG("cipher len + offset greater than "
"srcBuffer packet len");
status = CPA_STATUS_INVALID_PARAM;
} else {
switch (algorithm) {
case CPA_CY_SYM_CIPHER_ARC4:
case CPA_CY_SYM_CIPHER_AES_CTR:
case CPA_CY_SYM_CIPHER_3DES_CTR:
case CPA_CY_SYM_CIPHER_SM4_CTR:
case CPA_CY_SYM_CIPHER_AES_CCM:
case CPA_CY_SYM_CIPHER_AES_GCM:
case CPA_CY_SYM_CIPHER_CHACHA:
case CPA_CY_SYM_CIPHER_KASUMI_F8:
case CPA_CY_SYM_CIPHER_AES_F8:
case CPA_CY_SYM_CIPHER_SNOW3G_UEA2:
case CPA_CY_SYM_CIPHER_ZUC_EEA3:
break;
case CPA_CY_SYM_CIPHER_AES_XTS:
if ((pOpData->packetType ==
CPA_CY_SYM_PACKET_TYPE_FULL) ||
(pOpData->packetType ==
CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL)) {
if (pOpData->messageLenToCipherInBytes <
ICP_QAT_HW_AES_BLK_SZ) {
LAC_INVALID_PARAM_LOG(
"data size must be greater than block"
" size for last XTS partial or XTS "
"full packet");
status = CPA_STATUS_INVALID_PARAM;
}
}
break;
default:
if (pOpData->messageLenToCipherInBytes &
(LacSymQat_CipherBlockSizeBytesGet(algorithm) -
1)) {
LAC_INVALID_PARAM_LOG(
"data size must be block size"
" multiple");
status = CPA_STATUS_INVALID_PARAM;
}
}
}
return status;
}
Cpa32U
LacCipher_GetCipherSliceType(sal_crypto_service_t *pService,
CpaCySymCipherAlgorithm cipherAlgorithm,
CpaCySymHashAlgorithm hashAlgorithm)
{
Cpa32U sliceType = ICP_QAT_FW_LA_USE_LEGACY_SLICE_TYPE;
Cpa32U capabilitiesMask =
pService->generic_service_info.capabilitiesMask;
if (isCyGen4x(pService)) {
if (LAC_CIPHER_IS_XTS_MODE(cipherAlgorithm) ||
LAC_CIPHER_IS_CHACHA(cipherAlgorithm) ||
LAC_CIPHER_IS_GCM(cipherAlgorithm)) {
sliceType = ICP_QAT_FW_LA_USE_UCS_SLICE_TYPE;
} else if (LAC_CIPHER_IS_CCM(cipherAlgorithm) &&
LAC_CIPHER_AES_V2(capabilitiesMask)) {
sliceType = ICP_QAT_FW_LA_USE_LEGACY_SLICE_TYPE;
} else if (LAC_CIPHER_IS_AES(cipherAlgorithm) &&
LAC_CIPHER_IS_CTR_MODE(cipherAlgorithm)) {
sliceType = ICP_QAT_FW_LA_USE_UCS_SLICE_TYPE;
}
}
return sliceType;
}