#include "cpa.h"
#include "cpa_cy_sym.h"
#include "icp_accel_devices.h"
#include "icp_adf_init.h"
#include "icp_adf_transport.h"
#include "icp_adf_debug.h"
#include "lac_log.h"
#include "lac_common.h"
#include "lac_session.h"
#include "lac_sym_auth_enc.h"
#define LAC_ALG_CHAIN_CCM_B0_FLAGS_ADATA_SHIFT 6
#define LAC_ALG_CHAIN_CCM_B0_FLAGS_T_SHIFT 3
#define LAC_ALG_CHAIN_CCM_BUILD_B0_FLAGS(Adata, t, q) \
((((Adata) > 0 ? 1 : 0) << LAC_ALG_CHAIN_CCM_B0_FLAGS_ADATA_SHIFT) | \
((((t)-2) >> 1) << LAC_ALG_CHAIN_CCM_B0_FLAGS_T_SHIFT) | ((q)-1))
CpaStatus
LacSymAlgChain_CheckCCMData(Cpa8U *pAdditionalAuthData,
Cpa8U *pIv,
Cpa32U messageLenToCipherInBytes,
Cpa32U ivLenInBytes)
{
Cpa8U q = 0;
LAC_CHECK_NULL_PARAM(pIv);
LAC_CHECK_NULL_PARAM(pAdditionalAuthData);
if (ivLenInBytes < LAC_ALG_CHAIN_CCM_N_LEN_IN_BYTES_MIN ||
ivLenInBytes > LAC_ALG_CHAIN_CCM_N_LEN_IN_BYTES_MAX) {
LAC_INVALID_PARAM_LOG2("ivLenInBytes for CCM algorithm "
"must be between %d and %d inclusive",
LAC_ALG_CHAIN_CCM_N_LEN_IN_BYTES_MIN,
LAC_ALG_CHAIN_CCM_N_LEN_IN_BYTES_MAX);
return CPA_STATUS_INVALID_PARAM;
}
q = LAC_ALG_CHAIN_CCM_NQ_CONST - ivLenInBytes;
if ((messageLenToCipherInBytes >= (1 << (q * LAC_NUM_BITS_IN_BYTE))) &&
(q < sizeof(Cpa32U))) {
LAC_INVALID_PARAM_LOG(
"messageLenToCipherInBytes too long for the given"
" ivLenInBytes for CCM algorithm\n");
return CPA_STATUS_INVALID_PARAM;
}
return CPA_STATUS_SUCCESS;
}
void
LacSymAlgChain_PrepareCCMData(lac_session_desc_t *pSessionDesc,
Cpa8U *pAdditionalAuthData,
Cpa8U *pIv,
Cpa32U messageLenToCipherInBytes,
Cpa32U ivLenInBytes)
{
Cpa8U n =
ivLenInBytes;
Cpa8U q = LAC_ALG_CHAIN_CCM_NQ_CONST - n;
Cpa8U lenOfEncodedLen = 0;
Cpa16U lenAEncoded = 0;
Cpa32U bitStrQ = 0;
pIv[0] = (q - 1);
memset(pIv + n + 1, 0, q);
if (pSessionDesc->aadLenInBytes > 0) {
lenOfEncodedLen = sizeof(Cpa16U);
lenAEncoded = QAT_UTILS_HOST_TO_NW_16(
(Cpa16U)pSessionDesc->aadLenInBytes);
}
pAdditionalAuthData[0] =
LAC_ALG_CHAIN_CCM_BUILD_B0_FLAGS(lenOfEncodedLen,
pSessionDesc->hashResultSize,
q);
bitStrQ = QAT_UTILS_HOST_TO_NW_32(messageLenToCipherInBytes);
if (q > sizeof(bitStrQ)) {
memset(pAdditionalAuthData + n + 1, 0, q);
memcpy(pAdditionalAuthData + n + 1 + (q - sizeof(bitStrQ)),
(Cpa8U *)&bitStrQ,
sizeof(bitStrQ));
} else {
memcpy(pAdditionalAuthData + n + 1,
((Cpa8U *)&bitStrQ) + (sizeof(bitStrQ) - q),
q);
}
if (lenAEncoded > 0) {
*(Cpa16U
*)(&pAdditionalAuthData[1 + LAC_ALG_CHAIN_CCM_NQ_CONST]) =
lenAEncoded;
if (((pSessionDesc->aadLenInBytes + lenOfEncodedLen) %
LAC_HASH_AES_CCM_BLOCK_SIZE) != 0) {
Cpa8U paddingLen = 0;
Cpa8U paddingIndex = 0;
paddingLen = LAC_HASH_AES_CCM_BLOCK_SIZE -
((pSessionDesc->aadLenInBytes + lenOfEncodedLen) %
LAC_HASH_AES_CCM_BLOCK_SIZE);
paddingIndex = 1 + LAC_ALG_CHAIN_CCM_NQ_CONST;
paddingIndex +=
lenOfEncodedLen + pSessionDesc->aadLenInBytes;
memset(&pAdditionalAuthData[paddingIndex],
0,
paddingLen);
}
}
}
void
LacSymAlgChain_PrepareGCMData(lac_session_desc_t *pSessionDesc,
Cpa8U *pAdditionalAuthData)
{
Cpa8U paddingLen = 0;
if ((pSessionDesc->aadLenInBytes % LAC_HASH_AES_GCM_BLOCK_SIZE) != 0) {
paddingLen = LAC_HASH_AES_GCM_BLOCK_SIZE -
(pSessionDesc->aadLenInBytes % LAC_HASH_AES_GCM_BLOCK_SIZE);
memset(&pAdditionalAuthData[pSessionDesc->aadLenInBytes],
0,
paddingLen);
}
}