diff options
| author | Julian Grajkowski <julianx.grajkowski@intel.com> | 2022-07-19 08:15:34 +0000 |
|---|---|---|
| committer | Mark Johnston <markj@FreeBSD.org> | 2022-07-27 15:12:35 +0000 |
| commit | 78ee8d1c4cdad7a56dbf50f1c8ade75531ce620c (patch) | |
| tree | 4e96ef389636fdec894275b41201927d26d7677c /sys/dev/qat/qat_api/common | |
| parent | f4f56ff43dbd30930f4b018e39ba2b9abf84551f (diff) | |
Diffstat (limited to 'sys/dev/qat/qat_api/common')
84 files changed, 33353 insertions, 0 deletions
diff --git a/sys/dev/qat/qat_api/common/compression/dc_buffers.c b/sys/dev/qat/qat_api/common/compression/dc_buffers.c new file mode 100644 index 000000000000..1a5d9bc8973e --- /dev/null +++ b/sys/dev/qat/qat_api/common/compression/dc_buffers.c @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file dc_buffers.c + * + * @defgroup Dc_DataCompression DC Data Compression + * + * @ingroup Dc_DataCompression + * + * @description + * Implementation of the buffer management operations for + * Data Compression service. + * + *****************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ +#include "cpa.h" +#include "cpa_dc.h" +#include "cpa_dc_bp.h" + +#include "sal_types_compression.h" +#include "icp_qat_fw_comp.h" + +#define CPA_DC_CEIL_DIV(x, y) (((x) + (y)-1) / (y)) +#define DC_DEST_BUFF_EXTRA_DEFLATE_GEN2 (55) + +CpaStatus +cpaDcBufferListGetMetaSize(const CpaInstanceHandle instanceHandle, + Cpa32U numBuffers, + Cpa32U *pSizeInBytes) +{ + CpaInstanceHandle insHandle = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = instanceHandle; + } + + LAC_CHECK_INSTANCE_HANDLE(insHandle); + LAC_CHECK_NULL_PARAM(pSizeInBytes); + + /* Ensure this is a compression instance */ + SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); + + if (0 == numBuffers) { + QAT_UTILS_LOG("Number of buffers is 0.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + *pSizeInBytes = (sizeof(icp_buffer_list_desc_t) + + (sizeof(icp_flat_buffer_desc_t) * (numBuffers + 1)) + + ICP_DESCRIPTOR_ALIGNMENT_BYTES); + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcBnpBufferListGetMetaSize(const CpaInstanceHandle instanceHandle, + Cpa32U numJobs, + Cpa32U *pSizeInBytes) +{ + return CPA_STATUS_UNSUPPORTED; +} + +static inline CpaStatus +dcDeflateBoundGen2(CpaDcHuffType huffType, Cpa32U inputSize, Cpa32U *outputSize) +{ + /* Formula for GEN2 deflate: + * ceil(9 * Total input bytes / 8) + 55 bytes. + * 55 bytes is the skid pad value for GEN2 devices. + */ + *outputSize = + CPA_DC_CEIL_DIV(9 * inputSize, 8) + DC_DEST_BUFF_EXTRA_DEFLATE_GEN2; + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcDeflateCompressBound(const CpaInstanceHandle dcInstance, + CpaDcHuffType huffType, + Cpa32U inputSize, + Cpa32U *outputSize) +{ + CpaInstanceHandle insHandle = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = dcInstance; + } + + LAC_CHECK_INSTANCE_HANDLE(insHandle); + LAC_CHECK_NULL_PARAM(outputSize); + /* Ensure this is a compression instance */ + SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); + if (!inputSize) { + QAT_UTILS_LOG( + "The input size needs to be greater than zero.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if ((CPA_DC_HT_STATIC != huffType) && + (CPA_DC_HT_FULL_DYNAMIC != huffType)) { + QAT_UTILS_LOG("Invalid huffType value.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + return dcDeflateBoundGen2(huffType, inputSize, outputSize); +} diff --git a/sys/dev/qat/qat_api/common/compression/dc_datapath.c b/sys/dev/qat/qat_api/common/compression/dc_datapath.c new file mode 100644 index 000000000000..0e2aa9f389e2 --- /dev/null +++ b/sys/dev/qat/qat_api/common/compression/dc_datapath.c @@ -0,0 +1,1790 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file dc_datapath.c + * + * @defgroup Dc_DataCompression DC Data Compression + * + * @ingroup Dc_DataCompression + * + * @description + * Implementation of the Data Compression datapath operations. + * + *****************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ +#include "cpa.h" +#include "cpa_dc.h" +#include "cpa_dc_dp.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ +#include "dc_session.h" +#include "dc_datapath.h" +#include "sal_statistics.h" +#include "lac_common.h" +#include "lac_mem.h" +#include "lac_mem_pools.h" +#include "sal_types_compression.h" +#include "dc_stats.h" +#include "lac_buffer_desc.h" +#include "lac_sal.h" +#include "lac_log.h" +#include "lac_sync.h" +#include "sal_service_state.h" +#include "sal_qat_cmn_msg.h" +#include "dc_error_counter.h" +#define DC_COMP_MAX_BUFF_SIZE (1024 * 64) + +static QatUtilsAtomic dcErrorCount[MAX_DC_ERROR_TYPE]; + +void +dcErrorLog(CpaDcReqStatus dcError) +{ + Cpa32U absError = 0; + + absError = abs(dcError); + if ((dcError < CPA_DC_OK) && (absError < MAX_DC_ERROR_TYPE)) { + qatUtilsAtomicInc(&(dcErrorCount[absError])); + } +} + +Cpa64U +getDcErrorCounter(CpaDcReqStatus dcError) +{ + Cpa32U absError = 0; + + absError = abs(dcError); + if (!(dcError >= CPA_DC_OK || dcError < CPA_DC_EMPTY_DYM_BLK)) { + return (Cpa64U)qatUtilsAtomicGet(&dcErrorCount[absError]); + } + + return 0; +} + +void +dcCompression_ProcessCallback(void *pRespMsg) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + icp_qat_fw_comp_resp_t *pCompRespMsg = NULL; + void *callbackTag = NULL; + Cpa64U *pReqData = NULL; + CpaDcDpOpData *pResponse = NULL; + CpaDcRqResults *pResults = NULL; + CpaDcCallbackFn pCbFunc = NULL; + dc_session_desc_t *pSessionDesc = NULL; + sal_compression_service_t *pService = NULL; + dc_compression_cookie_t *pCookie = NULL; + CpaDcOpData *pOpData = NULL; + CpaBoolean cmpPass = CPA_TRUE, xlatPass = CPA_TRUE; + CpaBoolean verifyHwIntegrityCrcs = CPA_FALSE; + Cpa8U cmpErr = ERR_CODE_NO_ERROR, xlatErr = ERR_CODE_NO_ERROR; + dc_request_dir_t compDecomp = DC_COMPRESSION_REQUEST; + Cpa8U opStatus = ICP_QAT_FW_COMN_STATUS_FLAG_OK; + Cpa8U hdrFlags = 0; + + /* Cast response message to compression response message type */ + pCompRespMsg = (icp_qat_fw_comp_resp_t *)pRespMsg; + + /* Extract request data pointer from the opaque data */ + LAC_MEM_SHARED_READ_TO_PTR(pCompRespMsg->opaque_data, pReqData); + + /* Extract fields from the request data structure */ + pCookie = (dc_compression_cookie_t *)pReqData; + if (!pCookie) + return; + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pCookie->pSessionHandle); + + if (CPA_TRUE == pSessionDesc->isDcDp) { + pResponse = (CpaDcDpOpData *)pReqData; + pResults = &(pResponse->results); + + if (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection) { + compDecomp = DC_DECOMPRESSION_REQUEST; + } + } else { + pSessionDesc = pCookie->pSessionDesc; + pResults = pCookie->pResults; + callbackTag = pCookie->callbackTag; + pCbFunc = pCookie->pSessionDesc->pCompressionCb; + compDecomp = pCookie->compDecomp; + pOpData = pCookie->pDcOpData; + } + + pService = (sal_compression_service_t *)(pCookie->dcInstance); + + opStatus = pCompRespMsg->comn_resp.comn_status; + + if (NULL != pOpData) { + verifyHwIntegrityCrcs = pOpData->verifyHwIntegrityCrcs; + } + + hdrFlags = pCompRespMsg->comn_resp.hdr_flags; + + /* Get the cmp error code */ + cmpErr = pCompRespMsg->comn_resp.comn_error.s1.cmp_err_code; + if (ICP_QAT_FW_COMN_RESP_UNSUPPORTED_REQUEST_STAT_GET(opStatus)) { + /* Compression not supported by firmware, set produced/consumed + to zero + and call the cb function with status CPA_STATUS_UNSUPPORTED + */ + QAT_UTILS_LOG("Compression feature not supported\n"); + status = CPA_STATUS_UNSUPPORTED; + pResults->status = (Cpa8S)cmpErr; + pResults->consumed = 0; + pResults->produced = 0; + if (CPA_TRUE == pSessionDesc->isDcDp) { + if (pResponse) + pResponse->responseStatus = + CPA_STATUS_UNSUPPORTED; + (pService->pDcDpCb)(pResponse); + } else { + /* Free the memory pool */ + Lac_MemPoolEntryFree(pCookie); + pCookie = NULL; + if (NULL != pCbFunc) { + pCbFunc(callbackTag, status); + } + } + if (DC_COMPRESSION_REQUEST == compDecomp) { + COMPRESSION_STAT_INC(numCompCompletedErrors, pService); + } else { + COMPRESSION_STAT_INC(numDecompCompletedErrors, + pService); + } + return; + } else { + /* Check compression response status */ + cmpPass = + (CpaBoolean)(ICP_QAT_FW_COMN_STATUS_FLAG_OK == + ICP_QAT_FW_COMN_RESP_CMP_STAT_GET(opStatus)); + } + + if (CPA_DC_INCOMPLETE_FILE_ERR == (Cpa8S)cmpErr) { + cmpPass = CPA_TRUE; + cmpErr = ERR_CODE_NO_ERROR; + } + /* log the slice hang and endpoint push/pull error inside the response + */ + if (ERR_CODE_SSM_ERROR == (Cpa8S)cmpErr) { + QAT_UTILS_LOG( + "Slice hang detected on the compression slice.\n"); + } else if (ERR_CODE_ENDPOINT_ERROR == (Cpa8S)cmpErr) { + QAT_UTILS_LOG( + "PCIe End Point Push/Pull or TI/RI Parity error detected.\n"); + } + + /* We return the compression error code for now. We would need to update + * the API if we decide to return both error codes */ + pResults->status = (Cpa8S)cmpErr; + + /* Check the translator status */ + if ((DC_COMPRESSION_REQUEST == compDecomp) && + (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType)) { + /* Check translator response status */ + xlatPass = + (CpaBoolean)(ICP_QAT_FW_COMN_STATUS_FLAG_OK == + ICP_QAT_FW_COMN_RESP_XLAT_STAT_GET(opStatus)); + + /* Get the translator error code */ + xlatErr = pCompRespMsg->comn_resp.comn_error.s1.xlat_err_code; + + /* Return a fatal error or a potential error in the translator + * slice + * if the compression slice did not return any error */ + if ((CPA_DC_OK == pResults->status) || + (CPA_DC_FATALERR == (Cpa8S)xlatErr)) { + pResults->status = (Cpa8S)xlatErr; + } + } + /* Update dc error counter */ + dcErrorLog(pResults->status); + + if (CPA_FALSE == pSessionDesc->isDcDp) { + /* In case of any error for an end of packet request, we need to + * update + * the request type for the following request */ + if (CPA_DC_FLUSH_FINAL == pCookie->flushFlag && cmpPass && + xlatPass) { + pSessionDesc->requestType = DC_REQUEST_FIRST; + } else { + pSessionDesc->requestType = DC_REQUEST_SUBSEQUENT; + } + if ((CPA_DC_STATEFUL == pSessionDesc->sessState) || + ((CPA_DC_STATELESS == pSessionDesc->sessState) && + (DC_COMPRESSION_REQUEST == compDecomp))) { + /* Overflow is a valid use case for Traditional API + * only. + * Stateful Overflow is supported in both compression + * and + * decompression direction. + * Stateless Overflow is supported only in compression + * direction. + */ + if (CPA_DC_OVERFLOW == (Cpa8S)cmpErr) + cmpPass = CPA_TRUE; + + if (CPA_DC_OVERFLOW == (Cpa8S)xlatErr) { + xlatPass = CPA_TRUE; + } + } + } else { + if (CPA_DC_OVERFLOW == (Cpa8S)cmpErr) { + cmpPass = CPA_FALSE; + } + if (CPA_DC_OVERFLOW == (Cpa8S)xlatErr) { + xlatPass = CPA_FALSE; + } + } + + if ((CPA_TRUE == cmpPass) && (CPA_TRUE == xlatPass)) { + /* Extract the response from the firmware */ + pResults->consumed = + pCompRespMsg->comp_resp_pars.input_byte_counter; + pResults->produced = + pCompRespMsg->comp_resp_pars.output_byte_counter; + pSessionDesc->cumulativeConsumedBytes += pResults->consumed; + + if (CPA_DC_OVERFLOW != (Cpa8S)xlatErr) { + if (CPA_DC_CRC32 == pSessionDesc->checksumType) { + pResults->checksum = + pCompRespMsg->comp_resp_pars.crc.legacy + .curr_crc32; + } else if (CPA_DC_ADLER32 == + pSessionDesc->checksumType) { + pResults->checksum = + pCompRespMsg->comp_resp_pars.crc.legacy + .curr_adler_32; + } + pSessionDesc->previousChecksum = pResults->checksum; + } + + if (DC_DECOMPRESSION_REQUEST == compDecomp) { + pResults->endOfLastBlock = + (ICP_QAT_FW_COMN_STATUS_CMP_END_OF_LAST_BLK_FLAG_SET == + ICP_QAT_FW_COMN_RESP_CMP_END_OF_LAST_BLK_FLAG_GET( + opStatus)); + } + + /* Save the checksum for the next request */ + if ((CPA_DC_OVERFLOW != (Cpa8S)xlatErr) && + (CPA_TRUE == verifyHwIntegrityCrcs)) { + pSessionDesc->previousChecksum = + pSessionDesc->seedSwCrc.swCrcI; + } + + /* Check if a CNV recovery happened and + * increase stats counter + */ + if ((DC_COMPRESSION_REQUEST == compDecomp) && + ICP_QAT_FW_COMN_HDR_CNV_FLAG_GET(hdrFlags) && + ICP_QAT_FW_COMN_HDR_CNVNR_FLAG_GET(hdrFlags)) { + COMPRESSION_STAT_INC(numCompCnvErrorsRecovered, + pService); + } + + if (CPA_TRUE == pSessionDesc->isDcDp) { + if (pResponse) + pResponse->responseStatus = CPA_STATUS_SUCCESS; + } else { + if (DC_COMPRESSION_REQUEST == compDecomp) { + COMPRESSION_STAT_INC(numCompCompleted, + pService); + } else { + COMPRESSION_STAT_INC(numDecompCompleted, + pService); + } + } + } else { + pResults->consumed = 0; + pResults->produced = 0; + if (CPA_DC_OVERFLOW == pResults->status && + CPA_DC_STATELESS == pSessionDesc->sessState) { + /* This error message will be returned by Data Plane API + * in both + * compression and decompression direction. With + * Traditional API + * this error message will be returned only in stateless + * decompression direction */ + QAT_UTILS_LOG( + "Unrecoverable error: stateless overflow. You may need to increase the size of your destination buffer.\n"); + } + + if (CPA_TRUE == pSessionDesc->isDcDp) { + if (pResponse) + pResponse->responseStatus = CPA_STATUS_FAIL; + } else { + if (CPA_DC_OK != pResults->status && + CPA_DC_INCOMPLETE_FILE_ERR != pResults->status) { + status = CPA_STATUS_FAIL; + } + + if (DC_COMPRESSION_REQUEST == compDecomp) { + COMPRESSION_STAT_INC(numCompCompletedErrors, + pService); + } else { + COMPRESSION_STAT_INC(numDecompCompletedErrors, + pService); + } + } + } + + if (CPA_TRUE == pSessionDesc->isDcDp) { + /* Decrement number of stateless pending callbacks for session + */ + pSessionDesc->pendingDpStatelessCbCount--; + (pService->pDcDpCb)(pResponse); + } else { + /* Decrement number of pending callbacks for session */ + if (CPA_DC_STATELESS == pSessionDesc->sessState) { + qatUtilsAtomicDec( + &(pCookie->pSessionDesc->pendingStatelessCbCount)); + } else if (0 != + qatUtilsAtomicGet(&pCookie->pSessionDesc + ->pendingStatefulCbCount)) { + qatUtilsAtomicDec( + &(pCookie->pSessionDesc->pendingStatefulCbCount)); + } + + /* Free the memory pool */ + if (NULL != pCookie) { + Lac_MemPoolEntryFree(pCookie); + pCookie = NULL; + } + + if (NULL != pCbFunc) { + pCbFunc(callbackTag, status); + } + } +} + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Check that all the parameters in the pOpData structure are valid + * + * @description + * Check that all the parameters in the pOpData structure are valid + * + * @param[in] pService Pointer to the compression service + * @param[in] pOpData Pointer to request information structure + * holding parameters for cpaDcCompress2 and + * CpaDcDecompressData2 + * @retval CPA_STATUS_SUCCESS Function executed successfully + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in + * + *****************************************************************************/ +static CpaStatus +dcCheckOpData(sal_compression_service_t *pService, CpaDcOpData *pOpData) +{ + CpaDcSkipMode skipMode = 0; + + if ((pOpData->flushFlag < CPA_DC_FLUSH_NONE) || + (pOpData->flushFlag > CPA_DC_FLUSH_FULL)) { + LAC_INVALID_PARAM_LOG("Invalid flushFlag value"); + return CPA_STATUS_INVALID_PARAM; + } + + skipMode = pOpData->inputSkipData.skipMode; + if ((skipMode < CPA_DC_SKIP_DISABLED) || + (skipMode > CPA_DC_SKIP_STRIDE)) { + LAC_INVALID_PARAM_LOG("Invalid input skip mode value"); + return CPA_STATUS_INVALID_PARAM; + } + + skipMode = pOpData->outputSkipData.skipMode; + if ((skipMode < CPA_DC_SKIP_DISABLED) || + (skipMode > CPA_DC_SKIP_STRIDE)) { + LAC_INVALID_PARAM_LOG("Invalid output skip mode value"); + return CPA_STATUS_INVALID_PARAM; + } + + if (pOpData->integrityCrcCheck == CPA_FALSE && + pOpData->verifyHwIntegrityCrcs == CPA_TRUE) { + LAC_INVALID_PARAM_LOG( + "integrityCrcCheck must be set to true" + "in order to enable verifyHwIntegrityCrcs"); + return CPA_STATUS_INVALID_PARAM; + } + + if (pOpData->integrityCrcCheck != CPA_TRUE && + pOpData->integrityCrcCheck != CPA_FALSE) { + LAC_INVALID_PARAM_LOG("Invalid integrityCrcCheck value"); + return CPA_STATUS_INVALID_PARAM; + } + + if (pOpData->verifyHwIntegrityCrcs != CPA_TRUE && + pOpData->verifyHwIntegrityCrcs != CPA_FALSE) { + LAC_INVALID_PARAM_LOG("Invalid verifyHwIntegrityCrcs value"); + return CPA_STATUS_INVALID_PARAM; + } + + if (pOpData->compressAndVerify != CPA_TRUE && + pOpData->compressAndVerify != CPA_FALSE) { + LAC_INVALID_PARAM_LOG("Invalid cnv decompress check value"); + return CPA_STATUS_INVALID_PARAM; + } + + if (CPA_TRUE == pOpData->integrityCrcCheck && + CPA_FALSE == pService->generic_service_info.integrityCrcCheck) { + LAC_INVALID_PARAM_LOG("Integrity CRC check is not " + "supported on this device"); + return CPA_STATUS_INVALID_PARAM; + } + return CPA_STATUS_SUCCESS; +} + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Check the compression source buffer for Batch and Pack API. + * + * @description + * Check that all the parameters used for Pack compression + * request are valid. This function essentially checks the source buffer + * parameters and results structure parameters. + * + * @param[in] pSessionHandle Session handle + * @param[in] pSrcBuff Pointer to data buffer for compression + * @param[in] pDestBuff Pointer to buffer space allocated for + * output data + * @param[in] pResults Pointer to results structure + * @param[in] flushFlag Indicates the type of flush to be + * performed + * @param[in] srcBuffSize Size of the source buffer + * + * @retval CPA_STATUS_SUCCESS Function executed successfully + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in + * + *****************************************************************************/ +static CpaStatus +dcCheckSourceData(CpaDcSessionHandle pSessionHandle, + CpaBufferList *pSrcBuff, + CpaBufferList *pDestBuff, + CpaDcRqResults *pResults, + CpaDcFlush flushFlag, + Cpa64U srcBuffSize, + CpaDcSkipData *skipData) +{ + dc_session_desc_t *pSessionDesc = NULL; + + LAC_CHECK_NULL_PARAM(pSessionHandle); + LAC_CHECK_NULL_PARAM(pSrcBuff); + LAC_CHECK_NULL_PARAM(pDestBuff); + LAC_CHECK_NULL_PARAM(pResults); + + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); + if (NULL == pSessionDesc) { + LAC_INVALID_PARAM_LOG("Session handle not as expected"); + return CPA_STATUS_INVALID_PARAM; + } + + if ((flushFlag < CPA_DC_FLUSH_NONE) || + (flushFlag > CPA_DC_FLUSH_FULL)) { + LAC_INVALID_PARAM_LOG("Invalid flushFlag value"); + return CPA_STATUS_INVALID_PARAM; + } + + if (pSrcBuff == pDestBuff) { + LAC_INVALID_PARAM_LOG("In place operation not supported"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Compressing zero bytes is not supported for stateless sessions + * for non Batch and Pack requests */ + if ((CPA_DC_STATELESS == pSessionDesc->sessState) && + (0 == srcBuffSize) && (NULL == skipData)) { + LAC_INVALID_PARAM_LOG( + "The source buffer size needs to be greater than " + "zero bytes for stateless sessions"); + return CPA_STATUS_INVALID_PARAM; + } + + if (srcBuffSize > DC_BUFFER_MAX_SIZE) { + LAC_INVALID_PARAM_LOG( + "The source buffer size needs to be less than or " + "equal to 2^32-1 bytes"); + return CPA_STATUS_INVALID_PARAM; + } + + return CPA_STATUS_SUCCESS; +} + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Check the compression or decompression function parameters. + * + * @description + * Check that all the parameters used for a Batch and Pack compression + * request are valid. This function essentially checks the destination + * buffer parameters and intermediate buffer parameters. + * + * @param[in] pService Pointer to the compression service + * @param[in] pSessionHandle Session handle + * @param[in] pDestBuff Pointer to buffer space allocated for + * output data + * @param[in] compDecomp Direction of the operation + * + * @retval CPA_STATUS_SUCCESS Function executed successfully + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in + * + *****************************************************************************/ +static CpaStatus +dcCheckDestinationData(sal_compression_service_t *pService, + CpaDcSessionHandle pSessionHandle, + CpaBufferList *pDestBuff, + dc_request_dir_t compDecomp) +{ + dc_session_desc_t *pSessionDesc = NULL; + Cpa64U destBuffSize = 0; + + LAC_CHECK_NULL_PARAM(pSessionHandle); + LAC_CHECK_NULL_PARAM(pDestBuff); + + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); + if (NULL == pSessionDesc) { + LAC_INVALID_PARAM_LOG("Session handle not as expected"); + return CPA_STATUS_INVALID_PARAM; + } + + if (LacBuffDesc_BufferListVerify(pDestBuff, + &destBuffSize, + LAC_NO_ALIGNMENT_SHIFT) != + CPA_STATUS_SUCCESS) { + LAC_INVALID_PARAM_LOG( + "Invalid destination buffer list parameter"); + return CPA_STATUS_INVALID_PARAM; + } + + if (destBuffSize > DC_BUFFER_MAX_SIZE) { + LAC_INVALID_PARAM_LOG( + "The destination buffer size needs to be less " + "than or equal to 2^32-1 bytes"); + return CPA_STATUS_INVALID_PARAM; + } + + if (CPA_TRUE == pSessionDesc->isDcDp) { + LAC_INVALID_PARAM_LOG( + "The session type should not be data plane"); + return CPA_STATUS_INVALID_PARAM; + } + + if (DC_COMPRESSION_REQUEST == compDecomp) { + if (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType) { + + /* Check if intermediate buffers are supported */ + if ((0 == pService->pInterBuffPtrsArrayPhyAddr) || + (NULL == pService->pInterBuffPtrsArray)) { + LAC_LOG_ERROR( + "No intermediate buffer defined for this instance " + "- see cpaDcStartInstance"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Ensure that the destination buffer size is greater or + * equal to 128B */ + if (destBuffSize < DC_DEST_BUFFER_DYN_MIN_SIZE) { + LAC_INVALID_PARAM_LOG( + "Destination buffer size should be " + "greater or equal to 128B"); + return CPA_STATUS_INVALID_PARAM; + } + } else + { + /* Ensure that the destination buffer size is greater or + * equal to devices min output buff size */ + if (destBuffSize < + pService->comp_device_data.minOutputBuffSize) { + LAC_INVALID_PARAM_LOG1( + "Destination buffer size should be " + "greater or equal to %d bytes", + pService->comp_device_data + .minOutputBuffSize); + return CPA_STATUS_INVALID_PARAM; + } + } + } else { + /* Ensure that the destination buffer size is greater than + * 0 bytes */ + if (destBuffSize < DC_DEST_BUFFER_DEC_MIN_SIZE) { + LAC_INVALID_PARAM_LOG( + "Destination buffer size should be " + "greater than 0 bytes"); + return CPA_STATUS_INVALID_PARAM; + } + } + return CPA_STATUS_SUCCESS; +} + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Populate the compression request parameters + * + * @description + * This function will populate the compression request parameters + * + * @param[out] pCompReqParams Pointer to the compression request parameters + * @param[in] pCookie Pointer to the compression cookie + * + *****************************************************************************/ +static void +dcCompRequestParamsPopulate(icp_qat_fw_comp_req_params_t *pCompReqParams, + dc_compression_cookie_t *pCookie) +{ + pCompReqParams->comp_len = pCookie->srcTotalDataLenInBytes; + pCompReqParams->out_buffer_sz = pCookie->dstTotalDataLenInBytes; +} + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Create the requests for compression or decompression + * + * @description + * Create the requests for compression or decompression. This function + * will update the cookie will all required information. + * + * @param{out] pCookie Pointer to the compression cookie + * @param[in] pService Pointer to the compression service + * @param[in] pSessionDesc Pointer to the session descriptor + * @param[in pSessionHandle Session handle + * @param[in] pSrcBuff Pointer to data buffer for compression + * @param[in] pDestBuff Pointer to buffer space for data after + * compression + * @param[in] pResults Pointer to results structure + * @param[in] flushFlag Indicates the type of flush to be + * performed + * @param[in] pOpData Pointer to request information structure + * holding parameters for cpaDcCompress2 + * and CpaDcDecompressData2 + * @param[in] callbackTag Pointer to the callback tag + * @param[in] compDecomp Direction of the operation + * @param[in] compressAndVerify Compress and Verify + * + * @retval CPA_STATUS_SUCCESS Function executed successfully + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in + * + *****************************************************************************/ +static CpaStatus +dcCreateRequest(dc_compression_cookie_t *pCookie, + sal_compression_service_t *pService, + dc_session_desc_t *pSessionDesc, + CpaDcSessionHandle pSessionHandle, + CpaBufferList *pSrcBuff, + CpaBufferList *pDestBuff, + CpaDcRqResults *pResults, + CpaDcFlush flushFlag, + CpaDcOpData *pOpData, + void *callbackTag, + dc_request_dir_t compDecomp, + dc_cnv_mode_t cnvMode) +{ + icp_qat_fw_comp_req_t *pMsg = NULL; + icp_qat_fw_comp_req_params_t *pCompReqParams = NULL; + Cpa64U srcAddrPhys = 0, dstAddrPhys = 0; + Cpa64U srcTotalDataLenInBytes = 0, dstTotalDataLenInBytes = 0; + + Cpa32U rpCmdFlags = 0; + Cpa8U sop = ICP_QAT_FW_COMP_SOP; + Cpa8U eop = ICP_QAT_FW_COMP_EOP; + Cpa8U bFinal = ICP_QAT_FW_COMP_NOT_BFINAL; + Cpa8U crcMode = ICP_QAT_FW_COMP_CRC_MODE_LEGACY; + Cpa8U cnvDecompReq = ICP_QAT_FW_COMP_NO_CNV; + Cpa8U cnvRecovery = ICP_QAT_FW_COMP_NO_CNV_RECOVERY; + CpaBoolean integrityCrcCheck = CPA_FALSE; + CpaStatus status = CPA_STATUS_SUCCESS; + CpaDcFlush flush = CPA_DC_FLUSH_NONE; + Cpa32U initial_adler = 1; + Cpa32U initial_crc32 = 0; + icp_qat_fw_comp_req_t *pReqCache = NULL; + + /* Write the buffer descriptors */ + status = LacBuffDesc_BufferListDescWriteAndGetSize( + pSrcBuff, + &srcAddrPhys, + CPA_FALSE, + &srcTotalDataLenInBytes, + &(pService->generic_service_info)); + if (status != CPA_STATUS_SUCCESS) { + return status; + } + + status = LacBuffDesc_BufferListDescWriteAndGetSize( + pDestBuff, + &dstAddrPhys, + CPA_FALSE, + &dstTotalDataLenInBytes, + &(pService->generic_service_info)); + if (status != CPA_STATUS_SUCCESS) { + return status; + } + + /* Populate the compression cookie */ + pCookie->dcInstance = pService; + pCookie->pSessionHandle = pSessionHandle; + pCookie->callbackTag = callbackTag; + pCookie->pSessionDesc = pSessionDesc; + pCookie->pDcOpData = pOpData; + pCookie->pResults = pResults; + pCookie->compDecomp = compDecomp; + pCookie->pUserSrcBuff = NULL; + pCookie->pUserDestBuff = NULL; + + /* Extract flush flag from either the opData or from the + * parameter. Opdata have been introduce with APIs + * cpaDcCompressData2 and cpaDcDecompressData2 */ + if (NULL != pOpData) { + flush = pOpData->flushFlag; + integrityCrcCheck = pOpData->integrityCrcCheck; + } else { + flush = flushFlag; + } + pCookie->flushFlag = flush; + + /* The firmware expects the length in bytes for source and destination + * to be Cpa32U parameters. However the total data length could be + * bigger as allocated by the user. We ensure that this is not the case + * in dcCheckSourceData and cast the values to Cpa32U here */ + pCookie->srcTotalDataLenInBytes = (Cpa32U)srcTotalDataLenInBytes; + if ((DC_COMPRESSION_REQUEST == compDecomp) && + (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType)) { + if (pService->minInterBuffSizeInBytes < + (Cpa32U)dstTotalDataLenInBytes) { + pCookie->dstTotalDataLenInBytes = + (Cpa32U)(pService->minInterBuffSizeInBytes); + } else { + pCookie->dstTotalDataLenInBytes = + (Cpa32U)dstTotalDataLenInBytes; + } + } else + { + pCookie->dstTotalDataLenInBytes = + (Cpa32U)dstTotalDataLenInBytes; + } + + /* Device can not decompress an odd byte decompression request + * if bFinal is not set + */ + if (CPA_TRUE != pService->comp_device_data.oddByteDecompNobFinal) { + if ((CPA_DC_STATEFUL == pSessionDesc->sessState) && + (CPA_DC_FLUSH_FINAL != flushFlag) && + (DC_DECOMPRESSION_REQUEST == compDecomp) && + (pCookie->srcTotalDataLenInBytes & 0x1)) { + pCookie->srcTotalDataLenInBytes--; + } + } + /* Device can not decompress odd byte interim requests */ + if (CPA_TRUE != pService->comp_device_data.oddByteDecompInterim) { + if ((CPA_DC_STATEFUL == pSessionDesc->sessState) && + (CPA_DC_FLUSH_FINAL != flushFlag) && + (CPA_DC_FLUSH_FULL != flushFlag) && + (DC_DECOMPRESSION_REQUEST == compDecomp) && + (pCookie->srcTotalDataLenInBytes & 0x1)) { + pCookie->srcTotalDataLenInBytes--; + } + } + + pMsg = (icp_qat_fw_comp_req_t *)&pCookie->request; + + if (DC_COMPRESSION_REQUEST == compDecomp) { + pReqCache = &(pSessionDesc->reqCacheComp); + } else { + pReqCache = &(pSessionDesc->reqCacheDecomp); + } + + /* Fills the msg from the template cached in the session descriptor */ + memcpy((void *)pMsg, + (void *)(pReqCache), + LAC_QAT_DC_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES); + + if (DC_REQUEST_FIRST == pSessionDesc->requestType) { + initial_adler = 1; + initial_crc32 = 0; + + if (CPA_DC_ADLER32 == pSessionDesc->checksumType) { + pSessionDesc->previousChecksum = 1; + } else { + pSessionDesc->previousChecksum = 0; + } + } else if (CPA_DC_STATELESS == pSessionDesc->sessState) { + pSessionDesc->previousChecksum = pResults->checksum; + + if (CPA_DC_ADLER32 == pSessionDesc->checksumType) { + initial_adler = pSessionDesc->previousChecksum; + } else { + initial_crc32 = pSessionDesc->previousChecksum; + } + } + + /* Backup source and destination buffer addresses, + * CRC calculations both for CNV and translator overflow + * will be performed on them in the callback function. + */ + pCookie->pUserSrcBuff = pSrcBuff; + pCookie->pUserDestBuff = pDestBuff; + + /* + * Due to implementation of CNV support and need for backwards + * compatibility certain fields in the request and response structs had + * been changed, moved or placed in unions cnvMode flag signifies fields + * to be selected from req/res + * + * Doing extended crc checks makes sense only when we want to do the + * actual CNV + */ + if (CPA_TRUE == pService->generic_service_info.integrityCrcCheck && + CPA_TRUE == integrityCrcCheck) { + pMsg->comp_pars.crc.crc_data_addr = + pSessionDesc->physDataIntegrityCrcs; + crcMode = ICP_QAT_FW_COMP_CRC_MODE_E2E; + } else { + /* Legacy request structure */ + pMsg->comp_pars.crc.legacy.initial_adler = initial_adler; + pMsg->comp_pars.crc.legacy.initial_crc32 = initial_crc32; + crcMode = ICP_QAT_FW_COMP_CRC_MODE_LEGACY; + } + + /* Populate the cmdFlags */ + if (CPA_DC_STATEFUL == pSessionDesc->sessState) { + pSessionDesc->previousRequestType = pSessionDesc->requestType; + + if (DC_REQUEST_FIRST == pSessionDesc->requestType) { + /* Update the request type for following requests */ + pSessionDesc->requestType = DC_REQUEST_SUBSEQUENT; + + /* Reinitialise the cumulative amount of consumed bytes + */ + pSessionDesc->cumulativeConsumedBytes = 0; + + if (DC_COMPRESSION_REQUEST == compDecomp) { + pSessionDesc->isSopForCompressionProcessed = + CPA_TRUE; + } else if (DC_DECOMPRESSION_REQUEST == compDecomp) { + pSessionDesc->isSopForDecompressionProcessed = + CPA_TRUE; + } + } else { + if (DC_COMPRESSION_REQUEST == compDecomp) { + if (CPA_TRUE == + pSessionDesc + ->isSopForCompressionProcessed) { + sop = ICP_QAT_FW_COMP_NOT_SOP; + } else { + pSessionDesc + ->isSopForCompressionProcessed = + CPA_TRUE; + } + } else if (DC_DECOMPRESSION_REQUEST == compDecomp) { + if (CPA_TRUE == + pSessionDesc + ->isSopForDecompressionProcessed) { + sop = ICP_QAT_FW_COMP_NOT_SOP; + } else { + pSessionDesc + ->isSopForDecompressionProcessed = + CPA_TRUE; + } + } + } + + if ((CPA_DC_FLUSH_FINAL == flush) || + (CPA_DC_FLUSH_FULL == flush)) { + /* Update the request type for following requests */ + pSessionDesc->requestType = DC_REQUEST_FIRST; + } else { + eop = ICP_QAT_FW_COMP_NOT_EOP; + } + } else { + + if (DC_REQUEST_FIRST == pSessionDesc->requestType) { + /* Reinitialise the cumulative amount of consumed bytes + */ + pSessionDesc->cumulativeConsumedBytes = 0; + } + } + + /* (LW 14 - 15) */ + pCompReqParams = &(pMsg->comp_pars); + dcCompRequestParamsPopulate(pCompReqParams, pCookie); + if (CPA_DC_FLUSH_FINAL == flush) { + bFinal = ICP_QAT_FW_COMP_BFINAL; + } + + switch (cnvMode) { + case DC_CNVNR: + cnvRecovery = ICP_QAT_FW_COMP_CNV_RECOVERY; + /* Fall through is intended here, because for CNVNR + * cnvDecompReq also needs to be set */ + case DC_CNV: + cnvDecompReq = ICP_QAT_FW_COMP_CNV; + break; + case DC_NO_CNV: + cnvDecompReq = ICP_QAT_FW_COMP_NO_CNV; + cnvRecovery = ICP_QAT_FW_COMP_NO_CNV_RECOVERY; + break; + } + + /* LW 18 */ + rpCmdFlags = ICP_QAT_FW_COMP_REQ_PARAM_FLAGS_BUILD( + sop, eop, bFinal, cnvDecompReq, cnvRecovery, crcMode); + pMsg->comp_pars.req_par_flags = rpCmdFlags; + + /* Populates the QAT common request middle part of the message + * (LW 6 to 11) */ + SalQatMsg_CmnMidWrite((icp_qat_fw_la_bulk_req_t *)pMsg, + pCookie, + DC_DEFAULT_QAT_PTR_TYPE, + srcAddrPhys, + dstAddrPhys, + 0, + 0); + + return CPA_STATUS_SUCCESS; +} + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Send a compression request to QAT + * + * @description + * Send the requests for compression or decompression to QAT + * + * @param{in] pCookie Pointer to the compression cookie + * @param[in] pService Pointer to the compression service + * @param[in] pSessionDesc Pointer to the session descriptor + * @param[in] compDecomp Direction of the operation + * + * @retval CPA_STATUS_SUCCESS Function executed successfully + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in + * + *****************************************************************************/ +static CpaStatus +dcSendRequest(dc_compression_cookie_t *pCookie, + sal_compression_service_t *pService, + dc_session_desc_t *pSessionDesc, + dc_request_dir_t compDecomp) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + /* Send to QAT */ + status = icp_adf_transPutMsg(pService->trans_handle_compression_tx, + (void *)&(pCookie->request), + LAC_QAT_DC_REQ_SZ_LW); + + if ((CPA_DC_STATEFUL == pSessionDesc->sessState) && + (CPA_STATUS_RETRY == status)) { + /* reset requestType after receiving an retry on + * the stateful request */ + pSessionDesc->requestType = pSessionDesc->previousRequestType; + } + + return status; +} + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Process the synchronous and asynchronous case for compression or + * decompression + * + * @description + * Process the synchronous and asynchronous case for compression or + * decompression. This function will then create and send the request to + * the firmware. + * + * @param[in] pService Pointer to the compression service + * @param[in] pSessionDesc Pointer to the session descriptor + * @param[in] dcInstance Instance handle derived from discovery + * functions + * @param[in] pSessionHandle Session handle + * @param[in] numRequests Number of operations in the batch request + * @param[in] pBatchOpData Address of the list of jobs to be processed + * @param[in] pSrcBuff Pointer to data buffer for compression + * @param[in] pDestBuff Pointer to buffer space for data after + * compression + * @param[in] pResults Pointer to results structure + * @param[in] flushFlag Indicates the type of flush to be + * performed + * @param[in] pOpData Pointer to request information structure + * holding parameters for cpaDcCompress2 and + * CpaDcDecompressData2 + * @param[in] callbackTag Pointer to the callback tag + * @param[in] compDecomp Direction of the operation + * @param[in] isAsyncMode Used to know if synchronous or asynchronous + * mode + * @param[in] cnvMode CNV Mode + * + * @retval CPA_STATUS_SUCCESS Function executed successfully + * @retval CPA_STATUS_RETRY Retry operation + * @retval CPA_STATUS_FAIL Function failed + * @retval CPA_STATUS_RESOURCE Resource error + * + *****************************************************************************/ +static CpaStatus +dcCompDecompData(sal_compression_service_t *pService, + dc_session_desc_t *pSessionDesc, + CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle, + CpaBufferList *pSrcBuff, + CpaBufferList *pDestBuff, + CpaDcRqResults *pResults, + CpaDcFlush flushFlag, + CpaDcOpData *pOpData, + void *callbackTag, + dc_request_dir_t compDecomp, + CpaBoolean isAsyncMode, + dc_cnv_mode_t cnvMode) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + dc_compression_cookie_t *pCookie = NULL; + + if ((LacSync_GenWakeupSyncCaller == pSessionDesc->pCompressionCb) && + isAsyncMode == CPA_TRUE) { + lac_sync_op_data_t *pSyncCallbackData = NULL; + + status = LacSync_CreateSyncCookie(&pSyncCallbackData); + + if (CPA_STATUS_SUCCESS == status) { + status = dcCompDecompData(pService, + pSessionDesc, + dcInstance, + pSessionHandle, + pSrcBuff, + pDestBuff, + pResults, + flushFlag, + pOpData, + pSyncCallbackData, + compDecomp, + CPA_FALSE, + cnvMode); + } else { + return status; + } + + if (CPA_STATUS_SUCCESS == status) { + CpaStatus syncStatus = CPA_STATUS_SUCCESS; + + syncStatus = + LacSync_WaitForCallback(pSyncCallbackData, + DC_SYNC_CALLBACK_TIMEOUT, + &status, + NULL); + + /* If callback doesn't come back */ + if (CPA_STATUS_SUCCESS != syncStatus) { + if (DC_COMPRESSION_REQUEST == compDecomp) { + COMPRESSION_STAT_INC( + numCompCompletedErrors, pService); + } else { + COMPRESSION_STAT_INC( + numDecompCompletedErrors, pService); + } + LAC_LOG_ERROR("Callback timed out"); + status = syncStatus; + } + } else { + /* As the Request was not sent the Callback will never + * be called, so need to indicate that we're finished + * with cookie so it can be destroyed. */ + LacSync_SetSyncCookieComplete(pSyncCallbackData); + } + + LacSync_DestroySyncCookie(&pSyncCallbackData); + return status; + } + + /* Allocate the compression cookie + * The memory is freed in callback or in sendRequest if an error occurs + */ + pCookie = (dc_compression_cookie_t *)Lac_MemPoolEntryAlloc( + pService->compression_mem_pool); + if (NULL == pCookie) { + LAC_LOG_ERROR("Cannot get mem pool entry for compression"); + status = CPA_STATUS_RESOURCE; + } else if ((void *)CPA_STATUS_RETRY == pCookie) { + pCookie = NULL; + status = CPA_STATUS_RETRY; + } + + if (CPA_STATUS_SUCCESS == status) { + status = dcCreateRequest(pCookie, + pService, + pSessionDesc, + pSessionHandle, + pSrcBuff, + pDestBuff, + pResults, + flushFlag, + pOpData, + callbackTag, + compDecomp, + cnvMode); + } + + if (CPA_STATUS_SUCCESS == status) { + /* Increment number of pending callbacks for session */ + if (CPA_DC_STATELESS == pSessionDesc->sessState) { + qatUtilsAtomicInc( + &(pSessionDesc->pendingStatelessCbCount)); + } + status = + dcSendRequest(pCookie, pService, pSessionDesc, compDecomp); + } + + if (CPA_STATUS_SUCCESS == status) { + if (DC_COMPRESSION_REQUEST == compDecomp) { + COMPRESSION_STAT_INC(numCompRequests, pService); + } else { + COMPRESSION_STAT_INC(numDecompRequests, pService); + } + } else { + if (DC_COMPRESSION_REQUEST == compDecomp) { + COMPRESSION_STAT_INC(numCompRequestsErrors, pService); + } else { + COMPRESSION_STAT_INC(numDecompRequestsErrors, pService); + } + + /* Decrement number of pending callbacks for session */ + if (CPA_DC_STATELESS == pSessionDesc->sessState) { + qatUtilsAtomicDec( + &(pSessionDesc->pendingStatelessCbCount)); + } else { + qatUtilsAtomicDec( + &(pSessionDesc->pendingStatefulCbCount)); + } + + /* Free the memory pool */ + if (NULL != pCookie) { + if (status != CPA_STATUS_UNSUPPORTED) { + /* Free the memory pool */ + Lac_MemPoolEntryFree(pCookie); + pCookie = NULL; + } + } + } + + return status; +} + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Handle zero length compression or decompression requests + * + * @description + * Handle zero length compression or decompression requests + * + * @param[in] pService Pointer to the compression service + * @param[in] pSessionDesc Pointer to the session descriptor + * @param[in] pResults Pointer to results structure + * @param[in] flushFlag Indicates the type of flush to be + * performed + * @param[in] callbackTag User supplied value to help correlate + * the callback with its associated request + * @param[in] compDecomp Direction of the operation + * + * @retval CPA_TRUE Zero length SOP or MOP processed + * @retval CPA_FALSE Zero length EOP + * + *****************************************************************************/ +static CpaStatus +dcZeroLengthRequests(sal_compression_service_t *pService, + dc_session_desc_t *pSessionDesc, + CpaDcRqResults *pResults, + CpaDcFlush flushFlag, + void *callbackTag, + dc_request_dir_t compDecomp) +{ + CpaBoolean status = CPA_FALSE; + CpaDcCallbackFn pCbFunc = pSessionDesc->pCompressionCb; + + if (DC_REQUEST_FIRST == pSessionDesc->requestType) { + /* Reinitialise the cumulative amount of consumed bytes */ + pSessionDesc->cumulativeConsumedBytes = 0; + + /* Zero length SOP */ + if (CPA_DC_ADLER32 == pSessionDesc->checksumType) { + pResults->checksum = 1; + } else { + pResults->checksum = 0; + } + + status = CPA_TRUE; + } else if ((CPA_DC_FLUSH_NONE == flushFlag) || + (CPA_DC_FLUSH_SYNC == flushFlag)) { + /* Zero length MOP */ + pResults->checksum = pSessionDesc->previousChecksum; + status = CPA_TRUE; + } + + if (CPA_TRUE == status) { + pResults->status = CPA_DC_OK; + pResults->produced = 0; + pResults->consumed = 0; + + /* Increment statistics */ + if (DC_COMPRESSION_REQUEST == compDecomp) { + COMPRESSION_STAT_INC(numCompRequests, pService); + COMPRESSION_STAT_INC(numCompCompleted, pService); + } else { + COMPRESSION_STAT_INC(numDecompRequests, pService); + COMPRESSION_STAT_INC(numDecompCompleted, pService); + } + + if (CPA_STATUS_SUCCESS != + LAC_SPINUNLOCK(&(pSessionDesc->sessionLock))) { + LAC_LOG_ERROR("Cannot unlock session lock"); + } + + if ((NULL != pCbFunc) && + (LacSync_GenWakeupSyncCaller != pCbFunc)) { + pCbFunc(callbackTag, CPA_STATUS_SUCCESS); + } + + return CPA_TRUE; + } + + return CPA_FALSE; +} + +static CpaStatus +dcParamCheck(CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle, + sal_compression_service_t *pService, + CpaBufferList *pSrcBuff, + CpaBufferList *pDestBuff, + CpaDcRqResults *pResults, + dc_session_desc_t *pSessionDesc, + CpaDcFlush flushFlag, + Cpa64U srcBuffSize) +{ + + if (dcCheckSourceData(pSessionHandle, + pSrcBuff, + pDestBuff, + pResults, + flushFlag, + srcBuffSize, + NULL) != CPA_STATUS_SUCCESS) { + return CPA_STATUS_INVALID_PARAM; + } + if (dcCheckDestinationData( + pService, pSessionHandle, pDestBuff, DC_COMPRESSION_REQUEST) != + CPA_STATUS_SUCCESS) { + return CPA_STATUS_INVALID_PARAM; + } + if (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection) { + LAC_INVALID_PARAM_LOG("Invalid sessDirection value"); + return CPA_STATUS_INVALID_PARAM; + } + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcCompressData(CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle, + CpaBufferList *pSrcBuff, + CpaBufferList *pDestBuff, + CpaDcRqResults *pResults, + CpaDcFlush flushFlag, + void *callbackTag) +{ + sal_compression_service_t *pService = NULL; + dc_session_desc_t *pSessionDesc = NULL; + CpaInstanceHandle insHandle = NULL; + Cpa64U srcBuffSize = 0; + + + if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = dcInstance; + } + + pService = (sal_compression_service_t *)insHandle; + + LAC_CHECK_NULL_PARAM(insHandle); + LAC_CHECK_NULL_PARAM(pSessionHandle); + + /* Check if SAL is initialised otherwise return an error */ + SAL_RUNNING_CHECK(insHandle); + + /* This check is outside the parameter checking as it is needed to + * manage zero length requests */ + if (LacBuffDesc_BufferListVerifyNull(pSrcBuff, + &srcBuffSize, + LAC_NO_ALIGNMENT_SHIFT) != + CPA_STATUS_SUCCESS) { + LAC_INVALID_PARAM_LOG("Invalid source buffer list parameter"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Ensure this is a compression instance */ + SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); + + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); + if (CPA_STATUS_SUCCESS != + dcParamCheck(insHandle, + pSessionHandle, + pService, + pSrcBuff, + pDestBuff, + pResults, + pSessionDesc, + flushFlag, + srcBuffSize)) { + return CPA_STATUS_INVALID_PARAM; + } + if (CPA_DC_STATEFUL == pSessionDesc->sessState) { + LAC_INVALID_PARAM_LOG( + "Invalid session state, stateful sessions " + "are not supported"); + return CPA_STATUS_UNSUPPORTED; + } + + if (!(pService->generic_service_info.dcExtendedFeatures & + DC_CNV_EXTENDED_CAPABILITY)) { + LAC_INVALID_PARAM_LOG( + "CompressAndVerify feature not supported"); + return CPA_STATUS_UNSUPPORTED; + } + + if (!(pService->generic_service_info.dcExtendedFeatures & + DC_CNVNR_EXTENDED_CAPABILITY)) { + LAC_INVALID_PARAM_LOG( + "CompressAndVerifyAndRecovery feature not supported"); + return CPA_STATUS_UNSUPPORTED; + } + + return dcCompDecompData(pService, + pSessionDesc, + dcInstance, + pSessionHandle, + pSrcBuff, + pDestBuff, + pResults, + flushFlag, + NULL, + callbackTag, + DC_COMPRESSION_REQUEST, + CPA_TRUE, + DC_CNVNR); +} + +CpaStatus +cpaDcCompressData2(CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle, + CpaBufferList *pSrcBuff, + CpaBufferList *pDestBuff, + CpaDcOpData *pOpData, + CpaDcRqResults *pResults, + void *callbackTag) +{ + sal_compression_service_t *pService = NULL; + dc_session_desc_t *pSessionDesc = NULL; + CpaInstanceHandle insHandle = NULL; + Cpa64U srcBuffSize = 0; + dc_cnv_mode_t cnvMode = DC_NO_CNV; + + LAC_CHECK_NULL_PARAM(pOpData); + + if (((CPA_TRUE != pOpData->compressAndVerify) && + (CPA_FALSE != pOpData->compressAndVerify)) || + ((CPA_FALSE != pOpData->compressAndVerifyAndRecover) && + (CPA_TRUE != pOpData->compressAndVerifyAndRecover))) { + return CPA_STATUS_INVALID_PARAM; + } + + if ((CPA_FALSE == pOpData->compressAndVerify) && + (CPA_TRUE == pOpData->compressAndVerifyAndRecover)) { + return CPA_STATUS_INVALID_PARAM; + } + + + if ((CPA_TRUE == pOpData->compressAndVerify) && + (CPA_TRUE == pOpData->compressAndVerifyAndRecover) && + (CPA_FALSE == pOpData->integrityCrcCheck)) { + return cpaDcCompressData(dcInstance, + pSessionHandle, + pSrcBuff, + pDestBuff, + pResults, + pOpData->flushFlag, + callbackTag); + } + + if (CPA_FALSE == pOpData->compressAndVerify) { + LAC_INVALID_PARAM_LOG( + "Data compression without verification not allowed"); + return CPA_STATUS_UNSUPPORTED; + } + + + if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = dcInstance; + } + + pService = (sal_compression_service_t *)insHandle; + + LAC_CHECK_NULL_PARAM(insHandle); + LAC_CHECK_NULL_PARAM(pSessionHandle); + LAC_CHECK_NULL_PARAM(pOpData); + + /* Check if SAL is initialised otherwise return an error */ + SAL_RUNNING_CHECK(insHandle); + + /* This check is outside the parameter checking as it is needed to + * manage zero length requests */ + if (LacBuffDesc_BufferListVerifyNull(pSrcBuff, + &srcBuffSize, + LAC_NO_ALIGNMENT_SHIFT) != + CPA_STATUS_SUCCESS) { + LAC_INVALID_PARAM_LOG("Invalid source buffer list parameter"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Ensure this is a compression instance */ + SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); + + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); + + if (CPA_TRUE == pOpData->compressAndVerify && + CPA_DC_STATEFUL == pSessionDesc->sessState) { + LAC_INVALID_PARAM_LOG( + "Invalid session state, stateful sessions " + "not supported with CNV"); + return CPA_STATUS_UNSUPPORTED; + } + + if (!(pService->generic_service_info.dcExtendedFeatures & + DC_CNV_EXTENDED_CAPABILITY) && + (CPA_TRUE == pOpData->compressAndVerify)) { + LAC_INVALID_PARAM_LOG( + "CompressAndVerify feature not supported"); + return CPA_STATUS_UNSUPPORTED; + } + + if (CPA_STATUS_SUCCESS != + dcParamCheck(insHandle, + pSessionHandle, + pService, + pSrcBuff, + pDestBuff, + pResults, + pSessionDesc, + pOpData->flushFlag, + srcBuffSize)) { + return CPA_STATUS_INVALID_PARAM; + } + if (CPA_STATUS_SUCCESS != dcCheckOpData(pService, pOpData)) { + return CPA_STATUS_INVALID_PARAM; + } + if (CPA_TRUE != pOpData->compressAndVerify) { + if (srcBuffSize > DC_COMP_MAX_BUFF_SIZE) { + LAC_LOG_ERROR( + "Compression payload greater than 64KB is " + "unsupported, when CnV is disabled\n"); + return CPA_STATUS_UNSUPPORTED; + } + } + + if (CPA_DC_STATEFUL == pSessionDesc->sessState) { + /* Lock the session to check if there are in-flight stateful + * requests */ + if (CPA_STATUS_SUCCESS != + LAC_SPINLOCK(&(pSessionDesc->sessionLock))) { + LAC_LOG_ERROR("Cannot unlock session lock"); + } + + /* Check if there is already one in-flight stateful request */ + if (0 != + qatUtilsAtomicGet( + &(pSessionDesc->pendingStatefulCbCount))) { + LAC_LOG_ERROR( + "Only one in-flight stateful request supported"); + if (CPA_STATUS_SUCCESS != + LAC_SPINUNLOCK(&(pSessionDesc->sessionLock))) { + LAC_LOG_ERROR("Cannot unlock session lock"); + } + return CPA_STATUS_RETRY; + } + + if (0 == srcBuffSize) { + if (CPA_TRUE == + dcZeroLengthRequests(pService, + pSessionDesc, + pResults, + pOpData->flushFlag, + callbackTag, + DC_COMPRESSION_REQUEST)) { + return CPA_STATUS_SUCCESS; + } + } + + qatUtilsAtomicInc(&(pSessionDesc->pendingStatefulCbCount)); + if (CPA_STATUS_SUCCESS != + LAC_SPINUNLOCK(&(pSessionDesc->sessionLock))) { + LAC_LOG_ERROR("Cannot unlock session lock"); + } + } + + if (CPA_TRUE == pOpData->compressAndVerify) { + cnvMode = DC_CNV; + } + + return dcCompDecompData(pService, + pSessionDesc, + dcInstance, + pSessionHandle, + pSrcBuff, + pDestBuff, + pResults, + pOpData->flushFlag, + pOpData, + callbackTag, + DC_COMPRESSION_REQUEST, + CPA_TRUE, + cnvMode); +} + +static CpaStatus +dcDecompressDataCheck(CpaInstanceHandle insHandle, + CpaDcSessionHandle pSessionHandle, + CpaBufferList *pSrcBuff, + CpaBufferList *pDestBuff, + CpaDcRqResults *pResults, + CpaDcFlush flushFlag, + Cpa64U *srcBufferSize) +{ + sal_compression_service_t *pService = NULL; + dc_session_desc_t *pSessionDesc = NULL; + Cpa64U srcBuffSize = 0; + + pService = (sal_compression_service_t *)insHandle; + + LAC_CHECK_NULL_PARAM(insHandle); + + /* Check if SAL is initialised otherwise return an error */ + SAL_RUNNING_CHECK(insHandle); + + /* This check is outside the parameter checking as it is needed to + * manage zero length requests */ + if (LacBuffDesc_BufferListVerifyNull(pSrcBuff, + &srcBuffSize, + LAC_NO_ALIGNMENT_SHIFT) != + CPA_STATUS_SUCCESS) { + LAC_INVALID_PARAM_LOG("Invalid source buffer list parameter"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Ensure this is a compression instance */ + SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); + + if (dcCheckSourceData(pSessionHandle, + pSrcBuff, + pDestBuff, + pResults, + flushFlag, + srcBuffSize, + NULL) != CPA_STATUS_SUCCESS) { + return CPA_STATUS_INVALID_PARAM; + } + if (dcCheckDestinationData(pService, + pSessionHandle, + pDestBuff, + DC_DECOMPRESSION_REQUEST) != + CPA_STATUS_SUCCESS) { + return CPA_STATUS_INVALID_PARAM; + } + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); + + if (CPA_DC_DIR_COMPRESS == pSessionDesc->sessDirection) { + LAC_INVALID_PARAM_LOG("Invalid sessDirection value"); + return CPA_STATUS_INVALID_PARAM; + } + + + *srcBufferSize = srcBuffSize; + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcDecompressData(CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle, + CpaBufferList *pSrcBuff, + CpaBufferList *pDestBuff, + CpaDcRqResults *pResults, + CpaDcFlush flushFlag, + void *callbackTag) +{ + sal_compression_service_t *pService = NULL; + dc_session_desc_t *pSessionDesc = NULL; + CpaInstanceHandle insHandle = NULL; + Cpa64U srcBuffSize = 0; + CpaStatus status = CPA_STATUS_SUCCESS; + + + if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = dcInstance; + } + + status = dcDecompressDataCheck(insHandle, + pSessionHandle, + pSrcBuff, + pDestBuff, + pResults, + flushFlag, + &srcBuffSize); + if (CPA_STATUS_SUCCESS != status) { + return status; + } + + pService = (sal_compression_service_t *)insHandle; + + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); + + if (CPA_DC_STATEFUL == pSessionDesc->sessState) { + /* Lock the session to check if there are in-flight stateful + * requests */ + if (CPA_STATUS_SUCCESS != + LAC_SPINLOCK(&(pSessionDesc->sessionLock))) { + LAC_LOG_ERROR("Cannot lock session lock"); + return CPA_STATUS_RESOURCE; + } + + /* Check if there is already one in-flight stateful request */ + if (0 != + qatUtilsAtomicGet( + &(pSessionDesc->pendingStatefulCbCount))) { + LAC_LOG_ERROR( + "Only one in-flight stateful request supported"); + if (CPA_STATUS_SUCCESS != + LAC_SPINUNLOCK(&(pSessionDesc->sessionLock))) { + LAC_LOG_ERROR("Cannot unlock session lock"); + } + return CPA_STATUS_RETRY; + } + + if ((0 == srcBuffSize) || + ((1 == srcBuffSize) && (CPA_DC_FLUSH_FINAL != flushFlag) && + (CPA_DC_FLUSH_FULL != flushFlag))) { + if (CPA_TRUE == + dcZeroLengthRequests(pService, + pSessionDesc, + pResults, + flushFlag, + callbackTag, + DC_DECOMPRESSION_REQUEST)) { + return CPA_STATUS_SUCCESS; + } + } + + qatUtilsAtomicInc(&(pSessionDesc->pendingStatefulCbCount)); + if (CPA_STATUS_SUCCESS != + LAC_SPINUNLOCK(&(pSessionDesc->sessionLock))) { + LAC_LOG_ERROR("Cannot unlock session lock"); + } + } + + return dcCompDecompData(pService, + pSessionDesc, + dcInstance, + pSessionHandle, + pSrcBuff, + pDestBuff, + pResults, + flushFlag, + NULL, + callbackTag, + DC_DECOMPRESSION_REQUEST, + CPA_TRUE, + DC_NO_CNV); +} + +CpaStatus +cpaDcDecompressData2(CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle, + CpaBufferList *pSrcBuff, + CpaBufferList *pDestBuff, + CpaDcOpData *pOpData, + CpaDcRqResults *pResults, + void *callbackTag) +{ + sal_compression_service_t *pService = NULL; + dc_session_desc_t *pSessionDesc = NULL; + CpaInstanceHandle insHandle = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + Cpa64U srcBuffSize = 0; + LAC_CHECK_NULL_PARAM(pOpData); + + if (CPA_FALSE == pOpData->integrityCrcCheck) { + + return cpaDcDecompressData(dcInstance, + pSessionHandle, + pSrcBuff, + pDestBuff, + pResults, + pOpData->flushFlag, + callbackTag); + } + + + if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = dcInstance; + } + + status = dcDecompressDataCheck(insHandle, + pSessionHandle, + pSrcBuff, + pDestBuff, + pResults, + pOpData->flushFlag, + &srcBuffSize); + if (CPA_STATUS_SUCCESS != status) { + return status; + } + + pService = (sal_compression_service_t *)insHandle; + + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); + + if (CPA_DC_STATEFUL == pSessionDesc->sessState) { + LAC_INVALID_PARAM_LOG("Invalid session: Stateful session is " + "not supported"); + return CPA_STATUS_INVALID_PARAM; + } + + return dcCompDecompData(pService, + pSessionDesc, + insHandle, + pSessionHandle, + pSrcBuff, + pDestBuff, + pResults, + pOpData->flushFlag, + pOpData, + callbackTag, + DC_DECOMPRESSION_REQUEST, + CPA_TRUE, + DC_NO_CNV); +} diff --git a/sys/dev/qat/qat_api/common/compression/dc_dp.c b/sys/dev/qat/qat_api/common/compression/dc_dp.c new file mode 100644 index 000000000000..4a24bf17dc32 --- /dev/null +++ b/sys/dev/qat/qat_api/common/compression/dc_dp.c @@ -0,0 +1,545 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file dc_dp.c + * + * @defgroup cpaDcDp Data Compression Data Plane API + * + * @ingroup cpaDcDp + * + * @description + * Implementation of the Data Compression DP operations. + * + *****************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ +#include "cpa.h" +#include "cpa_dc.h" +#include "cpa_dc_dp.h" + +#include "icp_qat_fw_comp.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ +#include "dc_session.h" +#include "dc_datapath.h" +#include "lac_common.h" +#include "lac_mem.h" +#include "lac_mem_pools.h" +#include "sal_types_compression.h" +#include "lac_sal.h" +#include "lac_sync.h" +#include "sal_service_state.h" +#include "sal_qat_cmn_msg.h" +#include "icp_sal_poll.h" + +/** + ***************************************************************************** + * @ingroup cpaDcDp + * Check that pOpData is valid + * + * @description + * Check that all the parameters defined in the pOpData are valid + * + * @param[in] pOpData Pointer to a structure containing the + * request parameters + * + * @retval CPA_STATUS_SUCCESS Function executed successfully + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in + * + *****************************************************************************/ +static CpaStatus +dcDataPlaneParamCheck(const CpaDcDpOpData *pOpData) +{ + sal_compression_service_t *pService = NULL; + dc_session_desc_t *pSessionDesc = NULL; + + LAC_CHECK_NULL_PARAM(pOpData); + LAC_CHECK_NULL_PARAM(pOpData->dcInstance); + LAC_CHECK_NULL_PARAM(pOpData->pSessionHandle); + + /* Ensure this is a compression instance */ + SAL_CHECK_INSTANCE_TYPE(pOpData->dcInstance, + SAL_SERVICE_TYPE_COMPRESSION); + + pService = (sal_compression_service_t *)(pOpData->dcInstance); + + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pOpData->pSessionHandle); + if (NULL == pSessionDesc) { + QAT_UTILS_LOG("Session handle not as expected.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (CPA_FALSE == pSessionDesc->isDcDp) { + QAT_UTILS_LOG("The session type should be data plane.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Compressing zero byte is not supported */ + if ((CPA_DC_DIR_COMPRESS == pSessionDesc->sessDirection) && + (0 == pOpData->bufferLenToCompress)) { + QAT_UTILS_LOG( + "The source buffer length to compress needs to be greater than zero byte.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (pOpData->sessDirection > CPA_DC_DIR_DECOMPRESS) { + QAT_UTILS_LOG("Invalid direction of operation.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (0 == pOpData->srcBuffer) { + QAT_UTILS_LOG("Invalid srcBuffer\n"); + return CPA_STATUS_INVALID_PARAM; + } + if (0 == pOpData->destBuffer) { + QAT_UTILS_LOG("Invalid destBuffer\n"); + return CPA_STATUS_INVALID_PARAM; + } + if (pOpData->srcBuffer == pOpData->destBuffer) { + QAT_UTILS_LOG("In place operation is not supported.\n"); + return CPA_STATUS_INVALID_PARAM; + } + if (0 == pOpData->thisPhys) { + QAT_UTILS_LOG("Invalid thisPhys\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if ((CPA_TRUE != pOpData->compressAndVerify) && + (CPA_FALSE != pOpData->compressAndVerify)) { + QAT_UTILS_LOG("Invalid compressAndVerify\n"); + return CPA_STATUS_INVALID_PARAM; + } + if ((CPA_TRUE == pOpData->compressAndVerify) && + !(pService->generic_service_info.dcExtendedFeatures & + DC_CNV_EXTENDED_CAPABILITY)) { + QAT_UTILS_LOG("Invalid compressAndVerify, no CNV capability\n"); + return CPA_STATUS_UNSUPPORTED; + } + if ((CPA_TRUE != pOpData->compressAndVerifyAndRecover) && + (CPA_FALSE != pOpData->compressAndVerifyAndRecover)) { + QAT_UTILS_LOG("Invalid compressAndVerifyAndRecover\n"); + return CPA_STATUS_INVALID_PARAM; + } + if ((CPA_TRUE == pOpData->compressAndVerifyAndRecover) && + (CPA_FALSE == pOpData->compressAndVerify)) { + QAT_UTILS_LOG("CnVnR option set without setting CnV\n"); + return CPA_STATUS_INVALID_PARAM; + } + if ((CPA_TRUE == pOpData->compressAndVerifyAndRecover) && + !(pService->generic_service_info.dcExtendedFeatures & + DC_CNVNR_EXTENDED_CAPABILITY)) { + QAT_UTILS_LOG( + "Invalid CnVnR option set and no CnVnR capability.\n"); + return CPA_STATUS_UNSUPPORTED; + } + + if ((CPA_DP_BUFLIST == pOpData->srcBufferLen) && + (CPA_DP_BUFLIST != pOpData->destBufferLen)) { + QAT_UTILS_LOG( + "The source and destination buffers need to be of the same type (both flat buffers or buffer lists).\n"); + return CPA_STATUS_INVALID_PARAM; + } + if ((CPA_DP_BUFLIST != pOpData->srcBufferLen) && + (CPA_DP_BUFLIST == pOpData->destBufferLen)) { + QAT_UTILS_LOG( + "The source and destination buffers need to be of the same type (both flat buffers or buffer lists).\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (CPA_DP_BUFLIST != pOpData->srcBufferLen) { + if (pOpData->srcBufferLen < pOpData->bufferLenToCompress) { + QAT_UTILS_LOG( + "srcBufferLen is smaller than bufferLenToCompress.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (pOpData->destBufferLen < pOpData->bufferLenForData) { + QAT_UTILS_LOG( + "destBufferLen is smaller than bufferLenForData.\n"); + return CPA_STATUS_INVALID_PARAM; + } + } else { + /* We are assuming that there is enough memory in the source and + * destination buffer lists. We only receive physical addresses + * of the + * buffers so we are unable to test it here */ + LAC_CHECK_8_BYTE_ALIGNMENT(pOpData->srcBuffer); + LAC_CHECK_8_BYTE_ALIGNMENT(pOpData->destBuffer); + } + + LAC_CHECK_8_BYTE_ALIGNMENT(pOpData->thisPhys); + + if ((CPA_DC_DIR_COMPRESS == pSessionDesc->sessDirection) || + (CPA_DC_DIR_COMBINED == pSessionDesc->sessDirection)) { + if (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType) { + /* Check if Intermediate Buffer Array pointer is NULL */ + if ((0 == pService->pInterBuffPtrsArrayPhyAddr) || + (NULL == pService->pInterBuffPtrsArray)) { + QAT_UTILS_LOG( + "No intermediate buffer defined for this instance - see cpaDcStartInstance.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Ensure that the destination buffer length for data is + * greater + * or equal to 128B */ + if (pOpData->bufferLenForData < + DC_DEST_BUFFER_DYN_MIN_SIZE) { + QAT_UTILS_LOG( + "Destination buffer length for data should be greater or equal to 128B.\n"); + return CPA_STATUS_INVALID_PARAM; + } + } else { + /* Ensure that the destination buffer length for data is + * greater + * or equal to min output buffsize */ + if (pOpData->bufferLenForData < + pService->comp_device_data.minOutputBuffSize) { + QAT_UTILS_LOG( + "Destination buffer size should be greater or equal to %d bytes.\n", + pService->comp_device_data + .minOutputBuffSize); + return CPA_STATUS_INVALID_PARAM; + } + } + } + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcDpGetSessionSize(CpaInstanceHandle dcInstance, + CpaDcSessionSetupData *pSessionData, + Cpa32U *pSessionSize) +{ + return dcGetSessionSize(dcInstance, pSessionData, pSessionSize, NULL); +} + +CpaStatus +cpaDcDpInitSession(CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle, + CpaDcSessionSetupData *pSessionData) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + dc_session_desc_t *pSessionDesc = NULL; + sal_compression_service_t *pService = NULL; + + LAC_CHECK_INSTANCE_HANDLE(dcInstance); + SAL_CHECK_INSTANCE_TYPE(dcInstance, SAL_SERVICE_TYPE_COMPRESSION); + + pService = (sal_compression_service_t *)dcInstance; + + /* Check if SAL is initialised otherwise return an error */ + SAL_RUNNING_CHECK(pService); + + /* Stateful is not supported */ + if (CPA_DC_STATELESS != pSessionData->sessState) { + QAT_UTILS_LOG("Invalid sessState value\n"); + return CPA_STATUS_INVALID_PARAM; + } + + status = + dcInitSession(dcInstance, pSessionHandle, pSessionData, NULL, NULL); + if (CPA_STATUS_SUCCESS == status) { + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); + pSessionDesc->isDcDp = CPA_TRUE; + + ICP_QAT_FW_COMN_PTR_TYPE_SET( + pSessionDesc->reqCacheDecomp.comn_hdr.comn_req_flags, + DC_DP_QAT_PTR_TYPE); + ICP_QAT_FW_COMN_PTR_TYPE_SET( + pSessionDesc->reqCacheComp.comn_hdr.comn_req_flags, + DC_DP_QAT_PTR_TYPE); + } + + return status; +} + +CpaStatus +cpaDcDpRemoveSession(const CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle) +{ + return cpaDcRemoveSession(dcInstance, pSessionHandle); +} + +CpaStatus +cpaDcDpRegCbFunc(const CpaInstanceHandle dcInstance, + const CpaDcDpCallbackFn pNewCb) +{ + sal_compression_service_t *pService = NULL; + + LAC_CHECK_NULL_PARAM(dcInstance); + SAL_CHECK_INSTANCE_TYPE(dcInstance, SAL_SERVICE_TYPE_COMPRESSION); + LAC_CHECK_NULL_PARAM(pNewCb); + + /* Check if SAL is initialised otherwise return an error */ + SAL_RUNNING_CHECK(dcInstance); + + pService = (sal_compression_service_t *)dcInstance; + pService->pDcDpCb = pNewCb; + + return CPA_STATUS_SUCCESS; +} + +/** + ***************************************************************************** + * @ingroup cpaDcDp + * + * @description + * Writes the message to the ring + * + * @param[in] pOpData Pointer to a structure containing the + * request parameters + * @param[in] pCurrentQatMsg Pointer to current QAT message on the ring + * + *****************************************************************************/ +static void +dcDpWriteRingMsg(CpaDcDpOpData *pOpData, icp_qat_fw_comp_req_t *pCurrentQatMsg) +{ + icp_qat_fw_comp_req_t *pReqCache = NULL; + dc_session_desc_t *pSessionDesc = NULL; + Cpa8U bufferFormat; + + Cpa8U cnvDecompReq = ICP_QAT_FW_COMP_NO_CNV; + Cpa8U cnvnrCompReq = ICP_QAT_FW_COMP_NO_CNV_RECOVERY; + + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pOpData->pSessionHandle); + + if (CPA_DC_DIR_COMPRESS == pOpData->sessDirection) { + pReqCache = &(pSessionDesc->reqCacheComp); + /* CNV check */ + if (CPA_TRUE == pOpData->compressAndVerify) { + cnvDecompReq = ICP_QAT_FW_COMP_CNV; + /* CNVNR check */ + if (CPA_TRUE == pOpData->compressAndVerifyAndRecover) { + cnvnrCompReq = ICP_QAT_FW_COMP_CNV_RECOVERY; + } + } + } else { + pReqCache = &(pSessionDesc->reqCacheDecomp); + } + + /* Fills in the template DC ET ring message - cached from the + * session descriptor */ + memcpy((void *)pCurrentQatMsg, + (void *)(pReqCache), + (LAC_QAT_DC_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES)); + + if (CPA_DP_BUFLIST == pOpData->srcBufferLen) { + bufferFormat = QAT_COMN_PTR_TYPE_SGL; + } else { + bufferFormat = QAT_COMN_PTR_TYPE_FLAT; + } + + pCurrentQatMsg->comp_pars.req_par_flags |= + ICP_QAT_FW_COMP_REQ_PARAM_FLAGS_BUILD( + 0, 0, 0, cnvDecompReq, cnvnrCompReq, 0); + + SalQatMsg_CmnMidWrite((icp_qat_fw_la_bulk_req_t *)pCurrentQatMsg, + pOpData, + bufferFormat, + pOpData->srcBuffer, + pOpData->destBuffer, + pOpData->srcBufferLen, + pOpData->destBufferLen); + + pCurrentQatMsg->comp_pars.comp_len = pOpData->bufferLenToCompress; + pCurrentQatMsg->comp_pars.out_buffer_sz = pOpData->bufferLenForData; +} + +CpaStatus +cpaDcDpEnqueueOp(CpaDcDpOpData *pOpData, const CpaBoolean performOpNow) +{ + icp_qat_fw_comp_req_t *pCurrentQatMsg = NULL; + icp_comms_trans_handle trans_handle = NULL; + dc_session_desc_t *pSessionDesc = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + + status = dcDataPlaneParamCheck(pOpData); + if (CPA_STATUS_SUCCESS != status) { + return status; + } + + if ((CPA_FALSE == pOpData->compressAndVerify) && + (CPA_DC_DIR_COMPRESS == pOpData->sessDirection)) { + return CPA_STATUS_UNSUPPORTED; + } + + /* Check if SAL is initialised otherwise return an error */ + SAL_RUNNING_CHECK(pOpData->dcInstance); + + trans_handle = ((sal_compression_service_t *)pOpData->dcInstance) + ->trans_handle_compression_tx; + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pOpData->pSessionHandle); + + if ((CPA_DC_DIR_COMPRESS == pOpData->sessDirection) && + (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection)) { + QAT_UTILS_LOG( + "The session does not support this direction of operation.\n"); + return CPA_STATUS_INVALID_PARAM; + } else if ((CPA_DC_DIR_DECOMPRESS == pOpData->sessDirection) && + (CPA_DC_DIR_COMPRESS == pSessionDesc->sessDirection)) { + QAT_UTILS_LOG( + "The session does not support this direction of operation.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + icp_adf_getSingleQueueAddr(trans_handle, (void **)&pCurrentQatMsg); + if (NULL == pCurrentQatMsg) { + return CPA_STATUS_RETRY; + } + + dcDpWriteRingMsg(pOpData, pCurrentQatMsg); + pSessionDesc->pendingDpStatelessCbCount++; + + if (CPA_TRUE == performOpNow) { + SalQatMsg_updateQueueTail(trans_handle); + } + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcDpEnqueueOpBatch(const Cpa32U numberRequests, + CpaDcDpOpData *pOpData[], + const CpaBoolean performOpNow) +{ + icp_qat_fw_comp_req_t *pCurrentQatMsg = NULL; + icp_comms_trans_handle trans_handle = NULL; + dc_session_desc_t *pSessionDesc = NULL; + Cpa32U i = 0; + CpaStatus status = CPA_STATUS_SUCCESS; + sal_compression_service_t *pService = NULL; + + LAC_CHECK_NULL_PARAM(pOpData); + LAC_CHECK_NULL_PARAM(pOpData[0]); + LAC_CHECK_NULL_PARAM(pOpData[0]->dcInstance); + + pService = (sal_compression_service_t *)(pOpData[0]->dcInstance); + if ((numberRequests == 0) || + (numberRequests > pService->maxNumCompConcurrentReq)) { + QAT_UTILS_LOG( + "The number of requests needs to be between 1 and %d.\n", + pService->maxNumCompConcurrentReq); + return CPA_STATUS_INVALID_PARAM; + } + + for (i = 0; i < numberRequests; i++) { + status = dcDataPlaneParamCheck(pOpData[i]); + if (CPA_STATUS_SUCCESS != status) { + return status; + } + + /* Check that all instance handles and session handles are the + * same */ + if (pOpData[i]->dcInstance != pOpData[0]->dcInstance) { + QAT_UTILS_LOG( + "All instance handles should be the same in the pOpData.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (pOpData[i]->pSessionHandle != pOpData[0]->pSessionHandle) { + QAT_UTILS_LOG( + "All session handles should be the same in the pOpData.\n"); + return CPA_STATUS_INVALID_PARAM; + } + } + + for (i = 0; i < numberRequests; i++) { + if ((CPA_FALSE == pOpData[i]->compressAndVerify) && + (CPA_DC_DIR_COMPRESS == pOpData[i]->sessDirection)) { + return CPA_STATUS_UNSUPPORTED; + } + } + + /* Check if SAL is initialised otherwise return an error */ + SAL_RUNNING_CHECK(pOpData[0]->dcInstance); + + trans_handle = ((sal_compression_service_t *)pOpData[0]->dcInstance) + ->trans_handle_compression_tx; + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pOpData[0]->pSessionHandle); + + for (i = 0; i < numberRequests; i++) { + if ((CPA_DC_DIR_COMPRESS == pOpData[i]->sessDirection) && + (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection)) { + QAT_UTILS_LOG( + "The session does not support this direction of operation.\n"); + return CPA_STATUS_INVALID_PARAM; + } else if ((CPA_DC_DIR_DECOMPRESS == + pOpData[i]->sessDirection) && + (CPA_DC_DIR_COMPRESS == + pSessionDesc->sessDirection)) { + QAT_UTILS_LOG( + "The session does not support this direction of operation.\n"); + return CPA_STATUS_INVALID_PARAM; + } + } + + icp_adf_getQueueMemory(trans_handle, + numberRequests, + (void **)&pCurrentQatMsg); + if (NULL == pCurrentQatMsg) { + return CPA_STATUS_RETRY; + } + + for (i = 0; i < numberRequests; i++) { + dcDpWriteRingMsg(pOpData[i], pCurrentQatMsg); + icp_adf_getQueueNext(trans_handle, (void **)&pCurrentQatMsg); + } + + pSessionDesc->pendingDpStatelessCbCount += numberRequests; + + if (CPA_TRUE == performOpNow) { + SalQatMsg_updateQueueTail(trans_handle); + } + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +icp_sal_DcPollDpInstance(CpaInstanceHandle dcInstance, Cpa32U responseQuota) +{ + icp_comms_trans_handle trans_handle = NULL; + + LAC_CHECK_INSTANCE_HANDLE(dcInstance); + SAL_CHECK_INSTANCE_TYPE(dcInstance, SAL_SERVICE_TYPE_COMPRESSION); + + /* Check if SAL is initialised otherwise return an error */ + SAL_RUNNING_CHECK(dcInstance); + + trans_handle = ((sal_compression_service_t *)dcInstance) + ->trans_handle_compression_rx; + + return icp_adf_pollQueue(trans_handle, responseQuota); +} + +CpaStatus +cpaDcDpPerformOpNow(CpaInstanceHandle dcInstance) +{ + icp_comms_trans_handle trans_handle = NULL; + + LAC_CHECK_NULL_PARAM(dcInstance); + SAL_CHECK_INSTANCE_TYPE(dcInstance, SAL_SERVICE_TYPE_COMPRESSION); + + /* Check if SAL is initialised otherwise return an error */ + SAL_RUNNING_CHECK(dcInstance); + + trans_handle = ((sal_compression_service_t *)dcInstance) + ->trans_handle_compression_tx; + + if (CPA_TRUE == icp_adf_queueDataToSend(trans_handle)) { + SalQatMsg_updateQueueTail(trans_handle); + } + + return CPA_STATUS_SUCCESS; +} diff --git a/sys/dev/qat/qat_api/common/compression/dc_header_footer.c b/sys/dev/qat/qat_api/common/compression/dc_header_footer.c new file mode 100644 index 000000000000..4a92e20ba0f4 --- /dev/null +++ b/sys/dev/qat/qat_api/common/compression/dc_header_footer.c @@ -0,0 +1,237 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file dc_header_footer.c + * + * @ingroup Dc_DataCompression + * + * @description + * Implementation of the Data Compression header and footer operations. + * + *****************************************************************************/ + +/* + ******************************************************************************* + * Include public/global header files + ******************************************************************************* + */ +#include "cpa.h" +#include "cpa_dc.h" +#include "icp_adf_init.h" + +/* + ******************************************************************************* + * Include private header files + ******************************************************************************* + */ +#include "dc_header_footer.h" +#include "dc_session.h" +#include "dc_datapath.h" + +CpaStatus +cpaDcGenerateHeader(CpaDcSessionHandle pSessionHandle, + CpaFlatBuffer *pDestBuff, + Cpa32U *count) +{ + dc_session_desc_t *pSessionDesc = NULL; + + LAC_CHECK_NULL_PARAM(pSessionHandle); + LAC_CHECK_NULL_PARAM(pDestBuff); + LAC_CHECK_NULL_PARAM(pDestBuff->pData); + LAC_CHECK_NULL_PARAM(count); + + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); + + if (NULL == pSessionDesc) { + QAT_UTILS_LOG("Session handle not as expected\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection) { + QAT_UTILS_LOG("Invalid session direction\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (CPA_DC_DEFLATE == pSessionDesc->compType) { + /* Adding a Gzip header */ + if (CPA_DC_CRC32 == pSessionDesc->checksumType) { + Cpa8U *pDest = pDestBuff->pData; + + if (pDestBuff->dataLenInBytes < DC_GZIP_HEADER_SIZE) { + QAT_UTILS_LOG( + "The dataLenInBytes of the dest buffer is too small.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + pDest[0] = DC_GZIP_ID1; /* ID1 */ + pDest[1] = DC_GZIP_ID2; /* ID2 */ + pDest[2] = + 0x08; /* CM = 8 denotes "deflate" compression */ + pDest[3] = 0x00; /* FLG = 0 denotes "No extra fields" */ + pDest[4] = 0x00; + pDest[5] = 0x00; + pDest[6] = 0x00; + pDest[7] = 0x00; /* MTIME = 0x00 means time stamp not + available */ + + /* XFL = 4 - compressor used fastest compression, */ + /* XFL = 2 - compressor used maximum compression. */ + pDest[8] = 0; + if (CPA_DC_L1 == pSessionDesc->compLevel) + pDest[8] = DC_GZIP_FAST_COMP; + else if (CPA_DC_L4 >= pSessionDesc->compLevel) + pDest[8] = DC_GZIP_MAX_COMP; + + pDest[9] = + DC_GZIP_FILESYSTYPE; /* OS = 0 means FAT filesystem + (MS-DOS, OS/2, NT/Win32), 3 - Unix */ + + /* Set to the number of bytes added to the buffer */ + *count = DC_GZIP_HEADER_SIZE; + } + + /* Adding a Zlib header */ + else if (CPA_DC_ADLER32 == pSessionDesc->checksumType) { + Cpa8U *pDest = pDestBuff->pData; + Cpa16U header = 0, level = 0; + + if (pDestBuff->dataLenInBytes < DC_ZLIB_HEADER_SIZE) { + QAT_UTILS_LOG( + "The dataLenInBytes of the dest buffer is too small.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + /* CMF = CM | CMINFO. + CM = 8 denotes "deflate" compression, + CMINFO = 7 indicates a 32K window size */ + /* Depending on the device, at compression levels above + L1, the + window size can be 8 or 16K bytes. + The file will decompress ok if a greater window size + is specified + in the header. */ + header = + (DC_ZLIB_CM_DEFLATE + + (DC_32K_WINDOW_SIZE << DC_ZLIB_WINDOWSIZE_OFFSET)) + << LAC_NUM_BITS_IN_BYTE; + + switch (pSessionDesc->compLevel) { + case CPA_DC_L1: + level = DC_ZLIB_LEVEL_0; + break; + case CPA_DC_L2: + level = DC_ZLIB_LEVEL_1; + break; + case CPA_DC_L3: + level = DC_ZLIB_LEVEL_2; + break; + default: + level = DC_ZLIB_LEVEL_3; + } + + /* Bits 6 - 7: FLEVEL, compression level */ + header |= level << DC_ZLIB_FLEVEL_OFFSET; + + /* The header has to be a multiple of 31 */ + header += DC_ZLIB_HEADER_OFFSET - + (header % DC_ZLIB_HEADER_OFFSET); + + pDest[0] = (Cpa8U)(header >> LAC_NUM_BITS_IN_BYTE); + pDest[1] = (Cpa8U)header; + + /* Set to the number of bytes added to the buffer */ + *count = DC_ZLIB_HEADER_SIZE; + } + + /* If deflate but no checksum required */ + else { + *count = 0; + } + } else { + /* There is no header for other compressed data */ + *count = 0; + } + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcGenerateFooter(CpaDcSessionHandle pSessionHandle, + CpaFlatBuffer *pDestBuff, + CpaDcRqResults *pRes) +{ + dc_session_desc_t *pSessionDesc = NULL; + + LAC_CHECK_NULL_PARAM(pSessionHandle); + LAC_CHECK_NULL_PARAM(pDestBuff); + LAC_CHECK_NULL_PARAM(pDestBuff->pData); + LAC_CHECK_NULL_PARAM(pRes); + + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); + + if (NULL == pSessionDesc) { + QAT_UTILS_LOG("Session handle not as expected\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection) { + QAT_UTILS_LOG("Invalid session direction\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (CPA_DC_DEFLATE == pSessionDesc->compType) { + if (CPA_DC_CRC32 == pSessionDesc->checksumType) { + Cpa8U *pDest = pDestBuff->pData; + Cpa32U crc32 = pRes->checksum; + Cpa64U totalLenBeforeCompress = + pSessionDesc->cumulativeConsumedBytes; + + if (pDestBuff->dataLenInBytes < DC_GZIP_FOOTER_SIZE) { + QAT_UTILS_LOG( + "The dataLenInBytes of the dest buffer is too small.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Crc32 of the uncompressed data */ + pDest[0] = (Cpa8U)crc32; + pDest[1] = (Cpa8U)(crc32 >> LAC_NUM_BITS_IN_BYTE); + pDest[2] = (Cpa8U)(crc32 >> 2 * LAC_NUM_BITS_IN_BYTE); + pDest[3] = (Cpa8U)(crc32 >> 3 * LAC_NUM_BITS_IN_BYTE); + + /* Length of the uncompressed data */ + pDest[4] = (Cpa8U)totalLenBeforeCompress; + pDest[5] = (Cpa8U)(totalLenBeforeCompress >> + LAC_NUM_BITS_IN_BYTE); + pDest[6] = (Cpa8U)(totalLenBeforeCompress >> + 2 * LAC_NUM_BITS_IN_BYTE); + pDest[7] = (Cpa8U)(totalLenBeforeCompress >> + 3 * LAC_NUM_BITS_IN_BYTE); + + /* Increment produced by the number of bytes added to + * the buffer */ + pRes->produced += DC_GZIP_FOOTER_SIZE; + } else if (CPA_DC_ADLER32 == pSessionDesc->checksumType) { + Cpa8U *pDest = pDestBuff->pData; + Cpa32U adler32 = pRes->checksum; + + if (pDestBuff->dataLenInBytes < DC_ZLIB_FOOTER_SIZE) { + QAT_UTILS_LOG( + "The dataLenInBytes of the dest buffer is too small.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Adler32 of the uncompressed data */ + pDest[0] = (Cpa8U)(adler32 >> 3 * LAC_NUM_BITS_IN_BYTE); + pDest[1] = (Cpa8U)(adler32 >> 2 * LAC_NUM_BITS_IN_BYTE); + pDest[2] = (Cpa8U)(adler32 >> LAC_NUM_BITS_IN_BYTE); + pDest[3] = (Cpa8U)adler32; + + /* Increment produced by the number of bytes added to + * the buffer */ + pRes->produced += DC_ZLIB_FOOTER_SIZE; + } + } + + return CPA_STATUS_SUCCESS; +} diff --git a/sys/dev/qat/qat_api/common/compression/dc_session.c b/sys/dev/qat/qat_api/common/compression/dc_session.c new file mode 100644 index 000000000000..1d742e227a10 --- /dev/null +++ b/sys/dev/qat/qat_api/common/compression/dc_session.c @@ -0,0 +1,957 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file dc_session.c + * + * @ingroup Dc_DataCompression + * + * @description + * Implementation of the Data Compression session operations. + * + *****************************************************************************/ + +/* + ******************************************************************************* + * Include public/global header files + ******************************************************************************* + */ +#include "cpa.h" +#include "cpa_dc.h" + +#include "icp_qat_fw.h" +#include "icp_qat_fw_comp.h" +#include "icp_qat_hw.h" + +/* + ******************************************************************************* + * Include private header files + ******************************************************************************* + */ +#include "dc_session.h" +#include "dc_datapath.h" +#include "lac_mem_pools.h" +#include "sal_types_compression.h" +#include "lac_buffer_desc.h" +#include "sal_service_state.h" +#include "sal_qat_cmn_msg.h" + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Check that pSessionData is valid + * + * @description + * Check that all the parameters defined in the pSessionData are valid + * + * @param[in] pSessionData Pointer to a user instantiated structure + * containing session data + * + * @retval CPA_STATUS_SUCCESS Function executed successfully + * @retval CPA_STATUS_FAIL Function failed to find device + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in + * @retval CPA_STATUS_UNSUPPORTED Unsupported algorithm/feature + * + *****************************************************************************/ +static CpaStatus +dcCheckSessionData(const CpaDcSessionSetupData *pSessionData, + CpaInstanceHandle dcInstance) +{ + CpaDcInstanceCapabilities instanceCapabilities = { 0 }; + + cpaDcQueryCapabilities(dcInstance, &instanceCapabilities); + + if ((pSessionData->compLevel < CPA_DC_L1) || + (pSessionData->compLevel > CPA_DC_L9)) { + QAT_UTILS_LOG("Invalid compLevel value\n"); + return CPA_STATUS_INVALID_PARAM; + } + if ((pSessionData->autoSelectBestHuffmanTree < CPA_DC_ASB_DISABLED) || + (pSessionData->autoSelectBestHuffmanTree > + CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_NO_HDRS)) { + QAT_UTILS_LOG("Invalid autoSelectBestHuffmanTree value\n"); + return CPA_STATUS_INVALID_PARAM; + } + if (pSessionData->compType != CPA_DC_DEFLATE) { + QAT_UTILS_LOG("Invalid compType value\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if ((pSessionData->huffType < CPA_DC_HT_STATIC) || + (pSessionData->huffType > CPA_DC_HT_FULL_DYNAMIC) || + (CPA_DC_HT_PRECOMP == pSessionData->huffType)) { + QAT_UTILS_LOG("Invalid huffType value\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if ((pSessionData->sessDirection < CPA_DC_DIR_COMPRESS) || + (pSessionData->sessDirection > CPA_DC_DIR_COMBINED)) { + QAT_UTILS_LOG("Invalid sessDirection value\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if ((pSessionData->sessState < CPA_DC_STATEFUL) || + (pSessionData->sessState > CPA_DC_STATELESS)) { + QAT_UTILS_LOG("Invalid sessState value\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if ((pSessionData->checksum < CPA_DC_NONE) || + (pSessionData->checksum > CPA_DC_ADLER32)) { + QAT_UTILS_LOG("Invalid checksum value\n"); + return CPA_STATUS_INVALID_PARAM; + } + + return CPA_STATUS_SUCCESS; +} + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Populate the compression hardware block + * + * @description + * This function will populate the compression hardware block and update + * the size in bytes of the block + * + * @param[in] pSessionDesc Pointer to the session descriptor + * @param[in] pCompConfig Pointer to slice config word + * @param[in] compDecomp Direction of the operation + * @param[in] enableDmm Delayed Match Mode + * + *****************************************************************************/ +static void +dcCompHwBlockPopulate(dc_session_desc_t *pSessionDesc, + icp_qat_hw_compression_config_t *pCompConfig, + dc_request_dir_t compDecomp, + icp_qat_hw_compression_delayed_match_t enableDmm) +{ + icp_qat_hw_compression_direction_t dir = + ICP_QAT_HW_COMPRESSION_DIR_COMPRESS; + icp_qat_hw_compression_algo_t algo = + ICP_QAT_HW_COMPRESSION_ALGO_DEFLATE; + icp_qat_hw_compression_depth_t depth = ICP_QAT_HW_COMPRESSION_DEPTH_1; + icp_qat_hw_compression_file_type_t filetype = + ICP_QAT_HW_COMPRESSION_FILE_TYPE_0; + + /* Set the direction */ + if (DC_COMPRESSION_REQUEST == compDecomp) { + dir = ICP_QAT_HW_COMPRESSION_DIR_COMPRESS; + } else { + dir = ICP_QAT_HW_COMPRESSION_DIR_DECOMPRESS; + } + + if (CPA_DC_DEFLATE == pSessionDesc->compType) { + algo = ICP_QAT_HW_COMPRESSION_ALGO_DEFLATE; + } else { + QAT_UTILS_LOG("Algorithm not supported for Compression\n"); + } + + /* Set the depth */ + if (DC_DECOMPRESSION_REQUEST == compDecomp) { + depth = ICP_QAT_HW_COMPRESSION_DEPTH_1; + } else { + switch (pSessionDesc->compLevel) { + case CPA_DC_L1: + depth = ICP_QAT_HW_COMPRESSION_DEPTH_1; + break; + case CPA_DC_L2: + depth = ICP_QAT_HW_COMPRESSION_DEPTH_4; + break; + case CPA_DC_L3: + depth = ICP_QAT_HW_COMPRESSION_DEPTH_8; + break; + default: + depth = ICP_QAT_HW_COMPRESSION_DEPTH_16; + } + } + + /* The file type is set to ICP_QAT_HW_COMPRESSION_FILE_TYPE_0. The other + * modes will be used in the future for precompiled huffman trees */ + filetype = ICP_QAT_HW_COMPRESSION_FILE_TYPE_0; + + pCompConfig->val = ICP_QAT_HW_COMPRESSION_CONFIG_BUILD( + dir, enableDmm, algo, depth, filetype); + + pCompConfig->reserved = 0; +} + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Populate the compression content descriptor + * + * @description + * This function will populate the compression content descriptor + * + * @param[in] pService Pointer to the service + * @param[in] pSessionDesc Pointer to the session descriptor + * @param[in] contextBufferAddrPhys Physical address of the context buffer + * @param[out] pMsg Pointer to the compression message + * @param[in] nextSlice Next slice + * @param[in] compDecomp Direction of the operation + * + *****************************************************************************/ +static void +dcCompContentDescPopulate(sal_compression_service_t *pService, + dc_session_desc_t *pSessionDesc, + CpaPhysicalAddr contextBufferAddrPhys, + icp_qat_fw_comp_req_t *pMsg, + icp_qat_fw_slice_t nextSlice, + dc_request_dir_t compDecomp) +{ + + icp_qat_fw_comp_cd_hdr_t *pCompControlBlock = NULL; + icp_qat_hw_compression_config_t *pCompConfig = NULL; + CpaBoolean bankEnabled = CPA_FALSE; + + pCompControlBlock = (icp_qat_fw_comp_cd_hdr_t *)&(pMsg->comp_cd_ctrl); + pCompConfig = + (icp_qat_hw_compression_config_t *)(pMsg->cd_pars.sl + .comp_slice_cfg_word); + + ICP_QAT_FW_COMN_NEXT_ID_SET(pCompControlBlock, nextSlice); + ICP_QAT_FW_COMN_CURR_ID_SET(pCompControlBlock, ICP_QAT_FW_SLICE_COMP); + + pCompControlBlock->comp_cfg_offset = 0; + + if ((CPA_DC_STATEFUL == pSessionDesc->sessState) && + (CPA_DC_DEFLATE == pSessionDesc->compType) && + (DC_DECOMPRESSION_REQUEST == compDecomp)) { + /* Enable A, B, C, D, and E (CAMs). */ + pCompControlBlock->ram_bank_flags = + ICP_QAT_FW_COMP_RAM_FLAGS_BUILD( + ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank I */ + ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank H */ + ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank G */ + ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank F */ + ICP_QAT_FW_COMP_BANK_ENABLED, /* Bank E */ + ICP_QAT_FW_COMP_BANK_ENABLED, /* Bank D */ + ICP_QAT_FW_COMP_BANK_ENABLED, /* Bank C */ + ICP_QAT_FW_COMP_BANK_ENABLED, /* Bank B */ + ICP_QAT_FW_COMP_BANK_ENABLED); /* Bank A */ + bankEnabled = CPA_TRUE; + } else { + /* Disable all banks */ + pCompControlBlock->ram_bank_flags = + ICP_QAT_FW_COMP_RAM_FLAGS_BUILD( + ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank I */ + ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank H */ + ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank G */ + ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank F */ + ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank E */ + ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank D */ + ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank C */ + ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank B */ + ICP_QAT_FW_COMP_BANK_DISABLED); /* Bank A */ + } + + if (DC_COMPRESSION_REQUEST == compDecomp) { + LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( + pService->generic_service_info, + pCompControlBlock->comp_state_addr, + pSessionDesc->stateRegistersComp); + } else { + LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( + pService->generic_service_info, + pCompControlBlock->comp_state_addr, + pSessionDesc->stateRegistersDecomp); + } + + if (CPA_TRUE == bankEnabled) { + pCompControlBlock->ram_banks_addr = contextBufferAddrPhys; + } else { + pCompControlBlock->ram_banks_addr = 0; + } + + pCompControlBlock->resrvd = 0; + + /* Populate Compression Hardware Setup Block */ + dcCompHwBlockPopulate(pSessionDesc, + pCompConfig, + compDecomp, + pService->comp_device_data.enableDmm); +} + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Populate the translator content descriptor + * + * @description + * This function will populate the translator content descriptor + * + * @param[out] pMsg Pointer to the compression message + * @param[in] nextSlice Next slice + * + *****************************************************************************/ +static void +dcTransContentDescPopulate(icp_qat_fw_comp_req_t *pMsg, + icp_qat_fw_slice_t nextSlice) +{ + + icp_qat_fw_xlt_cd_hdr_t *pTransControlBlock = NULL; + pTransControlBlock = (icp_qat_fw_xlt_cd_hdr_t *)&(pMsg->u2.xlt_cd_ctrl); + + ICP_QAT_FW_COMN_NEXT_ID_SET(pTransControlBlock, nextSlice); + ICP_QAT_FW_COMN_CURR_ID_SET(pTransControlBlock, ICP_QAT_FW_SLICE_XLAT); + + pTransControlBlock->resrvd1 = 0; + pTransControlBlock->resrvd2 = 0; + pTransControlBlock->resrvd3 = 0; +} + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Get the context size and the history size + * + * @description + * This function will get the size of the context buffer and the history + * buffer. The history buffer is a subset of the context buffer and its + * size is needed for stateful compression. + + * @param[in] dcInstance DC Instance Handle + * + * @param[in] pSessionData Pointer to a user instantiated + * structure containing session data + * @param[out] pContextSize Pointer to the context size + * + * @retval CPA_STATUS_SUCCESS Function executed successfully + * + * + *****************************************************************************/ +static CpaStatus +dcGetContextSize(CpaInstanceHandle dcInstance, + CpaDcSessionSetupData *pSessionData, + Cpa32U *pContextSize) +{ + sal_compression_service_t *pCompService = NULL; + + pCompService = (sal_compression_service_t *)dcInstance; + + *pContextSize = 0; + if ((CPA_DC_STATEFUL == pSessionData->sessState) && + (CPA_DC_DEFLATE == pSessionData->compType) && + (CPA_DC_DIR_COMPRESS != pSessionData->sessDirection)) { + *pContextSize = + pCompService->comp_device_data.inflateContextSize; + } + return CPA_STATUS_SUCCESS; +} + +CpaStatus +dcInitSession(CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle, + CpaDcSessionSetupData *pSessionData, + CpaBufferList *pContextBuffer, + CpaDcCallbackFn callbackFn) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_compression_service_t *pService = NULL; + icp_qat_fw_comp_req_t *pReqCache = NULL; + dc_session_desc_t *pSessionDesc = NULL; + CpaPhysicalAddr contextAddrPhys = 0; + CpaPhysicalAddr physAddress = 0; + CpaPhysicalAddr physAddressAligned = 0; + Cpa32U minContextSize = 0, historySize = 0; + Cpa32U rpCmdFlags = 0; + icp_qat_fw_serv_specif_flags cmdFlags = 0; + Cpa8U secureRam = ICP_QAT_FW_COMP_ENABLE_SECURE_RAM_USED_AS_INTMD_BUF; + Cpa8U sessType = ICP_QAT_FW_COMP_STATELESS_SESSION; + Cpa8U autoSelectBest = ICP_QAT_FW_COMP_NOT_AUTO_SELECT_BEST; + Cpa8U enhancedAutoSelectBest = ICP_QAT_FW_COMP_NOT_ENH_AUTO_SELECT_BEST; + Cpa8U disableType0EnhancedAutoSelectBest = + ICP_QAT_FW_COMP_NOT_DISABLE_TYPE0_ENH_AUTO_SELECT_BEST; + icp_qat_fw_la_cmd_id_t dcCmdId = + (icp_qat_fw_la_cmd_id_t)ICP_QAT_FW_COMP_CMD_STATIC; + icp_qat_fw_comn_flags cmnRequestFlags = 0; + dc_integrity_crc_fw_t *pDataIntegrityCrcs = NULL; + + cmnRequestFlags = + ICP_QAT_FW_COMN_FLAGS_BUILD(DC_DEFAULT_QAT_PTR_TYPE, + QAT_COMN_CD_FLD_TYPE_16BYTE_DATA); + + pService = (sal_compression_service_t *)dcInstance; + + secureRam = pService->comp_device_data.useDevRam; + + LAC_CHECK_NULL_PARAM(pSessionHandle); + LAC_CHECK_NULL_PARAM(pSessionData); + + /* Check that the parameters defined in the pSessionData are valid for + * the + * device */ + if (CPA_STATUS_SUCCESS != + dcCheckSessionData(pSessionData, dcInstance)) { + return CPA_STATUS_INVALID_PARAM; + } + + if ((CPA_DC_STATEFUL == pSessionData->sessState) && + (CPA_DC_DIR_DECOMPRESS != pSessionData->sessDirection)) { + QAT_UTILS_LOG("Stateful sessions are not supported.\n"); + return CPA_STATUS_UNSUPPORTED; + } + + if (CPA_DC_HT_FULL_DYNAMIC == pSessionData->huffType) { + /* Test if DRAM is available for the intermediate buffers */ + if ((NULL == pService->pInterBuffPtrsArray) && + (0 == pService->pInterBuffPtrsArrayPhyAddr)) { + if (CPA_DC_ASB_STATIC_DYNAMIC == + pSessionData->autoSelectBestHuffmanTree) { + /* Define the Huffman tree as static */ + pSessionData->huffType = CPA_DC_HT_STATIC; + } else { + QAT_UTILS_LOG( + "No buffer defined for this instance - see cpaDcStartInstance.\n"); + return CPA_STATUS_RESOURCE; + } + } + } + + if ((CPA_DC_STATEFUL == pSessionData->sessState) && + (CPA_DC_DEFLATE == pSessionData->compType)) { + /* Get the size of the context buffer */ + status = + dcGetContextSize(dcInstance, pSessionData, &minContextSize); + + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG( + "Unable to get the context size of the session.\n"); + return CPA_STATUS_FAIL; + } + + /* If the minContextSize is zero it means we will not save or + * restore + * any history */ + if (0 != minContextSize) { + Cpa64U contextBuffSize = 0; + + LAC_CHECK_NULL_PARAM(pContextBuffer); + + if (LacBuffDesc_BufferListVerify( + pContextBuffer, + &contextBuffSize, + LAC_NO_ALIGNMENT_SHIFT) != CPA_STATUS_SUCCESS) { + return CPA_STATUS_INVALID_PARAM; + } + + /* Ensure that the context buffer size is greater or + * equal + * to minContextSize */ + if (contextBuffSize < minContextSize) { + QAT_UTILS_LOG( + "Context buffer size should be greater or equal to %d.\n", + minContextSize); + return CPA_STATUS_INVALID_PARAM; + } + } + } + + /* Re-align the session structure to 64 byte alignment */ + physAddress = + LAC_OS_VIRT_TO_PHYS_EXTERNAL(pService->generic_service_info, + (Cpa8U *)pSessionHandle + + sizeof(void *)); + + if (physAddress == 0) { + QAT_UTILS_LOG( + "Unable to get the physical address of the session.\n"); + return CPA_STATUS_FAIL; + } + + physAddressAligned = + (CpaPhysicalAddr)LAC_ALIGN_POW2_ROUNDUP(physAddress, + LAC_64BYTE_ALIGNMENT); + + pSessionDesc = (dc_session_desc_t *) + /* Move the session pointer by the physical offset + between aligned and unaligned memory */ + ((Cpa8U *)pSessionHandle + sizeof(void *) + + (physAddressAligned - physAddress)); + + /* Save the aligned pointer in the first bytes (size of LAC_ARCH_UINT) + * of the session memory */ + *((LAC_ARCH_UINT *)pSessionHandle) = (LAC_ARCH_UINT)pSessionDesc; + + /* Zero the compression session */ + LAC_OS_BZERO(pSessionDesc, sizeof(dc_session_desc_t)); + + /* Write the buffer descriptor for context/history */ + if (0 != minContextSize) { + status = LacBuffDesc_BufferListDescWrite( + pContextBuffer, + &contextAddrPhys, + CPA_FALSE, + &(pService->generic_service_info)); + + if (status != CPA_STATUS_SUCCESS) { + return status; + } + + pSessionDesc->pContextBuffer = pContextBuffer; + pSessionDesc->historyBuffSize = historySize; + } + + pSessionDesc->cumulativeConsumedBytes = 0; + + /* Initialise pSessionDesc */ + pSessionDesc->requestType = DC_REQUEST_FIRST; + pSessionDesc->huffType = pSessionData->huffType; + pSessionDesc->compType = pSessionData->compType; + pSessionDesc->checksumType = pSessionData->checksum; + pSessionDesc->autoSelectBestHuffmanTree = + pSessionData->autoSelectBestHuffmanTree; + pSessionDesc->sessDirection = pSessionData->sessDirection; + pSessionDesc->sessState = pSessionData->sessState; + pSessionDesc->compLevel = pSessionData->compLevel; + pSessionDesc->isDcDp = CPA_FALSE; + pSessionDesc->minContextSize = minContextSize; + pSessionDesc->isSopForCompressionProcessed = CPA_FALSE; + pSessionDesc->isSopForDecompressionProcessed = CPA_FALSE; + + if (CPA_DC_ADLER32 == pSessionDesc->checksumType) { + pSessionDesc->previousChecksum = 1; + } else { + pSessionDesc->previousChecksum = 0; + } + + if (CPA_DC_STATEFUL == pSessionData->sessState) { + /* Init the spinlock used to lock the access to the number of + * stateful + * in-flight requests */ + status = LAC_SPINLOCK_INIT(&(pSessionDesc->sessionLock)); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG( + "Spinlock init failed for sessionLock.\n"); + return CPA_STATUS_RESOURCE; + } + } + + /* For asynchronous - use the user supplied callback + * for synchronous - use the internal synchronous callback */ + pSessionDesc->pCompressionCb = ((void *)NULL != (void *)callbackFn) ? + callbackFn : + LacSync_GenWakeupSyncCaller; + + /* Reset the pending callback counters */ + qatUtilsAtomicSet(0, &pSessionDesc->pendingStatelessCbCount); + qatUtilsAtomicSet(0, &pSessionDesc->pendingStatefulCbCount); + pSessionDesc->pendingDpStatelessCbCount = 0; + + if (CPA_DC_DIR_DECOMPRESS != pSessionData->sessDirection) { + if (CPA_DC_HT_FULL_DYNAMIC == pSessionData->huffType) { + /* Populate the compression section of the content + * descriptor */ + dcCompContentDescPopulate(pService, + pSessionDesc, + contextAddrPhys, + &(pSessionDesc->reqCacheComp), + ICP_QAT_FW_SLICE_XLAT, + DC_COMPRESSION_REQUEST); + + /* Populate the translator section of the content + * descriptor */ + dcTransContentDescPopulate( + &(pSessionDesc->reqCacheComp), + ICP_QAT_FW_SLICE_DRAM_WR); + + if (0 != pService->pInterBuffPtrsArrayPhyAddr) { + pReqCache = &(pSessionDesc->reqCacheComp); + + pReqCache->u1.xlt_pars.inter_buff_ptr = + pService->pInterBuffPtrsArrayPhyAddr; + } + } else { + dcCompContentDescPopulate(pService, + pSessionDesc, + contextAddrPhys, + &(pSessionDesc->reqCacheComp), + ICP_QAT_FW_SLICE_DRAM_WR, + DC_COMPRESSION_REQUEST); + } + } + + /* Populate the compression section of the content descriptor for + * the decompression case or combined */ + if (CPA_DC_DIR_COMPRESS != pSessionData->sessDirection) { + dcCompContentDescPopulate(pService, + pSessionDesc, + contextAddrPhys, + &(pSessionDesc->reqCacheDecomp), + ICP_QAT_FW_SLICE_DRAM_WR, + DC_DECOMPRESSION_REQUEST); + } + + if (CPA_DC_STATEFUL == pSessionData->sessState) { + sessType = ICP_QAT_FW_COMP_STATEFUL_SESSION; + + LAC_OS_BZERO(&pSessionDesc->stateRegistersComp, + sizeof(pSessionDesc->stateRegistersComp)); + + LAC_OS_BZERO(&pSessionDesc->stateRegistersDecomp, + sizeof(pSessionDesc->stateRegistersDecomp)); + } + + /* Get physical address of E2E CRC buffer */ + pSessionDesc->physDataIntegrityCrcs = (icp_qat_addr_width_t) + LAC_OS_VIRT_TO_PHYS_EXTERNAL(pService->generic_service_info, + &pSessionDesc->dataIntegrityCrcs); + if (0 == pSessionDesc->physDataIntegrityCrcs) { + QAT_UTILS_LOG( + "Unable to get the physical address of Data Integrity buffer.\n"); + return CPA_STATUS_FAIL; + } + /* Initialize default CRC parameters */ + pDataIntegrityCrcs = &pSessionDesc->dataIntegrityCrcs; + pDataIntegrityCrcs->crc32 = 0; + pDataIntegrityCrcs->adler32 = 1; + pDataIntegrityCrcs->oCrc32Cpr = DC_INVALID_CRC; + pDataIntegrityCrcs->iCrc32Cpr = DC_INVALID_CRC; + pDataIntegrityCrcs->oCrc32Xlt = DC_INVALID_CRC; + pDataIntegrityCrcs->iCrc32Xlt = DC_INVALID_CRC; + pDataIntegrityCrcs->xorFlags = DC_XOR_FLAGS_DEFAULT; + pDataIntegrityCrcs->crcPoly = DC_CRC_POLY_DEFAULT; + pDataIntegrityCrcs->xorOut = DC_XOR_OUT_DEFAULT; + + /* Initialise seed checksums */ + pSessionDesc->seedSwCrc.swCrcI = 0; + pSessionDesc->seedSwCrc.swCrcO = 0; + + /* Populate the cmdFlags */ + switch (pSessionDesc->autoSelectBestHuffmanTree) { + case CPA_DC_ASB_DISABLED: + break; + case CPA_DC_ASB_STATIC_DYNAMIC: + autoSelectBest = ICP_QAT_FW_COMP_AUTO_SELECT_BEST; + break; + case CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_STORED_HDRS: + autoSelectBest = ICP_QAT_FW_COMP_AUTO_SELECT_BEST; + enhancedAutoSelectBest = ICP_QAT_FW_COMP_ENH_AUTO_SELECT_BEST; + break; + case CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_NO_HDRS: + autoSelectBest = ICP_QAT_FW_COMP_AUTO_SELECT_BEST; + enhancedAutoSelectBest = ICP_QAT_FW_COMP_ENH_AUTO_SELECT_BEST; + disableType0EnhancedAutoSelectBest = + ICP_QAT_FW_COMP_DISABLE_TYPE0_ENH_AUTO_SELECT_BEST; + break; + default: + break; + } + + rpCmdFlags = ICP_QAT_FW_COMP_REQ_PARAM_FLAGS_BUILD( + ICP_QAT_FW_COMP_SOP, + ICP_QAT_FW_COMP_EOP, + ICP_QAT_FW_COMP_BFINAL, + ICP_QAT_FW_COMP_NO_CNV, + ICP_QAT_FW_COMP_NO_CNV_RECOVERY, + ICP_QAT_FW_COMP_CRC_MODE_LEGACY); + + cmdFlags = + ICP_QAT_FW_COMP_FLAGS_BUILD(sessType, + autoSelectBest, + enhancedAutoSelectBest, + disableType0EnhancedAutoSelectBest, + secureRam); + + if (CPA_DC_DIR_DECOMPRESS != pSessionData->sessDirection) { + if (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType) { + dcCmdId = (icp_qat_fw_la_cmd_id_t)( + ICP_QAT_FW_COMP_CMD_DYNAMIC); + } + + pReqCache = &(pSessionDesc->reqCacheComp); + pReqCache->comp_pars.req_par_flags = rpCmdFlags; + pReqCache->comp_pars.crc.legacy.initial_adler = 1; + pReqCache->comp_pars.crc.legacy.initial_crc32 = 0; + + /* Populate header of the common request message */ + SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)pReqCache, + ICP_QAT_FW_COMN_REQ_CPM_FW_COMP, + (uint8_t)dcCmdId, + cmnRequestFlags, + cmdFlags); + } + + if (CPA_DC_DIR_COMPRESS != pSessionData->sessDirection) { + dcCmdId = + (icp_qat_fw_la_cmd_id_t)(ICP_QAT_FW_COMP_CMD_DECOMPRESS); + pReqCache = &(pSessionDesc->reqCacheDecomp); + pReqCache->comp_pars.req_par_flags = rpCmdFlags; + pReqCache->comp_pars.crc.legacy.initial_adler = 1; + pReqCache->comp_pars.crc.legacy.initial_crc32 = 0; + + /* Populate header of the common request message */ + SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)pReqCache, + ICP_QAT_FW_COMN_REQ_CPM_FW_COMP, + (uint8_t)dcCmdId, + cmnRequestFlags, + cmdFlags); + } + + return status; +} + +CpaStatus +cpaDcInitSession(CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle, + CpaDcSessionSetupData *pSessionData, + CpaBufferList *pContextBuffer, + CpaDcCallbackFn callbackFn) +{ + CpaInstanceHandle insHandle = NULL; + sal_compression_service_t *pService = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = dcInstance; + } + + LAC_CHECK_INSTANCE_HANDLE(insHandle); + SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); + + pService = (sal_compression_service_t *)insHandle; + + /* Check if SAL is initialised otherwise return an error */ + SAL_RUNNING_CHECK(pService); + + return dcInitSession(insHandle, + pSessionHandle, + pSessionData, + pContextBuffer, + callbackFn); +} + +CpaStatus +cpaDcResetSession(const CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + CpaInstanceHandle insHandle = NULL; + dc_session_desc_t *pSessionDesc = NULL; + Cpa64U numPendingStateless = 0; + Cpa64U numPendingStateful = 0; + icp_comms_trans_handle trans_handle = NULL; + LAC_CHECK_NULL_PARAM(pSessionHandle); + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); + LAC_CHECK_NULL_PARAM(pSessionDesc); + + if (CPA_TRUE == pSessionDesc->isDcDp) { + insHandle = dcInstance; + } else { + if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = dcInstance; + } + } + LAC_CHECK_NULL_PARAM(insHandle); + SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); + /* Check if SAL is running otherwise return an error */ + SAL_RUNNING_CHECK(insHandle); + if (CPA_TRUE == pSessionDesc->isDcDp) { + trans_handle = ((sal_compression_service_t *)dcInstance) + ->trans_handle_compression_tx; + if (CPA_TRUE == icp_adf_queueDataToSend(trans_handle)) { + /* Process the remaining messages on the ring */ + SalQatMsg_updateQueueTail(trans_handle); + QAT_UTILS_LOG( + "There are remaining messages on the ring\n"); + return CPA_STATUS_RETRY; + } + + /* Check if there are stateless pending requests */ + if (0 != pSessionDesc->pendingDpStatelessCbCount) { + QAT_UTILS_LOG( + "There are %llu stateless DP requests pending.\n", + (unsigned long long) + pSessionDesc->pendingDpStatelessCbCount); + return CPA_STATUS_RETRY; + } + } else { + numPendingStateless = + qatUtilsAtomicGet(&(pSessionDesc->pendingStatelessCbCount)); + numPendingStateful = + qatUtilsAtomicGet(&(pSessionDesc->pendingStatefulCbCount)); + /* Check if there are stateless pending requests */ + if (0 != numPendingStateless) { + QAT_UTILS_LOG( + "There are %llu stateless requests pending.\n", + (unsigned long long)numPendingStateless); + return CPA_STATUS_RETRY; + } + /* Check if there are stateful pending requests */ + if (0 != numPendingStateful) { + QAT_UTILS_LOG( + "There are %llu stateful requests pending.\n", + (unsigned long long)numPendingStateful); + return CPA_STATUS_RETRY; + } + + /* Reset pSessionDesc */ + pSessionDesc->requestType = DC_REQUEST_FIRST; + pSessionDesc->cumulativeConsumedBytes = 0; + if (CPA_DC_ADLER32 == pSessionDesc->checksumType) { + pSessionDesc->previousChecksum = 1; + } else { + pSessionDesc->previousChecksum = 0; + } + } + /* Reset the pending callback counters */ + qatUtilsAtomicSet(0, &pSessionDesc->pendingStatelessCbCount); + qatUtilsAtomicSet(0, &pSessionDesc->pendingStatefulCbCount); + pSessionDesc->pendingDpStatelessCbCount = 0; + if (CPA_DC_STATEFUL == pSessionDesc->sessState) { + LAC_OS_BZERO(&pSessionDesc->stateRegistersComp, + sizeof(pSessionDesc->stateRegistersComp)); + LAC_OS_BZERO(&pSessionDesc->stateRegistersDecomp, + sizeof(pSessionDesc->stateRegistersDecomp)); + } + return status; +} + +CpaStatus +cpaDcRemoveSession(const CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + CpaInstanceHandle insHandle = NULL; + dc_session_desc_t *pSessionDesc = NULL; + Cpa64U numPendingStateless = 0; + Cpa64U numPendingStateful = 0; + icp_comms_trans_handle trans_handle = NULL; + + LAC_CHECK_NULL_PARAM(pSessionHandle); + pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle); + LAC_CHECK_NULL_PARAM(pSessionDesc); + + if (CPA_TRUE == pSessionDesc->isDcDp) { + insHandle = dcInstance; + } else { + if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = dcInstance; + } + } + + LAC_CHECK_NULL_PARAM(insHandle); + SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); + + /* Check if SAL is running otherwise return an error */ + SAL_RUNNING_CHECK(insHandle); + + if (CPA_TRUE == pSessionDesc->isDcDp) { + trans_handle = ((sal_compression_service_t *)insHandle) + ->trans_handle_compression_tx; + + if (CPA_TRUE == icp_adf_queueDataToSend(trans_handle)) { + /* Process the remaining messages on the ring */ + SalQatMsg_updateQueueTail(trans_handle); + QAT_UTILS_LOG( + "There are remaining messages on the ring.\n"); + return CPA_STATUS_RETRY; + } + + /* Check if there are stateless pending requests */ + if (0 != pSessionDesc->pendingDpStatelessCbCount) { + QAT_UTILS_LOG( + "There are %llu stateless DP requests pending.\n", + (unsigned long long) + pSessionDesc->pendingDpStatelessCbCount); + return CPA_STATUS_RETRY; + } + } else { + numPendingStateless = + qatUtilsAtomicGet(&(pSessionDesc->pendingStatelessCbCount)); + numPendingStateful = + qatUtilsAtomicGet(&(pSessionDesc->pendingStatefulCbCount)); + + /* Check if there are stateless pending requests */ + if (0 != numPendingStateless) { + QAT_UTILS_LOG( + "There are %llu stateless requests pending.\n", + (unsigned long long)numPendingStateless); + status = CPA_STATUS_RETRY; + } + + /* Check if there are stateful pending requests */ + if (0 != numPendingStateful) { + QAT_UTILS_LOG( + "There are %llu stateful requests pending.\n", + (unsigned long long)numPendingStateful); + status = CPA_STATUS_RETRY; + } + if ((CPA_DC_STATEFUL == pSessionDesc->sessState) && + (CPA_STATUS_SUCCESS == status)) { + if (CPA_STATUS_SUCCESS != + LAC_SPINLOCK_DESTROY( + &(pSessionDesc->sessionLock))) { + QAT_UTILS_LOG( + "Failed to destory session lock.\n"); + } + } + } + + return status; +} + +CpaStatus +dcGetSessionSize(CpaInstanceHandle dcInstance, + CpaDcSessionSetupData *pSessionData, + Cpa32U *pSessionSize, + Cpa32U *pContextSize) +{ + + CpaStatus status = CPA_STATUS_SUCCESS; + CpaInstanceHandle insHandle = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = dcInstance; + } + + /* Check parameters */ + LAC_CHECK_NULL_PARAM(insHandle); + LAC_CHECK_NULL_PARAM(pSessionData); + LAC_CHECK_NULL_PARAM(pSessionSize); + + if (dcCheckSessionData(pSessionData, insHandle) != CPA_STATUS_SUCCESS) { + return CPA_STATUS_INVALID_PARAM; + } + + /* Get session size for session data */ + *pSessionSize = sizeof(dc_session_desc_t) + LAC_64BYTE_ALIGNMENT + + sizeof(LAC_ARCH_UINT); + + if (NULL != pContextSize) { + status = + dcGetContextSize(insHandle, pSessionData, pContextSize); + + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG( + "Unable to get the context size of the session.\n"); + return CPA_STATUS_FAIL; + } + } + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcGetSessionSize(CpaInstanceHandle dcInstance, + CpaDcSessionSetupData *pSessionData, + Cpa32U *pSessionSize, + Cpa32U *pContextSize) +{ + + LAC_CHECK_NULL_PARAM(pContextSize); + + return dcGetSessionSize(dcInstance, + pSessionData, + pSessionSize, + pContextSize); +} diff --git a/sys/dev/qat/qat_api/common/compression/dc_stats.c b/sys/dev/qat/qat_api/common/compression/dc_stats.c new file mode 100644 index 000000000000..bcd3d61cb3c6 --- /dev/null +++ b/sys/dev/qat/qat_api/common/compression/dc_stats.c @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file dc_stats.c + * + * @ingroup Dc_DataCompression + * + * @description + * Implementation of the Data Compression stats operations. + * + *****************************************************************************/ + +/* + ******************************************************************************* + * Include public/global header files + ******************************************************************************* + */ +#include "cpa.h" +#include "cpa_dc.h" +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" +/* + ******************************************************************************* + * Include private header files + ******************************************************************************* + */ +#include "lac_common.h" +#include "icp_accel_devices.h" +#include "sal_statistics.h" +#include "dc_session.h" +#include "dc_datapath.h" +#include "lac_mem_pools.h" +#include "sal_service_state.h" +#include "sal_types_compression.h" +#include "dc_stats.h" + +CpaStatus +dcStatsInit(sal_compression_service_t *pService) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + pService->pCompStatsArr = + LAC_OS_MALLOC(COMPRESSION_NUM_STATS * sizeof(QatUtilsAtomic)); + + if (pService->pCompStatsArr == NULL) { + status = CPA_STATUS_RESOURCE; + } + + if (CPA_STATUS_SUCCESS == status) { + COMPRESSION_STATS_RESET(pService); + } + + return status; +} + +void +dcStatsFree(sal_compression_service_t *pService) +{ + if (NULL != pService->pCompStatsArr) { + LAC_OS_FREE(pService->pCompStatsArr); + } +} + +CpaStatus +cpaDcGetStats(CpaInstanceHandle dcInstance, CpaDcStats *pStatistics) +{ + sal_compression_service_t *pService = NULL; + CpaInstanceHandle insHandle = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = dcInstance; + } + + pService = (sal_compression_service_t *)insHandle; + + LAC_CHECK_NULL_PARAM(insHandle); + LAC_CHECK_NULL_PARAM(pStatistics); + SAL_RUNNING_CHECK(insHandle); + + SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); + + /* Retrieves the statistics for compression */ + COMPRESSION_STATS_GET(pStatistics, pService); + + return CPA_STATUS_SUCCESS; +} diff --git a/sys/dev/qat/qat_api/common/compression/icp_sal_dc_err.c b/sys/dev/qat/qat_api/common/compression/icp_sal_dc_err.c new file mode 100644 index 000000000000..6b3735b4051b --- /dev/null +++ b/sys/dev/qat/qat_api/common/compression/icp_sal_dc_err.c @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file icp_sal_dc_err.c + * + * @defgroup SalCommon + * + * @ingroup SalCommon + * + *****************************************************************************/ + +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ +#include "cpa.h" +#include "icp_sal.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ +#include "dc_error_counter.h" + +Cpa64U +icp_sal_get_dc_error(Cpa8S dcError) +{ + return getDcErrorCounter(dcError); +} diff --git a/sys/dev/qat/qat_api/common/compression/include/dc_datapath.h b/sys/dev/qat/qat_api/common/compression/include/dc_datapath.h new file mode 100644 index 000000000000..0a6ef7191704 --- /dev/null +++ b/sys/dev/qat/qat_api/common/compression/include/dc_datapath.h @@ -0,0 +1,186 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file dc_datapath.h + * + * @ingroup Dc_DataCompression + * + * @description + * Definition of the Data Compression datapath parameters. + * + ******************* + * **********************************************************/ +#ifndef DC_DATAPATH_H_ +#define DC_DATAPATH_H_ + +#define LAC_QAT_DC_REQ_SZ_LW 32 +#define LAC_QAT_DC_RESP_SZ_LW 8 + +/* Restriction on the source buffer size for compression due to the firmware + * processing */ +#define DC_SRC_BUFFER_MIN_SIZE (15) + +/* Restriction on the destination buffer size for compression due to + * the management of skid buffers in the firmware */ +#define DC_DEST_BUFFER_DYN_MIN_SIZE (128) +#define DC_DEST_BUFFER_STA_MIN_SIZE (64) +/* C62x and C3xxx pcie rev0 devices require an additional 32bytes */ +#define DC_DEST_BUFFER_STA_ADDITIONAL_SIZE (32) + +/* C4xxx device only requires 47 bytes */ +#define DC_DEST_BUFFER_MIN_SIZE (47) + +/* Minimum destination buffer size for decompression */ +#define DC_DEST_BUFFER_DEC_MIN_SIZE (1) + +/* Restriction on the source and destination buffer sizes for compression due + * to the firmware taking 32 bits parameters. The max size is 2^32-1 */ +#define DC_BUFFER_MAX_SIZE (0xFFFFFFFF) + +/* DC Source & Destination buffer type (FLAT/SGL) */ +#define DC_DEFAULT_QAT_PTR_TYPE QAT_COMN_PTR_TYPE_SGL +#define DC_DP_QAT_PTR_TYPE QAT_COMN_PTR_TYPE_FLAT + +/* Offset to first byte of Input Byte Counter (IBC) in state register */ +#define DC_STATE_IBC_OFFSET (8) +/* Size in bytes of input byte counter (IBC) in state register */ +#define DC_IBC_SIZE_IN_BYTES (4) + +/* Offset to first byte to CRC32 in state register */ +#define DC_STATE_CRC32_OFFSET (40) +/* Offset to first byte to output CRC32 in state register */ +#define DC_STATE_OUTPUT_CRC32_OFFSET (48) +/* Offset to first byte to input CRC32 in state register */ +#define DC_STATE_INPUT_CRC32_OFFSET (52) + +/* Offset to first byte of ADLER32 in state register */ +#define DC_STATE_ADLER32_OFFSET (48) + +/* 8 bit mask value */ +#define DC_8_BIT_MASK (0xff) + +/* 8 bit shift position */ +#define DC_8_BIT_SHIFT_POS (8) + +/* Size in bytes of checksum */ +#define DC_CHECKSUM_SIZE_IN_BYTES (4) + +/* Mask used to set the most significant bit to zero */ +#define DC_STATE_REGISTER_ZERO_MSB_MASK (0x7F) + +/* Mask used to keep only the most significant bit and set the others to zero */ +#define DC_STATE_REGISTER_KEEP_MSB_MASK (0x80) + +/* Compression state register word containing the parity bit */ +#define DC_STATE_REGISTER_PARITY_BIT_WORD (5) + +/* Location of the parity bit within the compression state register word */ +#define DC_STATE_REGISTER_PARITY_BIT (7) + +/* size which needs to be reserved before the results field to + * align the results field with the API struct */ +#define DC_API_ALIGNMENT_OFFSET (offsetof(CpaDcDpOpData, results)) + +/* Mask used to check the CompressAndVerify capability bit */ +#define DC_CNV_EXTENDED_CAPABILITY (0x01) + +/* Mask used to check the CompressAndVerifyAndRecover capability bit */ +#define DC_CNVNR_EXTENDED_CAPABILITY (0x100) + +/* Default values for CNV integrity checks, + * those are used to inform hardware of specifying CRC parameters to be used + * when calculating CRCs */ +#define DC_CRC_POLY_DEFAULT 0x04c11db7 +#define DC_XOR_FLAGS_DEFAULT 0xe0000 +#define DC_XOR_OUT_DEFAULT 0xffffffff +#define DC_INVALID_CRC 0x0 + +/** +******************************************************************************* +* @ingroup cpaDc Data Compression +* Compression cookie +* @description +* This cookie stores information for a particular compression perform op. +* This includes various user-supplied parameters for the operation which +* will be needed in our callback function. +* A pointer to this cookie is stored in the opaque data field of the QAT +* message so that it can be accessed in the asynchronous callback. +* @note +* The order of the parameters within this structure is important. It needs +* to match the order of the parameters in CpaDcDpOpData up to the +* pSessionHandle. This allows the correct processing of the callback. +*****************************************************************************/ +typedef struct dc_compression_cookie_s { + Cpa8U dcReqParamsBuffer[DC_API_ALIGNMENT_OFFSET]; + /**< Memory block - was previously reserved for request parameters. + * Now size maintained so following members align with API struct, + * but no longer used for request parameters */ + CpaDcRqResults reserved; + /**< This is reserved for results to correctly align the structure + * to match the one from the data plane API */ + CpaInstanceHandle dcInstance; + /**< Compression instance handle */ + CpaDcSessionHandle pSessionHandle; + /**< Pointer to the session handle */ + icp_qat_fw_comp_req_t request; + /**< Compression request */ + void *callbackTag; + /**< Opaque data supplied by the client */ + dc_session_desc_t *pSessionDesc; + /**< Pointer to the session descriptor */ + CpaDcFlush flushFlag; + /**< Flush flag */ + CpaDcOpData *pDcOpData; + /**< struct containing flags and CRC related data for this session */ + CpaDcRqResults *pResults; + /**< Pointer to result buffer holding consumed and produced data */ + Cpa32U srcTotalDataLenInBytes; + /**< Total length of the source data */ + Cpa32U dstTotalDataLenInBytes; + /**< Total length of the destination data */ + dc_request_dir_t compDecomp; + /**< Used to know whether the request is compression or decompression. + * Useful when defining the session as combined */ + CpaBufferList *pUserSrcBuff; + /**< virtual userspace ptr to source SGL */ + CpaBufferList *pUserDestBuff; + /**< virtual userspace ptr to destination SGL */ +} dc_compression_cookie_t; + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Callback function called for compression and decompression requests in + * asynchronous mode + * + * @description + * Called to process compression and decompression response messages. This + * callback will check for errors, update the statistics and will call the + * user callback + * + * @param[in] pRespMsg Response message + * + *****************************************************************************/ +void dcCompression_ProcessCallback(void *pRespMsg); + +/** +***************************************************************************** +* @ingroup Dc_DataCompression +* Describes CNV and CNVNR modes +* +* @description +* This enum is used to indicate the CNV modes. +* +*****************************************************************************/ +typedef enum dc_cnv_mode_s { + DC_NO_CNV = 0, + /* CNV = FALSE, CNVNR = FALSE */ + DC_CNV, + /* CNV = TRUE, CNVNR = FALSE */ + DC_CNVNR, + /* CNV = TRUE, CNVNR = TRUE */ +} dc_cnv_mode_t; + +#endif /* DC_DATAPATH_H_ */ diff --git a/sys/dev/qat/qat_api/common/compression/include/dc_error_counter.h b/sys/dev/qat/qat_api/common/compression/include/dc_error_counter.h new file mode 100644 index 000000000000..dd1189fd970a --- /dev/null +++ b/sys/dev/qat/qat_api/common/compression/include/dc_error_counter.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file dc_error_counter.h + * + * @ingroup Dc_DataCompression + * + * @description + * Definition of the Data Compression Error Counter parameters. + * + *****************************************************************************/ +#ifndef DC_ERROR_COUNTER_H +#define DC_ERROR_COUNTER_H + +#include "cpa_types.h" +#include "cpa_dc.h" + +#define MAX_DC_ERROR_TYPE 20 + +void dcErrorLog(CpaDcReqStatus dcError); +Cpa64U getDcErrorCounter(CpaDcReqStatus dcError); + +#endif /* DC_ERROR_COUNTER_H */ diff --git a/sys/dev/qat/qat_api/common/compression/include/dc_header_footer.h b/sys/dev/qat/qat_api/common/compression/include/dc_header_footer.h new file mode 100644 index 000000000000..0ec2cc6f3f16 --- /dev/null +++ b/sys/dev/qat/qat_api/common/compression/include/dc_header_footer.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file dc_header_footer.h + * + * @ingroup Dc_DataCompression + * + * @description + * Definition of the Data Compression header and footer parameters. + * + *****************************************************************************/ +#ifndef DC_HEADER_FOOTER_H_ +#define DC_HEADER_FOOTER_H_ + +/* Header and footer sizes for Zlib and Gzip */ +#define DC_ZLIB_HEADER_SIZE (2) +#define DC_GZIP_HEADER_SIZE (10) +#define DC_ZLIB_FOOTER_SIZE (4) +#define DC_GZIP_FOOTER_SIZE (8) + +/* Values used to build the headers for Zlib and Gzip */ +#define DC_GZIP_ID1 (0x1f) +#define DC_GZIP_ID2 (0x8b) +#define DC_GZIP_FILESYSTYPE (0x03) +#define DC_ZLIB_WINDOWSIZE_OFFSET (4) +#define DC_ZLIB_FLEVEL_OFFSET (6) +#define DC_ZLIB_HEADER_OFFSET (31) + +/* Compression level for Zlib */ +#define DC_ZLIB_LEVEL_0 (0) +#define DC_ZLIB_LEVEL_1 (1) +#define DC_ZLIB_LEVEL_2 (2) +#define DC_ZLIB_LEVEL_3 (3) + +/* CM parameter for Zlib */ +#define DC_ZLIB_CM_DEFLATE (8) + +/* Type of Gzip compression */ +#define DC_GZIP_FAST_COMP (4) +#define DC_GZIP_MAX_COMP (2) + +#endif /* DC_HEADER_FOOTER_H_ */ diff --git a/sys/dev/qat/qat_api/common/compression/include/dc_session.h b/sys/dev/qat/qat_api/common/compression/include/dc_session.h new file mode 100644 index 000000000000..5a4961fadd60 --- /dev/null +++ b/sys/dev/qat/qat_api/common/compression/include/dc_session.h @@ -0,0 +1,278 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file dc_session.h + * + * @ingroup Dc_DataCompression + * + * @description + * Definition of the Data Compression session parameters. + * + *****************************************************************************/ +#ifndef DC_SESSION_H +#define DC_SESSION_H + +#include "cpa_dc_dp.h" +#include "icp_qat_fw_comp.h" +#include "sal_qat_cmn_msg.h" + +/* Maximum number of intermediate buffers SGLs for devices + * with a maximum of 6 compression slices */ +#define DC_QAT_MAX_NUM_INTER_BUFFERS_6COMP_SLICES (12) + +/* Maximum number of intermediate buffers SGLs for devices + * with a maximum of 10 max compression slices */ +#define DC_QAT_MAX_NUM_INTER_BUFFERS_10COMP_SLICES (20) + +/* Maximum number of intermediate buffers SGLs for devices + * with a maximum of 24 max compression slices and 32 MEs */ +#define DC_QAT_MAX_NUM_INTER_BUFFERS_24COMP_SLICES (64) + +/* Maximum size of the state registers 64 bytes */ +#define DC_QAT_STATE_REGISTERS_MAX_SIZE (64) + +/* Size of the history window. + * Base 2 logarithm of maximum window size minus 8 */ +#define DC_8K_WINDOW_SIZE (5) +#define DC_16K_WINDOW_SIZE (6) +#define DC_32K_WINDOW_SIZE (7) + +/* Context size */ +#define DC_DEFLATE_MAX_CONTEXT_SIZE (49152) +#define DC_INFLATE_CONTEXT_SIZE (36864) + +#define DC_DEFLATE_EH_MAX_CONTEXT_SIZE (65536) +#define DC_DEFLATE_EH_MIN_CONTEXT_SIZE (49152) +#define DC_INFLATE_EH_CONTEXT_SIZE (34032) + +/* Retrieve the session descriptor pointer from the session context structure + * that the user allocates. The pointer to the internally realigned address + * is stored at the start of the session context that the user allocates */ +#define DC_SESSION_DESC_FROM_CTX_GET(pSession) \ + (dc_session_desc_t *)(*(LAC_ARCH_UINT *)pSession) + +/* Maximum size for the compression part of the content descriptor */ +#define DC_QAT_COMP_CONTENT_DESC_SIZE sizeof(icp_qat_fw_comp_cd_hdr_t) + +/* Maximum size for the translator part of the content descriptor */ +#define DC_QAT_TRANS_CONTENT_DESC_SIZE \ + (sizeof(icp_qat_fw_xlt_cd_hdr_t) + DC_QAT_MAX_TRANS_SETUP_BLK_SZ) + +/* Maximum size of the decompression content descriptor */ +#define DC_QAT_CONTENT_DESC_DECOMP_MAX_SIZE \ + LAC_ALIGN_POW2_ROUNDUP(DC_QAT_COMP_CONTENT_DESC_SIZE, \ + (1 << LAC_64BYTE_ALIGNMENT_SHIFT)) + +/* Maximum size of the compression content descriptor */ +#define DC_QAT_CONTENT_DESC_COMP_MAX_SIZE \ + LAC_ALIGN_POW2_ROUNDUP(DC_QAT_COMP_CONTENT_DESC_SIZE + \ + DC_QAT_TRANS_CONTENT_DESC_SIZE, \ + (1 << LAC_64BYTE_ALIGNMENT_SHIFT)) + +/* Direction of the request */ +typedef enum dc_request_dir_e { + DC_COMPRESSION_REQUEST = 1, + DC_DECOMPRESSION_REQUEST +} dc_request_dir_t; + +/* Type of the compression request */ +typedef enum dc_request_type_e { + DC_REQUEST_FIRST = 1, + DC_REQUEST_SUBSEQUENT +} dc_request_type_t; + +typedef enum dc_block_type_e { + DC_CLEARTEXT_TYPE = 0, + DC_STATIC_TYPE, + DC_DYNAMIC_TYPE +} dc_block_type_t; + +/* Internal data structure supporting end to end data integrity checks. */ +typedef struct dc_integrity_crc_fw_s { + Cpa32U crc32; + /* CRC32 checksum returned for compressed data */ + Cpa32U adler32; + /* ADLER32 checksum returned for compressed data */ + Cpa32U oCrc32Cpr; + /* CRC32 checksum returned for data output by compression accelerator */ + Cpa32U iCrc32Cpr; + /* CRC32 checksum returned for input data to compression accelerator */ + Cpa32U oCrc32Xlt; + /* CRC32 checksum returned for data output by translator accelerator */ + Cpa32U iCrc32Xlt; + /* CRC32 checksum returned for input data to translator accelerator */ + Cpa32U xorFlags; + /* Initialise transactor pCRC controls in state register */ + Cpa32U crcPoly; + /* CRC32 polynomial used by hardware */ + Cpa32U xorOut; + /* CRC32 from XOR stage (Input CRC is xor'ed with value in the state) */ + Cpa32U deflateBlockType; + /* Bit 1 - Bit 0 + * 0 0 -> RAW DATA + Deflate header. + * This will not produced any CRC check because + * the output will not come from the slices. + * It will be a simple copy from input to output + * buffers list. + * 0 1 -> Static deflate block type + * 1 0 -> Dynamic deflate block type + * 1 1 -> Invalid type */ +} dc_integrity_crc_fw_t; + +typedef struct dc_sw_checksums_s { + Cpa32U swCrcI; + Cpa32U swCrcO; +} dc_sw_checksums_t; + +/* Session descriptor structure for compression */ +typedef struct dc_session_desc_s { + Cpa8U stateRegistersComp[DC_QAT_STATE_REGISTERS_MAX_SIZE]; + /**< State registers for compression */ + Cpa8U stateRegistersDecomp[DC_QAT_STATE_REGISTERS_MAX_SIZE]; + /**< State registers for decompression */ + icp_qat_fw_comp_req_t reqCacheComp; + /**< Cache as much as possible of the compression request in a pre-built + * request */ + icp_qat_fw_comp_req_t reqCacheDecomp; + /**< Cache as much as possible of the decompression request in a + * pre-built + * request */ + dc_request_type_t requestType; + /**< Type of the compression request. As stateful mode do not support + * more + * than one in-flight request there is no need to use spinlocks */ + dc_request_type_t previousRequestType; + /**< Type of the previous compression request. Used in cases where there + * the + * stateful operation needs to be resubmitted */ + CpaDcHuffType huffType; + /**< Huffman tree type */ + CpaDcCompType compType; + /**< Compression type */ + CpaDcChecksum checksumType; + /**< Type of checksum */ + CpaDcAutoSelectBest autoSelectBestHuffmanTree; + /**< Indicates if the implementation selects the best Huffman encoding + */ + CpaDcSessionDir sessDirection; + /**< Session direction */ + CpaDcSessionState sessState; + /**< Session state */ + Cpa32U deflateWindowSize; + /**< Window size */ + CpaDcCompLvl compLevel; + /**< Compression level */ + CpaDcCallbackFn pCompressionCb; + /**< Callback function defined for the traditional compression session + */ + QatUtilsAtomic pendingStatelessCbCount; + /**< Keeps track of number of pending requests on stateless session */ + QatUtilsAtomic pendingStatefulCbCount; + /**< Keeps track of number of pending requests on stateful session */ + Cpa64U pendingDpStatelessCbCount; + /**< Keeps track of number of data plane pending requests on stateless + * session */ + struct mtx sessionLock; + /**< Lock used to provide exclusive access for number of stateful + * in-flight + * requests update */ + CpaBoolean isDcDp; + /**< Indicates if the data plane API is used */ + Cpa32U minContextSize; + /**< Indicates the minimum size required to allocate the context buffer + */ + CpaBufferList *pContextBuffer; + /**< Context buffer */ + Cpa32U historyBuffSize; + /**< Size of the history buffer */ + Cpa64U cumulativeConsumedBytes; + /**< Cumulative amount of consumed bytes. Used to build the footer in + * the + * stateful case */ + Cpa32U previousChecksum; + /**< Save the previous value of the checksum. Used to process zero byte + * stateful compression or decompression requests */ + CpaBoolean isSopForCompressionProcessed; + /**< Indicates whether a Compression Request is received in this session + */ + CpaBoolean isSopForDecompressionProcessed; + /**< Indicates whether a Decompression Request is received in this + * session + */ + /**< Data integrity table */ + dc_integrity_crc_fw_t dataIntegrityCrcs; + /**< Physical address of Data integrity buffer */ + CpaPhysicalAddr physDataIntegrityCrcs; + /* Seed checksums structure used to calculate software calculated + * checksums. + */ + dc_sw_checksums_t seedSwCrc; + /* Driver calculated integrity software CRC */ + dc_sw_checksums_t integritySwCrc; +} dc_session_desc_t; + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Initialise a compression session + * + * @description + * This function will initialise a compression session + * + * @param[in] dcInstance Instance handle derived from discovery + * functions + * @param[in,out] pSessionHandle Pointer to a session handle + * @param[in,out] pSessionData Pointer to a user instantiated structure + * containing session data + * @param[in] pContextBuffer Pointer to context buffer + * + * @param[in] callbackFn For synchronous operation this callback + * shall be a null pointer + * + * @retval CPA_STATUS_SUCCESS Function executed successfully + * @retval CPA_STATUS_FAIL Function failed + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in + * @retval CPA_STATUS_RESOURCE Error related to system resources + *****************************************************************************/ +CpaStatus dcInitSession(CpaInstanceHandle dcInstance, + CpaDcSessionHandle pSessionHandle, + CpaDcSessionSetupData *pSessionData, + CpaBufferList *pContextBuffer, + CpaDcCallbackFn callbackFn); + +/** + ***************************************************************************** + * @ingroup Dc_DataCompression + * Get the size of the memory required to hold the session information + * + * @description + * This function will get the size of the memory required to hold the + * session information + * + * @param[in] dcInstance Instance handle derived from discovery + * functions + * @param[in] pSessionData Pointer to a user instantiated structure + * containing session data + * @param[out] pSessionSize On return, this parameter will be the size + * of the memory that will be + * required by cpaDcInitSession() for session + * data. + * @param[out] pContextSize On return, this parameter will be the size + * of the memory that will be required + * for context data. Context data is + * save/restore data including history and + * any implementation specific data that is + * required for a save/restore operation. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully + * @retval CPA_STATUS_FAIL Function failed + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in + *****************************************************************************/ +CpaStatus dcGetSessionSize(CpaInstanceHandle dcInstance, + CpaDcSessionSetupData *pSessionData, + Cpa32U *pSessionSize, + Cpa32U *pContextSize); + +#endif /* DC_SESSION_H */ diff --git a/sys/dev/qat/qat_api/common/compression/include/dc_stats.h b/sys/dev/qat/qat_api/common/compression/include/dc_stats.h new file mode 100644 index 000000000000..357be30107b1 --- /dev/null +++ b/sys/dev/qat/qat_api/common/compression/include/dc_stats.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file dc_stats.h + * + * @ingroup Dc_DataCompression + * + * @description + * Definition of the Data Compression stats parameters. + * + *****************************************************************************/ +#ifndef DC_STATS_H_ +#define DC_STATS_H_ + +/* Number of Compression statistics */ +#define COMPRESSION_NUM_STATS (sizeof(CpaDcStats) / sizeof(Cpa64U)) + +#define COMPRESSION_STAT_INC(statistic, pService) \ + do { \ + if (CPA_TRUE == \ + pService->generic_service_info.stats->bDcStatsEnabled) { \ + qatUtilsAtomicInc( \ + &pService->pCompStatsArr[offsetof(CpaDcStats, \ + statistic) / \ + sizeof(Cpa64U)]); \ + } \ + } while (0) + +/* Macro to get all Compression stats (from internal array of atomics) */ +#define COMPRESSION_STATS_GET(compStats, pService) \ + do { \ + int i; \ + for (i = 0; i < COMPRESSION_NUM_STATS; i++) { \ + ((Cpa64U *)compStats)[i] = \ + qatUtilsAtomicGet(&pService->pCompStatsArr[i]); \ + } \ + } while (0) + +/* Macro to reset all Compression stats */ +#define COMPRESSION_STATS_RESET(pService) \ + do { \ + int i; \ + for (i = 0; i < COMPRESSION_NUM_STATS; i++) { \ + qatUtilsAtomicSet(0, &pService->pCompStatsArr[i]); \ + } \ + } while (0) + +/** +******************************************************************************* +* @ingroup Dc_DataCompression +* Initialises the compression stats +* +* @description +* This function allocates and initialises the stats array to 0 +* +* @param[in] pService Pointer to a compression service structure +* +* @retval CPA_STATUS_SUCCESS initialisation successful +* @retval CPA_STATUS_RESOURCE array allocation failed +* +*****************************************************************************/ +CpaStatus dcStatsInit(sal_compression_service_t *pService); + +/** +******************************************************************************* +* @ingroup Dc_DataCompression +* Frees the compression stats +* +* @description +* This function frees the stats array +* +* @param[in] pService Pointer to a compression service structure +* +* @retval None +* +*****************************************************************************/ +void dcStatsFree(sal_compression_service_t *pService); + +#endif /* DC_STATS_H_ */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_session.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_session.h new file mode 100644 index 000000000000..6ae3c51e7766 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_session.h @@ -0,0 +1,622 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + ***************************************************************************** + * @file lac_session.h + * + * @defgroup LacSym_Session Session + * + * @ingroup LacSym + * + * Definition of symmetric session descriptor structure + * + * @lld_start + * + * @lld_overview + * A session is required for each symmetric operation. The session descriptor + * holds information about the session from when the session is initialised to + * when the session is removed. The session descriptor is used in the + * subsequent perform operations in the paths for both sending the request and + * receiving the response. The session descriptor and any other state + * information required for processing responses from the QAT are stored in an + * internal cookie. A pointer to this cookie is stored in the opaque data + * field of the QAT request. + * + * The user allocates the memory for the session using the size returned from + * \ref cpaCySymSessionCtxGetSize(). Internally this memory is re-aligned on a + * 64 byte boundary for use by the QAT engine. The aligned pointer is saved in + * the first bytes (size of void *) of the session memory. This address + * is then dereferenced in subsequent performs to get access to the session + * descriptor. + * + * <b>LAC Session Init</b>\n The session descriptor is re-aligned and + * populated. This includes populating the content descriptor which contains + * the hardware setup for the QAT engine. The content descriptor is a read + * only structure after session init and a pointer to it is sent to the QAT + * for each perform operation. + * + * <b>LAC Perform </b>\n + * The address for the session descriptor is got by dereferencing the first + * bytes of the session memory (size of void *). For each successful + * request put on the ring, the pendingCbCount for the session is incremented. + * + * <b>LAC Callback </b>\n + * For each successful response the pendingCbCount for the session is + * decremented. See \ref LacSymCb_ProcessCallbackInternal() + * + * <b>LAC Session Remove </b>\n + * The address for the session descriptor is got by dereferencing the first + * bytes of the session memory (size of void *). + * The pendingCbCount for the session is checked to see if it is 0. If it is + * non 0 then there are requests in flight. An error is returned to the user. + * + * <b>Concurrency</b>\n + * A reference count is used to prevent the descriptor being removed + * while there are requests in flight. + * + * <b>Reference Count</b>\n + * - The perform funcion increments the reference count for the session. + * - The callback function decrements the reference count for the session. + * - The Remove function checks the reference count to ensure that it is 0. + * + * @lld_dependencies + * - \ref LacMem "Memory" - Inline memory functions + * - QatUtils: logging, locking & virt to phys translations. + * + * @lld_initialisation + * + * @lld_module_algorithms + * + * @lld_process_context + * + * @lld_end + * + *****************************************************************************/ + +/***************************************************************************/ + +#ifndef LAC_SYM_SESSION_H +#define LAC_SYM_SESSION_H + +/* + * Common alignment attributes to ensure + * hashStatePrefixBuffer is 64-byte aligned + */ +#define ALIGN_START(x) +#define ALIGN_END(x) __attribute__((__aligned__(x))) +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ + +#include "cpa.h" +#include "icp_accel_devices.h" +#include "lac_list.h" +#include "lac_sal_types.h" +#include "sal_qat_cmn_msg.h" +#include "lac_sym_cipher_defs.h" +#include "lac_sym.h" +#include "lac_sym_hash_defs.h" +#include "lac_sym_qat_hash.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ +/** +******************************************************************************* +* @ingroup LacSym_Session +* Symmetric session descriptor +* @description +* This structure stores information about a session +* Note: struct types lac_session_d1_s and lac_session_d2_s are subsets of +* this structure. Elements in all three should retain the same order +* Only this structure is used in the session init call. The other two are +* for determining the size of memory to allocate. +* The comments section of each of the other two structures below show +* the conditions that determine which session context memory size to use. +*****************************************************************************/ +typedef struct lac_session_desc_s { + Cpa8U contentDescriptor[LAC_SYM_QAT_CONTENT_DESC_MAX_SIZE]; + /**< QAT Content Descriptor for this session. + * NOTE: Field must be correctly aligned in memory for access by QAT + * engine + */ + Cpa8U contentDescriptorOptimised[LAC_SYM_OPTIMISED_CD_SIZE]; + /**< QAT Optimised Content Descriptor for this session. + * NOTE: Field must be correctly aligned in memory for access by QAT + * engine + */ + CpaCySymOp symOperation; + /**< type of command to be performed */ + sal_qat_content_desc_info_t contentDescInfo; + /**< info on the content descriptor */ + sal_qat_content_desc_info_t contentDescOptimisedInfo; + /**< info on the optimised content descriptor */ + icp_qat_fw_la_cmd_id_t laCmdId; + /**<Command Id for the QAT FW */ + lac_sym_qat_hash_state_buffer_info_t hashStateBufferInfo; + /**< info on the hash state prefix buffer */ + CpaCySymHashAlgorithm hashAlgorithm; + /**< hash algorithm */ + Cpa32U authKeyLenInBytes; + /**< Authentication key length in bytes */ + CpaCySymHashMode hashMode; + /**< Mode of the hash operation. plain, auth or nested */ + Cpa32U hashResultSize; + /**< size of the digest produced/compared in bytes */ + CpaCySymCipherAlgorithm cipherAlgorithm; + /**< Cipher algorithm and mode */ + Cpa32U cipherKeyLenInBytes; + /**< Cipher key length in bytes */ + CpaCySymCipherDirection cipherDirection; + /**< This parameter determines if the cipher operation is an encrypt or + * a decrypt operation. */ + CpaCySymPacketType partialState; + /**< state of the partial packet. This can be written to by the perform + * because the SpinLock pPartialInFlightSpinlock guarantees that the + * state is accessible in only one place at a time. */ + icp_qat_la_bulk_req_hdr_t reqCacheHdr; + icp_qat_fw_la_key_gen_common_t reqCacheMid; + icp_qat_la_bulk_req_ftr_t reqCacheFtr; + /**< Cache as much as possible of the bulk request in a pre built + * request (header, mid & footer). */ + CpaCySymCbFunc pSymCb; + /**< symmetric function callback pointer */ + union { + QatUtilsAtomic pendingCbCount; + /**< Keeps track of number of pending requests. */ + QatUtilsAtomic pendingDpCbCount; + /**< Keeps track of number of pending DP requests (not thread + * safe)*/ + } u; + struct lac_sym_bulk_cookie_s *pRequestQueueHead; + /**< A fifo list of queued QAT requests. Head points to first queue + * entry */ + struct lac_sym_bulk_cookie_s *pRequestQueueTail; + /**< A fifo list of queued QAT requests. Tail points to last queue entry + */ + struct mtx requestQueueLock; + /**< A lock to protect accesses to the above request queue */ + CpaInstanceHandle pInstance; + /**< Pointer to Crypto instance running this session. */ + CpaBoolean isAuthEncryptOp : 1; + /**< if the algorithm chaining operation is auth encrypt */ + CpaBoolean nonBlockingOpsInProgress : 1; + /**< Flag is set if a non blocking operation is in progress for a + * session. + * If set to false, new requests will be queued until the condition is + * cleared. + * ASSUMPTION: Only one blocking condition per session can exist at any + * time + */ + CpaBoolean internalSession : 1; + /**< Flag which is set if the session was set up internally for DRBG */ + CpaBoolean isDPSession : 1; + /**< Flag which is set if the session was set up for Data Plane */ + CpaBoolean digestVerify : 1; + /**< Session digest verify for data plane and for CCM/GCM for trad + * api. For other cases on trad api this flag is set in each performOp + */ + CpaBoolean digestIsAppended : 1; + /**< Flag indicating whether the digest is appended immediately + * following + * the region over which the digest is computed */ + CpaBoolean isCipher : 1; + /**< Flag indicating whether symOperation includes a cipher operation */ + CpaBoolean isAuth : 1; + /**< Flag indicating whether symOperation includes an auth operation */ + CpaBoolean useSymConstantsTable : 1; + /**< Flag indicating whether the SymConstantsTable can be used or not */ + CpaBoolean useOptimisedContentDesc : 1; + /**< Flag indicating whether to use the optimised CD or not */ + icp_qat_la_bulk_req_hdr_t shramReqCacheHdr; + icp_qat_fw_la_key_gen_common_t shramReqCacheMid; + icp_qat_la_bulk_req_ftr_t shramReqCacheFtr; + /**< Alternative pre-built request (header, mid & footer) + * for use with symConstantsTable. */ + CpaBoolean isPartialSupported : 1; + /**< Flag indicating whether symOperation support partial packet */ + CpaBoolean isSinglePass : 1; + /**< Flag indicating whether symOperation is single pass operation */ + icp_qat_fw_serv_specif_flags laCmdFlags; + /**< Common request - Service specific flags type */ + icp_qat_fw_comn_flags cmnRequestFlags; + /**< Common request flags type */ + icp_qat_fw_ext_serv_specif_flags laExtCmdFlags; + /**< Common request - Service specific flags type */ + icp_qat_la_bulk_req_hdr_t reqSpcCacheHdr; + icp_qat_la_bulk_req_ftr_t reqSpcCacheFtr; + /**< request (header & footer)for use with Single Pass. */ + icp_qat_hw_auth_mode_t qatHashMode; + /**< Hash Mode for the qat slices. Not to be confused with QA-API + * hashMode + */ + void *writeRingMsgFunc; + /**< function which will be called to write ring message */ + Cpa32U aadLenInBytes; + /**< For CCM,GCM and Snow3G cases, this parameter holds the AAD size, + * otherwise it is set to zero */ + ALIGN_START(64) + Cpa8U hashStatePrefixBuffer[LAC_MAX_AAD_SIZE_BYTES] ALIGN_END(64); + /**< hash state prefix buffer used for hash operations - AAD only + * NOTE: Field must be correctly aligned in memory for access by QAT + * engine + */ + Cpa8U hashStatePrefixBufferExt[LAC_MAX_HASH_STATE_BUFFER_SIZE_BYTES - + LAC_MAX_AAD_SIZE_BYTES]; + /**< hash state prefix buffer used for hash operations - Remainder of + * array. + * NOTE: Field must be correctly aligned in memory for access by QAT + * engine + */ + Cpa8U cipherPartialOpState[LAC_CIPHER_STATE_SIZE_MAX]; + /**< Buffer to hold the cipher state for the session (for partial ops). + * NOTE: Field must be correctly aligned in memory for access by QAT + * engine + */ + Cpa8U cipherARC4InitialState[LAC_CIPHER_ARC4_STATE_LEN_BYTES]; + /**< Buffer to hold the initial ARC4 cipher state for the session, which + * is derived from the user-supplied base key during session + * registration. + * NOTE: Field must be correctly aligned in memory for access by QAT + * engine + */ + CpaPhysicalAddr cipherARC4InitialStatePhysAddr; + /**< The physical address of the ARC4 initial state, set at init + ** session time . + */ +} lac_session_desc_t; + +/** +******************************************************************************* +* @ingroup LacSym_Session +* Symmetric session descriptor - d1 +* @description +* This structure stores information about a specific session which +* assumes the following: +* - cipher algorithm is not ARC4 or Snow3G +* - partials not used +* - not AuthEncrypt operation +* - hash mode not Auth or Nested +* - no hashStatePrefixBuffer required +* It is therefore a subset of the standard symmetric session descriptor, +* with a smaller memory footprint +*****************************************************************************/ +typedef struct lac_session_desc_d1_s { + Cpa8U contentDescriptor[LAC_SYM_QAT_CONTENT_DESC_MAX_SIZE]; + /**< QAT Content Descriptor for this session. + * NOTE: Field must be correctly aligned in memory for access by QAT + * engine + */ + Cpa8U contentDescriptorOptimised[LAC_SYM_OPTIMISED_CD_SIZE]; + /**< QAT Optimised Content Descriptor for this session. + * NOTE: Field must be correctly aligned in memory for access by QAT + * engine + */ + CpaCySymOp symOperation; + /**< type of command to be performed */ + sal_qat_content_desc_info_t contentDescInfo; + /**< info on the content descriptor */ + sal_qat_content_desc_info_t contentDescOptimisedInfo; + /**< info on the optimised content descriptor */ + icp_qat_fw_la_cmd_id_t laCmdId; + /**<Command Id for the QAT FW */ + lac_sym_qat_hash_state_buffer_info_t hashStateBufferInfo; + /**< info on the hash state prefix buffer */ + CpaCySymHashAlgorithm hashAlgorithm; + /**< hash algorithm */ + Cpa32U authKeyLenInBytes; + /**< Authentication key length in bytes */ + CpaCySymHashMode hashMode; + /**< Mode of the hash operation. plain, auth or nested */ + Cpa32U hashResultSize; + /**< size of the digest produced/compared in bytes */ + CpaCySymCipherAlgorithm cipherAlgorithm; + /**< Cipher algorithm and mode */ + Cpa32U cipherKeyLenInBytes; + /**< Cipher key length in bytes */ + CpaCySymCipherDirection cipherDirection; + /**< This parameter determines if the cipher operation is an encrypt or + * a decrypt operation. */ + CpaCySymPacketType partialState; + /**< state of the partial packet. This can be written to by the perform + * because the SpinLock pPartialInFlightSpinlock guarantees that that + * the + * state is accessible in only one place at a time. */ + icp_qat_la_bulk_req_hdr_t reqCacheHdr; + icp_qat_fw_la_key_gen_common_t reqCacheMid; + icp_qat_la_bulk_req_ftr_t reqCacheFtr; + /**< Cache as much as possible of the bulk request in a pre built + * request (header, mid & footer). */ + CpaCySymCbFunc pSymCb; + /**< symmetric function callback pointer */ + union { + QatUtilsAtomic pendingCbCount; + /**< Keeps track of number of pending requests. */ + Cpa64U pendingDpCbCount; + /**< Keeps track of number of pending DP requests (not thread + * safe)*/ + } u; + struct lac_sym_bulk_cookie_s *pRequestQueueHead; + /**< A fifo list of queued QAT requests. Head points to first queue + * entry */ + struct lac_sym_bulk_cookie_s *pRequestQueueTail; + /**< A fifo list of queued QAT requests. Tail points to last queue entry + */ + struct mtx requestQueueLock; + /**< A lock to protect accesses to the above request queue */ + CpaInstanceHandle pInstance; + /**< Pointer to Crypto instance running this session. */ + CpaBoolean isAuthEncryptOp : 1; + /**< if the algorithm chaining operation is auth encrypt */ + CpaBoolean nonBlockingOpsInProgress : 1; + /**< Flag is set if a non blocking operation is in progress for a + * session. + * If set to false, new requests will be queued until the condition is + * cleared. + * ASSUMPTION: Only one blocking condition per session can exist at any + * time + */ + CpaBoolean internalSession : 1; + /**< Flag which is set if the session was set up internally for DRBG */ + CpaBoolean isDPSession : 1; + /**< Flag which is set if the session was set up for Data Plane */ + CpaBoolean digestVerify : 1; + /**< Session digest verify for data plane and for CCM/GCM for trad + * api. For other cases on trad api this flag is set in each performOp + */ + CpaBoolean digestIsAppended : 1; + /**< Flag indicating whether the digest is appended immediately + * following + * the region over which the digest is computed */ + CpaBoolean isCipher : 1; + /**< Flag indicating whether symOperation includes a cipher operation */ + CpaBoolean isAuth : 1; + /**< Flag indicating whether symOperation includes an auth operation */ + CpaBoolean useSymConstantsTable : 1; + /**< Flag indicating whether the SymConstantsTable can be used or not */ + CpaBoolean useOptimisedContentDesc : 1; + /**< Flag indicating whether to use the optimised CD or not */ + icp_qat_la_bulk_req_hdr_t shramReqCacheHdr; + icp_qat_fw_la_key_gen_common_t shramReqCacheMid; + icp_qat_la_bulk_req_ftr_t shramReqCacheFtr; + /**< Alternative pre-built request (header, mid & footer) + * for use with symConstantsTable. */ + CpaBoolean isPartialSupported : 1; + /**< Flag indicating whether symOperation support partial packet */ + CpaBoolean isSinglePass : 1; + /**< Flag indicating whether symOperation is single pass operation */ + icp_qat_fw_serv_specif_flags laCmdFlags; + /**< Common request - Service specific flags type */ + icp_qat_fw_comn_flags cmnRequestFlags; + /**< Common request flags type */ + icp_qat_fw_ext_serv_specif_flags laExtCmdFlags; + /**< Common request - Service specific flags type */ + icp_qat_la_bulk_req_hdr_t reqSpcCacheHdr; + icp_qat_la_bulk_req_ftr_t reqSpcCacheFtr; + /**< request (header & footer)for use with Single Pass. */ + icp_qat_hw_auth_mode_t qatHashMode; + /**< Hash Mode for the qat slices. Not to be confused with QA-API + * hashMode + */ + void *writeRingMsgFunc; + /**< function which will be called to write ring message */ +} lac_session_desc_d1_t; + +/** +******************************************************************************* +* @ingroup LacSym_Session +* Symmetric session descriptor - d2 +* @description +* This structure stores information about a specific session which +* assumes the following: +* - authEncrypt only +* - partials not used +* - hasStatePrefixBuffer just contains AAD +* It is therefore a subset of the standard symmetric session descriptor, +* with a smaller memory footprint +*****************************************************************************/ +typedef struct lac_session_desc_d2_s { + Cpa8U contentDescriptor[LAC_SYM_QAT_CONTENT_DESC_MAX_SIZE]; + /**< QAT Content Descriptor for this session. + * NOTE: Field must be correctly aligned in memory for access by QAT + * engine + */ + Cpa8U contentDescriptorOptimised[LAC_SYM_OPTIMISED_CD_SIZE]; + /**< QAT Optimised Content Descriptor for this session. + * NOTE: Field must be correctly aligned in memory for access by QAT + * engine + */ + CpaCySymOp symOperation; + /**< type of command to be performed */ + sal_qat_content_desc_info_t contentDescInfo; + /**< info on the content descriptor */ + sal_qat_content_desc_info_t contentDescOptimisedInfo; + /**< info on the optimised content descriptor */ + icp_qat_fw_la_cmd_id_t laCmdId; + /**<Command Id for the QAT FW */ + lac_sym_qat_hash_state_buffer_info_t hashStateBufferInfo; + /**< info on the hash state prefix buffer */ + CpaCySymHashAlgorithm hashAlgorithm; + /**< hash algorithm */ + Cpa32U authKeyLenInBytes; + /**< Authentication key length in bytes */ + CpaCySymHashMode hashMode; + /**< Mode of the hash operation. plain, auth or nested */ + Cpa32U hashResultSize; + /**< size of the digest produced/compared in bytes */ + CpaCySymCipherAlgorithm cipherAlgorithm; + /**< Cipher algorithm and mode */ + Cpa32U cipherKeyLenInBytes; + /**< Cipher key length in bytes */ + CpaCySymCipherDirection cipherDirection; + /**< This parameter determines if the cipher operation is an encrypt or + * a decrypt operation. */ + CpaCySymPacketType partialState; + /**< state of the partial packet. This can be written to by the perform + * because the SpinLock pPartialInFlightSpinlock guarantees that that + * the + * state is accessible in only one place at a time. */ + icp_qat_la_bulk_req_hdr_t reqCacheHdr; + icp_qat_fw_la_key_gen_common_t reqCacheMid; + icp_qat_la_bulk_req_ftr_t reqCacheFtr; + /**< Cache as much as possible of the bulk request in a pre built + * request (header. mid & footer). */ + CpaCySymCbFunc pSymCb; + /**< symmetric function callback pointer */ + union { + QatUtilsAtomic pendingCbCount; + /**< Keeps track of number of pending requests. */ + Cpa64U pendingDpCbCount; + /**< Keeps track of number of pending DP requests (not thread + * safe)*/ + } u; + struct lac_sym_bulk_cookie_s *pRequestQueueHead; + /**< A fifo list of queued QAT requests. Head points to first queue + * entry */ + struct lac_sym_bulk_cookie_s *pRequestQueueTail; + /**< A fifo list of queued QAT requests. Tail points to last queue entry + */ + struct mtx requestQueueLock; + /**< A lock to protect accesses to the above request queue */ + CpaInstanceHandle pInstance; + /**< Pointer to Crypto instance running this session. */ + CpaBoolean isAuthEncryptOp : 1; + /**< if the algorithm chaining operation is auth encrypt */ + CpaBoolean nonBlockingOpsInProgress : 1; + /**< Flag is set if a non blocking operation is in progress for a + * session. + * If set to false, new requests will be queued until the condition is + * cleared. + * ASSUMPTION: Only one blocking condition per session can exist at any + * time + */ + CpaBoolean internalSession : 1; + /**< Flag which is set if the session was set up internally for DRBG */ + CpaBoolean isDPSession : 1; + /**< Flag which is set if the session was set up for Data Plane */ + CpaBoolean digestVerify : 1; + /**< Session digest verify for data plane and for CCM/GCM for trad + * api. For other cases on trad api this flag is set in each performOp + */ + CpaBoolean digestIsAppended : 1; + /**< Flag indicating whether the digest is appended immediately + * following + * the region over which the digest is computed */ + CpaBoolean isCipher : 1; + /**< Flag indicating whether symOperation includes a cipher operation */ + CpaBoolean isAuth : 1; + /**< Flag indicating whether symOperation includes an auth operation */ + CpaBoolean useSymConstantsTable : 1; + /**< Flag indicating whether the SymConstantsTable can be used or not */ + CpaBoolean useOptimisedContentDesc : 1; + /**< Flag indicating whether to use the optimised CD or not */ + icp_qat_la_bulk_req_hdr_t shramReqCacheHdr; + icp_qat_fw_la_key_gen_common_t shramReqCacheMid; + icp_qat_la_bulk_req_ftr_t shramReqCacheFtr; + /**< Alternative pre-built request (header. mid & footer) + * for use with symConstantsTable. */ + CpaBoolean isPartialSupported : 1; + /**< Flag indicating whether symOperation support partial packet */ + CpaBoolean isSinglePass : 1; + /**< Flag indicating whether symOperation is single pass operation */ + icp_qat_fw_serv_specif_flags laCmdFlags; + /**< Common request - Service specific flags type */ + icp_qat_fw_comn_flags cmnRequestFlags; + /**< Common request flags type */ + icp_qat_fw_ext_serv_specif_flags laExtCmdFlags; + /**< Common request - Service specific flags type */ + icp_qat_la_bulk_req_hdr_t reqSpcCacheHdr; + icp_qat_la_bulk_req_ftr_t reqSpcCacheFtr; + /**< request (header & footer)for use with Single Pass. */ + icp_qat_hw_auth_mode_t qatHashMode; + /**< Hash Mode for the qat slices. Not to be confused with QA-API + * hashMode + */ + void *writeRingMsgFunc; + /**< function which will be called to write ring message */ + Cpa32U aadLenInBytes; + /**< For CCM,GCM and Snow3G cases, this parameter holds the AAD size, + * otherwise it is set to zero */ + ALIGN_START(64) + Cpa8U hashStatePrefixBuffer[LAC_MAX_AAD_SIZE_BYTES] ALIGN_END(64); + /**< hash state prefix buffer used for hash operations - AAD only + * NOTE: Field must be correctly aligned in memory for access by QAT + * engine + */ +} lac_session_desc_d2_t; + +#define LAC_SYM_SESSION_SIZE \ + (sizeof(lac_session_desc_t) + LAC_64BYTE_ALIGNMENT + \ + sizeof(LAC_ARCH_UINT)) +/**< @ingroup LacSym_Session + * Size of the memory that the client has to allocate for a session. Extra + * memory is needed to internally re-align the data. The pointer to the algined + * data is stored at the start of the user allocated memory hence the extra + * space for an LAC_ARCH_UINT */ + +#define LAC_SYM_SESSION_D1_SIZE \ + (sizeof(lac_session_desc_d1_t) + LAC_64BYTE_ALIGNMENT + \ + sizeof(LAC_ARCH_UINT)) +/**< @ingroup LacSym_Session +** Size of the memory that the client has to allocate for a session where : +* - cipher algorithm not ARC4 or Snow3G, no Partials, nonAuthEncrypt. +* Extra memory is needed to internally re-align the data. The pointer to the +* aligned data is stored at the start of the user allocated memory hence the +* extra space for an LAC_ARCH_UINT */ + +#define LAC_SYM_SESSION_D2_SIZE \ + (sizeof(lac_session_desc_d2_t) + LAC_64BYTE_ALIGNMENT + \ + sizeof(LAC_ARCH_UINT)) +/**< @ingroup LacSym_Session +** Size of the memory that the client has to allocate for a session where : +* - authEncrypt, no Partials - so hashStatePrefixBuffer is only AAD +* Extra memory is needed to internally re-align the data. The pointer to the +* aligned data is stored at the start of the user allocated memory hence the +* extra space for an LAC_ARCH_UINT */ + +#define LAC_SYM_SESSION_DESC_FROM_CTX_GET(pSession) \ + (lac_session_desc_t *)(*(LAC_ARCH_UINT *)pSession) +/**< @ingroup LacSym_Session + * Retrieve the session descriptor pointer from the session context structure + * that the user allocates. The pointer to the internally realigned address + * is stored at the start of the session context that the user allocates */ + +/** +******************************************************************************* +* @ingroup LacSym_Session +* This function initializes a session +* +* @description +* This function is called from the LAC session register API functions. +* It validates all input parameters. If an invalid parameter is passed, +* an error is returned to the calling function. If all parameters are valid +* a symmetric session is initialized +* +* @param[in] instanceHandle_in Instance Handle +* @param[in] pSymCb callback function +* @param[in] pSessionSetupData pointer to the strucutre containing the setup +*data +* @param[in] isDpSession CPA_TRUE for a data plane session +* @param[out] pSessionCtx Pointer to session context +* +* +* @retval CPA_STATUS_SUCCESS Function executed successfully. +* @retval CPA_STATUS_FAIL Function failed. +* @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. +* @retval CPA_STATUS_RESOURCE Error related to system resources. +* +*/ + +CpaStatus LacSym_InitSession(const CpaInstanceHandle instanceHandle_in, + const CpaCySymCbFunc pSymCb, + const CpaCySymSessionSetupData *pSessionSetupData, + const CpaBoolean isDpSession, + CpaCySymSessionCtx pSessionCtx); + +#endif /* LAC_SYM_SESSION_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym.h new file mode 100644 index 000000000000..402fe85378a1 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym.h @@ -0,0 +1,356 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym.h + * + * @defgroup LacSym Symmetric + * + * @ingroup Lac + * + * Symmetric component includes cipher, Hash, chained cipher & hash, + * authenticated encryption and key generation. + * + * @lld_start + * @lld_overview + * + * The symmetric component demuliplexes the following crypto operations to + * the appropriate sub-components: cipher, hash, algorithm chaining and + * authentication encryption. It is a common layer between the above + * mentioned components where common resources are allocated and paramater + * checks are done. The operation specific resource allocation and parameter + * checks are done in the sub-component itself. + * + * The symmetric component demultiplexes the session register/deregister + * and perform functions to the appropriate subcomponents. + * + * @lld_dependencies + * - \ref LacSymPartial "Partial Packet Code": This code manages the partial + * packet state for a session. + * - \ref LacBufferDesc "Common Buffer Code" : This code traverses a buffer + * chain to ensure it is valid. + * - \ref LacSymStats "Statistics": Manages statistics for symmetric + * - \ref LacSymQat "Symmetric QAT": The symmetric qat component is + * initialiased by the symmetric component. + * - \ref LacCipher "Cipher" : demultiplex cipher opertions to this component. + * - \ref LacHash "Hash" : demultiplex hash opertions to this component. + * to this component. + * - \ref LacAlgChain "Algorithm Chaining": The algorithm chaining component + * - OSAL : Memory allocation, Mutex's, atomics + * + * @lld_initialisation + * This component is initialied during the LAC initialisation sequence. It + * initialises the session table, statistics, symmetric QAT, initialises the + * hash definitions lookup table, the hash alg supported lookup table and + * registers a callback function with the symmetric response handler to process + * response messages for Cipher, Hash and Algorithm-Chaining requests. + * + * @lld_module_algorithms + * + * @lld_process_context + * Refer to \ref LacHash "Hash" and \ref LacCipher "Cipher" for sequence + * diagrams from the symmetric component through the sub components. + * + * @lld_end + * + ***************************************************************************/ + +/***************************************************************************/ + +#ifndef LAC_SYM_H +#define LAC_SYM_H + +#include "cpa.h" +#include "cpa_cy_sym.h" +#include "cpa_cy_sym_dp.h" +#include "lac_common.h" +#include "lac_mem_pools.h" +#include "lac_sym_cipher_defs.h" +#include "icp_qat_fw_la.h" + +#define LAC_SYM_KEY_TLS_PREFIX_SIZE 128 +/**< Hash Prefix size in bytes for TLS (128 = MAX = SHA2 (384, 512)*/ + +#define LAC_SYM_OPTIMISED_CD_SIZE 64 +/**< The size of the optimised content desc in DRAM*/ + +#define LAC_SYM_KEY_MAX_HASH_STATE_BUFFER (LAC_SYM_KEY_TLS_PREFIX_SIZE * 2) +/**< hash state prefix buffer structure that holds the maximum sized secret */ + +#define LAC_SYM_HASH_BUFFER_LEN 64 +/**< Buffer length to hold 16 byte MD5 key and 20 byte SHA1 key */ + +/* The ARC4 key will not be stored in the content descriptor so we only need to + * reserve enough space for the next biggest cipher setup block. + * Kasumi needs to store 2 keys and to have the size of 2 blocks for fw*/ +#define LAC_SYM_QAT_MAX_CIPHER_SETUP_BLK_SZ \ + (sizeof(icp_qat_hw_cipher_config_t) + 2 * ICP_QAT_HW_KASUMI_KEY_SZ + \ + 2 * ICP_QAT_HW_KASUMI_BLK_SZ) +/**< @ingroup LacSymQat + * Maximum size for the cipher setup block of the content descriptor */ + +#define LAC_SYM_QAT_MAX_HASH_SETUP_BLK_SZ sizeof(icp_qat_hw_auth_algo_blk_t) +/**< @ingroup LacSymQat + * Maximum size for the hash setup block of the content descriptor */ + +#define LAC_SYM_QAT_CONTENT_DESC_MAX_SIZE \ + LAC_ALIGN_POW2_ROUNDUP(LAC_SYM_QAT_MAX_CIPHER_SETUP_BLK_SZ + \ + LAC_SYM_QAT_MAX_HASH_SETUP_BLK_SZ, \ + (1 << LAC_64BYTE_ALIGNMENT_SHIFT)) +/**< @ingroup LacSymQat + * Maximum size of content descriptor. This is incremented to the next multiple + * of 64 so that it can be 64 byte aligned */ + +#define LAC_SYM_QAT_API_ALIGN_COOKIE_OFFSET \ + (offsetof(CpaCySymDpOpData, instanceHandle)) +/**< @ingroup LacSymQat + * Size which needs to be reserved before the instanceHandle field of + * lac_sym_bulk_cookie_s to align it to the correspondent instanceHandle + * in CpaCySymDpOpData */ + +#define LAC_SIZE_OF_CACHE_HDR_IN_LW 6 +/**< Size of Header part of reqCache/shramReqCache */ + +#define LAC_SIZE_OF_CACHE_MID_IN_LW 2 +/**< Size of Mid part (LW14/15) of reqCache/shramReqCache */ + +#define LAC_SIZE_OF_CACHE_FTR_IN_LW 6 +/**< Size of Footer part of reqCache/shramReqCache */ + +#define LAC_SIZE_OF_CACHE_TO_CLEAR_IN_LW 20 +/**< Size of dummy reqCache/shramReqCache to clear */ + +#define LAC_START_OF_CACHE_MID_IN_LW 14 +/**< Starting LW of reqCache/shramReqCache Mid */ + +#define LAC_START_OF_CACHE_FTR_IN_LW 26 +/**< Starting LW of reqCache/shramReqCache Footer */ + +/** + ******************************************************************************* + * @ingroup LacSym + * Symmetric cookie + * + * @description + * This cookie stores information for a particular symmetric perform op. + * This includes the request params, re-aligned Cipher IV, the request + * message sent to the QAT engine, and various user-supplied parameters + * for the operation which will be needed in our callback function. + * A pointer to this cookie is stored in the opaque data field of the QAT + * message so that it can be accessed in the asynchronous callback. + * Cookies for multiple operations on a given session can be linked + * together to allow queuing of requests using the pNext field. + * + * The parameters are placed in order to match the CpaCySymDpOpData + *structure + *****************************************************************************/ +typedef struct lac_sym_bulk_cookie_s { + + /* CpaCySymDpOpData struct so need to keep this here for correct + * alignment*/ + Cpa8U reserved[LAC_SYM_QAT_API_ALIGN_COOKIE_OFFSET]; + /** NOTE: Field must be correctly aligned in memory for access by QAT + * engine + */ + CpaInstanceHandle instanceHandle; + /**< Instance handle for the operation */ + CpaCySymSessionCtx sessionCtx; + /**< Session context */ + void *pCallbackTag; + /**< correlator supplied by the client */ + icp_qat_fw_la_bulk_req_t qatMsg; + /**< QAT request message */ + const CpaCySymOpData *pOpData; + /**< pointer to the op data structure that the user supplied in the + * perform + * operation. The op data is modified in the process callback function + * and the pointer is returned to the user in their callback function */ + CpaBoolean updateSessionIvOnSend; + /**< Boolean flag to indicate if the session cipher IV buffer should be + * updated prior to sending the request */ + CpaBoolean updateUserIvOnRecieve; + /**< Boolean flag to indicate if the user's cipher IV buffer should be + * updated after receiving the response from the QAT */ + CpaBoolean updateKeySizeOnRecieve; +/**< Boolean flag to indicate if the cipher key size should be + * updated after receiving the response from the QAT */ + CpaBufferList *pDstBuffer; + /**< Pointer to destination buffer to hold the data output */ + struct lac_sym_bulk_cookie_s *pNext; + /**< Pointer to next node in linked list (if request is queued) */ +} lac_sym_bulk_cookie_t; + +/** +******************************************************************************* +* @ingroup LacSymKey +* symmetric Key cookie +* @description +* This cookie stores information for a particular keygen perform op. +* This includes a hash content descriptor, request params, hash state +* buffer, and various user-supplied parameters for the operation which +* will be needed in our callback function. +* A pointer to this cookie is stored in the opaque data field of the QAT +* message so that it can be accessed in the asynchronous callback. +*****************************************************************************/ +typedef struct lac_sym_key_cookie_s { + CpaInstanceHandle instanceHandle; + /**< QAT device id supplied by the client */ + void *pCallbackTag; + /**< Mechanism used. TLS, SSL or MGF */ + Cpa8U contentDesc[LAC_SYM_QAT_MAX_HASH_SETUP_BLK_SZ]; + /**< Content descriptor. + **< NOTE: Field must be correctly aligned in memory for access by QAT + * engine */ + union { + icp_qat_fw_la_ssl_key_material_input_t sslKeyInput; + /**< SSL key material input structure */ + icp_qat_fw_la_tls_key_material_input_t tlsKeyInput; + /**< TLS key material input structure */ + icp_qat_fw_la_hkdf_key_material_input_t tlsHKDFKeyInput; + /**< TLS HHKDF key material input structure */ + } u; + /**< NOTE: Field must be correctly aligned in memory for access by QAT + * engine */ + Cpa8U hashStateBuffer[LAC_SYM_KEY_MAX_HASH_STATE_BUFFER]; + /**< hash state prefix buffer + * NOTE: Field must be correctly aligned in memory for access by QAT + * engine + */ + CpaCyGenFlatBufCbFunc pKeyGenCb; + /**< callback function supplied by the client */ + void *pKeyGenOpData; + /**< pointer to the (SSL/TLS) or MGF op data structure that the user + * supplied in the perform operation */ + CpaFlatBuffer *pKeyGenOutputData; + /**< Output data pointer supplied by the client */ + Cpa8U hashKeyBuffer[LAC_SYM_HASH_BUFFER_LEN]; + /**< 36 byte buffer to store MD5 key and SHA1 key */ +} lac_sym_key_cookie_t; + +/** +******************************************************************************* +* @ingroup LacSymNrbg +* symmetric NRBG cookie +* @description +* This cookie stores information for a particular NRBG operation. +* This includes various user-supplied parameters for the operation which +* will be needed in our callback function. +* A pointer to this cookie is stored in the opaque data field of the QAT +* message so that it can be accessed in the asynchronous callback. +*****************************************************************************/ +typedef struct lac_sym_nrbg_cookie_s { + CpaInstanceHandle instanceHandle; + /**< QAT device id supplied by the client */ + void *pCallbackTag; + /**< Opaque data supplied by the client */ + icp_qat_fw_la_trng_test_result_t trngHTResult; + /**< TRNG health test result + **< NOTE: Field must be correctly aligned in memory for access by QAT + * engine */ + icp_qat_fw_la_trng_req_t trngReq; + /**< TRNG request message */ + CpaCyGenFlatBufCbFunc pCb; + /**< Callback function supplied by the client */ + void *pOpData; + /**< Op data pointer supplied by the client */ + CpaFlatBuffer *pOutputData; + /**< Output data pointer supplied by the client */ +} lac_sym_nrbg_cookie_t; + +/** +******************************************************************************* +* @ingroup LacSym +* symmetric cookie +* @description +* used to determine the amount of memory to allocate for the symmetric +* cookie pool. As symmetric, random and key generation shared the same +* pool +*****************************************************************************/ +typedef struct lac_sym_cookie_s { + union { + lac_sym_bulk_cookie_t bulkCookie; + /**< symmetric bulk cookie */ + lac_sym_key_cookie_t keyCookie; + /**< symmetric key cookie */ + lac_sym_nrbg_cookie_t nrbgCookie; + /**< symmetric NRBG cookie */ + } u; + Cpa64U keyContentDescPhyAddr; + Cpa64U keyHashStateBufferPhyAddr; + Cpa64U keySslKeyInputPhyAddr; + Cpa64U keyTlsKeyInputPhyAddr; +} lac_sym_cookie_t; + +typedef struct icp_qat_la_auth_req_params_s { + /** equivalent of LW26 of icp_qat_fw_la_auth_req_params_s */ + union { + uint8_t inner_prefix_sz; + /**< Size in bytes of the inner prefix data */ + + uint8_t aad_sz; + /**< Size in bytes of padded AAD data to prefix to the packet + * for CCM + * or GCM processing */ + } u2; + + uint8_t resrvd1; + /**< reserved */ + + uint8_t hash_state_sz; + /**< Number of quad words of inner and outer hash prefix data to process + * Maximum size is 240 */ + + uint8_t auth_res_sz; + /**< Size in bytes of the authentication result */ +} icp_qat_la_auth_req_params_t; + +/* Header (LW's 0 - 5) of struct icp_qat_fw_la_bulk_req_s */ +typedef struct icp_qat_la_bulk_req_hdr_s { + /**< LWs 0-1 */ + icp_qat_fw_comn_req_hdr_t comn_hdr; + /**< Common request header - for Service Command Id, + * use service-specific Crypto Command Id. + * Service Specific Flags - use Symmetric Crypto Command Flags + * (all of cipher, auth, SSL3, TLS and MGF, + * excluding TRNG - field unused) */ + + /**< LWs 2-5 */ + icp_qat_fw_comn_req_hdr_cd_pars_t cd_pars; + /**< Common Request content descriptor field which points either to a + * content descriptor + * parameter block or contains the service-specific data itself. */ +} icp_qat_la_bulk_req_hdr_t; + +/** Footer (LW's 26 - 31) of struct icp_qat_fw_la_bulk_req_s */ +typedef struct icp_qat_la_bulk_req_ftr_s { + /**< LW 0 - equivalent to LW26 of icp_qat_fw_la_bulk_req_t */ + icp_qat_la_auth_req_params_t serv_specif_rqpars; + /**< Common request service-specific parameter field */ + + /**< LW's 1-5, equivalent to LWs 27-31 of icp_qat_fw_la_bulk_req_s */ + icp_qat_fw_comn_req_cd_ctrl_t cd_ctrl; + /**< Common request content descriptor control block - + * this field is service-specific */ +} icp_qat_la_bulk_req_ftr_t; + +/** + *** + ******************************************************************************* + * @ingroup LacSym + * Compile time check of lac_sym_bulk_cookie_t + * + * @description + * Performs a compile time check of lac_sym_bulk_cookie_t to ensure IA + * assumptions are valid. + * + *****************************************************************************/ +void LacSym_CompileTimeAssertions(void); + +void LacDp_WriteRingMsgFull(CpaCySymDpOpData *pRequest, + icp_qat_fw_la_bulk_req_t *pCurrentQatMsg); +void LacDp_WriteRingMsgOpt(CpaCySymDpOpData *pRequest, + icp_qat_fw_la_bulk_req_t *pCurrentQatMsg); + +#endif /* LAC_SYM_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_alg_chain.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_alg_chain.h new file mode 100644 index 000000000000..1750fd0bebf4 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_alg_chain.h @@ -0,0 +1,294 @@ +/*************************************************************************** + * + * <COPYRIGHT_TAG> + * + ***************************************************************************/ + +/** + ***************************************************************************** + * @file lac_sym_alg_chain.h + * + * @defgroup LacAlgChain Algorithm Chaining + * + * @ingroup LacSym + * + * Interfaces exposed by the Algorithm Chaining Component + * + * @lld_start + * + * @lld_overview + * This is the LAC Algorithm-Chaining feature component. This component + * implements session registration and cleanup functions, and a perform + * function. Statistics are maintained to track requests issued and completed, + * errors incurred, and authentication verification failures. For each + * function the parameters supplied by the client are checked, and then the + * function proceeds if all the parameters are valid. This component also + * incorporates support for Authenticated-Encryption (CCM and GCM) which + * essentially comprises of a cipher operation and a hash operation combined. + * + * This component can combine a cipher operation with a hash operation or just + * simply create a hash only or cipher only operation and is called from the + * LAC Symmetric API component. In turn it calls the LAC Cipher, LAC Hash, and + * LAC Symmetric QAT components. The goal here is to duplicate as little code + * as possible from the Cipher and Hash components. + * + * The cipher and hash operations can be combined in either order, i.e. cipher + * first then hash or hash first then cipher. The client specifies this via + * the algChainOrder field in the session context. This ordering choice is + * stored as part of the session descriptor, so that it is known when a + * perform request is issued. In the case of Authenticated-Encryption, the + * ordering is an implicit part of the CCM or GCM protocol. + * + * When building a content descriptor, as part of session registration, this + * component asks the Cipher and Hash components to build their respective + * parts of the session descriptor. The key aspect here is to provide the + * correct offsets to the Cipher and Hash components for where in the content + * descriptor to write their Config and Hardware Setup blocks. Also the + * Config block in each case must specify the appropriate next slice. + * + * When building request parameters, as part of a perform operation, this + * component asks the Cipher and Hash components to build their respective + * parts of the request parameters block. Again the key aspect here is to + * provide the correct offsets to the Cipher and Hash components for where in + * the request parameters block to write their parameters. Also the request + * parameters block in each case must specify the appropriate next slice. + * + * Parameter checking for session registration and for operation perform is + * mostly delegated to the Cipher and Hash components. There are a few + * extra checks that this component must perform: check the algChainOrder + * parameter, ensure that CCM/GCM are specified for hash/cipher algorithms + * as appropriate, and ensure that requests are for full packets (partial + * packets are not supported for Algorithm-Chaining). + * + * The perform operation allocates a cookie to capture information required + * in the request callback. This cookie is then freed in the callback. + * + * @lld_dependencies + * - \ref LacCipher "Cipher" : For taking care of the cipher aspects of + * session registration and operation perform + * - \ref LacHash "Hash" : For taking care of the hash aspects of session + * registration and operation perform + * - \ref LacSymCommon "Symmetric Common" : statistics. + * - \ref LacSymQat "Symmetric QAT": To build the QAT request message, + * request param structure, and populate the content descriptor. Also + * for registering a callback function to process the QAT response. + * - \ref QatComms "QAT Comms" : For sending messages to the QAT, and for + * setting the response callback + * - \ref LacMem "Mem" : For memory allocation and freeing, virtual/physical + * address translation, and translating between scalar and pointer types + * - OSAL : For atomics and locking + * + * @lld_module_algorithms + * This component builds up a chain of slices at session init time + * and stores it in the session descriptor. This is used for building up the + * content descriptor at session init time and the request parameters structure + * in the perform operation. + * + * The offsets for the first slice are updated so that the second slice adds + * its configuration information after that of the first slice. The first + * slice also configures the next slice appropriately. + * + * This component is very much hard-coded to just support cipher+hash or + * hash+cipher. It should be quite possible to extend this idea to support + * an arbitrary chain of commands, by building up a command chain that can + * be traversed in order to build up the appropriate configuration for the + * QAT. This notion should be looked at in the future if other forms of + * Algorithm-Chaining are desired. + * + * @lld_process_context + * + * @lld_end + * + *****************************************************************************/ + +/*****************************************************************************/ + +#ifndef LAC_SYM_ALG_CHAIN_H +#define LAC_SYM_ALG_CHAIN_H + +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ + +#include "cpa.h" +#include "cpa_cy_sym.h" +#include "lac_session.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ + +/* Macro for checking if zero length buffer are supported + * only for cipher is AES-GCM and hash are AES-GCM/AES-GMAC */ +#define IS_ZERO_LENGTH_BUFFER_SUPPORTED(cipherAlgo, hashAlgo) \ + (CPA_CY_SYM_CIPHER_AES_GCM == cipherAlgo && \ + (CPA_CY_SYM_HASH_AES_GMAC == hashAlgo || \ + CPA_CY_SYM_HASH_AES_GCM == hashAlgo)) + +/** +******************************************************************************* +* @ingroup LacAlgChain +* This function registers a session for an Algorithm-Chaining operation. +* +* @description +* This function is called from the LAC session register API function for +* Algorithm-Chaining operations. It validates all input parameters. If +* an invalid parameter is passed, an error is returned to the calling +* function. If all parameters are valid an Algorithm-Chaining session is +* registered. +* +* @param[in] instanceHandle Instance Handle +* +* @param[in] pSessionCtx Pointer to session context which contains +* parameters which are static for a given +* cryptographic session such as operation type, +* mechanisms, and keys for cipher and/or digest +* operations. +* @param[out] pSessionDesc Pointer to session descriptor +* +* @retval CPA_STATUS_SUCCESS Function executed successfully. +* @retval CPA_STATUS_FAIL Function failed. +* @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. +* @retval CPA_STATUS_RESOURCE Error related to system resources. +* +* @see cpaCySymInitSession() +* +*****************************************************************************/ +CpaStatus LacAlgChain_SessionInit(const CpaInstanceHandle instanceHandle, + const CpaCySymSessionSetupData *pSessionCtx, + lac_session_desc_t *pSessionDesc); + +/** +******************************************************************************* +* @ingroup LacAlgChain +* Data path function for the Algorithm-Chaining component +* +* @description +* This function gets called from cpaCySymPerformOp() which is the +* symmetric LAC API function. It is the data path function for the +* Algorithm-Chaining component. It does the parameter checking on the +* client supplied parameters and if the parameters are valid, the +* operation is performed and a request sent to the QAT, otherwise an +* error is returned to the client. +* +* @param[in] instanceHandle Instance Handle +* +* @param[in] pSessionDesc Pointer to session descriptor +* @param[in] pCallbackTag The application's context for this call +* @param[in] pOpData Pointer to a structure containing request +* parameters. The client code allocates the memory for +* this structure. This component takes ownership of +* the memory until it is returned in the callback. +* +* @param[in] pSrcBuffer Source Buffer List +* @param[out] pDstBuffer Destination Buffer List +* @param[out] pVerifyResult Verify Result +* +* @retval CPA_STATUS_SUCCESS Function executed successfully. +* @retval CPA_STATUS_FAIL Function failed. +* @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. +* @retval CPA_STATUS_RESOURCE Error related to system resource. +* +* @see cpaCySymPerformOp() +* +*****************************************************************************/ +CpaStatus LacAlgChain_Perform(const CpaInstanceHandle instanceHandle, + lac_session_desc_t *pSessionDesc, + void *pCallbackTag, + const CpaCySymOpData *pOpData, + const CpaBufferList *pSrcBuffer, + CpaBufferList *pDstBuffer, + CpaBoolean *pVerifyResult); + +/** +******************************************************************************* +* @ingroup LacAlgChain +* This function is used to update cipher key, as specified in provided +* input. +* +* @description +* This function is called from the LAC session register API function for +* Algorithm-Chaining operations. It validates all input parameters. If +* an invalid parameter is passed, an error is returned to the calling +* function. If all parameters are valid an Algorithm-Chaining session is +* updated. +* +* @threadSafe +* No +* +* @param[in] pSessionDesc Pointer to session descriptor +* @param[in] pCipherKey Pointer to new cipher key. +* +* @retval CPA_STATUS_SUCCESS Function executed successfully. +* @retval CPA_STATUS_FAIL Function failed. +* @retval CPA_STATUS_RETRY Resubmit the request. +* @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. +* @retval CPA_STATUS_UNSUPPORTED Function is not supported. +* +*****************************************************************************/ +CpaStatus LacAlgChain_SessionCipherKeyUpdate(lac_session_desc_t *pSessionDesc, + Cpa8U *pCipherKey); + +/** +******************************************************************************* +* @ingroup LacAlgChain +* This function is used to update authentication key, as specified in +* provided input. +* +* @description +* This function is called from the LAC session register API function for +* Algorithm-Chaining operations. It validates all input parameters. If +* an invalid parameter is passed, an error is returned to the calling +* function. If all parameters are valid an Algorithm-Chaining session is +* updated. +* +* @threadSafe +* No +* +* @param[in] pSessionDesc Pointer to session descriptor +* @param[in] pCipherKey Pointer to new authentication key. +* +* @retval CPA_STATUS_SUCCESS Function executed successfully. +* @retval CPA_STATUS_FAIL Function failed. +* @retval CPA_STATUS_RETRY Resubmit the request. +* @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. +* @retval CPA_STATUS_UNSUPPORTED Function is not supported. +* +*****************************************************************************/ +CpaStatus LacAlgChain_SessionAuthKeyUpdate(lac_session_desc_t *pSessionDesc, + Cpa8U *pAuthKey); + +/** +******************************************************************************* +* @ingroup LacAlgChain +* This function is used to update AAD length as specified in provided +* input. +* +* @description +* This function is called from the LAC session register API function for +* Algorithm-Chaining operations. It validates all input parameters. If +* an invalid parameter is passed, an error is returned to the calling +* function. If all parameters are valid an Algorithm-Chaining session is +* updated. +* +* @threadSafe +* No +* +* @param[in] pSessionDesc Pointer to session descriptor +* @param[in] newAADLength New AAD length. +* +* @retval CPA_STATUS_SUCCESS Function executed successfully. +* @retval CPA_STATUS_FAIL Function failed. +* @retval CPA_STATUS_RETRY Resubmit the request. +* @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. +* @retval CPA_STATUS_UNSUPPORTED Function is not supported. +* +*****************************************************************************/ +CpaStatus LacAlgChain_SessionAADUpdate(lac_session_desc_t *pSessionDesc, + Cpa32U newAADLength); + +#endif /* LAC_SYM_ALG_CHAIN_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_auth_enc.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_auth_enc.h new file mode 100644 index 000000000000..76e5e53c38a8 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_auth_enc.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + ***************************************************************************** + * @file lac_sym_auth_enc.h + * + * @defgroup LacAuthEnc Authenticated Encryption + * + * @ingroup LacSym + * + * @description + * Authenticated encryption specific functionality. + * For CCM related code NIST SP 800-38C is followed. + * For GCM related code NIST SP 800-38D is followed. + * + ***************************************************************************/ +#ifndef LAC_SYM_AUTH_ENC_H_ +#define LAC_SYM_AUTH_ENC_H_ + +/* This define for CCM describes constant sum of n and q */ +#define LAC_ALG_CHAIN_CCM_NQ_CONST 15 + +/* These defines for CCM describe maximum and minimum + * length of nonce in bytes*/ +#define LAC_ALG_CHAIN_CCM_N_LEN_IN_BYTES_MAX 13 +#define LAC_ALG_CHAIN_CCM_N_LEN_IN_BYTES_MIN 7 + +/** + * @ingroup LacAuthEnc + * This function applies any necessary padding to additional authentication data + * pointed by pAdditionalAuthData field of pOpData as described in + * NIST SP 800-38D + * + * @param[in] pSessionDesc Pointer to the session descriptor + * @param[in,out] pAdditionalAuthData Pointer to AAD + * + * @retval CPA_STATUS_SUCCESS Operation finished successfully + * + * @pre pAdditionalAuthData has been param checked + * + */ +void LacSymAlgChain_PrepareGCMData(lac_session_desc_t *pSessionDesc, + Cpa8U *pAdditionalAuthData); + +/** + * @ingroup LacAuthEnc + * This function prepares param checks iv and aad for CCM + * + * @param[in,out] pAdditionalAuthData Pointer to AAD + * @param[in,out] pIv Pointer to IV + * @param[in] messageLenToCipherInBytes Size of the message to cipher + * @param[in] ivLenInBytes Size of the IV + * + * @retval CPA_STATUS_SUCCESS Operation finished successfully + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed + * + */ +CpaStatus LacSymAlgChain_CheckCCMData(Cpa8U *pAdditionalAuthData, + Cpa8U *pIv, + Cpa32U messageLenToCipherInBytes, + Cpa32U ivLenInBytes); + +/** + * @ingroup LacAuthEnc + * This function prepares Ctr0 and B0-Bn blocks for CCM algorithm as described + * in NIST SP 800-38C. Ctr0 block is placed in pIv field of pOpData and B0-BN + * blocks are placed in pAdditionalAuthData. + * + * @param[in] pSessionDesc Pointer to the session descriptor + * @param[in,out] pAdditionalAuthData Pointer to AAD + * @param[in,out] pIv Pointer to IV + * @param[in] messageLenToCipherInBytes Size of the message to cipher + * @param[in] ivLenInBytes Size of the IV + * + * @retval none + * + * @pre parameters have been checked using LacSymAlgChain_CheckCCMData() + */ +void LacSymAlgChain_PrepareCCMData(lac_session_desc_t *pSessionDesc, + Cpa8U *pAdditionalAuthData, + Cpa8U *pIv, + Cpa32U messageLenToCipherInBytes, + Cpa32U ivLenInBytes); + +#endif /* LAC_SYM_AUTH_ENC_H_ */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_cb.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_cb.h new file mode 100644 index 000000000000..5332f8aab510 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_cb.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_cb.h + * + * @defgroup LacSymCb Symmetric callback functions + * + * @ingroup LacSym + * + * Functions to assist with callback processing for the symmetric component + ***************************************************************************/ + +#ifndef LAC_SYM_CB_H +#define LAC_SYM_CB_H + +/** + ***************************************************************************** + * @ingroup LacSym + * Dequeue pending requests + * @description + * This function is called by a callback function of a blocking + * operation (either a partial packet or a hash precompute operaion) + * in softIRQ context. It dequeues requests for the following reasons: + * 1. All pre-computes that happened when initialising a session + * have completed. Dequeue any requests that were queued on the + * session while waiting for the precompute operations to complete. + * 2. A partial packet request has completed. Dequeue any partials + * that were queued for this session while waiting for a previous + * partial to complete. + * + * @param[in] pSessionDesc Pointer to the session descriptor + * + * @return CpaStatus + * + ****************************************************************************/ +CpaStatus LacSymCb_PendingReqsDequeue(lac_session_desc_t *pSessionDesc); + +/** + ***************************************************************************** + * @ingroup LacSym + * Register symmetric callback funcion handlers + * + * @description + * This function registers the symmetric callback handler functions with + * the main symmetric callback handler function + * + * @return None + * + ****************************************************************************/ +void LacSymCb_CallbacksRegister(void); + +#endif /* LAC_SYM_CB_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_cipher.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_cipher.h new file mode 100644 index 000000000000..822e9ce03f94 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_cipher.h @@ -0,0 +1,312 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + ***************************************************************************** + * @file lac_sym_cipher.h + * + * @defgroup LacCipher Cipher + * + * @ingroup LacSym + * + * API functions of the cipher component + * + * @lld_start + * @lld_overview + * There is a single \ref icp_LacSym "Symmetric LAC API" for hash, cipher, + * auth encryption and algorithm chaining. This API is implemented by the + * \ref LacSym "Symmetric" module. It demultiplexes calls to this API into + * their basic operation and does some common parameter checking and deals + * with accesses to the session table. + * + * The cipher component supports data encryption/decryption using the AES, DES, + * and Triple-DES cipher algorithms, in ECB, CBC and CTR modes. The ARC4 stream + * cipher algorithm is also supported. Data may be provided as a full packet, + * or as a sequence of partial packets. The result of the operation can be + * written back to the source buffer (in-place) or to a seperate output buffer + * (out-of-place). Data must be encapsulated in ICP buffers. + * + * The cipher component is responsible for implementing the cipher-specific + * functionality for registering and de-registering a session, for the perform + * operation and for processing the QAT responses to cipher requests. Statistics + * are maintained for cipher in the symmetric \ref CpaCySymStats64 "stats" + * structure. This module has been seperated out into two. The cipher QAT module + * deals entirely with QAT data structures. The cipher module itself has minimal + * exposure to the QAT data structures. + * + * @lld_dependencies + * - \ref LacCommon + * - \ref LacSymQat "Symmetric QAT": Hash uses the lookup table provided by + * this module to validate user input. Hash also uses this module to build + * the hash QAT request message, request param structure, populate the + * content descriptor, allocate and populate the hash state prefix buffer. + * Hash also registers its function to process the QAT response with this + * module. + * - OSAL : For memory functions, atomics and locking + * + * @lld_module_algorithms + * In general, all the cipher algorithms supported by this component are + * implemented entirely by the QAT. However, in the case of the ARC4 algorithm, + * it was deemed more efficient to carry out some processing on IA. During + * session registration, an initial state is derived from the base key provided + * by the user, using a simple ARC4 Key Scheduling Algorithm (KSA). Then the + * base key is discarded, but the state is maintained for the duration of the + * session. + * + * The ARC4 key scheduling algorithm (KSA) is specified as follows + * (taken from http://en.wikipedia.org/wiki/RC4_(cipher)): + * \code + * for i from 0 to 255 + * S[i] := i + * endfor + * j := 0 + * for i from 0 to 255 + * j := (j + S[i] + key[i mod keylength]) mod 256 + * swap(S[i],S[j]) + * endfor + * \endcode + * + * On registration of a new ARC4 session, the user provides a base key of any + * length from 1 to 256 bytes. This algorithm produces the initial ARC4 state + * (key matrix + i & j index values) from that base key. This ARC4 state is + * used as input for each ARC4 cipher operation in that session, and is updated + * by the QAT after each operation. The ARC4 state is stored in a session + * descriptor, and it's memory is freed when the session is deregistered. + * + * <b>Block Vs. Stream Ciphers</b>\n + * Block ciphers are treated slightly differently than Stream ciphers by this + * cipher component. Supported stream ciphers consist of AES and + * TripleDES algorithms in CTR mode, and ARC4. The 2 primary differences are: + * - Data buffers for block ciphers are required to be a multiple of the + * block size defined for the algorithm (e.g. 8 bytes for DES). For stream + * ciphers, there is no such restriction. + * - For stream ciphers, decryption is performed by setting the QAT hardware + * to encryption mode. + * + * <b>Memory address alignment of data buffers </b>\n + * The QAT requires that most data buffers are aligned on an 8-byte memory + * address boundary (64-byte boundary for optimum performance). For Cipher, + * this applies to the cipher key buffer passed in the Content Descriptor, + * and the IV/State buffer passed in the Request Parameters block in each + * request. Both of these buffers are provided by the user. It does not + * apply to the cipher source/destination data buffers. + * Alignment of the key buffer is ensured because the key is always copied + * from the user provided buffer into a new (aligned) buffer for the QAT + * (the hardware setup block, which configures the QAT slice). This is done + * once only during session registration, and the user's key buffer can be + * effectively discarded after that. + * The IV/State buffer is provided per-request by the user, so it is recommended + * to the user to provide aligned buffers for optimal performance. In the case + * where an unaligned buffer is provided, a new temporary buffer is allocated + * and the user's IV/State data is copied into this buffer. The aligned buffer + * is then passed to the QAT in the request. In the response callback, if the + * IV was updated by the QAT, the contents are copied back to the user's buffer + * and the temporary buffer is freed. + * + * @lld_process_context + * + * Session Register Sequence Diagram: For ARC4 cipher algorithm + * \msc + * APP [label="Application"], SYM [label="Symmetric LAC"], + * Achain [label="Alg chain"], Cipher, SQAT [label="Symmetric QAT"]; + * + * APP=>SYM [ label = "cpaCySymInitSession(cbFunc)", + * URL="\ref cpaCySymInitSession()"] ; + * SYM=>SYM [ label = "LacSymSession_ParamCheck()", + * URL="\ref LacSymSession_ParamCheck()"]; + * SYM=>Achain [ label = "LacAlgChain_SessionInit()", + * URL="\ref LacAlgChain_SessionInit()"]; + * Achain=>Cipher [ label = "LacCipher_SessionSetupDataCheck()", + * URL="\ref LacCipher_SessionSetupDataCheck()"]; + * Achain<<Cipher [ label="return"]; + * Achain=>SQAT [ label = "LacSymQat_CipherContentDescPopulate()", + * URL="\ref LacSymQat_CipherContentDescPopulate()"]; + * Achain<<SQAT [ label="return"]; + * Achain=>SQAT [ label = "LacSymQat_CipherArc4StateInit()", + * URL="\ref LacSymQat_CipherArc4StateInit()"]; + * Achain<<SQAT [ label="return"]; + * SYM<<Achain [ label = "status" ]; + * SYM=>SYM [label = "LAC_SYM_STAT_INC", URL="\ref LAC_SYM_STAT_INC"]; + * APP<<SYM [label = "status"]; + * \endmsc + * + * Perform Sequence Diagram: TripleDES CBC-mode encryption, in-place full + *packet, asynchronous mode \msc APP [label="Application"], SYM + *[label="Symmetric LAC"], SC [label="Symmetric Common"], Achain [label="Alg + *chain"], Cipher, SQAT [label="Symmetric QAT"], BUF [label="LAC Buffer Desc"], + *SYMQ [label="Symmetric Queue"], SYMCB [label="Symmetric Callback"], LMP + *[label="LAC Mem Pool"], QATCOMMS [label="QAT Comms"]; + * + * APP=>SYM [ label = "cpaCySymPerformOp()", + * URL="\ref cpaCySymPerformOp()"] ; + * SYM=>SYM [ label = "LacSym_Perform()", + * URL="\ref LacSym_Perform()"]; + * SYM=>SYM [ label = "LacSymPerform_BufferParamCheck()", + * URL="\ref LacSymPerform_BufferParamCheck()"]; + * SYM<<SYM [ label = "status"]; + * SYM=>Achain [ label = "LacAlgChain_Perform()", + * URL="\ref LacCipher()"]; + * Achain=>Cipher [ label = "LacCipher_PerformParamCheck()", + * URL="\ref LacCipher_PerformParamCheck()"]; + * Achain<<Cipher [ label="status"]; + * Achain=>LMP [label="Lac_MemPoolEntryAlloc()", + * URL="\ref Lac_MemPoolEntryAlloc()"]; + * Achain<<LMP [label="return"]; + * Achain=>Cipher [ label = "LacCipher_PerformIvCheckAndAlign()", + * URL="\ref LacCipher_PerformIvCheckAndAlign()"]; + * Achain<<Cipher [ label="status"]; + * Achain=>SQAT [ label = "LacSymQat_CipherRequestParamsPopulate()", + * URL="\ref LacSymQat_CipherRequestParamsPopulate()"]; + * Achain<<SQAT [ label="return"]; + * Achain=>BUF [ label = "LacBuffDesc_BufferListDescWrite()", + * URL = "\ref LacBuffDesc_BufferListDescWrite()"]; + * Achain<<BUF [ label="return"]; + * Achain=>SQAT [ label = "SalQatMsg_CmnMsgAndReqParamsPopulate()", + * URL="\ref SalQatMsg_CmnMsgAndReqParamsPopulate()"]; + * Achain<<SQAT [ label="return"]; + * Achain=>SYMQ [ label = "LacSymQueue_RequestSend()", + * URL="\ref LacSymQueue_RequestSend()"]; + * SYMQ=>QATCOMMS [ label = "QatComms_MsgSend()", + * URL="\ref QatComms_MsgSend()"]; + * SYMQ<<QATCOMMS [ label="status"]; + * Achain<<SYMQ [ label="status"]; + * SYM<<Achain[ label="status"]; + * SYM=>SYM [ label = "LacSym_PartialPacketStateUpdate()", + * URL="\ref LacSym_PartialPacketStateUpdate()"]; + * SYM<<SYM [ label = "return"]; + * SYM=>SC [label = "LAC_SYM_STAT_INC", URL="\ref LAC_SYM_STAT_INC"]; + * SYM<<SC [ label="return"]; + * SYM<<SYM [ label = "status"]; + * APP<<SYM [label = "status"]; + * ... [label = "QAT processing the request and generates response"]; + * ...; + * QATCOMMS=>QATCOMMS [label ="QatComms_ResponseMsgHandler()", + * URL="\ref QatComms_ResponseMsgHandler()"]; + * QATCOMMS=>SQAT [label ="LacSymQat_SymRespHandler()", + * URL="\ref LacSymQat_SymRespHandler()"]; + * SQAT=>SYMCB [label="LacSymCb_ProcessCallback()", + * URL="\ref LacSymCb_ProcessCallback()"]; + * SYMCB=>SYMCB [label="LacSymCb_ProcessCallbackInternal()", + * URL="\ref LacSymCb_ProcessCallbackInternal()"]; + * SYMCB=>LMP [label="Lac_MemPoolEntryFree()", + * URL="\ref Lac_MemPoolEntryFree()"]; + * SYMCB<<LMP [label="return"]; + * SYMCB=>SC [label = "LAC_SYM_STAT_INC", URL="\ref LAC_SYM_STAT_INC"]; + * SYMCB<<SC [label = "return"]; + * SYMCB=>APP [label="cbFunc"]; + * SYMCB<<APP [label="return"]; + * SQAT<<SYMCB [label="return"]; + * QATCOMMS<<SQAT [label="return"]; + * \endmsc + * + * #See the sequence diagram for cpaCySymInitSession() + * + * @lld_end + * + *****************************************************************************/ + +/***************************************************************************/ + +#ifndef LAC_SYM_CIPHER_H +#define LAC_SYM_CIPHER_H + +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ + +#include "cpa.h" +#include "cpa_cy_sym.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ + +#include "lac_session.h" +#include "lac_sym.h" + +/* + * WARNING: There are no checks done on the parameters of the functions in + * this file. The expected values of the parameters are documented and it is + * up to the caller to provide valid values. + */ + +/***************************************************************************/ + +/** + ***************************************************************************** + * @ingroup LacCipher + * Cipher session setup data check + * + * @description + * This function will check any algorithm-specific fields + * in the session cipher setup data structure + * + * @param[in] pCipherSetupData Pointer to session cipher context + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter. + * + *****************************************************************************/ +CpaStatus LacCipher_SessionSetupDataCheck( + const CpaCySymCipherSetupData *pCipherSetupData); + +/** +******************************************************************************* +* @ingroup LacCipher +* Function that checks the perform common parameters for cipher +* +* @description +* This function checks the perform parameters for cipher operations +* +* @param[in] cipherAlgorithm read only pointer to cipher context structure +* +* @param[in] pOpData read only pointer to user-supplied data for this +* cipher operation +* @param[in] packetLen read only length of data in buffer +* +* @retval CPA_STATUS_SUCCESS Success +* @retval CPA_STATUS_INVALID_PARAM Invalid parameter +* +*****************************************************************************/ +CpaStatus LacCipher_PerformParamCheck(CpaCySymCipherAlgorithm cipherAlgorithm, + const CpaCySymOpData *pOpData, + const Cpa64U packetLen); + +/** + ***************************************************************************** + * @ingroup LacCipher + * Cipher perform IV check + * + * @description + * This function will perform algorithm-specific checks on the + * cipher Initialisation Vector data provided by the user. + * + * @param[in] pCbCookie Pointer to struct containing internal cookie + * data for the operation + * @param[in] qatPacketType QAT partial packet type (start/mid/end/none) + * @param[out] ppIvBuffer Returns a pointer to an IV buffer. + * + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter. + * + * @see LacCipher_Perform(), LacCipher_IvBufferRestore() + * + * @note LacCipher_IvBufferRestore() must be called when the request is + * completed to update the users IV buffer, only in the case of partial + * packet requests + * + *****************************************************************************/ +CpaStatus LacCipher_PerformIvCheck(sal_service_t *pService, + lac_sym_bulk_cookie_t *pCbCookie, + Cpa32U qatPacketType, + Cpa8U **ppIvBuffer); + +#endif /* LAC_SYM_CIPHER_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_cipher_defs.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_cipher_defs.h new file mode 100644 index 000000000000..4eddb70420da --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_cipher_defs.h @@ -0,0 +1,182 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + ***************************************************************************** + * @file lac_sym_cipher_defs.h + * + * @ingroup LacCipher + * + * @description + * This file defines constants for the cipher operations. + * + *****************************************************************************/ + +/***************************************************************************/ + +#ifndef LAC_SYM_CIPHER_DEFS_H +#define LAC_SYM_CIPHER_DEFS_H + +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ + +#include "cpa.h" +#include "cpa_cy_sym.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ + +/***************************************************************************/ + +/* + * Constants value for ARC4 algorithm + */ +/* ARC4 algorithm block size */ +#define LAC_CIPHER_ARC4_BLOCK_LEN_BYTES 8 +/* ARC4 key matrix size (bytes) */ +#define LAC_CIPHER_ARC4_KEY_MATRIX_LEN_BYTES 256 +/* ARC4 256 bytes for key matrix, 2 for i and j and 6 bytes for padding */ +#define LAC_CIPHER_ARC4_STATE_LEN_BYTES 264 + +#define LAC_SYM_SNOW3G_CIPHER_CONFIG_FOR_HASH_SZ 40 +/* Snow3g cipher config required for performing a Snow3g hash operation. + * It contains 8 Bytes of config for hardware, 16 Bytes of Key and requires + * 16 Bytes for the IV. + */ + +/* Key Modifier (KM) 4 bytes used in Kasumi algorithm in F8 mode to XOR + * Cipher Key (CK) */ +#define LAC_CIPHER_KASUMI_F8_KEY_MODIFIER_4_BYTES 0x55555555 + +/* The IV length for Kasumi Kgcore is 8 bytes */ +#define LAC_CIPHER_KASUMI_F8_IV_LENGTH 8 + +/* The Counter length for Kasumi Kgcore is 8 bytes */ +#define LAC_CIPHER_KASUMI_F8_COUNTER_LENGTH 8 + +/* The IV length for AES F8 is 16 bytes */ +#define LAC_CIPHER_AES_F8_IV_LENGTH 16 + +/* For Snow3G UEA2, need to make sure last 8 Bytes of IV buffer are + * zero. */ +#define LAC_CIPHER_SNOW3G_UEA2_IV_BUFFER_ZERO_LENGTH 8 + +/* Reserve enough space for max length cipher state + * (can be IV , counter or ARC4 state) */ +#define LAC_CIPHER_STATE_SIZE_MAX LAC_CIPHER_ARC4_STATE_LEN_BYTES + +/* Reserve enough space for max length cipher IV + * (can be A value for Kasumi(passed in as IV), IV or counter, + * but not ARC4 state) */ +#define LAC_CIPHER_IV_SIZE_MAX ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ + +/* 96-bit case of IV for GCM algorithm */ +#define LAC_CIPHER_IV_SIZE_GCM_12 12 + +/* 96-bit case of IV for CCP/GCM single pass algorithm */ +#define LAC_CIPHER_SPC_IV_SIZE 12 +/* + * Constants value for NULL algorithm + */ +/* NULL algorithm block size */ +#define LAC_CIPHER_NULL_BLOCK_LEN_BYTES 8 + +/* Macro to check if the Algorithm is SM4 */ +#define LAC_CIPHER_IS_SM4(algo) \ + ((algo == CPA_CY_SYM_CIPHER_SM4_ECB) || \ + (algo == CPA_CY_SYM_CIPHER_SM4_CBC) || \ + (algo == CPA_CY_SYM_CIPHER_SM4_CTR)) + +/* Macro to check if the Algorithm is CHACHA */ +#define LAC_CIPHER_IS_CHACHA(algo) (algo == CPA_CY_SYM_CIPHER_CHACHA) +/* Macro to check if the Algorithm is AES */ +#define LAC_CIPHER_IS_AES(algo) \ + ((algo == CPA_CY_SYM_CIPHER_AES_ECB) || \ + (algo == CPA_CY_SYM_CIPHER_AES_CBC) || \ + (algo == CPA_CY_SYM_CIPHER_AES_CTR) || \ + (algo == CPA_CY_SYM_CIPHER_AES_CCM) || \ + (algo == CPA_CY_SYM_CIPHER_AES_GCM) || \ + (algo == CPA_CY_SYM_CIPHER_AES_XTS)) + +/* Macro to check if the Algorithm is DES */ +#define LAC_CIPHER_IS_DES(algo) \ + ((algo == CPA_CY_SYM_CIPHER_DES_ECB) || \ + (algo == CPA_CY_SYM_CIPHER_DES_CBC)) + +/* Macro to check if the Algorithm is Triple DES */ +#define LAC_CIPHER_IS_TRIPLE_DES(algo) \ + ((algo == CPA_CY_SYM_CIPHER_3DES_ECB) || \ + (algo == CPA_CY_SYM_CIPHER_3DES_CBC) || \ + (algo == CPA_CY_SYM_CIPHER_3DES_CTR)) + +/* Macro to check if the Algorithm is Kasumi */ +#define LAC_CIPHER_IS_KASUMI(algo) (algo == CPA_CY_SYM_CIPHER_KASUMI_F8) + +/* Macro to check if the Algorithm is Snow3G UEA2 */ +#define LAC_CIPHER_IS_SNOW3G_UEA2(algo) (algo == CPA_CY_SYM_CIPHER_SNOW3G_UEA2) + +/* Macro to check if the Algorithm is ARC4 */ +#define LAC_CIPHER_IS_ARC4(algo) (algo == CPA_CY_SYM_CIPHER_ARC4) + +/* Macro to check if the Algorithm is ZUC EEA3 */ +#define LAC_CIPHER_IS_ZUC_EEA3(algo) (algo == CPA_CY_SYM_CIPHER_ZUC_EEA3) + +/* Macro to check if the Algorithm is NULL */ +#define LAC_CIPHER_IS_NULL(algo) (algo == CPA_CY_SYM_CIPHER_NULL) + +/* Macro to check if the Mode is CTR */ +#define LAC_CIPHER_IS_CTR_MODE(algo) \ + ((algo == CPA_CY_SYM_CIPHER_AES_CTR) || \ + (algo == CPA_CY_SYM_CIPHER_3DES_CTR) || (LAC_CIPHER_IS_CCM(algo)) || \ + (LAC_CIPHER_IS_GCM(algo)) || (LAC_CIPHER_IS_CHACHA(algo)) || \ + (algo == CPA_CY_SYM_CIPHER_SM4_CTR)) + +/* Macro to check if the Algorithm is ECB */ +#define LAC_CIPHER_IS_ECB_MODE(algo) \ + ((algo == CPA_CY_SYM_CIPHER_AES_ECB) || \ + (algo == CPA_CY_SYM_CIPHER_DES_ECB) || \ + (algo == CPA_CY_SYM_CIPHER_3DES_ECB) || \ + (algo == CPA_CY_SYM_CIPHER_NULL) || \ + (algo == CPA_CY_SYM_CIPHER_SNOW3G_UEA2) || \ + (algo == CPA_CY_SYM_CIPHER_SM4_ECB)) + +/* Macro to check if the Algorithm Mode is F8 */ +#define LAC_CIPHER_IS_F8_MODE(algo) \ + ((algo == CPA_CY_SYM_CIPHER_KASUMI_F8) || \ + (algo == CPA_CY_SYM_CIPHER_AES_F8)) + +/* Macro to check if the Algorithm is CBC */ +#define LAC_CIPHER_IS_CBC_MODE(algo) \ + ((algo == CPA_CY_SYM_CIPHER_AES_CBC) || \ + (algo == CPA_CY_SYM_CIPHER_DES_CBC) || \ + (algo == CPA_CY_SYM_CIPHER_3DES_CBC) || \ + (algo == CPA_CY_SYM_CIPHER_SM4_CBC)) + +/* Macro to check if the Algorithm is CCM */ +#define LAC_CIPHER_IS_CCM(algo) (algo == CPA_CY_SYM_CIPHER_AES_CCM) + +/* Macro to check if the Algorithm is GCM */ +#define LAC_CIPHER_IS_GCM(algo) (algo == CPA_CY_SYM_CIPHER_AES_GCM) + +/* Macro to check if the Algorithm is AES-F8 */ +#define LAC_CIPHER_IS_AES_F8(algo) (algo == CPA_CY_SYM_CIPHER_AES_F8) + +/* Macro to check if the Algorithm Mode is XTS */ +#define LAC_CIPHER_IS_XTS_MODE(algo) (algo == CPA_CY_SYM_CIPHER_AES_XTS) + +/* Macro to check if the Algorithm is single pass */ +#define LAC_CIPHER_IS_SPC(cipher, hash, mask) \ + ((LAC_CIPHER_IS_CHACHA(cipher) && (CPA_CY_SYM_HASH_POLY == hash) && \ + ((mask)&ICP_ACCEL_CAPABILITIES_CHACHA_POLY)) || \ + (LAC_CIPHER_IS_GCM(cipher) && ((CPA_CY_SYM_HASH_AES_GCM == hash) || \ + (CPA_CY_SYM_HASH_AES_GMAC == hash)) && \ + ((mask)&ICP_ACCEL_CAPABILITIES_AESGCM_SPC))) + +#endif /* LAC_CIPHER_DEFS_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_hash.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_hash.h new file mode 100644 index 000000000000..b2cd7bcd0b8c --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_hash.h @@ -0,0 +1,559 @@ +/*************************************************************************** + * + * <COPYRIGHT_TAG> + * + ***************************************************************************/ + +/** + ***************************************************************************** + * @file lac_sym_hash.h + * + * @defgroup LacHash Hash + * + * @ingroup LacSym + * + * API functions of the Hash component + * + * @lld_start + * @lld_overview + * There is a single \ref cpaCySym "Symmetric LAC API" for hash, cipher, + * auth encryption and algorithm chaining. This API is implemented by the + * \ref LacSym "Symmetric" module. It demultiplexes calls to this API into + * their basic operation and does some common parameter checking and deals + * with accesses to the session table. + * + * The hash component supports hashing in 3 modes. PLAIN, AUTH and NESTED. + * Plain mode is used to provide data integrity while auth mode is used to + * provide integrity as well as its authenticity. Nested mode is inteded + * for use by non standard HMAC like algorithms such as for the SSL master + * key secret. Partial packets is supported for both plain and auth modes. + * In-place and out-of-place processing is supported for all modes. The + * verify operation is supported for PLAIN and AUTH modes only. + * + * The hash component is responsible for implementing the hash specific + * functionality for initialising a session and for a perform operation. + * Statistics are maintained in the symmetric \ref CpaCySymStats64 "stats" + * structure. This module has been seperated out into two. The hash QAT module + * deals entirely with QAT data structures. The hash module itself has minimal + * exposure to the QAT data structures. + * + * @lld_dependencies + * - \ref LacCommon + * - \ref LacSymQat "Symmetric QAT": Hash uses the lookup table provided by + * this module to validate user input. Hash also uses this module to build + * the hash QAT request message, request param structure, populate the + * content descriptor, allocate and populate the hash state prefix buffer. + * Hash also registers its function to process the QAT response with this + * module. + * - OSAL : For memory functions, atomics and locking + * + * @lld_module_algorithms + * <b>a. HMAC Precomputes</b>\n + * HMAC algorithm is specified as follows: + * \f$ HMAC(msg) = hash((key \oplus opad) \parallel + * hash((key \oplus ipad) \parallel msg ))\f$. + * The key is fixed per session, and is padded up to the block size of the + * algorithm if necessary and xored with the ipad/opad. The following portion + * of the operation can be precomputed: \f$ hash(key \oplus ipad) \f$ as the + * output of this intermediate hash will be the same for every perform + * operation. This intermediate state is the intermediate state of a partial + * partial packet. It is used as the initialiser state to \f$ hash(msg) \f$. + * The same applies to \f$ hash(key \oplus ipad) \f$. There is a saving in + * the data path by the length of time it takes to do two hashes on a block + * size of data. Note: a partial packet operation generates an intermediate + * state. The final operation on a partial packet or when a full packet is + * used applies padding and gives the final hash result. Esentially for the + * inner hash, a partial packet final is issued on the data, using the + * precomputed intermediate state and returns the digest. + * + * For the HMAC precomputes, \ref LacSymHash_HmacPreCompute(), there are two + * hash operations done using a internal content descriptor to configure the + * QAT. A first partial packet is specified as the packet type for the + * pre-computes as we need the state that uses the initialiser constants + * specific to the algorithm. The resulting output is copied from the hash + * state prefix buffer into the QAT content descriptor for the session being + * initialised. The state is used each perform operation as the initialiser + * to the algorithm + * + * <b>b. AES XCBC Precomputes</b>\n + * A similar technique to HMAC will be used to generate the precomputes for + * AES XCBC. In this case a cipher operation will be used to generate the + * precomputed result. The Pre-compute operation involves deriving 3 128-bit + * keys (K1, K2 and K3) from the 128-bit secret key K. + * + * - K1 = 0x01010101010101010101010101010101 encrypted with Key K + * - K2 = 0x02020202020202020202020202020202 encrypted with Key K + * - K3 = 0x03030303030303030303030303030303 encrypted with Key K + * + * A content descriptor is created with the cipher algorithm set to AES + * in ECB mode and with the keysize set to 128 bits. The 3 constants, 16 bytes + * each, are copied into the src buffer and an in-place cipher operation is + * performed on the 48 bytes. ECB mode does not maintain the state, therefore + * the 3 keys can be encrypted in one perform. The encrypted result is used by + * the state2 field in the hash setup block of the content descriptor. + * + * The precompute operations use a different lac command ID and thus have a + * different route in the response path to the symmetric code. In this + * precompute callback function the output of the precompute operation is + * copied into the content descriptor for the session being registered. + * + * <b>c. AES CCM Precomputes</b>\n + * The precomputes for AES CCM are trivial, i.e. there is no need to perform + * a cipher or a digest operation. Instead, the key is stored directly in + * the state2 field. + * + * <b>d. AES GCM Precomputes</b>\n + * As with AES XCBC precomputes, a cipher operation will be used to generate + * the precomputed result for AES GCM. In this case the Galois Hash + * Multiplier (H) must be derived and stored in the state2 field. H is + * derived by encrypting a 16-byte block of zeroes with the + * cipher/authentication key, using AES in ECB mode. + * + * <b>Key size for Auth algorithms</b>\n + * <i>Min Size</i>\n + * RFC 2104 states "The key for HMAC can be of any length. However, less than + * L bytes is strongly discouraged as it would decrease the security strength + * of the function." + * + * FIPS 198a states "The size of the key, K, shall be equal to or greater than + * L/2, where L is the size of the hash function output." + * + * RFC 4434 states "If the key has fewer than 128 bits, lengthen it to exactly + * 128 bits by padding it on the right with zero bits. + * + * A key length of 0 upwards is accepted. It is up to the client to pass in a + * key that complies with the standard they wish to support. + * + * <i>Max Size</i>\n + * RFC 2104 section 2 states : "Applications that use keys longer than B bytes + * will first hash the key using H and then use the resultant L byte string + * as the actual key to HMAC + * + * RFC 4434 section 2 states: + * "If the key is 129 bits or longer, shorten it to exactly 128 bits + * by performing the steps in AES-XCBC-PRF-128 (that is, the + * algorithm described in this document). In that re-application of + * this algorithm, the key is 128 zero bits; the message is the + * too-long current key." + * + * We push this up to the client. They need to do the hash operation through + * the LAC API if the key is greater than the block size of the algorithm. This + * will reduce the key size to the digest size of the algorithm. + * + * RFC 3566 section 4 states: + * AES-XCBC-MAC-96 is a secret key algorithm. For use with either ESP or + * AH a fixed key length of 128-bits MUST be supported. Key lengths + * other than 128-bits MUST NOT be supported (i.e., only 128-bit keys are + * to be used by AES-XCBC-MAC-96). + * + * In this case it is up to the client to provide a key that complies with + * the standards. i.e. exactly 128 bits in size. + * + * + * <b>HMAC-MD5-96 and HMAC-SHA1-96</b>\n + * HMAC-MD5-96 and HMAC-SHA1-96 are defined as requirements by Look Aside + * IPsec. The differences between HMAC-SHA1 and HMAC-SHA1-96 are that the + * digest produced is truncated and there are strict requirements on the + * size of the key that is used. + * + * They are supported in LAC by HMAC-MD5 and HMAC-SHA1. The field + * \ref CpaCySymHashSetupData::digestResultLenInBytes in the LAC API in + * bytes needs to be set to 12 bytes. There are also requirements regarding + * the keysize. It is up to the client to ensure the key size meets the + * requirements of the standards they are using. + * + * RFC 2403: HMAC-MD5-96 Key lengths other than 128-bits MUST NOT be supported. + * HMAC-MD5-96 produces a 128-bit authenticator value. For use with either + * ESP or AH, a truncated value using the first 96 bits MUST be supported. + * + * RFC2404: HMAC-SHA1-96 Key lengths other than 160- bits MUST NOT be supported + * HMAC-SHA-1-96 produces a 160-bit authenticator value. For use with either + * ESP or AH, a truncated value using the first 96 bits MUST be supported. + * + * <b>Out of place operations</b> + * When verify is disabled, the digest will be written to the destination + * buffer. When verify is enabled, the digest calculated is compared to the + * digest stored in the source buffer. + * + * <b>Partial Packets</b> + * Partial packets are handled in the \ref LacSym "Symmetric" component for + * the request. The hash callback function handles the update of the state + * in the callback. + * + * + * @lld_process_context + * + * Session Register Sequence Diagram: For hash modes plain and nested. + * \msc + * APP [label="Application"], SYM [label="Symmetric LAC"], + * Achain [label="Alg chain"], Hash, SQAT [label="Symmetric QAT"]; + * + * APP=>SYM [ label = "cpaCySymInitSession(cbFunc)", + * URL="\ref cpaCySymInitSession()"] ; + * SYM=>SYM [ label = "LacSymSession_ParamCheck()", + * URL="\ref LacSymSession_ParamCheck()"]; + * SYM=>Achain [ label = "LacAlgChain_SessionInit()", + * URL="\ref LacAlgChain_SessionInit()"]; + * Achain=>Hash [ label = "LacHash_HashContextCheck()", + * URL="\ref LacHash_HashContextCheck()"]; + * Achain<<Hash [ label="return"]; + * Achain=>SQAT [ label = "LacSymQat_HashContentDescInit()", + * URL="\ref LacSymQat_HashContentDescInit()"]; + * Achain<<SQAT [ label="return"]; + * Achain=>Hash [ label = "LacHash_StatePrefixAadBufferInit()", + * URL="\ref LacHash_StatePrefixAadBufferInit()"]; + * Hash=>SQAT [ label = "LacSymQat_HashStatePrefixAadBufferSizeGet()", + * URL="\ref LacSymQat_HashStatePrefixAadBufferSizeGet()"]; + * Hash<<SQAT [ label="return"]; + * Hash=>SQAT [ label = "LacSymQat_HashStatePrefixAadBufferPopulate()", + * URL="\ref LacSymQat_HashStatePrefixAadBufferPopulate()"]; + * Hash<<SQAT [ label="return"]; + * Achain<<Hash [ label="return"]; + * SYM<<Achain [ label = "status" ]; + * SYM=>SYM [label = "LAC_SYM_STAT_INC", URL="\ref LAC_SYM_STAT_INC"]; + * APP<<SYM [label = "status"]; + * \endmsc + * + * Perform Sequence Diagram: For all 3 modes, full packets and in-place. + * \msc + * APP [label="Application"], SYM [label="Symmetric LAC"], + * Achain [label="Alg chain"], Hash, SQAT [label="Symmetric QAT"], + * QATCOMMS [label="QAT Comms"]; + * + * APP=>SYM [ label = "cpaCySymPerformOp()", + * URL="\ref cpaCySymPerformOp()"] ; + * SYM=>SYM [ label = "LacSymPerform_BufferParamCheck()", + * URL="\ref LacSymPerform_BufferParamCheck()"]; + * SYM=>Achain [ label = "LacAlgChain_Perform()", + * URL="\ref LacAlgChain_Perform()"]; + * Achain=>Achain [ label = "Lac_MemPoolEntryAlloc()", + * URL="\ref Lac_MemPoolEntryAlloc()"]; + * Achain=>SQAT [ label = "LacSymQat_packetTypeGet()", + * URL="\ref LacSymQat_packetTypeGet()"]; + * Achain<<SQAT [ label="return"]; + * Achain=>Achain [ label = "LacBuffDesc_BufferListTotalSizeGet()", + * URL="\ref LacBuffDesc_BufferListTotalSizeGet()"]; + * Achain=>Hash [ label = "LacHash_PerformParamCheck()", + * URL = "\ref LacHash_PerformParamCheck()"]; + * Achain<<Hash [ label="status"]; + * Achain=>SQAT [ label = "LacSymQat_HashRequestParamsPopulate()", + * URL="\ref LacSymQat_HashRequestParamsPopulate()"]; + * Achain<<SQAT [ label="return"]; + * Achain<<SQAT [ label="cmdFlags"]; + * + * Achain=>Achain [ label = "LacBuffDesc_BufferListDescWrite()", + * URL="\ref LacBuffDesc_BufferListDescWrite()"]; + * Achain=>SQAT [ label = "SalQatMsg_CmnMsgAndReqParamsPopulate()", + * URL="\ref SalQatMsg_CmnMsgAndReqParamsPopulate()"]; + * Achain<<SQAT [ label="return"]; + * Achain=>SYM [ label = "LacSymQueue_RequestSend()", + * URL="\ref LacSymQueue_RequestSend()"]; + * SYM=>QATCOMMS [ label = "QatComms_MsgSend()", + * URL="\ref QatComms_MsgSend()"]; + * SYM<<QATCOMMS [ label="status"]; + * Achain<<SYM [ label="status"]; + * SYM<<Achain [ label="status"]; + * SYM=>SYM [label = "LAC_SYM_STAT_INC", URL="\ref LAC_SYM_STAT_INC"]; + * APP<<SYM [label = "status"]; + * ... [label = "QAT processing the request and generates response. + * Callback in Bottom Half Context"]; + * ...; + * QATCOMMS=>QATCOMMS [label ="QatComms_ResponseMsgHandler()", + * URL="\ref QatComms_ResponseMsgHandler()"]; + * QATCOMMS=>SQAT [label ="LacSymQat_SymRespHandler()", + * URL="\ref LacSymQat_SymRespHandler()"]; + * SQAT=>SYM [label="LacSymCb_ProcessCallback()", + * URL="\ref LacSymCb_ProcessCallback()"]; + * SYM=>SYM [label = "LacSymCb_ProcessCallbackInternal()", + * URL="\ref LacSymCb_ProcessCallbackInternal()"]; + * SYM=>SYM [label = "Lac_MemPoolEntryFree()", + * URL="\ref Lac_MemPoolEntryFree()"]; + * SYM=>SYM [label = "LAC_SYM_STAT_INC", URL="\ref LAC_SYM_STAT_INC"]; + * SYM=>APP [label="cbFunc"]; + * APP>>SYM [label="return"]; + * SYM>>SQAT [label="return"]; + * SQAT>>QATCOMMS [label="return"]; + * \endmsc + * + * @lld_end + * + *****************************************************************************/ + +/*****************************************************************************/ + +#ifndef LAC_SYM_HASH_H +#define LAC_SYM_HASH_H + +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ + +#include "cpa.h" +#include "cpa_cy_sym.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ + +#include "lac_session.h" +#include "lac_buffer_desc.h" + +/** + ***************************************************************************** + * @ingroup LacHash + * Definition of callback function. + * + * @description + * This is the callback function prototype. The callback function is + * invoked when a hash precompute operation completes. + * + * @param[in] pCallbackTag Opaque value provided by user while making + * individual function call. + * + * @retval + * None + *****************************************************************************/ +typedef void (*lac_hash_precompute_done_cb_t)(void *pCallbackTag); + +/* + * WARNING: There are no checks done on the parameters of the functions in + * this file. The expected values of the parameters are documented and it is + * up to the caller to provide valid values. + */ + +/** +******************************************************************************* +* @ingroup LacHash +* validate the hash context +* +* @description +* The client populates the hash context in the session context structure +* This is passed as parameter to the session register API function and +* needs to be validated. +* +* @param[in] pHashSetupData pointer to hash context structure +* +* @retval CPA_STATUS_SUCCESS Success +* @retval CPA_STATUS_INVALID_PARAM Invalid parameter +* +*****************************************************************************/ +CpaStatus LacHash_HashContextCheck(CpaInstanceHandle instanceHandle, + const CpaCySymHashSetupData *pHashSetupData); + +/** + ****************************************************************************** + * @ingroup LacHash + * Populate the hash pre-compute data. + * + * @description + * This function populates the state1 and state2 fields with the hash + * pre-computes. This is only done for authentication. The state1 + * and state2 pointers must be set to point to the correct locations + * in the content descriptor where the precompute result(s) will be + * written, before this function is called. + * + * @param[in] instanceHandle Instance Handle + * @param[in] pSessionSetup pointer to session setup data + * @param[in] callbackFn Callback function which is invoked when + * the precompute operation is completed + * @param[in] pCallbackTag Opaque data which is passed back to the user + * as a parameter in the callback function + * @param[out] pWorkingBuffer Pointer to working buffer, sufficient memory + * must be allocated by the caller for this. + * Assumption that this is 8 byte aligned. + * @param[out] pState1 pointer to State 1 in content descriptor + * @param[out] pState2 pointer to State 2 in content descriptor + * + * @retval CPA_STATUS_SUCCESS Success + * @retval CPA_STATUS_RETRY Retry the operation. + * @retval CPA_STATUS_RESOURCE Error Allocating memory + * @retval CPA_STATUS_FAIL Operation Failed + * + *****************************************************************************/ +CpaStatus LacHash_PrecomputeDataCreate(const CpaInstanceHandle instanceHandle, + CpaCySymSessionSetupData *pSessionSetup, + lac_hash_precompute_done_cb_t callbackFn, + void *pCallbackTag, + Cpa8U *pWorkingBuffer, + Cpa8U *pState1, + Cpa8U *pState2); + +/** + ****************************************************************************** + * @ingroup LacHash + * populate the hash state prefix aad buffer. + * + * @description + * This function populates the hash state prefix aad buffer. This function + * is not called for CCM/GCM operations as the AAD data varies per request + * and is stored in the cookie as opposed to the session descriptor. + * + * @param[in] pHashSetupData pointer to hash setup structure + * @param[in] pHashControlBlock pointer to hash control block + * @param[in] qatHashMode QAT Mode for hash + * @param[in] pHashStateBuffer pointer to hash state prefix aad buffer + * @param[in] pHashStateBufferInfo Pointer to hash state prefix buffer info + * + * @retval CPA_STATUS_SUCCESS Success + * @retval CPA_STATUS_FAIL Operation Failed + * + *****************************************************************************/ +CpaStatus LacHash_StatePrefixAadBufferInit( + sal_service_t *pService, + const CpaCySymHashSetupData *pHashSetupData, + icp_qat_la_bulk_req_ftr_t *pHashControlBlock, + icp_qat_hw_auth_mode_t qatHashMode, + Cpa8U *pHashStateBuffer, + lac_sym_qat_hash_state_buffer_info_t *pHashStateBufferInfo); + +/** +******************************************************************************* +* @ingroup LacHash +* Check parameters for a hash perform operation +* +* @description +* This function checks the parameters for a hash perform operation. +* +* @param[in] pSessionDesc Pointer to session descriptor. +* @param[in] pOpData Pointer to request parameters. +* @param[in] srcPktSize Total size of the Buffer List +* @param[in] pVerifyResult Pointer to user flag +* +* @retval CPA_STATUS_SUCCESS Success +* @retval CPA_STATUS_INVALID_PARAM Invalid Parameter +* +*****************************************************************************/ +CpaStatus LacHash_PerformParamCheck(CpaInstanceHandle instanceHandle, + lac_session_desc_t *pSessionDesc, + const CpaCySymOpData *pOpData, + Cpa64U srcPktSize, + const CpaBoolean *pVerifyResult); + +/** +******************************************************************************* +* @ingroup LacHash +* Perform hash precompute operation for HMAC +* +* @description +* This function sends 2 requests to the CPM for the hmac precompute +* operations. The results of the ipad and opad state calculation +* is copied into pState1 and pState2 (e.g. these may be the state1 and +* state2 buffers in a hash content desciptor) and when +* the final operation has completed the condition passed as a param to +* this function is set to true. +* +* This function performs the XORing of the IPAD and OPAD constants to +* the key (which was padded to the block size of the algorithm) +* +* @param[in] instanceHandle Instance Handle +* @param[in] hashAlgorithm Hash Algorithm +* @param[in] authKeyLenInBytes Length of Auth Key +* @param[in] pAuthKey Pointer to Auth Key +* @param[out] pWorkingMemory Pointer to working memory that is carved +* up and used in the pre-compute operations. +* Assumption that this is 8 byte aligned. +* @param[out] pState1 Pointer to State 1 in content descriptor +* @param[out] pState2 Pointer to State 2 in content descriptor +* @param[in] callbackFn Callback function which is invoked when +* the precompute operation is completed +* @param[in] pCallbackTag Opaque data which is passed back to the user +* as a parameter in the callback function +* +* @retval CPA_STATUS_SUCCESS Success +* @retval CPA_STATUS_RETRY Retry the operation. +* @retval CPA_STATUS_FAIL Operation Failed +* +*****************************************************************************/ +CpaStatus LacSymHash_HmacPreComputes(CpaInstanceHandle instanceHandle, + CpaCySymHashAlgorithm hashAlgorithm, + Cpa32U authKeyLenInBytes, + Cpa8U *pAuthKey, + Cpa8U *pWorkingMemory, + Cpa8U *pState1, + Cpa8U *pState2, + lac_hash_precompute_done_cb_t callbackFn, + void *pCallbackTag); + +/** +******************************************************************************* + * @ingroup LacHash + * Perform hash precompute operation for XCBC MAC and GCM + * + * @description + * This function sends 1 request to the CPM for the precompute operation + * based on an AES ECB cipher. The results of the calculation is copied + * into pState (this may be a pointer to the State 2 buffer in a Hash + * content descriptor) and when the operation has completed the condition + * passed as a param to this function is set to true. + * + * @param[in] instanceHandle Instance Handle + * @param[in] hashAlgorithm Hash Algorithm + * @param[in] authKeyLenInBytes Length of Auth Key + * @param[in] pAuthKey Auth Key + * @param[out] pWorkingMemory Pointer to working memory that is carved + * up and used in the pre-compute operations. + * Assumption that this is 8 byte aligned. + * @param[out] pState Pointer to output state + * @param[in] callbackFn Callback function which is invoked when + * the precompute operation is completed + * @param[in] pCallbackTag Opaque data which is passed back to the user + * as a parameter in the callback function + + * + * @retval CPA_STATUS_SUCCESS Success + * @retval CPA_STATUS_RETRY Retry the operation. + * @retval CPA_STATUS_FAIL Operation Failed + * + *****************************************************************************/ +CpaStatus LacSymHash_AesECBPreCompute(CpaInstanceHandle instanceHandle, + CpaCySymHashAlgorithm hashAlgorithm, + Cpa32U authKeyLenInBytes, + Cpa8U *pAuthKey, + Cpa8U *pWorkingMemory, + Cpa8U *pState, + lac_hash_precompute_done_cb_t callbackFn, + void *pCallbackTag); + +/** +******************************************************************************* +* @ingroup LacHash +* initialise data structures for the hash precompute operations +* +* @description +* This function registers the precompute callback handler function, which +* is different to the default one used by symmetric. Content desciptors +* are preallocted for the hmac precomputes as they are constant for these +* operations. +* +* @retval CPA_STATUS_SUCCESS Success +* @retval CPA_STATUS_RESOURCE Error allocating memory +* +*****************************************************************************/ +CpaStatus LacSymHash_HmacPrecompInit(CpaInstanceHandle instanceHandle); + +/** +******************************************************************************* +* @ingroup LacHash +* free resources allocated for the precompute operations +* +* @description +* free up the memory allocated on init time for the content descriptors +* that were allocated for the HMAC precompute operations. +* +* @return none +* +*****************************************************************************/ +void LacSymHash_HmacPrecompShutdown(CpaInstanceHandle instanceHandle); + +void LacSync_GenBufListVerifyCb(void *pCallbackTag, + CpaStatus status, + CpaCySymOp operationType, + void *pOpData, + CpaBufferList *pDstBuffer, + CpaBoolean opResult); + +#endif /* LAC_SYM_HASH_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_hash_defs.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_hash_defs.h new file mode 100644 index 000000000000..e95b0efb5b0e --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_hash_defs.h @@ -0,0 +1,344 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_hash_defs.h + * + * @defgroup LacHashDefs Hash Definitions + * + * @ingroup LacHash + * + * Constants for hash algorithms + * + ***************************************************************************/ + +#ifndef LAC_SYM_HASH_DEFS_H +#define LAC_SYM_HASH_DEFS_H + +/* Constant for MD5 algorithm */ +#define LAC_HASH_MD5_BLOCK_SIZE 64 +/**< @ingroup LacHashDefs + * MD5 block size in bytes */ +#define LAC_HASH_MD5_DIGEST_SIZE 16 +/**< @ingroup LacHashDefs + * MD5 digest length in bytes */ +#define LAC_HASH_MD5_STATE_SIZE 16 +/**< @ingroup LacHashDefs + * MD5 state size */ + +/* Constants for SHA1 algorithm */ +#define LAC_HASH_SHA1_BLOCK_SIZE 64 +/**< @ingroup LacHashDefs + * SHA1 Block size in bytes */ +#define LAC_HASH_SHA1_DIGEST_SIZE 20 +/**< @ingroup LacHashDefs + * SHA1 digest length in bytes */ +#define LAC_HASH_SHA1_STATE_SIZE 20 +/**< @ingroup LacHashDefs + * SHA1 state size */ + +/* Constants for SHA224 algorithm */ +#define LAC_HASH_SHA224_BLOCK_SIZE 64 +/**< @ingroup LacHashDefs + * SHA224 block size in bytes */ +#define LAC_HASH_SHA224_DIGEST_SIZE 28 +/**< @ingroup LacHashDefs + * SHA224 digest length in bytes */ +#define LAC_HASH_SHA224_STATE_SIZE 32 +/**< @ingroup LacHashDefs + * SHA224 state size */ + +/* Constants for SHA256 algorithm */ +#define LAC_HASH_SHA256_BLOCK_SIZE 64 +/**< @ingroup LacHashDefs + * SHA256 block size in bytes */ +#define LAC_HASH_SHA256_DIGEST_SIZE 32 +/**< @ingroup LacHashDefs + * SHA256 digest length */ +#define LAC_HASH_SHA256_STATE_SIZE 32 +/**< @ingroup LacHashDefs + * SHA256 state size */ + +/* Constants for SHA384 algorithm */ +#define LAC_HASH_SHA384_BLOCK_SIZE 128 +/**< @ingroup LacHashDefs + * SHA384 block size in bytes */ +#define LAC_HASH_SHA384_DIGEST_SIZE 48 +/**< @ingroup LacHashDefs + * SHA384 digest length in bytes */ +#define LAC_HASH_SHA384_STATE_SIZE 64 +/**< @ingroup LacHashDefs + * SHA384 state size */ + +/* Constants for SHA512 algorithm */ +#define LAC_HASH_SHA512_BLOCK_SIZE 128 +/**< @ingroup LacHashDefs + * SHA512 block size in bytes */ +#define LAC_HASH_SHA512_DIGEST_SIZE 64 +/**< @ingroup LacHashDefs + * SHA512 digest length in bytes */ +#define LAC_HASH_SHA512_STATE_SIZE 64 +/**< @ingroup LacHashDefs + * SHA512 state size */ + +/* Constants for SHA3_224 algorithm */ +#define LAC_HASH_SHA3_224_BLOCK_SIZE 144 +/**< @ingroup LacHashDefs + * SHA3_224 block size in bytes */ +#define LAC_HASH_SHA3_224_DIGEST_SIZE 28 +/**< @ingroup LacHashDefs + * SHA3_224 digest length in bytes */ +#define LAC_HASH_SHA3_224_STATE_SIZE 28 +/**< @ingroup LacHashDefs + * SHA3_224 state size */ + +/* Constants for SHA3_256 algorithm */ +#define LAC_HASH_SHA3_256_BLOCK_SIZE 136 +/**< @ingroup LacHashDefs + * SHA3_256 block size in bytes */ +#define LAC_HASH_SHA3_256_DIGEST_SIZE 32 +/**< @ingroup LacHashDefs + * SHA3_256 digest length in bytes */ +#define LAC_HASH_SHA3_256_STATE_SIZE 32 +/**< @ingroup LacHashDefs + * SHA3_256 state size */ + +/* Constants for SHA3_384 algorithm */ +#define LAC_HASH_SHA3_384_BLOCK_SIZE 104 +/**< @ingroup LacHashDefs + * * SHA3_384 block size in bytes */ +#define LAC_HASH_SHA3_384_DIGEST_SIZE 48 +/**< @ingroup LacHashDefs + * * SHA3_384 digest length in bytes */ +#define LAC_HASH_SHA3_384_STATE_SIZE 48 +/**< @ingroup LacHashDefs + * * SHA3_384 state size */ + +/* Constants for SHA3_512 algorithm */ +#define LAC_HASH_SHA3_512_BLOCK_SIZE 72 +/**< @ingroup LacHashDefs + * * * SHA3_512 block size in bytes */ +#define LAC_HASH_SHA3_512_DIGEST_SIZE 64 +/**< @ingroup LacHashDefs + * * * SHA3_512 digest length in bytes */ +#define LAC_HASH_SHA3_512_STATE_SIZE 64 +/**< @ingroup LacHashDefs + * * * SHA3_512 state size */ + +/* Constants for SHAKE_128 algorithm */ +#define LAC_HASH_SHAKE_128_BLOCK_SIZE 168 +/**< @ingroup LacHashDefs + * * * SHAKE_128 block size in bytes */ +#define LAC_HASH_SHAKE_128_DIGEST_SIZE 0xFFFFFFFF +/**< @ingroup LacHashDefs + * * * SHAKE_128 digest length in bytes ((2^32)-1)*/ + +/* Constants for SHAKE_256 algorithm */ +#define LAC_HASH_SHAKE_256_BLOCK_SIZE 136 +/**< @ingroup LacHashDefs + * * * SHAKE_256 block size in bytes */ +#define LAC_HASH_SHAKE_256_DIGEST_SIZE 0xFFFFFFFF +/**< @ingroup LacHashDefs + * * * SHAKE_256 digest length in bytes ((2^ 32)-1)*/ + +/* Constants for POLY algorithm */ +#define LAC_HASH_POLY_BLOCK_SIZE 64 +/**< @ingroup LacHashDefs + * POLY block size in bytes */ +#define LAC_HASH_POLY_DIGEST_SIZE 16 +/**< @ingroup LacHashDefs + * POLY digest length */ +#define LAC_HASH_POLY_STATE_SIZE 0 +/**< @ingroup LacHashDefs + * POLY state size */ + +/* Constants for SM3 algorithm */ +#define LAC_HASH_SM3_BLOCK_SIZE 64 +/**< @ingroup LacHashDefs + * SM3 block size in bytes */ +#define LAC_HASH_SM3_DIGEST_SIZE 32 +/**< @ingroup LacHashDefs + * SM3 digest length */ +#define LAC_HASH_SM3_STATE_SIZE 32 +/**< @ingroup LacHashDefs + * SM3 state size */ + +/* Constants for XCBC precompute algorithm */ +#define LAC_HASH_XCBC_PRECOMP_KEY_NUM 3 +/**< @ingroup LacHashDefs + * The Pre-compute operation involves deriving 3 128-bit + * keys (K1, K2 and K3) */ + +/* Constants for XCBC MAC algorithm */ +#define LAC_HASH_XCBC_MAC_BLOCK_SIZE 16 +/**< @ingroup LacHashDefs + * XCBC_MAC block size in bytes */ +#define LAC_HASH_XCBC_MAC_128_DIGEST_SIZE 16 +/**< @ingroup LacHashDefs + * XCBC_MAC_PRF_128 digest length in bytes */ + +/* Constants for AES CMAC algorithm */ +#define LAC_HASH_CMAC_BLOCK_SIZE 16 +/**< @ingroup LacHashDefs + * AES CMAC block size in bytes */ +#define LAC_HASH_CMAC_128_DIGEST_SIZE 16 +/**< @ingroup LacHashDefs + * AES CMAC digest length in bytes */ + +/* constants for AES CCM */ +#define LAC_HASH_AES_CCM_BLOCK_SIZE 16 +/**< @ingroup LacHashDefs + * block size for CBC-MAC part of CCM */ +#define LAC_HASH_AES_CCM_DIGEST_SIZE 16 +/**< @ingroup LacHashDefs + * untruncated size of authentication field */ + +/* constants for AES GCM */ +#define LAC_HASH_AES_GCM_BLOCK_SIZE 16 +/**< @ingroup LacHashDefs + * block size for Galois Hash 128 part of CCM */ +#define LAC_HASH_AES_GCM_DIGEST_SIZE 16 +/**< @ingroup LacHashDefs + * untruncated size of authentication field */ + +/* constants for KASUMI F9 */ +#define LAC_HASH_KASUMI_F9_BLOCK_SIZE 8 +/**< @ingroup LacHashDefs + * KASUMI_F9 block size in bytes */ +#define LAC_HASH_KASUMI_F9_DIGEST_SIZE 4 +/**< @ingroup LacHashDefs + * KASUMI_F9 digest size in bytes */ + +/* constants for SNOW3G UIA2 */ +#define LAC_HASH_SNOW3G_UIA2_BLOCK_SIZE 8 +/**< @ingroup LacHashDefs + * SNOW3G UIA2 block size in bytes */ +#define LAC_HASH_SNOW3G_UIA2_DIGEST_SIZE 4 +/**< @ingroup LacHashDefs + * SNOW3G UIA2 digest size in bytes */ + +/* constants for AES CBC MAC */ +#define LAC_HASH_AES_CBC_MAC_BLOCK_SIZE 16 +/**< @ingroup LacHashDefs + * AES CBC MAC block size in bytes */ +#define LAC_HASH_AES_CBC_MAC_DIGEST_SIZE 16 +/**< @ingroup LacHashDefs + * AES CBC MAC digest size in bytes */ + +#define LAC_HASH_ZUC_EIA3_BLOCK_SIZE 4 +/**< @ingroup LacHashDefs + * ZUC EIA3 block size in bytes */ +#define LAC_HASH_ZUC_EIA3_DIGEST_SIZE 4 +/**< @ingroup LacHashDefs + * ZUC EIA3 digest size in bytes */ + +/* constants for AES GCM ICV allowed sizes */ +#define LAC_HASH_AES_GCM_ICV_SIZE_8 8 +#define LAC_HASH_AES_GCM_ICV_SIZE_12 12 +#define LAC_HASH_AES_GCM_ICV_SIZE_16 16 + +/* constants for AES CCM ICV allowed sizes */ +#define LAC_HASH_AES_CCM_ICV_SIZE_MIN 4 +#define LAC_HASH_AES_CCM_ICV_SIZE_MAX 16 + +/* constants for authentication algorithms */ +#define LAC_HASH_IPAD_BYTE 0x36 +/**< @ingroup LacHashDefs + * Ipad Byte */ +#define LAC_HASH_OPAD_BYTE 0x5c +/**< @ingroup LacHashDefs + * Opad Byte */ + +#define LAC_HASH_IPAD_4_BYTES 0x36363636 +/**< @ingroup LacHashDefs + * Ipad for 4 Bytes */ +#define LAC_HASH_OPAD_4_BYTES 0x5c5c5c5c +/**< @ingroup LacHashDefs + * Opad for 4 Bytes */ + +/* Key Modifier (KM) value used in Kasumi algorithm in F9 mode to XOR + * Integrity Key (IK) */ +#define LAC_HASH_KASUMI_F9_KEY_MODIFIER_4_BYTES 0xAAAAAAAA +/**< @ingroup LacHashDefs + * Kasumi F9 Key Modifier for 4 bytes */ + +#define LAC_SYM_QAT_HASH_IV_REQ_MAX_SIZE_QW 2 +/**< @ingroup LacSymQatHash + * Maximum size of IV embedded in the request. + * This is set to 2, namely 4 LONGWORDS. */ + +#define LAC_SYM_QAT_HASH_STATE1_MAX_SIZE_BYTES LAC_HASH_SHA512_BLOCK_SIZE +/**< @ingroup LacSymQatHash + * Maximum size of state1 in the hash setup block of the content descriptor. + * This is set to the block size of SHA512. */ + +#define LAC_SYM_QAT_HASH_STATE2_MAX_SIZE_BYTES LAC_HASH_SHA512_BLOCK_SIZE +/**< @ingroup LacSymQatHash + * Maximum size of state2 in the hash setup block of the content descriptor. + * This is set to the block size of SHA512. */ + +#define LAC_MAX_INNER_OUTER_PREFIX_SIZE_BYTES 255 +/**< Maximum size of the inner and outer prefix for nested hashing operations. + * This is got from the maximum size supported by the accelerator which stores + * the size in an 8bit field */ + +#define LAC_MAX_HASH_STATE_STORAGE_SIZE \ + (sizeof(icp_qat_hw_auth_counter_t) + LAC_HASH_SHA512_STATE_SIZE) +/**< Maximum size of the hash state storage section of the hash state prefix + * buffer */ + +#define LAC_MAX_HASH_STATE_BUFFER_SIZE_BYTES \ + LAC_MAX_HASH_STATE_STORAGE_SIZE + \ + (LAC_ALIGN_POW2_ROUNDUP(LAC_MAX_INNER_OUTER_PREFIX_SIZE_BYTES, \ + LAC_QUAD_WORD_IN_BYTES) * \ + 2) +/**< Maximum size of the hash state prefix buffer will be for nested hash when + * there is the maximum sized inner prefix and outer prefix */ + +#define LAC_MAX_AAD_SIZE_BYTES 256 +/**< Maximum size of AAD in bytes */ + +#define IS_HMAC_ALG(algorithm) \ + ((algorithm == CPA_CY_SYM_HASH_MD5) || \ + (algorithm == CPA_CY_SYM_HASH_SHA1) || \ + (algorithm == CPA_CY_SYM_HASH_SHA224) || \ + (algorithm == CPA_CY_SYM_HASH_SHA256) || \ + (algorithm == CPA_CY_SYM_HASH_SHA384) || \ + (algorithm == CPA_CY_SYM_HASH_SHA512) || \ + (algorithm == CPA_CY_SYM_HASH_SHA3_224) || \ + (algorithm == CPA_CY_SYM_HASH_SHA3_256) || \ + (algorithm == CPA_CY_SYM_HASH_SHA3_384) || \ + (algorithm == CPA_CY_SYM_HASH_SHA3_512) || \ + (algorithm == CPA_CY_SYM_HASH_SM3)) +/**< @ingroup LacSymQatHash + * Macro to detect if the hash algorithm is a HMAC algorithm */ + +#define IS_HASH_MODE_1(qatHashMode) (ICP_QAT_HW_AUTH_MODE1 == qatHashMode) +/**< @ingroup LacSymQatHash + * Macro to detect is qat hash mode is set to 1 (precompute mode) + * only used with algorithms in hash mode CPA_CY_SYM_HASH_MODE_AUTH */ + +#define IS_HASH_MODE_2(qatHashMode) (ICP_QAT_HW_AUTH_MODE2 == qatHashMode) +/**< @ingroup LacSymQatHash + * Macro to detect is qat hash mode is set to 2. This is used for TLS and + * mode 2 HMAC (no preompute mode) */ + +#define IS_HASH_MODE_2_AUTH(qatHashMode, hashMode) \ + ((IS_HASH_MODE_2(qatHashMode)) && \ + (CPA_CY_SYM_HASH_MODE_AUTH == hashMode)) +/**< @ingroup LacSymQatHash + * Macro to check for qat hash mode is set to 2 and the hash mode is + * Auth. This applies to HMAC algorithms (no pre compute). This is used + * to differntiate between TLS and HMAC */ + +#define IS_HASH_MODE_2_NESTED(qatHashMode, hashMode) \ + ((IS_HASH_MODE_2(qatHashMode)) && \ + (CPA_CY_SYM_HASH_MODE_NESTED == hashMode)) +/**< @ingroup LacSymQatHash + * Macro to check for qat hash mode is set to 2 and the LAC hash mode is + * Nested. This applies to TLS. This is used to differentiate between + * TLS and HMAC */ + +#endif /* LAC_SYM_HASH_DEFS_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_hash_precomputes.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_hash_precomputes.h new file mode 100644 index 000000000000..6fd93cc28175 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_hash_precomputes.h @@ -0,0 +1,176 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_hash_precomputes.h + * + * @defgroup LacHashDefs Hash Definitions + * + * @ingroup LacHash + * + * Constants for hash algorithms + * + ***************************************************************************/ +#ifndef LAC_SYM_HASH_PRECOMPUTES_H +#define LAC_SYM_HASH_PRECOMPUTES_H + +#include "lac_sym_hash.h" + +#define LAC_SYM_AES_CMAC_RB_128 0x87 /* constant used for */ + /* CMAC calculation */ + +#define LAC_SYM_HASH_MSBIT_MASK 0x80 /* Mask to check MSB top bit */ + /* zero or one */ + +#define LAC_SINGLE_BUFFER_HW_META_SIZE \ + (sizeof(icp_buffer_list_desc_t) + sizeof(icp_flat_buffer_desc_t)) +/**< size of memory to allocate for the HW buffer list that is sent to the + * QAT */ + +#define LAC_SYM_HASH_PRECOMP_MAX_WORKING_BUFFER \ + ((sizeof(lac_sym_hash_precomp_op_data_t) * 2) + \ + sizeof(lac_sym_hash_precomp_op_t)) +/**< maximum size of the working data for the HMAC precompute operations + * + * Maximum size of lac_sym_hash_precomp_op_data_t is 264 bytes. For hash + * precomputes there are 2 of these structrues and a further + * lac_sym_hash_precomp_op_t structure required. This comes to a total of 536 + * bytes. + * For the asynchronous version of the precomputes, the memory for the hash + * state prefix buffer is used as the working memory. There are 584 bytes + * which are alloacted for the hash state prefix buffer which is enough to + * carve up for the precomputes. + */ + +#define LAC_SYM_HASH_PRECOMP_MAX_AES_ECB_DATA \ + ((ICP_QAT_HW_AES_128_KEY_SZ) * (3)) +/**< Maximum size for the data that an AES ECB precompute is generated on */ + +/** + ***************************************************************************** + * @ingroup LacHashDefs + * Precompute type enum + * @description + * Enum used to distinguish between precompute types + * + *****************************************************************************/ +typedef enum { + LAC_SYM_HASH_PRECOMP_HMAC = 1, + /**< Hmac precompute operation. Copy state from hash state buffer */ + LAC_SYM_HASH_PRECOMP_AES_ECB, + /**< XCBC/CGM precompute, Copy state from data buffer */ +} lac_sym_hash_precomp_type_t; + +/** + ***************************************************************************** + * @ingroup LacHashDefs + * overall precompute management structure + * @description + * structure used to manage the precompute operations for a session + * + *****************************************************************************/ +typedef struct lac_sym_hash_precomp_op_s { + lac_hash_precompute_done_cb_t callbackFn; + /**< Callback function to be invoked when the final precompute completes + */ + + void *pCallbackTag; + /**< Opaque data to be passed back as a parameter in the callback */ + + QatUtilsAtomic opsPending; + /**< counter used to determine if the current precompute is the + * final one. */ + +} lac_sym_hash_precomp_op_t; + +/** + ***************************************************************************** + * @ingroup LacHashDefs + * hmac precompute structure as used by the QAT + * @description + * data used by the QAT for HMAC precomputes + * + * Must be allocated on an 8-byte aligned memory address. + * + *****************************************************************************/ +typedef struct lac_sym_hash_hmac_precomp_qat_s { + Cpa8U data[LAC_HASH_SHA512_BLOCK_SIZE]; + /**< data to be hashed - block size of data for the algorithm */ + /* NOTE: to save space we could have got the QAT to overwrite + * this with the hash state storage */ + icp_qat_fw_la_auth_req_params_t hashReqParams; + /**< Request parameters as read in by the QAT */ + Cpa8U bufferDesc[LAC_SINGLE_BUFFER_HW_META_SIZE]; + /**< Buffer descriptor structure */ + Cpa8U hashStateStorage[LAC_MAX_HASH_STATE_STORAGE_SIZE]; + /**< Internal buffer where QAT writes the intermediate partial + * state that is used in the precompute */ +} lac_sym_hash_hmac_precomp_qat_t; + +/** + ***************************************************************************** + * @ingroup LacHashDefs + * AES ECB precompute structure as used by the QAT + * @description + * data used by the QAT for AES ECB precomptes + * + * Must be allocated on an 8-byte aligned memory address. + * + *****************************************************************************/ +typedef struct lac_sym_hash_aes_precomp_qat_s { + Cpa8U contentDesc[LAC_SYM_QAT_MAX_CIPHER_SETUP_BLK_SZ]; + /**< Content descriptor for a cipher operation */ + Cpa8U data[LAC_SYM_HASH_PRECOMP_MAX_AES_ECB_DATA]; + /**< The data to be ciphered is conatined here and the result is + * written in place back into this buffer */ + icp_qat_fw_la_cipher_req_params_t cipherReqParams; + /**< Request parameters as read in by the QAT */ + Cpa8U bufferDesc[LAC_SINGLE_BUFFER_HW_META_SIZE]; + /**< Buffer descriptor structure */ +} lac_sym_hash_aes_precomp_qat_t; + +/** + ***************************************************************************** + * @ingroup LacHashDefs + * overall structure for managing a single precompute operation + * @description + * overall structure for managing a single precompute operation + * + * Must be allocated on an 8-byte aligned memory address. + * + *****************************************************************************/ +typedef struct lac_sym_hash_precomp_op_data_s { + sal_crypto_service_t *pInstance; + /**< Instance handle for the operation */ + Cpa8U reserved[4]; + /**< padding to align later structures on minimum 8-Byte address */ + lac_sym_hash_precomp_type_t opType; + /**< operation type to determine the precompute type in the callback */ + lac_sym_hash_precomp_op_t *pOpStatus; + /**< structure containing the counter and the condition for the overall + * precompute operation. This is a pointer because the memory structure + * may be shared between precomputes when there are more than 1 as in + * the + * case of HMAC */ + union { + lac_sym_hash_hmac_precomp_qat_t hmacQatData; + /**< Data sent to the QAT for hmac precomputes */ + lac_sym_hash_aes_precomp_qat_t aesQatData; + /**< Data sent to the QAT for AES ECB precomputes */ + } u; + + /**< ASSUMPTION: The above structures are 8 byte aligned if the overall + * struct is 8 byte aligned, as there are two 4 byte fields before this + * union */ + Cpa32U stateSize; + /**< Size of the state to be copied into the state pointer in the + * content + * descriptor */ + Cpa8U *pState; + /**< pointer to the state in the content descriptor where the result of + * the precompute should be copied to */ +} lac_sym_hash_precomp_op_data_t; + +#endif /* LAC_SYM_HASH_PRECOMPUTES_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_key.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_key.h new file mode 100644 index 000000000000..bae0d8faabc7 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_key.h @@ -0,0 +1,184 @@ +/*************************************************************************** + * + * <COPYRIGHT_TAG> + * + ***************************************************************************/ + +/** + ***************************************************************************** + * @file lac_sym_key.h + * + * @defgroup LacSymKey Key Generation + * + * @ingroup LacSym + * + * @lld_start + * + * @lld_overview + * + * Key generation component is reponsible for SSL, TLS & MGF operations. All + * memory required for the keygen operations is got from the keygen cookie + * structure which is carved up as required. + * + * For SSL the QAT accelerates the nested hash function with MD5 as the + * outer hash and SHA1 as the inner hash. + * + * Refer to sections in draft-freier-ssl-version3-02.txt: + * 6.1 Asymmetric cryptographic computations - This refers to coverting + * the pre master secret to the master secret. + * 6.2.2 Converting the master secret into keys and MAC secrets - Using + * the master secret to generate the key material. + * + * For TLS the QAT accelerates the PRF function as described in + * rfc4346 - TLS version 1.1 (this obsoletes rfc2246 - TLS version 1.0) + * 5. HMAC and the pseudorandom function - For the TLS PRF and getting + * S1 and S2 from the secret. + * 6.3. Key calculation - For how the key material is generated + * 7.4.9. Finished - How the finished message uses the TLS PRF + * 8.1. Computing the master secret + * + * + * @lld_dependencies + * \ref LacSymQatHash: for building up hash content descriptor + * \ref LacMem: for virt to phys coversions + * + * @lld_initialisation + * The reponse handler is registered with Symmetric. The Maximum SSL is + * allocated. A structure is allocated containing all the TLS lables that + * are supported. On shutdown the memory for these structures are freed. + * + * @lld_module_algorithms + * @lld_process_context + * + * @lld_end + * + * + *****************************************************************************/ +#ifndef LAC_SYM_KEY_H_ +#define LAC_SYM_KEY_H_ + +#include "icp_qat_fw_la.h" +#include "cpa_cy_key.h" + +/**< @ingroup LacSymKey + * Label for SSL. Size is 136 bytes for 16 iterations, which can theroretically + * generate up to 256 bytes of output data. QAT will generate a maximum of + * 255 bytes */ + +#define LAC_SYM_KEY_TLS_MASTER_SECRET_LABEL ("master secret") +/**< @ingroup LacSymKey + * Label for TLS Master Secret Key Derivation, as defined in RFC4346 */ + +#define LAC_SYM_KEY_TLS_KEY_MATERIAL_LABEL ("key expansion") +/**< @ingroup LacSymKey + * Label for TLS Key Material Generation, as defined in RFC4346. */ + +#define LAC_SYM_KEY_TLS_CLIENT_FIN_LABEL ("client finished") +/**< @ingroup LacSymKey + * Label for TLS Client finished Message, as defined in RFC4346. */ + +#define LAC_SYM_KEY_TLS_SERVER_FIN_LABEL ("server finished") +/**< @ingroup LacSymKey + * Label for TLS Server finished Message, as defined in RFC4346. */ + +/* +******************************************************************************* +* Define Constants and Macros for SSL, TLS and MGF +******************************************************************************* +*/ + +#define LAC_SYM_KEY_NO_HASH_BLK_OFFSET_QW 0 +/**< Used to indicate there is no hash block offset in the content descriptor + */ + +/* +******************************************************************************* +* Define Constant lengths for HKDF TLS v1.3 sublabels. +******************************************************************************* +*/ +#define HKDF_SUB_LABEL_KEY_LENGTH ((Cpa8U)13) +#define HKDF_SUB_LABEL_IV_LENGTH ((Cpa8U)12) +#define HKDF_SUB_LABEL_RESUMPTION_LENGTH ((Cpa8U)20) +#define HKDF_SUB_LABEL_FINISHED_LENGTH ((Cpa8U)18) +#define HKDF_SUB_LABELS_ALL \ + (CPA_CY_HKDF_SUBLABEL_KEY | CPA_CY_HKDF_SUBLABEL_IV | \ + CPA_CY_HKDF_SUBLABEL_RESUMPTION | CPA_CY_HKDF_SUBLABEL_FINISHED) +#define LAC_KEY_HKDF_SUBLABELS_NUM 4 +#define LAC_KEY_HKDF_DIGESTS 0 +#define LAC_KEY_HKDF_CIPHERS_MAX (CPA_CY_HKDF_TLS_AES_128_CCM_8_SHA256 + 1) +#define LAC_KEY_HKDF_SUBLABELS_MAX (LAC_KEY_HKDF_SUBLABELS_NUM + 1) + +/** + ****************************************************************************** + * @ingroup LacSymKey + * TLS label struct + * + * @description + * This structure is used to hold the various TLS labels. Each field is + * on an 8 byte boundary provided the structure itslef is 8 bytes aligned. + *****************************************************************************/ +typedef struct lac_sym_key_tls_labels_s { + Cpa8U masterSecret[ICP_QAT_FW_LA_TLS_LABEL_LEN_MAX]; + /**< Master secret label */ + Cpa8U keyMaterial[ICP_QAT_FW_LA_TLS_LABEL_LEN_MAX]; + /**< Key material label */ + Cpa8U clientFinished[ICP_QAT_FW_LA_TLS_LABEL_LEN_MAX]; + /**< client finished label */ + Cpa8U serverFinished[ICP_QAT_FW_LA_TLS_LABEL_LEN_MAX]; + /**< server finished label */ +} lac_sym_key_tls_labels_t; + +/** + ****************************************************************************** + * @ingroup LacSymKey + * TLS HKDF sub label struct + * + * @description + * This structure is used to hold the various TLS HKDF sub labels. + * Each field is on an 8 byte boundary. + *****************************************************************************/ +typedef struct lac_sym_key_tls_hkdf_sub_labels_s { + CpaCyKeyGenHKDFExpandLabel keySublabel256; + /**< CPA_CY_HKDF_SUBLABEL_KEY */ + CpaCyKeyGenHKDFExpandLabel ivSublabel256; + /**< CPA_CY_HKDF_SUBLABEL_IV */ + CpaCyKeyGenHKDFExpandLabel resumptionSublabel256; + /**< CPA_CY_HKDF_SUBLABEL_RESUMPTION */ + CpaCyKeyGenHKDFExpandLabel finishedSublabel256; + /**< CPA_CY_HKDF_SUBLABEL_FINISHED */ + CpaCyKeyGenHKDFExpandLabel keySublabel384; + /**< CPA_CY_HKDF_SUBLABEL_KEY */ + CpaCyKeyGenHKDFExpandLabel ivSublabel384; + /**< CPA_CY_HKDF_SUBLABEL_IV */ + CpaCyKeyGenHKDFExpandLabel resumptionSublabel384; + /**< CPA_CY_HKDF_SUBLABEL_RESUMPTION */ + CpaCyKeyGenHKDFExpandLabel finishedSublabel384; + /**< CPA_CY_HKDF_SUBLABEL_FINISHED */ + CpaCyKeyGenHKDFExpandLabel keySublabelChaChaPoly; + /**< CPA_CY_HKDF_SUBLABEL_KEY */ + CpaCyKeyGenHKDFExpandLabel ivSublabelChaChaPoly; + /**< CPA_CY_HKDF_SUBLABEL_IV */ + CpaCyKeyGenHKDFExpandLabel resumptionSublabelChaChaPoly; + /**< CPA_CY_HKDF_SUBLABEL_RESUMPTION */ + CpaCyKeyGenHKDFExpandLabel finishedSublabelChaChaPoly; + /**< CPA_CY_HKDF_SUBLABEL_FINISHED */ + Cpa64U sublabelPhysAddr256; + /**< Physical address of the SHA-256 subLabels */ + Cpa64U sublabelPhysAddr384; + /**< Physical address of the SHA-384 subLabels */ + Cpa64U sublabelPhysAddrChaChaPoly; + /**< Physical address of the ChaChaPoly subLabels */ +} lac_sym_key_tls_hkdf_sub_labels_t; + +/** + ****************************************************************************** + * @ingroup LacSymKey + * This function prints the stats to standard out. + * + * @retval CPA_STATUS_SUCCESS Status Success + * @retval CPA_STATUS_FAIL General failure + * + *****************************************************************************/ +void LacKeygen_StatsShow(CpaInstanceHandle instanceHandle); + +#endif diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_partial.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_partial.h new file mode 100644 index 000000000000..b3088784a273 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_partial.h @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_partial.h + * + * @defgroup LacSymPartial Partial Packets + * + * @ingroup LacSymCommon + * + * Partial packet handling code + * + * @lld_start + * + * <b>Partials In Flight</b>\n + * The API states that for partial packets the client should not submit + * the next partial request until the callback for the current partial has + * been called. We have chosen to enforce this rather than letting the user + * proceed where they would get an incorrect digest, cipher result. + * + * Maintain a SpinLock for partials in flight per session. Try and acquire this + * SpinLock. If it cant be acquired return an error straight away to the client + * as there is already a partial in flight. There is no blocking in the data + * path for this. + * + * By preventing any other partials from coming in while a partial is in flight + * we can check and change the state of the session without having to lock + * round it (dont want to have to lock and block in the data path). The state + * of the session indicates the previous packet type that a request was + * successfully completed for. The last packet type is only updated for partial + * packets. This state determines the packet types that can be accepted. + * e.g a last partial will not be accepted unless the previous packet was a + * partial. By only allowing one partial packet to be in flight, there is no + * need to lock around the update of the previous packet type for the session. + * + * The ECB Cipher mode, ciphers each block separately. No state is maintained + * between blocks. There is no need to wait for the callback for previous + * partial in ECB mode as the result of the previous partial has no impact on + * it. The API and our implementation only allows 1 partial packet to be in + * flight per session, therefore a partial packet request for ECB mode must + * be fully completed (ie. callback called) before the next partial request + * can be issued. + * + * <b>Partial Ordering</b>\n + * The ordering that the user submits partial packets will be checked. + * (we could have let the user proceed where they will get an incorrect + * digest/cipher result but chose against this). + * + * -# Maintain the last packet type of a partial operation for the session. If + * there have been no previous partials, we will accept only first partials + * -# The state must be set to partial before we will accept a final partial. + * i.e. a partial request must have already completed. + * + * The last packet type is updated in the callback for partial packets as this + * is the only place we can guarantee that a partial packet operation has been + * completed. When a partial completes the state can be updated from FULL to + * PARTIAL. The SpinLock for partial packets in flight for the session can be + * unlocked at this point. On a final Partial request the last packet type is + * reset back to FULL. NOTE: This is not done at the same time as the check in + * the perform as if an error occurs we would have to roll back the state + * + * For Hash mode it is possible to interleave full and a single partial + * packet stream in a session as the hash state buffer is updated for partial + * packets. It is not touched by full packets. For cipher mode, as the client + * manages the state, they can interleave full and a single partial packets. + * For ARC4, the state is managed internally and the packet type will always + * be set to partial internally. + * + * @lld_end + * + ***************************************************************************/ + +/***************************************************************************/ + +#ifndef LAC_SYM_PARTIAL_H +#define LAC_SYM_PARTIAL_H + +#include "cpa.h" +#include "cpa_cy_sym.h" + +/***************************************************************************/ + +/** +******************************************************************************* +* @ingroup LacSymPartial +* check if partial packet request is valid for a session +* +* @description +* This function checks to see if there is a partial packet request in +* flight and then if the partial state is correct +* +* @param[in] packetType Partial packet request +* @param[in] partialState Partial state of session +* +* @retval CPA_STATUS_SUCCESS Normal Operation +* @retval CPA_STATUS_INVALID_PARAM Invalid Parameter +* +*****************************************************************************/ +CpaStatus LacSym_PartialPacketStateCheck(CpaCySymPacketType packetType, + CpaCySymPacketType partialState); + +/** +******************************************************************************* +* @ingroup LacSymPartial +* update the state of the partial packet in a session +* +* @description +* This function is called in callback operation. It updates the state +* of a partial packet in a session and indicates that there is no +* longer a partial packet in flight for the session +* +* @param[in] packetType Partial packet request +* @param[out] pPartialState Pointer to partial state of session +* +*****************************************************************************/ +void LacSym_PartialPacketStateUpdate(CpaCySymPacketType packetType, + CpaCySymPacketType *pPartialState); + +#endif /* LAC_SYM_PARTIAL_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat.h new file mode 100644 index 000000000000..af49764b6498 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat.h @@ -0,0 +1,209 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + ***************************************************************************** + * @file lac_sym_qat.h + * + * @defgroup LacSymQat Symmetric QAT + * + * @ingroup LacSym + * + * Interfaces for populating the qat structures for a symmetric operation + * + * @lld_start + * + * @lld_overview + * This file documents the interfaces for populating the qat structures + * that are common for all symmetric operations. + * + * @lld_dependencies + * - \ref LacSymQatHash "Hash QAT Comms" Sym Qat commons for Hash + * - \ref LacSymQat_Cipher "Cipher QAT Comms" Sym Qat commons for Cipher + * - OSAL: logging + * - \ref LacMem "Memory" - Inline memory functions + * + * @lld_initialisation + * This component is initialied during the LAC initialisation sequence. It + * is called by the Symmetric Initialisation function. + * + * @lld_module_algorithms + * + * @lld_process_context + * Refer to \ref LacHash "Hash" and \ref LacCipher "Cipher" for sequence + * diagrams to see their interactions with this code. + * + * + * @lld_end + * + *****************************************************************************/ + +/*****************************************************************************/ + +#ifndef LAC_SYM_QAT_H +#define LAC_SYM_QAT_H + +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ + +#include "cpa.h" +#include "cpa_cy_sym.h" +#include "icp_accel_devices.h" +#include "icp_qat_fw_la.h" +#include "icp_qat_hw.h" +#include "lac_session.h" +#include "sal_qat_cmn_msg.h" +#include "lac_common.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ + +#define LAC_SYM_DEFAULT_QAT_PTR_TYPE QAT_COMN_PTR_TYPE_SGL +#define LAC_SYM_DP_QAT_PTR_TYPE QAT_COMN_PTR_TYPE_FLAT +#define LAC_SYM_KEY_QAT_PTR_TYPE QAT_COMN_PTR_TYPE_FLAT +/**< @ingroup LacSymQat + * LAC SYM Source & Destination buffer type (FLAT/SGL) */ + +#define LAC_QAT_SYM_REQ_SZ_LW 32 +#define SYM_TX_MSG_SIZE (LAC_QAT_SYM_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES) +#define NRBG_TX_MSG_SIZE (LAC_QAT_SYM_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES) + +#define LAC_QAT_SYM_RESP_SZ_LW 8 +#define SYM_RX_MSG_SIZE (LAC_QAT_SYM_RESP_SZ_LW * LAC_LONG_WORD_IN_BYTES) +#define NRBG_RX_MSG_SIZE (LAC_QAT_SYM_RESP_SZ_LW * LAC_LONG_WORD_IN_BYTES) + +/** + ******************************************************************************* + * @ingroup LacSymQat + * Symmetric crypto response handler + * + * @description + * This function handles the symmetric crypto response + * + * @param[in] trans_handle transport handle (if ICP_QAT_DBG set) + * @param[in] instanceHandle void* pRespMsg + * + * + *****************************************************************************/ +void LacSymQat_SymRespHandler(void *pRespMsg); + +/** + ******************************************************************************* + * @ingroup LacSymQat + * Initialise the Symmetric QAT code + * + * @description + * This function initialises the symmetric QAT code + * + * @param[in] device Pointer to the acceleration device + * structure + * @param[in] instanceHandle Instance handle + * @param[in] numSymRequests Number of concurrent requests a pair + * (tx and rx) need to support + * + * @return CPA_STATUS_SUCCESS Operation successful + * @return CPA_STATUS_FAIL Initialisation Failed + * + *****************************************************************************/ +CpaStatus LacSymQat_Init(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacSymQat + * Register a response handler function for a symmetric command ID + * + * @description + * This function registers a response handler function for a symmetric + * operation. + * + * Note: This operation should only be performed once by the init function + * of a component. There is no corresponding deregister function, but + * registering a NULL function pointer will have the same effect. There + * MUST not be any requests in flight when calling this function. + * + * @param[in] lacCmdId Command Id of operation + * @param[in] pCbHandler callback handler function + * + * @return None + * + *****************************************************************************/ +void LacSymQat_RespHandlerRegister(icp_qat_fw_la_cmd_id_t lacCmdId, + sal_qat_resp_handler_func_t pCbHandler); + +/** + ****************************************************************************** + * @ingroup LacSymQat + * get the QAT packet type + * + * @description + * This function returns the QAT packet type for a LAC packet type. The + * LAC packet type does not indicate a first partial. therefore for a + * partial request, the previous packet type needs to be looked at to + * figure out if the current partial request is a first partial. + * + * + * @param[in] packetType LAC Packet type + * @param[in] packetState LAC Previous Packet state + * @param[out] pQatPacketType Packet type using the QAT macros + * + * @return none + * + *****************************************************************************/ +void LacSymQat_packetTypeGet(CpaCySymPacketType packetType, + CpaCySymPacketType packetState, + Cpa32U *pQatPacketType); + +/** + ****************************************************************************** + * @ingroup LacSymQat + * Populate the command flags based on the packet type + * + * @description + * This function populates the following flags in the Symmetric Crypto + * service_specif_flags field of the common header of the request: + * - LA_PARTIAL + * - UPDATE_STATE + * - RET_AUTH_RES + * - CMP_AUTH_RES + * based on looking at the input params listed below. + * + * @param[in] qatPacketType Packet type + * @param[in] cmdId Command Id + * @param[in] cipherAlgorithm Cipher Algorithm + * @param[out] pLaCommandFlags Command Flags + * + * @return none + * + *****************************************************************************/ +void LacSymQat_LaPacketCommandFlagSet(Cpa32U qatPacketType, + icp_qat_fw_la_cmd_id_t laCmdId, + CpaCySymCipherAlgorithm cipherAlgorithm, + Cpa16U *pLaCommandFlags, + Cpa32U ivLenInBytes); + +/** + ****************************************************************************** + * @ingroup LacSymQat + * + * + * @description + * defaults the common request service specific flags + * + * @param[in] laCmdFlags Common request service specific flags + * @param[in] symOp Type of operation performed e.g hash or cipher + * + * @return none + * + *****************************************************************************/ + +void LacSymQat_LaSetDefaultFlags(icp_qat_fw_serv_specif_flags *laCmdFlags, + CpaCySymOp symOp); + +#endif /* LAC_SYM_QAT_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_cipher.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_cipher.h new file mode 100644 index 000000000000..2360aa53633f --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_cipher.h @@ -0,0 +1,291 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + ***************************************************************************** + * @file lac_sym_qat_cipher.h + * + * @defgroup LacSymQat_Cipher Cipher QAT + * + * @ingroup LacSymQat + * + * external interfaces for populating QAT structures for cipher operations. + * + *****************************************************************************/ + +/*****************************************************************************/ + +#ifndef LAC_SYM_QAT_CIPHER_H +#define LAC_SYM_QAT_CIPHER_H + +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ + +#include "cpa_cy_sym.h" +#include "icp_qat_fw_la.h" +#include "lac_session.h" +#include "lac_sal_types_crypto.h" + +/* + ************************************************************************** + * @ingroup LacSymQat_Cipher + * + * @description + * Defines for building the cipher request params cache + * + ************************************************************************** */ + +#define LAC_SYM_QAT_CIPHER_NEXT_ID_BIT_OFFSET 24 +#define LAC_SYM_QAT_CIPHER_CURR_ID_BIT_OFFSET 16 +#define LAC_SYM_QAT_CIPHER_STATE_SIZE_BIT_OFFSET 8 +#define LAC_SYM_QAT_CIPHER_OFFSET_IN_DRAM_GCM_SPC 9 +#define LAC_SYM_QAT_CIPHER_OFFSET_IN_DRAM_CHACHA_SPC 2 +#define LAC_SYM_QAT_CIPHER_STATE_SIZE_SPC 48 +/** + ****************************************************************************** + * @ingroup LacSymQat_Cipher + * Retrieve the cipher block size in bytes for a given algorithm + * + * @description + * This function returns a hard-coded block size for the specific cipher + * algorithm + * + * @param[in] cipherAlgorithm Cipher algorithm for the current session + * + * @retval The block size, in bytes, for the given cipher algorithm + * + *****************************************************************************/ +Cpa8U +LacSymQat_CipherBlockSizeBytesGet(CpaCySymCipherAlgorithm cipherAlgorithm); + +/** + ****************************************************************************** + * @ingroup LacSymQat_Cipher + * Retrieve the cipher IV/state size in bytes for a given algorithm + * + * @description + * This function returns a hard-coded IV/state size for the specific cipher + * algorithm + * + * @param[in] cipherAlgorithm Cipher algorithm for the current session + * + * @retval The IV/state size, in bytes, for the given cipher algorithm + * + *****************************************************************************/ +Cpa32U LacSymQat_CipherIvSizeBytesGet(CpaCySymCipherAlgorithm cipherAlgorithm); + +/** + ****************************************************************************** + * @ingroup LacSymQat_Cipher + * Populate the cipher request params structure + * + * @description + * This function is passed a pointer to the 128B request block. + * (This memory must be allocated prior to calling this function). It + * populates: + * - the cipher fields of the req_params block in the request. No + * need to zero this first, all fields will be populated. + * - the corresponding CIPH_IV_FLD flag in the serv_specif_flags field + * of the common header. + * To do this it uses the parameters described below and the following + *fields from the request block which must be populated prior to calling this + *function: + * - cd_ctrl.cipher_state_sz + * - UPDATE_STATE flag in comn_hdr.serv_specif_flags + * + * + * @param[in] pReq Pointer to request block. + * * + * @param[in] cipherOffsetInBytes Offset to cipher data in user data buffer + * + * @param[in] cipherLenInBytes Length of cipher data in buffer + * + * @param[in] ivBufferPhysAddr Physical address of aligned IV/state + * buffer + * @param[in] pIvBufferVirt Virtual address of aligned IV/state + * buffer + * @retval void + * + *****************************************************************************/ +CpaStatus LacSymQat_CipherRequestParamsPopulate(icp_qat_fw_la_bulk_req_t *pReq, + Cpa32U cipherOffsetInBytes, + Cpa32U cipherLenInBytes, + Cpa64U ivBufferPhysAddr, + Cpa8U *pIvBufferVirt); + +/** + ****************************************************************************** + * @ingroup LacSymQat_Cipher + * Derive initial ARC4 cipher state from a base key + * + * @description + * An initial state for an ARC4 cipher session is derived from the base + * key provided by the user, using the ARC4 Key Scheduling Algorithm (KSA) + * + * @param[in] pKey The base key provided by the user + * + * @param[in] keyLenInBytes The length of the base key provided. + * The range of valid values is 1-256 bytes + * + * @param[out] pArc4CipherState The initial state is written to this buffer, + * including i and j values, and 6 bytes of padding + * so 264 bytes must be allocated for this buffer + * by the caller + * + * @retval void + * + *****************************************************************************/ +void LacSymQat_CipherArc4StateInit(const Cpa8U *pKey, + Cpa32U keyLenInBytes, + Cpa8U *pArc4CipherState); + +/** + ****************************************************************************** + * @ingroup LacSymQat_CipherXTSModeUpdateKeyLen + * Update the initial XTS key after the first partial has been received. + * + * @description + * For XTS mode using partial packets, after the first partial response + * has been received, the the key length needs to be halved for subsequent + * partials. + * + * @param[in] pSessionDesc The session descriptor. + * + * @param[in] newKeySizeInBytes The new key size.. + * + * @retval void + * + *****************************************************************************/ +void LacSymQat_CipherXTSModeUpdateKeyLen(lac_session_desc_t *pSessionDesc, + Cpa32U newKeySizeInBytes); + +/** + ****************************************************************************** + * @ingroup LacSymQat_Cipher + * LacSymQat_CipherCtrlBlockInitialize() + * + * @description + * intialize the cipher control block with all zeros + * + * @param[in] pMsg Pointer to the common request message + * + * @retval void + * + *****************************************************************************/ +void LacSymQat_CipherCtrlBlockInitialize(icp_qat_fw_la_bulk_req_t *pMsg); + +/** + ****************************************************************************** + * @ingroup LacSymQat_Cipher + * LacSymQat_CipherCtrlBlockWrite() + * + * @description + * This function populates the cipher control block of the common request + * message + * + * @param[in] pMsg Pointer to the common request message + * + * @param[in] cipherAlgorithm Cipher Algorithm to be used + * + * @param[in] targetKeyLenInBytes cipher key length in bytes of selected + * algorithm + * + * @param[out] nextSlice SliceID for next control block + * entry. This value is known only by + * the calling component + * + * @param[out] cipherCfgOffsetInQuadWord Offset into the config table in QW + * + * @retval void + * + *****************************************************************************/ +void LacSymQat_CipherCtrlBlockWrite(icp_qat_la_bulk_req_ftr_t *pMsg, + Cpa32U cipherAlgorithm, + Cpa32U targetKeyLenInBytes, + icp_qat_fw_slice_t nextSlice, + Cpa8U cipherCfgOffsetInQuadWord); + +/** + ****************************************************************************** + * @ingroup LacSymQat_Cipher + * LacSymQat_CipherHwBlockPopulateCfgData() + * + * @description + * Populate the physical HW block with config data + * + * @param[in] pSession Pointer to the session data + * + * @param[in] pCipherHwBlock pointer to the hardware control block + * in the common message + * + * @param[in] pSizeInBytes + * + * @retval void + * + *****************************************************************************/ +void LacSymQat_CipherHwBlockPopulateCfgData(lac_session_desc_t *pSession, + const void *pCipherHwBlock, + Cpa32U *pSizeInBytes); + +/** + ****************************************************************************** + * @ingroup LacSymQat_Cipher + * LacSymQat_CipherGetCfgData() + * + * @description + * setup the config data for cipher + * + * @param[in] pSession Pointer to the session data + * + * @param[in] pAlgorithm * + * @param[in] pMode + * @param[in] pDir + * @param[in] pKey_convert + * + * @retval void + * + *****************************************************************************/ +void LacSymQat_CipherGetCfgData(lac_session_desc_t *pSession, + icp_qat_hw_cipher_algo_t *pAlgorithm, + icp_qat_hw_cipher_mode_t *pMode, + icp_qat_hw_cipher_dir_t *pDir, + icp_qat_hw_cipher_convert_t *pKey_convert); + +/** + ****************************************************************************** + * @ingroup LacSymQat_Cipher + * LacSymQat_CipherHwBlockPopulateKeySetup() + * + * @description + * populate the key setup data in the cipher hardware control block + * in the common request message + * + * param[in] pCipherSetupData Pointer to cipher setup data + * + * @param[in] targetKeyLenInBytes Target key length. If key length given + * in cipher setup data is less that this, + * the key will be "rounded up" to this + * target length by padding it with 0's. + * In normal no-padding case, the target + * key length MUST match the key length + * in the cipher setup data. + * + * @param[in] pCipherHwBlock Pointer to the cipher hardware block + * + * @param[out] pCipherHwBlockSizeBytes Size in bytes of cipher setup block + * + * + * @retval void + * + *****************************************************************************/ +void LacSymQat_CipherHwBlockPopulateKeySetup( + const CpaCySymCipherSetupData *pCipherSetupData, + Cpa32U targetKeyLenInBytes, + const void *pCipherHwBlock, + Cpa32U *pCipherHwBlockSizeBytes); + +#endif /* LAC_SYM_QAT_CIPHER_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_hash.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_hash.h new file mode 100644 index 000000000000..147e10f573f0 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_hash.h @@ -0,0 +1,309 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + ***************************************************************************** + * @file lac_sym_qat_hash.h + * + * @defgroup LacSymQatHash Hash QAT + * + * @ingroup LacSymQat + * + * interfaces for populating qat structures for a hash operation + * + *****************************************************************************/ + +/*****************************************************************************/ + +#ifndef LAC_SYM_QAT_HASH_H +#define LAC_SYM_QAT_HASH_H + +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ + +#include "cpa.h" +#include "cpa_cy_sym.h" +#include "icp_qat_fw_la.h" +#include "icp_qat_hw.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ +#include "lac_common.h" + +/** + ****************************************************************************** + * @ingroup LacSymQatHash + * hash precomputes + * + * @description + * This structure contains infomation on the hash precomputes + * + *****************************************************************************/ +typedef struct lac_sym_qat_hash_precompute_info_s { + Cpa8U *pState1; + /**< state1 pointer */ + Cpa32U state1Size; + /**< state1 size */ + Cpa8U *pState2; + /**< state2 pointer */ + Cpa32U state2Size; + /**< state2 size */ +} lac_sym_qat_hash_precompute_info_t; + +/** + ****************************************************************************** + * @ingroup LacSymQatHash + * hash state prefix buffer info + * + * @description + * This structure contains infomation on the hash state prefix aad buffer + * + *****************************************************************************/ +typedef struct lac_sym_qat_hash_state_buffer_info_s { + Cpa64U pDataPhys; + /**< Physical pointer to the hash state prefix buffer */ + Cpa8U *pData; + /**< Virtual pointer to the hash state prefix buffer */ + Cpa8U stateStorageSzQuadWords; + /**< hash state storage size in quad words */ + Cpa8U prefixAadSzQuadWords; + /**< inner prefix/aad and outer prefix size in quad words */ +} lac_sym_qat_hash_state_buffer_info_t; + +/** + ****************************************************************************** + * @ingroup LacSymQatHash + * Init the hash specific part of the content descriptor. + * + * @description + * This function populates the hash specific fields of the control block + * and the hardware setup block for a digest session. This function sets + * the size param to hold the size of the hash setup block. + * + * In the case of hash only, the content descriptor will contain just a + * hash control block and hash setup block. In the case of chaining it + * will contain the hash control block and setup block along with the + * control block and setup blocks of additional services. + * + * Note: The memory for the content descriptor MUST be allocated prior to + * calling this function. The memory for the hash control block and hash + * setup block MUST be set to 0 prior to calling this function. + * + * @image html contentDescriptor.png "Content Descriptor" + * + * @param[in] pMsg Pointer to req Parameter Footer + * + * @param[in] pHashSetupData Pointer to the hash setup data as + * defined in the LAC API. + * + * @param[in] pHwBlockBase Pointer to the base of the hardware + * setup block + * + * @param[in] hashBlkOffsetInHwBlock Offset in quad-words from the base of + * the hardware setup block where the + * hash block will start. This offset + * is stored in the control block. It + * is used to figure out where to write + * that hash setup block. + * + * @param[in] nextSlice SliceID for next control block + * entry This value is known only by + * the calling component + * + * @param[in] qatHashMode QAT hash mode + * + * @param[in] useSymConstantsTable Indicate if Shared-SRAM constants table + * is used for this session. If TRUE, the + * h/w setup block is NOT populated + * + * @param[in] useOptimisedContentDesc Indicate if optimised content desc + * is used for this session. + * + * @param[in] pPrecompute For auth mode, this is the pointer + * to the precompute data. Otherwise this + * should be set to NULL + * + * @param[out] pHashBlkSizeInBytes size in bytes of hash setup block + * + * @return void + * + *****************************************************************************/ +void +LacSymQat_HashContentDescInit(icp_qat_la_bulk_req_ftr_t *pMsg, + CpaInstanceHandle instanceHandle, + const CpaCySymHashSetupData *pHashSetupData, + void *pHwBlockBase, + Cpa32U hashBlkOffsetInHwBlock, + icp_qat_fw_slice_t nextSlice, + icp_qat_hw_auth_mode_t qatHashMode, + CpaBoolean useSymConstantsTable, + CpaBoolean useOptimisedContentDesc, + lac_sym_qat_hash_precompute_info_t *pPrecompute, + Cpa32U *pHashBlkSizeInBytes); + +/** + ****************************************************************************** + * @ingroup LacSymQatHash + * Calculate the size of the hash state prefix aad buffer + * + * @description + * This function inspects the hash control block and based on the values + * in the fields, it calculates the size of the hash state prefix aad + * buffer. + * + * A partial packet processing request is possible at any stage during a + * hash session. In this case, there will always be space for the hash + * state storage field of the hash state prefix buffer. When there is + * AAD data just the inner prefix AAD data field is used. + * + * @param[in] pMsg Pointer to the Request Message + * + * @param[out] pHashStateBuf Pointer to hash state prefix buffer info + * structure. + * + * @return None + * + *****************************************************************************/ +void LacSymQat_HashStatePrefixAadBufferSizeGet( + icp_qat_la_bulk_req_ftr_t *pMsg, + lac_sym_qat_hash_state_buffer_info_t *pHashStateBuf); + +/** + ****************************************************************************** + * @ingroup LacSymQatHash + * Populate the fields of the hash state prefix buffer + * + * @description + * This function populates the inner prefix/aad fields and/or the outer + * prefix field of the hash state prefix buffer. + * + * @param[in] pHashStateBuf Pointer to hash state prefix buffer info + * structure. + * + * @param[in] pMsg Pointer to the Request Message + * + * @param[in] pInnerPrefixAad Pointer to the Inner Prefix or Aad data + * This is NULL where if the data size is 0 + * + * @param[in] innerPrefixSize Size of inner prefix/aad data in bytes + * + * @param[in] pOuterPrefix Pointer to the Outer Prefix data. This is + * NULL where the data size is 0. + * + * @param[in] outerPrefixSize Size of the outer prefix data in bytes + * + * @return void + * + *****************************************************************************/ +void LacSymQat_HashStatePrefixAadBufferPopulate( + lac_sym_qat_hash_state_buffer_info_t *pHashStateBuf, + icp_qat_la_bulk_req_ftr_t *pMsg, + Cpa8U *pInnerPrefixAad, + Cpa8U innerPrefixSize, + Cpa8U *pOuterPrefix, + Cpa8U outerPrefixSize); + +/** + ****************************************************************************** + * @ingroup LacSymQatHash + * Populate the hash request params structure + * + * @description + * This function is passed a pointer to the 128B Request block. + * (This memory must be allocated prior to calling this function). It + * populates the fields of this block using the parameters as described + * below. It is also expected that this structure has been set to 0 + * prior to calling this function. + * + * + * @param[in] pReq Pointer to 128B request block. + * + * @param[in] authOffsetInBytes start offset of data that the digest is to + * be computed on. + * + * @param[in] authLenInBytes Length of data digest calculated on + * + * @param[in] pService Pointer to service data + * + * @param[in] pHashStateBuf Pointer to hash state buffer info. This + * structure contains the pointers and sizes. + * If there is no hash state prefix buffer + * required, this parameter can be set to NULL + * + * @param[in] qatPacketType Packet type using QAT macros. The hash + * state buffer pointer and state size will be + * different depending on the packet type + * + * @param[in] hashResultSize Size of the final hash result in bytes. + * + * @param[in] digestVerify Indicates if verify is enabled or not + * + * @param[in] pAuthResult Virtual pointer to digest + * + * @return CPA_STATUS_SUCCESS or CPA_STATUS_FAIL + * + *****************************************************************************/ +CpaStatus LacSymQat_HashRequestParamsPopulate( + icp_qat_fw_la_bulk_req_t *pReq, + Cpa32U authOffsetInBytes, + Cpa32U authLenInBytes, + sal_service_t *pService, + lac_sym_qat_hash_state_buffer_info_t *pHashStateBuf, + Cpa32U qatPacketType, + Cpa32U hashResultSize, + CpaBoolean digestVerify, + Cpa8U *pAuthResult, + CpaCySymHashAlgorithm alg, + void *data); + +/** + ****************************************************************************** + * @ingroup LacSymQatHash + * + * + * @description + * This fn returns the QAT values for hash algorithm and nested fields + * + * + * @param[in] pInstance Pointer to service instance. + * + * @param[in] qatHashMode value for hash mode on the fw qat + *interface. + * + * @param[in] apiHashMode value for hash mode on the QA API. + * + * @param[in] apiHashAlgorithm value for hash algorithm on the QA API. + * + * @param[out] pQatAlgorithm Pointer to return fw qat value for + *algorithm. + * + * @param[out] pQatNested Pointer to return fw qat value for nested. + * + * + * @return + * none + * + *****************************************************************************/ +void LacSymQat_HashGetCfgData(CpaInstanceHandle pInstance, + icp_qat_hw_auth_mode_t qatHashMode, + CpaCySymHashMode apiHashMode, + CpaCySymHashAlgorithm apiHashAlgorithm, + icp_qat_hw_auth_algo_t *pQatAlgorithm, + CpaBoolean *pQatNested); + +void LacSymQat_HashSetupReqParamsMetaData( + icp_qat_la_bulk_req_ftr_t *pMsg, + CpaInstanceHandle instanceHandle, + const CpaCySymHashSetupData *pHashSetupData, + CpaBoolean hashStateBuffer, + icp_qat_hw_auth_mode_t qatHashMode, + CpaBoolean digestVerify); + +#endif /* LAC_SYM_QAT_HASH_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_hash_defs_lookup.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_hash_defs_lookup.h new file mode 100644 index 000000000000..23db82a3b180 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_hash_defs_lookup.h @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + ***************************************************************************** + * @file lac_sym_qat_hash_defs_lookup.h + * + * @defgroup LacSymQatHashDefsLookup Hash Defs Lookup + * + * @ingroup LacSymQatHash + * + * API to be used for the hash defs lookup table. + * + *****************************************************************************/ + +#ifndef LAC_SYM_QAT_HASH_DEFS_LOOKUP_P_H +#define LAC_SYM_QAT_HASH_DEFS_LOOKUP_P_H + +#include "cpa.h" +#include "cpa_cy_sym.h" + +/** +****************************************************************************** +* @ingroup LacSymQatHashDefsLookup +* Finishing Hash algorithm +* @description +* This define points to the last available hash algorithm +* @NOTE: If a new algorithm is added to the api, this #define +* MUST be updated to being the last hash algorithm in the struct +* CpaCySymHashAlgorithm in the file cpa_cy_sym.h +*****************************************************************************/ +#define CPA_CY_HASH_ALG_END CPA_CY_SYM_HASH_SM3 + +/***************************************************************************/ + +/** +****************************************************************************** +* @ingroup LacSymQatHashDefsLookup +* hash algorithm specific structure +* @description +* This structure contain constants specific to an algorithm. +*****************************************************************************/ +typedef struct lac_sym_qat_hash_alg_info_s { + Cpa32U digestLength; /**< Digest length in bytes */ + Cpa32U blockLength; /**< Block length in bytes */ + Cpa8U *initState; /**< Initialiser state for hash algorithm */ + Cpa32U stateSize; /**< size of above state in bytes */ +} lac_sym_qat_hash_alg_info_t; + +/** +****************************************************************************** +* @ingroup LacSymQatHashDefsLookup +* hash qat specific structure +* @description +* This structure contain constants as defined by the QAT for an +* algorithm. +*****************************************************************************/ +typedef struct lac_sym_qat_hash_qat_info_s { + Cpa32U algoEnc; /**< QAT Algorithm encoding */ + Cpa32U authCounter; /**< Counter value for Auth */ + Cpa32U state1Length; /**< QAT state1 length in bytes */ + Cpa32U state2Length; /**< QAT state2 length in bytes */ +} lac_sym_qat_hash_qat_info_t; + +/** +****************************************************************************** +* @ingroup LacSymQatHashDefsLookup +* hash defs structure +* @description +* This type contains pointers to the hash algorithm structure and +* to the hash qat specific structure +*****************************************************************************/ +typedef struct lac_sym_qat_hash_defs_s { + lac_sym_qat_hash_alg_info_t *algInfo; + /**< pointer to hash info structure */ + lac_sym_qat_hash_qat_info_t *qatInfo; + /**< pointer to hash QAT info structure */ +} lac_sym_qat_hash_defs_t; + +/** +******************************************************************************* +* @ingroup LacSymQatHashDefsLookup +* initialise the hash lookup table +* +* @description +* This function initialises the digest lookup table. +* +* @note +* This function does not have a corresponding shutdown function. +* +* @return CPA_STATUS_SUCCESS Operation successful +* @return CPA_STATUS_RESOURCE Allocating of hash lookup table failed +* +*****************************************************************************/ +CpaStatus LacSymQat_HashLookupInit(CpaInstanceHandle instanceHandle); + +/** +******************************************************************************* +* @ingroup LacSymQatHashDefsLookup +* get hash algorithm specific structure from lookup table +* +* @description +* This function looks up the hash lookup array for a structure +* containing data specific to a hash algorithm. The hashAlgorithm enum +* value MUST be in the correct range prior to calling this function. +* +* @param[in] hashAlgorithm Hash Algorithm +* @param[out] ppHashAlgInfo Hash Alg Info structure +* +* @return None +* +*****************************************************************************/ +void LacSymQat_HashAlgLookupGet(CpaInstanceHandle instanceHandle, + CpaCySymHashAlgorithm hashAlgorithm, + lac_sym_qat_hash_alg_info_t **ppHashAlgInfo); + +/** +******************************************************************************* +* @ingroup LacSymQatHashDefsLookup +* get hash defintions from lookup table. +* +* @description +* This function looks up the hash lookup array for a structure +* containing data specific to a hash algorithm. This includes both +* algorithm specific info and qat specific infro. The hashAlgorithm enum +* value MUST be in the correct range prior to calling this function. +* +* @param[in] hashAlgorithm Hash Algorithm +* @param[out] ppHashDefsInfo Hash Defs structure +* +* @return void +* +*****************************************************************************/ +void LacSymQat_HashDefsLookupGet(CpaInstanceHandle instanceHandle, + CpaCySymHashAlgorithm hashAlgorithm, + lac_sym_qat_hash_defs_t **ppHashDefsInfo); + +#endif /* LAC_SYM_QAT_HASH_DEFS_LOOKUP_P_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_key.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_key.h new file mode 100644 index 000000000000..a6a5d5169e11 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_qat_key.h @@ -0,0 +1,189 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + ***************************************************************************** + * @file lac_sym_qat_key.h + * + * @defgroup LacSymQatKey Key QAT + * + * @ingroup LacSymQat + * + * interfaces for populating qat structures for a key operation + * + *****************************************************************************/ + +#ifndef LAC_SYM_QAT_KEY_H +#define LAC_SYM_QAT_KEY_H + +#include "cpa.h" +#include "lac_sym.h" +#include "icp_qat_fw_la.h" + +/** +****************************************************************************** +* @ingroup LacSymQatKey +* Number of bytes generated per iteration +* @description +* This define is the number of bytes generated per iteration +*****************************************************************************/ +#define LAC_SYM_QAT_KEY_SSL_BYTES_PER_ITERATION (16) + +/** +****************************************************************************** +* @ingroup LacSymQatKey +* Shift to calculate the number of iterations +* @description +* This define is the shift to calculate the number of iterations +*****************************************************************************/ +#define LAC_SYM_QAT_KEY_SSL_ITERATIONS_SHIFT LAC_16BYTE_ALIGNMENT_SHIFT + +/** +******************************************************************************* +* @ingroup LacSymKey +* Populate the SSL request +* +* @description +* Populate the SSL request +* +* @param[out] pKeyGenReqHdr Pointer to Key Generation request Header +* @param[out] pKeyGenReqMid Pointer to LW's 14/15 of Key Gen request +* @param[in] generatedKeyLenInBytes Length of Key generated +* @param[in] labelLenInBytes Length of Label +* @param[in] secretLenInBytes Length of Secret +* @param[in] iterations Number of iterations. This is related +* to the label length. +* +* @return None +* +*****************************************************************************/ +void +LacSymQat_KeySslRequestPopulate(icp_qat_la_bulk_req_hdr_t *pKeyGenReqHdr, + icp_qat_fw_la_key_gen_common_t *pKeyGenReqMid, + Cpa32U generatedKeyLenInBytes, + Cpa32U labelLenInBytes, + Cpa32U secretLenInBytes, + Cpa32U iterations); + +/** +******************************************************************************* +* @ingroup LacSymKey +* Populate the TLS request +* +* @description +* Populate the TLS request +* +* @param[out] pKeyGenReq Pointer to Key Generation request +* @param[in] generatedKeyLenInBytes Length of Key generated +* @param[in] labelLenInBytes Length of Label +* @param[in] secretLenInBytes Length of Secret +* @param[in] seedLenInBytes Length of Seed +* @param[in] cmdId Command Id to differentiate TLS versions +* +* @return None +* +*****************************************************************************/ +void LacSymQat_KeyTlsRequestPopulate( + icp_qat_fw_la_key_gen_common_t *pKeyGenReqParams, + Cpa32U generatedKeyLenInBytes, + Cpa32U labelLenInBytes, + Cpa32U secretLenInBytes, + Cpa8U seedLenInBytes, + icp_qat_fw_la_cmd_id_t cmdId); + +/** +******************************************************************************* +* @ingroup LacSymKey +* Populate MGF request +* +* @description +* Populate MGF request +* +* @param[out] pKeyGenReqHdr Pointer to Key Generation request Header +* @param[out] pKeyGenReqMid Pointer to LW's 14/15 of Key Gen request +* @param[in] seedLenInBytes Length of Seed +* @param[in] maskLenInBytes Length of Mask +* @param[in] hashLenInBytes Length of hash +* +* @return None +* +*****************************************************************************/ +void +LacSymQat_KeyMgfRequestPopulate(icp_qat_la_bulk_req_hdr_t *pKeyGenReqHdr, + icp_qat_fw_la_key_gen_common_t *pKeyGenReqMid, + Cpa8U seedLenInBytes, + Cpa16U maskLenInBytes, + Cpa8U hashLenInBytes); + +/** +******************************************************************************* +* @ingroup LacSymKey +* Populate the SSL key material input +* +* @description +* Populate the SSL key material input +* +* @param[in] pService Pointer to service +* @param[out] pSslKeyMaterialInput Pointer to SSL key material input +* @param[in] pSeed Pointer to Seed +* @param[in] labelPhysAddr Physical address of the label +* @param[in] pSecret Pointer to Secret +* +* @return None +* +*****************************************************************************/ +void LacSymQat_KeySslKeyMaterialInputPopulate( + sal_service_t *pService, + icp_qat_fw_la_ssl_key_material_input_t *pSslKeyMaterialInput, + void *pSeed, + Cpa64U labelPhysAddr, + void *pSecret); + +/** +******************************************************************************* +* @ingroup LacSymKey +* Populate the TLS key material input +* +* @description +* Populate the TLS key material input +* +* @param[in] pService Pointer to service +* @param[out] pTlsKeyMaterialInput Pointer to TLS key material input +* @param[in] pSeed Pointer to Seed +* @param[in] labelPhysAddr Physical address of the label +* +* @return None +* +*****************************************************************************/ +void LacSymQat_KeyTlsKeyMaterialInputPopulate( + sal_service_t *pService, + icp_qat_fw_la_tls_key_material_input_t *pTlsKeyMaterialInput, + void *pSeed, + Cpa64U labelPhysAddr); + +/** +******************************************************************************* +* @ingroup LacSymKey +* Populate the TLS HKDF key material input +* +* @description +* Populate the TLS HKDF key material input +* +* @param[in] pService Pointer to service +* @param[out] pTlsKeyMaterialInput Pointer to TLS key material input +* @param[in] pSeed Pointer to Seed +* @param[in] labelPhysAddr Physical address of the label +* @param[in] cmdId Command ID +* +* @return None +* +*****************************************************************************/ +void LacSymQat_KeyTlsHKDFKeyMaterialInputPopulate( + sal_service_t *pService, + icp_qat_fw_la_hkdf_key_material_input_t *pTlsKeyMaterialInput, + CpaCyKeyGenHKDFOpData *pKeyGenTlsOpData, + Cpa64U subLabelsPhysAddr, + icp_qat_fw_la_cmd_id_t cmdId); + +#endif /* LAC_SYM_QAT_KEY_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_queue.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_queue.h new file mode 100644 index 000000000000..d7a5cd3c9e92 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_queue.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + ****************************************************************************** + * @file lac_sym_queue.h + * + * @defgroup LacSymQueue Symmetric request queueing functions + * + * @ingroup LacSym + * + * Function prototypes for sending/queuing symmetric requests + *****************************************************************************/ + +#ifndef LAC_SYM_QUEUE_H +#define LAC_SYM_QUEUE_H + +#include "cpa.h" +#include "lac_session.h" +#include "lac_sym.h" + +/** +******************************************************************************* +* @ingroup LacSymQueue +* Send a request message to the QAT, or queue it if necessary +* +* @description +* This function will send a request message to the QAT. However, if a +* blocking condition exists on the session (e.g. partial packet in flight, +* precompute in progress), then the message will instead be pushed on to +* the request queue for the session and will be sent later to the QAT +* once the blocking condition is cleared. +* +* @param[in] instanceHandle Handle for instance of QAT +* @param[in] pRequest Pointer to request cookie +* @param[out] pSessionDesc Pointer to session descriptor +* +* +* @retval CPA_STATUS_SUCCESS Success +* @retval CPA_STATUS_FAIL Function failed. +* @retval CPA_STATUS_RESOURCE Problem Acquiring system resource +* @retval CPA_STATUS_RETRY Failed to send message to QAT due to queue +* full condition +* +*****************************************************************************/ +CpaStatus LacSymQueue_RequestSend(const CpaInstanceHandle instanceHandle, + lac_sym_bulk_cookie_t *pRequest, + lac_session_desc_t *pSessionDesc); + +#endif /* LAC_SYM_QUEUE_H */ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_stats.h b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_stats.h new file mode 100644 index 000000000000..b5d823420163 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/include/lac_sym_stats.h @@ -0,0 +1,191 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_stats.h + * + * @defgroup LacSymCommon Symmetric Common + * + * @ingroup LacSym + * + * Symetric Common consists of common statistics, buffer and partial packet + * functionality. + * + ***************************************************************************/ + +/** + *************************************************************************** + * @defgroup LacSymStats Statistics + * + * @ingroup LacSymCommon + * + * definitions and prototypes for LAC symmetric statistics. + * + * @lld_start + * In the LAC API the stats fields are defined as Cpa32U but + * QatUtilsAtomic is the type that the atomic API supports. Therefore we + * need to define a structure internally with the same fields as the API + * stats structure, but each field must be of type QatUtilsAtomic. + * + * - <b>Incrementing Statistics:</b>\n + * Atomically increment the statistic on the internal stats structure. + * + * - <b>Providing a copy of the stats back to the user:</b>\n + * Use atomicGet to read the atomic variable for each stat field in the + * local internal stat structure. These values are saved in structure + * (as defined by the LAC API) that the client will provide a pointer + * to as a parameter. + * + * - <b>Stats Show:</b>\n + * Use atomicGet to read the atomic variables for each field in the local + * internal stat structure and print to the screen + * + * - <b>Stats Array:</b>\n + * A macro is used to get the offset off the stat in the structure. This + * offset is passed to a function which uses it to increment the stat + * at that offset. + * + * @lld_end + * + ***************************************************************************/ + +/***************************************************************************/ + +#ifndef LAC_SYM_STATS_H +#define LAC_SYM_STATS_H + +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ + +#include "cpa.h" +#include "cpa_cy_sym.h" +#include "cpa_cy_common.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ + +/** +******************************************************************************* +* @ingroup LacSymStats +* increment a symmetric statistic +* +* @description +* Increment the statistics +* +* @param statistic IN The field in the symmetric statistics structure to be +* incremented +* @param instanceHandle IN engine Id Number +* +* @retval None +* +*****************************************************************************/ +#define LAC_SYM_STAT_INC(statistic, instanceHandle) \ + LacSym_StatsInc(offsetof(CpaCySymStats64, statistic), instanceHandle) + +/** +******************************************************************************* +* @ingroup LacSymStats +* initialises the symmetric stats +* +* @description +* This function allocates and initialises the stats array to 0 +* +* @param instanceHandle Instance Handle +* +* @retval CPA_STATUS_SUCCESS initialisation successful +* @retval CPA_STATUS_RESOURCE array allocation failed +* +*****************************************************************************/ +CpaStatus LacSym_StatsInit(CpaInstanceHandle instanceHandle); + +/** +******************************************************************************* +* @ingroup LacSymStats +* Frees the symmetric stats +* +* @description +* This function frees the stats array +* +* @param instanceHandle Instance Handle +* +* @retval None +* +*****************************************************************************/ +void LacSym_StatsFree(CpaInstanceHandle instanceHandle); + +/** +******************************************************************************* +* @ingroup LacSymStats +* Inrement a stat +* +* @description +* This function incrementes a stat for a specific engine. +* +* @param offset IN offset of stat field in structure +* @param instanceHandle IN qat Handle +* +* @retval None +* +*****************************************************************************/ +void LacSym_StatsInc(Cpa32U offset, CpaInstanceHandle instanceHandle); + +/** +******************************************************************************* +* @ingroup LacSymStats +* Copy the contents of the statistics structure for an engine +* +* @description +* This function copies the 32bit symmetric statistics structure for +* a specific engine into an address supplied as a parameter. +* +* @param instanceHandle IN engine Id Number +* @param pSymStats OUT stats structure to copy the stats for the into +* +* @retval None +* +*****************************************************************************/ +void LacSym_Stats32CopyGet(CpaInstanceHandle instanceHandle, + struct _CpaCySymStats *const pSymStats); + +/** +******************************************************************************* +* @ingroup LacSymStats +* Copy the contents of the statistics structure for an engine +* +* @description +* This function copies the 64bit symmetric statistics structure for +* a specific engine into an address supplied as a parameter. +* +* @param instanceHandle IN engine Id Number +* @param pSymStats OUT stats structure to copy the stats for the into +* +* @retval None +* +*****************************************************************************/ +void LacSym_Stats64CopyGet(CpaInstanceHandle instanceHandle, + CpaCySymStats64 *const pSymStats); + +/** +******************************************************************************* +* @ingroup LacSymStats +* print the symmetric stats to standard output +* +* @description +* The statistics for symmetric are printed to standard output. +* +* @retval None +* +* @see LacSym_StatsCopyGet() +* +*****************************************************************************/ +void LacSym_StatsShow(CpaInstanceHandle instanceHandle); + +#endif /*LAC_SYM_STATS_H_*/ diff --git a/sys/dev/qat/qat_api/common/crypto/sym/key/lac_sym_key.c b/sys/dev/qat/qat_api/common/crypto/sym/key/lac_sym_key.c new file mode 100644 index 000000000000..2f27a1781876 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/key/lac_sym_key.c @@ -0,0 +1,3021 @@ +/*************************************************************************** + * + * <COPYRIGHT_TAG> + * + ***************************************************************************/ + +/** + ***************************************************************************** + * @file lac_sym_key.c + * + * @ingroup LacSymKey + * + * This file contains the implementation of all keygen functionality + * + *****************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ +#include "cpa.h" +#include "cpa_cy_key.h" +#include "cpa_cy_im.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" +#include "icp_adf_init.h" +#include "icp_adf_transport.h" + +#include "qat_utils.h" + +#include "lac_log.h" +#include "lac_hooks.h" +#include "lac_sym.h" +#include "lac_sym_qat_hash_defs_lookup.h" +#include "lac_sym_qat.h" +#include "lac_sal.h" +#include "lac_sym_key.h" +#include "lac_sal_types_crypto.h" +#include "sal_service_state.h" +#include "lac_sym_qat_key.h" +#include "lac_sym_hash_defs.h" +#include "sal_statistics.h" + +/* Number of statistics */ +#define LAC_KEY_NUM_STATS (sizeof(CpaCyKeyGenStats64) / sizeof(Cpa64U)) + +#define LAC_KEY_STAT_INC(statistic, instanceHandle) \ + do { \ + sal_crypto_service_t *pService = NULL; \ + pService = (sal_crypto_service_t *)instanceHandle; \ + if (CPA_TRUE == \ + pService->generic_service_info.stats \ + ->bKeyGenStatsEnabled) { \ + qatUtilsAtomicInc( \ + &pService \ + ->pLacKeyStats[offsetof(CpaCyKeyGenStats64, \ + statistic) / \ + sizeof(Cpa64U)]); \ + } \ + } while (0) +/**< Macro to increment a Key stat (derives offset into array of atomics) */ + +#define LAC_KEY_STATS32_GET(keyStats, instanceHandle) \ + do { \ + int i; \ + sal_crypto_service_t *pService = \ + (sal_crypto_service_t *)instanceHandle; \ + for (i = 0; i < LAC_KEY_NUM_STATS; i++) { \ + ((Cpa32U *)&(keyStats))[i] = \ + (Cpa32U)qatUtilsAtomicGet( \ + &pService->pLacKeyStats[i]); \ + } \ + } while (0) +/**< Macro to get all 32bit Key stats (from internal array of atomics) */ + +#define LAC_KEY_STATS64_GET(keyStats, instanceHandle) \ + do { \ + int i; \ + sal_crypto_service_t *pService = \ + (sal_crypto_service_t *)instanceHandle; \ + for (i = 0; i < LAC_KEY_NUM_STATS; i++) { \ + ((Cpa64U *)&(keyStats))[i] = \ + qatUtilsAtomicGet(&pService->pLacKeyStats[i]); \ + } \ + } while (0) +/**< Macro to get all 64bit Key stats (from internal array of atomics) */ + +#define IS_HKDF_UNSUPPORTED(cmdId, hkdfSupported) \ + ((ICP_QAT_FW_LA_CMD_HKDF_EXTRACT <= cmdId && \ + ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL >= cmdId) && \ + !hkdfSupported) /**< macro to check whether the HKDF algorithm can be \ + supported on the device */ + +/* Sublabel for HKDF TLS Key Generation, as defined in RFC8446. */ +const static Cpa8U key256[HKDF_SUB_LABEL_KEY_LENGTH] = { 0, 16, 9, 't', + 'l', 's', '1', '3', + ' ', 'k', 'e', 'y', + 0 }; +const static Cpa8U key384[HKDF_SUB_LABEL_KEY_LENGTH] = { 0, 32, 9, 't', + 'l', 's', '1', '3', + ' ', 'k', 'e', 'y', + 0 }; +const static Cpa8U keyChaChaPoly[HKDF_SUB_LABEL_KEY_LENGTH] = { 0, 32, 9, + 't', 'l', 's', + '1', '3', ' ', + 'k', 'e', 'y', + 0 }; +/* Sublabel for HKDF TLS IV key Generation, as defined in RFC8446. */ +const static Cpa8U iv256[HKDF_SUB_LABEL_IV_LENGTH] = { 0, 12, 8, 't', + 'l', 's', '1', '3', + ' ', 'i', 'v', 0 }; +const static Cpa8U iv384[HKDF_SUB_LABEL_IV_LENGTH] = { 0, 12, 8, 't', + 'l', 's', '1', '3', + ' ', 'i', 'v', 0 }; +/* Sublabel for HKDF TLS RESUMPTION key Generation, as defined in RFC8446. */ +const static Cpa8U resumption256[HKDF_SUB_LABEL_RESUMPTION_LENGTH] = + { 0, 32, 16, 't', 'l', 's', '1', '3', ' ', 'r', + 'e', 's', 'u', 'm', 'p', 't', 'i', 'o', 'n', 0 }; +const static Cpa8U resumption384[HKDF_SUB_LABEL_RESUMPTION_LENGTH] = + { 0, 48, 16, 't', 'l', 's', '1', '3', ' ', 'r', + 'e', 's', 'u', 'm', 'p', 't', 'i', 'o', 'n', 0 }; +/* Sublabel for HKDF TLS FINISHED key Generation, as defined in RFC8446. */ +const static Cpa8U finished256[HKDF_SUB_LABEL_FINISHED_LENGTH] = + { 0, 32, 14, 't', 'l', 's', '1', '3', ' ', + 'f', 'i', 'n', 'i', 's', 'h', 'e', 'd', 0 }; +const static Cpa8U finished384[HKDF_SUB_LABEL_FINISHED_LENGTH] = + { 0, 48, 14, 't', 'l', 's', '1', '3', ' ', + 'f', 'i', 'n', 'i', 's', 'h', 'e', 'd', 0 }; + +/** + ****************************************************************************** + * @ingroup LacSymKey + * SSL/TLS stat type + * + * @description + * This enum determines which stat should be incremented + *****************************************************************************/ +typedef enum { + LAC_KEY_REQUESTS = 0, + /**< Key requests sent */ + LAC_KEY_REQUEST_ERRORS, + /**< Key requests errors */ + LAC_KEY_COMPLETED, + /**< Key requests which received responses */ + LAC_KEY_COMPLETED_ERRORS + /**< Key requests which received responses with errors */ +} lac_key_stat_type_t; + +/*** Local functions prototypes ***/ +static void +LacSymKey_MgfHandleResponse(icp_qat_fw_la_cmd_id_t lacCmdId, + void *pOpaqueData, + icp_qat_fw_comn_flags cmnRespFlags); + +static CpaStatus +LacSymKey_MgfSync(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const void *pKeyGenMgfOpData, + CpaFlatBuffer *pGeneratedMaskBuffer, + CpaBoolean bIsExtRequest); + +static void +LacSymKey_SslTlsHandleResponse(icp_qat_fw_la_cmd_id_t lacCmdId, + void *pOpaqueData, + icp_qat_fw_comn_flags cmnRespFlags); + +static CpaStatus +LacSymKey_SslTlsSync(CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + icp_qat_fw_la_cmd_id_t lacCmdId, + void *pKeyGenSslTlsOpData, + Cpa8U hashAlgorithm, + CpaFlatBuffer *pKeyGenOutpuData); + +/*** Implementation ***/ + +/** + ****************************************************************************** + * @ingroup LacSymKey + * Get the instance handle. Support single handle. + * @param[in] instanceHandle_in user supplied handle. + * @retval CpaInstanceHandle the instance handle + */ +static CpaInstanceHandle +LacKey_GetHandle(CpaInstanceHandle instanceHandle_in) +{ + CpaInstanceHandle instanceHandle = NULL; + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + return instanceHandle; +} + +/** +******************************************************************************* +* @ingroup LacSymKey +* Perform SSL/TLS key gen operation +* +* @description +* Perform SSL/TLS key gen operation +* +* @param[in] instanceHandle QAT device handle. +* @param[in] pKeyGenCb Pointer to callback function to be invoked +* when the operation is complete. +* @param[in] pCallbackTag Opaque User Data for this specific call. +* @param[in] lacCmdId Lac command ID (identify SSL & TLS ops) +* @param[in] pKeyGenSslTlsOpData Structure containing all the data needed to +* perform the SSL/TLS key generation +* operation. +* @param[in] hashAlgorithm Specifies the hash algorithm to use. +* According to RFC5246, this should be +* "SHA-256 or a stronger standard hash +* function." +* @param[out] pKeyGenOutputData pointer to where output result should be +* written +* +* @retval CPA_STATUS_SUCCESS Function executed successfully. +* @retval CPA_STATUS_FAIL Function failed. +* @retval CPA_STATUS_RETRY Function should be retried. +* @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. +* @retval CPA_STATUS_RESOURCE Error related to system resources. +* +*****************************************************************************/ +static CpaStatus +LacSymKey_KeyGenSslTls_GenCommon(CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + icp_qat_fw_la_cmd_id_t lacCmdId, + void *pKeyGenSslTlsOpData, + Cpa8U hashAlgorithm, + CpaFlatBuffer *pKeyGenOutputData); + +/** + ****************************************************************************** + * @ingroup LacSymKey + * Increment stat for TLS or SSL operation + * + * @description + * This is a generic function to update the stats for either a TLS or SSL + * operation. + * + * @param[in] lacCmdId Indicate SSL or TLS operations + * @param[in] statType Statistics Type + * @param[in] instanceHandle Instance Handle + * + * @return None + * + *****************************************************************************/ +static void +LacKey_StatsInc(icp_qat_fw_la_cmd_id_t lacCmdId, + lac_key_stat_type_t statType, + CpaInstanceHandle instanceHandle) +{ + if (ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE == lacCmdId) { + switch (statType) { + case LAC_KEY_REQUESTS: + LAC_KEY_STAT_INC(numSslKeyGenRequests, instanceHandle); + break; + case LAC_KEY_REQUEST_ERRORS: + LAC_KEY_STAT_INC(numSslKeyGenRequestErrors, + instanceHandle); + break; + case LAC_KEY_COMPLETED: + LAC_KEY_STAT_INC(numSslKeyGenCompleted, instanceHandle); + break; + case LAC_KEY_COMPLETED_ERRORS: + LAC_KEY_STAT_INC(numSslKeyGenCompletedErrors, + instanceHandle); + break; + default: + QAT_UTILS_LOG("Invalid statistics type\n"); + break; + } + } else /* TLS v1.0/1.1 and 1.2 */ + { + switch (statType) { + case LAC_KEY_REQUESTS: + LAC_KEY_STAT_INC(numTlsKeyGenRequests, instanceHandle); + break; + case LAC_KEY_REQUEST_ERRORS: + LAC_KEY_STAT_INC(numTlsKeyGenRequestErrors, + instanceHandle); + break; + case LAC_KEY_COMPLETED: + LAC_KEY_STAT_INC(numTlsKeyGenCompleted, instanceHandle); + break; + case LAC_KEY_COMPLETED_ERRORS: + LAC_KEY_STAT_INC(numTlsKeyGenCompletedErrors, + instanceHandle); + break; + default: + QAT_UTILS_LOG("Invalid statistics type\n"); + break; + } + } +} + +void +LacKeygen_StatsShow(CpaInstanceHandle instanceHandle) +{ + CpaCyKeyGenStats64 keyStats = { 0 }; + + LAC_KEY_STATS64_GET(keyStats, instanceHandle); + + QAT_UTILS_LOG(SEPARATOR BORDER + " Key Stats: " BORDER + "\n" SEPARATOR); + + QAT_UTILS_LOG(BORDER " SSL Key Requests: %16llu " BORDER + "\n" BORDER + " SSL Key Request Errors: %16llu " BORDER + "\n" BORDER + " SSL Key Completed %16llu " BORDER + "\n" BORDER + " SSL Key Complete Errors: %16llu " BORDER + "\n" SEPARATOR, + (unsigned long long)keyStats.numSslKeyGenRequests, + (unsigned long long)keyStats.numSslKeyGenRequestErrors, + (unsigned long long)keyStats.numSslKeyGenCompleted, + (unsigned long long)keyStats.numSslKeyGenCompletedErrors); + + QAT_UTILS_LOG(BORDER " TLS Key Requests: %16llu " BORDER + "\n" BORDER + " TLS Key Request Errors: %16llu " BORDER + "\n" BORDER + " TLS Key Completed %16llu " BORDER + "\n" BORDER + " TLS Key Complete Errors: %16llu " BORDER + "\n" SEPARATOR, + (unsigned long long)keyStats.numTlsKeyGenRequests, + (unsigned long long)keyStats.numTlsKeyGenRequestErrors, + (unsigned long long)keyStats.numTlsKeyGenCompleted, + (unsigned long long)keyStats.numTlsKeyGenCompletedErrors); + + QAT_UTILS_LOG(BORDER " MGF Key Requests: %16llu " BORDER + "\n" BORDER + " MGF Key Request Errors: %16llu " BORDER + "\n" BORDER + " MGF Key Completed %16llu " BORDER + "\n" BORDER + " MGF Key Complete Errors: %16llu " BORDER + "\n" SEPARATOR, + (unsigned long long)keyStats.numMgfKeyGenRequests, + (unsigned long long)keyStats.numMgfKeyGenRequestErrors, + (unsigned long long)keyStats.numMgfKeyGenCompleted, + (unsigned long long)keyStats.numMgfKeyGenCompletedErrors); +} + +/** @ingroup LacSymKey */ +CpaStatus +cpaCyKeyGenQueryStats(CpaInstanceHandle instanceHandle_in, + struct _CpaCyKeyGenStats *pSymKeyStats) +{ + CpaInstanceHandle instanceHandle = NULL; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(pSymKeyStats); + + SAL_RUNNING_CHECK(instanceHandle); + + LAC_KEY_STATS32_GET(*pSymKeyStats, instanceHandle); + + return CPA_STATUS_SUCCESS; +} + +/** @ingroup LacSymKey */ +CpaStatus +cpaCyKeyGenQueryStats64(CpaInstanceHandle instanceHandle_in, + CpaCyKeyGenStats64 *pSymKeyStats) +{ + CpaInstanceHandle instanceHandle = NULL; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(pSymKeyStats); + + SAL_RUNNING_CHECK(instanceHandle); + + LAC_KEY_STATS64_GET(*pSymKeyStats, instanceHandle); + + return CPA_STATUS_SUCCESS; +} + +/** + ****************************************************************************** + * @ingroup LacSymKey + * Return the size of the digest for a specific hash algorithm. + * @description + * Return the expected digest size based on the sha algorithm submitted. + * The only supported value are sha256, sha384 and sha512. + * + * @param[in] hashAlgorithm either sha256, sha384 or sha512. + * @return the expected size or 0 for an invalid hash. + * + *****************************************************************************/ +static Cpa32U +getDigestSizeFromHashAlgo(CpaCySymHashAlgorithm hashAlgorithm) +{ + switch (hashAlgorithm) { + case CPA_CY_SYM_HASH_SHA256: + return LAC_HASH_SHA256_DIGEST_SIZE; + case CPA_CY_SYM_HASH_SHA384: + return LAC_HASH_SHA384_DIGEST_SIZE; + case CPA_CY_SYM_HASH_SHA512: + return LAC_HASH_SHA512_DIGEST_SIZE; + case CPA_CY_SYM_HASH_SM3: + return LAC_HASH_SM3_DIGEST_SIZE; + default: + return 0; + } +} + +/** + ****************************************************************************** + * @ingroup LacSymKey + * Return the hash algorithm for a specific cipher. + * @description + * Return the hash algorithm related to the cipher suite. + * Supported hash's are SHA256, and SHA384. + * + * @param[in] cipherSuite AES_128_GCM, AES_256_GCM, AES_128_CCM, + * and CHACHA20_POLY1305. + * @return the expected hash algorithm or 0 for an invalid cipher. + * + *****************************************************************************/ +static CpaCySymHashAlgorithm +getHashAlgorithmFromCipherSuiteHKDF(CpaCyKeyHKDFCipherSuite cipherSuite) +{ + switch (cipherSuite) { + case CPA_CY_HKDF_TLS_AES_128_GCM_SHA256: /* Fall through */ + case CPA_CY_HKDF_TLS_CHACHA20_POLY1305_SHA256: + case CPA_CY_HKDF_TLS_AES_128_CCM_SHA256: + case CPA_CY_HKDF_TLS_AES_128_CCM_8_SHA256: + return CPA_CY_SYM_HASH_SHA256; + case CPA_CY_HKDF_TLS_AES_256_GCM_SHA384: + return CPA_CY_SYM_HASH_SHA384; + default: + return 0; + } +} + +/** + ****************************************************************************** + * @ingroup LacSymKey + * Return the digest size of cipher. + * @description + * Return the output key size of specific cipher, for specified sub label + * + * @param[in] cipherSuite = AES_128_GCM, AES_256_GCM, AES_128_CCM, + * and CHACHA20_POLY1305. + * subLabels = KEY, IV, RESUMPTION, and FINISHED. + * @return the expected digest size of the cipher. + * + *****************************************************************************/ +static const Cpa32U cipherSuiteHKDFHashSizes + [LAC_KEY_HKDF_CIPHERS_MAX][LAC_KEY_HKDF_SUBLABELS_MAX] = { + {}, /* Not used */ + { 32, 16, 12, 32, 32 }, /* AES_128_GCM_SHA256 */ + { 48, 32, 12, 48, 48 }, /* AES_256_GCM_SHA384 */ + { 32, 32, 12, 32, 32 }, /* CHACHA20_POLY1305_SHA256 */ + { 32, 16, 12, 32, 32 }, /* AES_128_CCM_SHA256 */ + { 32, 16, 12, 32, 32 } /* AES_128_CCM_8_SHA256 */ + }; + +/** + ****************************************************************************** + * @ingroup LacSymKey + * Key Generation MGF response handler + * + * @description + * Handles Key Generation MGF response messages from the QAT. + * + * @param[in] lacCmdId Command id of the original request + * @param[in] pOpaqueData Pointer to opaque data that was in request + * @param[in] cmnRespFlags Indicates whether request succeeded + * + * @return void + * + *****************************************************************************/ +static void +LacSymKey_MgfHandleResponse(icp_qat_fw_la_cmd_id_t lacCmdId, + void *pOpaqueData, + icp_qat_fw_comn_flags cmnRespFlags) +{ + CpaCyKeyGenMgfOpData *pMgfOpData = NULL; + lac_sym_key_cookie_t *pCookie = NULL; + CpaCyGenFlatBufCbFunc pKeyGenMgfCb = NULL; + void *pCallbackTag = NULL; + CpaFlatBuffer *pGeneratedKeyBuffer = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + CpaBoolean respStatusOk = + (ICP_QAT_FW_COMN_STATUS_FLAG_OK == + ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(cmnRespFlags)) ? + CPA_TRUE : + CPA_FALSE; + + pCookie = (lac_sym_key_cookie_t *)pOpaqueData; + + if (CPA_TRUE == respStatusOk) { + status = CPA_STATUS_SUCCESS; + LAC_KEY_STAT_INC(numMgfKeyGenCompleted, + pCookie->instanceHandle); + } else { + status = CPA_STATUS_FAIL; + LAC_KEY_STAT_INC(numMgfKeyGenCompletedErrors, + pCookie->instanceHandle); + } + + pKeyGenMgfCb = (CpaCyGenFlatBufCbFunc)(pCookie->pKeyGenCb); + + pMgfOpData = pCookie->pKeyGenOpData; + pCallbackTag = pCookie->pCallbackTag; + pGeneratedKeyBuffer = pCookie->pKeyGenOutputData; + + Lac_MemPoolEntryFree(pCookie); + + (*pKeyGenMgfCb)(pCallbackTag, status, pMgfOpData, pGeneratedKeyBuffer); +} + +/** + ****************************************************************************** + * @ingroup LacSymKey + * Synchronous mode of operation wrapper function + * + * @description + * Wrapper function to implement synchronous mode of operation for + * cpaCyKeyGenMgf and cpaCyKeyGenMgfExt function. + * + * @param[in] instanceHandle Instance handle + * @param[in] pKeyGenCb Internal callback function pointer + * @param[in] pCallbackTag Callback tag + * @param[in] pKeyGenMgfOpData Pointer to user provided Op Data structure + * @param[in] pGeneratedMaskBuffer Pointer to a buffer where generated mask + * will be stored + * @param[in] bIsExtRequest Indicates origin of function call; + * if CPA_TRUE then the call comes from + * cpaCyKeyGenMgfExt function, otherwise + * from cpaCyKeyGenMgf + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Function should be retried. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * + *****************************************************************************/ +static CpaStatus +LacSymKey_MgfSync(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const void *pKeyGenMgfOpData, + CpaFlatBuffer *pGeneratedMaskBuffer, + CpaBoolean bIsExtRequest) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + lac_sync_op_data_t *pSyncCallbackData = NULL; + + status = LacSync_CreateSyncCookie(&pSyncCallbackData); + + if (CPA_STATUS_SUCCESS == status) { + if (CPA_TRUE == bIsExtRequest) { + status = cpaCyKeyGenMgfExt( + instanceHandle, + LacSync_GenFlatBufCb, + pSyncCallbackData, + (const CpaCyKeyGenMgfOpDataExt *)pKeyGenMgfOpData, + pGeneratedMaskBuffer); + } else { + status = cpaCyKeyGenMgf(instanceHandle, + LacSync_GenFlatBufCb, + pSyncCallbackData, + (const CpaCyKeyGenMgfOpData *) + pKeyGenMgfOpData, + pGeneratedMaskBuffer); + } + } else { + /* Failure allocating sync cookie */ + LAC_KEY_STAT_INC(numMgfKeyGenRequestErrors, instanceHandle); + return status; + } + + if (CPA_STATUS_SUCCESS == status) { + CpaStatus syncStatus = CPA_STATUS_SUCCESS; + + syncStatus = + LacSync_WaitForCallback(pSyncCallbackData, + LAC_SYM_SYNC_CALLBACK_TIMEOUT, + &status, + NULL); + + /* If callback doesn't come back */ + if (CPA_STATUS_SUCCESS != syncStatus) { + LAC_KEY_STAT_INC(numMgfKeyGenCompletedErrors, + instanceHandle); + LAC_LOG_ERROR("Callback timed out"); + status = syncStatus; + } + } else { + /* As the Request was not sent the Callback will never + * be called, so need to indicate that we're finished + * with cookie so it can be destroyed. + */ + LacSync_SetSyncCookieComplete(pSyncCallbackData); + } + + LacSync_DestroySyncCookie(&pSyncCallbackData); + + return status; +} + +/** + ****************************************************************************** + * @ingroup LacSymKey + * Perform MGF key gen operation + * + * @description + * This function performs MGF key gen operation. It is common for requests + * coming from both cpaCyKeyGenMgf and cpaCyKeyGenMgfExt QAT API + * functions. + * + * @param[in] instanceHandle Instance handle + * @param[in] pKeyGenCb Pointer to callback function to be invoked + * when the operation is complete. + * @param[in] pCallbackTag Opaque User Data for this specific call. + * @param[in] pOpData Pointer to the Op Data structure provided by + * the user in API function call. For calls + * originating from cpaCyKeyGenMgfExt it will + * point to CpaCyKeyGenMgfOpDataExt type of + * structure while for calls originating from + * cpaCyKeyGenMgf it will point to + * CpaCyKeyGenMgfOpData type of structure. + * @param[in] pKeyGenMgfOpData Pointer to the user provided + * CpaCyKeyGenMgfOpData structure. For calls + * originating from cpaCyKeyGenMgf it will + * point to the same structure as pOpData + * parameter; for calls originating from + * cpaCyKeyGenMgfExt it will point to the + * baseOpData member of the + * CpaCyKeyGenMgfOpDataExt structure passed in + * as a parameter to the API function call. + * @param[in] pGeneratedMaskBuffer Pointer to a buffer where generated mask + * will be stored + * @param[in] hashAlgorithm Indicates which hash algorithm is to be used + * to perform MGF key gen operation. For calls + * originating from cpaCyKeyGenMgf it will + * always be CPA_CY_SYM_HASH_SHA1. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Function should be retried. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * + *****************************************************************************/ +static CpaStatus +LacSymKey_MgfCommon(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const void *pOpData, + const CpaCyKeyGenMgfOpData *pKeyGenMgfOpData, + CpaFlatBuffer *pGeneratedMaskBuffer, + CpaCySymHashAlgorithm hashAlgorithm) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + icp_qat_fw_la_bulk_req_t keyGenReq = { { 0 } }; + icp_qat_la_bulk_req_hdr_t keyGenReqHdr = { { 0 } }; + icp_qat_fw_la_key_gen_common_t keyGenReqMid = { { 0 } }; + icp_qat_la_bulk_req_ftr_t keyGenReqFtr = { { { 0 } } }; + Cpa8U *pMsgDummy = NULL; + Cpa8U *pCacheDummyHdr = NULL; + Cpa8U *pCacheDummyMid = NULL; + Cpa8U *pCacheDummyFtr = NULL; + sal_qat_content_desc_info_t contentDescInfo = { 0 }; + lac_sym_key_cookie_t *pCookie = NULL; + lac_sym_cookie_t *pSymCookie = NULL; + sal_crypto_service_t *pService = NULL; + Cpa64U inputPhysAddr = 0; + Cpa64U outputPhysAddr = 0; +/* Structure initializer is supported by C99, but it is + * not supported by some former Intel compiler. + */ + CpaCySymHashSetupData hashSetupData = { 0 }; + Cpa32U hashBlkSizeInBytes = 0; + lac_sym_qat_hash_alg_info_t *pHashAlgInfo = NULL; + icp_qat_fw_serv_specif_flags laCmdFlags = 0; + icp_qat_fw_comn_flags cmnRequestFlags = + ICP_QAT_FW_COMN_FLAGS_BUILD(QAT_COMN_PTR_TYPE_FLAT, + QAT_COMN_CD_FLD_TYPE_64BIT_ADR); + + pService = (sal_crypto_service_t *)instanceHandle; + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + + SAL_RUNNING_CHECK(instanceHandle); + LAC_CHECK_NULL_PARAM(pOpData); + LAC_CHECK_NULL_PARAM(pKeyGenMgfOpData); + LAC_CHECK_NULL_PARAM(pGeneratedMaskBuffer); + LAC_CHECK_NULL_PARAM(pGeneratedMaskBuffer->pData); + LAC_CHECK_NULL_PARAM(pKeyGenMgfOpData->seedBuffer.pData); + + /* Maximum seed length for MGF1 request */ + if (pKeyGenMgfOpData->seedBuffer.dataLenInBytes > + ICP_QAT_FW_LA_MGF_SEED_LEN_MAX) { + LAC_INVALID_PARAM_LOG("seedBuffer.dataLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Maximum mask length for MGF1 request */ + if (pKeyGenMgfOpData->maskLenInBytes > ICP_QAT_FW_LA_MGF_MASK_LEN_MAX) { + LAC_INVALID_PARAM_LOG("maskLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + + /* check for enough space in the flat buffer */ + if (pKeyGenMgfOpData->maskLenInBytes > + pGeneratedMaskBuffer->dataLenInBytes) { + LAC_INVALID_PARAM_LOG("pGeneratedMaskBuffer.dataLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Get hash alg info */ + LacSymQat_HashAlgLookupGet(instanceHandle, + hashAlgorithm, + &pHashAlgInfo); + + /* Allocate the cookie */ + pCookie = (lac_sym_key_cookie_t *)Lac_MemPoolEntryAlloc( + pService->lac_sym_cookie_pool); + if (NULL == pCookie) { + LAC_LOG_ERROR("Cannot get mem pool entry"); + status = CPA_STATUS_RESOURCE; + } else if ((void *)CPA_STATUS_RETRY == pCookie) { + pCookie = NULL; + status = CPA_STATUS_RETRY; + } else { + pSymCookie = (lac_sym_cookie_t *)pCookie; + } + + if (CPA_STATUS_SUCCESS == status) { + /* populate the cookie */ + pCookie->instanceHandle = instanceHandle; + pCookie->pCallbackTag = pCallbackTag; + pCookie->pKeyGenOpData = (void *)LAC_CONST_PTR_CAST(pOpData); + pCookie->pKeyGenCb = pKeyGenCb; + pCookie->pKeyGenOutputData = pGeneratedMaskBuffer; + hashSetupData.hashAlgorithm = hashAlgorithm; + hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_PLAIN; + hashSetupData.digestResultLenInBytes = + pHashAlgInfo->digestLength; + + /* Populate the CD ctrl Block (LW 27 - LW 31) + * and the CD Hash HW setup block + */ + LacSymQat_HashContentDescInit( + &(keyGenReqFtr), + instanceHandle, + &hashSetupData, + /* point to base of hw setup block */ + (Cpa8U *)pCookie->contentDesc, + LAC_SYM_KEY_NO_HASH_BLK_OFFSET_QW, + ICP_QAT_FW_SLICE_DRAM_WR, + ICP_QAT_HW_AUTH_MODE0, /* just a plain hash */ + CPA_FALSE, /* Not using sym Constants Table in Shared SRAM + */ + CPA_FALSE, /* not using the optimised Content Desc */ + NULL, + &hashBlkSizeInBytes); + + /* Populate the Req param LW 14-26 */ + LacSymQat_KeyMgfRequestPopulate( + &keyGenReqHdr, + &keyGenReqMid, + pKeyGenMgfOpData->seedBuffer.dataLenInBytes, + pKeyGenMgfOpData->maskLenInBytes, + (Cpa8U)pHashAlgInfo->digestLength); + + contentDescInfo.pData = pCookie->contentDesc; + contentDescInfo.hardwareSetupBlockPhys = + LAC_MEM_CAST_PTR_TO_UINT64( + pSymCookie->keyContentDescPhyAddr); + contentDescInfo.hwBlkSzQuadWords = + LAC_BYTES_TO_QUADWORDS(hashBlkSizeInBytes); + + /* Populate common request fields */ + inputPhysAddr = + LAC_MEM_CAST_PTR_TO_UINT64(LAC_OS_VIRT_TO_PHYS_EXTERNAL( + pService->generic_service_info, + pKeyGenMgfOpData->seedBuffer.pData)); + + if (inputPhysAddr == 0) { + LAC_LOG_ERROR( + "Unable to get the seed buffer physical address"); + status = CPA_STATUS_FAIL; + } + outputPhysAddr = LAC_MEM_CAST_PTR_TO_UINT64( + LAC_OS_VIRT_TO_PHYS_EXTERNAL(pService->generic_service_info, + pGeneratedMaskBuffer->pData)); + if (outputPhysAddr == 0) { + LAC_LOG_ERROR( + "Unable to get the physical address of the mask"); + status = CPA_STATUS_FAIL; + } + } + + if (CPA_STATUS_SUCCESS == status) { + /* Make up the full keyGenReq struct from its constituents */ + pMsgDummy = (Cpa8U *)&(keyGenReq); + pCacheDummyHdr = (Cpa8U *)&(keyGenReqHdr); + pCacheDummyMid = (Cpa8U *)&(keyGenReqMid); + pCacheDummyFtr = (Cpa8U *)&(keyGenReqFtr); + + memcpy(pMsgDummy, + pCacheDummyHdr, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)); + memset((pMsgDummy + + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)), + 0, + (LAC_LONG_WORD_IN_BYTES * + LAC_SIZE_OF_CACHE_TO_CLEAR_IN_LW)); + memcpy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_MID_IN_LW), + pCacheDummyMid, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_MID_IN_LW)); + memcpy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_FTR_IN_LW), + pCacheDummyFtr, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_FTR_IN_LW)); + + SalQatMsg_ContentDescHdrWrite((icp_qat_fw_comn_req_t *)&( + keyGenReq), + &(contentDescInfo)); + + SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)&keyGenReq, + ICP_QAT_FW_COMN_REQ_CPM_FW_LA, + ICP_QAT_FW_LA_CMD_MGF1, + cmnRequestFlags, + laCmdFlags); + + /* + * MGF uses a flat buffer but we can use zero for source and + * dest length because the firmware will use the seed length, + * hash length and mask length to find source length. + */ + SalQatMsg_CmnMidWrite((icp_qat_fw_la_bulk_req_t *)&(keyGenReq), + pCookie, + LAC_SYM_KEY_QAT_PTR_TYPE, + inputPhysAddr, + outputPhysAddr, + 0, + 0); + + /* Send to QAT */ + status = icp_adf_transPutMsg(pService->trans_handle_sym_tx, + (void *)&(keyGenReq), + LAC_QAT_SYM_REQ_SZ_LW); + } + if (CPA_STATUS_SUCCESS == status) { + /* Update stats */ + LAC_KEY_STAT_INC(numMgfKeyGenRequests, instanceHandle); + } else { + LAC_KEY_STAT_INC(numMgfKeyGenRequestErrors, instanceHandle); + /* clean up memory */ + if (NULL != pCookie) { + Lac_MemPoolEntryFree(pCookie); + } + } + return status; +} + +/** + * cpaCyKeyGenMgf + */ +CpaStatus +cpaCyKeyGenMgf(const CpaInstanceHandle instanceHandle_in, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const CpaCyKeyGenMgfOpData *pKeyGenMgfOpData, + CpaFlatBuffer *pGeneratedMaskBuffer) +{ + CpaInstanceHandle instanceHandle = NULL; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + /* If synchronous Operation */ + if (NULL == pKeyGenCb) { + return LacSymKey_MgfSync(instanceHandle, + pKeyGenCb, + pCallbackTag, + (const void *)pKeyGenMgfOpData, + pGeneratedMaskBuffer, + CPA_FALSE); + } + /* Asynchronous Operation */ + return LacSymKey_MgfCommon(instanceHandle, + pKeyGenCb, + pCallbackTag, + (const void *)pKeyGenMgfOpData, + pKeyGenMgfOpData, + pGeneratedMaskBuffer, + CPA_CY_SYM_HASH_SHA1); +} + +/** + * cpaCyKeyGenMgfExt + */ +CpaStatus +cpaCyKeyGenMgfExt(const CpaInstanceHandle instanceHandle_in, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const CpaCyKeyGenMgfOpDataExt *pKeyGenMgfOpDataExt, + CpaFlatBuffer *pGeneratedMaskBuffer) +{ + CpaInstanceHandle instanceHandle = NULL; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + /* If synchronous Operation */ + if (NULL == pKeyGenCb) { + return LacSymKey_MgfSync(instanceHandle, + pKeyGenCb, + pCallbackTag, + (const void *)pKeyGenMgfOpDataExt, + pGeneratedMaskBuffer, + CPA_TRUE); + } + + /* Param check specific for Ext function, rest of parameters validated + * in LacSymKey_MgfCommon + */ + LAC_CHECK_NULL_PARAM(pKeyGenMgfOpDataExt); + if (CPA_CY_SYM_HASH_MD5 > pKeyGenMgfOpDataExt->hashAlgorithm || + CPA_CY_SYM_HASH_SHA512 < pKeyGenMgfOpDataExt->hashAlgorithm) { + LAC_INVALID_PARAM_LOG("hashAlgorithm"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Asynchronous Operation */ + return LacSymKey_MgfCommon(instanceHandle, + pKeyGenCb, + pCallbackTag, + (const void *)pKeyGenMgfOpDataExt, + &pKeyGenMgfOpDataExt->baseOpData, + pGeneratedMaskBuffer, + pKeyGenMgfOpDataExt->hashAlgorithm); +} + +/** + ****************************************************************************** + * @ingroup LacSymKey + * Key Generation SSL & TLS response handler + * + * @description + * Handles Key Generation SSL & TLS response messages from the QAT. + * + * @param[in] lacCmdId Command id of the original request + * @param[in] pOpaqueData Pointer to opaque data that was in request + * @param[in] cmnRespFlags LA response flags + * + * @return void + * + *****************************************************************************/ +static void +LacSymKey_SslTlsHandleResponse(icp_qat_fw_la_cmd_id_t lacCmdId, + void *pOpaqueData, + icp_qat_fw_comn_flags cmnRespFlags) +{ + void *pSslTlsOpData = NULL; + CpaCyGenFlatBufCbFunc pKeyGenSslTlsCb = NULL; + lac_sym_key_cookie_t *pCookie = NULL; + void *pCallbackTag = NULL; + CpaFlatBuffer *pGeneratedKeyBuffer = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + + CpaBoolean respStatusOk = + (ICP_QAT_FW_COMN_STATUS_FLAG_OK == + ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(cmnRespFlags)) ? + CPA_TRUE : + CPA_FALSE; + + pCookie = (lac_sym_key_cookie_t *)pOpaqueData; + + pSslTlsOpData = pCookie->pKeyGenOpData; + + if (CPA_TRUE == respStatusOk) { + LacKey_StatsInc(lacCmdId, + LAC_KEY_COMPLETED, + pCookie->instanceHandle); + } else { + status = CPA_STATUS_FAIL; + LacKey_StatsInc(lacCmdId, + LAC_KEY_COMPLETED_ERRORS, + pCookie->instanceHandle); + } + + pKeyGenSslTlsCb = (CpaCyGenFlatBufCbFunc)(pCookie->pKeyGenCb); + + pCallbackTag = pCookie->pCallbackTag; + pGeneratedKeyBuffer = pCookie->pKeyGenOutputData; + + Lac_MemPoolEntryFree(pCookie); + + (*pKeyGenSslTlsCb)(pCallbackTag, + status, + pSslTlsOpData, + pGeneratedKeyBuffer); +} + +/** +******************************************************************************* +* @ingroup LacSymKey +* Synchronous mode of operation function wrapper for performing SSL/TLS +* key gen operation +* +* @description +* Synchronous mode of operation function wrapper for performing SSL/TLS +* key gen operation +* +* @param[in] instanceHandle QAT device handle. +* @param[in] pKeyGenCb Pointer to callback function to be invoked +* when the operation is complete. +* @param[in] pCallbackTag Opaque User Data for this specific call. +* @param[in] lacCmdId Lac command ID (identify SSL & TLS ops) +* @param[in] pKeyGenSslTlsOpData Structure containing all the data needed to +* perform the SSL/TLS key generation +* operation. +* @param[in] hashAlgorithm Specifies the hash algorithm to use. +* According to RFC5246, this should be +* "SHA-256 or a stronger standard hash +* function." +* @param[out] pKeyGenOutputData pointer to where output result should be +* written +* +* @retval CPA_STATUS_SUCCESS Function executed successfully. +* @retval CPA_STATUS_FAIL Function failed. +* @retval CPA_STATUS_RETRY Function should be retried. +* @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. +* @retval CPA_STATUS_RESOURCE Error related to system resources. +* +*****************************************************************************/ +static CpaStatus +LacSymKey_SslTlsSync(CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + icp_qat_fw_la_cmd_id_t lacCmdId, + void *pKeyGenSslTlsOpData, + Cpa8U hashAlgorithm, + CpaFlatBuffer *pKeyGenOutpuData) +{ + lac_sync_op_data_t *pSyncCallbackData = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + + status = LacSync_CreateSyncCookie(&pSyncCallbackData); + if (CPA_STATUS_SUCCESS == status) { + status = LacSymKey_KeyGenSslTls_GenCommon(instanceHandle, + pKeyGenCb, + pSyncCallbackData, + lacCmdId, + pKeyGenSslTlsOpData, + hashAlgorithm, + pKeyGenOutpuData); + } else { + /* Failure allocating sync cookie */ + LacKey_StatsInc(lacCmdId, + LAC_KEY_REQUEST_ERRORS, + instanceHandle); + return status; + } + + if (CPA_STATUS_SUCCESS == status) { + CpaStatus syncStatus = CPA_STATUS_SUCCESS; + + syncStatus = + LacSync_WaitForCallback(pSyncCallbackData, + LAC_SYM_SYNC_CALLBACK_TIMEOUT, + &status, + NULL); + + /* If callback doesn't come back */ + if (CPA_STATUS_SUCCESS != syncStatus) { + LacKey_StatsInc(lacCmdId, + LAC_KEY_COMPLETED_ERRORS, + instanceHandle); + LAC_LOG_ERROR("Callback timed out"); + status = syncStatus; + } + } else { + /* As the Request was not sent the Callback will never + * be called, so need to indicate that we're finished + * with cookie so it can be destroyed. + */ + LacSync_SetSyncCookieComplete(pSyncCallbackData); + } + + LacSync_DestroySyncCookie(&pSyncCallbackData); + + return status; +} + +static CpaStatus +computeHashKey(CpaFlatBuffer *secret, + CpaFlatBuffer *hash, + CpaCySymHashAlgorithm *hashAlgorithm) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + switch (*hashAlgorithm) { + case CPA_CY_SYM_HASH_MD5: + status = qatUtilsHashMD5Full(secret->pData, + hash->pData, + secret->dataLenInBytes); + break; + case CPA_CY_SYM_HASH_SHA1: + status = qatUtilsHashSHA1Full(secret->pData, + hash->pData, + secret->dataLenInBytes); + break; + case CPA_CY_SYM_HASH_SHA256: + status = qatUtilsHashSHA256Full(secret->pData, + hash->pData, + secret->dataLenInBytes); + break; + case CPA_CY_SYM_HASH_SHA384: + status = qatUtilsHashSHA384Full(secret->pData, + hash->pData, + secret->dataLenInBytes); + break; + case CPA_CY_SYM_HASH_SHA512: + status = qatUtilsHashSHA512Full(secret->pData, + hash->pData, + secret->dataLenInBytes); + break; + default: + status = CPA_STATUS_FAIL; + } + return status; +} + +static CpaStatus +LacSymKey_KeyGenSslTls_GenCommon(CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + icp_qat_fw_la_cmd_id_t lacCmdId, + void *pKeyGenSslTlsOpData, + Cpa8U hashAlgCipher, + CpaFlatBuffer *pKeyGenOutputData) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + CpaBoolean precompute = CPA_FALSE; + icp_qat_fw_la_bulk_req_t keyGenReq = { { 0 } }; + icp_qat_la_bulk_req_hdr_t keyGenReqHdr = { { 0 } }; + icp_qat_fw_la_key_gen_common_t keyGenReqMid = { { 0 } }; + icp_qat_la_bulk_req_ftr_t keyGenReqFtr = { { { 0 } } }; + Cpa8U *pMsgDummy = NULL; + Cpa8U *pCacheDummyHdr = NULL; + Cpa8U *pCacheDummyMid = NULL; + Cpa8U *pCacheDummyFtr = NULL; + lac_sym_key_cookie_t *pCookie = NULL; + lac_sym_cookie_t *pSymCookie = NULL; + Cpa64U inputPhysAddr = 0; + Cpa64U outputPhysAddr = 0; +/* Structure initializer is supported by C99, but it is + * not supported by some former Intel compiler. + */ + CpaCySymHashSetupData hashSetupData = { 0 }; + sal_qat_content_desc_info_t contentDescInfo = { 0 }; + Cpa32U hashBlkSizeInBytes = 0; + Cpa32U tlsPrefixLen = 0; + + CpaFlatBuffer inputSecret = { 0 }; + CpaFlatBuffer hashKeyOutput = { 0 }; + Cpa32U uSecretLen = 0; + CpaCySymHashNestedModeSetupData *pNestedModeSetupData = + &(hashSetupData.nestedModeSetupData); + icp_qat_fw_serv_specif_flags laCmdFlags = 0; + icp_qat_fw_comn_flags cmnRequestFlags = + ICP_QAT_FW_COMN_FLAGS_BUILD(QAT_COMN_PTR_TYPE_FLAT, + QAT_COMN_CD_FLD_TYPE_64BIT_ADR); + + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + + /* If synchronous Operation */ + if (NULL == pKeyGenCb) { + return LacSymKey_SslTlsSync(instanceHandle, + LacSync_GenFlatBufCb, + pCallbackTag, + lacCmdId, + pKeyGenSslTlsOpData, + hashAlgCipher, + pKeyGenOutputData); + } + /* Allocate the cookie */ + pCookie = (lac_sym_key_cookie_t *)Lac_MemPoolEntryAlloc( + pService->lac_sym_cookie_pool); + if (NULL == pCookie) { + LAC_LOG_ERROR("Cannot get mem pool entry"); + status = CPA_STATUS_RESOURCE; + } else if ((void *)CPA_STATUS_RETRY == pCookie) { + pCookie = NULL; + status = CPA_STATUS_RETRY; + } else { + pSymCookie = (lac_sym_cookie_t *)pCookie; + } + + if (CPA_STATUS_SUCCESS == status) { + icp_qat_hw_auth_mode_t qatHashMode = 0; + + if (ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE == lacCmdId) { + qatHashMode = ICP_QAT_HW_AUTH_MODE0; + } else /* TLS v1.1, v1.2, v1.3 */ + { + qatHashMode = ICP_QAT_HW_AUTH_MODE2; + } + + pCookie->instanceHandle = pService; + pCookie->pCallbackTag = pCallbackTag; + pCookie->pKeyGenCb = pKeyGenCb; + pCookie->pKeyGenOpData = pKeyGenSslTlsOpData; + pCookie->pKeyGenOutputData = pKeyGenOutputData; + hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_NESTED; + + /* SSL3 */ + if (ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE == lacCmdId) { + hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA1; + hashSetupData.digestResultLenInBytes = + LAC_HASH_MD5_DIGEST_SIZE; + pNestedModeSetupData->outerHashAlgorithm = + CPA_CY_SYM_HASH_MD5; + + pNestedModeSetupData->pInnerPrefixData = NULL; + pNestedModeSetupData->innerPrefixLenInBytes = 0; + pNestedModeSetupData->pOuterPrefixData = NULL; + pNestedModeSetupData->outerPrefixLenInBytes = 0; + } + /* TLS v1.1 */ + else if (ICP_QAT_FW_LA_CMD_TLS_V1_1_KEY_DERIVE == lacCmdId) { + CpaCyKeyGenTlsOpData *pKeyGenTlsOpData = + (CpaCyKeyGenTlsOpData *)pKeyGenSslTlsOpData; + + hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA1; + hashSetupData.digestResultLenInBytes = + LAC_HASH_MD5_DIGEST_SIZE; + pNestedModeSetupData->outerHashAlgorithm = + CPA_CY_SYM_HASH_MD5; + + uSecretLen = pKeyGenTlsOpData->secret.dataLenInBytes; + + /* We want to handle pre_master_secret > 128 bytes + * therefore we + * only verify if the current operation is Master Secret + * Derive. + * The other operations remain unchanged. + */ + if ((uSecretLen > + ICP_QAT_FW_LA_TLS_V1_1_SECRET_LEN_MAX) && + (CPA_CY_KEY_TLS_OP_MASTER_SECRET_DERIVE == + pKeyGenTlsOpData->tlsOp || + CPA_CY_KEY_TLS_OP_USER_DEFINED == + pKeyGenTlsOpData->tlsOp)) { + CpaCySymHashAlgorithm hashAlgorithm = + (CpaCySymHashAlgorithm)hashAlgCipher; + /* secret = [s1 | s2 ] + * s1 = outer prefix, s2 = inner prefix + * length of s1 and s2 = ceil(secret_length / 2) + * (secret length + 1)/2 will always give the + * ceil as + * division by 2 + * (>>1) will give the smallest integral value + * not less than + * arg + */ + tlsPrefixLen = + (pKeyGenTlsOpData->secret.dataLenInBytes + + 1) >> + 1; + inputSecret.dataLenInBytes = tlsPrefixLen; + inputSecret.pData = + pKeyGenTlsOpData->secret.pData; + + /* Since the pre_master_secret is > 128, we + * split the input + * pre_master_secret in 2 halves and compute the + * MD5 of the + * first half and the SHA1 on the second half. + */ + hashAlgorithm = CPA_CY_SYM_HASH_MD5; + + /* Initialize pointer where MD5 key will go. */ + hashKeyOutput.pData = + &pCookie->hashKeyBuffer[0]; + hashKeyOutput.dataLenInBytes = + LAC_HASH_MD5_DIGEST_SIZE; + computeHashKey(&inputSecret, + &hashKeyOutput, + &hashAlgorithm); + + pNestedModeSetupData->pOuterPrefixData = + &pCookie->hashKeyBuffer[0]; + pNestedModeSetupData->outerPrefixLenInBytes = + LAC_HASH_MD5_DIGEST_SIZE; + + /* Point to the second half of the + * pre_master_secret */ + inputSecret.pData = + pKeyGenTlsOpData->secret.pData + + (pKeyGenTlsOpData->secret.dataLenInBytes - + tlsPrefixLen); + + /* Compute SHA1 on the second half of the + * pre_master_secret + */ + hashAlgorithm = CPA_CY_SYM_HASH_SHA1; + /* Initialize pointer where SHA1 key will go. */ + hashKeyOutput.pData = + &pCookie->hashKeyBuffer + [LAC_HASH_MD5_DIGEST_SIZE]; + hashKeyOutput.dataLenInBytes = + LAC_HASH_SHA1_DIGEST_SIZE; + computeHashKey(&inputSecret, + &hashKeyOutput, + &hashAlgorithm); + + pNestedModeSetupData->pInnerPrefixData = + &pCookie->hashKeyBuffer + [LAC_HASH_MD5_DIGEST_SIZE]; + pNestedModeSetupData->innerPrefixLenInBytes = + LAC_HASH_SHA1_DIGEST_SIZE; + } else { + /* secret = [s1 | s2 ] + * s1 = outer prefix, s2 = inner prefix + * length of s1 and s2 = ceil(secret_length / 2) + * (secret length + 1)/2 will always give the + * ceil as + * division by 2 + * (>>1) will give the smallest integral value + * not less than + * arg + */ + tlsPrefixLen = + (pKeyGenTlsOpData->secret.dataLenInBytes + + 1) >> + 1; + /* last byte of s1 will be first byte of s2 if + * Length is odd + */ + pNestedModeSetupData->pInnerPrefixData = + pKeyGenTlsOpData->secret.pData + + (pKeyGenTlsOpData->secret.dataLenInBytes - + tlsPrefixLen); + + pNestedModeSetupData->pOuterPrefixData = + pKeyGenTlsOpData->secret.pData; + + pNestedModeSetupData->innerPrefixLenInBytes = + pNestedModeSetupData + ->outerPrefixLenInBytes = tlsPrefixLen; + } + } + /* TLS v1.2 */ + else if (ICP_QAT_FW_LA_CMD_TLS_V1_2_KEY_DERIVE == lacCmdId) { + CpaCyKeyGenTlsOpData *pKeyGenTlsOpData = + (CpaCyKeyGenTlsOpData *)pKeyGenSslTlsOpData; + CpaCySymHashAlgorithm hashAlgorithm = + (CpaCySymHashAlgorithm)hashAlgCipher; + + uSecretLen = pKeyGenTlsOpData->secret.dataLenInBytes; + + hashSetupData.hashAlgorithm = + (CpaCySymHashAlgorithm)hashAlgorithm; + hashSetupData.digestResultLenInBytes = + (Cpa32U)getDigestSizeFromHashAlgo(hashAlgorithm); + pNestedModeSetupData->outerHashAlgorithm = + (CpaCySymHashAlgorithm)hashAlgorithm; + if (CPA_CY_KEY_TLS_OP_MASTER_SECRET_DERIVE == + pKeyGenTlsOpData->tlsOp || + CPA_CY_KEY_TLS_OP_USER_DEFINED == + pKeyGenTlsOpData->tlsOp) { + switch (hashAlgorithm) { + case CPA_CY_SYM_HASH_SM3: + precompute = CPA_FALSE; + break; + case CPA_CY_SYM_HASH_SHA256: + if (uSecretLen > + ICP_QAT_FW_LA_TLS_V1_2_SECRET_LEN_MAX) { + precompute = CPA_TRUE; + } + break; + case CPA_CY_SYM_HASH_SHA384: + case CPA_CY_SYM_HASH_SHA512: + if (uSecretLen > + ICP_QAT_FW_LA_TLS_SECRET_LEN_MAX) { + precompute = CPA_TRUE; + } + break; + default: + break; + } + } + if (CPA_TRUE == precompute) { + /* Case when secret > algorithm block size + * RFC 4868: For SHA-256 Block size is 512 bits, + * for SHA-384 + * and SHA-512 Block size is 1024 bits + * Initialize pointer + * where SHAxxx key will go. + */ + hashKeyOutput.pData = + &pCookie->hashKeyBuffer[0]; + hashKeyOutput.dataLenInBytes = + hashSetupData.digestResultLenInBytes; + computeHashKey(&pKeyGenTlsOpData->secret, + &hashKeyOutput, + &hashSetupData.hashAlgorithm); + + /* Outer prefix = secret , inner prefix = secret + * secret < 64 bytes + */ + pNestedModeSetupData->pInnerPrefixData = + hashKeyOutput.pData; + pNestedModeSetupData->pOuterPrefixData = + hashKeyOutput.pData; + pNestedModeSetupData->innerPrefixLenInBytes = + hashKeyOutput.dataLenInBytes; + pNestedModeSetupData->outerPrefixLenInBytes = + hashKeyOutput.dataLenInBytes; + } else { + /* Outer prefix = secret , inner prefix = secret + * secret <= 64 bytes + */ + pNestedModeSetupData->pInnerPrefixData = + pKeyGenTlsOpData->secret.pData; + + pNestedModeSetupData->pOuterPrefixData = + pKeyGenTlsOpData->secret.pData; + + pNestedModeSetupData->innerPrefixLenInBytes = + pKeyGenTlsOpData->secret.dataLenInBytes; + pNestedModeSetupData->outerPrefixLenInBytes = + pKeyGenTlsOpData->secret.dataLenInBytes; + } + } + /* TLS v1.3 */ + else if ((ICP_QAT_FW_LA_CMD_HKDF_EXTRACT <= lacCmdId) && + (ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL >= + lacCmdId)) { + CpaCyKeyGenHKDFOpData *pKeyGenTlsOpData = + (CpaCyKeyGenHKDFOpData *)pKeyGenSslTlsOpData; + CpaCySymHashAlgorithm hashAlgorithm = + getHashAlgorithmFromCipherSuiteHKDF(hashAlgCipher); + + /* Set HASH data */ + hashSetupData.hashAlgorithm = hashAlgorithm; + /* Calculate digest length from the HASH type */ + hashSetupData.digestResultLenInBytes = + cipherSuiteHKDFHashSizes[hashAlgCipher] + [LAC_KEY_HKDF_DIGESTS]; + /* Outer Hash type is the same as inner hash type */ + pNestedModeSetupData->outerHashAlgorithm = + hashAlgorithm; + + /* EXPAND (PRK): + * Outer prefix = secret, inner prefix = secret + * EXTRACT (SEED/SALT): + * Outer prefix = seed, inner prefix = seed + * Secret <= 64 Bytes + * We do not pre compute as secret can't be larger than + * 64 bytes + */ + + if ((ICP_QAT_FW_LA_CMD_HKDF_EXPAND == lacCmdId) || + (ICP_QAT_FW_LA_CMD_HKDF_EXPAND_LABEL == lacCmdId)) { + pNestedModeSetupData->pInnerPrefixData = + pKeyGenTlsOpData->secret; + pNestedModeSetupData->pOuterPrefixData = + pKeyGenTlsOpData->secret; + pNestedModeSetupData->innerPrefixLenInBytes = + pKeyGenTlsOpData->secretLen; + pNestedModeSetupData->outerPrefixLenInBytes = + pKeyGenTlsOpData->secretLen; + } else { + pNestedModeSetupData->pInnerPrefixData = + pKeyGenTlsOpData->seed; + pNestedModeSetupData->pOuterPrefixData = + pKeyGenTlsOpData->seed; + pNestedModeSetupData->innerPrefixLenInBytes = + pKeyGenTlsOpData->seedLen; + pNestedModeSetupData->outerPrefixLenInBytes = + pKeyGenTlsOpData->seedLen; + } + } + + /* Set the footer Data. + * Note that following function doesn't look at inner/outer + * prefix pointers in nested digest ctx + */ + LacSymQat_HashContentDescInit( + &keyGenReqFtr, + instanceHandle, + &hashSetupData, + pCookie + ->contentDesc, /* Pointer to base of hw setup block */ + LAC_SYM_KEY_NO_HASH_BLK_OFFSET_QW, + ICP_QAT_FW_SLICE_DRAM_WR, + qatHashMode, + CPA_FALSE, /* Not using sym Constants Table in SRAM */ + CPA_FALSE, /* Not using the optimised content Desc */ + NULL, /* Precompute data */ + &hashBlkSizeInBytes); + + /* SSL3 */ + if (ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE == lacCmdId) { + CpaCyKeyGenSslOpData *pKeyGenSslOpData = + (CpaCyKeyGenSslOpData *)pKeyGenSslTlsOpData; + Cpa8U *pLabel = NULL; + Cpa32U labelLen = 0; + Cpa8U iterations = 0; + Cpa64U labelPhysAddr = 0; + + /* Iterations = ceiling of output required / output per + * iteration Ceiling of a / b = (a + (b-1)) / b + */ + iterations = + (pKeyGenSslOpData->generatedKeyLenInBytes + + (LAC_SYM_QAT_KEY_SSL_BYTES_PER_ITERATION - 1)) >> + LAC_SYM_QAT_KEY_SSL_ITERATIONS_SHIFT; + + if (CPA_CY_KEY_SSL_OP_USER_DEFINED == + pKeyGenSslOpData->sslOp) { + pLabel = pKeyGenSslOpData->userLabel.pData; + labelLen = + pKeyGenSslOpData->userLabel.dataLenInBytes; + labelPhysAddr = LAC_OS_VIRT_TO_PHYS_EXTERNAL( + pService->generic_service_info, pLabel); + + if (labelPhysAddr == 0) { + LAC_LOG_ERROR( + "Unable to get the physical address of the" + " label"); + status = CPA_STATUS_FAIL; + } + } else { + pLabel = pService->pSslLabel; + + /* Calculate label length. + * eg. 3 iterations is ABBCCC so length is 6 + */ + labelLen = + ((iterations * iterations) + iterations) >> + 1; + labelPhysAddr = + LAC_OS_VIRT_TO_PHYS_INTERNAL(pLabel); + } + + LacSymQat_KeySslRequestPopulate( + &keyGenReqHdr, + &keyGenReqMid, + pKeyGenSslOpData->generatedKeyLenInBytes, + labelLen, + pKeyGenSslOpData->secret.dataLenInBytes, + iterations); + + LacSymQat_KeySslKeyMaterialInputPopulate( + &(pService->generic_service_info), + &(pCookie->u.sslKeyInput), + pKeyGenSslOpData->seed.pData, + labelPhysAddr, + pKeyGenSslOpData->secret.pData); + + inputPhysAddr = LAC_MEM_CAST_PTR_TO_UINT64( + pSymCookie->keySslKeyInputPhyAddr); + } + /* TLS v1.1, v1.2 */ + else if (ICP_QAT_FW_LA_CMD_TLS_V1_1_KEY_DERIVE == lacCmdId || + ICP_QAT_FW_LA_CMD_TLS_V1_2_KEY_DERIVE == lacCmdId) { + CpaCyKeyGenTlsOpData *pKeyGenTlsOpData = + (CpaCyKeyGenTlsOpData *)pKeyGenSslTlsOpData; + lac_sym_qat_hash_state_buffer_info_t + hashStateBufferInfo = { 0 }; + CpaBoolean hashStateBuffer = CPA_FALSE; + icp_qat_fw_auth_cd_ctrl_hdr_t *pHashControlBlock = + (icp_qat_fw_auth_cd_ctrl_hdr_t *)&( + keyGenReqFtr.cd_ctrl); + icp_qat_la_auth_req_params_t *pHashReqParams = NULL; + Cpa8U *pLabel = NULL; + Cpa32U labelLen = 0; + Cpa64U labelPhysAddr = 0; + hashStateBufferInfo.pData = pCookie->hashStateBuffer; + hashStateBufferInfo.pDataPhys = + LAC_MEM_CAST_PTR_TO_UINT64( + pSymCookie->keyHashStateBufferPhyAddr); + hashStateBufferInfo.stateStorageSzQuadWords = 0; + + LacSymQat_HashSetupReqParamsMetaData(&(keyGenReqFtr), + instanceHandle, + &(hashSetupData), + hashStateBuffer, + qatHashMode, + CPA_FALSE); + + pHashReqParams = (icp_qat_la_auth_req_params_t *)&( + keyGenReqFtr.serv_specif_rqpars); + + hashStateBufferInfo.prefixAadSzQuadWords = + LAC_BYTES_TO_QUADWORDS( + pHashReqParams->u2.inner_prefix_sz + + pHashControlBlock->outer_prefix_sz); + + /* Copy prefix data into hash state buffer */ + pMsgDummy = (Cpa8U *)&(keyGenReq); + pCacheDummyHdr = (Cpa8U *)&(keyGenReqHdr); + pCacheDummyMid = (Cpa8U *)&(keyGenReqMid); + pCacheDummyFtr = (Cpa8U *)&(keyGenReqFtr); + memcpy(pMsgDummy, + pCacheDummyHdr, + (LAC_LONG_WORD_IN_BYTES * + LAC_SIZE_OF_CACHE_HDR_IN_LW)); + memcpy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_MID_IN_LW), + pCacheDummyMid, + (LAC_LONG_WORD_IN_BYTES * + LAC_SIZE_OF_CACHE_MID_IN_LW)); + memcpy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_FTR_IN_LW), + pCacheDummyFtr, + (LAC_LONG_WORD_IN_BYTES * + LAC_SIZE_OF_CACHE_FTR_IN_LW)); + + LacSymQat_HashStatePrefixAadBufferPopulate( + &hashStateBufferInfo, + &keyGenReqFtr, + pNestedModeSetupData->pInnerPrefixData, + pNestedModeSetupData->innerPrefixLenInBytes, + pNestedModeSetupData->pOuterPrefixData, + pNestedModeSetupData->outerPrefixLenInBytes); + + /* Firmware only looks at hash state buffer pointer and + * the + * hash state buffer size so all other fields are set to + * 0 + */ + LacSymQat_HashRequestParamsPopulate( + &(keyGenReq), + 0, /* Auth offset */ + 0, /* Auth length */ + &(pService->generic_service_info), + &hashStateBufferInfo, /* Hash state prefix buffer */ + ICP_QAT_FW_LA_PARTIAL_NONE, + 0, /* Hash result size */ + CPA_FALSE, + NULL, + CPA_CY_SYM_HASH_NONE, /* Hash algorithm */ + NULL); /* HKDF only */ + + /* Set up the labels and their length */ + if (CPA_CY_KEY_TLS_OP_USER_DEFINED == + pKeyGenTlsOpData->tlsOp) { + pLabel = pKeyGenTlsOpData->userLabel.pData; + labelLen = + pKeyGenTlsOpData->userLabel.dataLenInBytes; + labelPhysAddr = LAC_OS_VIRT_TO_PHYS_EXTERNAL( + pService->generic_service_info, pLabel); + + if (labelPhysAddr == 0) { + LAC_LOG_ERROR( + "Unable to get the physical address of the" + " label"); + status = CPA_STATUS_FAIL; + } + } else if (CPA_CY_KEY_TLS_OP_MASTER_SECRET_DERIVE == + pKeyGenTlsOpData->tlsOp) { + pLabel = pService->pTlsLabel->masterSecret; + labelLen = + sizeof( + LAC_SYM_KEY_TLS_MASTER_SECRET_LABEL) - + 1; + labelPhysAddr = + LAC_OS_VIRT_TO_PHYS_INTERNAL(pLabel); + } else if (CPA_CY_KEY_TLS_OP_KEY_MATERIAL_DERIVE == + pKeyGenTlsOpData->tlsOp) { + pLabel = pService->pTlsLabel->keyMaterial; + labelLen = + sizeof(LAC_SYM_KEY_TLS_KEY_MATERIAL_LABEL) - + 1; + labelPhysAddr = + LAC_OS_VIRT_TO_PHYS_INTERNAL(pLabel); + } else if (CPA_CY_KEY_TLS_OP_CLIENT_FINISHED_DERIVE == + pKeyGenTlsOpData->tlsOp) { + pLabel = pService->pTlsLabel->clientFinished; + labelLen = + sizeof(LAC_SYM_KEY_TLS_CLIENT_FIN_LABEL) - + 1; + labelPhysAddr = + LAC_OS_VIRT_TO_PHYS_INTERNAL(pLabel); + } else { + pLabel = pService->pTlsLabel->serverFinished; + labelLen = + sizeof(LAC_SYM_KEY_TLS_SERVER_FIN_LABEL) - + 1; + labelPhysAddr = + LAC_OS_VIRT_TO_PHYS_INTERNAL(pLabel); + } + LacSymQat_KeyTlsRequestPopulate( + &keyGenReqMid, + pKeyGenTlsOpData->generatedKeyLenInBytes, + labelLen, + pKeyGenTlsOpData->secret.dataLenInBytes, + pKeyGenTlsOpData->seed.dataLenInBytes, + lacCmdId); + + LacSymQat_KeyTlsKeyMaterialInputPopulate( + &(pService->generic_service_info), + &(pCookie->u.tlsKeyInput), + pKeyGenTlsOpData->seed.pData, + labelPhysAddr); + + inputPhysAddr = LAC_MEM_CAST_PTR_TO_UINT64( + pSymCookie->keyTlsKeyInputPhyAddr); + } + /* TLS v1.3 */ + else if (ICP_QAT_FW_LA_CMD_HKDF_EXTRACT <= lacCmdId && + ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND >= + lacCmdId) { + CpaCyKeyGenHKDFOpData *pKeyGenTlsOpData = + (CpaCyKeyGenHKDFOpData *)pKeyGenSslTlsOpData; + lac_sym_qat_hash_state_buffer_info_t + hashStateBufferInfo = { 0 }; + CpaBoolean hashStateBuffer = CPA_FALSE; + icp_qat_fw_auth_cd_ctrl_hdr_t *pHashControlBlock = + (icp_qat_fw_auth_cd_ctrl_hdr_t *)&( + keyGenReqFtr.cd_ctrl); + icp_qat_la_auth_req_params_t *pHashReqParams = NULL; + hashStateBufferInfo.pData = pCookie->hashStateBuffer; + hashStateBufferInfo.pDataPhys = + LAC_MEM_CAST_PTR_TO_UINT64( + pSymCookie->keyHashStateBufferPhyAddr); + hashStateBufferInfo.stateStorageSzQuadWords = 0; + + LacSymQat_HashSetupReqParamsMetaData(&(keyGenReqFtr), + instanceHandle, + &(hashSetupData), + hashStateBuffer, + qatHashMode, + CPA_FALSE); + + pHashReqParams = (icp_qat_la_auth_req_params_t *)&( + keyGenReqFtr.serv_specif_rqpars); + + hashStateBufferInfo.prefixAadSzQuadWords = + LAC_BYTES_TO_QUADWORDS( + pHashReqParams->u2.inner_prefix_sz + + pHashControlBlock->outer_prefix_sz); + + /* Copy prefix data into hash state buffer */ + pMsgDummy = (Cpa8U *)&(keyGenReq); + pCacheDummyHdr = (Cpa8U *)&(keyGenReqHdr); + pCacheDummyMid = (Cpa8U *)&(keyGenReqMid); + pCacheDummyFtr = (Cpa8U *)&(keyGenReqFtr); + memcpy(pMsgDummy, + pCacheDummyHdr, + (LAC_LONG_WORD_IN_BYTES * + LAC_SIZE_OF_CACHE_HDR_IN_LW)); + memcpy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_MID_IN_LW), + pCacheDummyMid, + (LAC_LONG_WORD_IN_BYTES * + LAC_SIZE_OF_CACHE_MID_IN_LW)); + memcpy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_FTR_IN_LW), + pCacheDummyFtr, + (LAC_LONG_WORD_IN_BYTES * + LAC_SIZE_OF_CACHE_FTR_IN_LW)); + + LacSymQat_HashStatePrefixAadBufferPopulate( + &hashStateBufferInfo, + &keyGenReqFtr, + pNestedModeSetupData->pInnerPrefixData, + pNestedModeSetupData->innerPrefixLenInBytes, + pNestedModeSetupData->pOuterPrefixData, + pNestedModeSetupData->outerPrefixLenInBytes); + + /* Firmware only looks at hash state buffer pointer and + * the + * hash state buffer size so all other fields are set to + * 0 + */ + LacSymQat_HashRequestParamsPopulate( + &(keyGenReq), + 0, /* Auth offset */ + 0, /* Auth length */ + &(pService->generic_service_info), + &hashStateBufferInfo, /* Hash state prefix buffer */ + ICP_QAT_FW_LA_PARTIAL_NONE, + 0, /* Hash result size */ + CPA_FALSE, + NULL, + CPA_CY_SYM_HASH_NONE, /* Hash algorithm */ + pKeyGenTlsOpData->secret); /* IKM or PRK */ + + LacSymQat_KeyTlsRequestPopulate( + &keyGenReqMid, + cipherSuiteHKDFHashSizes[hashAlgCipher] + [LAC_KEY_HKDF_DIGESTS], + /* For EXTRACT, EXPAND, FW expects info to be passed + as label */ + pKeyGenTlsOpData->infoLen, + pKeyGenTlsOpData->secretLen, + pKeyGenTlsOpData->seedLen, + lacCmdId); + + LacSymQat_KeyTlsHKDFKeyMaterialInputPopulate( + &(pService->generic_service_info), + &(pCookie->u.tlsHKDFKeyInput), + pKeyGenTlsOpData, + 0, /* No subLabels used */ + lacCmdId); /* Pass op being performed */ + + inputPhysAddr = LAC_MEM_CAST_PTR_TO_UINT64( + pSymCookie->keyTlsKeyInputPhyAddr); + } + /* TLS v1.3 LABEL */ + else if (ICP_QAT_FW_LA_CMD_HKDF_EXPAND_LABEL == lacCmdId || + ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL == + lacCmdId) { + CpaCyKeyGenHKDFOpData *pKeyGenTlsOpData = + (CpaCyKeyGenHKDFOpData *)pKeyGenSslTlsOpData; + Cpa64U subLabelsPhysAddr = 0; + lac_sym_qat_hash_state_buffer_info_t + hashStateBufferInfo = { 0 }; + CpaBoolean hashStateBuffer = CPA_FALSE; + icp_qat_fw_auth_cd_ctrl_hdr_t *pHashControlBlock = + (icp_qat_fw_auth_cd_ctrl_hdr_t *)&( + keyGenReqFtr.cd_ctrl); + icp_qat_la_auth_req_params_t *pHashReqParams = NULL; + hashStateBufferInfo.pData = pCookie->hashStateBuffer; + hashStateBufferInfo.pDataPhys = + LAC_MEM_CAST_PTR_TO_UINT64( + pSymCookie->keyHashStateBufferPhyAddr); + hashStateBufferInfo.stateStorageSzQuadWords = 0; + + LacSymQat_HashSetupReqParamsMetaData(&(keyGenReqFtr), + instanceHandle, + &(hashSetupData), + hashStateBuffer, + qatHashMode, + CPA_FALSE); + + pHashReqParams = (icp_qat_la_auth_req_params_t *)&( + keyGenReqFtr.serv_specif_rqpars); + + hashStateBufferInfo.prefixAadSzQuadWords = + LAC_BYTES_TO_QUADWORDS( + pHashReqParams->u2.inner_prefix_sz + + pHashControlBlock->outer_prefix_sz); + + /* Copy prefix data into hash state buffer */ + pMsgDummy = (Cpa8U *)&(keyGenReq); + pCacheDummyHdr = (Cpa8U *)&(keyGenReqHdr); + pCacheDummyMid = (Cpa8U *)&(keyGenReqMid); + pCacheDummyFtr = (Cpa8U *)&(keyGenReqFtr); + memcpy(pMsgDummy, + pCacheDummyHdr, + (LAC_LONG_WORD_IN_BYTES * + LAC_SIZE_OF_CACHE_HDR_IN_LW)); + memcpy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_MID_IN_LW), + pCacheDummyMid, + (LAC_LONG_WORD_IN_BYTES * + LAC_SIZE_OF_CACHE_MID_IN_LW)); + memcpy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_FTR_IN_LW), + pCacheDummyFtr, + (LAC_LONG_WORD_IN_BYTES * + LAC_SIZE_OF_CACHE_FTR_IN_LW)); + + LacSymQat_HashStatePrefixAadBufferPopulate( + &hashStateBufferInfo, + &keyGenReqFtr, + pNestedModeSetupData->pInnerPrefixData, + pNestedModeSetupData->innerPrefixLenInBytes, + pNestedModeSetupData->pOuterPrefixData, + pNestedModeSetupData->outerPrefixLenInBytes); + + /* Firmware only looks at hash state buffer pointer and + * the + * hash state buffer size so all other fields are set to + * 0 + */ + LacSymQat_HashRequestParamsPopulate( + &(keyGenReq), + 0, /* Auth offset */ + 0, /* Auth length */ + &(pService->generic_service_info), + &hashStateBufferInfo, /* Hash state prefix buffer */ + ICP_QAT_FW_LA_PARTIAL_NONE, + 0, /* Hash result size */ + CPA_FALSE, + NULL, + CPA_CY_SYM_HASH_NONE, /* Hash algorithm */ + pKeyGenTlsOpData->secret); /* IKM or PRK */ + + LacSymQat_KeyTlsRequestPopulate( + &keyGenReqMid, + cipherSuiteHKDFHashSizes[hashAlgCipher] + [LAC_KEY_HKDF_DIGESTS], + pKeyGenTlsOpData->numLabels, /* Number of Labels */ + pKeyGenTlsOpData->secretLen, + pKeyGenTlsOpData->seedLen, + lacCmdId); + + /* Get physical address of subLabels */ + switch (hashAlgCipher) { + case CPA_CY_HKDF_TLS_AES_128_GCM_SHA256: /* Fall Through + */ + case CPA_CY_HKDF_TLS_AES_128_CCM_SHA256: + case CPA_CY_HKDF_TLS_AES_128_CCM_8_SHA256: + subLabelsPhysAddr = pService->pTlsHKDFSubLabel + ->sublabelPhysAddr256; + break; + case CPA_CY_HKDF_TLS_CHACHA20_POLY1305_SHA256: + subLabelsPhysAddr = + pService->pTlsHKDFSubLabel + ->sublabelPhysAddrChaChaPoly; + break; + case CPA_CY_HKDF_TLS_AES_256_GCM_SHA384: + subLabelsPhysAddr = pService->pTlsHKDFSubLabel + ->sublabelPhysAddr384; + break; + default: + break; + } + + LacSymQat_KeyTlsHKDFKeyMaterialInputPopulate( + &(pService->generic_service_info), + &(pCookie->u.tlsHKDFKeyInput), + pKeyGenTlsOpData, + subLabelsPhysAddr, + lacCmdId); /* Pass op being performed */ + + inputPhysAddr = LAC_MEM_CAST_PTR_TO_UINT64( + pSymCookie->keyTlsKeyInputPhyAddr); + } + + outputPhysAddr = LAC_MEM_CAST_PTR_TO_UINT64( + LAC_OS_VIRT_TO_PHYS_EXTERNAL(pService->generic_service_info, + pKeyGenOutputData->pData)); + + if (outputPhysAddr == 0) { + LAC_LOG_ERROR( + "Unable to get the physical address of the" + " output buffer"); + status = CPA_STATUS_FAIL; + } + } + if (CPA_STATUS_SUCCESS == status) { + Cpa8U lw26[4]; + char *tmp = NULL; + unsigned char a; + int n = 0; + /* Make up the full keyGenReq struct from its constituents + * before calling the SalQatMsg functions below. + * Note: The full cache struct has been reduced to a + * header, mid and footer for memory size reduction + */ + pMsgDummy = (Cpa8U *)&(keyGenReq); + pCacheDummyHdr = (Cpa8U *)&(keyGenReqHdr); + pCacheDummyMid = (Cpa8U *)&(keyGenReqMid); + pCacheDummyFtr = (Cpa8U *)&(keyGenReqFtr); + + memcpy(pMsgDummy, + pCacheDummyHdr, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)); + memcpy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_MID_IN_LW), + pCacheDummyMid, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_MID_IN_LW)); + memcpy(&lw26, + pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_FTR_IN_LW), + LAC_LONG_WORD_IN_BYTES); + memcpy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_FTR_IN_LW), + pCacheDummyFtr, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_FTR_IN_LW)); + tmp = (char *)(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_FTR_IN_LW)); + + /* Copy LW26, or'd with what's already there, into the Msg, for + * TLS */ + for (n = 0; n < LAC_LONG_WORD_IN_BYTES; n++) { + a = (unsigned char)*(tmp + n); + lw26[n] = lw26[n] | a; + } + memcpy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_FTR_IN_LW), + &lw26, + LAC_LONG_WORD_IN_BYTES); + + contentDescInfo.pData = pCookie->contentDesc; + contentDescInfo.hardwareSetupBlockPhys = + LAC_MEM_CAST_PTR_TO_UINT64( + pSymCookie->keyContentDescPhyAddr); + contentDescInfo.hwBlkSzQuadWords = + LAC_BYTES_TO_QUADWORDS(hashBlkSizeInBytes); + + /* Populate common request fields */ + SalQatMsg_ContentDescHdrWrite((icp_qat_fw_comn_req_t *)&( + keyGenReq), + &(contentDescInfo)); + + SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)&keyGenReq, + ICP_QAT_FW_COMN_REQ_CPM_FW_LA, + lacCmdId, + cmnRequestFlags, + laCmdFlags); + + SalQatMsg_CmnMidWrite((icp_qat_fw_la_bulk_req_t *)&(keyGenReq), + pCookie, + LAC_SYM_KEY_QAT_PTR_TYPE, + inputPhysAddr, + outputPhysAddr, + 0, + 0); + + /* Send to QAT */ + status = icp_adf_transPutMsg(pService->trans_handle_sym_tx, + (void *)&(keyGenReq), + LAC_QAT_SYM_REQ_SZ_LW); + } + if (CPA_STATUS_SUCCESS == status) { + /* Update stats */ + LacKey_StatsInc(lacCmdId, + LAC_KEY_REQUESTS, + pCookie->instanceHandle); + } else { + /* Clean up cookie memory */ + if (NULL != pCookie) { + LacKey_StatsInc(lacCmdId, + LAC_KEY_REQUEST_ERRORS, + pCookie->instanceHandle); + Lac_MemPoolEntryFree(pCookie); + } + } + return status; +} + +/** + * @ingroup LacSymKey + * Parameters check for TLS v1.0/1.1, v1.2, v1.3 and SSL3 + * @description + * Check user parameters against the firmware/spec requirements. + * + * @param[in] pKeyGenOpData Pointer to a structure containing all + * the data needed to perform the key + * generation operation. + * @param[in] hashAlgCipher Specifies the hash algorithm, + * or cipher we are using. + * According to RFC5246, this should be + * "SHA-256 or a stronger standard hash + * function." + * @param[in] pGeneratedKeyBuffer User output buffers. + * @param[in] cmdId Keygen operation to perform. + */ +static CpaStatus +LacSymKey_CheckParamSslTls(const void *pKeyGenOpData, + Cpa8U hashAlgCipher, + const CpaFlatBuffer *pGeneratedKeyBuffer, + icp_qat_fw_la_cmd_id_t cmdId) +{ + /* Api max value */ + Cpa32U maxSecretLen = 0; + Cpa32U maxSeedLen = 0; + Cpa32U maxOutputLen = 0; + Cpa32U maxInfoLen = 0; + Cpa32U maxLabelLen = 0; + + /* User info */ + Cpa32U uSecretLen = 0; + Cpa32U uSeedLen = 0; + Cpa32U uOutputLen = 0; + + LAC_CHECK_NULL_PARAM(pKeyGenOpData); + LAC_CHECK_NULL_PARAM(pGeneratedKeyBuffer); + LAC_CHECK_NULL_PARAM(pGeneratedKeyBuffer->pData); + + if (ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE == cmdId) { + CpaCyKeyGenSslOpData *opData = + (CpaCyKeyGenSslOpData *)pKeyGenOpData; + + /* User info */ + uSecretLen = opData->secret.dataLenInBytes; + uSeedLen = opData->seed.dataLenInBytes; + uOutputLen = opData->generatedKeyLenInBytes; + + /* Api max value */ + maxSecretLen = ICP_QAT_FW_LA_SSL_SECRET_LEN_MAX; + maxSeedLen = ICP_QAT_FW_LA_SSL_SEED_LEN_MAX; + maxOutputLen = ICP_QAT_FW_LA_SSL_OUTPUT_LEN_MAX; + + /* Check user buffers */ + LAC_CHECK_NULL_PARAM(opData->secret.pData); + LAC_CHECK_NULL_PARAM(opData->seed.pData); + + /* Check operation */ + if ((Cpa32U)opData->sslOp > CPA_CY_KEY_SSL_OP_USER_DEFINED) { + LAC_INVALID_PARAM_LOG("opData->sslOp"); + return CPA_STATUS_INVALID_PARAM; + } + if ((Cpa32U)opData->sslOp == CPA_CY_KEY_SSL_OP_USER_DEFINED) { + LAC_CHECK_NULL_PARAM(opData->userLabel.pData); + /* Maximum label length for SSL Key Gen request */ + if (opData->userLabel.dataLenInBytes > + ICP_QAT_FW_LA_SSL_LABEL_LEN_MAX) { + LAC_INVALID_PARAM_LOG( + "userLabel.dataLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* Only seed length for SSL3 Key Gen request */ + if (maxSeedLen != uSeedLen) { + LAC_INVALID_PARAM_LOG("seed.dataLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Maximum output length for SSL3 Key Gen request */ + if (uOutputLen > maxOutputLen) { + LAC_INVALID_PARAM_LOG("generatedKeyLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } + /* TLS v1.1 or TLS v.12 */ + else if (ICP_QAT_FW_LA_CMD_TLS_V1_1_KEY_DERIVE == cmdId || + ICP_QAT_FW_LA_CMD_TLS_V1_2_KEY_DERIVE == cmdId) { + CpaCyKeyGenTlsOpData *opData = + (CpaCyKeyGenTlsOpData *)pKeyGenOpData; + + /* User info */ + uSecretLen = opData->secret.dataLenInBytes; + uSeedLen = opData->seed.dataLenInBytes; + uOutputLen = opData->generatedKeyLenInBytes; + + if (ICP_QAT_FW_LA_CMD_TLS_V1_1_KEY_DERIVE == cmdId) { + /* Api max value */ + /* ICP_QAT_FW_LA_TLS_V1_1_SECRET_LEN_MAX needs to be + * multiplied + * by 4 in order to verifiy the 512 conditions. We did + * not change + * ICP_QAT_FW_LA_TLS_V1_1_SECRET_LEN_MAX as it + * represents + * the max value tha firmware can handle. + */ + maxSecretLen = + ICP_QAT_FW_LA_TLS_V1_1_SECRET_LEN_MAX * 4; + } else { + /* Api max value */ + /* ICP_QAT_FW_LA_TLS_V1_2_SECRET_LEN_MAX needs to be + * multiplied + * by 8 in order to verifiy the 512 conditions. We did + * not change + * ICP_QAT_FW_LA_TLS_V1_2_SECRET_LEN_MAX as it + * represents + * the max value tha firmware can handle. + */ + maxSecretLen = + ICP_QAT_FW_LA_TLS_V1_2_SECRET_LEN_MAX * 8; + + /* Check Hash algorithm */ + if (0 == getDigestSizeFromHashAlgo(hashAlgCipher)) { + LAC_INVALID_PARAM_LOG("hashAlgorithm"); + return CPA_STATUS_INVALID_PARAM; + } + } + maxSeedLen = ICP_QAT_FW_LA_TLS_SEED_LEN_MAX; + maxOutputLen = ICP_QAT_FW_LA_TLS_OUTPUT_LEN_MAX; + /* Check user buffers */ + LAC_CHECK_NULL_PARAM(opData->secret.pData); + LAC_CHECK_NULL_PARAM(opData->seed.pData); + + /* Check operation */ + if ((Cpa32U)opData->tlsOp > CPA_CY_KEY_TLS_OP_USER_DEFINED) { + LAC_INVALID_PARAM_LOG("opData->tlsOp"); + return CPA_STATUS_INVALID_PARAM; + } else if ((Cpa32U)opData->tlsOp == + CPA_CY_KEY_TLS_OP_USER_DEFINED) { + LAC_CHECK_NULL_PARAM(opData->userLabel.pData); + /* Maximum label length for TLS Key Gen request */ + if (opData->userLabel.dataLenInBytes > + ICP_QAT_FW_LA_TLS_LABEL_LEN_MAX) { + LAC_INVALID_PARAM_LOG( + "userLabel.dataLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* Maximum/only seed length for TLS Key Gen request */ + if (((Cpa32U)opData->tlsOp != + CPA_CY_KEY_TLS_OP_MASTER_SECRET_DERIVE) && + ((Cpa32U)opData->tlsOp != + CPA_CY_KEY_TLS_OP_KEY_MATERIAL_DERIVE)) { + if (uSeedLen > maxSeedLen) { + LAC_INVALID_PARAM_LOG("seed.dataLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } else { + if (maxSeedLen != uSeedLen) { + LAC_INVALID_PARAM_LOG("seed.dataLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* Maximum output length for TLS Key Gen request */ + if (uOutputLen > maxOutputLen) { + LAC_INVALID_PARAM_LOG("generatedKeyLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } + /* TLS v1.3 */ + else if (cmdId >= ICP_QAT_FW_LA_CMD_HKDF_EXTRACT && + cmdId <= ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL) { + CpaCyKeyGenHKDFOpData *HKDF_Data = + (CpaCyKeyGenHKDFOpData *)pKeyGenOpData; + CpaCyKeyHKDFCipherSuite cipherSuite = hashAlgCipher; + CpaCySymHashAlgorithm hashAlgorithm = + getHashAlgorithmFromCipherSuiteHKDF(cipherSuite); + maxSeedLen = + cipherSuiteHKDFHashSizes[cipherSuite][LAC_KEY_HKDF_DIGESTS]; + maxSecretLen = CPA_CY_HKDF_KEY_MAX_SECRET_SZ; + maxInfoLen = CPA_CY_HKDF_KEY_MAX_INFO_SZ; + maxLabelLen = CPA_CY_HKDF_KEY_MAX_LABEL_SZ; + + uSecretLen = HKDF_Data->secretLen; + + /* Check using supported hash function */ + if (0 == + (uOutputLen = getDigestSizeFromHashAlgo(hashAlgorithm))) { + LAC_INVALID_PARAM_LOG("Hash function not supported"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Number of labels does not exceed the MAX */ + if (HKDF_Data->numLabels > CPA_CY_HKDF_KEY_MAX_LABEL_COUNT) { + LAC_INVALID_PARAM_LOG( + "CpaCyKeyGenHKDFOpData.numLabels"); + return CPA_STATUS_INVALID_PARAM; + } + + switch (cmdId) { + case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT: + if (maxSeedLen < HKDF_Data->seedLen) { + LAC_INVALID_PARAM_LOG( + "CpaCyKeyGenHKDFOpData.seedLen"); + return CPA_STATUS_INVALID_PARAM; + } + break; + case ICP_QAT_FW_LA_CMD_HKDF_EXPAND: + maxSecretLen = + cipherSuiteHKDFHashSizes[cipherSuite] + [LAC_KEY_HKDF_DIGESTS]; + + if (maxInfoLen < HKDF_Data->infoLen) { + LAC_INVALID_PARAM_LOG( + "CpaCyKeyGenHKDFOpData.infoLen"); + return CPA_STATUS_INVALID_PARAM; + } + break; + case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND: + uOutputLen *= 2; + if (maxSeedLen < HKDF_Data->seedLen) { + LAC_INVALID_PARAM_LOG( + "CpaCyKeyGenHKDFOpData.seedLen"); + return CPA_STATUS_INVALID_PARAM; + } + if (maxInfoLen < HKDF_Data->infoLen) { + LAC_INVALID_PARAM_LOG( + "CpaCyKeyGenHKDFOpData.infoLen"); + return CPA_STATUS_INVALID_PARAM; + } + break; + case ICP_QAT_FW_LA_CMD_HKDF_EXPAND_LABEL: /* Fall through */ + case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL: { + Cpa8U subl_mask = 0, subl_number = 1; + Cpa8U i = 0; + + if (maxSeedLen < HKDF_Data->seedLen) { + LAC_INVALID_PARAM_LOG( + "CpaCyKeyGenHKDFOpData.seedLen"); + return CPA_STATUS_INVALID_PARAM; + } + + /* If EXPAND set uOutputLen to zero */ + if (ICP_QAT_FW_LA_CMD_HKDF_EXPAND_LABEL == cmdId) { + uOutputLen = 0; + maxSecretLen = cipherSuiteHKDFHashSizes + [cipherSuite][LAC_KEY_HKDF_DIGESTS]; + } + + for (i = 0; i < HKDF_Data->numLabels; i++) { + /* Check that the labelLen does not overflow */ + if (maxLabelLen < + HKDF_Data->label[i].labelLen) { + LAC_INVALID_PARAM_LOG1( + "CpaCyKeyGenHKDFOpData.label[%d].labelLen", + i); + return CPA_STATUS_INVALID_PARAM; + } + + if (HKDF_Data->label[i].sublabelFlag & + ~HKDF_SUB_LABELS_ALL) { + LAC_INVALID_PARAM_LOG1( + "CpaCyKeyGenHKDFOpData.label[%d]." + "subLabelFlag", + i); + return CPA_STATUS_INVALID_PARAM; + } + + /* Calculate the appended subLabel output + * lengths and + * check that the output buffer that the user + * has + * supplied is the correct length. + */ + uOutputLen += cipherSuiteHKDFHashSizes + [cipherSuite][LAC_KEY_HKDF_DIGESTS]; + /* Get mask of subLabel */ + subl_mask = HKDF_Data->label[i].sublabelFlag; + + for (subl_number = 1; + subl_number <= LAC_KEY_HKDF_SUBLABELS_NUM; + subl_number++) { + /* Add the used subLabel key lengths */ + if (subl_mask & 1) { + uOutputLen += + cipherSuiteHKDFHashSizes + [cipherSuite] + [subl_number]; + } + subl_mask >>= 1; + } + } + } break; + default: + break; + } + } else { + LAC_INVALID_PARAM_LOG("TLS/SSL operation"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Maximum secret length for TLS/SSL Key Gen request */ + if (uSecretLen > maxSecretLen) { + LAC_INVALID_PARAM_LOG("HKFD.secretLen/secret.dataLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Check for enough space in the flat buffer */ + if (uOutputLen > pGeneratedKeyBuffer->dataLenInBytes) { + LAC_INVALID_PARAM_LOG("pGeneratedKeyBuffer->dataLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + return CPA_STATUS_SUCCESS; +} + +/** + * + */ +/** + * @ingroup LacSymKey + * Common Keygen Code for TLS v1.0/1.1, v1.2 and SSL3. + * @description + * Check user parameters and perform the required operation. + * + * @param[in] instanceHandle_in Instance handle. + * @param[in] pKeyGenCb Pointer to callback function to be + * invoked when the operation is complete. + * If this is set to a NULL value the + * function will operate synchronously. + * @param[in] pCallbackTag Opaque User Data for this specific + * call. Will be returned unchanged in the + * callback. + * @param[in] pKeyGenOpData Pointer to a structure containing all + * the data needed to perform the key + * generation operation. + * @param[in] hashAlgorithm Specifies the hash algorithm to use. + * According to RFC5246, this should be + * "SHA-256 or a stronger standard hash + * function." + * @param[out] pGeneratedKeyBuffer User output buffer. + * @param[in] cmdId Keygen operation to perform. + */ +static CpaStatus +LacSymKey_KeyGenSslTls(const CpaInstanceHandle instanceHandle_in, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const void *pKeyGenOpData, + Cpa8U hashAlgorithm, + CpaFlatBuffer *pGeneratedKeyBuffer, + icp_qat_fw_la_cmd_id_t cmdId) +{ + CpaStatus status = CPA_STATUS_FAIL; + CpaInstanceHandle instanceHandle = LacKey_GetHandle(instanceHandle_in); + CpaCyCapabilitiesInfo cyCapInfo; + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + + SAL_RUNNING_CHECK(instanceHandle); + SalCtrl_CyQueryCapabilities(instanceHandle, &cyCapInfo); + + if (IS_HKDF_UNSUPPORTED(cmdId, cyCapInfo.hkdfSupported)) { + LAC_LOG_ERROR("The device does not support HKDF"); + return CPA_STATUS_UNSUPPORTED; + } + + status = LacSymKey_CheckParamSslTls(pKeyGenOpData, + hashAlgorithm, + pGeneratedKeyBuffer, + cmdId); + if (CPA_STATUS_SUCCESS != status) + return status; + return LacSymKey_KeyGenSslTls_GenCommon(instanceHandle, + pKeyGenCb, + pCallbackTag, + cmdId, + LAC_CONST_PTR_CAST( + pKeyGenOpData), + hashAlgorithm, + pGeneratedKeyBuffer); +} + +/** + * @ingroup LacSymKey + * SSL Key Generation Function. + * @description + * This function is used for SSL key generation. It implements the key + * generation function defined in section 6.2.2 of the SSL 3.0 + * specification as described in + * http://www.mozilla.org/projects/security/pki/nss/ssl/draft302.txt. + * + * The input seed is taken as a flat buffer and the generated key is + * returned to caller in a flat destination data buffer. + * + * @param[in] instanceHandle_in Instance handle. + * @param[in] pKeyGenCb Pointer to callback function to be + * invoked when the operation is complete. + * If this is set to a NULL value the + * function will operate synchronously. + * @param[in] pCallbackTag Opaque User Data for this specific + * call. Will be returned unchanged in the + * callback. + * @param[in] pKeyGenSslOpData Pointer to a structure containing all + * the data needed to perform the SSL key + * generation operation. The client code + * allocates the memory for this + * structure. This component takes + * ownership of the memory until it is + * returned in the callback. + * @param[out] pGeneratedKeyBuffer Caller MUST allocate a sufficient + * buffer to hold the key generation + * output. The data pointer SHOULD be + * aligned on an 8-byte boundary. The + * length field passed in represents the + * size of the buffer in bytes. The value + * that is returned is the size of the + * result key in bytes. + * On invocation the callback function + * will contain this parameter in the + * pOut parameter. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + */ +CpaStatus +cpaCyKeyGenSsl(const CpaInstanceHandle instanceHandle_in, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const CpaCyKeyGenSslOpData *pKeyGenSslOpData, + CpaFlatBuffer *pGeneratedKeyBuffer) +{ + CpaInstanceHandle instanceHandle = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + return LacSymKey_KeyGenSslTls(instanceHandle, + pKeyGenCb, + pCallbackTag, + LAC_CONST_PTR_CAST(pKeyGenSslOpData), + CPA_CY_SYM_HASH_NONE, /* Hash algorithm */ + pGeneratedKeyBuffer, + ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE); +} + +/** + * @ingroup LacSymKey + * TLS Key Generation Function. + * @description + * This function is used for TLS key generation. It implements the + * TLS PRF (Pseudo Random Function) as defined by RFC2246 (TLS v1.0) + * and RFC4346 (TLS v1.1). + * + * The input seed is taken as a flat buffer and the generated key is + * returned to caller in a flat destination data buffer. + * + * @param[in] instanceHandle_in Instance handle. + * @param[in] pKeyGenCb Pointer to callback function to be + * invoked when the operation is complete. + * If this is set to a NULL value the + * function will operate synchronously. + * @param[in] pCallbackTag Opaque User Data for this specific + * call. Will be returned unchanged in the + * callback. + * @param[in] pKeyGenTlsOpData Pointer to a structure containing all + * the data needed to perform the TLS key + * generation operation. The client code + * allocates the memory for this + * structure. This component takes + * ownership of the memory until it is + * returned in the callback. + * @param[out] pGeneratedKeyBuffer Caller MUST allocate a sufficient + * buffer to hold the key generation + * output. The data pointer SHOULD be + * aligned on an 8-byte boundary. The + * length field passed in represents the + * size of the buffer in bytes. The value + * that is returned is the size of the + * result key in bytes. + * On invocation the callback function + * will contain this parameter in the + * pOut parameter. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + * + */ +CpaStatus +cpaCyKeyGenTls(const CpaInstanceHandle instanceHandle_in, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const CpaCyKeyGenTlsOpData *pKeyGenTlsOpData, + CpaFlatBuffer *pGeneratedKeyBuffer) +{ + CpaInstanceHandle instanceHandle = NULL; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + return LacSymKey_KeyGenSslTls(instanceHandle, + pKeyGenCb, + pCallbackTag, + LAC_CONST_PTR_CAST(pKeyGenTlsOpData), + CPA_CY_SYM_HASH_NONE, /* Hash algorithm */ + pGeneratedKeyBuffer, + ICP_QAT_FW_LA_CMD_TLS_V1_1_KEY_DERIVE); +} + +/** + * @ingroup LacSymKey + * @description + * This function is used for TLS key generation. It implements the + * TLS PRF (Pseudo Random Function) as defined by RFC5246 (TLS v1.2). + * + * The input seed is taken as a flat buffer and the generated key is + * returned to caller in a flat destination data buffer. + * + * @param[in] instanceHandle_in Instance handle. + * @param[in] pKeyGenCb Pointer to callback function to be + * invoked when the operation is complete. + * If this is set to a NULL value the + * function will operate synchronously. + * @param[in] pCallbackTag Opaque User Data for this specific + * call. Will be returned unchanged in the + * callback. + * @param[in] pKeyGenTlsOpData Pointer to a structure containing all + * the data needed to perform the TLS key + * generation operation. The client code + * allocates the memory for this + * structure. This component takes + * ownership of the memory until it is + * returned in the callback. + * @param[in] hashAlgorithm Specifies the hash algorithm to use. + * According to RFC5246, this should be + * "SHA-256 or a stronger standard hash + * function." + * @param[out] pGeneratedKeyBuffer Caller MUST allocate a sufficient + * buffer to hold the key generation + * output. The data pointer SHOULD be + * aligned on an 8-byte boundary. The + * length field passed in represents the + * size of the buffer in bytes. The value + * that is returned is the size of the + * result key in bytes. + * On invocation the callback function + * will contain this parameter in the + * pOut parameter. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + */ +CpaStatus +cpaCyKeyGenTls2(const CpaInstanceHandle instanceHandle_in, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const CpaCyKeyGenTlsOpData *pKeyGenTlsOpData, + CpaCySymHashAlgorithm hashAlgorithm, + CpaFlatBuffer *pGeneratedKeyBuffer) +{ + CpaInstanceHandle instanceHandle = NULL; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + return LacSymKey_KeyGenSslTls(instanceHandle, + pKeyGenCb, + pCallbackTag, + LAC_CONST_PTR_CAST(pKeyGenTlsOpData), + hashAlgorithm, + pGeneratedKeyBuffer, + ICP_QAT_FW_LA_CMD_TLS_V1_2_KEY_DERIVE); +} + +/** + * @ingroup LacSymKey + * @description + * This function is used for TLS1.3 HKDF key generation. It implements + * the "extract-then-expand" paradigm as defined by RFC 5869. + * + * The input seed/secret/info is taken as a flat buffer and the generated + * key(s)/labels are returned to caller in a flat data buffer. + * + * @param[in] instanceHandle_in Instance handle. + * @param[in] pKeyGenCb Pointer to callback function to be + * invoked when the operation is complete. + * If this is set to a NULL value the + * function will operate synchronously. + * @param[in] pCallbackTag Opaque User Data for this specific + * call. Will be returned unchanged in the + * callback. + * @param[in] pKeyGenTlsOpData Pointer to a structure containing + * the data needed to perform the HKDF key + * generation operation. + * The client code allocates the memory + * for this structure as contiguous + * pinned memory. + * This component takes ownership of the + * memory until it is returned in the + * callback. + * @param[in] hashAlgorithm Specifies the hash algorithm to use. + * According to RFC5246, this should be + * "SHA-256 or a stronger standard hash + * function." + * @param[out] pGeneratedKeyBuffer Caller MUST allocate a sufficient + * buffer to hold the key generation + * output. The data pointer SHOULD be + * aligned on an 8-byte boundary. The + * length field passed in represents the + * size of the buffer in bytes. The value + * that is returned is the size of the + * result key in bytes. + * On invocation the callback function + * will contain this parameter in the + * pOut parameter. + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_FAIL Function failed. + * @retval CPA_STATUS_RETRY Resubmit the request. + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in. + * @retval CPA_STATUS_RESOURCE Error related to system resources. + */ +CpaStatus +cpaCyKeyGenTls3(const CpaInstanceHandle instanceHandle_in, + const CpaCyGenFlatBufCbFunc pKeyGenCb, + void *pCallbackTag, + const CpaCyKeyGenHKDFOpData *pKeyGenTlsOpData, + CpaCyKeyHKDFCipherSuite cipherSuite, + CpaFlatBuffer *pGeneratedKeyBuffer) +{ + + LAC_CHECK_NULL_PARAM(pKeyGenTlsOpData); + switch (pKeyGenTlsOpData->hkdfKeyOp) { + case CPA_CY_HKDF_KEY_EXTRACT: /* Fall through */ + case CPA_CY_HKDF_KEY_EXPAND: + case CPA_CY_HKDF_KEY_EXTRACT_EXPAND: + case CPA_CY_HKDF_KEY_EXPAND_LABEL: + case CPA_CY_HKDF_KEY_EXTRACT_EXPAND_LABEL: + break; + default: + LAC_INVALID_PARAM_LOG("HKDF operation not supported"); + return CPA_STATUS_INVALID_PARAM; + } + + + return LacSymKey_KeyGenSslTls(instanceHandle_in, + pKeyGenCb, + pCallbackTag, + LAC_CONST_PTR_CAST(pKeyGenTlsOpData), + cipherSuite, + pGeneratedKeyBuffer, + (icp_qat_fw_la_cmd_id_t) + pKeyGenTlsOpData->hkdfKeyOp); +} + +/* + * LacSymKey_Init + */ +CpaStatus +LacSymKey_Init(CpaInstanceHandle instanceHandle_in) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + CpaInstanceHandle instanceHandle = LacKey_GetHandle(instanceHandle_in); + sal_crypto_service_t *pService = NULL; + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + + pService = (sal_crypto_service_t *)instanceHandle; + + pService->pLacKeyStats = + LAC_OS_MALLOC(LAC_KEY_NUM_STATS * sizeof(QatUtilsAtomic)); + + if (NULL != pService->pLacKeyStats) { + LAC_OS_BZERO((void *)pService->pLacKeyStats, + LAC_KEY_NUM_STATS * sizeof(QatUtilsAtomic)); + + status = LAC_OS_CAMALLOC(&pService->pSslLabel, + ICP_QAT_FW_LA_SSL_LABEL_LEN_MAX, + LAC_8BYTE_ALIGNMENT, + pService->nodeAffinity); + } else { + status = CPA_STATUS_RESOURCE; + } + + if (CPA_STATUS_SUCCESS == status) { + Cpa32U i = 0; + Cpa32U offset = 0; + + /* Initialise SSL label ABBCCC..... */ + for (i = 0; i < ICP_QAT_FW_LA_SSL_ITERATES_LEN_MAX; i++) { + memset(pService->pSslLabel + offset, 'A' + i, i + 1); + offset += (i + 1); + } + + /* Allocate memory for TLS labels */ + status = LAC_OS_CAMALLOC(&pService->pTlsLabel, + sizeof(lac_sym_key_tls_labels_t), + LAC_8BYTE_ALIGNMENT, + pService->nodeAffinity); + } + + if (CPA_STATUS_SUCCESS == status) { + /* Allocate memory for HKDF sub_labels */ + status = + LAC_OS_CAMALLOC(&pService->pTlsHKDFSubLabel, + sizeof(lac_sym_key_tls_hkdf_sub_labels_t), + LAC_8BYTE_ALIGNMENT, + pService->nodeAffinity); + } + + if (CPA_STATUS_SUCCESS == status) { + LAC_OS_BZERO(pService->pTlsLabel, + sizeof(lac_sym_key_tls_labels_t)); + + /* Copy the TLS v1.2 labels into the dynamically allocated + * structure */ + memcpy(pService->pTlsLabel->masterSecret, + LAC_SYM_KEY_TLS_MASTER_SECRET_LABEL, + sizeof(LAC_SYM_KEY_TLS_MASTER_SECRET_LABEL) - 1); + + memcpy(pService->pTlsLabel->keyMaterial, + LAC_SYM_KEY_TLS_KEY_MATERIAL_LABEL, + sizeof(LAC_SYM_KEY_TLS_KEY_MATERIAL_LABEL) - 1); + + memcpy(pService->pTlsLabel->clientFinished, + LAC_SYM_KEY_TLS_CLIENT_FIN_LABEL, + sizeof(LAC_SYM_KEY_TLS_CLIENT_FIN_LABEL) - 1); + + memcpy(pService->pTlsLabel->serverFinished, + LAC_SYM_KEY_TLS_SERVER_FIN_LABEL, + sizeof(LAC_SYM_KEY_TLS_SERVER_FIN_LABEL) - 1); + + LAC_OS_BZERO(pService->pTlsHKDFSubLabel, + sizeof(lac_sym_key_tls_hkdf_sub_labels_t)); + + /* Copy the TLS v1.3 subLabels into the dynamically allocated + * struct */ + /* KEY SHA-256 */ + memcpy(&pService->pTlsHKDFSubLabel->keySublabel256, + &key256, + HKDF_SUB_LABEL_KEY_LENGTH); + pService->pTlsHKDFSubLabel->keySublabel256.labelLen = + HKDF_SUB_LABEL_KEY_LENGTH; + pService->pTlsHKDFSubLabel->keySublabel256.sublabelFlag = 1 + << QAT_FW_HKDF_INNER_SUBLABEL_16_BYTE_OKM_BITPOS; + /* KEY SHA-384 */ + memcpy(&pService->pTlsHKDFSubLabel->keySublabel384, + &key384, + HKDF_SUB_LABEL_KEY_LENGTH); + pService->pTlsHKDFSubLabel->keySublabel384.labelLen = + HKDF_SUB_LABEL_KEY_LENGTH; + pService->pTlsHKDFSubLabel->keySublabel384.sublabelFlag = 1 + << QAT_FW_HKDF_INNER_SUBLABEL_32_BYTE_OKM_BITPOS; + /* KEY CHACHAPOLY */ + memcpy(&pService->pTlsHKDFSubLabel->keySublabelChaChaPoly, + &keyChaChaPoly, + HKDF_SUB_LABEL_KEY_LENGTH); + pService->pTlsHKDFSubLabel->keySublabelChaChaPoly.labelLen = + HKDF_SUB_LABEL_KEY_LENGTH; + pService->pTlsHKDFSubLabel->keySublabelChaChaPoly.sublabelFlag = + 1 << QAT_FW_HKDF_INNER_SUBLABEL_32_BYTE_OKM_BITPOS; + /* IV SHA-256 */ + memcpy(&pService->pTlsHKDFSubLabel->ivSublabel256, + &iv256, + HKDF_SUB_LABEL_IV_LENGTH); + pService->pTlsHKDFSubLabel->ivSublabel256.labelLen = + HKDF_SUB_LABEL_IV_LENGTH; + pService->pTlsHKDFSubLabel->ivSublabel256.sublabelFlag = 1 + << QAT_FW_HKDF_INNER_SUBLABEL_12_BYTE_OKM_BITPOS; + /* IV SHA-384 */ + memcpy(&pService->pTlsHKDFSubLabel->ivSublabel384, + &iv384, + HKDF_SUB_LABEL_IV_LENGTH); + pService->pTlsHKDFSubLabel->ivSublabel384.labelLen = + HKDF_SUB_LABEL_IV_LENGTH; + pService->pTlsHKDFSubLabel->ivSublabel384.sublabelFlag = 1 + << QAT_FW_HKDF_INNER_SUBLABEL_12_BYTE_OKM_BITPOS; + /* IV CHACHAPOLY */ + memcpy(&pService->pTlsHKDFSubLabel->ivSublabelChaChaPoly, + &iv256, + HKDF_SUB_LABEL_IV_LENGTH); + pService->pTlsHKDFSubLabel->ivSublabelChaChaPoly.labelLen = + HKDF_SUB_LABEL_IV_LENGTH; + pService->pTlsHKDFSubLabel->ivSublabelChaChaPoly.sublabelFlag = + 1 << QAT_FW_HKDF_INNER_SUBLABEL_12_BYTE_OKM_BITPOS; + /* RESUMPTION SHA-256 */ + memcpy(&pService->pTlsHKDFSubLabel->resumptionSublabel256, + &resumption256, + HKDF_SUB_LABEL_RESUMPTION_LENGTH); + pService->pTlsHKDFSubLabel->resumptionSublabel256.labelLen = + HKDF_SUB_LABEL_RESUMPTION_LENGTH; + /* RESUMPTION SHA-384 */ + memcpy(&pService->pTlsHKDFSubLabel->resumptionSublabel384, + &resumption384, + HKDF_SUB_LABEL_RESUMPTION_LENGTH); + pService->pTlsHKDFSubLabel->resumptionSublabel384.labelLen = + HKDF_SUB_LABEL_RESUMPTION_LENGTH; + /* RESUMPTION CHACHAPOLY */ + memcpy( + &pService->pTlsHKDFSubLabel->resumptionSublabelChaChaPoly, + &resumption256, + HKDF_SUB_LABEL_RESUMPTION_LENGTH); + pService->pTlsHKDFSubLabel->resumptionSublabelChaChaPoly + .labelLen = HKDF_SUB_LABEL_RESUMPTION_LENGTH; + /* FINISHED SHA-256 */ + memcpy(&pService->pTlsHKDFSubLabel->finishedSublabel256, + &finished256, + HKDF_SUB_LABEL_FINISHED_LENGTH); + pService->pTlsHKDFSubLabel->finishedSublabel256.labelLen = + HKDF_SUB_LABEL_FINISHED_LENGTH; + /* FINISHED SHA-384 */ + memcpy(&pService->pTlsHKDFSubLabel->finishedSublabel384, + &finished384, + HKDF_SUB_LABEL_FINISHED_LENGTH); + pService->pTlsHKDFSubLabel->finishedSublabel384.labelLen = + HKDF_SUB_LABEL_FINISHED_LENGTH; + /* FINISHED CHACHAPOLY */ + memcpy(&pService->pTlsHKDFSubLabel->finishedSublabelChaChaPoly, + &finished256, + HKDF_SUB_LABEL_FINISHED_LENGTH); + pService->pTlsHKDFSubLabel->finishedSublabelChaChaPoly + .labelLen = HKDF_SUB_LABEL_FINISHED_LENGTH; + + /* Set physical address of sublabels */ + pService->pTlsHKDFSubLabel->sublabelPhysAddr256 = + LAC_OS_VIRT_TO_PHYS_INTERNAL( + &pService->pTlsHKDFSubLabel->keySublabel256); + pService->pTlsHKDFSubLabel->sublabelPhysAddr384 = + LAC_OS_VIRT_TO_PHYS_INTERNAL( + &pService->pTlsHKDFSubLabel->keySublabel384); + pService->pTlsHKDFSubLabel->sublabelPhysAddrChaChaPoly = + LAC_OS_VIRT_TO_PHYS_INTERNAL( + &pService->pTlsHKDFSubLabel->keySublabelChaChaPoly); + + /* Register request handlers */ + LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE, + LacSymKey_SslTlsHandleResponse); + + LacSymQat_RespHandlerRegister( + ICP_QAT_FW_LA_CMD_TLS_V1_1_KEY_DERIVE, + LacSymKey_SslTlsHandleResponse); + + LacSymQat_RespHandlerRegister( + ICP_QAT_FW_LA_CMD_TLS_V1_2_KEY_DERIVE, + LacSymKey_SslTlsHandleResponse); + + LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_HKDF_EXTRACT, + LacSymKey_SslTlsHandleResponse); + + LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_HKDF_EXPAND, + LacSymKey_SslTlsHandleResponse); + + LacSymQat_RespHandlerRegister( + ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND, + LacSymKey_SslTlsHandleResponse); + + LacSymQat_RespHandlerRegister( + ICP_QAT_FW_LA_CMD_HKDF_EXPAND_LABEL, + LacSymKey_SslTlsHandleResponse); + + LacSymQat_RespHandlerRegister( + ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL, + LacSymKey_SslTlsHandleResponse); + + LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_MGF1, + LacSymKey_MgfHandleResponse); + } + + if (CPA_STATUS_SUCCESS != status) { + LAC_OS_FREE(pService->pLacKeyStats); + LAC_OS_CAFREE(pService->pSslLabel); + LAC_OS_CAFREE(pService->pTlsLabel); + LAC_OS_CAFREE(pService->pTlsHKDFSubLabel); + } + + return status; +} + +/* + * LacSymKey_Shutdown + */ +CpaStatus +LacSymKey_Shutdown(CpaInstanceHandle instanceHandle_in) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + CpaInstanceHandle instanceHandle = LacKey_GetHandle(instanceHandle_in); + sal_crypto_service_t *pService = NULL; + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + + pService = (sal_crypto_service_t *)instanceHandle; + + if (NULL != pService->pLacKeyStats) { + LAC_OS_FREE(pService->pLacKeyStats); + } + + LAC_OS_CAFREE(pService->pSslLabel); + LAC_OS_CAFREE(pService->pTlsLabel); + LAC_OS_CAFREE(pService->pTlsHKDFSubLabel); + + return status; +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_alg_chain.c b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_alg_chain.c new file mode 100644 index 000000000000..c2d30c77eeab --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_alg_chain.c @@ -0,0 +1,1860 @@ +/*************************************************************************** + * + * <COPYRIGHT_TAG> + * + ***************************************************************************/ + +/** + *************************************************************************** + * @file lac_sym_alg_chain.c Algorithm Chaining Perform + * + * @ingroup LacAlgChain + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ + +#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 private header files +******************************************************************************* +*/ + +#include "lac_mem.h" +#include "lac_log.h" +#include "lac_sym.h" +#include "lac_list.h" +#include "icp_qat_fw_la.h" +#include "lac_sal_types_crypto.h" +#include "lac_sal.h" +#include "lac_sal_ctrl.h" +#include "lac_sym_alg_chain.h" +#include "lac_sym_cipher.h" +#include "lac_sym_cipher_defs.h" +#include "lac_sym_hash.h" +#include "lac_sym_hash_defs.h" +#include "lac_sym_qat_cipher.h" +#include "lac_sym_qat_hash.h" +#include "lac_sym_stats.h" +#include "lac_sym_queue.h" +#include "lac_sym_cb.h" +#include "sal_string_parse.h" +#include "lac_sym_auth_enc.h" +#include "lac_sym_qat.h" + +/** + * @ingroup LacAlgChain + * Function which checks for support of partial packets for symmetric + * crypto operations + * + * @param[in] pService Pointer to service descriptor + * @param[in/out] pSessionDesc Pointer to session descriptor + * + */ +static void +LacSymCheck_IsPartialSupported(Cpa32U capabilitiesMask, + lac_session_desc_t *pSessionDesc) +{ + CpaBoolean isHashPartialSupported = CPA_FALSE; + CpaBoolean isCipherPartialSupported = CPA_FALSE; + CpaBoolean isPartialSupported = CPA_FALSE; + + switch (pSessionDesc->cipherAlgorithm) { + /* Following ciphers don't support partial */ + 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_CHACHA: + case CPA_CY_SYM_CIPHER_ZUC_EEA3: + break; + /* All others support partial */ + default: + isCipherPartialSupported = CPA_TRUE; + } + switch (pSessionDesc->hashAlgorithm) { + /* Following hash don't support partial */ + case CPA_CY_SYM_HASH_KASUMI_F9: + case CPA_CY_SYM_HASH_SNOW3G_UIA2: + case CPA_CY_SYM_HASH_POLY: + case CPA_CY_SYM_HASH_ZUC_EIA3: + case CPA_CY_SYM_HASH_SHAKE_128: + case CPA_CY_SYM_HASH_SHAKE_256: + break; + /* Following hash may support partial based on device capabilities */ + case CPA_CY_SYM_HASH_SHA3_256: + if (ICP_ACCEL_CAPABILITIES_SHA3_EXT & capabilitiesMask) { + isHashPartialSupported = CPA_TRUE; + } + break; + /* All others support partial */ + default: + isHashPartialSupported = CPA_TRUE; + } + switch (pSessionDesc->symOperation) { + case CPA_CY_SYM_OP_CIPHER: + isPartialSupported = isCipherPartialSupported; + break; + case CPA_CY_SYM_OP_HASH: + isPartialSupported = isHashPartialSupported; + break; + case CPA_CY_SYM_OP_ALGORITHM_CHAINING: + if (isCipherPartialSupported && isHashPartialSupported) { + isPartialSupported = CPA_TRUE; + } + break; + case CPA_CY_SYM_OP_NONE: + break; + } + pSessionDesc->isPartialSupported = isPartialSupported; +} + +/** + * @ingroup LacAlgChain + * This callback function will be invoked whenever a hash precompute + * operation completes. It will dequeue and send any QAT requests + * which were queued up while the precompute was in progress. + * + * @param[in] callbackTag Opaque value provided by user. This will + * be a pointer to the session descriptor. + * + * @retval + * None + * + */ +static void +LacSymAlgChain_HashPrecomputeDoneCb(void *callbackTag) +{ + LacSymCb_PendingReqsDequeue((lac_session_desc_t *)callbackTag); +} + +/** + * @ingroup LacAlgChain + * Walk the buffer list and find the address for the given offset within + * a buffer. + * + * @param[in] pBufferList Buffer List + * @param[in] packetOffset Offset in the buffer list for which address + * is to be found. + * @param[out] ppDataPtr This is where the sought pointer will be put + * @param[out] pSpaceLeft Pointer to a variable in which information about + * available space from the given offset to the end + * of the flat buffer it is located in will be returned + * + * @retval CPA_STATUS_SUCCESS Address with a given offset is found in the list + * @retval CPA_STATUS_FAIL Address with a given offset not found in the list. + * + */ +static CpaStatus +LacSymAlgChain_PtrFromOffsetGet(const CpaBufferList *pBufferList, + const Cpa32U packetOffset, + Cpa8U **ppDataPtr) +{ + Cpa32U currentOffset = 0; + Cpa32U i = 0; + + for (i = 0; i < pBufferList->numBuffers; i++) { + Cpa8U *pCurrData = pBufferList->pBuffers[i].pData; + Cpa32U currDataSize = pBufferList->pBuffers[i].dataLenInBytes; + + /* If the offset is within the address space of the current + * buffer */ + if ((packetOffset >= currentOffset) && + (packetOffset < (currentOffset + currDataSize))) { + /* increment by offset of the address in the current + * buffer */ + *ppDataPtr = pCurrData + (packetOffset - currentOffset); + return CPA_STATUS_SUCCESS; + } + + /* Increment by the size of the buffer */ + currentOffset += currDataSize; + } + + return CPA_STATUS_FAIL; +} + +static void +LacAlgChain_CipherCDBuild(const CpaCySymCipherSetupData *pCipherData, + lac_session_desc_t *pSessionDesc, + icp_qat_fw_slice_t nextSlice, + Cpa8U cipherOffsetInConstantsTable, + icp_qat_fw_comn_flags *pCmnRequestFlags, + icp_qat_fw_serv_specif_flags *pLaCmdFlags, + Cpa8U *pHwBlockBaseInDRAM, + Cpa32U *pHwBlockOffsetInDRAM) +{ + Cpa8U *pCipherKeyField = NULL; + Cpa8U cipherOffsetInReqQW = 0; + Cpa32U sizeInBytes = 0; + + /* Construct the ContentDescriptor in DRAM */ + cipherOffsetInReqQW = (*pHwBlockOffsetInDRAM / LAC_QUAD_WORD_IN_BYTES); + ICP_QAT_FW_LA_CIPH_AUTH_CFG_OFFSET_FLAG_SET( + *pLaCmdFlags, ICP_QAT_FW_CIPH_AUTH_CFG_OFFSET_IN_CD_SETUP); + + /* construct cipherConfig in CD in DRAM */ + LacSymQat_CipherHwBlockPopulateCfgData(pSessionDesc, + pHwBlockBaseInDRAM + + *pHwBlockOffsetInDRAM, + &sizeInBytes); + + *pHwBlockOffsetInDRAM += sizeInBytes; + + /* Cipher key will be in CD in DRAM. + * The Request contains a ptr to the CD. + * This ptr will be copied into the request later once the CD is + * fully constructed, but the flag is set here. */ + pCipherKeyField = pHwBlockBaseInDRAM + *pHwBlockOffsetInDRAM; + ICP_QAT_FW_COMN_CD_FLD_TYPE_SET(*pCmnRequestFlags, + QAT_COMN_CD_FLD_TYPE_64BIT_ADR); + + LacSymQat_CipherHwBlockPopulateKeySetup( + pCipherData, + pCipherData->cipherKeyLenInBytes, + pCipherKeyField, + &sizeInBytes); + /* update offset */ + *pHwBlockOffsetInDRAM += sizeInBytes; + + LacSymQat_CipherCtrlBlockWrite(&(pSessionDesc->reqCacheFtr), + pSessionDesc->cipherAlgorithm, + pSessionDesc->cipherKeyLenInBytes, + nextSlice, + cipherOffsetInReqQW); + if (LAC_CIPHER_IS_GCM(pSessionDesc->cipherAlgorithm) || + LAC_CIPHER_IS_CHACHA(pSessionDesc->cipherAlgorithm)) { + LacSymQat_CipherCtrlBlockWrite( + &(pSessionDesc->reqSpcCacheFtr), + pSessionDesc->cipherAlgorithm, + pSessionDesc->cipherKeyLenInBytes, + ICP_QAT_FW_SLICE_DRAM_WR, + cipherOffsetInReqQW); + } +} + +static void +LacAlgChain_HashCDBuild( + const CpaCySymHashSetupData *pHashData, + CpaInstanceHandle instanceHandle, + lac_session_desc_t *pSessionDesc, + icp_qat_fw_slice_t nextSlice, + Cpa8U hashOffsetInConstantsTable, + icp_qat_fw_comn_flags *pCmnRequestFlags, + icp_qat_fw_serv_specif_flags *pLaCmdFlags, + lac_sym_qat_hash_precompute_info_t *pPrecomputeData, + lac_sym_qat_hash_precompute_info_t *pPrecomputeDataOptimisedCd, + Cpa8U *pHwBlockBaseInDRAM, + Cpa32U *pHwBlockOffsetInDRAM, + Cpa8U *pOptimisedHwBlockBaseInDRAM, + Cpa32U *pOptimisedHwBlockOffsetInDRAM) +{ + Cpa32U sizeInBytes = 0; + Cpa32U hwBlockOffsetInQuadWords = + *pHwBlockOffsetInDRAM / LAC_QUAD_WORD_IN_BYTES; + + /* build: + * - the hash part of the ContentDescriptor in DRAM */ + /* - the hash part of the CD control block in the Request template */ + LacSymQat_HashContentDescInit(&(pSessionDesc->reqCacheFtr), + instanceHandle, + pHashData, + pHwBlockBaseInDRAM, + hwBlockOffsetInQuadWords, + nextSlice, + pSessionDesc->qatHashMode, + CPA_FALSE, + CPA_FALSE, + pPrecomputeData, + &sizeInBytes); + + /* Using DRAM CD so update offset */ + *pHwBlockOffsetInDRAM += sizeInBytes; + + sizeInBytes = 0; +} + +CpaStatus +LacAlgChain_SessionAADUpdate(lac_session_desc_t *pSessionDesc, + Cpa32U newAADLength) +{ + icp_qat_la_bulk_req_ftr_t *req_ftr = &pSessionDesc->reqCacheFtr; + icp_qat_la_auth_req_params_t *req_params = &req_ftr->serv_specif_rqpars; + + if (!pSessionDesc) + return CPA_STATUS_FAIL; + + pSessionDesc->aadLenInBytes = newAADLength; + req_params->u2.aad_sz = + LAC_ALIGN_POW2_ROUNDUP(newAADLength, LAC_HASH_AES_GCM_BLOCK_SIZE); + + if (CPA_TRUE == pSessionDesc->isSinglePass) { + Cpa8U *pHwBlockBaseInDRAM = NULL; + Cpa32U hwBlockOffsetInDRAM = 0; + Cpa32U pSizeInBytes = 0; + CpaCySymCipherAlgorithm cipher = pSessionDesc->cipherAlgorithm; + + pHwBlockBaseInDRAM = + (Cpa8U *)pSessionDesc->contentDescInfo.pData; + if (pSessionDesc->cipherDirection == + CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT) { + if (LAC_CIPHER_IS_GCM(cipher)) { + hwBlockOffsetInDRAM = LAC_QUADWORDS_TO_BYTES( + LAC_SYM_QAT_CIPHER_OFFSET_IN_DRAM_GCM_SPC); + } else { + hwBlockOffsetInDRAM = LAC_QUADWORDS_TO_BYTES( + LAC_SYM_QAT_CIPHER_OFFSET_IN_DRAM_CHACHA_SPC); + } + } + LacSymQat_CipherHwBlockPopulateCfgData(pSessionDesc, + pHwBlockBaseInDRAM + + hwBlockOffsetInDRAM, + &pSizeInBytes); + } + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +LacAlgChain_SessionCipherKeyUpdate(lac_session_desc_t *pSessionDesc, + Cpa8U *pCipherKey) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + if (pSessionDesc == NULL || pCipherKey == NULL) + return CPA_STATUS_FAIL; + + if (LAC_CIPHER_IS_ARC4(pSessionDesc->cipherAlgorithm)) { + LacSymQat_CipherArc4StateInit( + pCipherKey, + pSessionDesc->cipherKeyLenInBytes, + pSessionDesc->cipherARC4InitialState); + } else { + CpaCySymCipherSetupData cipherSetupData = { 0 }; + Cpa32U sizeInBytes; + Cpa8U *pCipherKeyField; + sal_qat_content_desc_info_t *pCdInfo = + &(pSessionDesc->contentDescInfo); + + cipherSetupData.cipherAlgorithm = pSessionDesc->cipherAlgorithm; + cipherSetupData.cipherKeyLenInBytes = + pSessionDesc->cipherKeyLenInBytes; + cipherSetupData.pCipherKey = pCipherKey; + + switch (pSessionDesc->symOperation) { + case CPA_CY_SYM_OP_CIPHER: { + pCipherKeyField = (Cpa8U *)pCdInfo->pData + + sizeof(icp_qat_hw_cipher_config_t); + + LacSymQat_CipherHwBlockPopulateKeySetup( + &(cipherSetupData), + cipherSetupData.cipherKeyLenInBytes, + pCipherKeyField, + &sizeInBytes); + + if (pSessionDesc->useSymConstantsTable) { + pCipherKeyField = (Cpa8U *)&( + pSessionDesc->shramReqCacheHdr.cd_pars.s1 + .serv_specif_fields); + + LacSymQat_CipherHwBlockPopulateKeySetup( + &(cipherSetupData), + cipherSetupData.cipherKeyLenInBytes, + pCipherKeyField, + &sizeInBytes); + } + } break; + + case CPA_CY_SYM_OP_ALGORITHM_CHAINING: { + icp_qat_fw_cipher_auth_cd_ctrl_hdr_t *cd_ctrl = + (icp_qat_fw_cipher_auth_cd_ctrl_hdr_t + *)&pSessionDesc->reqCacheFtr.cd_ctrl; + + pCipherKeyField = (Cpa8U *)pCdInfo->pData + + cd_ctrl->cipher_cfg_offset * + LAC_QUAD_WORD_IN_BYTES + + sizeof(icp_qat_hw_cipher_config_t); + + LacSymQat_CipherHwBlockPopulateKeySetup( + &(cipherSetupData), + cipherSetupData.cipherKeyLenInBytes, + pCipherKeyField, + &sizeInBytes); + } break; + + default: + LAC_LOG_ERROR("Invalid sym operation\n"); + status = CPA_STATUS_INVALID_PARAM; + break; + } + } + return status; +} + +CpaStatus +LacAlgChain_SessionAuthKeyUpdate(lac_session_desc_t *pSessionDesc, + Cpa8U *pAuthKey) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + Cpa8U *pHwBlockBaseInDRAM = NULL; + Cpa8U *pOutHashSetup = NULL; + Cpa8U *pInnerState1 = NULL; + Cpa8U *pInnerState2 = NULL; + CpaCySymSessionSetupData sessionSetup = { 0 }; + + if (pSessionDesc == NULL || pAuthKey == NULL) + return CPA_STATUS_FAIL; + + icp_qat_fw_cipher_auth_cd_ctrl_hdr_t *cd_ctrl = + (icp_qat_fw_cipher_auth_cd_ctrl_hdr_t *)&pSessionDesc->reqCacheFtr + .cd_ctrl; + + pHwBlockBaseInDRAM = (Cpa8U *)pSessionDesc->contentDescInfo.pData; + + sessionSetup.hashSetupData.hashAlgorithm = pSessionDesc->hashAlgorithm; + sessionSetup.hashSetupData.hashMode = pSessionDesc->hashMode; + sessionSetup.hashSetupData.authModeSetupData.authKey = pAuthKey; + sessionSetup.hashSetupData.authModeSetupData.authKeyLenInBytes = + pSessionDesc->authKeyLenInBytes; + sessionSetup.hashSetupData.authModeSetupData.aadLenInBytes = + pSessionDesc->aadLenInBytes; + sessionSetup.hashSetupData.digestResultLenInBytes = + pSessionDesc->hashResultSize; + + sessionSetup.cipherSetupData.cipherAlgorithm = + pSessionDesc->cipherAlgorithm; + sessionSetup.cipherSetupData.cipherKeyLenInBytes = + pSessionDesc->cipherKeyLenInBytes; + + /* Calculate hash states offsets */ + pInnerState1 = pHwBlockBaseInDRAM + + cd_ctrl->hash_cfg_offset * LAC_QUAD_WORD_IN_BYTES + + sizeof(icp_qat_hw_auth_setup_t); + + pInnerState2 = pInnerState1 + cd_ctrl->inner_state1_sz; + + pOutHashSetup = pInnerState2 + cd_ctrl->inner_state2_sz; + + /* Calculate offset of cipher key */ + if (pSessionDesc->laCmdId == ICP_QAT_FW_LA_CMD_CIPHER_HASH) { + sessionSetup.cipherSetupData.pCipherKey = + (Cpa8U *)pHwBlockBaseInDRAM + + sizeof(icp_qat_hw_cipher_config_t); + } else if (pSessionDesc->laCmdId == ICP_QAT_FW_LA_CMD_HASH_CIPHER) { + sessionSetup.cipherSetupData.pCipherKey = + pOutHashSetup + sizeof(icp_qat_hw_cipher_config_t); + } else if (CPA_TRUE == pSessionDesc->isSinglePass) { + CpaCySymCipherAlgorithm cipher = pSessionDesc->cipherAlgorithm; + Cpa32U hwBlockOffsetInDRAM = 0; + + if (pSessionDesc->cipherDirection == + CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT) { + sessionSetup.cipherSetupData.pCipherKey = + (Cpa8U *)pHwBlockBaseInDRAM + + sizeof(icp_qat_hw_cipher_config_t); + } else { + if (LAC_CIPHER_IS_GCM(cipher)) + hwBlockOffsetInDRAM = LAC_QUADWORDS_TO_BYTES( + LAC_SYM_QAT_CIPHER_OFFSET_IN_DRAM_GCM_SPC); + else + hwBlockOffsetInDRAM = LAC_QUADWORDS_TO_BYTES( + LAC_SYM_QAT_CIPHER_OFFSET_IN_DRAM_CHACHA_SPC); + sessionSetup.cipherSetupData.pCipherKey = + (Cpa8U *)pHwBlockBaseInDRAM + hwBlockOffsetInDRAM + + sizeof(icp_qat_hw_cipher_config_t); + } + } + + if (!sessionSetup.cipherSetupData.pCipherKey) + return CPA_STATUS_FAIL; + + if (CPA_CY_SYM_HASH_SHA3_256 == pSessionDesc->hashAlgorithm) { + if (CPA_FALSE == pSessionDesc->isAuthEncryptOp) { + lac_sym_qat_hash_state_buffer_info_t + *pHashStateBufferInfo = + &(pSessionDesc->hashStateBufferInfo); + + sal_crypto_service_t *pService = + (sal_crypto_service_t *)pSessionDesc->pInstance; + + status = LacHash_StatePrefixAadBufferInit( + &(pService->generic_service_info), + &(sessionSetup.hashSetupData), + &(pSessionDesc->reqCacheFtr), + pSessionDesc->qatHashMode, + pSessionDesc->hashStatePrefixBuffer, + pHashStateBufferInfo); + /* SHRAM Constants Table not used for Auth-Enc */ + } + } else if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == pSessionDesc->hashAlgorithm) { + Cpa8U *authKey = + (Cpa8U *)pOutHashSetup + sizeof(icp_qat_hw_cipher_config_t); + memcpy(authKey, pAuthKey, pSessionDesc->authKeyLenInBytes); + } else if (CPA_CY_SYM_HASH_ZUC_EIA3 == pSessionDesc->hashAlgorithm || + CPA_CY_SYM_HASH_AES_CBC_MAC == pSessionDesc->hashAlgorithm) { + memcpy(pInnerState2, pAuthKey, pSessionDesc->authKeyLenInBytes); + } else if (CPA_CY_SYM_HASH_AES_CMAC == pSessionDesc->hashAlgorithm || + CPA_CY_SYM_HASH_KASUMI_F9 == pSessionDesc->hashAlgorithm || + IS_HASH_MODE_1(pSessionDesc->qatHashMode)) { + if (CPA_CY_SYM_HASH_AES_CMAC == pSessionDesc->hashAlgorithm) { + memset(pInnerState2, 0, cd_ctrl->inner_state2_sz); + } + + /* Block messages until precompute is completed */ + pSessionDesc->nonBlockingOpsInProgress = CPA_FALSE; + + status = LacHash_PrecomputeDataCreate( + pSessionDesc->pInstance, + (CpaCySymSessionSetupData *)&(sessionSetup), + LacSymAlgChain_HashPrecomputeDoneCb, + pSessionDesc, + pSessionDesc->hashStatePrefixBuffer, + pInnerState1, + pInnerState2); + } + + return status; +} + +/** @ingroup LacAlgChain */ +CpaStatus +LacAlgChain_SessionInit(const CpaInstanceHandle instanceHandle, + const CpaCySymSessionSetupData *pSessionSetupData, + lac_session_desc_t *pSessionDesc) +{ + CpaStatus stat, status = CPA_STATUS_SUCCESS; + sal_qat_content_desc_info_t *pCdInfo = NULL; + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + Cpa32U capabilitiesMask = + pService->generic_service_info.capabilitiesMask; + Cpa8U *pHwBlockBaseInDRAM = NULL; + Cpa8U *pOptimisedHwBlockBaseInDRAM = NULL; + Cpa32U hwBlockOffsetInDRAM = 0; + Cpa32U optimisedHwBlockOffsetInDRAM = 0; + Cpa8U cipherOffsetInConstantsTable = 0; + Cpa8U hashOffsetInConstantsTable = 0; + icp_qat_fw_comn_req_t *pMsg = NULL; + const CpaCySymCipherSetupData *pCipherData; + const CpaCySymHashSetupData *pHashData; + Cpa16U proto = ICP_QAT_FW_LA_NO_PROTO; /* no CCM/GCM/Snow3G */ + CpaCySymAlgChainOrder chainOrder = 0; + lac_sym_qat_hash_precompute_info_t precomputeData = { 0 }; + lac_sym_qat_hash_precompute_info_t precomputeDataOptimisedCd = { 0 }; + + pCipherData = &(pSessionSetupData->cipherSetupData); + pHashData = &(pSessionSetupData->hashSetupData); + + /*------------------------------------------------------------------------- + * Populate session data + *-----------------------------------------------------------------------*/ + + /* Initialise Request Queue */ + stat = LAC_SPINLOCK_INIT(&pSessionDesc->requestQueueLock); + if (CPA_STATUS_SUCCESS != stat) { + LAC_LOG_ERROR("Spinlock init failed for sessionLock"); + return CPA_STATUS_RESOURCE; + } + + pSessionDesc->pRequestQueueHead = NULL; + pSessionDesc->pRequestQueueTail = NULL; + pSessionDesc->nonBlockingOpsInProgress = CPA_TRUE; + pSessionDesc->pInstance = instanceHandle; + pSessionDesc->digestIsAppended = pSessionSetupData->digestIsAppended; + pSessionDesc->digestVerify = pSessionSetupData->verifyDigest; + + /* Reset the pending callback counter */ + qatUtilsAtomicSet(0, &pSessionDesc->u.pendingCbCount); + qatUtilsAtomicSet(0, &pSessionDesc->u.pendingDpCbCount); + + /* Partial state must be set to full, to indicate that next packet + * expected on the session is a full packet or the start of a + * partial packet. */ + pSessionDesc->partialState = CPA_CY_SYM_PACKET_TYPE_FULL; + + pSessionDesc->symOperation = pSessionSetupData->symOperation; + switch (pSessionDesc->symOperation) { + case CPA_CY_SYM_OP_CIPHER: + pSessionDesc->laCmdId = ICP_QAT_FW_LA_CMD_CIPHER; + pSessionDesc->isCipher = TRUE; + pSessionDesc->isAuth = FALSE; + pSessionDesc->isAuthEncryptOp = CPA_FALSE; + + if (CPA_CY_SYM_CIPHER_SNOW3G_UEA2 == + pSessionSetupData->cipherSetupData.cipherAlgorithm) { + proto = ICP_QAT_FW_LA_SNOW_3G_PROTO; + } else if (CPA_CY_SYM_CIPHER_ZUC_EEA3 == + pSessionSetupData->cipherSetupData.cipherAlgorithm) { + proto = ICP_QAT_FW_LA_ZUC_3G_PROTO; + } + break; + case CPA_CY_SYM_OP_HASH: + pSessionDesc->laCmdId = ICP_QAT_FW_LA_CMD_AUTH; + pSessionDesc->isCipher = FALSE; + pSessionDesc->isAuth = TRUE; + pSessionDesc->isAuthEncryptOp = CPA_FALSE; + + if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == + pSessionSetupData->hashSetupData.hashAlgorithm) { + proto = ICP_QAT_FW_LA_SNOW_3G_PROTO; + } else if (CPA_CY_SYM_HASH_ZUC_EIA3 == + pSessionSetupData->hashSetupData.hashAlgorithm) { + proto = ICP_QAT_FW_LA_ZUC_3G_PROTO; + } + + break; + case CPA_CY_SYM_OP_ALGORITHM_CHAINING: + pSessionDesc->isCipher = TRUE; + pSessionDesc->isAuth = TRUE; + + { + /* set up some useful shortcuts */ + CpaCySymCipherAlgorithm cipherAlgorithm = + pSessionSetupData->cipherSetupData.cipherAlgorithm; + CpaCySymCipherDirection cipherDir = + pSessionSetupData->cipherSetupData.cipherDirection; + + if (LAC_CIPHER_IS_CCM(cipherAlgorithm)) { + pSessionDesc->isAuthEncryptOp = CPA_TRUE; + pSessionDesc->digestIsAppended = CPA_TRUE; + proto = ICP_QAT_FW_LA_CCM_PROTO; + + /* Derive chainOrder from direction for + * isAuthEncryptOp + * cases */ + /* For CCM & GCM modes: force digest verify flag + _TRUE + for decrypt and _FALSE for encrypt. For all + other cases + use user defined value */ + + if (CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT == + cipherDir) { + chainOrder = + CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER; + pSessionDesc->digestVerify = CPA_FALSE; + } else { + chainOrder = + CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH; + pSessionDesc->digestVerify = CPA_TRUE; + } + } else if (LAC_CIPHER_IS_GCM(cipherAlgorithm)) { + pSessionDesc->isAuthEncryptOp = CPA_TRUE; + proto = ICP_QAT_FW_LA_GCM_PROTO; + + /* Derive chainOrder from direction for + * isAuthEncryptOp + * cases */ + /* For CCM & GCM modes: force digest verify flag + _TRUE + for decrypt and _FALSE for encrypt. For all + other cases + use user defined value */ + + if (CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT == + cipherDir) { + chainOrder = + CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH; + pSessionDesc->digestVerify = CPA_FALSE; + } else { + chainOrder = + CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER; + pSessionDesc->digestVerify = CPA_TRUE; + } + } else if (LAC_CIPHER_IS_CHACHA(cipherAlgorithm)) { + pSessionDesc->isAuthEncryptOp = CPA_TRUE; + proto = ICP_QAT_FW_LA_SINGLE_PASS_PROTO; + + if (CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT == + cipherDir) { + chainOrder = + CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH; + } else { + chainOrder = + CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER; + } + } else { + pSessionDesc->isAuthEncryptOp = CPA_FALSE; + /* Use the chainOrder passed in */ + chainOrder = pSessionSetupData->algChainOrder; + if ((chainOrder != + CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER) && + (chainOrder != + CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH)) { + LAC_INVALID_PARAM_LOG("algChainOrder"); + return CPA_STATUS_INVALID_PARAM; + } + + if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == + pSessionSetupData->hashSetupData + .hashAlgorithm) { + proto = ICP_QAT_FW_LA_SNOW_3G_PROTO; + } else if (CPA_CY_SYM_HASH_ZUC_EIA3 == + pSessionSetupData->hashSetupData + .hashAlgorithm) { + proto = ICP_QAT_FW_LA_ZUC_3G_PROTO; + } + } + + if (CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH == + chainOrder) { + pSessionDesc->laCmdId = + ICP_QAT_FW_LA_CMD_CIPHER_HASH; + } else if ( + CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER == + chainOrder) { + pSessionDesc->laCmdId = + ICP_QAT_FW_LA_CMD_HASH_CIPHER; + } + } + break; + default: + break; + } + + if (pSessionDesc->isCipher) { +/* Populate cipher specific session data */ + + status = LacCipher_SessionSetupDataCheck(pCipherData); + + if (CPA_STATUS_SUCCESS == status) { + pSessionDesc->cipherAlgorithm = + pCipherData->cipherAlgorithm; + pSessionDesc->cipherKeyLenInBytes = + pCipherData->cipherKeyLenInBytes; + pSessionDesc->cipherDirection = + pCipherData->cipherDirection; + + /* ARC4 base key isn't added to the content descriptor, + * because + * we don't need to pass it directly to the QAT engine. + * Instead + * an initial cipher state & key matrix is derived from + * the + * base key and provided to the QAT through the state + * pointer + * in the request params. We'll store this initial state + * in + * the session descriptor. */ + + if (LAC_CIPHER_IS_ARC4(pSessionDesc->cipherAlgorithm)) { + LacSymQat_CipherArc4StateInit( + pCipherData->pCipherKey, + pSessionDesc->cipherKeyLenInBytes, + pSessionDesc->cipherARC4InitialState); + + pSessionDesc->cipherARC4InitialStatePhysAddr = + LAC_OS_VIRT_TO_PHYS_EXTERNAL( + pService->generic_service_info, + pSessionDesc->cipherARC4InitialState); + + if (0 == + pSessionDesc + ->cipherARC4InitialStatePhysAddr) { + LAC_LOG_ERROR( + "Unable to get the physical address of " + "the initial state for ARC4\n"); + status = CPA_STATUS_FAIL; + } + } + } + } + + if ((CPA_STATUS_SUCCESS == status) && pSessionDesc->isAuth) { + /* Populate auth-specific session data */ + const CpaCySymHashSetupData *pHashData = + &pSessionSetupData->hashSetupData; + + status = LacHash_HashContextCheck(instanceHandle, pHashData); + if (CPA_STATUS_SUCCESS == status) { + pSessionDesc->hashResultSize = + pHashData->digestResultLenInBytes; + pSessionDesc->hashMode = pHashData->hashMode; + pSessionDesc->hashAlgorithm = pHashData->hashAlgorithm; + + /* Save the authentication key length for further update + */ + if (CPA_CY_SYM_HASH_MODE_AUTH == pHashData->hashMode) { + pSessionDesc->authKeyLenInBytes = + pHashData->authModeSetupData + .authKeyLenInBytes; + } + if (CPA_TRUE == pSessionDesc->isAuthEncryptOp || + (pHashData->hashAlgorithm == + CPA_CY_SYM_HASH_SNOW3G_UIA2 || + pHashData->hashAlgorithm == + CPA_CY_SYM_HASH_ZUC_EIA3)) { + pSessionDesc->aadLenInBytes = + pHashData->authModeSetupData.aadLenInBytes; + } + + /* Set the QAT hash mode */ + if ((pHashData->hashMode == + CPA_CY_SYM_HASH_MODE_NESTED) || + (pHashData->hashMode == + CPA_CY_SYM_HASH_MODE_PLAIN) || + (pHashData->hashMode == CPA_CY_SYM_HASH_MODE_AUTH && + pHashData->hashAlgorithm == + CPA_CY_SYM_HASH_AES_CBC_MAC)) { + pSessionDesc->qatHashMode = + ICP_QAT_HW_AUTH_MODE0; + } else /* CPA_CY_SYM_HASH_MODE_AUTH + && anything except CPA_CY_SYM_HASH_AES_CBC_MAC + */ + { + if (IS_HMAC_ALG(pHashData->hashAlgorithm)) { + /* SHA3 and SM3 HMAC do not support + * precompute, force MODE2 + * for AUTH */ + if ((CPA_CY_SYM_HASH_SHA3_224 == + pHashData->hashAlgorithm) || + (CPA_CY_SYM_HASH_SHA3_256 == + pHashData->hashAlgorithm) || + (CPA_CY_SYM_HASH_SHA3_384 == + pHashData->hashAlgorithm) || + (CPA_CY_SYM_HASH_SHA3_512 == + pHashData->hashAlgorithm) || + (CPA_CY_SYM_HASH_SM3 == + pHashData->hashAlgorithm)) { + pSessionDesc->qatHashMode = + ICP_QAT_HW_AUTH_MODE2; + } else { + pSessionDesc->qatHashMode = + ICP_QAT_HW_AUTH_MODE1; + } + } else if (CPA_CY_SYM_HASH_ZUC_EIA3 == + pHashData->hashAlgorithm) { + pSessionDesc->qatHashMode = + ICP_QAT_HW_AUTH_MODE0; + } else { + pSessionDesc->qatHashMode = + ICP_QAT_HW_AUTH_MODE1; + } + } + } + } + + /*------------------------------------------------------------------------- + * build the message templates + * create two content descriptors in the case we can support using SHRAM + * constants and an optimised content descriptor. we have to do this in + *case + * of partials. + * 64 byte content desciptor is used in the SHRAM case for + *AES-128-HMAC-SHA1 + *-----------------------------------------------------------------------*/ + if (CPA_STATUS_SUCCESS == status) { + + LacSymCheck_IsPartialSupported(capabilitiesMask, pSessionDesc); + + /* setup some convenience pointers */ + pCdInfo = &(pSessionDesc->contentDescInfo); + pHwBlockBaseInDRAM = (Cpa8U *)pCdInfo->pData; + hwBlockOffsetInDRAM = 0; + + /* + * Build the header flags with the default settings for this + * session. + */ + if (pSessionDesc->isDPSession == CPA_TRUE) { + pSessionDesc->cmnRequestFlags = + ICP_QAT_FW_COMN_FLAGS_BUILD( + QAT_COMN_CD_FLD_TYPE_64BIT_ADR, + LAC_SYM_DP_QAT_PTR_TYPE); + } else { + pSessionDesc->cmnRequestFlags = + ICP_QAT_FW_COMN_FLAGS_BUILD( + QAT_COMN_CD_FLD_TYPE_64BIT_ADR, + LAC_SYM_DEFAULT_QAT_PTR_TYPE); + } + + LacSymQat_LaSetDefaultFlags(&pSessionDesc->laCmdFlags, + pSessionDesc->symOperation); + + switch (pSessionDesc->symOperation) { + case CPA_CY_SYM_OP_CIPHER: { + LacAlgChain_CipherCDBuild( + pCipherData, + pSessionDesc, + ICP_QAT_FW_SLICE_DRAM_WR, + cipherOffsetInConstantsTable, + &pSessionDesc->cmnRequestFlags, + &pSessionDesc->laCmdFlags, + pHwBlockBaseInDRAM, + &hwBlockOffsetInDRAM); + } break; + case CPA_CY_SYM_OP_HASH: + LacAlgChain_HashCDBuild(pHashData, + instanceHandle, + pSessionDesc, + ICP_QAT_FW_SLICE_DRAM_WR, + hashOffsetInConstantsTable, + &pSessionDesc->cmnRequestFlags, + &pSessionDesc->laCmdFlags, + &precomputeData, + &precomputeDataOptimisedCd, + pHwBlockBaseInDRAM, + &hwBlockOffsetInDRAM, + NULL, + NULL); + break; + case CPA_CY_SYM_OP_ALGORITHM_CHAINING: + /* For CCM/GCM, CPM firmware currently expects the + * cipher and + * hash h/w setup blocks to be arranged according to the + * chain + * order (Except for GCM/CCM, order doesn't actually + * matter as + * long as the config offsets are set correctly in CD + * control + * blocks + */ + if (CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER == + chainOrder) { + LacAlgChain_HashCDBuild( + pHashData, + instanceHandle, + pSessionDesc, + ICP_QAT_FW_SLICE_CIPHER, + hashOffsetInConstantsTable, + &pSessionDesc->cmnRequestFlags, + &pSessionDesc->laCmdFlags, + &precomputeData, + &precomputeDataOptimisedCd, + pHwBlockBaseInDRAM, + &hwBlockOffsetInDRAM, + pOptimisedHwBlockBaseInDRAM, + &optimisedHwBlockOffsetInDRAM); + + LacAlgChain_CipherCDBuild( + pCipherData, + pSessionDesc, + ICP_QAT_FW_SLICE_DRAM_WR, + cipherOffsetInConstantsTable, + &pSessionDesc->cmnRequestFlags, + &pSessionDesc->laCmdFlags, + pHwBlockBaseInDRAM, + &hwBlockOffsetInDRAM); + if (LAC_CIPHER_IS_SPC( + pCipherData->cipherAlgorithm, + pHashData->hashAlgorithm, + capabilitiesMask)) { + pCdInfo->hwBlkSzQuadWords = + (LAC_BYTES_TO_QUADWORDS( + hwBlockOffsetInDRAM)); + pMsg = (icp_qat_fw_comn_req_t *)&( + pSessionDesc->reqSpcCacheHdr); + SalQatMsg_ContentDescHdrWrite( + (icp_qat_fw_comn_req_t *)pMsg, + pCdInfo); + } + } else { + LacAlgChain_CipherCDBuild( + pCipherData, + pSessionDesc, + ICP_QAT_FW_SLICE_AUTH, + cipherOffsetInConstantsTable, + &pSessionDesc->cmnRequestFlags, + &pSessionDesc->laCmdFlags, + pHwBlockBaseInDRAM, + &hwBlockOffsetInDRAM); + + if (LAC_CIPHER_IS_SPC( + pCipherData->cipherAlgorithm, + pHashData->hashAlgorithm, + capabilitiesMask)) { + pCdInfo->hwBlkSzQuadWords = + LAC_BYTES_TO_QUADWORDS( + hwBlockOffsetInDRAM); + pMsg = (icp_qat_fw_comn_req_t *)&( + pSessionDesc->reqSpcCacheHdr); + SalQatMsg_ContentDescHdrWrite( + (icp_qat_fw_comn_req_t *)pMsg, + pCdInfo); + } + LacAlgChain_HashCDBuild( + pHashData, + instanceHandle, + pSessionDesc, + ICP_QAT_FW_SLICE_DRAM_WR, + hashOffsetInConstantsTable, + &pSessionDesc->cmnRequestFlags, + &pSessionDesc->laCmdFlags, + &precomputeData, + &precomputeDataOptimisedCd, + pHwBlockBaseInDRAM, + &hwBlockOffsetInDRAM, + pOptimisedHwBlockBaseInDRAM, + &optimisedHwBlockOffsetInDRAM); + } + break; + default: + LAC_LOG_ERROR("Invalid sym operation\n"); + status = CPA_STATUS_INVALID_PARAM; + } + } + + if ((CPA_STATUS_SUCCESS == status) && pSessionDesc->isAuth) { + lac_sym_qat_hash_state_buffer_info_t *pHashStateBufferInfo = + &(pSessionDesc->hashStateBufferInfo); + CpaBoolean hashStateBuffer = CPA_TRUE; + + /* set up fields in both the cd_ctrl and reqParams which + * describe + * the ReqParams block */ + LacSymQat_HashSetupReqParamsMetaData( + &(pSessionDesc->reqCacheFtr), + instanceHandle, + pHashData, + hashStateBuffer, + pSessionDesc->qatHashMode, + pSessionDesc->digestVerify); + + /* populate the hash state prefix buffer info structure + * (part of user allocated session memory & the + * buffer itself. For CCM/GCM the buffer is stored in the + * cookie and is not initialised here) */ + if (CPA_FALSE == pSessionDesc->isAuthEncryptOp) { + LAC_CHECK_64_BYTE_ALIGNMENT( + &(pSessionDesc->hashStatePrefixBuffer[0])); + status = LacHash_StatePrefixAadBufferInit( + &(pService->generic_service_info), + pHashData, + &(pSessionDesc->reqCacheFtr), + pSessionDesc->qatHashMode, + pSessionDesc->hashStatePrefixBuffer, + pHashStateBufferInfo); + /* SHRAM Constants Table not used for Auth-Enc */ + } + + if (CPA_STATUS_SUCCESS == status) { + if (IS_HASH_MODE_1(pSessionDesc->qatHashMode) || + CPA_CY_SYM_HASH_ZUC_EIA3 == + pHashData->hashAlgorithm) { + LAC_CHECK_64_BYTE_ALIGNMENT( + &(pSessionDesc->hashStatePrefixBuffer[0])); + + /* Block messages until precompute is completed + */ + pSessionDesc->nonBlockingOpsInProgress = + CPA_FALSE; + status = LacHash_PrecomputeDataCreate( + instanceHandle, + (CpaCySymSessionSetupData *) + pSessionSetupData, + LacSymAlgChain_HashPrecomputeDoneCb, + pSessionDesc, + pSessionDesc->hashStatePrefixBuffer, + precomputeData.pState1, + precomputeData.pState2); + } else if (pHashData->hashAlgorithm == + CPA_CY_SYM_HASH_AES_CBC_MAC) { + LAC_OS_BZERO(precomputeData.pState2, + precomputeData.state2Size); + memcpy(precomputeData.pState2, + pHashData->authModeSetupData.authKey, + pHashData->authModeSetupData + .authKeyLenInBytes); + } + } + if (CPA_STATUS_SUCCESS == status) { + + if (pSessionDesc->digestVerify) { + + ICP_QAT_FW_LA_CMP_AUTH_SET( + pSessionDesc->laCmdFlags, + ICP_QAT_FW_LA_CMP_AUTH_RES); + ICP_QAT_FW_LA_RET_AUTH_SET( + pSessionDesc->laCmdFlags, + ICP_QAT_FW_LA_NO_RET_AUTH_RES); + } else { + + ICP_QAT_FW_LA_RET_AUTH_SET( + pSessionDesc->laCmdFlags, + ICP_QAT_FW_LA_RET_AUTH_RES); + ICP_QAT_FW_LA_CMP_AUTH_SET( + pSessionDesc->laCmdFlags, + ICP_QAT_FW_LA_NO_CMP_AUTH_RES); + } + } + } + + if (CPA_STATUS_SUCCESS == status) { + + pCdInfo->hwBlkSzQuadWords = + LAC_BYTES_TO_QUADWORDS(hwBlockOffsetInDRAM); + pMsg = (icp_qat_fw_comn_req_t *)&(pSessionDesc->reqCacheHdr); + + /* Configure the ContentDescriptor field + * in the request if not done already */ + SalQatMsg_ContentDescHdrWrite((icp_qat_fw_comn_req_t *)pMsg, + pCdInfo); + + if (CPA_CY_SYM_CIPHER_ZUC_EEA3 == + pSessionSetupData->cipherSetupData.cipherAlgorithm || + pHashData->hashAlgorithm == CPA_CY_SYM_HASH_ZUC_EIA3) { + /* New bit position (12) for ZUC. The FW provides a + * specific macro + * to use to set the ZUC proto flag. With the new FW I/F + * this needs + * to be set for both Cipher and Auth */ + ICP_QAT_FW_LA_ZUC_3G_PROTO_FLAG_SET( + pSessionDesc->laCmdFlags, proto); + } else { + /* Configure the common header */ + ICP_QAT_FW_LA_PROTO_SET(pSessionDesc->laCmdFlags, + proto); + } + + /* set Append flag, if digest is appended */ + if (pSessionDesc->digestIsAppended) { + ICP_QAT_FW_LA_DIGEST_IN_BUFFER_SET( + pSessionDesc->laCmdFlags, + ICP_QAT_FW_LA_DIGEST_IN_BUFFER); + } else { + ICP_QAT_FW_LA_DIGEST_IN_BUFFER_SET( + pSessionDesc->laCmdFlags, + ICP_QAT_FW_LA_NO_DIGEST_IN_BUFFER); + } + + SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)pMsg, + ICP_QAT_FW_COMN_REQ_CPM_FW_LA, + pSessionDesc->laCmdId, + pSessionDesc->cmnRequestFlags, + pSessionDesc->laCmdFlags); + } + + return status; +} + +/** @ingroup LacAlgChain */ +CpaStatus +LacAlgChain_Perform(const CpaInstanceHandle instanceHandle, + lac_session_desc_t *pSessionDesc, + void *pCallbackTag, + const CpaCySymOpData *pOpData, + const CpaBufferList *pSrcBuffer, + CpaBufferList *pDstBuffer, + CpaBoolean *pVerifyResult) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + Cpa32U capabilitiesMask = + pService->generic_service_info.capabilitiesMask; + lac_sym_bulk_cookie_t *pCookie = NULL; + lac_sym_cookie_t *pSymCookie = NULL; + icp_qat_fw_la_bulk_req_t *pMsg = NULL; + Cpa8U *pMsgDummy = NULL; + Cpa8U *pCacheDummyHdr = NULL; + Cpa8U *pCacheDummyFtr = NULL; + Cpa32U qatPacketType = 0; + CpaBufferList *pBufferList = NULL; + Cpa8U *pDigestResult = NULL; + Cpa64U srcAddrPhys = 0; + Cpa64U dstAddrPhys = 0; + icp_qat_fw_la_cmd_id_t laCmdId; + sal_qat_content_desc_info_t *pCdInfo = NULL; + Cpa8U *pHwBlockBaseInDRAM = NULL; + Cpa32U hwBlockOffsetInDRAM = 0; + Cpa32U sizeInBytes = 0; + icp_qat_fw_cipher_cd_ctrl_hdr_t *pSpcCdCtrlHdr = NULL; + CpaCySymCipherAlgorithm cipher; + CpaCySymHashAlgorithm hash; + Cpa8U paddingLen = 0; + Cpa8U blockLen = 0; + Cpa64U srcPktSize = 0; + + /* Set the command id */ + laCmdId = pSessionDesc->laCmdId; + + cipher = pSessionDesc->cipherAlgorithm; + hash = pSessionDesc->hashAlgorithm; + + /* Convert Alg Chain Request to Cipher Request for CCP and + * AES_GCM single pass */ + if (!pSessionDesc->isSinglePass && + LAC_CIPHER_IS_SPC(cipher, hash, capabilitiesMask) && + (LAC_CIPHER_SPC_IV_SIZE == pOpData->ivLenInBytes)) { + pSessionDesc->laCmdId = ICP_QAT_FW_LA_CMD_CIPHER; + laCmdId = pSessionDesc->laCmdId; + pSessionDesc->symOperation = CPA_CY_SYM_OP_CIPHER; + pSessionDesc->isSinglePass = CPA_TRUE; + pSessionDesc->isCipher = CPA_TRUE; + pSessionDesc->isAuthEncryptOp = CPA_FALSE; + pSessionDesc->isAuth = CPA_FALSE; + if (CPA_CY_SYM_HASH_AES_GMAC == pSessionDesc->hashAlgorithm) { + pSessionDesc->aadLenInBytes = + pOpData->messageLenToHashInBytes; + if (ICP_QAT_FW_SPC_AAD_SZ_MAX < + pSessionDesc->aadLenInBytes) { + LAC_INVALID_PARAM_LOG( + "aadLenInBytes for AES_GMAC"); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* New bit position (13) for SINGLE PASS. + * The FW provides a specific macro to use to set the proto flag + */ + ICP_QAT_FW_LA_SINGLE_PASS_PROTO_FLAG_SET( + pSessionDesc->laCmdFlags, ICP_QAT_FW_LA_SINGLE_PASS_PROTO); + ICP_QAT_FW_LA_PROTO_SET(pSessionDesc->laCmdFlags, 0); + + pCdInfo = &(pSessionDesc->contentDescInfo); + pHwBlockBaseInDRAM = (Cpa8U *)pCdInfo->pData; + if (CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT == + pSessionDesc->cipherDirection) { + if (LAC_CIPHER_IS_GCM(cipher)) + hwBlockOffsetInDRAM = LAC_QUADWORDS_TO_BYTES( + LAC_SYM_QAT_CIPHER_OFFSET_IN_DRAM_GCM_SPC); + else + hwBlockOffsetInDRAM = LAC_QUADWORDS_TO_BYTES( + LAC_SYM_QAT_CIPHER_OFFSET_IN_DRAM_CHACHA_SPC); + } + /* construct cipherConfig in CD in DRAM */ + LacSymQat_CipherHwBlockPopulateCfgData(pSessionDesc, + pHwBlockBaseInDRAM + + hwBlockOffsetInDRAM, + &sizeInBytes); + SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)&( + pSessionDesc->reqSpcCacheHdr), + ICP_QAT_FW_COMN_REQ_CPM_FW_LA, + pSessionDesc->laCmdId, + pSessionDesc->cmnRequestFlags, + pSessionDesc->laCmdFlags); + } else if (CPA_CY_SYM_HASH_AES_GMAC == pSessionDesc->hashAlgorithm) { + pSessionDesc->aadLenInBytes = pOpData->messageLenToHashInBytes; + } + + if (LAC_CIPHER_IS_CHACHA(cipher) && + (LAC_CIPHER_SPC_IV_SIZE != pOpData->ivLenInBytes)) { + LAC_INVALID_PARAM_LOG("IV for CHACHA"); + return CPA_STATUS_INVALID_PARAM; + } else if (CPA_CY_SYM_HASH_AES_GMAC == pSessionDesc->hashAlgorithm) { + if (pOpData->messageLenToHashInBytes == 0 || + pOpData->pAdditionalAuthData != NULL) { + LAC_INVALID_PARAM_LOG( + "For AES_GMAC, AAD Length " + "(messageLenToHashInBytes) must " + "be non zero and pAdditionalAuthData " + "must be NULL"); + status = CPA_STATUS_INVALID_PARAM; + } + } + + if (CPA_TRUE == pSessionDesc->isAuthEncryptOp) { + if (CPA_CY_SYM_HASH_AES_CCM == pSessionDesc->hashAlgorithm) { + status = LacSymAlgChain_CheckCCMData( + pOpData->pAdditionalAuthData, + pOpData->pIv, + pOpData->messageLenToCipherInBytes, + pOpData->ivLenInBytes); + if (CPA_STATUS_SUCCESS == status) { + LacSymAlgChain_PrepareCCMData( + pSessionDesc, + pOpData->pAdditionalAuthData, + pOpData->pIv, + pOpData->messageLenToCipherInBytes, + pOpData->ivLenInBytes); + } + } else if (CPA_CY_SYM_HASH_AES_GCM == + pSessionDesc->hashAlgorithm) { + if (pSessionDesc->aadLenInBytes != 0 && + pOpData->pAdditionalAuthData == NULL) { + LAC_INVALID_PARAM_LOG("pAdditionalAuthData"); + status = CPA_STATUS_INVALID_PARAM; + } + if (CPA_STATUS_SUCCESS == status) { + LacSymAlgChain_PrepareGCMData( + pSessionDesc, pOpData->pAdditionalAuthData); + } + } + } + + /* allocate cookie (used by callback function) */ + if (CPA_STATUS_SUCCESS == status) { + pSymCookie = (lac_sym_cookie_t *)Lac_MemPoolEntryAlloc( + pService->lac_sym_cookie_pool); + if (pSymCookie == NULL) { + LAC_LOG_ERROR("Cannot allocate cookie - NULL"); + status = CPA_STATUS_RESOURCE; + } else if ((void *)CPA_STATUS_RETRY == pSymCookie) { + pSymCookie = NULL; + status = CPA_STATUS_RETRY; + } else { + pCookie = &(pSymCookie->u.bulkCookie); + } + } + + if (CPA_STATUS_SUCCESS == status) { + /* write the buffer descriptors */ + if (IS_ZERO_LENGTH_BUFFER_SUPPORTED(cipher, hash)) { + status = + LacBuffDesc_BufferListDescWriteAndAllowZeroBuffer( + (CpaBufferList *)pSrcBuffer, + &srcAddrPhys, + CPA_FALSE, + &(pService->generic_service_info)); + } else { + status = LacBuffDesc_BufferListDescWrite( + (CpaBufferList *)pSrcBuffer, + &srcAddrPhys, + CPA_FALSE, + &(pService->generic_service_info)); + } + if (CPA_STATUS_SUCCESS != status) { + LAC_LOG_ERROR("Unable to write src buffer descriptors"); + } + + /* For out of place operations */ + if ((pSrcBuffer != pDstBuffer) && + (CPA_STATUS_SUCCESS == status)) { + if (IS_ZERO_LENGTH_BUFFER_SUPPORTED(cipher, hash)) { + status = + LacBuffDesc_BufferListDescWriteAndAllowZeroBuffer( + pDstBuffer, + &dstAddrPhys, + CPA_FALSE, + &(pService->generic_service_info)); + } else { + status = LacBuffDesc_BufferListDescWrite( + pDstBuffer, + &dstAddrPhys, + CPA_FALSE, + &(pService->generic_service_info)); + } + if (CPA_STATUS_SUCCESS != status) { + LAC_LOG_ERROR( + "Unable to write dest buffer descriptors"); + } + } + } + if (CPA_STATUS_SUCCESS == status) { + /* populate the cookie */ + pCookie->pCallbackTag = pCallbackTag; + pCookie->sessionCtx = pOpData->sessionCtx; + pCookie->pOpData = (const CpaCySymOpData *)pOpData; + pCookie->pDstBuffer = pDstBuffer; + pCookie->updateSessionIvOnSend = CPA_FALSE; + pCookie->updateUserIvOnRecieve = CPA_FALSE; + pCookie->updateKeySizeOnRecieve = CPA_FALSE; + pCookie->pNext = NULL; + pCookie->instanceHandle = pService; + + /* get the qat packet type for LAC packet type */ + LacSymQat_packetTypeGet(pOpData->packetType, + pSessionDesc->partialState, + &qatPacketType); + /* + * For XTS mode, the key size must be updated after + * the first partial has been sent. Set a flag here so the + * response knows to do this. + */ + if ((laCmdId != ICP_QAT_FW_LA_CMD_AUTH) && + (CPA_CY_SYM_PACKET_TYPE_PARTIAL == pOpData->packetType) && + (LAC_CIPHER_IS_XTS_MODE(pSessionDesc->cipherAlgorithm)) && + (qatPacketType == ICP_QAT_FW_LA_PARTIAL_START)) { + pCookie->updateKeySizeOnRecieve = CPA_TRUE; + } + + /* + * Now create the Request. + * Start by populating it from the cache in the session + * descriptor. + */ + pMsg = &(pCookie->qatMsg); + pMsgDummy = (Cpa8U *)pMsg; + + if (pSessionDesc->isSinglePass) { + pCacheDummyHdr = + (Cpa8U *)&(pSessionDesc->reqSpcCacheHdr); + pCacheDummyFtr = + (Cpa8U *)&(pSessionDesc->reqSpcCacheFtr); + } else { + /* Normally, we want to use the SHRAM Constants Table if + * possible + * for best performance (less DRAM accesses incurred by + * CPM). But + * we can't use it for partial-packet hash operations. + * This is why + * we build 2 versions of the message template at + * sessionInit, + * one for SHRAM Constants Table usage and the other + * (default) for + * Content Descriptor h/w setup data in DRAM. And we + * chose between + * them here on a per-request basis, when we know the + * packetType + */ + if ((!pSessionDesc->useSymConstantsTable) || + (pSessionDesc->isAuth && + (CPA_CY_SYM_PACKET_TYPE_FULL != + pOpData->packetType))) { + pCacheDummyHdr = + (Cpa8U *)&(pSessionDesc->reqCacheHdr); + pCacheDummyFtr = + (Cpa8U *)&(pSessionDesc->reqCacheFtr); + } else { + pCacheDummyHdr = + (Cpa8U *)&(pSessionDesc->shramReqCacheHdr); + pCacheDummyFtr = + (Cpa8U *)&(pSessionDesc->shramReqCacheFtr); + } + } + memcpy(pMsgDummy, + pCacheDummyHdr, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)); + memset((pMsgDummy + + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)), + 0, + (LAC_LONG_WORD_IN_BYTES * + LAC_SIZE_OF_CACHE_TO_CLEAR_IN_LW)); + memcpy(pMsgDummy + (LAC_LONG_WORD_IN_BYTES * + LAC_START_OF_CACHE_FTR_IN_LW), + pCacheDummyFtr, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_FTR_IN_LW)); + /* + * Populate the comn_mid section + */ + SalQatMsg_CmnMidWrite(pMsg, + pCookie, + LAC_SYM_DEFAULT_QAT_PTR_TYPE, + srcAddrPhys, + dstAddrPhys, + 0, + 0); + + /* + * Populate the serv_specif_flags field of the Request header + * Some of the flags are set up here. + * Others are set up later when the RequestParams are set up. + */ + + LacSymQat_LaPacketCommandFlagSet( + qatPacketType, + laCmdId, + pSessionDesc->cipherAlgorithm, + &pMsg->comn_hdr.serv_specif_flags, + pOpData->ivLenInBytes); + + if (pSessionDesc->isSinglePass) { + ICP_QAT_FW_LA_GCM_IV_LEN_FLAG_SET( + pMsg->comn_hdr.serv_specif_flags, + ICP_QAT_FW_LA_GCM_IV_LEN_NOT_12_OCTETS); + + if (CPA_CY_SYM_PACKET_TYPE_PARTIAL == + pOpData->packetType) { + ICP_QAT_FW_LA_RET_AUTH_SET( + pMsg->comn_hdr.serv_specif_flags, + ICP_QAT_FW_LA_NO_RET_AUTH_RES); + + ICP_QAT_FW_LA_CMP_AUTH_SET( + pMsg->comn_hdr.serv_specif_flags, + ICP_QAT_FW_LA_NO_CMP_AUTH_RES); + } + } + + LacBuffDesc_BufferListTotalSizeGet(pSrcBuffer, &srcPktSize); + + /* + * Populate the CipherRequestParams section of the Request + */ + if (laCmdId != ICP_QAT_FW_LA_CMD_AUTH) { + + Cpa8U *pIvBuffer = NULL; + + status = LacCipher_PerformParamCheck( + pSessionDesc->cipherAlgorithm, pOpData, srcPktSize); + if (CPA_STATUS_SUCCESS != status) { + /* free the cookie */ + Lac_MemPoolEntryFree(pCookie); + return status; + } + + if (CPA_STATUS_SUCCESS == status) { + /* align cipher IV */ + status = LacCipher_PerformIvCheck( + &(pService->generic_service_info), + pCookie, + qatPacketType, + &pIvBuffer); + } + if (pSessionDesc->isSinglePass && + ((ICP_QAT_FW_LA_PARTIAL_MID == qatPacketType) || + (ICP_QAT_FW_LA_PARTIAL_END == qatPacketType))) { + /* For SPC stateful cipher state size for mid + * and + * end partial packet is 48 bytes + */ + pSpcCdCtrlHdr = + (icp_qat_fw_cipher_cd_ctrl_hdr_t *)&( + pMsg->cd_ctrl); + pSpcCdCtrlHdr->cipher_state_sz = + LAC_BYTES_TO_QUADWORDS( + LAC_SYM_QAT_CIPHER_STATE_SIZE_SPC); + } + /*populate the cipher request parameters */ + if (CPA_STATUS_SUCCESS == status) { + Cpa64U ivBufferPhysAddr = 0; + + if (pIvBuffer != NULL) { + /* User OpData memory being used for IV + * buffer */ + /* get the physical address */ + ivBufferPhysAddr = + LAC_OS_VIRT_TO_PHYS_EXTERNAL( + pService->generic_service_info, + pIvBuffer); + if (0 == ivBufferPhysAddr) { + LAC_LOG_ERROR( + "Unable to get the physical address " + "of the IV\n"); + status = CPA_STATUS_FAIL; + } + } + + if (status == CPA_STATUS_SUCCESS) { + status = + LacSymQat_CipherRequestParamsPopulate( + pMsg, + pOpData + ->cryptoStartSrcOffsetInBytes, + pOpData + ->messageLenToCipherInBytes, + ivBufferPhysAddr, + pIvBuffer); + } + } + + if (CPA_STATUS_SUCCESS == status && + pSessionDesc->isSinglePass) { + Cpa64U aadBufferPhysAddr = 0; + + /* For CHACHA and AES-GCM there is an AAD buffer + * if + * aadLenInBytes is nonzero In case of AES-GMAC, + * AAD buffer + * passed in the src buffer. + */ + if (0 != pSessionDesc->aadLenInBytes && + CPA_CY_SYM_HASH_AES_GMAC != + pSessionDesc->hashAlgorithm) { + LAC_CHECK_NULL_PARAM( + pOpData->pAdditionalAuthData); + blockLen = + LacSymQat_CipherBlockSizeBytesGet( + pSessionDesc->cipherAlgorithm); + if ((pSessionDesc->aadLenInBytes % + blockLen) != 0) { + paddingLen = blockLen - + (pSessionDesc + ->aadLenInBytes % + blockLen); + memset( + &pOpData->pAdditionalAuthData + [pSessionDesc + ->aadLenInBytes], + 0, + paddingLen); + } + + /* User OpData memory being used for aad + * buffer */ + /* get the physical address */ + aadBufferPhysAddr = + LAC_OS_VIRT_TO_PHYS_EXTERNAL( + pService->generic_service_info, + pOpData->pAdditionalAuthData); + if (0 == aadBufferPhysAddr) { + LAC_LOG_ERROR( + "Unable to get the physical address " + "of the aad\n"); + status = CPA_STATUS_FAIL; + } + } + + if (CPA_STATUS_SUCCESS == status) { + icp_qat_fw_la_cipher_req_params_t *pCipherReqParams = + (icp_qat_fw_la_cipher_req_params_t + *)((Cpa8U *)&( + pMsg->serv_specif_rqpars) + + ICP_QAT_FW_CIPHER_REQUEST_PARAMETERS_OFFSET); + pCipherReqParams->spc_aad_addr = + aadBufferPhysAddr; + pCipherReqParams->spc_aad_sz = + pSessionDesc->aadLenInBytes; + + if (CPA_TRUE != + pSessionDesc->digestIsAppended) { + Cpa64U digestBufferPhysAddr = 0; + /* User OpData memory being used + * for digest buffer */ + /* get the physical address */ + digestBufferPhysAddr = + LAC_OS_VIRT_TO_PHYS_EXTERNAL( + pService + ->generic_service_info, + pOpData->pDigestResult); + if (0 != digestBufferPhysAddr) { + pCipherReqParams + ->spc_auth_res_addr = + digestBufferPhysAddr; + pCipherReqParams + ->spc_auth_res_sz = + pSessionDesc + ->hashResultSize; + } else { + LAC_LOG_ERROR( + "Unable to get the physical address " + "of the digest\n"); + status = + CPA_STATUS_FAIL; + } + } + } + } + } + + /* + * Set up HashRequestParams part of Request + */ + if ((status == CPA_STATUS_SUCCESS) && + (laCmdId != ICP_QAT_FW_LA_CMD_CIPHER)) { + Cpa32U authOffsetInBytes = + pOpData->hashStartSrcOffsetInBytes; + Cpa32U authLenInBytes = + pOpData->messageLenToHashInBytes; + + status = LacHash_PerformParamCheck(instanceHandle, + pSessionDesc, + pOpData, + srcPktSize, + pVerifyResult); + if (CPA_STATUS_SUCCESS != status) { + /* free the cookie */ + Lac_MemPoolEntryFree(pCookie); + return status; + } + if (CPA_STATUS_SUCCESS == status) { + /* Info structure for CCM/GCM */ + lac_sym_qat_hash_state_buffer_info_t + hashStateBufferInfo = { 0 }; + lac_sym_qat_hash_state_buffer_info_t + *pHashStateBufferInfo = + &(pSessionDesc->hashStateBufferInfo); + + if (CPA_TRUE == pSessionDesc->isAuthEncryptOp) { + icp_qat_fw_la_auth_req_params_t *pHashReqParams = + (icp_qat_fw_la_auth_req_params_t + *)((Cpa8U *)&( + pMsg->serv_specif_rqpars) + + ICP_QAT_FW_HASH_REQUEST_PARAMETERS_OFFSET); + + hashStateBufferInfo.pData = + pOpData->pAdditionalAuthData; + if (pOpData->pAdditionalAuthData == + NULL) { + hashStateBufferInfo.pDataPhys = + 0; + } else { + hashStateBufferInfo + .pDataPhys = LAC_MEM_CAST_PTR_TO_UINT64( + LAC_OS_VIRT_TO_PHYS_EXTERNAL( + pService + ->generic_service_info, + pOpData + ->pAdditionalAuthData)); + } + + hashStateBufferInfo + .stateStorageSzQuadWords = 0; + hashStateBufferInfo + .prefixAadSzQuadWords = + LAC_BYTES_TO_QUADWORDS( + pHashReqParams->u2.aad_sz); + + /* Overwrite hash state buffer info + * structure pointer + * with the one created for CCM/GCM */ + pHashStateBufferInfo = + &hashStateBufferInfo; + + /* Aad buffer could be null in the GCM + * case */ + if (0 == + hashStateBufferInfo.pDataPhys && + CPA_CY_SYM_HASH_AES_GCM != + pSessionDesc->hashAlgorithm && + CPA_CY_SYM_HASH_AES_GMAC != + pSessionDesc->hashAlgorithm) { + LAC_LOG_ERROR( + "Unable to get the physical address" + "of the AAD\n"); + status = CPA_STATUS_FAIL; + } + + /* for CCM/GCM the hash and cipher data + * regions + * are equal */ + authOffsetInBytes = + pOpData + ->cryptoStartSrcOffsetInBytes; + + /* For authenticated encryption, + * authentication length is + * determined by + * messageLenToCipherInBytes for AES-GCM + * and + * AES-CCM, and by + * messageLenToHashInBytes for AES-GMAC. + * You don't see the latter here, as + * that is the initial + * value of authLenInBytes. */ + if (pSessionDesc->hashAlgorithm != + CPA_CY_SYM_HASH_AES_GMAC) + authLenInBytes = + pOpData + ->messageLenToCipherInBytes; + } else if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == + pSessionDesc->hashAlgorithm || + CPA_CY_SYM_HASH_ZUC_EIA3 == + pSessionDesc->hashAlgorithm) { + hashStateBufferInfo.pData = + pOpData->pAdditionalAuthData; + hashStateBufferInfo.pDataPhys = + LAC_OS_VIRT_TO_PHYS_EXTERNAL( + pService->generic_service_info, + hashStateBufferInfo.pData); + hashStateBufferInfo + .stateStorageSzQuadWords = 0; + hashStateBufferInfo + .prefixAadSzQuadWords = + LAC_BYTES_TO_QUADWORDS( + pSessionDesc->aadLenInBytes); + + pHashStateBufferInfo = + &hashStateBufferInfo; + + if (0 == + hashStateBufferInfo.pDataPhys) { + LAC_LOG_ERROR( + "Unable to get the physical address" + "of the AAD\n"); + status = CPA_STATUS_FAIL; + } + } + if (CPA_CY_SYM_HASH_AES_CCM == + pSessionDesc->hashAlgorithm) { + if (CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT == + pSessionDesc->cipherDirection) { + /* On a decrypt path pSrcBuffer + * is used as this is + * where encrypted digest is + * located. Firmware + * uses encrypted digest for + * compare/verification*/ + pBufferList = + (CpaBufferList *)pSrcBuffer; + } else { + /* On an encrypt path pDstBuffer + * is used as this is + * where encrypted digest will + * be written */ + pBufferList = + (CpaBufferList *)pDstBuffer; + } + status = LacSymAlgChain_PtrFromOffsetGet( + pBufferList, + pOpData->cryptoStartSrcOffsetInBytes + + pOpData + ->messageLenToCipherInBytes, + &pDigestResult); + if (CPA_STATUS_SUCCESS != status) { + LAC_LOG_ERROR( + "Cannot set digest pointer within the" + " buffer list - offset out of bounds"); + } + } else { + pDigestResult = pOpData->pDigestResult; + } + + if (CPA_CY_SYM_OP_ALGORITHM_CHAINING == + pSessionDesc->symOperation) { + /* In alg chaining mode, packets are not + * seen as partials + * for hash operations. Override to + * NONE. + */ + qatPacketType = + ICP_QAT_FW_LA_PARTIAL_NONE; + } + if (CPA_TRUE == + pSessionDesc->digestIsAppended) { + /*Check if the destination buffer can + * handle the digest + * if digestIsAppend is true*/ + if (srcPktSize < + (authOffsetInBytes + + authLenInBytes + + pSessionDesc->hashResultSize)) { + status = + CPA_STATUS_INVALID_PARAM; + } + } + if (CPA_STATUS_SUCCESS == status) { + /* populate the hash request parameters + */ + status = + LacSymQat_HashRequestParamsPopulate( + pMsg, + authOffsetInBytes, + authLenInBytes, + &(pService + ->generic_service_info), + pHashStateBufferInfo, + qatPacketType, + pSessionDesc->hashResultSize, + pSessionDesc->digestVerify, + pSessionDesc->digestIsAppended ? + NULL : + pDigestResult, + pSessionDesc->hashAlgorithm, + NULL); + } + } + } + } + + /* + * send the message to the QAT + */ + if (CPA_STATUS_SUCCESS == status) { + qatUtilsAtomicInc(&(pSessionDesc->u.pendingCbCount)); + + status = LacSymQueue_RequestSend(instanceHandle, + pCookie, + pSessionDesc); + + if (CPA_STATUS_SUCCESS != status) { + /* Decrease pending callback counter on send fail. */ + qatUtilsAtomicDec(&(pSessionDesc->u.pendingCbCount)); + } + } + /* Case that will catch all error status's for this function */ + if (CPA_STATUS_SUCCESS != status) { + /* free the cookie */ + if (NULL != pSymCookie) { + Lac_MemPoolEntryFree(pSymCookie); + } + } + return status; +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_api.c b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_api.c new file mode 100644 index 000000000000..70446ef988b0 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_api.c @@ -0,0 +1,1130 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_api.c Implementation of the symmetric API + * + * @ingroup LacSym + * + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ + +#include "cpa.h" +#include "cpa_cy_sym.h" +#include "cpa_cy_im.h" + +#include "icp_adf_init.h" +#include "icp_adf_transport.h" +#include "icp_adf_transport_dp.h" +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" +#include "icp_qat_fw_la.h" + +/* + ****************************************************************************** + * Include private header files + ****************************************************************************** + */ +#include "lac_common.h" +#include "lac_log.h" +#include "lac_mem.h" +#include "lac_mem_pools.h" +#include "lac_list.h" +#include "lac_sym.h" +#include "lac_sym_qat.h" +#include "lac_sal.h" +#include "lac_sal_ctrl.h" +#include "lac_session.h" +#include "lac_sym_cipher.h" +#include "lac_sym_hash.h" +#include "lac_sym_alg_chain.h" +#include "lac_sym_stats.h" +#include "lac_sym_partial.h" +#include "lac_sym_qat_hash_defs_lookup.h" +#include "lac_sym_cb.h" +#include "lac_buffer_desc.h" +#include "lac_sync.h" +#include "lac_hooks.h" +#include "lac_sal_types_crypto.h" +#include "sal_service_state.h" + +#define IS_EXT_ALG_CHAIN_UNSUPPORTED( \ + cipherAlgorithm, hashAlgorithm, extAlgchainSupported) \ + ((((CPA_CY_SYM_CIPHER_ZUC_EEA3 == cipherAlgorithm || \ + CPA_CY_SYM_CIPHER_SNOW3G_UEA2 == cipherAlgorithm) && \ + CPA_CY_SYM_HASH_AES_CMAC == hashAlgorithm) || \ + ((CPA_CY_SYM_CIPHER_NULL == cipherAlgorithm || \ + CPA_CY_SYM_CIPHER_AES_CTR == cipherAlgorithm || \ + CPA_CY_SYM_CIPHER_ZUC_EEA3 == cipherAlgorithm) && \ + CPA_CY_SYM_HASH_SNOW3G_UIA2 == hashAlgorithm) || \ + ((CPA_CY_SYM_CIPHER_NULL == cipherAlgorithm || \ + CPA_CY_SYM_CIPHER_AES_CTR == cipherAlgorithm || \ + CPA_CY_SYM_CIPHER_SNOW3G_UEA2 == cipherAlgorithm) && \ + CPA_CY_SYM_HASH_ZUC_EIA3 == hashAlgorithm)) && \ + !extAlgchainSupported) + +/*** Local functions definitions ***/ +static CpaStatus +LacSymPerform_BufferParamCheck(const CpaBufferList *const pSrcBuffer, + const CpaBufferList *const pDstBuffer, + const lac_session_desc_t *const pSessionDesc, + const CpaCySymOpData *const pOpData); + +void getCtxSize(const CpaCySymSessionSetupData *pSessionSetupData, + Cpa32U *pSessionCtxSizeInBytes); + +/** + ***************************************************************************** + * @ingroup LacSym + * Generic bufferList callback function. + * @description + * This function is used when the API is called in synchronous mode. + * It's assumed the callbackTag holds a lac_sync_op_data_t type + * and when the callback is received, this callback shall set the + * status and opResult element of that cookie structure and + * kick the sid. + * This function may be used directly as a callback function. + * + * @param[in] callbackTag Callback Tag + * @param[in] status Status of callback + * @param[in] operationType Operation Type + * @param[in] pOpData Pointer to the Op Data + * @param[out] pDstBuffer Pointer to destination buffer list + * @param[out] opResult Boolean to indicate the result of the operation + * + * @return void + * + *****************************************************************************/ +void +LacSync_GenBufListVerifyCb(void *pCallbackTag, + CpaStatus status, + CpaCySymOp operationType, + void *pOpData, + CpaBufferList *pDstBuffer, + CpaBoolean opResult) +{ + LacSync_GenVerifyWakeupSyncCaller(pCallbackTag, status, opResult); +} + +/* +******************************************************************************* +* Define static function definitions +******************************************************************************* +*/ +/** + * @ingroup LacSym + * Function which perform parameter checks on session setup data + * + * @param[in] CpaInstanceHandle Instance Handle + * @param[in] pSessionSetupData Pointer to session setup data + * + * @retval CPA_STATUS_SUCCESS The operation succeeded + * @retval CPA_STATUS_INVALID_PARAM An invalid parameter value was found + */ +static CpaStatus +LacSymSession_ParamCheck(const CpaInstanceHandle instanceHandle, + const CpaCySymSessionSetupData *pSessionSetupData) +{ + /* initialize convenient pointers to cipher and hash contexts */ + const CpaCySymCipherSetupData *const pCipherSetupData = + (const CpaCySymCipherSetupData *)&pSessionSetupData + ->cipherSetupData; + const CpaCySymHashSetupData *const pHashSetupData = + &pSessionSetupData->hashSetupData; + + CpaCySymCapabilitiesInfo capInfo; + CpaCyCapabilitiesInfo cyCapInfo; + cpaCySymQueryCapabilities(instanceHandle, &capInfo); + SalCtrl_CyQueryCapabilities(instanceHandle, &cyCapInfo); + + /* Ensure cipher algorithm is correct and supported */ + if ((CPA_CY_SYM_OP_ALGORITHM_CHAINING == + pSessionSetupData->symOperation) || + (CPA_CY_SYM_OP_CIPHER == pSessionSetupData->symOperation)) { + /* Protect against value of cipher outside the bitmap + * and check if cipher algorithm is correct + */ + if ((pCipherSetupData->cipherAlgorithm >= + CPA_CY_SYM_CIPHER_CAP_BITMAP_SIZE) || + (!CPA_BITMAP_BIT_TEST(capInfo.ciphers, + pCipherSetupData->cipherAlgorithm))) { + LAC_INVALID_PARAM_LOG("cipherAlgorithm"); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* Ensure hash algorithm is correct and supported */ + if ((CPA_CY_SYM_OP_ALGORITHM_CHAINING == + pSessionSetupData->symOperation) || + (CPA_CY_SYM_OP_HASH == pSessionSetupData->symOperation)) { + /* Ensure SHAKE algorithms are not supported */ + if ((CPA_CY_SYM_HASH_SHAKE_128 == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_SHAKE_256 == + pHashSetupData->hashAlgorithm)) { + LAC_INVALID_PARAM_LOG( + "Hash algorithms SHAKE-128 and SHAKE-256 " + "are not supported."); + return CPA_STATUS_UNSUPPORTED; + } + + /* Protect against value of hash outside the bitmap + * and check if hash algorithm is correct + */ + if ((pHashSetupData->hashAlgorithm >= + CPA_CY_SYM_HASH_CAP_BITMAP_SIZE) || + (!CPA_BITMAP_BIT_TEST(capInfo.hashes, + pHashSetupData->hashAlgorithm))) { + LAC_INVALID_PARAM_LOG("hashAlgorithm"); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* ensure CCM, GCM, Kasumi, Snow3G and ZUC cipher and hash algorithms + * are + * selected together for Algorithm Chaining */ + if (CPA_CY_SYM_OP_ALGORITHM_CHAINING == + pSessionSetupData->symOperation) { + /* ensure both hash and cipher algorithms are POLY and CHACHA */ + if (((CPA_CY_SYM_CIPHER_CHACHA == + pCipherSetupData->cipherAlgorithm) && + (CPA_CY_SYM_HASH_POLY != pHashSetupData->hashAlgorithm)) || + ((CPA_CY_SYM_HASH_POLY == pHashSetupData->hashAlgorithm) && + (CPA_CY_SYM_CIPHER_CHACHA != + pCipherSetupData->cipherAlgorithm))) { + LAC_INVALID_PARAM_LOG( + "Invalid combination of Cipher/Hash " + "Algorithms for CHACHA/POLY"); + return CPA_STATUS_INVALID_PARAM; + } + + /* ensure both hash and cipher algorithms are CCM */ + if (((CPA_CY_SYM_CIPHER_AES_CCM == + pCipherSetupData->cipherAlgorithm) && + (CPA_CY_SYM_HASH_AES_CCM != + pHashSetupData->hashAlgorithm)) || + ((CPA_CY_SYM_HASH_AES_CCM == + pHashSetupData->hashAlgorithm) && + (CPA_CY_SYM_CIPHER_AES_CCM != + pCipherSetupData->cipherAlgorithm))) { + LAC_INVALID_PARAM_LOG( + "Invalid combination of Cipher/Hash Algorithms for CCM"); + return CPA_STATUS_INVALID_PARAM; + } + + /* ensure both hash and cipher algorithms are GCM/GMAC */ + if ((CPA_CY_SYM_CIPHER_AES_GCM == + pCipherSetupData->cipherAlgorithm && + (CPA_CY_SYM_HASH_AES_GCM != + pHashSetupData->hashAlgorithm && + CPA_CY_SYM_HASH_AES_GMAC != + pHashSetupData->hashAlgorithm)) || + ((CPA_CY_SYM_HASH_AES_GCM == + pHashSetupData->hashAlgorithm || + CPA_CY_SYM_HASH_AES_GMAC == + pHashSetupData->hashAlgorithm) && + CPA_CY_SYM_CIPHER_AES_GCM != + pCipherSetupData->cipherAlgorithm)) { + LAC_INVALID_PARAM_LOG( + "Invalid combination of Cipher/Hash Algorithms for GCM"); + return CPA_STATUS_INVALID_PARAM; + } + + /* ensure both hash and cipher algorithms are Kasumi */ + if (((CPA_CY_SYM_CIPHER_KASUMI_F8 == + pCipherSetupData->cipherAlgorithm) && + (CPA_CY_SYM_HASH_KASUMI_F9 != + pHashSetupData->hashAlgorithm)) || + ((CPA_CY_SYM_HASH_KASUMI_F9 == + pHashSetupData->hashAlgorithm) && + (CPA_CY_SYM_CIPHER_KASUMI_F8 != + pCipherSetupData->cipherAlgorithm))) { + LAC_INVALID_PARAM_LOG( + "Invalid combination of Cipher/Hash Algorithms for Kasumi"); + return CPA_STATUS_INVALID_PARAM; + } + + if (IS_EXT_ALG_CHAIN_UNSUPPORTED( + pCipherSetupData->cipherAlgorithm, + pHashSetupData->hashAlgorithm, + cyCapInfo.extAlgchainSupported)) { + LAC_UNSUPPORTED_PARAM_LOG( + "ExtAlgChain feature not supported"); + return CPA_STATUS_UNSUPPORTED; + } + + /* ensure both hash and cipher algorithms are Snow3G */ + if (((CPA_CY_SYM_CIPHER_SNOW3G_UEA2 == + pCipherSetupData->cipherAlgorithm) && + (CPA_CY_SYM_HASH_SNOW3G_UIA2 != + pHashSetupData->hashAlgorithm)) || + ((CPA_CY_SYM_HASH_SNOW3G_UIA2 == + pHashSetupData->hashAlgorithm) && + (CPA_CY_SYM_CIPHER_SNOW3G_UEA2 != + pCipherSetupData->cipherAlgorithm))) { + LAC_INVALID_PARAM_LOG( + "Invalid combination of Cipher/Hash Algorithms for Snow3G"); + return CPA_STATUS_INVALID_PARAM; + } + + /* ensure both hash and cipher algorithms are ZUC */ + if (((CPA_CY_SYM_CIPHER_ZUC_EEA3 == + pCipherSetupData->cipherAlgorithm) && + (CPA_CY_SYM_HASH_ZUC_EIA3 != + pHashSetupData->hashAlgorithm)) || + ((CPA_CY_SYM_HASH_ZUC_EIA3 == + pHashSetupData->hashAlgorithm) && + (CPA_CY_SYM_CIPHER_ZUC_EEA3 != + pCipherSetupData->cipherAlgorithm))) { + LAC_INVALID_PARAM_LOG( + "Invalid combination of Cipher/Hash Algorithms for ZUC"); + return CPA_STATUS_INVALID_PARAM; + } + } + /* not Algorithm Chaining so prevent CCM/GCM being selected */ + else if (CPA_CY_SYM_OP_CIPHER == pSessionSetupData->symOperation) { + /* ensure cipher algorithm is not CCM or GCM */ + if ((CPA_CY_SYM_CIPHER_AES_CCM == + pCipherSetupData->cipherAlgorithm) || + (CPA_CY_SYM_CIPHER_AES_GCM == + pCipherSetupData->cipherAlgorithm) || + (CPA_CY_SYM_CIPHER_CHACHA == + pCipherSetupData->cipherAlgorithm)) { + LAC_INVALID_PARAM_LOG( + "Invalid Cipher Algorithm for non-Algorithm " + "Chaining operation"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (CPA_CY_SYM_OP_HASH == pSessionSetupData->symOperation) { + /* ensure hash algorithm is not CCM or GCM/GMAC */ + if ((CPA_CY_SYM_HASH_AES_CCM == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_AES_GCM == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_AES_GMAC == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_POLY == pHashSetupData->hashAlgorithm)) { + LAC_INVALID_PARAM_LOG( + "Invalid Hash Algorithm for non-Algorithm Chaining operation"); + return CPA_STATUS_INVALID_PARAM; + } + } + /* Unsupported operation. Return error */ + else { + LAC_INVALID_PARAM_LOG("symOperation"); + return CPA_STATUS_INVALID_PARAM; + } + + /* ensure that cipher direction param is + * valid for cipher and algchain ops */ + if (CPA_CY_SYM_OP_HASH != pSessionSetupData->symOperation) { + if ((pCipherSetupData->cipherDirection != + CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT) && + (pCipherSetupData->cipherDirection != + CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT)) { + LAC_INVALID_PARAM_LOG("Invalid Cipher Direction"); + return CPA_STATUS_INVALID_PARAM; + } + } + + return CPA_STATUS_SUCCESS; +} + + +/** + * @ingroup LacSym + * Function which perform parameter checks on data buffers for symmetric + * crypto operations + * + * @param[in] pSrcBuffer Pointer to source buffer list + * @param[in] pDstBuffer Pointer to destination buffer list + * @param[in] pSessionDesc Pointer to session descriptor + * @param[in] pOpData Pointer to CryptoSymOpData. + * + * @retval CPA_STATUS_SUCCESS The operation succeeded + * @retval CPA_STATUS_INVALID_PARAM An invalid parameter value was found + */ + +static CpaStatus +LacSymPerform_BufferParamCheck(const CpaBufferList *const pSrcBuffer, + const CpaBufferList *const pDstBuffer, + const lac_session_desc_t *const pSessionDesc, + const CpaCySymOpData *const pOpData) +{ + Cpa64U srcBufferLen = 0, dstBufferLen = 0; + CpaStatus status = CPA_STATUS_SUCCESS; + + /* verify packet type is in correct range */ + switch (pOpData->packetType) { + case CPA_CY_SYM_PACKET_TYPE_FULL: + case CPA_CY_SYM_PACKET_TYPE_PARTIAL: + case CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL: + break; + default: { + LAC_INVALID_PARAM_LOG("packetType"); + return CPA_STATUS_INVALID_PARAM; + } + } + + if (!((CPA_CY_SYM_OP_CIPHER != pSessionDesc->symOperation && + CPA_CY_SYM_HASH_MODE_PLAIN == pSessionDesc->hashMode) && + (0 == pOpData->messageLenToHashInBytes))) { + if (IS_ZERO_LENGTH_BUFFER_SUPPORTED( + pSessionDesc->cipherAlgorithm, + pSessionDesc->hashAlgorithm)) { + status = LacBuffDesc_BufferListVerifyNull( + pSrcBuffer, &srcBufferLen, LAC_NO_ALIGNMENT_SHIFT); + } else { + status = LacBuffDesc_BufferListVerify( + pSrcBuffer, &srcBufferLen, LAC_NO_ALIGNMENT_SHIFT); + } + if (CPA_STATUS_SUCCESS != status) { + LAC_INVALID_PARAM_LOG("Source buffer invalid"); + return CPA_STATUS_INVALID_PARAM; + } + } else { + /* check MetaData !NULL */ + if (NULL == pSrcBuffer->pPrivateMetaData) { + LAC_INVALID_PARAM_LOG( + "Source buffer MetaData cannot be NULL"); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* out of place checks */ + if (pSrcBuffer != pDstBuffer) { + /* exception for this check is zero length hash requests to + * allow */ + /* for srcBufflen=DstBufferLen=0 */ + if (!((CPA_CY_SYM_OP_CIPHER != pSessionDesc->symOperation && + CPA_CY_SYM_HASH_MODE_PLAIN == pSessionDesc->hashMode) && + (0 == pOpData->messageLenToHashInBytes))) { + /* Verify buffer(s) for dest packet & return packet + * length */ + if (IS_ZERO_LENGTH_BUFFER_SUPPORTED( + pSessionDesc->cipherAlgorithm, + pSessionDesc->hashAlgorithm)) { + status = LacBuffDesc_BufferListVerifyNull( + pDstBuffer, + &dstBufferLen, + LAC_NO_ALIGNMENT_SHIFT); + } else { + status = LacBuffDesc_BufferListVerify( + pDstBuffer, + &dstBufferLen, + LAC_NO_ALIGNMENT_SHIFT); + } + if (CPA_STATUS_SUCCESS != status) { + LAC_INVALID_PARAM_LOG( + "Destination buffer invalid"); + return CPA_STATUS_INVALID_PARAM; + } + } else { + /* check MetaData !NULL */ + if (NULL == pDstBuffer->pPrivateMetaData) { + LAC_INVALID_PARAM_LOG( + "Dest buffer MetaData cannot be NULL"); + return CPA_STATUS_INVALID_PARAM; + } + } + /* Check that src Buffer and dst Buffer Lengths are equal */ + if (srcBufferLen != dstBufferLen) { + LAC_INVALID_PARAM_LOG( + "Source and Dest buffer lengths need to be equal "); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* check for partial packet suport for the session operation */ + if (CPA_CY_SYM_PACKET_TYPE_FULL != pOpData->packetType) { + if (CPA_FALSE == pSessionDesc->isPartialSupported) { + /* return out here to simplify cleanup */ + LAC_INVALID_PARAM_LOG( + "Partial packets not supported for operation"); + return CPA_STATUS_INVALID_PARAM; + } else { + /* This function checks to see if the partial packet + * sequence + * is correct */ + if (CPA_STATUS_SUCCESS != + LacSym_PartialPacketStateCheck( + pOpData->packetType, + pSessionDesc->partialState)) { + LAC_INVALID_PARAM_LOG("Partial packet Type"); + return CPA_STATUS_INVALID_PARAM; + } + } + } + return CPA_STATUS_SUCCESS; +} + +/** @ingroup LacSym */ +CpaStatus +cpaCySymInitSession(const CpaInstanceHandle instanceHandle_in, + const CpaCySymCbFunc pSymCb, + const CpaCySymSessionSetupData *pSessionSetupData, + CpaCySymSessionCtx pSessionCtx) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + CpaInstanceHandle instanceHandle = NULL; + sal_service_t *pService = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + + pService = (sal_service_t *)instanceHandle; + + /* check crypto service is running otherwise return an error */ + SAL_RUNNING_CHECK(pService); + + status = LacSym_InitSession(instanceHandle, + pSymCb, + pSessionSetupData, + CPA_FALSE, /* isDPSession */ + pSessionCtx); + + if (CPA_STATUS_SUCCESS == status) { + /* Increment the stats for a session registered successfully */ + LAC_SYM_STAT_INC(numSessionsInitialized, instanceHandle); + } else /* if there was an error */ + { + LAC_SYM_STAT_INC(numSessionErrors, instanceHandle); + } + + return status; +} + +CpaStatus +cpaCySymSessionInUse(CpaCySymSessionCtx pSessionCtx, CpaBoolean *pSessionInUse) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + lac_session_desc_t *pSessionDesc = NULL; + + LAC_CHECK_NULL_PARAM(pSessionInUse); + LAC_CHECK_INSTANCE_HANDLE(pSessionCtx); + + *pSessionInUse = CPA_FALSE; + + pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pSessionCtx); + + /* If there are pending requests */ + if (pSessionDesc->isDPSession) { + if (qatUtilsAtomicGet(&(pSessionDesc->u.pendingDpCbCount))) + *pSessionInUse = CPA_TRUE; + } else { + if (qatUtilsAtomicGet(&(pSessionDesc->u.pendingCbCount))) + *pSessionInUse = CPA_TRUE; + } + + return status; +} + +CpaStatus +LacSym_InitSession(const CpaInstanceHandle instanceHandle, + const CpaCySymCbFunc pSymCb, + const CpaCySymSessionSetupData *pSessionSetupData, + const CpaBoolean isDPSession, + CpaCySymSessionCtx pSessionCtx) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + lac_session_desc_t *pSessionDesc = NULL; + Cpa32U sessionCtxSizeInBytes = 0; + CpaPhysicalAddr physAddress = 0; + CpaPhysicalAddr physAddressAligned = 0; + sal_service_t *pService = NULL; + const CpaCySymCipherSetupData *pCipherSetupData = NULL; + const CpaCySymHashSetupData *pHashSetupData = NULL; + +/* Instance param checking done by calling function */ + + LAC_CHECK_NULL_PARAM(pSessionSetupData); + LAC_CHECK_NULL_PARAM(pSessionCtx); + status = LacSymSession_ParamCheck(instanceHandle, pSessionSetupData); + LAC_CHECK_STATUS(status); + + /* set the session priority for QAT AL*/ + if ((CPA_CY_PRIORITY_HIGH == pSessionSetupData->sessionPriority) || + (CPA_CY_PRIORITY_NORMAL == pSessionSetupData->sessionPriority)) { + // do nothing - clean up this code. use RANGE macro + } else { + LAC_INVALID_PARAM_LOG("sessionPriority"); + return CPA_STATUS_INVALID_PARAM; + } + + + pCipherSetupData = &pSessionSetupData->cipherSetupData; + pHashSetupData = &pSessionSetupData->hashSetupData; + + pService = (sal_service_t *)instanceHandle; + + /* Re-align the session structure to 64 byte alignment */ + physAddress = + LAC_OS_VIRT_TO_PHYS_EXTERNAL((*pService), + (Cpa8U *)pSessionCtx + sizeof(void *)); + + if (0 == physAddress) { + LAC_LOG_ERROR( + "Unable to get the physical address of the session"); + return CPA_STATUS_FAIL; + } + + physAddressAligned = + LAC_ALIGN_POW2_ROUNDUP(physAddress, LAC_64BYTE_ALIGNMENT); + + pSessionDesc = (lac_session_desc_t *) + /* Move the session pointer by the physical offset + between aligned and unaligned memory */ + ((Cpa8U *)pSessionCtx + sizeof(void *) + + (physAddressAligned - physAddress)); + + /* save the aligned pointer in the first bytes (size of unsigned long) + * of the session memory */ + *((LAC_ARCH_UINT *)pSessionCtx) = (LAC_ARCH_UINT)pSessionDesc; + + /* start off with a clean session */ + /* Choose Session Context size */ + getCtxSize(pSessionSetupData, &sessionCtxSizeInBytes); + switch (sessionCtxSizeInBytes) { + case LAC_SYM_SESSION_D1_SIZE: + memset(pSessionDesc, 0, sizeof(lac_session_desc_d1_t)); + break; + case LAC_SYM_SESSION_D2_SIZE: + memset(pSessionDesc, 0, sizeof(lac_session_desc_d2_t)); + break; + default: + memset(pSessionDesc, 0, sizeof(lac_session_desc_t)); + break; + } + + /* Setup content descriptor info structure + * assumption that content descriptor is the first field in + * in the session descriptor */ + pSessionDesc->contentDescInfo.pData = (Cpa8U *)pSessionDesc; + pSessionDesc->contentDescInfo.hardwareSetupBlockPhys = + physAddressAligned; + + pSessionDesc->contentDescOptimisedInfo.pData = + ((Cpa8U *)pSessionDesc + LAC_SYM_QAT_CONTENT_DESC_MAX_SIZE); + pSessionDesc->contentDescOptimisedInfo.hardwareSetupBlockPhys = + (physAddressAligned + LAC_SYM_QAT_CONTENT_DESC_MAX_SIZE); + + /* Set the Common Session Information */ + pSessionDesc->symOperation = pSessionSetupData->symOperation; + + if (CPA_FALSE == isDPSession) { + /* For asynchronous - use the user supplied callback + * for synchronous - use the internal synchronous callback */ + pSessionDesc->pSymCb = ((void *)NULL != (void *)pSymCb) ? + pSymCb : + LacSync_GenBufListVerifyCb; + } + + pSessionDesc->isDPSession = isDPSession; + if ((CPA_CY_SYM_HASH_AES_GCM == pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_AES_GMAC == pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_AES_CCM == pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_CIPHER_CHACHA == pCipherSetupData->cipherAlgorithm) || + (CPA_CY_SYM_CIPHER_ARC4 == pCipherSetupData->cipherAlgorithm)) { + pSessionDesc->writeRingMsgFunc = LacDp_WriteRingMsgFull; + } else { + pSessionDesc->writeRingMsgFunc = LacDp_WriteRingMsgOpt; + } + + if (CPA_STATUS_SUCCESS == status) { + /* Session set up via API call (not internal one) */ + /* Services such as DRBG call the crypto api as part of their + * service + * hence the need to for the flag, it is needed to distinguish + * between + * an internal and external session. + */ + pSessionDesc->internalSession = CPA_FALSE; + + status = LacAlgChain_SessionInit(instanceHandle, + pSessionSetupData, + pSessionDesc); + } + return status; +} + +/** @ingroup LacSym */ +CpaStatus +cpaCySymRemoveSession(const CpaInstanceHandle instanceHandle_in, + CpaCySymSessionCtx pSessionCtx) +{ + lac_session_desc_t *pSessionDesc = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + CpaInstanceHandle instanceHandle = NULL; + Cpa64U numPendingRequests = 0; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(pSessionCtx); + + /* check crypto service is running otherwise return an error */ + SAL_RUNNING_CHECK(instanceHandle); + pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pSessionCtx); + + LAC_CHECK_NULL_PARAM(pSessionDesc); + + if (CPA_TRUE == pSessionDesc->isDPSession) { + /* + * Based on one instance, we can initialize multiple sessions. + * For example, we can initialize the session "X" and session + * "Y" with + * the same instance "A". If there is no operation pending for + * session + * "X", we can remove the session "X". + * + * Now we only check the @pSessionDesc->pendingDpCbCount, if it + * becomes + * zero, we can remove the session. + * + * Why? + * (1) We increase it in the cpaCySymDpEnqueueOp/ + * cpaCySymDpEnqueueOpBatch. + * (2) We decrease it in the LacSymCb_ProcessCallback. + * + * If the @pSessionDesc->pendingDpCbCount becomes zero, it means + * there is no operation pending for the session "X" anymore, so + * we can + * remove this session. Maybe there is still some requests left + * in the + * instance's ring (icp_adf_queueDataToSend() returns true), but + * the + * request does not belong to "X", it belongs to session "Y". + */ + numPendingRequests = + qatUtilsAtomicGet(&(pSessionDesc->u.pendingDpCbCount)); + } else { + numPendingRequests = + qatUtilsAtomicGet(&(pSessionDesc->u.pendingCbCount)); + } + + /* If there are pending requests */ + if (0 != numPendingRequests) { + QAT_UTILS_LOG("There are %llu requests pending\n", + (unsigned long long)numPendingRequests); + status = CPA_STATUS_RETRY; + if (CPA_TRUE == pSessionDesc->isDPSession) { + /* Need to update tail if messages queue on tx hi ring + for + data plane api */ + icp_comms_trans_handle trans_handle = + ((sal_crypto_service_t *)instanceHandle) + ->trans_handle_sym_tx; + + if (CPA_TRUE == icp_adf_queueDataToSend(trans_handle)) { + /* process the remaining messages in the ring */ + QAT_UTILS_LOG("Submitting enqueued requests\n"); + /* + * SalQatMsg_updateQueueTail + */ + SalQatMsg_updateQueueTail(trans_handle); + return status; + } + } + } + if (CPA_STATUS_SUCCESS == status) { + if (CPA_STATUS_SUCCESS != + LAC_SPINLOCK_DESTROY(&pSessionDesc->requestQueueLock)) { + LAC_LOG_ERROR("Failed to destroy request queue lock"); + } + if (CPA_FALSE == pSessionDesc->isDPSession) { + LAC_SYM_STAT_INC(numSessionsRemoved, instanceHandle); + } + } else if (CPA_FALSE == pSessionDesc->isDPSession) { + LAC_SYM_STAT_INC(numSessionErrors, instanceHandle); + } + return status; +} + +/** @ingroup LacSym */ +static CpaStatus +LacSym_Perform(const CpaInstanceHandle instanceHandle, + void *callbackTag, + const CpaCySymOpData *pOpData, + const CpaBufferList *pSrcBuffer, + CpaBufferList *pDstBuffer, + CpaBoolean *pVerifyResult, + CpaBoolean isAsyncMode) +{ + lac_session_desc_t *pSessionDesc = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + /* check crypto service is running otherwise return an error */ + SAL_RUNNING_CHECK(instanceHandle); + LAC_CHECK_NULL_PARAM(pOpData); + LAC_CHECK_NULL_PARAM(pOpData->sessionCtx); + LAC_CHECK_NULL_PARAM(pSrcBuffer); + LAC_CHECK_NULL_PARAM(pDstBuffer); + + pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pOpData->sessionCtx); + LAC_CHECK_NULL_PARAM(pSessionDesc); + + /*check whether Payload size is zero for CHACHA-POLY*/ + if ((CPA_CY_SYM_CIPHER_CHACHA == pSessionDesc->cipherAlgorithm) && + (CPA_CY_SYM_HASH_POLY == pSessionDesc->hashAlgorithm) && + (CPA_CY_SYM_OP_ALGORITHM_CHAINING == pSessionDesc->symOperation)) { + if (!pOpData->messageLenToCipherInBytes) { + LAC_INVALID_PARAM_LOG( + "Invalid messageLenToCipherInBytes for CHACHA-POLY"); + return CPA_STATUS_INVALID_PARAM; + } + } + + + /* If synchronous Operation - Callback function stored in the session + * descriptor so a flag is set in the perform to indicate that + * the perform is being re-called for the synchronous operation */ + if ((LacSync_GenBufListVerifyCb == pSessionDesc->pSymCb) && + isAsyncMode == CPA_TRUE) { + CpaBoolean opResult = CPA_FALSE; + lac_sync_op_data_t *pSyncCallbackData = NULL; + + status = LacSync_CreateSyncCookie(&pSyncCallbackData); + + if (CPA_STATUS_SUCCESS == status) { + status = LacSym_Perform(instanceHandle, + pSyncCallbackData, + pOpData, + pSrcBuffer, + pDstBuffer, + pVerifyResult, + CPA_FALSE); + } else { + /* Failure allocating sync cookie */ + LAC_SYM_STAT_INC(numSymOpRequestErrors, instanceHandle); + return status; + } + + if (CPA_STATUS_SUCCESS == status) { + CpaStatus syncStatus = CPA_STATUS_SUCCESS; + syncStatus = LacSync_WaitForCallback( + pSyncCallbackData, + LAC_SYM_SYNC_CALLBACK_TIMEOUT, + &status, + &opResult); + /* If callback doesn't come back */ + if (CPA_STATUS_SUCCESS != syncStatus) { + LAC_SYM_STAT_INC(numSymOpCompletedErrors, + instanceHandle); + LAC_LOG_ERROR("Callback timed out"); + status = syncStatus; + } + } else { + /* As the Request was not sent the Callback will never + * be called, so need to indicate that we're finished + * with cookie so it can be destroyed. */ + LacSync_SetSyncCookieComplete(pSyncCallbackData); + } + + if (CPA_STATUS_SUCCESS == status) { + if (NULL != pVerifyResult) { + *pVerifyResult = opResult; + } + } + + LacSync_DestroySyncCookie(&pSyncCallbackData); + return status; + } + + status = + LacSymPerform_BufferParamCheck((const CpaBufferList *)pSrcBuffer, + pDstBuffer, + pSessionDesc, + pOpData); + LAC_CHECK_STATUS(status); + + if ((!pSessionDesc->digestIsAppended) && + (CPA_CY_SYM_OP_ALGORITHM_CHAINING == pSessionDesc->symOperation)) { + /* Check that pDigestResult is not NULL */ + LAC_CHECK_NULL_PARAM(pOpData->pDigestResult); + } + + status = LacAlgChain_Perform(instanceHandle, + pSessionDesc, + callbackTag, + pOpData, + pSrcBuffer, + pDstBuffer, + pVerifyResult); + + if (CPA_STATUS_SUCCESS == status) { + /* check for partial packet suport for the session operation */ + if (CPA_CY_SYM_PACKET_TYPE_FULL != pOpData->packetType) { + LacSym_PartialPacketStateUpdate( + pOpData->packetType, &pSessionDesc->partialState); + } + /* increment #requests stat */ + LAC_SYM_STAT_INC(numSymOpRequests, instanceHandle); + } + /* Retry also results in the errors stat been incremented */ + else { + /* increment #errors stat */ + LAC_SYM_STAT_INC(numSymOpRequestErrors, instanceHandle); + } + return status; +} + +/** @ingroup LacSym */ +CpaStatus +cpaCySymPerformOp(const CpaInstanceHandle instanceHandle_in, + void *callbackTag, + const CpaCySymOpData *pOpData, + const CpaBufferList *pSrcBuffer, + CpaBufferList *pDstBuffer, + CpaBoolean *pVerifyResult) +{ + CpaInstanceHandle instanceHandle = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + return LacSym_Perform(instanceHandle, + callbackTag, + pOpData, + pSrcBuffer, + pDstBuffer, + pVerifyResult, + CPA_TRUE); +} + +/** @ingroup LacSym */ +CpaStatus +cpaCySymQueryStats(const CpaInstanceHandle instanceHandle_in, + struct _CpaCySymStats *pSymStats) +{ + + CpaInstanceHandle instanceHandle = NULL; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(pSymStats); + + /* check if crypto service is running + * otherwise return an error */ + SAL_RUNNING_CHECK(instanceHandle); + + /* copy the fields from the internal structure into the api defined + * structure */ + LacSym_Stats32CopyGet(instanceHandle, pSymStats); + return CPA_STATUS_SUCCESS; +} + +/** @ingroup LacSym */ +CpaStatus +cpaCySymQueryStats64(const CpaInstanceHandle instanceHandle_in, + CpaCySymStats64 *pSymStats) +{ + + CpaInstanceHandle instanceHandle = NULL; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(pSymStats); + + /* check if crypto service is running + * otherwise return an error */ + SAL_RUNNING_CHECK(instanceHandle); + + /* copy the fields from the internal structure into the api defined + * structure */ + LacSym_Stats64CopyGet(instanceHandle, pSymStats); + + return CPA_STATUS_SUCCESS; +} + +/** @ingroup LacSym */ +CpaStatus +cpaCySymSessionCtxGetSize(const CpaInstanceHandle instanceHandle_in, + const CpaCySymSessionSetupData *pSessionSetupData, + Cpa32U *pSessionCtxSizeInBytes) +{ + CpaInstanceHandle instanceHandle = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(pSessionSetupData); + LAC_CHECK_NULL_PARAM(pSessionCtxSizeInBytes); + + /* check crypto service is running otherwise return an error */ + SAL_RUNNING_CHECK(instanceHandle); + *pSessionCtxSizeInBytes = LAC_SYM_SESSION_SIZE; + + return CPA_STATUS_SUCCESS; +} + +/** @ingroup LacSym */ +CpaStatus +cpaCySymSessionCtxGetDynamicSize( + const CpaInstanceHandle instanceHandle_in, + const CpaCySymSessionSetupData *pSessionSetupData, + Cpa32U *pSessionCtxSizeInBytes) +{ + CpaInstanceHandle instanceHandle = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(pSessionSetupData); + LAC_CHECK_NULL_PARAM(pSessionCtxSizeInBytes); + + /* check crypto service is running otherwise return an error */ + SAL_RUNNING_CHECK(instanceHandle); + /* Choose Session Context size */ + getCtxSize(pSessionSetupData, pSessionCtxSizeInBytes); + + + return CPA_STATUS_SUCCESS; +} + +void +getCtxSize(const CpaCySymSessionSetupData *pSessionSetupData, + Cpa32U *pSessionCtxSizeInBytes) +{ + /* using lac_session_desc_d1_t */ + if ((pSessionSetupData->cipherSetupData.cipherAlgorithm != + CPA_CY_SYM_CIPHER_ARC4) && + (pSessionSetupData->cipherSetupData.cipherAlgorithm != + CPA_CY_SYM_CIPHER_SNOW3G_UEA2) && + (pSessionSetupData->hashSetupData.hashAlgorithm != + CPA_CY_SYM_HASH_SNOW3G_UIA2) && + (pSessionSetupData->cipherSetupData.cipherAlgorithm != + CPA_CY_SYM_CIPHER_AES_CCM) && + (pSessionSetupData->cipherSetupData.cipherAlgorithm != + CPA_CY_SYM_CIPHER_AES_GCM) && + (pSessionSetupData->hashSetupData.hashMode != + CPA_CY_SYM_HASH_MODE_AUTH) && + (pSessionSetupData->hashSetupData.hashMode != + CPA_CY_SYM_HASH_MODE_NESTED) && + (pSessionSetupData->partialsNotRequired == CPA_TRUE)) { + *pSessionCtxSizeInBytes = LAC_SYM_SESSION_D1_SIZE; + } + /* using lac_session_desc_d2_t */ + else if (((pSessionSetupData->cipherSetupData.cipherAlgorithm == + CPA_CY_SYM_CIPHER_AES_CCM) || + (pSessionSetupData->cipherSetupData.cipherAlgorithm == + CPA_CY_SYM_CIPHER_AES_GCM)) && + (pSessionSetupData->partialsNotRequired == CPA_TRUE)) { + *pSessionCtxSizeInBytes = LAC_SYM_SESSION_D2_SIZE; + } + /* using lac_session_desc_t */ + else { + *pSessionCtxSizeInBytes = LAC_SYM_SESSION_SIZE; + } +} + +/** + ****************************************************************************** + * @ingroup LacSym + *****************************************************************************/ +CpaStatus +cpaCyBufferListGetMetaSize(const CpaInstanceHandle instanceHandle_in, + Cpa32U numBuffers, + Cpa32U *pSizeInBytes) +{ + + CpaInstanceHandle instanceHandle = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + instanceHandle = instanceHandle_in; + } + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(pSizeInBytes); + + /* In the case of zero buffers we still need to allocate one + * descriptor to pass to the firmware */ + if (0 == numBuffers) { + numBuffers = 1; + } + + /* Note: icp_buffer_list_desc_t is 8 bytes in size and + * icp_flat_buffer_desc_t is 16 bytes in size. Therefore if + * icp_buffer_list_desc_t is aligned + * so will each icp_flat_buffer_desc_t structure */ + + *pSizeInBytes = sizeof(icp_buffer_list_desc_t) + + (sizeof(icp_flat_buffer_desc_t) * numBuffers) + + ICP_DESCRIPTOR_ALIGNMENT_BYTES; + + + return CPA_STATUS_SUCCESS; +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_auth_enc.c b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_auth_enc.c new file mode 100644 index 000000000000..fe46b7eee3df --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_auth_enc.c @@ -0,0 +1,197 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_auth_enc.c + * + * @ingroup LacAuthEnc + * + * @description + * Authenticated encryption specific functionality. + * For CCM related code NIST SP 800-38C is followed. + * For GCM related code NIST SP 800-38D is followed. + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ + +#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 private header files +******************************************************************************* +*/ +#include "lac_log.h" +#include "lac_common.h" +#include "lac_session.h" +#include "lac_sym_auth_enc.h" + +/* These defines describe position of the flag fields + * in B0 block for CCM algorithm*/ +#define LAC_ALG_CHAIN_CCM_B0_FLAGS_ADATA_SHIFT 6 +#define LAC_ALG_CHAIN_CCM_B0_FLAGS_T_SHIFT 3 + +/* This macro builds flags field to be put in B0 block for CCM algorithm */ +#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)) + +/** + * @ingroup LacAuthEnc + */ +CpaStatus +LacSymAlgChain_CheckCCMData(Cpa8U *pAdditionalAuthData, + Cpa8U *pIv, + Cpa32U messageLenToCipherInBytes, + Cpa32U ivLenInBytes) +{ + Cpa8U q = 0; + + LAC_CHECK_NULL_PARAM(pIv); + LAC_CHECK_NULL_PARAM(pAdditionalAuthData); + + /* check if n is within permitted range */ + 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; + + /* Check if q is big enough to hold actual length of message to cipher + * if q = 8 -> maxlen = 2^64 always good as + * messageLenToCipherInBytes is 32 bits + * if q = 7 -> maxlen = 2^56 always good + * if q = 6 -> maxlen = 2^48 always good + * if q = 5 -> maxlen = 2^40 always good + * if q = 4 -> maxlen = 2^32 always good. + */ + 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; +} + + +/** + * @ingroup LacAuthEnc + */ +void +LacSymAlgChain_PrepareCCMData(lac_session_desc_t *pSessionDesc, + Cpa8U *pAdditionalAuthData, + Cpa8U *pIv, + Cpa32U messageLenToCipherInBytes, + Cpa32U ivLenInBytes) +{ + Cpa8U n = + ivLenInBytes; /* assumes ivLenInBytes has been param checked */ + Cpa8U q = LAC_ALG_CHAIN_CCM_NQ_CONST - n; + Cpa8U lenOfEncodedLen = 0; + Cpa16U lenAEncoded = 0; + Cpa32U bitStrQ = 0; + + /* populate Ctr0 block - stored in pIv */ + pIv[0] = (q - 1); + /* bytes 1 to n are already set with nonce by the user */ + /* set last q bytes with 0 */ + memset(pIv + n + 1, 0, q); + + /* Encode the length of associated data 'a'. As the API limits the + * length + * of an array pointed by pAdditionalAuthData to be 240 bytes max, the + * maximum length of 'a' might be 240 - 16 - 2 = 222. Hence the encoding + * below is simplified. */ + if (pSessionDesc->aadLenInBytes > 0) { + lenOfEncodedLen = sizeof(Cpa16U); + lenAEncoded = QAT_UTILS_HOST_TO_NW_16( + (Cpa16U)pSessionDesc->aadLenInBytes); + } + + /* populate B0 block */ + /* first, set the flags field */ + pAdditionalAuthData[0] = + LAC_ALG_CHAIN_CCM_BUILD_B0_FLAGS(lenOfEncodedLen, + pSessionDesc->hashResultSize, + q); + /* bytes 1 to n are already set with nonce by the user*/ + /* put Q in bytes 16-q...15 */ + 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); + } + + /* populate B1-Bn blocks */ + if (lenAEncoded > 0) { + *(Cpa16U + *)(&pAdditionalAuthData[1 + LAC_ALG_CHAIN_CCM_NQ_CONST]) = + lenAEncoded; + /* Next bytes are already set by the user with + * the associated data 'a' */ + + /* Check if padding is required */ + 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); + } + } +} + +/** + * @ingroup LacAuthEnc + */ +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); + } +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_cb.c b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_cb.c new file mode 100644 index 000000000000..8fa0a798304e --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_cb.c @@ -0,0 +1,545 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_cb.c Callback handler functions for symmetric components + * + * @ingroup LacSym + * + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ + +#include "cpa.h" +#include "cpa_cy_sym.h" + +#include "icp_accel_devices.h" +#include "icp_adf_init.h" +#include "icp_qat_fw_la.h" +#include "icp_adf_transport.h" +#include "icp_adf_debug.h" + +#include "lac_sym.h" +#include "lac_sym_cipher.h" +#include "lac_common.h" +#include "lac_list.h" +#include "lac_sal_types_crypto.h" +#include "lac_sal.h" +#include "lac_sal_ctrl.h" +#include "lac_session.h" +#include "lac_sym_stats.h" +#include "lac_log.h" +#include "lac_sym_cb.h" +#include "lac_sym_hash.h" +#include "lac_sym_qat_cipher.h" +#include "lac_sym_qat.h" + +#define DEQUEUE_MSGPUT_MAX_RETRIES 10000 + +/* +******************************************************************************* +* Define static function definitions +******************************************************************************* +*/ + +/** + ***************************************************************************** + * @ingroup LacSymCb + * Function to clean computed data. + * + * @description + * This function cleans GCM or CCM data in the case of a failure. + * + * @param[in] pSessionDesc pointer to the session descriptor + * @param[out] pBufferList pointer to the bufferlist to clean + * @param[in] pOpData pointer to operation data + * @param[in] isCCM is it a CCM operation boolean + * + * @return None + *****************************************************************************/ +static void +LacSymCb_CleanUserData(const lac_session_desc_t *pSessionDesc, + CpaBufferList *pBufferList, + const CpaCySymOpData *pOpData, + CpaBoolean isCCM) +{ + Cpa8U authTagLen = 0; + + /* Retrieve authTagLen */ + authTagLen = pSessionDesc->hashResultSize; + + /* Cleaning */ + if (isCCM) { + /* for CCM the digest is inside the buffer list */ + LacBuffDesc_BufferListZeroFromOffset( + pBufferList, + pOpData->cryptoStartSrcOffsetInBytes, + pOpData->messageLenToCipherInBytes + authTagLen); + } else { + /* clean buffer list */ + LacBuffDesc_BufferListZeroFromOffset( + pBufferList, + pOpData->cryptoStartSrcOffsetInBytes, + pOpData->messageLenToCipherInBytes); + } + if ((CPA_TRUE != pSessionDesc->digestIsAppended) && + (NULL != pOpData->pDigestResult)) { + /* clean digest */ + memset(pOpData->pDigestResult, 0, authTagLen); + } +} + +/** + ***************************************************************************** + * @ingroup LacSymCb + * Definition of callback function for processing symmetric responses + * + * @description + * This callback is invoked to process symmetric response messages from + * the QAT. It will extract some details from the message and invoke + * the user's callback to complete a symmetric operation. + * + * @param[in] pCookie Pointer to cookie associated with this request + * @param[in] qatRespStatusOkFlag Boolean indicating ok/fail status from QAT + * @param[in] status Status variable indicating an error occurred + * in sending the message (e.g. when dequeueing) + * @param[in] pSessionDesc Session descriptor + * + * @return None + *****************************************************************************/ +static void +LacSymCb_ProcessCallbackInternal(lac_sym_bulk_cookie_t *pCookie, + CpaBoolean qatRespStatusOkFlag, + CpaStatus status, + lac_session_desc_t *pSessionDesc) +{ + CpaCySymCbFunc pSymCb = NULL; + void *pCallbackTag = NULL; + CpaCySymOpData *pOpData = NULL; + CpaBufferList *pDstBuffer = NULL; + CpaCySymOp operationType = CPA_CY_SYM_OP_NONE; + CpaStatus dequeueStatus = CPA_STATUS_SUCCESS; + + CpaInstanceHandle instanceHandle = CPA_INSTANCE_HANDLE_SINGLE; + /* NOTE: cookie pointer validated in previous function */ + instanceHandle = pCookie->instanceHandle; + + pOpData = (CpaCySymOpData *)LAC_CONST_PTR_CAST(pCookie->pOpData); + operationType = pSessionDesc->symOperation; + + /* Set the destination pointer to the one supplied in the cookie. */ + pDstBuffer = pCookie->pDstBuffer; + + /* For a digest verify operation - for full packet and final partial + * only, perform a comparison with the digest generated and with the one + * supplied in the packet. */ + + if (((pSessionDesc->isSinglePass && + (CPA_CY_SYM_CIPHER_AES_GCM == pSessionDesc->cipherAlgorithm)) || + (CPA_CY_SYM_OP_CIPHER != operationType)) && + (CPA_TRUE == pSessionDesc->digestVerify) && + ((CPA_CY_SYM_PACKET_TYPE_FULL == pOpData->packetType) || + (CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL == pOpData->packetType))) { + if (CPA_FALSE == qatRespStatusOkFlag) { + LAC_SYM_STAT_INC(numSymOpVerifyFailures, + instanceHandle); + + /* The comparison has failed at this point (status is + * fail), + * need to clean any sensitive calculated data up to + * this point. + * The data calculated is no longer useful to the end + * result and + * does not need to be returned to the user so setting + * buffers to + * zero. + */ + if (pSessionDesc->cipherAlgorithm == + CPA_CY_SYM_CIPHER_AES_CCM) { + LacSymCb_CleanUserData(pSessionDesc, + pDstBuffer, + pOpData, + CPA_TRUE); + } else if (pSessionDesc->cipherAlgorithm == + CPA_CY_SYM_CIPHER_AES_GCM) { + LacSymCb_CleanUserData(pSessionDesc, + pDstBuffer, + pOpData, + CPA_FALSE); + } + } + } else { + /* Most commands have no point of failure and always return + * success. This is the default response from the QAT. + * If status is already set to an error value, don't overwrite + * it + */ + if ((CPA_STATUS_SUCCESS == status) && + (CPA_TRUE != qatRespStatusOkFlag)) { + LAC_LOG_ERROR("Response status value not as expected"); + status = CPA_STATUS_FAIL; + } + } + + pSymCb = pSessionDesc->pSymCb; + pCallbackTag = pCookie->pCallbackTag; + + /* State returned to the client for intermediate partials packets + * for hash only and cipher only partial packets. Cipher update + * allow next partial through */ + if (CPA_CY_SYM_PACKET_TYPE_PARTIAL == pOpData->packetType) { + if ((CPA_CY_SYM_OP_CIPHER == operationType) || + (CPA_CY_SYM_OP_ALGORITHM_CHAINING == operationType)) { + if (CPA_TRUE == pCookie->updateUserIvOnRecieve) { + /* Update the user's IV buffer + * Very important to do this BEFORE dequeuing + * subsequent partial requests, as the state + * buffer + * may get overwritten + */ + memcpy(pCookie->pOpData->pIv, + pSessionDesc->cipherPartialOpState, + pCookie->pOpData->ivLenInBytes); + } + if (CPA_TRUE == pCookie->updateKeySizeOnRecieve && + LAC_CIPHER_IS_XTS_MODE( + pSessionDesc->cipherAlgorithm)) { + LacSymQat_CipherXTSModeUpdateKeyLen( + pSessionDesc, + pSessionDesc->cipherKeyLenInBytes / 2); + } + } + } else if (CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL == pOpData->packetType) { + if ((CPA_CY_SYM_OP_CIPHER == operationType) || + (CPA_CY_SYM_OP_ALGORITHM_CHAINING == operationType)) { + if (CPA_TRUE == LAC_CIPHER_IS_XTS_MODE( + pSessionDesc->cipherAlgorithm)) { + /* + * For XTS mode, we replace the updated key with + * the original key - for subsequent partial + * requests + * + */ + LacSymQat_CipherXTSModeUpdateKeyLen( + pSessionDesc, + pSessionDesc->cipherKeyLenInBytes); + } + } + } + + if ((CPA_CY_SYM_PACKET_TYPE_FULL != pOpData->packetType) && + (qatRespStatusOkFlag != CPA_FALSE)) { + /* There may be requests blocked pending the completion of this + * operation + */ + + dequeueStatus = LacSymCb_PendingReqsDequeue(pSessionDesc); + if (CPA_STATUS_SUCCESS != dequeueStatus) { + LAC_SYM_STAT_INC(numSymOpCompletedErrors, + instanceHandle); + qatRespStatusOkFlag = CPA_FALSE; + if (CPA_STATUS_SUCCESS == status) { + status = dequeueStatus; + } + } + } + + if (CPA_STATUS_SUCCESS == status) { + /* update stats */ + if (pSessionDesc->internalSession == CPA_FALSE) { + LAC_SYM_STAT_INC(numSymOpCompleted, instanceHandle); + if (CPA_STATUS_SUCCESS != status) { + LAC_SYM_STAT_INC(numSymOpCompletedErrors, + instanceHandle); + } + } + } + + qatUtilsAtomicDec(&(pSessionDesc->u.pendingCbCount)); + + /* deallocate the memory for the internal callback cookie */ + Lac_MemPoolEntryFree(pCookie); + + /* user callback function is the last thing to be called */ + pSymCb(pCallbackTag, + status, + operationType, + pOpData, + pDstBuffer, + qatRespStatusOkFlag); +} + +/** + ****************************************************************************** + * @ingroup LacSymCb + * Definition of callback function for processing symmetric Data Plane + * responses + * + * @description + * This callback checks the status, decrements the number of operations + * pending and calls the user callback + * + * @param[in/out] pResponse pointer to the response structure + * @param[in] qatRespStatusOkFlag status + * @param[in] pSessionDesc pointer to the session descriptor + * + * @return None + ******************************************************************************/ +static void +LacSymCb_ProcessDpCallback(CpaCySymDpOpData *pResponse, + CpaBoolean qatRespStatusOkFlag, + lac_session_desc_t *pSessionDesc) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + /* For CCM and GCM, if qatRespStatusOkFlag is false, the data has to be + * cleaned as stated in RFC 3610; in DP mode, it is the user + * responsability + * to do so */ + + if (CPA_FALSE == pSessionDesc->isSinglePass) { + if ((CPA_CY_SYM_OP_CIPHER == pSessionDesc->symOperation) || + (CPA_FALSE == pSessionDesc->digestVerify)) { + /* If not doing digest compare and qatRespStatusOkFlag + != + CPA_TRUE + then there is something very wrong */ + if (CPA_FALSE == qatRespStatusOkFlag) { + LAC_LOG_ERROR( + "Response status value not as expected"); + status = CPA_STATUS_FAIL; + } + } + } + + ((sal_crypto_service_t *)pResponse->instanceHandle) + ->pSymDpCb(pResponse, status, qatRespStatusOkFlag); + /* + * Decrement the number of pending CB. + * + * If the @pendingDpCbCount becomes zero, we may remove the session, + * please + * read more information in the cpaCySymRemoveSession(). + * + * But there is a field in the @pResponse to store the session, + * the "sessionCtx". In another word, in the above @->pSymDpCb() + * callback, + * it may use the session again. If we decrease the @pendingDpCbCount + * before + * the @->pSymDpCb(), there is a _risk_ the @->pSymDpCb() may reference + * to + * a deleted session. + * + * So in order to avoid the risk, we decrease the @pendingDpCbCount + * after + * the @->pSymDpCb() callback. + */ + qatUtilsAtomicDec(&pSessionDesc->u.pendingDpCbCount); +} + +/** + ****************************************************************************** + * @ingroup LacSymCb + * Definition of callback function for processing symmetric responses + * + * @description + * This callback, which is registered with the common symmetric response + * message handler, is invoked to process symmetric response messages from + * the QAT. It will extract the response status from the cmnRespFlags set + * by the QAT, and then will pass it to @ref + * LacSymCb_ProcessCallbackInternal to complete the response processing. + * + * @param[in] lacCmdId ID of the symmetric QAT command of the request + * message + * @param[in] pOpaqueData pointer to opaque data in the request message + * @param[in] cmnRespFlags Flags set by QAT to indicate response status + * + * @return None + ******************************************************************************/ +static void +LacSymCb_ProcessCallback(icp_qat_fw_la_cmd_id_t lacCmdId, + void *pOpaqueData, + icp_qat_fw_comn_flags cmnRespFlags) +{ + CpaCySymDpOpData *pDpOpData = (CpaCySymDpOpData *)pOpaqueData; + lac_session_desc_t *pSessionDesc = + LAC_SYM_SESSION_DESC_FROM_CTX_GET(pDpOpData->sessionCtx); + CpaBoolean qatRespStatusOkFlag = + (CpaBoolean)(ICP_QAT_FW_COMN_STATUS_FLAG_OK == + ICP_QAT_FW_COMN_RESP_CRYPTO_STAT_GET(cmnRespFlags)); + + if (CPA_TRUE == pSessionDesc->isDPSession) { + /* DP session */ + LacSymCb_ProcessDpCallback(pDpOpData, + qatRespStatusOkFlag, + pSessionDesc); + } else { + /* Trad session */ + LacSymCb_ProcessCallbackInternal((lac_sym_bulk_cookie_t *) + pOpaqueData, + qatRespStatusOkFlag, + CPA_STATUS_SUCCESS, + pSessionDesc); + } +} + +/* +******************************************************************************* +* Define public/global function definitions +******************************************************************************* +*/ + +/** + * @ingroup LacSymCb + * + * @return CpaStatus + * value returned will be the result of icp_adf_transPutMsg + */ +CpaStatus +LacSymCb_PendingReqsDequeue(lac_session_desc_t *pSessionDesc) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_crypto_service_t *pService = NULL; + Cpa32U retries = 0; + + pService = (sal_crypto_service_t *)pSessionDesc->pInstance; + + /* Need to protect access to queue head and tail pointers, which may + * be accessed by multiple contexts simultaneously for enqueue and + * dequeue operations + */ + if (CPA_STATUS_SUCCESS != + LAC_SPINLOCK(&pSessionDesc->requestQueueLock)) { + LAC_LOG_ERROR("Failed to lock request queue"); + return CPA_STATUS_RESOURCE; + } + + /* Clear the blocking flag in the session descriptor */ + pSessionDesc->nonBlockingOpsInProgress = CPA_TRUE; + + while ((NULL != pSessionDesc->pRequestQueueHead) && + (CPA_TRUE == pSessionDesc->nonBlockingOpsInProgress)) { + + /* If we send a partial packet request, set the + * blockingOpsInProgress + * flag for the session to indicate that subsequent requests + * must be + * queued up until this request completes + */ + if (CPA_CY_SYM_PACKET_TYPE_FULL != + pSessionDesc->pRequestQueueHead->pOpData->packetType) { + pSessionDesc->nonBlockingOpsInProgress = CPA_FALSE; + } + + /* At this point, we're clear to send the request. For cipher + * requests, + * we need to check if the session IV needs to be updated. This + * can + * only be done when no other partials are in flight for this + * session, + * to ensure the cipherPartialOpState buffer in the session + * descriptor + * is not currently in use + */ + if (CPA_TRUE == + pSessionDesc->pRequestQueueHead->updateSessionIvOnSend) { + if (LAC_CIPHER_IS_ARC4(pSessionDesc->cipherAlgorithm)) { + memcpy(pSessionDesc->cipherPartialOpState, + pSessionDesc->cipherARC4InitialState, + LAC_CIPHER_ARC4_STATE_LEN_BYTES); + } else { + memcpy(pSessionDesc->cipherPartialOpState, + pSessionDesc->pRequestQueueHead->pOpData + ->pIv, + pSessionDesc->pRequestQueueHead->pOpData + ->ivLenInBytes); + } + } + + /* + * Now we'll attempt to send the message directly to QAT. We'll + * keep + * looing until it succeeds (or at least a very high number of + * retries), + * as the failure only happens when the ring is full, and this + * is only + * a temporary situation. After a few retries, space will become + * availble, allowing the putMsg to succeed. + */ + retries = 0; + do { + /* Send to QAT */ + status = icp_adf_transPutMsg( + pService->trans_handle_sym_tx, + (void *)&(pSessionDesc->pRequestQueueHead->qatMsg), + LAC_QAT_SYM_REQ_SZ_LW); + + retries++; + /* + * Yield to allow other threads that may be on this + * session to poll + * and make some space on the ring + */ + if (CPA_STATUS_SUCCESS != status) { + qatUtilsYield(); + } + } while ((CPA_STATUS_SUCCESS != status) && + (retries < DEQUEUE_MSGPUT_MAX_RETRIES)); + + if ((CPA_STATUS_SUCCESS != status) || + (retries >= DEQUEUE_MSGPUT_MAX_RETRIES)) { + LAC_LOG_ERROR( + "Failed to SalQatMsg_transPutMsg, maximum retries exceeded."); + goto cleanup; + } + + pSessionDesc->pRequestQueueHead = + pSessionDesc->pRequestQueueHead->pNext; + } + + /* If we've drained the queue, ensure the tail pointer is set to NULL */ + if (NULL == pSessionDesc->pRequestQueueHead) { + pSessionDesc->pRequestQueueTail = NULL; + } + +cleanup: + if (CPA_STATUS_SUCCESS != + LAC_SPINUNLOCK(&pSessionDesc->requestQueueLock)) { + LAC_LOG_ERROR("Failed to unlock request queue"); + } + return status; +} + +/** + * @ingroup LacSymCb + */ +void +LacSymCb_CallbacksRegister() +{ + /*** HASH ***/ + LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_AUTH, + LacSymCb_ProcessCallback); + + /*** ALGORITHM-CHAINING CIPHER_HASH***/ + LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_CIPHER_HASH, + LacSymCb_ProcessCallback); + + /*** ALGORITHM-CHAINING HASH_CIPHER***/ + LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_HASH_CIPHER, + LacSymCb_ProcessCallback); + + /*** CIPHER ***/ + LacSymQat_RespHandlerRegister(ICP_QAT_FW_LA_CMD_CIPHER, + LacSymCb_ProcessCallback); + + /* Call compile time param check function to ensure it is included + in the build by the compiler - this compile time check + ensures callbacks run as expected */ + LacSym_CompileTimeAssertions(); +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_cipher.c b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_cipher.c new file mode 100644 index 000000000000..0039c1f66884 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_cipher.c @@ -0,0 +1,416 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_cipher.c Cipher + * + * @ingroup LacCipher + * + * @description Functions specific to cipher + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ +#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 private header files +******************************************************************************* +*/ +#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" + +/* +******************************************************************************* +* Static Variables +******************************************************************************* +*/ + +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; + + /* Perform IV check. */ + if (LAC_CIPHER_IS_CTR_MODE(algorithm) || + LAC_CIPHER_IS_CBC_MODE(algorithm) || + LAC_CIPHER_IS_AES_F8(algorithm) || + LAC_CIPHER_IS_XTS_MODE(algorithm)) { + unsigned ivLenInBytes = + LacSymQat_CipherIvSizeBytesGet(algorithm); + LAC_CHECK_NULL_PARAM(pOpData->pIv); + if (pOpData->ivLenInBytes != ivLenInBytes) { + if (!(/* GCM with 12 byte IV is OK */ + (LAC_CIPHER_IS_GCM(algorithm) && + pOpData->ivLenInBytes == + LAC_CIPHER_IV_SIZE_GCM_12) || + /* IV len for CCM has been checked before */ + LAC_CIPHER_IS_CCM(algorithm))) { + LAC_INVALID_PARAM_LOG("invalid cipher IV size"); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* Always copy the user's IV into another cipher state buffer if + * the request is part of a partial packet sequence + * (ensures that pipelined partial requests use same + * buffer) + */ + if (ICP_QAT_FW_LA_PARTIAL_NONE == qatPacketType) { + /* Set the value of the ppIvBuffer to that supplied + * by the user. + * NOTE: There is no guarantee that this address is + * aligned on + * an 8 or 64 Byte address. */ + *ppIvBuffer = pOpData->pIv; + } else { + /* For partial packets, we use a per-session buffer to + * maintain + * the IV. This allows us to easily pass the updated IV + * forward + * to the next partial in the sequence. This makes + * internal + * buffering of partials easier to implement. + */ + *ppIvBuffer = pSessionDesc->cipherPartialOpState; + + /* Ensure that the user's IV buffer gets updated between + * partial + * requests so that they may also see the residue from + * the + * previous partial. Not needed for final partials + * though. + */ + 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) { + /* if the previous partial state was + * full, then this is + * the first partial in the sequence so + * we need to copy + * in the user's IV. But, we have to be + * very careful + * here not to overwrite the + * cipherPartialOpState just + * yet in case there's a previous + * partial sequence in + * flight, so we defer the copy for now. + * This will be + * completed in the + * LacSymQueue_RequestSend() function. + */ + pCbCookie->updateSessionIvOnSend = + CPA_TRUE; + } + /* For subsequent partials in a sequence, we'll + * re-use the + * IV that was written back by the QAT, using + * internal + * request queueing if necessary to ensure that + * the next + * partial request isn't issued to the QAT until + * the + * previous one completes + */ + } + } + } else if (LAC_CIPHER_IS_KASUMI(algorithm)) { + LAC_CHECK_NULL_PARAM(pOpData->pIv); + + if (LAC_CIPHER_IS_KASUMI(algorithm) && + (pOpData->ivLenInBytes != LAC_CIPHER_KASUMI_F8_IV_LENGTH)) { + LAC_INVALID_PARAM_LOG("invalid cipher IV size"); + return CPA_STATUS_INVALID_PARAM; + } + + + *ppIvBuffer = pOpData->pIv; + } else if (LAC_CIPHER_IS_SNOW3G_UEA2(algorithm)) { + LAC_CHECK_NULL_PARAM(pOpData->pIv); + if (LAC_CIPHER_IS_SNOW3G_UEA2(algorithm) && + (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; + } else if (LAC_CIPHER_IS_ARC4(algorithm)) { + if (ICP_QAT_FW_LA_PARTIAL_NONE == qatPacketType) { + /* For full packets, the initial ARC4 state is stored in + * the + * session descriptor. Use it directly. + */ + *ppIvBuffer = pSessionDesc->cipherARC4InitialState; + } else { + /* For partial packets, we maintain the running ARC4 + * state in + * dedicated buffer in the session descriptor + */ + *ppIvBuffer = pSessionDesc->cipherPartialOpState; + + if (ICP_QAT_FW_LA_PARTIAL_START == qatPacketType) { + /* if the previous partial state was full, then + * this is the + * first partial in the sequence so we need to + * (re-)initialise + * the contents of the state buffer using the + * initial state + * that is stored in the session descriptor. + * But, we have to be + * very careful here not to overwrite the + * cipherPartialOpState + * just yet in case there's a previous partial + * sequence in + * flight, so we defer the copy for now. This + * will be completed + * in the LacSymQueue_RequestSend() function + * when clear to send. + */ + pCbCookie->updateSessionIvOnSend = CPA_TRUE; + } + } + } else if (LAC_CIPHER_IS_ZUC_EEA3(algorithm)) { + 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; + } else { + *ppIvBuffer = NULL; + } + + return CPA_STATUS_SUCCESS; +} + + +CpaStatus +LacCipher_SessionSetupDataCheck(const CpaCySymCipherSetupData *pCipherSetupData) +{ + /* No key required for NULL algorithm */ + if (!LAC_CIPHER_IS_NULL(pCipherSetupData->cipherAlgorithm)) { + LAC_CHECK_NULL_PARAM(pCipherSetupData->pCipherKey); + + /* Check that algorithm and keys passed in are correct size */ + if (LAC_CIPHER_IS_ARC4(pCipherSetupData->cipherAlgorithm)) { + if (pCipherSetupData->cipherKeyLenInBytes > + ICP_QAT_HW_ARC4_KEY_SZ) { + LAC_INVALID_PARAM_LOG( + "Invalid ARC4 cipher key length"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (LAC_CIPHER_IS_CCM( + pCipherSetupData->cipherAlgorithm)) { + if (pCipherSetupData->cipherKeyLenInBytes != + ICP_QAT_HW_AES_128_KEY_SZ) { + LAC_INVALID_PARAM_LOG( + "Invalid AES CCM cipher key length"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (LAC_CIPHER_IS_XTS_MODE( + pCipherSetupData->cipherAlgorithm)) { + if ((pCipherSetupData->cipherKeyLenInBytes != + ICP_QAT_HW_AES_128_XTS_KEY_SZ) && + (pCipherSetupData->cipherKeyLenInBytes != + ICP_QAT_HW_AES_256_XTS_KEY_SZ)) { + LAC_INVALID_PARAM_LOG( + "Invalid AES XTS cipher key length"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (LAC_CIPHER_IS_AES( + pCipherSetupData->cipherAlgorithm)) { + 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; + } + } else if (LAC_CIPHER_IS_AES_F8( + pCipherSetupData->cipherAlgorithm)) { + 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; + } + } else if (LAC_CIPHER_IS_DES( + pCipherSetupData->cipherAlgorithm)) { + if (pCipherSetupData->cipherKeyLenInBytes != + ICP_QAT_HW_DES_KEY_SZ) { + LAC_INVALID_PARAM_LOG( + "Invalid DES cipher key length"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (LAC_CIPHER_IS_TRIPLE_DES( + pCipherSetupData->cipherAlgorithm)) { + if (pCipherSetupData->cipherKeyLenInBytes != + ICP_QAT_HW_3DES_KEY_SZ) { + LAC_INVALID_PARAM_LOG( + "Invalid Triple-DES cipher key length"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (LAC_CIPHER_IS_KASUMI( + pCipherSetupData->cipherAlgorithm)) { + /* QAT-FW only supports 128 bits Cipher Key size for + * Kasumi F8 + * Ref: 3GPP TS 55.216 V6.2.0 */ + if (pCipherSetupData->cipherKeyLenInBytes != + ICP_QAT_HW_KASUMI_KEY_SZ) { + LAC_INVALID_PARAM_LOG( + "Invalid Kasumi cipher key length"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (LAC_CIPHER_IS_SNOW3G_UEA2( + pCipherSetupData->cipherAlgorithm)) { + /* QAT-FW only supports 256 bits Cipher Key size for + * Snow_3G */ + 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; + } + } else if (LAC_CIPHER_IS_ZUC_EEA3( + pCipherSetupData->cipherAlgorithm)) { + /* 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; + } + } else if (LAC_CIPHER_IS_CHACHA( + pCipherSetupData->cipherAlgorithm)) { + if (pCipherSetupData->cipherKeyLenInBytes != + ICP_QAT_HW_CHACHAPOLY_KEY_SZ) { + LAC_INVALID_PARAM_LOG( + "Invalid CHACHAPOLY cipher key length"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (LAC_CIPHER_IS_SM4( + pCipherSetupData->cipherAlgorithm)) { + if (pCipherSetupData->cipherKeyLenInBytes != + ICP_QAT_HW_SM4_KEY_SZ) { + LAC_INVALID_PARAM_LOG( + "Invalid SM4 cipher key length"); + return CPA_STATUS_INVALID_PARAM; + } + } else { + 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; + + /* The following check will cover the dstBuffer as well, since + * the dstBuffer cannot be smaller than the srcBuffer (checked in + * LacSymPerform_BufferParamCheck() called from LacSym_Perform()) + */ + if ((pOpData->messageLenToCipherInBytes + + pOpData->cryptoStartSrcOffsetInBytes) > packetLen) { + LAC_INVALID_PARAM_LOG("cipher len + offset greater than " + "srcBuffer packet len"); + status = CPA_STATUS_INVALID_PARAM; + } + + if (CPA_STATUS_SUCCESS == status) { + /* + * XTS Mode allow for ciphers which are not multiples of + * the block size. + */ + /* Perform algorithm-specific checks */ + if (LAC_CIPHER_IS_XTS_MODE(algorithm) && + ((pOpData->packetType == CPA_CY_SYM_PACKET_TYPE_FULL) || + (pOpData->packetType == + CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL))) { + /* + * If this is the last of a partial request + */ + 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; + } + } else if (!(LAC_CIPHER_IS_ARC4(algorithm) || + LAC_CIPHER_IS_CTR_MODE(algorithm) || + LAC_CIPHER_IS_F8_MODE(algorithm) || + LAC_CIPHER_IS_SNOW3G_UEA2(algorithm) || + LAC_CIPHER_IS_XTS_MODE(algorithm) || + LAC_CIPHER_IS_CHACHA(algorithm) || + LAC_CIPHER_IS_ZUC_EEA3(algorithm))) { + /* Mask & check below is based on assumption that block + * size is + * a power of 2. If data size is not a multiple of the + * block size, + * the "remainder" bits selected by the mask be non-zero + */ + 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; +} + diff --git a/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_compile_check.c b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_compile_check.c new file mode 100644 index 000000000000..d732add29c76 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_compile_check.c @@ -0,0 +1,45 @@ +/*************************************************************************** + * + * <COPYRIGHT_TAG> + * + ***************************************************************************/ + +/** + *************************************************************************** + * @file lac_sym_compile_check.c + * + * @ingroup LacSym + * + * This file checks at compile time that some assumptions about the layout + * of key structures are as expected. + * + * + ***************************************************************************/ + +#include "cpa.h" + +#include "lac_common.h" +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" +#include "lac_sym.h" +#include "cpa_cy_sym_dp.h" + +#define COMPILE_TIME_ASSERT(pred) \ + switch (0) { \ + case 0: \ + case pred:; \ + } + +void +LacSym_CompileTimeAssertions(void) +{ + /* ************************************************************* + * Check sessionCtx is at the same location in bulk cookie and + * CpaCySymDpOpData. + * This is required for the callbacks to work as expected - + * see LacSymCb_ProcessCallback + * ************************************************************* */ + + COMPILE_TIME_ASSERT(offsetof(lac_sym_bulk_cookie_t, sessionCtx) == + offsetof(CpaCySymDpOpData, sessionCtx)); +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_dp.c b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_dp.c new file mode 100644 index 000000000000..4ccf1f7f82d5 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_dp.c @@ -0,0 +1,1080 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_dp.c + * Implementation of the symmetric data plane API + * + * @ingroup cpaCySymDp + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ + +#include "cpa.h" +#include "cpa_cy_sym.h" +#include "cpa_cy_sym_dp.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ + +#include "icp_accel_devices.h" +#include "icp_adf_init.h" +#include "icp_adf_transport.h" +#include "icp_adf_transport_dp.h" +#include "icp_adf_debug.h" +#include "icp_sal_poll.h" + +#include "qat_utils.h" + +#include "lac_mem.h" +#include "lac_log.h" +#include "lac_sym.h" +#include "lac_sym_qat_cipher.h" +#include "lac_list.h" +#include "lac_sal_types_crypto.h" +#include "sal_service_state.h" +#include "lac_sym_auth_enc.h" + +typedef void (*write_ringMsgFunc_t)(CpaCySymDpOpData *pRequest, + icp_qat_fw_la_bulk_req_t *pCurrentQatMsg); + +/** + ***************************************************************************** + * @ingroup cpaCySymDp + * Check that the operation data is valid + * + * @description + * Check that all the parameters defined in the operation data are valid + * + * @param[in] pRequest Pointer to an operation data for crypto + * data plane API + * + * @retval CPA_STATUS_SUCCESS Function executed successfully + * @retval CPA_STATUS_INVALID_PARAM Invalid parameter passed in + * + *****************************************************************************/ +static CpaStatus +LacDp_EnqueueParamCheck(const CpaCySymDpOpData *pRequest) +{ + lac_session_desc_t *pSessionDesc = NULL; + CpaCySymCipherAlgorithm cipher = 0; + CpaCySymHashAlgorithm hash = 0; + Cpa32U capabilitiesMask = 0; + + LAC_CHECK_NULL_PARAM(pRequest); + LAC_CHECK_NULL_PARAM(pRequest->instanceHandle); + LAC_CHECK_NULL_PARAM(pRequest->sessionCtx); + + /* Ensure this is a crypto instance */ + SAL_CHECK_INSTANCE_TYPE(pRequest->instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + + pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pRequest->sessionCtx); + if (NULL == pSessionDesc) { + do { + qatUtilsSleep(500); + pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET( + pRequest->sessionCtx); + } while (NULL == pSessionDesc); + } + if (NULL == pSessionDesc) { + LAC_INVALID_PARAM_LOG("Session context not as expected"); + return CPA_STATUS_INVALID_PARAM; + } + + if (CPA_FALSE == pSessionDesc->isDPSession) { + LAC_INVALID_PARAM_LOG( + "Session not initialised for data plane API"); + return CPA_STATUS_INVALID_PARAM; + } + + /*check whether Payload size is zero for CHACHA-POLY */ + if ((CPA_CY_SYM_CIPHER_CHACHA == pSessionDesc->cipherAlgorithm) && + (CPA_CY_SYM_HASH_POLY == pSessionDesc->hashAlgorithm) && + (CPA_CY_SYM_OP_ALGORITHM_CHAINING == pSessionDesc->symOperation)) { + if (!pRequest->messageLenToCipherInBytes) { + LAC_INVALID_PARAM_LOG( + "Invalid messageLenToCipherInBytes for CHACHA-POLY"); + return CPA_STATUS_INVALID_PARAM; + } + } + + if (0 == pRequest->srcBuffer) { + LAC_INVALID_PARAM_LOG("Invalid srcBuffer"); + return CPA_STATUS_INVALID_PARAM; + } + if (0 == pRequest->dstBuffer) { + LAC_INVALID_PARAM_LOG("Invalid destBuffer"); + return CPA_STATUS_INVALID_PARAM; + } + if (0 == pRequest->thisPhys) { + LAC_INVALID_PARAM_LOG("Invalid thisPhys"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Check that src buffer Len = dst buffer Len + Note this also checks that they are of the same type */ + if (pRequest->srcBufferLen != pRequest->dstBufferLen) { + LAC_INVALID_PARAM_LOG( + "Source and Destination buffer lengths need to be equal"); + return CPA_STATUS_INVALID_PARAM; + } + + /* digestVerify and digestIsAppended on Hash-Only operation not + * supported */ + if (pSessionDesc->digestIsAppended && pSessionDesc->digestVerify && + (CPA_CY_SYM_OP_HASH == pSessionDesc->symOperation)) { + LAC_INVALID_PARAM_LOG( + "digestVerify and digestIsAppended set " + "on Hash-Only operation is not supported"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Cipher specific tests */ + if (CPA_CY_SYM_OP_HASH != pSessionDesc->symOperation) { + /* Perform IV check */ + if ((LAC_CIPHER_IS_CTR_MODE(pSessionDesc->cipherAlgorithm) || + LAC_CIPHER_IS_CBC_MODE(pSessionDesc->cipherAlgorithm) || + LAC_CIPHER_IS_AES_F8(pSessionDesc->cipherAlgorithm)) && + (!(LAC_CIPHER_IS_CCM(pSessionDesc->cipherAlgorithm)))) { + Cpa32U ivLenInBytes = LacSymQat_CipherIvSizeBytesGet( + pSessionDesc->cipherAlgorithm); + if (pRequest->ivLenInBytes != ivLenInBytes) { + if (!(/* GCM with 12 byte IV is OK */ + (LAC_CIPHER_IS_GCM( + pSessionDesc->cipherAlgorithm) && + pRequest->ivLenInBytes == + LAC_CIPHER_IV_SIZE_GCM_12))) { + LAC_INVALID_PARAM_LOG( + "invalid cipher IV size"); + return CPA_STATUS_INVALID_PARAM; + } + } + if (0 == pRequest->iv) { + LAC_INVALID_PARAM_LOG("invalid iv of 0"); + return CPA_STATUS_INVALID_PARAM; + } + + /* pRequest->pIv is only used for CCM so is not checked + * here */ + } else if (LAC_CIPHER_IS_KASUMI( + pSessionDesc->cipherAlgorithm)) { + if (LAC_CIPHER_KASUMI_F8_IV_LENGTH != + pRequest->ivLenInBytes) { + LAC_INVALID_PARAM_LOG("invalid cipher IV size"); + return CPA_STATUS_INVALID_PARAM; + } + if (0 == pRequest->iv) { + LAC_INVALID_PARAM_LOG("invalid iv of 0"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (LAC_CIPHER_IS_SNOW3G_UEA2( + pSessionDesc->cipherAlgorithm)) { + if (ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ != + pRequest->ivLenInBytes) { + LAC_INVALID_PARAM_LOG("invalid cipher IV size"); + return CPA_STATUS_INVALID_PARAM; + } + if (0 == pRequest->iv) { + LAC_INVALID_PARAM_LOG("invalid iv of 0"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (LAC_CIPHER_IS_ZUC_EEA3( + pSessionDesc->cipherAlgorithm)) { + if (ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ != + pRequest->ivLenInBytes) { + LAC_INVALID_PARAM_LOG("invalid cipher IV size"); + return CPA_STATUS_INVALID_PARAM; + } + if (0 == pRequest->iv) { + LAC_INVALID_PARAM_LOG("invalid iv of 0"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (LAC_CIPHER_IS_CCM(pSessionDesc->cipherAlgorithm)) { + if (CPA_STATUS_SUCCESS != + LacSymAlgChain_CheckCCMData( + pRequest->pAdditionalAuthData, + pRequest->pIv, + pRequest->messageLenToCipherInBytes, + pRequest->ivLenInBytes)) { + return CPA_STATUS_INVALID_PARAM; + } + } + + /* Perform algorithm-specific checks */ + if (!(LAC_CIPHER_IS_ARC4(pSessionDesc->cipherAlgorithm) || + LAC_CIPHER_IS_CTR_MODE(pSessionDesc->cipherAlgorithm) || + LAC_CIPHER_IS_F8_MODE(pSessionDesc->cipherAlgorithm) || + LAC_CIPHER_IS_SNOW3G_UEA2( + pSessionDesc->cipherAlgorithm) || + LAC_CIPHER_IS_ZUC_EEA3(pSessionDesc->cipherAlgorithm))) { + /* Mask & check below is based on assumption that block + * size is + * a power of 2. If data size is not a multiple of the + * block size, + * the "remainder" bits selected by the mask be non-zero + */ + if (pRequest->messageLenToCipherInBytes & + (LacSymQat_CipherBlockSizeBytesGet( + pSessionDesc->cipherAlgorithm) - + 1)) { + LAC_INVALID_PARAM_LOG( + "Data size must be block size multiple"); + return CPA_STATUS_INVALID_PARAM; + } + } + + cipher = pSessionDesc->cipherAlgorithm; + hash = pSessionDesc->hashAlgorithm; + capabilitiesMask = + ((sal_crypto_service_t *)pRequest->instanceHandle) + ->generic_service_info.capabilitiesMask; + if (LAC_CIPHER_IS_SPC(cipher, hash, capabilitiesMask) && + (LAC_CIPHER_SPC_IV_SIZE == pRequest->ivLenInBytes)) { + /* For CHACHA and AES_GCM single pass there is an AAD + * buffer + * if aadLenInBytes is nonzero. AES_GMAC AAD is stored + * in + * source buffer, therefore there is no separate AAD + * buffer. */ + if ((0 != pSessionDesc->aadLenInBytes) && + (CPA_CY_SYM_HASH_AES_GMAC != + pSessionDesc->hashAlgorithm)) { + LAC_CHECK_NULL_PARAM( + pRequest->pAdditionalAuthData); + } + + /* Ensure AAD length for AES_GMAC spc */ + if ((CPA_CY_SYM_HASH_AES_GMAC == hash) && + (ICP_QAT_FW_SPC_AAD_SZ_MAX < + pRequest->messageLenToHashInBytes)) { + LAC_INVALID_PARAM_LOG( + "aadLenInBytes for AES_GMAC"); + return CPA_STATUS_INVALID_PARAM; + } + } + } + + /* Hash specific tests */ + if (CPA_CY_SYM_OP_CIPHER != pSessionDesc->symOperation) { + /* For CCM, snow3G and ZUC there is always an AAD buffer + For GCM there is an AAD buffer if aadLenInBytes is + nonzero */ + if ((CPA_CY_SYM_HASH_AES_CCM == pSessionDesc->hashAlgorithm) || + (CPA_CY_SYM_HASH_AES_GCM == pSessionDesc->hashAlgorithm && + (0 != pSessionDesc->aadLenInBytes))) { + LAC_CHECK_NULL_PARAM(pRequest->pAdditionalAuthData); + if (0 == pRequest->additionalAuthData) { + LAC_INVALID_PARAM_LOG( + "Invalid additionalAuthData"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == + pSessionDesc->hashAlgorithm || + CPA_CY_SYM_HASH_ZUC_EIA3 == + pSessionDesc->hashAlgorithm) { + if (0 == pRequest->additionalAuthData) { + LAC_INVALID_PARAM_LOG( + "Invalid additionalAuthData"); + return CPA_STATUS_INVALID_PARAM; + } + } + + if ((CPA_CY_SYM_HASH_AES_CCM != pSessionDesc->hashAlgorithm) && + (!pSessionDesc->digestIsAppended) && + (0 == pRequest->digestResult)) { + LAC_INVALID_PARAM_LOG("Invalid digestResult"); + return CPA_STATUS_INVALID_PARAM; + } + + if (CPA_CY_SYM_HASH_AES_CCM == pSessionDesc->hashAlgorithm) { + if ((pRequest->cryptoStartSrcOffsetInBytes + + pRequest->messageLenToCipherInBytes + + pSessionDesc->hashResultSize) > + pRequest->dstBufferLen) { + LAC_INVALID_PARAM_LOG( + "CCM - Not enough room for" + " digest in destination buffer"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (CPA_TRUE == pSessionDesc->digestIsAppended) { + if (CPA_CY_SYM_HASH_AES_GMAC == + pSessionDesc->hashAlgorithm) { + if ((pRequest->hashStartSrcOffsetInBytes + + pRequest->messageLenToHashInBytes + + pSessionDesc->hashResultSize) > + pRequest->dstBufferLen) { + LAC_INVALID_PARAM_LOG( + "Append Digest - Not enough room for" + " digest in destination buffer for " + "AES GMAC algorithm"); + return CPA_STATUS_INVALID_PARAM; + } + } + if (CPA_CY_SYM_HASH_AES_GCM == + pSessionDesc->hashAlgorithm) { + if ((pRequest->cryptoStartSrcOffsetInBytes + + pRequest->messageLenToCipherInBytes + + pSessionDesc->hashResultSize) > + pRequest->dstBufferLen) { + LAC_INVALID_PARAM_LOG( + "Append Digest - Not enough room " + "for digest in destination buffer" + " for GCM algorithm"); + return CPA_STATUS_INVALID_PARAM; + } + } + + if ((pRequest->hashStartSrcOffsetInBytes + + pRequest->messageLenToHashInBytes + + pSessionDesc->hashResultSize) > + pRequest->dstBufferLen) { + LAC_INVALID_PARAM_LOG( + "Append Digest - Not enough room for" + " digest in destination buffer"); + return CPA_STATUS_INVALID_PARAM; + } + } + if (CPA_CY_SYM_HASH_AES_GMAC == pSessionDesc->hashAlgorithm) { + if (pRequest->messageLenToHashInBytes == 0 || + pRequest->pAdditionalAuthData != NULL) { + LAC_INVALID_PARAM_LOG( + "For AES_GMAC, AAD Length " + "(messageLenToHashInBytes) must be " + "non zero and pAdditionalAuthData " + "must be NULL"); + return CPA_STATUS_INVALID_PARAM; + } + } + } + + if (CPA_DP_BUFLIST != pRequest->srcBufferLen) { + if ((CPA_CY_SYM_OP_HASH != pSessionDesc->symOperation) && + ((pRequest->messageLenToCipherInBytes + + pRequest->cryptoStartSrcOffsetInBytes) > + pRequest->srcBufferLen)) { + LAC_INVALID_PARAM_LOG( + "cipher len + offset greater than " + "srcBufferLen"); + return CPA_STATUS_INVALID_PARAM; + } else if ((CPA_CY_SYM_OP_CIPHER != + pSessionDesc->symOperation) && + (CPA_CY_SYM_HASH_AES_CCM != + pSessionDesc->hashAlgorithm) && + (CPA_CY_SYM_HASH_AES_GCM != + pSessionDesc->hashAlgorithm) && + (CPA_CY_SYM_HASH_AES_GMAC != + pSessionDesc->hashAlgorithm) && + ((pRequest->messageLenToHashInBytes + + pRequest->hashStartSrcOffsetInBytes) > + pRequest->srcBufferLen)) { + LAC_INVALID_PARAM_LOG( + "hash len + offset greater than srcBufferLen"); + return CPA_STATUS_INVALID_PARAM; + } + } else { + LAC_CHECK_8_BYTE_ALIGNMENT(pRequest->srcBuffer); + LAC_CHECK_8_BYTE_ALIGNMENT(pRequest->dstBuffer); + } + + LAC_CHECK_8_BYTE_ALIGNMENT(pRequest->thisPhys); + + return CPA_STATUS_SUCCESS; +} + +/** + ***************************************************************************** + * @ingroup cpaCySymDp + * Write Message on the ring and write request params + * This is the optimized version, which should not be used for + * algorithm of CCM, GCM and RC4 + * + * @description + * Write Message on the ring and write request params + * + * @param[in/out] pRequest Pointer to operation data for crypto + * data plane API + * @param[in/out] pCurrentQatMsg Pointer to ring memory where msg will + * be written + * + * @retval none + * + *****************************************************************************/ + +void +LacDp_WriteRingMsgOpt(CpaCySymDpOpData *pRequest, + icp_qat_fw_la_bulk_req_t *pCurrentQatMsg) +{ + lac_session_desc_t *pSessionDesc = + LAC_SYM_SESSION_DESC_FROM_CTX_GET(pRequest->sessionCtx); + Cpa8U *pMsgDummy = NULL; + Cpa8U *pCacheDummyHdr = NULL; + Cpa8U *pCacheDummyFtr = NULL; + + pMsgDummy = (Cpa8U *)pCurrentQatMsg; + /* Write Request */ + /* + * Fill in the header and footer bytes of the ET ring message - cached + * from + * the session descriptor. + */ + pCacheDummyHdr = (Cpa8U *)&(pSessionDesc->reqCacheHdr); + pCacheDummyFtr = (Cpa8U *)&(pSessionDesc->reqCacheFtr); + + memcpy(pMsgDummy, + pCacheDummyHdr, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)); + memset((pMsgDummy + + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)), + 0, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_TO_CLEAR_IN_LW)); + memcpy(pMsgDummy + + (LAC_LONG_WORD_IN_BYTES * LAC_START_OF_CACHE_FTR_IN_LW), + pCacheDummyFtr, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_FTR_IN_LW)); + + SalQatMsg_CmnMidWrite(pCurrentQatMsg, + pRequest, + (CPA_DP_BUFLIST == pRequest->srcBufferLen ? + QAT_COMN_PTR_TYPE_SGL : + QAT_COMN_PTR_TYPE_FLAT), + pRequest->srcBuffer, + pRequest->dstBuffer, + pRequest->srcBufferLen, + pRequest->dstBufferLen); + + /* Write Request Params */ + if (pSessionDesc->isCipher) { + + LacSymQat_CipherRequestParamsPopulate( + pCurrentQatMsg, + pRequest->cryptoStartSrcOffsetInBytes, + pRequest->messageLenToCipherInBytes, + pRequest->iv, + pRequest->pIv); + } + + if (pSessionDesc->isAuth) { + lac_sym_qat_hash_state_buffer_info_t *pHashStateBufferInfo = + &(pSessionDesc->hashStateBufferInfo); + icp_qat_fw_la_auth_req_params_t *pAuthReqPars = + (icp_qat_fw_la_auth_req_params_t + *)((Cpa8U *)&(pCurrentQatMsg->serv_specif_rqpars) + + ICP_QAT_FW_HASH_REQUEST_PARAMETERS_OFFSET); + + if ((CPA_CY_SYM_HASH_SNOW3G_UIA2 != + pSessionDesc->hashAlgorithm && + CPA_CY_SYM_HASH_AES_CCM != pSessionDesc->hashAlgorithm && + CPA_CY_SYM_HASH_AES_GCM != pSessionDesc->hashAlgorithm && + CPA_CY_SYM_HASH_AES_GMAC != pSessionDesc->hashAlgorithm && + CPA_CY_SYM_HASH_ZUC_EIA3 != pSessionDesc->hashAlgorithm) && + (pHashStateBufferInfo->prefixAadSzQuadWords > 0)) { + /* prefixAadSzQuadWords > 0 when there is prefix data + - i.e. nested hash or HMAC no precompute cases + Note partials not supported on DP api so we do not need + dynamic hash state in this case */ + pRequest->additionalAuthData = + pHashStateBufferInfo->pDataPhys + + LAC_QUADWORDS_TO_BYTES( + pHashStateBufferInfo->stateStorageSzQuadWords); + } + + /* The first 24 bytes in icp_qat_fw_la_auth_req_params_t can be + * copied directly from the op request data because they share a + * corresponding layout. The remaining 4 bytes are taken + * from the session message template and use values + * preconfigured at + * sessionInit (updated per request for some specific cases + * below) + */ + memcpy(pAuthReqPars, + (Cpa32U *)&(pRequest->hashStartSrcOffsetInBytes), + ((unsigned long)&(pAuthReqPars->u2.inner_prefix_sz) - + (unsigned long)pAuthReqPars)); + + if (CPA_TRUE == pSessionDesc->isAuthEncryptOp) { + pAuthReqPars->hash_state_sz = + LAC_BYTES_TO_QUADWORDS(pAuthReqPars->u2.aad_sz); + } else if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == + pSessionDesc->hashAlgorithm || + CPA_CY_SYM_HASH_ZUC_EIA3 == + pSessionDesc->hashAlgorithm) { + pAuthReqPars->hash_state_sz = + LAC_BYTES_TO_QUADWORDS(pSessionDesc->aadLenInBytes); + } + } + +} + +/** + ***************************************************************************** + * @ingroup cpaCySymDp + * Write Message on the ring and write request params + * + * @description + * Write Message on the ring and write request params + * + * @param[in/out] pRequest Pointer to operation data for crypto + * data plane API + * @param[in/out] pCurrentQatMsg Pointer to ring memory where msg will + * be written + * + * @retval none + * + *****************************************************************************/ + +void +LacDp_WriteRingMsgFull(CpaCySymDpOpData *pRequest, + icp_qat_fw_la_bulk_req_t *pCurrentQatMsg) +{ + lac_session_desc_t *pSessionDesc = + LAC_SYM_SESSION_DESC_FROM_CTX_GET(pRequest->sessionCtx); + Cpa8U *pMsgDummy = NULL; + Cpa8U *pCacheDummyHdr = NULL; + Cpa8U *pCacheDummyFtr = NULL; + sal_qat_content_desc_info_t *pCdInfo = NULL; + Cpa8U *pHwBlockBaseInDRAM = NULL; + Cpa32U hwBlockOffsetInDRAM = 0; + Cpa32U sizeInBytes = 0; + CpaCySymCipherAlgorithm cipher = pSessionDesc->cipherAlgorithm; + CpaCySymHashAlgorithm hash = pSessionDesc->hashAlgorithm; + Cpa32U capabilitiesMask = + ((sal_crypto_service_t *)pRequest->instanceHandle) + ->generic_service_info.capabilitiesMask; + + Cpa8U paddingLen = 0; + Cpa8U blockLen = 0; + + pMsgDummy = (Cpa8U *)pCurrentQatMsg; + /* Write Request */ + /* + * Fill in the header and footer bytes of the ET ring message - cached + * from + * the session descriptor. + */ + + if (!pSessionDesc->isSinglePass && + LAC_CIPHER_IS_SPC(cipher, hash, capabilitiesMask) && + (LAC_CIPHER_SPC_IV_SIZE == pRequest->ivLenInBytes)) { + pSessionDesc->isSinglePass = CPA_TRUE; + pSessionDesc->isCipher = CPA_TRUE; + pSessionDesc->isAuthEncryptOp = CPA_FALSE; + pSessionDesc->isAuth = CPA_FALSE; + pSessionDesc->symOperation = CPA_CY_SYM_OP_CIPHER; + pSessionDesc->laCmdId = ICP_QAT_FW_LA_CMD_CIPHER; + if (CPA_CY_SYM_HASH_AES_GMAC == pSessionDesc->hashAlgorithm) { + pSessionDesc->aadLenInBytes = + pRequest->messageLenToHashInBytes; + } + /* New bit position (13) for SINGLE PASS. + * The FW provides a specific macro to use to set the proto flag + */ + ICP_QAT_FW_LA_SINGLE_PASS_PROTO_FLAG_SET( + pSessionDesc->laCmdFlags, ICP_QAT_FW_LA_SINGLE_PASS_PROTO); + ICP_QAT_FW_LA_PROTO_SET(pSessionDesc->laCmdFlags, 0); + + pCdInfo = &(pSessionDesc->contentDescInfo); + pHwBlockBaseInDRAM = (Cpa8U *)pCdInfo->pData; + if (CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT == + pSessionDesc->cipherDirection) { + if (LAC_CIPHER_IS_GCM(cipher)) + hwBlockOffsetInDRAM = LAC_QUADWORDS_TO_BYTES( + LAC_SYM_QAT_CIPHER_OFFSET_IN_DRAM_GCM_SPC); + else + hwBlockOffsetInDRAM = LAC_QUADWORDS_TO_BYTES( + LAC_SYM_QAT_CIPHER_OFFSET_IN_DRAM_CHACHA_SPC); + } + /* construct cipherConfig in CD in DRAM */ + LacSymQat_CipherHwBlockPopulateCfgData(pSessionDesc, + pHwBlockBaseInDRAM + + hwBlockOffsetInDRAM, + &sizeInBytes); + SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)&( + pSessionDesc->reqSpcCacheHdr), + ICP_QAT_FW_COMN_REQ_CPM_FW_LA, + pSessionDesc->laCmdId, + pSessionDesc->cmnRequestFlags, + pSessionDesc->laCmdFlags); + } else if (CPA_CY_SYM_HASH_AES_GMAC == pSessionDesc->hashAlgorithm) { + pSessionDesc->aadLenInBytes = pRequest->messageLenToHashInBytes; + } + if (pSessionDesc->isSinglePass) { + pCacheDummyHdr = (Cpa8U *)&(pSessionDesc->reqSpcCacheHdr); + pCacheDummyFtr = (Cpa8U *)&(pSessionDesc->reqSpcCacheFtr); + } else { + if (!pSessionDesc->useSymConstantsTable) { + pCacheDummyHdr = (Cpa8U *)&(pSessionDesc->reqCacheHdr); + pCacheDummyFtr = (Cpa8U *)&(pSessionDesc->reqCacheFtr); + } else { + pCacheDummyHdr = + (Cpa8U *)&(pSessionDesc->shramReqCacheHdr); + pCacheDummyFtr = + (Cpa8U *)&(pSessionDesc->shramReqCacheFtr); + } + } + memcpy(pMsgDummy, + pCacheDummyHdr, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)); + memset((pMsgDummy + + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_HDR_IN_LW)), + 0, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_TO_CLEAR_IN_LW)); + memcpy(pMsgDummy + + (LAC_LONG_WORD_IN_BYTES * LAC_START_OF_CACHE_FTR_IN_LW), + pCacheDummyFtr, + (LAC_LONG_WORD_IN_BYTES * LAC_SIZE_OF_CACHE_FTR_IN_LW)); + + SalQatMsg_CmnMidWrite(pCurrentQatMsg, + pRequest, + (CPA_DP_BUFLIST == pRequest->srcBufferLen ? + QAT_COMN_PTR_TYPE_SGL : + QAT_COMN_PTR_TYPE_FLAT), + pRequest->srcBuffer, + pRequest->dstBuffer, + pRequest->srcBufferLen, + pRequest->dstBufferLen); + + if (CPA_CY_SYM_HASH_AES_CCM == pSessionDesc->hashAlgorithm && + pSessionDesc->isAuth == CPA_TRUE) { + /* prepare IV and AAD for CCM */ + LacSymAlgChain_PrepareCCMData( + pSessionDesc, + pRequest->pAdditionalAuthData, + pRequest->pIv, + pRequest->messageLenToCipherInBytes, + pRequest->ivLenInBytes); + + /* According to the API, for CCM and GCM, + * messageLenToHashInBytes + * and hashStartSrcOffsetInBytes are not initialized by the + * user and must be set by the driver + */ + pRequest->hashStartSrcOffsetInBytes = + pRequest->cryptoStartSrcOffsetInBytes; + pRequest->messageLenToHashInBytes = + pRequest->messageLenToCipherInBytes; + } else if (!pSessionDesc->isSinglePass && + (CPA_CY_SYM_HASH_AES_GCM == pSessionDesc->hashAlgorithm || + CPA_CY_SYM_HASH_AES_GMAC == pSessionDesc->hashAlgorithm)) { + /* GCM case */ + if (CPA_CY_SYM_HASH_AES_GMAC != pSessionDesc->hashAlgorithm) { + /* According to the API, for CCM and GCM, + * messageLenToHashInBytes and hashStartSrcOffsetInBytes + * are not initialized by the user and must be set + * by the driver + */ + pRequest->hashStartSrcOffsetInBytes = + pRequest->cryptoStartSrcOffsetInBytes; + pRequest->messageLenToHashInBytes = + pRequest->messageLenToCipherInBytes; + + LacSymAlgChain_PrepareGCMData( + pSessionDesc, pRequest->pAdditionalAuthData); + } + + if (LAC_CIPHER_IV_SIZE_GCM_12 == pRequest->ivLenInBytes) { + ICP_QAT_FW_LA_GCM_IV_LEN_FLAG_SET( + pCurrentQatMsg->comn_hdr.serv_specif_flags, + ICP_QAT_FW_LA_GCM_IV_LEN_12_OCTETS); + } + } + + /* Write Request Params */ + if (pSessionDesc->isCipher) { + if (CPA_CY_SYM_CIPHER_ARC4 == pSessionDesc->cipherAlgorithm) { + /* ARC4 does not have an IV but the field is used to + * store the + * initial state */ + pRequest->iv = + pSessionDesc->cipherARC4InitialStatePhysAddr; + } + + LacSymQat_CipherRequestParamsPopulate( + pCurrentQatMsg, + pRequest->cryptoStartSrcOffsetInBytes, + pRequest->messageLenToCipherInBytes, + pRequest->iv, + pRequest->pIv); + if (pSessionDesc->isSinglePass) { + icp_qat_fw_la_cipher_req_params_t *pCipherReqParams = + (icp_qat_fw_la_cipher_req_params_t + *)((Cpa8U *)&( + pCurrentQatMsg->serv_specif_rqpars) + + ICP_QAT_FW_CIPHER_REQUEST_PARAMETERS_OFFSET); + + pCipherReqParams->spc_aad_addr = + (uint64_t)pRequest->additionalAuthData; + pCipherReqParams->spc_aad_sz = + pSessionDesc->aadLenInBytes; + + pCipherReqParams->spc_auth_res_addr = + (uint64_t)pRequest->digestResult; + pCipherReqParams->spc_auth_res_sz = + pSessionDesc->hashResultSize; + + /* For CHACHA and AES_GCM single pass AAD buffer needs + * alignment + * if aadLenInBytes is nonzero. + * In case of AES-GMAC, AAD buffer passed in the src + * buffer. + */ + if (0 != pSessionDesc->aadLenInBytes && + CPA_CY_SYM_HASH_AES_GMAC != + pSessionDesc->hashAlgorithm) { + blockLen = LacSymQat_CipherBlockSizeBytesGet( + pSessionDesc->cipherAlgorithm); + if ((pSessionDesc->aadLenInBytes % blockLen) != + 0) { + paddingLen = blockLen - + (pSessionDesc->aadLenInBytes % + blockLen); + memset( + &pRequest->pAdditionalAuthData + [pSessionDesc->aadLenInBytes], + 0, + paddingLen); + } + } + } + } + + if (pSessionDesc->isAuth) { + lac_sym_qat_hash_state_buffer_info_t *pHashStateBufferInfo = + &(pSessionDesc->hashStateBufferInfo); + icp_qat_fw_la_auth_req_params_t *pAuthReqPars = + (icp_qat_fw_la_auth_req_params_t + *)((Cpa8U *)&(pCurrentQatMsg->serv_specif_rqpars) + + ICP_QAT_FW_HASH_REQUEST_PARAMETERS_OFFSET); + + if ((CPA_CY_SYM_HASH_SNOW3G_UIA2 != + pSessionDesc->hashAlgorithm && + CPA_CY_SYM_HASH_AES_CCM != pSessionDesc->hashAlgorithm && + CPA_CY_SYM_HASH_AES_GCM != pSessionDesc->hashAlgorithm && + CPA_CY_SYM_HASH_AES_GMAC != pSessionDesc->hashAlgorithm && + CPA_CY_SYM_HASH_ZUC_EIA3 != pSessionDesc->hashAlgorithm) && + (pHashStateBufferInfo->prefixAadSzQuadWords > 0)) { + /* prefixAadSzQuadWords > 0 when there is prefix data + - i.e. nested hash or HMAC no precompute cases + Note partials not supported on DP api so we do not need + dynamic hash state in this case */ + pRequest->additionalAuthData = + pHashStateBufferInfo->pDataPhys + + LAC_QUADWORDS_TO_BYTES( + pHashStateBufferInfo->stateStorageSzQuadWords); + } + + /* The first 24 bytes in icp_qat_fw_la_auth_req_params_t can be + * copied directly from the op request data because they share a + * corresponding layout. The remaining 4 bytes are taken + * from the session message template and use values + * preconfigured at + * sessionInit (updated per request for some specific cases + * below) + */ + + /* We force a specific compiler optimisation here. The length + * to + * be copied turns out to be always 16, and by coding a memcpy + * with + * a literal value the compiler will compile inline code (in + * fact, + * only two vector instructions) to effect the copy. This gives + * us + * a huge performance increase. + */ + unsigned long cplen = + (unsigned long)&(pAuthReqPars->u2.inner_prefix_sz) - + (unsigned long)pAuthReqPars; + if (cplen == 16) + memcpy(pAuthReqPars, + (Cpa32U *)&(pRequest->hashStartSrcOffsetInBytes), + 16); + else + memcpy(pAuthReqPars, + (Cpa32U *)&(pRequest->hashStartSrcOffsetInBytes), + cplen); + + if (CPA_TRUE == pSessionDesc->isAuthEncryptOp) { + pAuthReqPars->hash_state_sz = + LAC_BYTES_TO_QUADWORDS(pAuthReqPars->u2.aad_sz); + } else if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == + pSessionDesc->hashAlgorithm || + CPA_CY_SYM_HASH_ZUC_EIA3 == + pSessionDesc->hashAlgorithm) { + pAuthReqPars->hash_state_sz = + LAC_BYTES_TO_QUADWORDS(pSessionDesc->aadLenInBytes); + } + } + +} + +CpaStatus +cpaCySymDpSessionCtxGetSize(const CpaInstanceHandle instanceHandle, + const CpaCySymSessionSetupData *pSessionSetupData, + Cpa32U *pSessionCtxSizeInBytes) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + /* CPA_INSTANCE_HANDLE_SINGLE is not supported on DP apis */ + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + /* All other param checks are common with trad api */ + /* Check for valid pointers */ + LAC_CHECK_NULL_PARAM(pSessionCtxSizeInBytes); + status = cpaCySymSessionCtxGetSize(instanceHandle, + pSessionSetupData, + pSessionCtxSizeInBytes); + + return status; +} + +CpaStatus +cpaCySymDpSessionCtxGetDynamicSize( + const CpaInstanceHandle instanceHandle, + const CpaCySymSessionSetupData *pSessionSetupData, + Cpa32U *pSessionCtxSizeInBytes) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + /* CPA_INSTANCE_HANDLE_SINGLE is not supported on DP apis */ + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + /* All other param checks are common with trad api */ + /* Check for valid pointers */ + LAC_CHECK_NULL_PARAM(pSessionCtxSizeInBytes); + status = cpaCySymSessionCtxGetDynamicSize(instanceHandle, + pSessionSetupData, + pSessionCtxSizeInBytes); + + return status; +} + +/** @ingroup cpaCySymDp */ +CpaStatus +cpaCySymDpInitSession(CpaInstanceHandle instanceHandle, + const CpaCySymSessionSetupData *pSessionSetupData, + CpaCySymDpSessionCtx sessionCtx) +{ + CpaStatus status = CPA_STATUS_FAIL; + sal_service_t *pService = NULL; + + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(pSessionSetupData); + pService = (sal_service_t *)instanceHandle; + + /* Check crypto service is running otherwise return an error */ + SAL_RUNNING_CHECK(pService); + + status = LacSym_InitSession(instanceHandle, + NULL, /* Callback */ + pSessionSetupData, + CPA_TRUE, /* isDPSession */ + sessionCtx); + return status; +} + +CpaStatus +cpaCySymDpRemoveSession(const CpaInstanceHandle instanceHandle, + CpaCySymDpSessionCtx sessionCtx) +{ + + /* CPA_INSTANCE_HANDLE_SINGLE is not supported on DP apis */ + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); +/* All other param checks are common with trad api */ + + return cpaCySymRemoveSession(instanceHandle, sessionCtx); +} + +CpaStatus +cpaCySymDpRegCbFunc(const CpaInstanceHandle instanceHandle, + const CpaCySymDpCbFunc pSymDpCb) +{ + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(pSymDpCb); + SAL_RUNNING_CHECK(instanceHandle); + pService->pSymDpCb = pSymDpCb; + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaCySymDpEnqueueOp(CpaCySymDpOpData *pRequest, const CpaBoolean performOpNow) +{ + icp_qat_fw_la_bulk_req_t *pCurrentQatMsg = NULL; + icp_comms_trans_handle trans_handle = NULL; + lac_session_desc_t *pSessionDesc = NULL; + write_ringMsgFunc_t callFunc; + + CpaStatus status = CPA_STATUS_SUCCESS; + + + LAC_CHECK_NULL_PARAM(pRequest); + status = LacDp_EnqueueParamCheck(pRequest); + if (CPA_STATUS_SUCCESS != status) { + return status; + } + + trans_handle = ((sal_crypto_service_t *)pRequest->instanceHandle) + ->trans_handle_sym_tx; + + pSessionDesc = LAC_SYM_SESSION_DESC_FROM_CTX_GET(pRequest->sessionCtx); + icp_adf_getSingleQueueAddr(trans_handle, (void **)&pCurrentQatMsg); + if (NULL == pCurrentQatMsg) { + /* + * No space is available on the queue. + */ + return CPA_STATUS_RETRY; + } + + callFunc = (write_ringMsgFunc_t)pSessionDesc->writeRingMsgFunc; + + LAC_CHECK_NULL_PARAM(callFunc); + + callFunc(pRequest, pCurrentQatMsg); + + qatUtilsAtomicInc(&(pSessionDesc->u.pendingDpCbCount)); + + if (CPA_TRUE == performOpNow) { + SalQatMsg_updateQueueTail(trans_handle); + } + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaCySymDpPerformOpNow(const CpaInstanceHandle instanceHandle) +{ + icp_comms_trans_handle trans_handle = NULL; + + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + + /* Check if SAL is initialised otherwise return an error */ + SAL_RUNNING_CHECK(instanceHandle); + + trans_handle = + ((sal_crypto_service_t *)instanceHandle)->trans_handle_sym_tx; + + if (CPA_TRUE == icp_adf_queueDataToSend(trans_handle)) { + SalQatMsg_updateQueueTail(trans_handle); + } + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaCySymDpEnqueueOpBatch(const Cpa32U numberRequests, + CpaCySymDpOpData *pRequests[], + const CpaBoolean performOpNow) +{ + icp_qat_fw_la_bulk_req_t *pCurrentQatMsg = NULL; + icp_comms_trans_handle trans_handle = NULL; + lac_session_desc_t *pSessionDesc = NULL; + write_ringMsgFunc_t callFunc; + Cpa32U i = 0; + + CpaStatus status = CPA_STATUS_SUCCESS; + sal_crypto_service_t *pService = NULL; + + + LAC_CHECK_NULL_PARAM(pRequests); + LAC_CHECK_NULL_PARAM(pRequests[0]); + LAC_CHECK_NULL_PARAM(pRequests[0]->instanceHandle); + + pService = (sal_crypto_service_t *)(pRequests[0]->instanceHandle); + + if ((0 == numberRequests) || + (numberRequests > pService->maxNumSymReqBatch)) { + LAC_INVALID_PARAM_LOG1( + "The number of requests needs to be between 1 " + "and %d", + pService->maxNumSymReqBatch); + return CPA_STATUS_INVALID_PARAM; + } + + for (i = 0; i < numberRequests; i++) { + status = LacDp_EnqueueParamCheck(pRequests[i]); + if (CPA_STATUS_SUCCESS != status) { + return status; + } + + /* Check that all instance handles are the same */ + if (pRequests[i]->instanceHandle != + pRequests[0]->instanceHandle) { + LAC_INVALID_PARAM_LOG( + "All instance handles should be the same " + "in the requests"); + return CPA_STATUS_INVALID_PARAM; + } + } + + trans_handle = ((sal_crypto_service_t *)pRequests[0]->instanceHandle) + ->trans_handle_sym_tx; + pSessionDesc = + LAC_SYM_SESSION_DESC_FROM_CTX_GET(pRequests[0]->sessionCtx); + icp_adf_getQueueMemory(trans_handle, + numberRequests, + (void **)&pCurrentQatMsg); + if (NULL == pCurrentQatMsg) { + /* + * No space is available on the queue. + */ + return CPA_STATUS_RETRY; + } + + for (i = 0; i < numberRequests; i++) { + pSessionDesc = + LAC_SYM_SESSION_DESC_FROM_CTX_GET(pRequests[i]->sessionCtx); + callFunc = (write_ringMsgFunc_t)pSessionDesc->writeRingMsgFunc; + callFunc(pRequests[i], pCurrentQatMsg); + icp_adf_getQueueNext(trans_handle, (void **)&pCurrentQatMsg); + qatUtilsAtomicAdd(1, &(pSessionDesc->u.pendingDpCbCount)); + } + + if (CPA_TRUE == performOpNow) { + SalQatMsg_updateQueueTail(trans_handle); + } + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +icp_sal_CyPollDpInstance(const CpaInstanceHandle instanceHandle, + const Cpa32U responseQuota) +{ + icp_comms_trans_handle trans_handle = NULL; + + LAC_CHECK_INSTANCE_HANDLE(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + + /* Check if SAL is initialised otherwise return an error */ + SAL_RUNNING_CHECK(instanceHandle); + + trans_handle = + ((sal_crypto_service_t *)instanceHandle)->trans_handle_sym_rx; + + return icp_adf_pollQueue(trans_handle, responseQuota); +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_hash.c b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_hash.c new file mode 100644 index 000000000000..e662d0d6d220 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_hash.c @@ -0,0 +1,783 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_hash.c + * + * @ingroup LacHash + * + * Hash specific functionality + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ + +#include "cpa.h" +#include "cpa_cy_sym.h" + +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ + +#include "lac_common.h" +#include "lac_mem.h" +#include "lac_sym.h" +#include "lac_session.h" +#include "lac_sym_hash.h" +#include "lac_log.h" +#include "lac_sym_qat_hash.h" +#include "lac_sym_qat_hash_defs_lookup.h" +#include "lac_sym_cb.h" +#include "lac_sync.h" + +#define LAC_HASH_ALG_MODE_NOT_SUPPORTED(alg, mode) \ + ((((CPA_CY_SYM_HASH_KASUMI_F9 == (alg)) || \ + (CPA_CY_SYM_HASH_SNOW3G_UIA2 == (alg)) || \ + (CPA_CY_SYM_HASH_AES_XCBC == (alg)) || \ + (CPA_CY_SYM_HASH_AES_CCM == (alg)) || \ + (CPA_CY_SYM_HASH_AES_GCM == (alg)) || \ + (CPA_CY_SYM_HASH_AES_GMAC == (alg)) || \ + (CPA_CY_SYM_HASH_AES_CMAC == (alg)) || \ + (CPA_CY_SYM_HASH_ZUC_EIA3 == (alg))) && \ + (CPA_CY_SYM_HASH_MODE_AUTH != (mode))) || \ + (((CPA_CY_SYM_HASH_SHA3_224 == (alg)) || \ + (CPA_CY_SYM_HASH_SHA3_256 == (alg)) || \ + (CPA_CY_SYM_HASH_SHA3_384 == (alg)) || \ + (CPA_CY_SYM_HASH_SHA3_512 == (alg))) && \ + (CPA_CY_SYM_HASH_MODE_NESTED == (mode))) || \ + (((CPA_CY_SYM_HASH_SHAKE_128 == (alg)) || \ + (CPA_CY_SYM_HASH_SHAKE_256 == (alg))) && \ + (CPA_CY_SYM_HASH_MODE_AUTH == (mode)))) + +/**< Macro to check for valid algorithm-mode combination */ + +/** + * @ingroup LacHash + * This callback function will be invoked whenever a synchronous + * hash precompute operation completes. It will set the wait + * queue flag for the synchronous operation. + * + * @param[in] pCallbackTag Opaque value provided by user. This will + * be a pointer to a wait queue flag. + * + * @retval + * None + * + */ +static void +LacHash_SyncPrecomputeDoneCb(void *pCallbackTag) +{ + LacSync_GenWakeupSyncCaller(pCallbackTag, CPA_STATUS_SUCCESS); +} + +/** @ingroup LacHash */ +CpaStatus +LacHash_StatePrefixAadBufferInit( + sal_service_t *pService, + const CpaCySymHashSetupData *pHashSetupData, + icp_qat_la_bulk_req_ftr_t *pReq, + icp_qat_hw_auth_mode_t qatHashMode, + Cpa8U *pHashStateBuffer, + lac_sym_qat_hash_state_buffer_info_t *pHashStateBufferInfo) +{ + /* set up the hash state prefix buffer info structure */ + pHashStateBufferInfo->pData = pHashStateBuffer; + + pHashStateBufferInfo->pDataPhys = LAC_MEM_CAST_PTR_TO_UINT64( + LAC_OS_VIRT_TO_PHYS_EXTERNAL((*pService), pHashStateBuffer)); + + if (pHashStateBufferInfo->pDataPhys == 0) { + LAC_LOG_ERROR("Unable to get the physical address of " + "the hash state buffer"); + return CPA_STATUS_FAIL; + } + + LacSymQat_HashStatePrefixAadBufferSizeGet(pReq, pHashStateBufferInfo); + + /* Prefix data gets copied to the hash state buffer for nested mode */ + if (CPA_CY_SYM_HASH_MODE_NESTED == pHashSetupData->hashMode) { + LacSymQat_HashStatePrefixAadBufferPopulate( + pHashStateBufferInfo, + pReq, + pHashSetupData->nestedModeSetupData.pInnerPrefixData, + pHashSetupData->nestedModeSetupData.innerPrefixLenInBytes, + pHashSetupData->nestedModeSetupData.pOuterPrefixData, + pHashSetupData->nestedModeSetupData.outerPrefixLenInBytes); + } + /* For mode2 HMAC the key gets copied into both the inner and + * outer prefix fields */ + else if (IS_HASH_MODE_2_AUTH(qatHashMode, pHashSetupData->hashMode)) { + LacSymQat_HashStatePrefixAadBufferPopulate( + pHashStateBufferInfo, + pReq, + pHashSetupData->authModeSetupData.authKey, + pHashSetupData->authModeSetupData.authKeyLenInBytes, + pHashSetupData->authModeSetupData.authKey, + pHashSetupData->authModeSetupData.authKeyLenInBytes); + } + /* else do nothing for the other cases */ + return CPA_STATUS_SUCCESS; +} + +/** @ingroup LacHash */ +CpaStatus +LacHash_PrecomputeDataCreate(const CpaInstanceHandle instanceHandle, + CpaCySymSessionSetupData *pSessionSetup, + lac_hash_precompute_done_cb_t callbackFn, + void *pCallbackTag, + Cpa8U *pWorkingBuffer, + Cpa8U *pState1, + Cpa8U *pState2) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + Cpa8U *pAuthKey = NULL; + Cpa32U authKeyLenInBytes = 0; + CpaCySymHashAlgorithm hashAlgorithm = + pSessionSetup->hashSetupData.hashAlgorithm; + CpaCySymHashAuthModeSetupData *pAuthModeSetupData = + &pSessionSetup->hashSetupData.authModeSetupData; + + /* synchronous operation */ + if (NULL == callbackFn) { + lac_sync_op_data_t *pSyncCallbackData = NULL; + + status = LacSync_CreateSyncCookie(&pSyncCallbackData); + + if (CPA_STATUS_SUCCESS == status) { + status = LacHash_PrecomputeDataCreate( + instanceHandle, + pSessionSetup, + LacHash_SyncPrecomputeDoneCb, + /* wait queue condition from sync cookie */ + pSyncCallbackData, + pWorkingBuffer, + pState1, + pState2); + } else { + return status; + } + + if (CPA_STATUS_SUCCESS == status) { + CpaStatus syncStatus = CPA_STATUS_SUCCESS; + + syncStatus = LacSync_WaitForCallback( + pSyncCallbackData, + LAC_SYM_SYNC_CALLBACK_TIMEOUT, + &status, + NULL); + + /* If callback doesn't come back */ + if (CPA_STATUS_SUCCESS != syncStatus) { + QAT_UTILS_LOG( + "callback functions for precomputes did not return\n"); + status = syncStatus; + } + } else { + /* As the Request was not sent the Callback will never + * be called, so need to indicate that we're finished + * with cookie so it can be destroyed. */ + LacSync_SetSyncCookieComplete(pSyncCallbackData); + } + LacSync_DestroySyncCookie(&pSyncCallbackData); + + return status; + } + + /* set up convenience pointers */ + pAuthKey = pAuthModeSetupData->authKey; + authKeyLenInBytes = pAuthModeSetupData->authKeyLenInBytes; + + /* Pre-compute data state pointers must already be set up + * by LacSymQat_HashSetupBlockInit() + */ + + /* state1 is not allocated for AES XCBC/CCM/GCM/Kasumi/UIA2 + * so for these algorithms set state2 only */ + if (CPA_CY_SYM_HASH_AES_XCBC == hashAlgorithm) { + status = LacSymHash_AesECBPreCompute(instanceHandle, + hashAlgorithm, + authKeyLenInBytes, + pAuthKey, + pWorkingBuffer, + pState2, + callbackFn, + pCallbackTag); + } else if (CPA_CY_SYM_HASH_AES_CMAC == hashAlgorithm) { + /* First, copy the original key to pState2 */ + memcpy(pState2, pAuthKey, authKeyLenInBytes); + /* Then precompute */ + status = LacSymHash_AesECBPreCompute(instanceHandle, + hashAlgorithm, + authKeyLenInBytes, + pAuthKey, + pWorkingBuffer, + pState2, + callbackFn, + pCallbackTag); + } else if (CPA_CY_SYM_HASH_AES_CCM == hashAlgorithm) { + /* + * The Inner Hash Initial State2 block must contain K + * (the cipher key) and 16 zeroes which will be replaced with + * EK(Ctr0) by the QAT-ME. + */ + + /* write the auth key which for CCM is equivalent to cipher key + */ + memcpy(pState2, + pSessionSetup->cipherSetupData.pCipherKey, + pSessionSetup->cipherSetupData.cipherKeyLenInBytes); + + /* initialize remaining buffer space to all zeroes */ + LAC_OS_BZERO( + pState2 + + pSessionSetup->cipherSetupData.cipherKeyLenInBytes, + ICP_QAT_HW_AES_CCM_CBC_E_CTR0_SZ); + + /* There is no request sent to the QAT for this operation, + * so just invoke the user's callback directly to signal + * completion of the precompute + */ + callbackFn(pCallbackTag); + } else if (CPA_CY_SYM_HASH_AES_GCM == hashAlgorithm || + CPA_CY_SYM_HASH_AES_GMAC == hashAlgorithm) { + /* + * The Inner Hash Initial State2 block contains the following + * H (the Galois Hash Multiplier) + * len(A) (the length of A), (length before padding) + * 16 zeroes which will be replaced with EK(Ctr0) by the + * QAT. + */ + + /* Memset state2 to 0 */ + LAC_OS_BZERO(pState2, + ICP_QAT_HW_GALOIS_H_SZ + + ICP_QAT_HW_GALOIS_LEN_A_SZ + + ICP_QAT_HW_GALOIS_E_CTR0_SZ); + + /* write H (the Galois Hash Multiplier) where H = E(K, 0...0) + * This will only write bytes 0-15 of pState2 + */ + status = LacSymHash_AesECBPreCompute( + instanceHandle, + hashAlgorithm, + pSessionSetup->cipherSetupData.cipherKeyLenInBytes, + pSessionSetup->cipherSetupData.pCipherKey, + pWorkingBuffer, + pState2, + callbackFn, + pCallbackTag); + + if (CPA_STATUS_SUCCESS == status) { + /* write len(A) (the length of A) into bytes 16-19 of + * pState2 + * in big-endian format. This field is 8 bytes */ + *(Cpa32U *)&pState2[ICP_QAT_HW_GALOIS_H_SZ] = + LAC_MEM_WR_32(pAuthModeSetupData->aadLenInBytes); + } + } else if (CPA_CY_SYM_HASH_KASUMI_F9 == hashAlgorithm) { + Cpa32U wordIndex = 0; + Cpa32U *pTempKey = (Cpa32U *)(pState2 + authKeyLenInBytes); + /* + * The Inner Hash Initial State2 block must contain IK + * (Initialisation Key), followed by IK XOR-ed with KM + * (Key Modifier): IK||(IK^KM). + */ + + /* write the auth key */ + memcpy(pState2, pAuthKey, authKeyLenInBytes); + /* initialise temp key with auth key */ + memcpy(pTempKey, pAuthKey, authKeyLenInBytes); + + /* XOR Key with KASUMI F9 key modifier at 4 bytes level */ + for (wordIndex = 0; + wordIndex < LAC_BYTES_TO_LONGWORDS(authKeyLenInBytes); + wordIndex++) { + pTempKey[wordIndex] ^= + LAC_HASH_KASUMI_F9_KEY_MODIFIER_4_BYTES; + } + /* There is no request sent to the QAT for this operation, + * so just invoke the user's callback directly to signal + * completion of the precompute + */ + callbackFn(pCallbackTag); + } else if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == hashAlgorithm) { + /* + * The Inner Hash Initial State2 should be all zeros + */ + LAC_OS_BZERO(pState2, ICP_QAT_HW_SNOW_3G_UIA2_STATE2_SZ); + + /* There is no request sent to the QAT for this operation, + * so just invoke the user's callback directly to signal + * completion of the precompute + */ + callbackFn(pCallbackTag); + } else if (CPA_CY_SYM_HASH_ZUC_EIA3 == hashAlgorithm) { + /* + * The Inner Hash Initial State2 should contain the key + * and zero the rest of the state. + */ + LAC_OS_BZERO(pState2, ICP_QAT_HW_ZUC_3G_EIA3_STATE2_SZ); + memcpy(pState2, pAuthKey, authKeyLenInBytes); + + /* There is no request sent to the QAT for this operation, + * so just invoke the user's callback directly to signal + * completion of the precompute + */ + callbackFn(pCallbackTag); + } else if (CPA_CY_SYM_HASH_POLY == hashAlgorithm) { + /* There is no request sent to the QAT for this operation, + * so just invoke the user's callback directly to signal + * completion of the precompute + */ + callbackFn(pCallbackTag); + } else /* For Hmac Precomputes */ + { + status = LacSymHash_HmacPreComputes(instanceHandle, + hashAlgorithm, + authKeyLenInBytes, + pAuthKey, + pWorkingBuffer, + pState1, + pState2, + callbackFn, + pCallbackTag); + } + + return status; +} + + +/** @ingroup LacHash */ +CpaStatus +LacHash_HashContextCheck(CpaInstanceHandle instanceHandle, + const CpaCySymHashSetupData *pHashSetupData) +{ + lac_sym_qat_hash_alg_info_t *pHashAlgInfo = NULL; + lac_sym_qat_hash_alg_info_t *pOuterHashAlgInfo = NULL; + CpaCySymCapabilitiesInfo capInfo; + + /*Protect against value of hash outside the bitmap*/ + if ((pHashSetupData->hashAlgorithm) >= + CPA_CY_SYM_HASH_CAP_BITMAP_SIZE) { + LAC_INVALID_PARAM_LOG("hashAlgorithm"); + return CPA_STATUS_INVALID_PARAM; + } + cpaCySymQueryCapabilities(instanceHandle, &capInfo); + if (!CPA_BITMAP_BIT_TEST(capInfo.hashes, + pHashSetupData->hashAlgorithm) && + pHashSetupData->hashAlgorithm != CPA_CY_SYM_HASH_AES_CBC_MAC) { + /* Ensure SHAKE algorithms are not supported */ + if ((CPA_CY_SYM_HASH_SHAKE_128 == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_SHAKE_256 == + pHashSetupData->hashAlgorithm)) { + LAC_INVALID_PARAM_LOG( + "Hash algorithms SHAKE-128 and SHAKE-256 " + "are not supported."); + return CPA_STATUS_UNSUPPORTED; + } + + LAC_INVALID_PARAM_LOG("hashAlgorithm"); + return CPA_STATUS_INVALID_PARAM; + } + + switch (pHashSetupData->hashMode) { + case CPA_CY_SYM_HASH_MODE_PLAIN: + case CPA_CY_SYM_HASH_MODE_AUTH: + case CPA_CY_SYM_HASH_MODE_NESTED: + break; + + default: { + LAC_INVALID_PARAM_LOG("hashMode"); + return CPA_STATUS_INVALID_PARAM; + } + } + + if (LAC_HASH_ALG_MODE_NOT_SUPPORTED(pHashSetupData->hashAlgorithm, + pHashSetupData->hashMode)) { + LAC_INVALID_PARAM_LOG("hashAlgorithm and hashMode combination"); + return CPA_STATUS_INVALID_PARAM; + } + + LacSymQat_HashAlgLookupGet(instanceHandle, + pHashSetupData->hashAlgorithm, + &pHashAlgInfo); + + /* note: nested hash mode checks digest length against outer algorithm + */ + if ((CPA_CY_SYM_HASH_MODE_PLAIN == pHashSetupData->hashMode) || + (CPA_CY_SYM_HASH_MODE_AUTH == pHashSetupData->hashMode)) { + /* Check Digest Length is permitted by the algorithm */ + if ((0 == pHashSetupData->digestResultLenInBytes) || + (pHashSetupData->digestResultLenInBytes > + pHashAlgInfo->digestLength)) { + LAC_INVALID_PARAM_LOG("digestResultLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } + + if (CPA_CY_SYM_HASH_MODE_AUTH == pHashSetupData->hashMode) { + if (CPA_CY_SYM_HASH_AES_GCM == pHashSetupData->hashAlgorithm || + CPA_CY_SYM_HASH_AES_GMAC == pHashSetupData->hashAlgorithm) { + Cpa32U aadDataSize = 0; + + /* RFC 4106: Implementations MUST support a full-length + * 16-octet + * ICV, and MAY support 8 or 12 octet ICVs, and MUST NOT + * support + * other ICV lengths. */ + if ((pHashSetupData->digestResultLenInBytes != + LAC_HASH_AES_GCM_ICV_SIZE_8) && + (pHashSetupData->digestResultLenInBytes != + LAC_HASH_AES_GCM_ICV_SIZE_12) && + (pHashSetupData->digestResultLenInBytes != + LAC_HASH_AES_GCM_ICV_SIZE_16)) { + LAC_INVALID_PARAM_LOG("digestResultLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + + /* ensure aadLen is within maximum limit imposed by QAT + */ + aadDataSize = + pHashSetupData->authModeSetupData.aadLenInBytes; + + /* round the aad size to the multiple of GCM hash block + * size. */ + aadDataSize = + LAC_ALIGN_POW2_ROUNDUP(aadDataSize, + LAC_HASH_AES_GCM_BLOCK_SIZE); + + if (aadDataSize > ICP_QAT_FW_CCM_GCM_AAD_SZ_MAX && + CPA_CY_SYM_HASH_AES_GMAC != + pHashSetupData->hashAlgorithm) { + LAC_INVALID_PARAM_LOG("aadLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (CPA_CY_SYM_HASH_AES_CCM == + pHashSetupData->hashAlgorithm) { + Cpa32U aadDataSize = 0; + + /* RFC 3610: Valid values are 4, 6, 8, 10, 12, 14, and + * 16 octets */ + if ((pHashSetupData->digestResultLenInBytes >= + LAC_HASH_AES_CCM_ICV_SIZE_MIN) && + (pHashSetupData->digestResultLenInBytes <= + LAC_HASH_AES_CCM_ICV_SIZE_MAX)) { + if ((pHashSetupData->digestResultLenInBytes & + 0x01) != 0) { + LAC_INVALID_PARAM_LOG( + "digestResultLenInBytes must be a multiple of 2"); + return CPA_STATUS_INVALID_PARAM; + } + } else { + LAC_INVALID_PARAM_LOG("digestResultLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + + /* ensure aadLen is within maximum limit imposed by QAT + */ + /* at the beginning of the buffer there is B0 block */ + aadDataSize = LAC_HASH_AES_CCM_BLOCK_SIZE; + + /* then, if there is some 'a' data, the buffer will + * store encoded + * length of 'a' and 'a' itself */ + if (pHashSetupData->authModeSetupData.aadLenInBytes > + 0) { + /* as the QAT API puts the requirement on the + * pAdditionalAuthData not to be bigger than 240 + * bytes then we + * just need 2 bytes to store encoded length of + * 'a' */ + aadDataSize += sizeof(Cpa16U); + aadDataSize += pHashSetupData->authModeSetupData + .aadLenInBytes; + } + + /* round the aad size to the multiple of CCM block + * size.*/ + aadDataSize = + LAC_ALIGN_POW2_ROUNDUP(aadDataSize, + LAC_HASH_AES_CCM_BLOCK_SIZE); + if (aadDataSize > ICP_QAT_FW_CCM_GCM_AAD_SZ_MAX) { + LAC_INVALID_PARAM_LOG("aadLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (CPA_CY_SYM_HASH_KASUMI_F9 == + pHashSetupData->hashAlgorithm) { + /* QAT-FW only supports 128 bit Integrity Key size for + * Kasumi f9 + * Ref: 3GPP TS 35.201 version 7.0.0 Release 7 */ + if (pHashSetupData->authModeSetupData + .authKeyLenInBytes != + ICP_QAT_HW_KASUMI_KEY_SZ) { + LAC_INVALID_PARAM_LOG("authKeyLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == + pHashSetupData->hashAlgorithm) { + + /* QAT-FW only supports 128 bits Integrity Key size for + * Snow3g */ + if (pHashSetupData->authModeSetupData + .authKeyLenInBytes != + ICP_QAT_HW_SNOW_3G_UEA2_KEY_SZ) { + LAC_INVALID_PARAM_LOG("authKeyLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + /* For Snow3g hash aad field contains IV - it needs to + * be 16 + * bytes long + */ + if (pHashSetupData->authModeSetupData.aadLenInBytes != + ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ) { + LAC_INVALID_PARAM_LOG("aadLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (CPA_CY_SYM_HASH_AES_XCBC == + pHashSetupData->hashAlgorithm || + CPA_CY_SYM_HASH_AES_CMAC == + pHashSetupData->hashAlgorithm || + CPA_CY_SYM_HASH_AES_CBC_MAC == + pHashSetupData->hashAlgorithm) { + /* ensure auth key len is valid (128-bit keys supported) + */ + if ((pHashSetupData->authModeSetupData + .authKeyLenInBytes != + ICP_QAT_HW_AES_128_KEY_SZ)) { + LAC_INVALID_PARAM_LOG("authKeyLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (CPA_CY_SYM_HASH_ZUC_EIA3 == + pHashSetupData->hashAlgorithm) { + + /* QAT-FW only supports 128 bits Integrity Key size for + * ZUC */ + if (pHashSetupData->authModeSetupData + .authKeyLenInBytes != + ICP_QAT_HW_ZUC_3G_EEA3_KEY_SZ) { + LAC_INVALID_PARAM_LOG("authKeyLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + /* For ZUC EIA3 hash aad field contains IV - it needs to + * be 16 + * bytes long + */ + if (pHashSetupData->authModeSetupData.aadLenInBytes != + ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ) { + LAC_INVALID_PARAM_LOG("aadLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } else if (CPA_CY_SYM_HASH_POLY == + pHashSetupData->hashAlgorithm) { + if (pHashSetupData->digestResultLenInBytes != + ICP_QAT_HW_SPC_CTR_SZ) { + LAC_INVALID_PARAM_LOG("Digest Length for CCP"); + return CPA_STATUS_INVALID_PARAM; + } + if (pHashSetupData->authModeSetupData.aadLenInBytes > + ICP_QAT_FW_CCM_GCM_AAD_SZ_MAX) { + LAC_INVALID_PARAM_LOG("AAD Length for CCP"); + return CPA_STATUS_INVALID_PARAM; + } + } else { + /* The key size must be less than or equal the block + * length */ + if (pHashSetupData->authModeSetupData + .authKeyLenInBytes > + pHashAlgInfo->blockLength) { + LAC_INVALID_PARAM_LOG("authKeyLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* when the key size is greater than 0 check pointer is not null + */ + if (CPA_CY_SYM_HASH_AES_CCM != pHashSetupData->hashAlgorithm && + CPA_CY_SYM_HASH_AES_GCM != pHashSetupData->hashAlgorithm && + pHashSetupData->authModeSetupData.authKeyLenInBytes > 0) { + LAC_CHECK_NULL_PARAM( + pHashSetupData->authModeSetupData.authKey); + } + } else if (CPA_CY_SYM_HASH_MODE_NESTED == pHashSetupData->hashMode) { + if (!CPA_BITMAP_BIT_TEST(capInfo.hashes, + pHashSetupData->nestedModeSetupData + .outerHashAlgorithm)) { + /* Ensure SHAKE algorithms are not supported */ + if ((CPA_CY_SYM_HASH_SHAKE_128 == + pHashSetupData->nestedModeSetupData + .outerHashAlgorithm) || + (CPA_CY_SYM_HASH_SHAKE_256 == + pHashSetupData->nestedModeSetupData + .outerHashAlgorithm)) { + LAC_INVALID_PARAM_LOG( + "Hash algorithms SHAKE-128 and SHAKE-256 " + "are not supported."); + return CPA_STATUS_UNSUPPORTED; + } + + LAC_INVALID_PARAM_LOG("outerHashAlgorithm"); + return CPA_STATUS_INVALID_PARAM; + } + + if (LAC_HASH_ALG_MODE_NOT_SUPPORTED( + pHashSetupData->nestedModeSetupData.outerHashAlgorithm, + pHashSetupData->hashMode)) { + LAC_INVALID_PARAM_LOG( + "outerHashAlgorithm and hashMode combination"); + return CPA_STATUS_INVALID_PARAM; + } + + LacSymQat_HashAlgLookupGet( + instanceHandle, + pHashSetupData->nestedModeSetupData.outerHashAlgorithm, + &pOuterHashAlgInfo); + + /* Check Digest Length is permitted by the algorithm */ + if ((0 == pHashSetupData->digestResultLenInBytes) || + (pHashSetupData->digestResultLenInBytes > + pOuterHashAlgInfo->digestLength)) { + LAC_INVALID_PARAM_LOG("digestResultLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + + if (pHashSetupData->nestedModeSetupData.innerPrefixLenInBytes > + LAC_MAX_INNER_OUTER_PREFIX_SIZE_BYTES) { + LAC_INVALID_PARAM_LOG("innerPrefixLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + + if (pHashSetupData->nestedModeSetupData.innerPrefixLenInBytes > + 0) { + LAC_CHECK_NULL_PARAM(pHashSetupData->nestedModeSetupData + .pInnerPrefixData); + } + + if (pHashSetupData->nestedModeSetupData.outerPrefixLenInBytes > + LAC_MAX_INNER_OUTER_PREFIX_SIZE_BYTES) { + LAC_INVALID_PARAM_LOG("outerPrefixLenInBytes"); + return CPA_STATUS_INVALID_PARAM; + } + + if (pHashSetupData->nestedModeSetupData.outerPrefixLenInBytes > + 0) { + LAC_CHECK_NULL_PARAM(pHashSetupData->nestedModeSetupData + .pOuterPrefixData); + } + } + + return CPA_STATUS_SUCCESS; +} + +/** @ingroup LacHash */ +CpaStatus +LacHash_PerformParamCheck(CpaInstanceHandle instanceHandle, + lac_session_desc_t *pSessionDesc, + const CpaCySymOpData *pOpData, + Cpa64U srcPktSize, + const CpaBoolean *pVerifyResult) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + lac_sym_qat_hash_alg_info_t *pHashAlgInfo = NULL; + + /* digestVerify and digestIsAppended on Hash-Only operation not + * supported */ + if (pSessionDesc->digestIsAppended && pSessionDesc->digestVerify && + (CPA_CY_SYM_OP_HASH == pSessionDesc->symOperation)) { + LAC_INVALID_PARAM_LOG( + "digestVerify and digestIsAppended set " + "on Hash-Only operation is not supported"); + return CPA_STATUS_INVALID_PARAM; + } + + /* check the digest result pointer */ + if ((CPA_CY_SYM_PACKET_TYPE_PARTIAL != pOpData->packetType) && + !pSessionDesc->digestIsAppended && + (NULL == pOpData->pDigestResult)) { + LAC_INVALID_PARAM_LOG("pDigestResult is NULL"); + return CPA_STATUS_INVALID_PARAM; + } + + /* + * Check if the pVerifyResult pointer is not null for hash operation + * when + * the packet is the last one and user has set verifyDigest flag + * Also, this is only needed for symchronous operation, so check if the + * callback pointer is the internal synchronous one rather than a user- + * supplied one. + */ + if ((CPA_TRUE == pSessionDesc->digestVerify) && + (CPA_CY_SYM_PACKET_TYPE_PARTIAL != pOpData->packetType) && + (LacSync_GenBufListVerifyCb == pSessionDesc->pSymCb)) { + if (NULL == pVerifyResult) { + LAC_INVALID_PARAM_LOG( + "Null pointer pVerifyResult for hash op"); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* verify start offset + messageLenToDigest is inside the source packet. + * this also verifies that the start offset is inside the packet + * Note: digest is specified as a pointer therefore it can be + * written anywhere so we cannot check for this been inside a buffer + * CCM/GCM specify the auth region using just the cipher params as this + * region is the same for auth and cipher. It is not checked here */ + if ((CPA_CY_SYM_HASH_AES_CCM == pSessionDesc->hashAlgorithm) || + (CPA_CY_SYM_HASH_AES_GCM == pSessionDesc->hashAlgorithm)) { + /* ensure AAD data pointer is non-NULL if AAD len > 0 */ + if ((pSessionDesc->aadLenInBytes > 0) && + (NULL == pOpData->pAdditionalAuthData)) { + LAC_INVALID_PARAM_LOG("pAdditionalAuthData is NULL"); + return CPA_STATUS_INVALID_PARAM; + } + } else { + if ((pOpData->hashStartSrcOffsetInBytes + + pOpData->messageLenToHashInBytes) > srcPktSize) { + LAC_INVALID_PARAM_LOG( + "hashStartSrcOffsetInBytes + " + "messageLenToHashInBytes > Src Buffer Packet Length"); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* For Snow3g & ZUC hash pAdditionalAuthData field + * of OpData should contain IV */ + if ((CPA_CY_SYM_HASH_SNOW3G_UIA2 == pSessionDesc->hashAlgorithm) || + (CPA_CY_SYM_HASH_ZUC_EIA3 == pSessionDesc->hashAlgorithm)) { + if (NULL == pOpData->pAdditionalAuthData) { + LAC_INVALID_PARAM_LOG("pAdditionalAuthData is NULL"); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* partial packets need to be multiples of the algorithm block size in + * hash + * only mode (except for final partial packet) */ + if ((CPA_CY_SYM_PACKET_TYPE_PARTIAL == pOpData->packetType) && + (CPA_CY_SYM_OP_HASH == pSessionDesc->symOperation)) { + LacSymQat_HashAlgLookupGet(instanceHandle, + pSessionDesc->hashAlgorithm, + &pHashAlgInfo); + + /* check if the message is a multiple of the block size. */ + if ((pOpData->messageLenToHashInBytes % + pHashAlgInfo->blockLength) != 0) { + LAC_INVALID_PARAM_LOG( + "messageLenToHashInBytes not block size"); + return CPA_STATUS_INVALID_PARAM; + } + } + + return status; +} + diff --git a/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_hash_sw_precomputes.c b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_hash_sw_precomputes.c new file mode 100644 index 000000000000..be3a39755b4a --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_hash_sw_precomputes.c @@ -0,0 +1,353 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_hash_sw_precomputes.c + * + * @ingroup LacHashDefs + * + * Hash Software + ***************************************************************************/ + +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ + +#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 private header files +******************************************************************************* +*/ + +#include "qat_utils.h" +#include "lac_mem.h" +#include "lac_sym.h" +#include "lac_log.h" +#include "lac_mem_pools.h" +#include "lac_list.h" +#include "lac_sym_hash_defs.h" +#include "lac_sym_qat_hash_defs_lookup.h" +#include "lac_sal_types_crypto.h" +#include "lac_sal.h" +#include "lac_session.h" +#include "lac_sym_hash_precomputes.h" + +static CpaStatus +LacSymHash_Compute(CpaCySymHashAlgorithm hashAlgorithm, + lac_sym_qat_hash_alg_info_t *pHashAlgInfo, + Cpa8U *in, + Cpa8U *out) +{ + /* + * Note: from SHA hashes appropriate endian swapping is required. + * For sha1, sha224 and sha256 double words based swapping. + * For sha384 and sha512 quad words swapping. + * No endianes swapping for md5 is required. + */ + CpaStatus status = CPA_STATUS_FAIL; + Cpa32U i = 0; + switch (hashAlgorithm) { + case CPA_CY_SYM_HASH_MD5: + if (CPA_STATUS_SUCCESS != qatUtilsHashMD5(in, out)) { + LAC_LOG_ERROR("qatUtilsHashMD5 Failed\n"); + return status; + } + status = CPA_STATUS_SUCCESS; + break; + case CPA_CY_SYM_HASH_SHA1: + if (CPA_STATUS_SUCCESS != qatUtilsHashSHA1(in, out)) { + LAC_LOG_ERROR("qatUtilsHashSHA1 Failed\n"); + return status; + } + for (i = 0; i < LAC_BYTES_TO_LONGWORDS(pHashAlgInfo->stateSize); + i++) { + ((Cpa32U *)(out))[i] = + LAC_MEM_WR_32(((Cpa32U *)(out))[i]); + } + status = CPA_STATUS_SUCCESS; + break; + case CPA_CY_SYM_HASH_SHA224: + if (CPA_STATUS_SUCCESS != qatUtilsHashSHA224(in, out)) { + LAC_LOG_ERROR("qatUtilsHashSHA224 Failed\n"); + return status; + } + for (i = 0; i < LAC_BYTES_TO_LONGWORDS(pHashAlgInfo->stateSize); + i++) { + ((Cpa32U *)(out))[i] = + LAC_MEM_WR_32(((Cpa32U *)(out))[i]); + } + status = CPA_STATUS_SUCCESS; + break; + case CPA_CY_SYM_HASH_SHA256: + if (CPA_STATUS_SUCCESS != qatUtilsHashSHA256(in, out)) { + LAC_LOG_ERROR("qatUtilsHashSHA256 Failed\n"); + return status; + } + for (i = 0; i < LAC_BYTES_TO_LONGWORDS(pHashAlgInfo->stateSize); + i++) { + ((Cpa32U *)(out))[i] = + LAC_MEM_WR_32(((Cpa32U *)(out))[i]); + } + status = CPA_STATUS_SUCCESS; + break; + case CPA_CY_SYM_HASH_SHA384: + if (CPA_STATUS_SUCCESS != qatUtilsHashSHA384(in, out)) { + LAC_LOG_ERROR("qatUtilsHashSHA384 Failed\n"); + return status; + } + for (i = 0; i < LAC_BYTES_TO_QUADWORDS(pHashAlgInfo->stateSize); + i++) { + ((Cpa64U *)(out))[i] = + LAC_MEM_WR_64(((Cpa64U *)(out))[i]); + } + status = CPA_STATUS_SUCCESS; + break; + case CPA_CY_SYM_HASH_SHA512: + if (CPA_STATUS_SUCCESS != qatUtilsHashSHA512(in, out)) { + LAC_LOG_ERROR("qatUtilsHashSHA512 Failed\n"); + return status; + } + for (i = 0; i < LAC_BYTES_TO_QUADWORDS(pHashAlgInfo->stateSize); + i++) { + ((Cpa64U *)(out))[i] = + LAC_MEM_WR_64(((Cpa64U *)(out))[i]); + } + status = CPA_STATUS_SUCCESS; + break; + default: + return CPA_STATUS_INVALID_PARAM; + } + return status; +} + +CpaStatus +LacSymHash_HmacPreComputes(CpaInstanceHandle instanceHandle, + CpaCySymHashAlgorithm hashAlgorithm, + Cpa32U authKeyLenInBytes, + Cpa8U *pAuthKey, + Cpa8U *pWorkingMemory, + Cpa8U *pState1, + Cpa8U *pState2, + lac_hash_precompute_done_cb_t callbackFn, + void *pCallbackTag) +{ + Cpa8U *pIpadData = NULL; + Cpa8U *pOpadData = NULL; + CpaStatus status = CPA_STATUS_FAIL; + lac_sym_hash_precomp_op_data_t *pHmacIpadOpData = + (lac_sym_hash_precomp_op_data_t *)pWorkingMemory; + lac_sym_hash_precomp_op_data_t *pHmacOpadOpData = pHmacIpadOpData + 1; + + /* Convenience pointers */ + lac_sym_hash_hmac_precomp_qat_t *pHmacIpadQatData = + &pHmacIpadOpData->u.hmacQatData; + lac_sym_hash_hmac_precomp_qat_t *pHmacOpadQatData = + &pHmacOpadOpData->u.hmacQatData; + + lac_sym_qat_hash_alg_info_t *pHashAlgInfo = NULL; + Cpa32U i = 0; + Cpa32U padLenBytes = 0; + + LacSymQat_HashAlgLookupGet(instanceHandle, + hashAlgorithm, + &pHashAlgInfo); + pHmacIpadOpData->stateSize = pHashAlgInfo->stateSize; + pHmacOpadOpData->stateSize = pHashAlgInfo->stateSize; + + /* Copy HMAC key into buffers */ + if (authKeyLenInBytes > 0) { + memcpy(pHmacIpadQatData->data, pAuthKey, authKeyLenInBytes); + memcpy(pHmacOpadQatData->data, pAuthKey, authKeyLenInBytes); + } + + padLenBytes = pHashAlgInfo->blockLength - authKeyLenInBytes; + + /* Clear the remaining buffer space */ + if (padLenBytes > 0) { + LAC_OS_BZERO(pHmacIpadQatData->data + authKeyLenInBytes, + padLenBytes); + LAC_OS_BZERO(pHmacOpadQatData->data + authKeyLenInBytes, + padLenBytes); + } + + /* XOR Key with IPAD at 4-byte level */ + for (i = 0; i < pHashAlgInfo->blockLength; i++) { + Cpa8U *ipad = pHmacIpadQatData->data + i; + Cpa8U *opad = pHmacOpadQatData->data + i; + + *ipad ^= LAC_HASH_IPAD_BYTE; + *opad ^= LAC_HASH_OPAD_BYTE; + } + pIpadData = (Cpa8U *)pHmacIpadQatData->data; + pOpadData = (Cpa8U *)pHmacOpadQatData->data; + + status = LacSymHash_Compute(hashAlgorithm, + pHashAlgInfo, + (Cpa8U *)pIpadData, + pState1); + + if (CPA_STATUS_SUCCESS == status) { + status = LacSymHash_Compute(hashAlgorithm, + pHashAlgInfo, + (Cpa8U *)pOpadData, + pState2); + } + + if (CPA_STATUS_SUCCESS == status) { + callbackFn(pCallbackTag); + } + return status; +} + +CpaStatus +LacSymHash_AesECBPreCompute(CpaInstanceHandle instanceHandle, + CpaCySymHashAlgorithm hashAlgorithm, + Cpa32U authKeyLenInBytes, + Cpa8U *pAuthKey, + Cpa8U *pWorkingMemory, + Cpa8U *pState, + lac_hash_precompute_done_cb_t callbackFn, + void *pCallbackTag) +{ + CpaStatus status = CPA_STATUS_FAIL; + Cpa32U stateSize = 0, x = 0; + lac_sym_qat_hash_alg_info_t *pHashAlgInfo = NULL; + + if (CPA_CY_SYM_HASH_AES_XCBC == hashAlgorithm) { + Cpa8U *in = pWorkingMemory; + Cpa8U *out = pState; + LacSymQat_HashAlgLookupGet(instanceHandle, + hashAlgorithm, + &pHashAlgInfo); + stateSize = pHashAlgInfo->stateSize; + memcpy(pWorkingMemory, pHashAlgInfo->initState, stateSize); + + for (x = 0; x < LAC_HASH_XCBC_PRECOMP_KEY_NUM; x++) { + if (CPA_STATUS_SUCCESS != + qatUtilsAESEncrypt( + pAuthKey, authKeyLenInBytes, in, out)) { + return status; + } + in += LAC_HASH_XCBC_MAC_BLOCK_SIZE; + out += LAC_HASH_XCBC_MAC_BLOCK_SIZE; + } + status = CPA_STATUS_SUCCESS; + } else if (CPA_CY_SYM_HASH_AES_CMAC == hashAlgorithm) { + Cpa8U *out = pState; + Cpa8U k1[LAC_HASH_CMAC_BLOCK_SIZE], + k2[LAC_HASH_CMAC_BLOCK_SIZE]; + Cpa8U *ptr = NULL, i = 0; + stateSize = LAC_HASH_CMAC_BLOCK_SIZE; + LacSymQat_HashAlgLookupGet(instanceHandle, + hashAlgorithm, + &pHashAlgInfo); + /* Original state size includes K, K1 and K2 which are of equal + * length. + * For precompute state size is only of the length of K which is + * equal + * to the block size for CPA_CY_SYM_HASH_AES_CMAC. + * The algorithm is described in rfc4493 + * K is just copeid, K1 and K2 need to be single inplace encrypt + * with AES. + * */ + memcpy(out, pHashAlgInfo->initState, stateSize); + memcpy(out, pAuthKey, authKeyLenInBytes); + out += LAC_HASH_CMAC_BLOCK_SIZE; + + for (x = 0; x < LAC_HASH_XCBC_PRECOMP_KEY_NUM - 1; x++) { + if (CPA_STATUS_SUCCESS != + qatUtilsAESEncrypt( + pAuthKey, authKeyLenInBytes, out, out)) { + return status; + } + out += LAC_HASH_CMAC_BLOCK_SIZE; + } + + ptr = pState + LAC_HASH_CMAC_BLOCK_SIZE; + + /* Derived keys (k1 and k2), copy them to + * pPrecompOpData->pState, + * but remember that at the beginning is original key (K0) + */ + /* Calculating K1 */ + for (i = 0; i < LAC_HASH_CMAC_BLOCK_SIZE; i++, ptr++) { + k1[i] = (*ptr) << 1; + if (i != 0) { + k1[i - 1] |= + (*ptr) >> (LAC_NUM_BITS_IN_BYTE - 1); + } + if (i + 1 == LAC_HASH_CMAC_BLOCK_SIZE) { + /* If msb of pState + LAC_HASH_CMAC_BLOCK_SIZE + is set xor + with RB. Because only the final byte of RB is + non-zero + this is all we need to xor */ + if ((*(pState + LAC_HASH_CMAC_BLOCK_SIZE)) & + LAC_SYM_HASH_MSBIT_MASK) { + k1[i] ^= LAC_SYM_AES_CMAC_RB_128; + } + } + } + + /* Calculating K2 */ + for (i = 0; i < LAC_HASH_CMAC_BLOCK_SIZE; i++) { + k2[i] = (k1[i]) << 1; + if (i != 0) { + k2[i - 1] |= + (k1[i]) >> (LAC_NUM_BITS_IN_BYTE - 1); + } + if (i + 1 == LAC_HASH_CMAC_BLOCK_SIZE) { + /* If msb of k1 is set xor last byte with RB */ + if (k1[0] & LAC_SYM_HASH_MSBIT_MASK) { + k2[i] ^= LAC_SYM_AES_CMAC_RB_128; + } + } + } + /* Now, when we have K1 & K2 lets copy them to the state2 */ + ptr = pState + LAC_HASH_CMAC_BLOCK_SIZE; + memcpy(ptr, k1, LAC_HASH_CMAC_BLOCK_SIZE); + ptr += LAC_HASH_CMAC_BLOCK_SIZE; + memcpy(ptr, k2, LAC_HASH_CMAC_BLOCK_SIZE); + status = CPA_STATUS_SUCCESS; + } else if (CPA_CY_SYM_HASH_AES_GCM == hashAlgorithm || + CPA_CY_SYM_HASH_AES_GMAC == hashAlgorithm) { + Cpa8U *in = pWorkingMemory; + Cpa8U *out = pState; + LAC_OS_BZERO(pWorkingMemory, ICP_QAT_HW_GALOIS_H_SZ); + + if (CPA_STATUS_SUCCESS != + qatUtilsAESEncrypt(pAuthKey, authKeyLenInBytes, in, out)) { + return status; + } + status = CPA_STATUS_SUCCESS; + } else { + return CPA_STATUS_INVALID_PARAM; + } + callbackFn(pCallbackTag); + return status; +} + +CpaStatus +LacSymHash_HmacPrecompInit(CpaInstanceHandle instanceHandle) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + return status; +} + +void +LacSymHash_HmacPrecompShutdown(CpaInstanceHandle instanceHandle) +{ + return; +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_partial.c b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_partial.c new file mode 100644 index 000000000000..4a937c7d093a --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_partial.c @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_partial.c common partial packet functions + * + * @ingroup LacSym + * + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ +#include "cpa.h" + +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" + +#include "lac_log.h" +#include "lac_sym.h" +#include "cpa_cy_sym.h" +#include "lac_common.h" + +#include "lac_sym_partial.h" + +CpaStatus +LacSym_PartialPacketStateCheck(CpaCySymPacketType packetType, + CpaCySymPacketType partialState) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + /* ASSUMPTION - partial requests on a given session must be issued + * sequentially to guarantee ordering + * (i.e. issuing partials on concurrent threads for a particular session + * just wouldn't work) + */ + + /* state is no partial - only a partial is allowed */ + if (((CPA_CY_SYM_PACKET_TYPE_FULL == partialState) && + (CPA_CY_SYM_PACKET_TYPE_PARTIAL == packetType)) || + + /* state is partial - only a partial or final partial is allowed */ + ((CPA_CY_SYM_PACKET_TYPE_PARTIAL == partialState) && + ((CPA_CY_SYM_PACKET_TYPE_PARTIAL == packetType) || + (CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL == packetType)))) { + status = CPA_STATUS_SUCCESS; + } else /* invalid sequence */ + { + LAC_INVALID_PARAM_LOG("invalid partial packet sequence"); + status = CPA_STATUS_INVALID_PARAM; + } + + return status; +} + +void +LacSym_PartialPacketStateUpdate(CpaCySymPacketType packetType, + CpaCySymPacketType *pPartialState) +{ + /* if previous packet was either a full or ended a partial stream, + * update + * state to partial to indicate a new partial stream was created */ + if (CPA_CY_SYM_PACKET_TYPE_FULL == *pPartialState) { + *pPartialState = CPA_CY_SYM_PACKET_TYPE_PARTIAL; + } else { + /* if packet type is final - reset the partial state */ + if (CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL == packetType) { + *pPartialState = CPA_CY_SYM_PACKET_TYPE_FULL; + } + } +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_queue.c b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_queue.c new file mode 100644 index 000000000000..977fb0b84d0b --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_queue.c @@ -0,0 +1,165 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_queue.c Functions for sending/queuing symmetric requests + * + * @ingroup LacSym + * + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ +#include "cpa.h" +#include "cpa_cy_sym.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ +#include "icp_accel_devices.h" +#include "icp_adf_init.h" +#include "icp_adf_debug.h" +#include "icp_adf_transport.h" +#include "lac_sym_queue.h" +#include "lac_sym_qat.h" +#include "lac_session.h" +#include "lac_sym.h" +#include "lac_log.h" +#include "icp_qat_fw_la.h" +#include "lac_sal_types_crypto.h" + +#define GetSingleBitFromByte(byte, bit) ((byte) & (1 << (bit))) + +/* +******************************************************************************* +* Define public/global function definitions +******************************************************************************* +*/ + +CpaStatus +LacSymQueue_RequestSend(const CpaInstanceHandle instanceHandle, + lac_sym_bulk_cookie_t *pRequest, + lac_session_desc_t *pSessionDesc) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + CpaBoolean enqueued = CPA_FALSE; + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + /* Enqueue the message instead of sending directly if: + * (i) a blocking operation is in progress + * (ii) there are previous requests already in the queue + */ + if ((CPA_FALSE == pSessionDesc->nonBlockingOpsInProgress) || + (NULL != pSessionDesc->pRequestQueueTail)) { + if (CPA_STATUS_SUCCESS != + LAC_SPINLOCK(&pSessionDesc->requestQueueLock)) { + LAC_LOG_ERROR("Failed to lock request queue"); + return CPA_STATUS_RESOURCE; + } + + /* Re-check blockingOpsInProgress and pRequestQueueTail in case + * either + * changed before the lock was acquired. The lock is shared + * with + * the callback context which drains this queue + */ + if ((CPA_FALSE == pSessionDesc->nonBlockingOpsInProgress) || + (NULL != pSessionDesc->pRequestQueueTail)) { + /* Enqueue the message and exit */ + /* The FIFO queue is made up of a head and tail pointer. + * The head pointer points to the first/oldest, entry + * in the queue, and the tail pointer points to the + * last/newest + * entry in the queue + */ + + if (NULL != pSessionDesc->pRequestQueueTail) { + /* Queue is non-empty. Add this request to the + * list */ + pSessionDesc->pRequestQueueTail->pNext = + pRequest; + } else { + /* Queue is empty. Initialise the head pointer + * as well */ + pSessionDesc->pRequestQueueHead = pRequest; + } + + pSessionDesc->pRequestQueueTail = pRequest; + + /* request is queued, don't send to QAT here */ + enqueued = CPA_TRUE; + } + if (CPA_STATUS_SUCCESS != + LAC_SPINUNLOCK(&pSessionDesc->requestQueueLock)) { + LAC_LOG_ERROR("Failed to unlock request queue"); + } + } + + if (CPA_FALSE == enqueued) { + /* If we send a partial packet request, set the + * blockingOpsInProgress + * flag for the session to indicate that subsequent requests + * must be + * queued up until this request completes + * + * @assumption + * If we have got here it means that there were no previous + * blocking + * operations in progress and, since multiple partial packet + * requests + * on a given session cannot be issued concurrently, there + * should be + * no need for a critical section around the following code + */ + if (CPA_CY_SYM_PACKET_TYPE_FULL != + pRequest->pOpData->packetType) { + /* Select blocking operations which this reqest will + * complete */ + pSessionDesc->nonBlockingOpsInProgress = CPA_FALSE; + } + + /* At this point, we're clear to send the request. For cipher + * requests, + * we need to check if the session IV needs to be updated. This + * can + * only be done when no other partials are in flight for this + * session, + * to ensure the cipherPartialOpState buffer in the session + * descriptor + * is not currently in use + */ + if (CPA_TRUE == pRequest->updateSessionIvOnSend) { + if (LAC_CIPHER_IS_ARC4(pSessionDesc->cipherAlgorithm)) { + memcpy(pSessionDesc->cipherPartialOpState, + pSessionDesc->cipherARC4InitialState, + LAC_CIPHER_ARC4_STATE_LEN_BYTES); + } else { + memcpy(pSessionDesc->cipherPartialOpState, + pRequest->pOpData->pIv, + pRequest->pOpData->ivLenInBytes); + } + } + + /* Send to QAT */ + status = icp_adf_transPutMsg(pService->trans_handle_sym_tx, + (void *)&(pRequest->qatMsg), + LAC_QAT_SYM_REQ_SZ_LW); + + /* if fail to send request, we need to change + * nonBlockingOpsInProgress + * to CPA_TRUE + */ + if ((CPA_STATUS_SUCCESS != status) && + (CPA_CY_SYM_PACKET_TYPE_FULL != + pRequest->pOpData->packetType)) { + pSessionDesc->nonBlockingOpsInProgress = CPA_TRUE; + } + } + return status; +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_stats.c b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_stats.c new file mode 100644 index 000000000000..ca1bbb99d3a4 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/lac_sym_stats.c @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_stats.c Implementation of symmetric stats + * + * @ingroup LacSym + * + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ +#include "cpa.h" +#include "cpa_cy_sym.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ +#include "lac_mem_pools.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_qat.h" +#include "lac_sym_stats.h" +#include "lac_sal_types_crypto.h" +#include "sal_statistics.h" + +/* Number of Symmetric Crypto statistics */ +#define LAC_SYM_NUM_STATS (sizeof(CpaCySymStats64) / sizeof(Cpa64U)) + +CpaStatus +LacSym_StatsInit(CpaInstanceHandle instanceHandle) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + + pService->pLacSymStatsArr = + LAC_OS_MALLOC(LAC_SYM_NUM_STATS * sizeof(QatUtilsAtomic)); + + if (NULL != pService->pLacSymStatsArr) { + LAC_OS_BZERO((void *)LAC_CONST_VOLATILE_PTR_CAST( + pService->pLacSymStatsArr), + LAC_SYM_NUM_STATS * sizeof(QatUtilsAtomic)); + } else { + status = CPA_STATUS_RESOURCE; + } + return status; +} + +void +LacSym_StatsFree(CpaInstanceHandle instanceHandle) +{ + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + if (NULL != pService->pLacSymStatsArr) { + LAC_OS_FREE(pService->pLacSymStatsArr); + } +} + +void +LacSym_StatsInc(Cpa32U offset, CpaInstanceHandle instanceHandle) +{ + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + if (CPA_TRUE == + pService->generic_service_info.stats->bSymStatsEnabled) { + qatUtilsAtomicInc( + &pService->pLacSymStatsArr[offset / sizeof(Cpa64U)]); + } +} + +void +LacSym_Stats32CopyGet(CpaInstanceHandle instanceHandle, + struct _CpaCySymStats *const pSymStats) +{ + int i = 0; + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + + for (i = 0; i < LAC_SYM_NUM_STATS; i++) { + ((Cpa32U *)pSymStats)[i] = + (Cpa32U)qatUtilsAtomicGet(&pService->pLacSymStatsArr[i]); + } +} + +void +LacSym_Stats64CopyGet(CpaInstanceHandle instanceHandle, + CpaCySymStats64 *const pSymStats) +{ + int i = 0; + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + + for (i = 0; i < LAC_SYM_NUM_STATS; i++) { + ((Cpa64U *)pSymStats)[i] = + qatUtilsAtomicGet(&pService->pLacSymStatsArr[i]); + } +} + +void +LacSym_StatsShow(CpaInstanceHandle instanceHandle) +{ + CpaCySymStats64 symStats = { 0 }; + + LacSym_Stats64CopyGet(instanceHandle, &symStats); + + QAT_UTILS_LOG(SEPARATOR BORDER + " Symmetric Stats " BORDER + "\n" SEPARATOR); + + /* Session Info */ + QAT_UTILS_LOG(BORDER " Sessions Initialized: %16llu " BORDER + "\n" BORDER + " Sessions Removed: %16llu " BORDER + "\n" BORDER + " Session Errors: %16llu " BORDER + "\n" SEPARATOR, + (unsigned long long)symStats.numSessionsInitialized, + (unsigned long long)symStats.numSessionsRemoved, + (unsigned long long)symStats.numSessionErrors); + + /* Session info */ + QAT_UTILS_LOG( + BORDER " Symmetric Requests: %16llu " BORDER "\n" BORDER + " Symmetric Request Errors: %16llu " BORDER "\n" BORDER + " Symmetric Completed: %16llu " BORDER "\n" BORDER + " Symmetric Completed Errors: %16llu " BORDER "\n" BORDER + " Symmetric Verify Failures: %16llu " BORDER + "\n" SEPARATOR, + (unsigned long long)symStats.numSymOpRequests, + (unsigned long long)symStats.numSymOpRequestErrors, + (unsigned long long)symStats.numSymOpCompleted, + (unsigned long long)symStats.numSymOpCompletedErrors, + (unsigned long long)symStats.numSymOpVerifyFailures); +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat.c b/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat.c new file mode 100644 index 000000000000..c55da0a0d531 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat.c @@ -0,0 +1,227 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + ***************************************************************************** + * @file lac_sym_qat.c Interfaces for populating the symmetric qat structures + * + * @ingroup LacSymQat + * + *****************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ +#include "cpa.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ +#include "icp_accel_devices.h" +#include "icp_adf_cfg.h" +#include "lac_log.h" +#include "lac_sym.h" +#include "lac_sym_qat.h" +#include "lac_sal_types_crypto.h" +#include "sal_string_parse.h" +#include "lac_sym_key.h" +#include "lac_sym_qat_hash_defs_lookup.h" +#include "lac_sym_qat_cipher.h" +#include "lac_sym_qat_hash.h" + +#define EMBEDDED_CIPHER_KEY_MAX_SIZE 16 +static void +LacSymQat_SymLogSliceHangError(icp_qat_fw_la_cmd_id_t symCmdId) +{ + Cpa8U cmdId = symCmdId; + + switch (cmdId) { + case ICP_QAT_FW_LA_CMD_CIPHER: + case ICP_QAT_FW_LA_CMD_CIPHER_PRE_COMP: + LAC_LOG_ERROR("slice hang detected on CPM cipher slice."); + break; + + case ICP_QAT_FW_LA_CMD_AUTH: + case ICP_QAT_FW_LA_CMD_AUTH_PRE_COMP: + LAC_LOG_ERROR("slice hang detected on CPM auth slice."); + break; + + case ICP_QAT_FW_LA_CMD_CIPHER_HASH: + case ICP_QAT_FW_LA_CMD_HASH_CIPHER: + case ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE: + case ICP_QAT_FW_LA_CMD_TLS_V1_1_KEY_DERIVE: + case ICP_QAT_FW_LA_CMD_TLS_V1_2_KEY_DERIVE: + case ICP_QAT_FW_LA_CMD_MGF1: + default: + LAC_LOG_ERROR( + "slice hang detected on CPM cipher or auth slice."); + } + return; +} + +/* sym crypto response handlers */ +static sal_qat_resp_handler_func_t + respHandlerSymTbl[ICP_QAT_FW_LA_CMD_DELIMITER]; + +void +LacSymQat_SymRespHandler(void *pRespMsg) +{ + Cpa8U lacCmdId = 0; + void *pOpaqueData = NULL; + icp_qat_fw_la_resp_t *pRespMsgFn = NULL; + Cpa8U opStatus = ICP_QAT_FW_COMN_STATUS_FLAG_OK; + Cpa8U comnErr = ERR_CODE_NO_ERROR; + + pRespMsgFn = (icp_qat_fw_la_resp_t *)pRespMsg; + LAC_MEM_SHARED_READ_TO_PTR(pRespMsgFn->opaque_data, pOpaqueData); + + lacCmdId = pRespMsgFn->comn_resp.cmd_id; + opStatus = pRespMsgFn->comn_resp.comn_status; + comnErr = pRespMsgFn->comn_resp.comn_error.s.comn_err_code; + + /* log the slice hang and endpoint push/pull error inside the response + */ + if (ERR_CODE_SSM_ERROR == (Cpa8S)comnErr) { + LacSymQat_SymLogSliceHangError(lacCmdId); + } else if (ERR_CODE_ENDPOINT_ERROR == (Cpa8S)comnErr) { + LAC_LOG_ERROR("The PCIe End Point Push/Pull or" + " TI/RI Parity error detected."); + } + + /* call the response message handler registered for the command ID */ + respHandlerSymTbl[lacCmdId]((icp_qat_fw_la_cmd_id_t)lacCmdId, + pOpaqueData, + (icp_qat_fw_comn_flags)opStatus); +} + +CpaStatus +LacSymQat_Init(CpaInstanceHandle instanceHandle) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + /* Initialise the Hash lookup table */ + status = LacSymQat_HashLookupInit(instanceHandle); + + return status; +} + +void +LacSymQat_RespHandlerRegister(icp_qat_fw_la_cmd_id_t lacCmdId, + sal_qat_resp_handler_func_t pCbHandler) +{ + if (lacCmdId >= ICP_QAT_FW_LA_CMD_DELIMITER) { + QAT_UTILS_LOG("Invalid Command ID\n"); + return; + } + + /* set the response handler for the command ID */ + respHandlerSymTbl[lacCmdId] = pCbHandler; +} + +void +LacSymQat_LaPacketCommandFlagSet(Cpa32U qatPacketType, + icp_qat_fw_la_cmd_id_t laCmdId, + CpaCySymCipherAlgorithm cipherAlgorithm, + Cpa16U *pLaCommandFlags, + Cpa32U ivLenInBytes) +{ + /* For Chacha ciphers set command flag as partial none to proceed + * with stateless processing */ + if (LAC_CIPHER_IS_CHACHA(cipherAlgorithm) || + LAC_CIPHER_IS_SM4(cipherAlgorithm)) { + ICP_QAT_FW_LA_PARTIAL_SET(*pLaCommandFlags, + ICP_QAT_FW_LA_PARTIAL_NONE); + return; + } + ICP_QAT_FW_LA_PARTIAL_SET(*pLaCommandFlags, qatPacketType); + + /* For ECB-mode ciphers, IV is NULL so update-state flag + * must be disabled always. + * For all other ciphers and auth + * update state is disabled for full packets and final partials */ + if (((laCmdId != ICP_QAT_FW_LA_CMD_AUTH) && + LAC_CIPHER_IS_ECB_MODE(cipherAlgorithm)) || + (ICP_QAT_FW_LA_PARTIAL_NONE == qatPacketType) || + (ICP_QAT_FW_LA_PARTIAL_END == qatPacketType)) { + ICP_QAT_FW_LA_UPDATE_STATE_SET(*pLaCommandFlags, + ICP_QAT_FW_LA_NO_UPDATE_STATE); + } + /* For first or middle partials set the update state command flag */ + else { + ICP_QAT_FW_LA_UPDATE_STATE_SET(*pLaCommandFlags, + ICP_QAT_FW_LA_UPDATE_STATE); + + if (laCmdId == ICP_QAT_FW_LA_CMD_AUTH) { + /* For hash only partial - verify and return auth result + * are + * disabled */ + ICP_QAT_FW_LA_RET_AUTH_SET( + *pLaCommandFlags, ICP_QAT_FW_LA_NO_RET_AUTH_RES); + + ICP_QAT_FW_LA_CMP_AUTH_SET( + *pLaCommandFlags, ICP_QAT_FW_LA_NO_CMP_AUTH_RES); + } + } + + if ((LAC_CIPHER_IS_GCM(cipherAlgorithm)) && + (LAC_CIPHER_IV_SIZE_GCM_12 == ivLenInBytes)) + + { + ICP_QAT_FW_LA_GCM_IV_LEN_FLAG_SET( + *pLaCommandFlags, ICP_QAT_FW_LA_GCM_IV_LEN_12_OCTETS); + } +} + +void +LacSymQat_packetTypeGet(CpaCySymPacketType packetType, + CpaCySymPacketType packetState, + Cpa32U *pQatPacketType) +{ + /* partial */ + if (CPA_CY_SYM_PACKET_TYPE_PARTIAL == packetType) { + /* if the previous state was full, then this is the first packet + */ + if (CPA_CY_SYM_PACKET_TYPE_FULL == packetState) { + *pQatPacketType = ICP_QAT_FW_LA_PARTIAL_START; + } else { + *pQatPacketType = ICP_QAT_FW_LA_PARTIAL_MID; + } + } + /* final partial */ + else if (CPA_CY_SYM_PACKET_TYPE_LAST_PARTIAL == packetType) { + *pQatPacketType = ICP_QAT_FW_LA_PARTIAL_END; + } + /* full packet - CPA_CY_SYM_PACKET_TYPE_FULL */ + else { + *pQatPacketType = ICP_QAT_FW_LA_PARTIAL_NONE; + } +} + +void +LacSymQat_LaSetDefaultFlags(icp_qat_fw_serv_specif_flags *laCmdFlags, + CpaCySymOp symOp) +{ + + ICP_QAT_FW_LA_PARTIAL_SET(*laCmdFlags, ICP_QAT_FW_LA_PARTIAL_NONE); + + ICP_QAT_FW_LA_UPDATE_STATE_SET(*laCmdFlags, + ICP_QAT_FW_LA_NO_UPDATE_STATE); + + if (symOp != CPA_CY_SYM_OP_CIPHER) { + ICP_QAT_FW_LA_RET_AUTH_SET(*laCmdFlags, + ICP_QAT_FW_LA_RET_AUTH_RES); + } else { + ICP_QAT_FW_LA_RET_AUTH_SET(*laCmdFlags, + ICP_QAT_FW_LA_NO_RET_AUTH_RES); + } + + ICP_QAT_FW_LA_CMP_AUTH_SET(*laCmdFlags, ICP_QAT_FW_LA_NO_CMP_AUTH_RES); + + ICP_QAT_FW_LA_GCM_IV_LEN_FLAG_SET( + *laCmdFlags, ICP_QAT_FW_LA_GCM_IV_LEN_NOT_12_OCTETS); +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_cipher.c b/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_cipher.c new file mode 100644 index 000000000000..b958d3723703 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_cipher.c @@ -0,0 +1,889 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_qat_cipher.c QAT-related support functions for Cipher + * + * @ingroup LacSymQat_Cipher + * + * @description Functions to support the QAT related operations for Cipher + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ + +#include "cpa.h" +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" +#include "lac_sym_qat.h" +#include "lac_sym_qat_cipher.h" +#include "lac_mem.h" +#include "lac_common.h" +#include "cpa_cy_sym.h" +#include "lac_sym_qat.h" +#include "lac_sym_cipher_defs.h" +#include "icp_qat_hw.h" +#include "icp_qat_fw_la.h" + +/***************************************************************************** + * Internal data + *****************************************************************************/ + +typedef enum _icp_qat_hw_key_depend { + IS_KEY_DEP_NO = 0, + IS_KEY_DEP_YES, +} icp_qat_hw_key_depend; + +/* LAC_CIPHER_IS_XTS_MODE */ +static const uint8_t key_size_xts[] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ICP_QAT_HW_CIPHER_ALGO_AES128, // ICP_QAT_HW_AES_128_XTS_KEY_SZ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ICP_QAT_HW_CIPHER_ALGO_AES256 // ICP_QAT_HW_AES_256_XTS_KEY_SZ +}; +/* LAC_CIPHER_IS_AES */ +static const uint8_t key_size_aes[] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ICP_QAT_HW_CIPHER_ALGO_AES128, // ICP_QAT_HW_AES_128_KEY_SZ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ICP_QAT_HW_CIPHER_ALGO_AES192, // ICP_QAT_HW_AES_192_KEY_SZ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ICP_QAT_HW_CIPHER_ALGO_AES256 // ICP_QAT_HW_AES_256_KEY_SZ +}; +/* LAC_CIPHER_IS_AES_F8 */ +static const uint8_t key_size_f8[] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ICP_QAT_HW_CIPHER_ALGO_AES128, // ICP_QAT_HW_AES_128_F8_KEY_SZ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ICP_QAT_HW_CIPHER_ALGO_AES192, // ICP_QAT_HW_AES_192_F8_KEY_SZ + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ICP_QAT_HW_CIPHER_ALGO_AES256 // ICP_QAT_HW_AES_256_F8_KEY_SZ +}; +/* LAC_CIPHER_IS_SM4 */ +static const uint8_t key_size_sm4[] = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + ICP_QAT_HW_CIPHER_ALGO_SM4 // ICP_QAT_HW_SM4_KEY_SZ +}; + +typedef struct _icp_qat_hw_cipher_info { + icp_qat_hw_cipher_algo_t algorithm; + icp_qat_hw_cipher_mode_t mode; + icp_qat_hw_cipher_convert_t key_convert[2]; + icp_qat_hw_cipher_dir_t dir[2]; + icp_qat_hw_key_depend isKeyLenDepend; + const uint8_t *pAlgByKeySize; +} icp_qat_hw_cipher_info; + +static const icp_qat_hw_cipher_info icp_qat_alg_info[] = + { + /* CPA_CY_SYM_CIPHER_NULL */ + { + ICP_QAT_HW_CIPHER_ALGO_NULL, + ICP_QAT_HW_CIPHER_ECB_MODE, + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_NO, + NULL, + }, + /* CPA_CY_SYM_CIPHER_ARC4 */ + { + ICP_QAT_HW_CIPHER_ALGO_ARC4, + ICP_QAT_HW_CIPHER_ECB_MODE, + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + /* Streaming ciphers are a special case. Decrypt = encrypt */ + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_ENCRYPT }, + IS_KEY_DEP_NO, + NULL, + }, + /* CPA_CY_SYM_CIPHER_AES_ECB */ + { + ICP_QAT_HW_CIPHER_ALGO_AES128, + ICP_QAT_HW_CIPHER_ECB_MODE, + /* AES decrypt key needs to be reversed. Instead of reversing the key + * at session registration, it is instead reversed on-the-fly by + * setting the KEY_CONVERT bit here + */ + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_KEY_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_YES, + key_size_aes, + }, + /* CPA_CY_SYM_CIPHER_AES_CBC */ + { + ICP_QAT_HW_CIPHER_ALGO_AES128, + ICP_QAT_HW_CIPHER_CBC_MODE, + /* AES decrypt key needs to be reversed. Instead of reversing the key + * at session registration, it is instead reversed on-the-fly by + * setting the KEY_CONVERT bit here + */ + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_KEY_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_YES, + key_size_aes, + }, + /* CPA_CY_SYM_CIPHER_AES_CTR */ + { + ICP_QAT_HW_CIPHER_ALGO_AES128, + ICP_QAT_HW_CIPHER_CTR_MODE, + /* AES decrypt key needs to be reversed. Instead of reversing the key + * at session registration, it is instead reversed on-the-fly by + * setting the KEY_CONVERT bit here + */ + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + /* Streaming ciphers are a special case. Decrypt = encrypt + * Overriding default values previously set for AES + */ + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_ENCRYPT }, + IS_KEY_DEP_YES, + key_size_aes, + }, + /* CPA_CY_SYM_CIPHER_AES_CCM */ + { + ICP_QAT_HW_CIPHER_ALGO_AES128, + ICP_QAT_HW_CIPHER_CTR_MODE, + /* AES decrypt key needs to be reversed. Instead of reversing the key + * at session registration, it is instead reversed on-the-fly by + * setting the KEY_CONVERT bit here + */ + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + /* Streaming ciphers are a special case. Decrypt = encrypt + * Overriding default values previously set for AES + */ + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_ENCRYPT }, + IS_KEY_DEP_YES, + key_size_aes, + }, + /* CPA_CY_SYM_CIPHER_AES_GCM */ + { + ICP_QAT_HW_CIPHER_ALGO_AES128, + ICP_QAT_HW_CIPHER_CTR_MODE, + /* AES decrypt key needs to be reversed. Instead of reversing the key + * at session registration, it is instead reversed on-the-fly by + * setting the KEY_CONVERT bit here + */ + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + /* Streaming ciphers are a special case. Decrypt = encrypt + * Overriding default values previously set for AES + */ + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_ENCRYPT }, + IS_KEY_DEP_YES, + key_size_aes, + }, + /* CPA_CY_SYM_CIPHER_DES_ECB */ + { + ICP_QAT_HW_CIPHER_ALGO_DES, + ICP_QAT_HW_CIPHER_ECB_MODE, + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_NO, + NULL, + }, + /* CPA_CY_SYM_CIPHER_DES_CBC */ + { + ICP_QAT_HW_CIPHER_ALGO_DES, + ICP_QAT_HW_CIPHER_CBC_MODE, + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_NO, + NULL, + }, + /* CPA_CY_SYM_CIPHER_3DES_ECB */ + { + ICP_QAT_HW_CIPHER_ALGO_3DES, + ICP_QAT_HW_CIPHER_ECB_MODE, + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_NO, + NULL, + }, + /* CPA_CY_SYM_CIPHER_3DES_CBC */ + { + ICP_QAT_HW_CIPHER_ALGO_3DES, + ICP_QAT_HW_CIPHER_CBC_MODE, + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_NO, + NULL, + }, + /* CPA_CY_SYM_CIPHER_3DES_CTR */ + { + ICP_QAT_HW_CIPHER_ALGO_3DES, + ICP_QAT_HW_CIPHER_CTR_MODE, + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + /* Streaming ciphers are a special case. Decrypt = encrypt + * Overriding default values previously set for AES + */ + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_ENCRYPT }, + IS_KEY_DEP_NO, + NULL, + }, + /* CPA_CY_SYM_CIPHER_KASUMI_F8 */ + { + ICP_QAT_HW_CIPHER_ALGO_KASUMI, + ICP_QAT_HW_CIPHER_F8_MODE, + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + /* Streaming ciphers are a special case. Decrypt = encrypt */ + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_ENCRYPT }, + IS_KEY_DEP_NO, + NULL, + }, + /* CPA_CY_SYM_CIPHER_SNOW3G_UEA2 */ + { + /* The KEY_CONVERT bit has to be set for Snow_3G operation */ + ICP_QAT_HW_CIPHER_ALGO_SNOW_3G_UEA2, + ICP_QAT_HW_CIPHER_ECB_MODE, + { ICP_QAT_HW_CIPHER_KEY_CONVERT, ICP_QAT_HW_CIPHER_KEY_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_NO, + NULL, + }, + /* CPA_CY_SYM_CIPHER_AES_F8 */ + { + ICP_QAT_HW_CIPHER_ALGO_AES128, + ICP_QAT_HW_CIPHER_F8_MODE, + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + /* Streaming ciphers are a special case. Decrypt = encrypt */ + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_ENCRYPT }, + IS_KEY_DEP_YES, + key_size_f8, + }, + /* CPA_CY_SYM_CIPHER_AES_XTS */ + { + ICP_QAT_HW_CIPHER_ALGO_AES128, + ICP_QAT_HW_CIPHER_XTS_MODE, + /* AES decrypt key needs to be reversed. Instead of reversing the key + * at session registration, it is instead reversed on-the-fly by + * setting the KEY_CONVERT bit here + */ + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_KEY_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_YES, + key_size_xts, + }, + /* CPA_CY_SYM_CIPHER_ZUC_EEA3 */ + { + ICP_QAT_HW_CIPHER_ALGO_ZUC_3G_128_EEA3, + ICP_QAT_HW_CIPHER_ECB_MODE, + { ICP_QAT_HW_CIPHER_KEY_CONVERT, ICP_QAT_HW_CIPHER_KEY_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_NO, + NULL, + }, + /* CPA_CY_SYM_CIPHER_CHACHA */ + { + ICP_QAT_HW_CIPHER_ALGO_CHACHA20_POLY1305, + ICP_QAT_HW_CIPHER_CTR_MODE, + { ICP_QAT_HW_CIPHER_KEY_CONVERT, ICP_QAT_HW_CIPHER_KEY_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_NO, + NULL, + }, + /* CPA_CY_SYM_CIPHER_SM4_ECB */ + { + ICP_QAT_HW_CIPHER_ALGO_SM4, + ICP_QAT_HW_CIPHER_ECB_MODE, + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_KEY_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_YES, + key_size_sm4, + }, + /* CPA_CY_SYM_CIPHER_SM4_CBC */ + { + ICP_QAT_HW_CIPHER_ALGO_SM4, + ICP_QAT_HW_CIPHER_CBC_MODE, + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_KEY_CONVERT }, + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_DECRYPT }, + IS_KEY_DEP_YES, + key_size_sm4, + }, + /* CPA_CY_SYM_CIPHER_SM4_CTR */ + { + ICP_QAT_HW_CIPHER_ALGO_SM4, + ICP_QAT_HW_CIPHER_CTR_MODE, + { ICP_QAT_HW_CIPHER_NO_CONVERT, ICP_QAT_HW_CIPHER_NO_CONVERT }, + /* Streaming ciphers are a special case. Decrypt = encrypt */ + { ICP_QAT_HW_CIPHER_ENCRYPT, ICP_QAT_HW_CIPHER_ENCRYPT }, + IS_KEY_DEP_YES, + key_size_sm4, + }, + }; + +/***************************************************************************** + * Internal functions + *****************************************************************************/ + +void +LacSymQat_CipherCtrlBlockWrite(icp_qat_la_bulk_req_ftr_t *pMsg, + Cpa32U cipherAlgorithm, + Cpa32U targetKeyLenInBytes, + icp_qat_fw_slice_t nextSlice, + Cpa8U cipherCfgOffsetInQuadWord) +{ + icp_qat_fw_cipher_cd_ctrl_hdr_t *cd_ctrl = + (icp_qat_fw_cipher_cd_ctrl_hdr_t *)&(pMsg->cd_ctrl); + + /* state_padding_sz is nonzero for f8 mode only */ + cd_ctrl->cipher_padding_sz = 0; + + /* Base Key is not passed down to QAT in the case of ARC4 or NULL */ + if (LAC_CIPHER_IS_ARC4(cipherAlgorithm) || + LAC_CIPHER_IS_NULL(cipherAlgorithm)) { + cd_ctrl->cipher_key_sz = 0; + } else if (LAC_CIPHER_IS_KASUMI(cipherAlgorithm)) { + cd_ctrl->cipher_key_sz = + LAC_BYTES_TO_QUADWORDS(ICP_QAT_HW_KASUMI_F8_KEY_SZ); + cd_ctrl->cipher_padding_sz = + ICP_QAT_HW_MODE_F8_NUM_REG_TO_CLEAR; + } else if (LAC_CIPHER_IS_SNOW3G_UEA2(cipherAlgorithm)) { + /* For Snow3G UEA2 content descriptor key size is + key size plus iv size */ + cd_ctrl->cipher_key_sz = + LAC_BYTES_TO_QUADWORDS(ICP_QAT_HW_SNOW_3G_UEA2_KEY_SZ + + ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ); + } else if (LAC_CIPHER_IS_AES_F8(cipherAlgorithm)) { + cd_ctrl->cipher_key_sz = + LAC_BYTES_TO_QUADWORDS(targetKeyLenInBytes); + cd_ctrl->cipher_padding_sz = + 2 * ICP_QAT_HW_MODE_F8_NUM_REG_TO_CLEAR; + } else if (LAC_CIPHER_IS_ZUC_EEA3(cipherAlgorithm)) { + /* For ZUC EEA3 content descriptor key size is + key size plus iv size */ + cd_ctrl->cipher_key_sz = + LAC_BYTES_TO_QUADWORDS(ICP_QAT_HW_ZUC_3G_EEA3_KEY_SZ + + ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ); + } else { + cd_ctrl->cipher_key_sz = + LAC_BYTES_TO_QUADWORDS(targetKeyLenInBytes); + } + + cd_ctrl->cipher_state_sz = LAC_BYTES_TO_QUADWORDS( + LacSymQat_CipherIvSizeBytesGet(cipherAlgorithm)); + + cd_ctrl->cipher_cfg_offset = cipherCfgOffsetInQuadWord; + + ICP_QAT_FW_COMN_NEXT_ID_SET(cd_ctrl, nextSlice); + ICP_QAT_FW_COMN_CURR_ID_SET(cd_ctrl, ICP_QAT_FW_SLICE_CIPHER); +} + +void +LacSymQat_CipherGetCfgData(lac_session_desc_t *pSession, + icp_qat_hw_cipher_algo_t *pAlgorithm, + icp_qat_hw_cipher_mode_t *pMode, + icp_qat_hw_cipher_dir_t *pDir, + icp_qat_hw_cipher_convert_t *pKey_convert) +{ + + CpaCySymCipherAlgorithm cipherAlgorithm = 0; + icp_qat_hw_cipher_dir_t cipherDirection = 0; + + /* Set defaults */ + *pKey_convert = ICP_QAT_HW_CIPHER_NO_CONVERT; + *pAlgorithm = ICP_QAT_HW_CIPHER_ALGO_NULL; + *pMode = ICP_QAT_HW_CIPHER_ECB_MODE; + *pDir = ICP_QAT_HW_CIPHER_ENCRYPT; + + /* decrease since it's numbered from 1 instead of 0 */ + cipherAlgorithm = pSession->cipherAlgorithm - 1; + cipherDirection = + pSession->cipherDirection == CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT ? + ICP_QAT_HW_CIPHER_ENCRYPT : + ICP_QAT_HW_CIPHER_DECRYPT; + + *pAlgorithm = icp_qat_alg_info[cipherAlgorithm].algorithm; + *pMode = icp_qat_alg_info[cipherAlgorithm].mode; + *pDir = icp_qat_alg_info[cipherAlgorithm].dir[cipherDirection]; + *pKey_convert = + icp_qat_alg_info[cipherAlgorithm].key_convert[cipherDirection]; + + if (IS_KEY_DEP_NO != icp_qat_alg_info[cipherAlgorithm].isKeyLenDepend) { + *pAlgorithm = icp_qat_alg_info[cipherAlgorithm] + .pAlgByKeySize[pSession->cipherKeyLenInBytes]; + } + /* Set the mode */ + if (LAC_CIPHER_IS_CTR_MODE(pSession->cipherAlgorithm)) { + *pMode = ICP_QAT_HW_CIPHER_CTR_MODE; + *pKey_convert = ICP_QAT_HW_CIPHER_NO_CONVERT; + /* CCP and AES_GCM single pass, despite being limited to + * CTR/AEAD mode, + * support both Encrypt/Decrypt modes - this is because of the + * differences in the hash computation/verification paths in + * encrypt/decrypt modes respectively. + * By default CCP is set as CTR Mode.Set AEAD Mode for AES_GCM. + */ + if (pSession->isSinglePass) { + if (LAC_CIPHER_IS_GCM(pSession->cipherAlgorithm)) + *pMode = ICP_QAT_HW_CIPHER_AEAD_MODE; + if (cipherDirection == ICP_QAT_HW_CIPHER_DECRYPT) + *pDir = ICP_QAT_HW_CIPHER_DECRYPT; + } + } +} + +void +LacSymQat_CipherHwBlockPopulateCfgData(lac_session_desc_t *pSession, + const void *pCipherHwBlock, + Cpa32U *pSizeInBytes) +{ + icp_qat_hw_cipher_algo_t algorithm = ICP_QAT_HW_CIPHER_ALGO_NULL; + icp_qat_hw_cipher_mode_t mode = ICP_QAT_HW_CIPHER_ECB_MODE; + icp_qat_hw_cipher_dir_t dir = ICP_QAT_HW_CIPHER_ENCRYPT; + icp_qat_hw_cipher_convert_t key_convert; + icp_qat_hw_cipher_config_t *pCipherConfig = + (icp_qat_hw_cipher_config_t *)pCipherHwBlock; + Cpa32U aed_hash_cmp_length = 0; + + *pSizeInBytes = 0; + + LacSymQat_CipherGetCfgData( + pSession, &algorithm, &mode, &dir, &key_convert); + + /* Build the cipher config into the hardware setup block */ + if (pSession->isSinglePass) { + aed_hash_cmp_length = pSession->hashResultSize; + pCipherConfig->reserved = ICP_QAT_HW_CIPHER_CONFIG_BUILD_UPPER( + pSession->aadLenInBytes); + } else { + pCipherConfig->reserved = 0; + } + + pCipherConfig->val = ICP_QAT_HW_CIPHER_CONFIG_BUILD( + mode, algorithm, key_convert, dir, aed_hash_cmp_length); + + *pSizeInBytes = sizeof(icp_qat_hw_cipher_config_t); +} + +void +LacSymQat_CipherHwBlockPopulateKeySetup( + const CpaCySymCipherSetupData *pCipherSetupData, + Cpa32U targetKeyLenInBytes, + const void *pCipherHwBlock, + Cpa32U *pSizeInBytes) +{ + Cpa8U *pCipherKey = (Cpa8U *)pCipherHwBlock; + Cpa32U actualKeyLenInBytes = pCipherSetupData->cipherKeyLenInBytes; + + *pSizeInBytes = 0; + + /* Key is copied into content descriptor for all cases except for + * Arc4 and Null cipher */ + if (!(LAC_CIPHER_IS_ARC4(pCipherSetupData->cipherAlgorithm) || + LAC_CIPHER_IS_NULL(pCipherSetupData->cipherAlgorithm))) { + /* Set the Cipher key field in the cipher block */ + memcpy(pCipherKey, + pCipherSetupData->pCipherKey, + actualKeyLenInBytes); + /* Pad the key with 0's if required */ + if (0 < (targetKeyLenInBytes - actualKeyLenInBytes)) { + LAC_OS_BZERO(pCipherKey + actualKeyLenInBytes, + targetKeyLenInBytes - actualKeyLenInBytes); + } + *pSizeInBytes += targetKeyLenInBytes; + + /* For Kasumi in F8 mode Cipher Key is concatenated with + * Cipher Key XOR-ed with Key Modifier (CK||CK^KM) */ + if (LAC_CIPHER_IS_KASUMI(pCipherSetupData->cipherAlgorithm)) { + Cpa32U wordIndex = 0; + Cpa32U *pu32CipherKey = + (Cpa32U *)pCipherSetupData->pCipherKey; + Cpa32U *pTempKey = + (Cpa32U *)(pCipherKey + targetKeyLenInBytes); + + /* XOR Key with KASUMI F8 key modifier at 4 bytes level + */ + for (wordIndex = 0; wordIndex < + LAC_BYTES_TO_LONGWORDS(targetKeyLenInBytes); + wordIndex++) { + pTempKey[wordIndex] = pu32CipherKey[wordIndex] ^ + LAC_CIPHER_KASUMI_F8_KEY_MODIFIER_4_BYTES; + } + + *pSizeInBytes += targetKeyLenInBytes; + + /* also add padding for F8 */ + *pSizeInBytes += LAC_QUADWORDS_TO_BYTES( + ICP_QAT_HW_MODE_F8_NUM_REG_TO_CLEAR); + LAC_OS_BZERO((Cpa8U *)pTempKey + targetKeyLenInBytes, + LAC_QUADWORDS_TO_BYTES( + ICP_QAT_HW_MODE_F8_NUM_REG_TO_CLEAR)); + } + /* For AES in F8 mode Cipher Key is concatenated with + * Cipher Key XOR-ed with Key Mask (CK||CK^KM) */ + else if (LAC_CIPHER_IS_AES_F8( + pCipherSetupData->cipherAlgorithm)) { + Cpa32U index = 0; + Cpa8U *pTempKey = + pCipherKey + (targetKeyLenInBytes / 2); + *pSizeInBytes += targetKeyLenInBytes; + /* XOR Key with key Mask */ + for (index = 0; index < targetKeyLenInBytes; index++) { + pTempKey[index] = + pCipherKey[index] ^ pTempKey[index]; + } + pTempKey = (pCipherKey + targetKeyLenInBytes); + /* also add padding for AES F8 */ + *pSizeInBytes += 2 * targetKeyLenInBytes; + LAC_OS_BZERO(pTempKey, 2 * targetKeyLenInBytes); + } else if (LAC_CIPHER_IS_SNOW3G_UEA2( + pCipherSetupData->cipherAlgorithm)) { + /* For Snow3G zero area after the key for FW */ + LAC_OS_BZERO(pCipherKey + targetKeyLenInBytes, + ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ); + + *pSizeInBytes += ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ; + } else if (LAC_CIPHER_IS_ZUC_EEA3( + pCipherSetupData->cipherAlgorithm)) { + /* For ZUC zero area after the key for FW */ + LAC_OS_BZERO(pCipherKey + targetKeyLenInBytes, + ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ); + + *pSizeInBytes += ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ; + } + } +} + +/***************************************************************************** + * External functions + *****************************************************************************/ + +Cpa8U +LacSymQat_CipherBlockSizeBytesGet(CpaCySymCipherAlgorithm cipherAlgorithm) +{ + if (LAC_CIPHER_IS_ARC4(cipherAlgorithm)) { + return LAC_CIPHER_ARC4_BLOCK_LEN_BYTES; + } else if (LAC_CIPHER_IS_AES(cipherAlgorithm) || + LAC_CIPHER_IS_AES_F8(cipherAlgorithm)) { + return ICP_QAT_HW_AES_BLK_SZ; + } else if (LAC_CIPHER_IS_DES(cipherAlgorithm)) { + return ICP_QAT_HW_DES_BLK_SZ; + } else if (LAC_CIPHER_IS_TRIPLE_DES(cipherAlgorithm)) { + return ICP_QAT_HW_3DES_BLK_SZ; + } else if (LAC_CIPHER_IS_KASUMI(cipherAlgorithm)) { + return ICP_QAT_HW_KASUMI_BLK_SZ; + } else if (LAC_CIPHER_IS_SNOW3G_UEA2(cipherAlgorithm)) { + return ICP_QAT_HW_SNOW_3G_BLK_SZ; + } else if (LAC_CIPHER_IS_ZUC_EEA3(cipherAlgorithm)) { + return ICP_QAT_HW_ZUC_3G_BLK_SZ; + } else if (LAC_CIPHER_IS_NULL(cipherAlgorithm)) { + return LAC_CIPHER_NULL_BLOCK_LEN_BYTES; + } else if (LAC_CIPHER_IS_CHACHA(cipherAlgorithm)) { + return ICP_QAT_HW_CHACHAPOLY_BLK_SZ; + } else if (LAC_CIPHER_IS_SM4(cipherAlgorithm)) { + return ICP_QAT_HW_SM4_BLK_SZ; + } else { + QAT_UTILS_LOG("Algorithm not supported in Cipher\n"); + return 0; + } +} + +Cpa32U +LacSymQat_CipherIvSizeBytesGet(CpaCySymCipherAlgorithm cipherAlgorithm) +{ + if (CPA_CY_SYM_CIPHER_ARC4 == cipherAlgorithm) { + return LAC_CIPHER_ARC4_STATE_LEN_BYTES; + } else if (LAC_CIPHER_IS_KASUMI(cipherAlgorithm)) { + return ICP_QAT_HW_KASUMI_BLK_SZ; + } else if (LAC_CIPHER_IS_SNOW3G_UEA2(cipherAlgorithm)) { + return ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ; + } else if (LAC_CIPHER_IS_ZUC_EEA3(cipherAlgorithm)) { + return ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ; + } else if (LAC_CIPHER_IS_CHACHA(cipherAlgorithm)) { + return ICP_QAT_HW_CHACHAPOLY_IV_SZ; + } else if (LAC_CIPHER_IS_ECB_MODE(cipherAlgorithm)) { + return 0; + } else { + return (Cpa32U)LacSymQat_CipherBlockSizeBytesGet( + cipherAlgorithm); + } +} + +inline CpaStatus +LacSymQat_CipherRequestParamsPopulate(icp_qat_fw_la_bulk_req_t *pReq, + Cpa32U cipherOffsetInBytes, + Cpa32U cipherLenInBytes, + Cpa64U ivBufferPhysAddr, + Cpa8U *pIvBufferVirt) +{ + icp_qat_fw_la_cipher_req_params_t *pCipherReqParams; + icp_qat_fw_cipher_cd_ctrl_hdr_t *pCipherCdCtrlHdr; + icp_qat_fw_serv_specif_flags *pCipherSpecificFlags; + + pCipherReqParams = (icp_qat_fw_la_cipher_req_params_t + *)((Cpa8U *)&(pReq->serv_specif_rqpars) + + ICP_QAT_FW_CIPHER_REQUEST_PARAMETERS_OFFSET); + pCipherCdCtrlHdr = (icp_qat_fw_cipher_cd_ctrl_hdr_t *)&(pReq->cd_ctrl); + pCipherSpecificFlags = &(pReq->comn_hdr.serv_specif_flags); + + pCipherReqParams->cipher_offset = cipherOffsetInBytes; + pCipherReqParams->cipher_length = cipherLenInBytes; + + /* Don't copy the buffer into the Msg if + * it's too big for the cipher_IV_array + * OR if the FW needs to update it + * OR if there's no buffer supplied + * OR if last partial + */ + if ((pCipherCdCtrlHdr->cipher_state_sz > + LAC_SYM_QAT_HASH_IV_REQ_MAX_SIZE_QW) || + (ICP_QAT_FW_LA_UPDATE_STATE_GET(*pCipherSpecificFlags) == + ICP_QAT_FW_LA_UPDATE_STATE) || + (pIvBufferVirt == NULL) || + (ICP_QAT_FW_LA_PARTIAL_GET(*pCipherSpecificFlags) == + ICP_QAT_FW_LA_PARTIAL_END)) { + /* Populate the field with a ptr to the flat buffer */ + pCipherReqParams->u.s.cipher_IV_ptr = ivBufferPhysAddr; + pCipherReqParams->u.s.resrvd1 = 0; + /* Set the flag indicating the field format */ + ICP_QAT_FW_LA_CIPH_IV_FLD_FLAG_SET( + *pCipherSpecificFlags, ICP_QAT_FW_CIPH_IV_64BIT_PTR); + } else { + /* Populate the field with the contents of the buffer, + * zero field first as data may be smaller than the field */ + memset(pCipherReqParams->u.cipher_IV_array, + 0, + LAC_LONGWORDS_TO_BYTES(ICP_QAT_FW_NUM_LONGWORDS_4)); + + /* We force a specific compiler optimisation here. The length + * to + * be copied turns out to be always 16, and by coding a memcpy + * with + * a literal value the compiler will compile inline code (in + * fact, + * only two vector instructions) to effect the copy. This gives + * us + * a huge performance increase. + */ + unsigned long cplen = + LAC_QUADWORDS_TO_BYTES(pCipherCdCtrlHdr->cipher_state_sz); + + if (cplen == 16) + memcpy(pCipherReqParams->u.cipher_IV_array, + pIvBufferVirt, + 16); + else + memcpy(pCipherReqParams->u.cipher_IV_array, + pIvBufferVirt, + cplen); + /* Set the flag indicating the field format */ + ICP_QAT_FW_LA_CIPH_IV_FLD_FLAG_SET( + *pCipherSpecificFlags, ICP_QAT_FW_CIPH_IV_16BYTE_DATA); + } + + return CPA_STATUS_SUCCESS; +} + +void +LacSymQat_CipherArc4StateInit(const Cpa8U *pKey, + Cpa32U keyLenInBytes, + Cpa8U *pArc4CipherState) +{ + Cpa32U i = 0; + Cpa32U j = 0; + Cpa32U k = 0; + + for (i = 0; i < LAC_CIPHER_ARC4_KEY_MATRIX_LEN_BYTES; ++i) { + pArc4CipherState[i] = (Cpa8U)i; + } + + for (i = 0; i < LAC_CIPHER_ARC4_KEY_MATRIX_LEN_BYTES; ++i) { + Cpa8U swap = 0; + + if (k >= keyLenInBytes) + k -= keyLenInBytes; + + j = (j + pArc4CipherState[i] + pKey[k]); + if (j >= LAC_CIPHER_ARC4_KEY_MATRIX_LEN_BYTES) + j %= LAC_CIPHER_ARC4_KEY_MATRIX_LEN_BYTES; + ++k; + + /* Swap state[i] & state[j] */ + swap = pArc4CipherState[i]; + pArc4CipherState[i] = pArc4CipherState[j]; + pArc4CipherState[j] = swap; + } + + /* Initialise i & j values for QAT */ + pArc4CipherState[LAC_CIPHER_ARC4_KEY_MATRIX_LEN_BYTES] = 0; + pArc4CipherState[LAC_CIPHER_ARC4_KEY_MATRIX_LEN_BYTES + 1] = 0; +} + +/* Update the cipher_key_sz in the Request cache prepared and stored + * in the session */ +void +LacSymQat_CipherXTSModeUpdateKeyLen(lac_session_desc_t *pSessionDesc, + Cpa32U newKeySizeInBytes) +{ + icp_qat_fw_cipher_cd_ctrl_hdr_t *pCipherControlBlock = NULL; + + pCipherControlBlock = (icp_qat_fw_cipher_cd_ctrl_hdr_t *)&( + pSessionDesc->reqCacheFtr.cd_ctrl); + + pCipherControlBlock->cipher_key_sz = + LAC_BYTES_TO_QUADWORDS(newKeySizeInBytes); +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_hash.c b/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_hash.c new file mode 100644 index 000000000000..a39734ad16d0 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_hash.c @@ -0,0 +1,942 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_qat_hash.c + * + * @ingroup LacSymQatHash + * + * Implementation for populating QAT data structures for hash operation + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ + +#include "cpa.h" +#include "cpa_cy_sym.h" +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" +#include "lac_log.h" +#include "lac_mem.h" +#include "lac_sym.h" +#include "lac_common.h" +#include "lac_sym_qat.h" +#include "lac_list.h" +#include "lac_sal_types.h" +#include "lac_sym_qat_hash.h" +#include "lac_sym_qat_hash_defs_lookup.h" + +/** + * This structure contains pointers into the hash setup block of the + * security descriptor. As the hash setup block contains fields that + * are of variable length, pointers must be calculated to these fields + * and the hash setup block is populated using these pointers. */ +typedef struct lac_hash_blk_ptrs_s { + icp_qat_hw_auth_setup_t *pInHashSetup; + /**< inner hash setup */ + Cpa8U *pInHashInitState1; + /**< inner initial state 1 */ + Cpa8U *pInHashInitState2; + /**< inner initial state 2 */ + icp_qat_hw_auth_setup_t *pOutHashSetup; + /**< outer hash setup */ + Cpa8U *pOutHashInitState1; + /**< outer hash initial state */ +} lac_hash_blk_ptrs_t; + +typedef struct lac_hash_blk_ptrs_optimised_s { + Cpa8U *pInHashInitState1; + /**< inner initial state 1 */ + Cpa8U *pInHashInitState2; + /**< inner initial state 2 */ + +} lac_hash_blk_ptrs_optimised_t; + +/** + * This function calculates the pointers into the hash setup block + * based on the control block + * + * @param[in] pHashControlBlock Pointer to hash control block + * @param[in] pHwBlockBase pointer to base of hardware block + * @param[out] pHashBlkPtrs structure containing pointers to + * various fields in the hash setup block + * + * @return void + */ +static void +LacSymQat_HashHwBlockPtrsInit(icp_qat_fw_auth_cd_ctrl_hdr_t *pHashControlBlock, + void *pHwBlockBase, + lac_hash_blk_ptrs_t *pHashBlkPtrs); + +static void +LacSymQat_HashSetupBlockOptimisedFormatInit( + const CpaCySymHashSetupData *pHashSetupData, + icp_qat_fw_auth_cd_ctrl_hdr_t *pHashControlBlock, + void *pHwBlockBase, + icp_qat_hw_auth_mode_t qatHashMode, + lac_sym_qat_hash_precompute_info_t *pPrecompute, + lac_sym_qat_hash_defs_t *pHashDefs, + lac_sym_qat_hash_defs_t *pOuterHashDefs); + +/** + * This function populates the hash setup block + * + * @param[in] pHashSetupData Pointer to the hash context + * @param[in] pHashControlBlock Pointer to hash control block + * @param[in] pHwBlockBase pointer to base of hardware block + * @param[in] qatHashMode QAT hash mode + * @param[in] pPrecompute For auth mode, this is the pointer + * to the precompute data. Otherwise this + * should be set to NULL + * @param[in] pHashDefs Pointer to Hash definitions + * @param[in] pOuterHashDefs Pointer to Outer Hash definitions. + * Required for nested hash mode only + * + * @return void + */ +static void +LacSymQat_HashSetupBlockInit(const CpaCySymHashSetupData *pHashSetupData, + icp_qat_fw_auth_cd_ctrl_hdr_t *pHashControlBlock, + void *pHwBlockBase, + icp_qat_hw_auth_mode_t qatHashMode, + lac_sym_qat_hash_precompute_info_t *pPrecompute, + lac_sym_qat_hash_defs_t *pHashDefs, + lac_sym_qat_hash_defs_t *pOuterHashDefs); + +/** @ingroup LacSymQatHash */ +void +LacSymQat_HashGetCfgData(CpaInstanceHandle pInstance, + icp_qat_hw_auth_mode_t qatHashMode, + CpaCySymHashMode apiHashMode, + CpaCySymHashAlgorithm apiHashAlgorithm, + icp_qat_hw_auth_algo_t *pQatAlgorithm, + CpaBoolean *pQatNested) +{ + lac_sym_qat_hash_defs_t *pHashDefs = NULL; + + LacSymQat_HashDefsLookupGet(pInstance, apiHashAlgorithm, &pHashDefs); + *pQatAlgorithm = pHashDefs->qatInfo->algoEnc; + + if (IS_HASH_MODE_2(qatHashMode)) { + /* set bit for nested hashing */ + *pQatNested = ICP_QAT_FW_AUTH_HDR_FLAG_DO_NESTED; + } + /* Nested hash in mode 0. */ + else if (CPA_CY_SYM_HASH_MODE_NESTED == apiHashMode) { + /* set bit for nested hashing */ + *pQatNested = ICP_QAT_FW_AUTH_HDR_FLAG_DO_NESTED; + } + /* mode0 - plain or mode1 - auth */ + else { + *pQatNested = ICP_QAT_FW_AUTH_HDR_FLAG_NO_NESTED; + } +} + +/** @ingroup LacSymQatHash */ +void +LacSymQat_HashContentDescInit(icp_qat_la_bulk_req_ftr_t *pMsg, + CpaInstanceHandle instanceHandle, + const CpaCySymHashSetupData *pHashSetupData, + void *pHwBlockBase, + Cpa32U hwBlockOffsetInQuadWords, + icp_qat_fw_slice_t nextSlice, + icp_qat_hw_auth_mode_t qatHashMode, + CpaBoolean useSymConstantsTable, + CpaBoolean useOptimisedContentDesc, + lac_sym_qat_hash_precompute_info_t *pPrecompute, + Cpa32U *pHashBlkSizeInBytes) +{ + + icp_qat_fw_auth_cd_ctrl_hdr_t *cd_ctrl = + (icp_qat_fw_auth_cd_ctrl_hdr_t *)&(pMsg->cd_ctrl); + lac_sym_qat_hash_defs_t *pHashDefs = NULL; + lac_sym_qat_hash_defs_t *pOuterHashDefs = NULL; + Cpa32U hashSetupBlkSize = 0; + + /* setup the offset in QuadWords into the hw blk */ + cd_ctrl->hash_cfg_offset = hwBlockOffsetInQuadWords; + + ICP_QAT_FW_COMN_NEXT_ID_SET(cd_ctrl, nextSlice); + ICP_QAT_FW_COMN_CURR_ID_SET(cd_ctrl, ICP_QAT_FW_SLICE_AUTH); + + LacSymQat_HashDefsLookupGet(instanceHandle, + pHashSetupData->hashAlgorithm, + &pHashDefs); + + /* Hmac in mode 2 TLS */ + if (IS_HASH_MODE_2(qatHashMode)) { + /* Set bit for nested hashing. + * Make sure not to overwrite other flags in hash_flags byte. + */ + ICP_QAT_FW_HASH_FLAG_AUTH_HDR_NESTED_SET( + cd_ctrl->hash_flags, ICP_QAT_FW_AUTH_HDR_FLAG_DO_NESTED); + } + /* Nested hash in mode 0 */ + else if (CPA_CY_SYM_HASH_MODE_NESTED == pHashSetupData->hashMode) { + /* Set bit for nested hashing. + * Make sure not to overwrite other flags in hash_flags byte. + */ + ICP_QAT_FW_HASH_FLAG_AUTH_HDR_NESTED_SET( + cd_ctrl->hash_flags, ICP_QAT_FW_AUTH_HDR_FLAG_DO_NESTED); + } + /* mode0 - plain or mode1 - auth */ + else { + ICP_QAT_FW_HASH_FLAG_AUTH_HDR_NESTED_SET( + cd_ctrl->hash_flags, ICP_QAT_FW_AUTH_HDR_FLAG_NO_NESTED); + } + + /* set the final digest size */ + cd_ctrl->final_sz = pHashSetupData->digestResultLenInBytes; + + /* set the state1 size */ + cd_ctrl->inner_state1_sz = + LAC_ALIGN_POW2_ROUNDUP(pHashDefs->qatInfo->state1Length, + LAC_QUAD_WORD_IN_BYTES); + + /* set the inner result size to the digest length */ + cd_ctrl->inner_res_sz = pHashDefs->algInfo->digestLength; + + /* set the state2 size - only for mode 1 Auth algos and AES CBC MAC */ + if (IS_HASH_MODE_1(qatHashMode) || + pHashSetupData->hashAlgorithm == CPA_CY_SYM_HASH_AES_CBC_MAC || + pHashSetupData->hashAlgorithm == CPA_CY_SYM_HASH_ZUC_EIA3) { + cd_ctrl->inner_state2_sz = + LAC_ALIGN_POW2_ROUNDUP(pHashDefs->qatInfo->state2Length, + LAC_QUAD_WORD_IN_BYTES); + } else { + cd_ctrl->inner_state2_sz = 0; + } + + cd_ctrl->inner_state2_offset = cd_ctrl->hash_cfg_offset + + LAC_BYTES_TO_QUADWORDS(sizeof(icp_qat_hw_auth_setup_t) + + cd_ctrl->inner_state1_sz); + + /* size of inner part of hash setup block */ + hashSetupBlkSize = sizeof(icp_qat_hw_auth_setup_t) + + cd_ctrl->inner_state1_sz + cd_ctrl->inner_state2_sz; + + /* For nested hashing - Fill in the outer fields */ + if (CPA_CY_SYM_HASH_MODE_NESTED == pHashSetupData->hashMode || + IS_HASH_MODE_2(qatHashMode)) { + /* For nested - use the outer algorithm. This covers TLS and + * nested hash. For HMAC mode2 use inner algorithm again */ + CpaCySymHashAlgorithm outerAlg = + (CPA_CY_SYM_HASH_MODE_NESTED == pHashSetupData->hashMode) ? + pHashSetupData->nestedModeSetupData.outerHashAlgorithm : + pHashSetupData->hashAlgorithm; + + LacSymQat_HashDefsLookupGet(instanceHandle, + outerAlg, + &pOuterHashDefs); + + /* outer config offset */ + cd_ctrl->outer_config_offset = cd_ctrl->inner_state2_offset + + LAC_BYTES_TO_QUADWORDS(cd_ctrl->inner_state2_sz); + + cd_ctrl->outer_state1_sz = + LAC_ALIGN_POW2_ROUNDUP(pOuterHashDefs->algInfo->stateSize, + LAC_QUAD_WORD_IN_BYTES); + + /* outer result size */ + cd_ctrl->outer_res_sz = pOuterHashDefs->algInfo->digestLength; + + /* outer_prefix_offset will be the size of the inner prefix data + * plus the hash state storage size. */ + /* The prefix buffer is part of the ReqParams, so this param + * will be + * setup where ReqParams are set up */ + + /* add on size of outer part of hash block */ + hashSetupBlkSize += + sizeof(icp_qat_hw_auth_setup_t) + cd_ctrl->outer_state1_sz; + } else { + cd_ctrl->outer_config_offset = 0; + cd_ctrl->outer_state1_sz = 0; + cd_ctrl->outer_res_sz = 0; + } + + if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == pHashSetupData->hashAlgorithm) { + /* add the size for the cipher config word, the key and the IV*/ + hashSetupBlkSize += sizeof(icp_qat_hw_cipher_config_t) + + pHashSetupData->authModeSetupData.authKeyLenInBytes + + ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ; + } + + *pHashBlkSizeInBytes = hashSetupBlkSize; + + if (useOptimisedContentDesc) { + LacSymQat_HashSetupBlockOptimisedFormatInit(pHashSetupData, + cd_ctrl, + pHwBlockBase, + qatHashMode, + pPrecompute, + pHashDefs, + pOuterHashDefs); + } else if (!useSymConstantsTable) { + /***************************************************************************** + * Populate Hash Setup block * + *****************************************************************************/ + LacSymQat_HashSetupBlockInit(pHashSetupData, + cd_ctrl, + pHwBlockBase, + qatHashMode, + pPrecompute, + pHashDefs, + pOuterHashDefs); + } +} + +/* This fn populates fields in both the CD ctrl block and the ReqParams block + * which describe the Hash ReqParams: + * cd_ctrl.outer_prefix_offset + * cd_ctrl.outer_prefix_sz + * req_params.inner_prefix_sz/aad_sz + * req_params.hash_state_sz + * req_params.auth_res_sz + * + */ +void +LacSymQat_HashSetupReqParamsMetaData( + icp_qat_la_bulk_req_ftr_t *pMsg, + CpaInstanceHandle instanceHandle, + const CpaCySymHashSetupData *pHashSetupData, + CpaBoolean hashStateBuffer, + icp_qat_hw_auth_mode_t qatHashMode, + CpaBoolean digestVerify) +{ + icp_qat_fw_auth_cd_ctrl_hdr_t *cd_ctrl = NULL; + icp_qat_la_auth_req_params_t *pHashReqParams = NULL; + lac_sym_qat_hash_defs_t *pHashDefs = NULL; + + cd_ctrl = (icp_qat_fw_auth_cd_ctrl_hdr_t *)&(pMsg->cd_ctrl); + pHashReqParams = + (icp_qat_la_auth_req_params_t *)(&(pMsg->serv_specif_rqpars)); + + LacSymQat_HashDefsLookupGet(instanceHandle, + pHashSetupData->hashAlgorithm, + &pHashDefs); + + /* Hmac in mode 2 TLS */ + if (IS_HASH_MODE_2(qatHashMode)) { + /* Inner and outer prefixes are the block length */ + pHashReqParams->u2.inner_prefix_sz = + pHashDefs->algInfo->blockLength; + cd_ctrl->outer_prefix_sz = pHashDefs->algInfo->blockLength; + cd_ctrl->outer_prefix_offset = LAC_BYTES_TO_QUADWORDS( + LAC_ALIGN_POW2_ROUNDUP((pHashReqParams->u2.inner_prefix_sz), + LAC_QUAD_WORD_IN_BYTES)); + } + /* Nested hash in mode 0 */ + else if (CPA_CY_SYM_HASH_MODE_NESTED == pHashSetupData->hashMode) { + + /* set inner and outer prefixes */ + pHashReqParams->u2.inner_prefix_sz = + pHashSetupData->nestedModeSetupData.innerPrefixLenInBytes; + cd_ctrl->outer_prefix_sz = + pHashSetupData->nestedModeSetupData.outerPrefixLenInBytes; + cd_ctrl->outer_prefix_offset = LAC_BYTES_TO_QUADWORDS( + LAC_ALIGN_POW2_ROUNDUP((pHashReqParams->u2.inner_prefix_sz), + LAC_QUAD_WORD_IN_BYTES)); + } + /* mode0 - plain or mode1 - auth */ + else { + Cpa16U aadDataSize = 0; + + /* For Auth Encrypt set the aad size */ + if (CPA_CY_SYM_HASH_AES_CCM == pHashSetupData->hashAlgorithm) { + /* at the beginning of the buffer there is B0 block */ + aadDataSize = LAC_HASH_AES_CCM_BLOCK_SIZE; + + /* then, if there is some 'a' data, the buffer will + * store encoded + * length of 'a' and 'a' itself */ + if (pHashSetupData->authModeSetupData.aadLenInBytes > + 0) { + /* as the QAT API puts the requirement on the + * pAdditionalAuthData not to be bigger than 240 + * bytes then we + * just need 2 bytes to store encoded length of + * 'a' */ + aadDataSize += sizeof(Cpa16U); + aadDataSize += pHashSetupData->authModeSetupData + .aadLenInBytes; + } + + /* round the aad size to the multiple of CCM block + * size.*/ + pHashReqParams->u2.aad_sz = + LAC_ALIGN_POW2_ROUNDUP(aadDataSize, + LAC_HASH_AES_CCM_BLOCK_SIZE); + } else if (CPA_CY_SYM_HASH_AES_GCM == + pHashSetupData->hashAlgorithm) { + aadDataSize = + pHashSetupData->authModeSetupData.aadLenInBytes; + + /* round the aad size to the multiple of GCM hash block + * size. */ + pHashReqParams->u2.aad_sz = + LAC_ALIGN_POW2_ROUNDUP(aadDataSize, + LAC_HASH_AES_GCM_BLOCK_SIZE); + } else { + pHashReqParams->u2.aad_sz = 0; + } + + cd_ctrl->outer_prefix_sz = 0; + cd_ctrl->outer_prefix_offset = 0; + } + + /* If there is a hash state prefix buffer */ + if (CPA_TRUE == hashStateBuffer) { + /* Note, this sets up size for both aad and non-aad cases */ + pHashReqParams->hash_state_sz = LAC_BYTES_TO_QUADWORDS( + LAC_ALIGN_POW2_ROUNDUP(pHashReqParams->u2.inner_prefix_sz, + LAC_QUAD_WORD_IN_BYTES) + + LAC_ALIGN_POW2_ROUNDUP(cd_ctrl->outer_prefix_sz, + LAC_QUAD_WORD_IN_BYTES)); + } else { + pHashReqParams->hash_state_sz = 0; + } + + if (CPA_TRUE == digestVerify) { + /* auth result size in bytes to be read in for a verify + * operation */ + pHashReqParams->auth_res_sz = + pHashSetupData->digestResultLenInBytes; + } else { + pHashReqParams->auth_res_sz = 0; + } + + pHashReqParams->resrvd1 = 0; +} + +void +LacSymQat_HashHwBlockPtrsInit(icp_qat_fw_auth_cd_ctrl_hdr_t *cd_ctrl, + void *pHwBlockBase, + lac_hash_blk_ptrs_t *pHashBlkPtrs) +{ + /* encoded offset for inner config is converted to a byte offset. */ + pHashBlkPtrs->pInHashSetup = + (icp_qat_hw_auth_setup_t *)((Cpa8U *)pHwBlockBase + + (cd_ctrl->hash_cfg_offset * + LAC_QUAD_WORD_IN_BYTES)); + + pHashBlkPtrs->pInHashInitState1 = (Cpa8U *)pHashBlkPtrs->pInHashSetup + + sizeof(icp_qat_hw_auth_setup_t); + + pHashBlkPtrs->pInHashInitState2 = + (Cpa8U *)(pHashBlkPtrs->pInHashInitState1) + + cd_ctrl->inner_state1_sz; + + pHashBlkPtrs->pOutHashSetup = + (icp_qat_hw_auth_setup_t *)((Cpa8U *)(pHashBlkPtrs + ->pInHashInitState2) + + cd_ctrl->inner_state2_sz); + + pHashBlkPtrs->pOutHashInitState1 = + (Cpa8U *)(pHashBlkPtrs->pOutHashSetup) + + sizeof(icp_qat_hw_auth_setup_t); +} + +static void +LacSymQat_HashSetupBlockInit(const CpaCySymHashSetupData *pHashSetupData, + icp_qat_fw_auth_cd_ctrl_hdr_t *pHashControlBlock, + void *pHwBlockBase, + icp_qat_hw_auth_mode_t qatHashMode, + lac_sym_qat_hash_precompute_info_t *pPrecompute, + lac_sym_qat_hash_defs_t *pHashDefs, + lac_sym_qat_hash_defs_t *pOuterHashDefs) +{ + Cpa32U innerConfig = 0; + lac_hash_blk_ptrs_t hashBlkPtrs = { 0 }; + Cpa32U aed_hash_cmp_length = 0; + + LacSymQat_HashHwBlockPtrsInit(pHashControlBlock, + pHwBlockBase, + &hashBlkPtrs); + + innerConfig = ICP_QAT_HW_AUTH_CONFIG_BUILD( + qatHashMode, + pHashDefs->qatInfo->algoEnc, + pHashSetupData->digestResultLenInBytes); + + /* Set the Inner hash configuration */ + hashBlkPtrs.pInHashSetup->auth_config.config = innerConfig; + hashBlkPtrs.pInHashSetup->auth_config.reserved = 0; + + /* For mode 1 pre-computes for auth algorithms */ + if (IS_HASH_MODE_1(qatHashMode) || + CPA_CY_SYM_HASH_AES_CBC_MAC == pHashSetupData->hashAlgorithm || + CPA_CY_SYM_HASH_ZUC_EIA3 == pHashSetupData->hashAlgorithm) { + /* for HMAC in mode 1 authCounter is the block size + * else the authCounter is 0. The firmware expects the counter + * to be + * big endian */ + LAC_MEM_SHARED_WRITE_SWAP( + hashBlkPtrs.pInHashSetup->auth_counter.counter, + pHashDefs->qatInfo->authCounter); + + /* state 1 is set to 0 for the following algorithms */ + if ((CPA_CY_SYM_HASH_AES_XCBC == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_AES_CMAC == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_AES_CBC_MAC == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_KASUMI_F9 == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_SNOW3G_UIA2 == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_AES_CCM == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_AES_GMAC == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_AES_GCM == + pHashSetupData->hashAlgorithm) || + (CPA_CY_SYM_HASH_ZUC_EIA3 == + pHashSetupData->hashAlgorithm)) { + LAC_OS_BZERO(hashBlkPtrs.pInHashInitState1, + pHashDefs->qatInfo->state1Length); + } + + /* Pad remaining bytes of sha1 precomputes */ + if (CPA_CY_SYM_HASH_SHA1 == pHashSetupData->hashAlgorithm) { + Cpa32U state1PadLen = 0; + Cpa32U state2PadLen = 0; + + if (pHashControlBlock->inner_state1_sz > + pHashDefs->algInfo->stateSize) { + state1PadLen = + pHashControlBlock->inner_state1_sz - + pHashDefs->algInfo->stateSize; + } + + if (pHashControlBlock->inner_state2_sz > + pHashDefs->algInfo->stateSize) { + state2PadLen = + pHashControlBlock->inner_state2_sz - + pHashDefs->algInfo->stateSize; + } + + if (state1PadLen > 0) { + + LAC_OS_BZERO(hashBlkPtrs.pInHashInitState1 + + pHashDefs->algInfo->stateSize, + state1PadLen); + } + + if (state2PadLen > 0) { + LAC_OS_BZERO(hashBlkPtrs.pInHashInitState2 + + pHashDefs->algInfo->stateSize, + state2PadLen); + } + } + + pPrecompute->state1Size = pHashDefs->qatInfo->state1Length; + pPrecompute->state2Size = pHashDefs->qatInfo->state2Length; + + /* Set the destination for pre-compute state1 data to be written + */ + pPrecompute->pState1 = hashBlkPtrs.pInHashInitState1; + + /* Set the destination for pre-compute state1 data to be written + */ + pPrecompute->pState2 = hashBlkPtrs.pInHashInitState2; + } + /* For digest and nested digest */ + else { + Cpa32U padLen = pHashControlBlock->inner_state1_sz - + pHashDefs->algInfo->stateSize; + + /* counter set to 0 */ + hashBlkPtrs.pInHashSetup->auth_counter.counter = 0; + + /* set the inner hash state 1 */ + memcpy(hashBlkPtrs.pInHashInitState1, + pHashDefs->algInfo->initState, + pHashDefs->algInfo->stateSize); + + if (padLen > 0) { + LAC_OS_BZERO(hashBlkPtrs.pInHashInitState1 + + pHashDefs->algInfo->stateSize, + padLen); + } + } + + hashBlkPtrs.pInHashSetup->auth_counter.reserved = 0; + + /* Fill in the outer part of the hash setup block */ + if ((CPA_CY_SYM_HASH_MODE_NESTED == pHashSetupData->hashMode || + IS_HASH_MODE_2(qatHashMode)) && + (NULL != pOuterHashDefs)) { + Cpa32U outerConfig = ICP_QAT_HW_AUTH_CONFIG_BUILD( + qatHashMode, + pOuterHashDefs->qatInfo->algoEnc, + pHashSetupData->digestResultLenInBytes); + + Cpa32U padLen = pHashControlBlock->outer_state1_sz - + pOuterHashDefs->algInfo->stateSize; + + /* populate the auth config */ + hashBlkPtrs.pOutHashSetup->auth_config.config = outerConfig; + hashBlkPtrs.pOutHashSetup->auth_config.reserved = 0; + + /* outer Counter set to 0 */ + hashBlkPtrs.pOutHashSetup->auth_counter.counter = 0; + hashBlkPtrs.pOutHashSetup->auth_counter.reserved = 0; + + /* set outer hash state 1 */ + memcpy(hashBlkPtrs.pOutHashInitState1, + pOuterHashDefs->algInfo->initState, + pOuterHashDefs->algInfo->stateSize); + + if (padLen > 0) { + LAC_OS_BZERO(hashBlkPtrs.pOutHashInitState1 + + pOuterHashDefs->algInfo->stateSize, + padLen); + } + } + + if (CPA_CY_SYM_HASH_SNOW3G_UIA2 == pHashSetupData->hashAlgorithm) { + icp_qat_hw_cipher_config_t *pCipherConfig = + (icp_qat_hw_cipher_config_t *)hashBlkPtrs.pOutHashSetup; + + pCipherConfig->val = ICP_QAT_HW_CIPHER_CONFIG_BUILD( + ICP_QAT_HW_CIPHER_ECB_MODE, + ICP_QAT_HW_CIPHER_ALGO_SNOW_3G_UEA2, + ICP_QAT_HW_CIPHER_KEY_CONVERT, + ICP_QAT_HW_CIPHER_ENCRYPT, + aed_hash_cmp_length); + + pCipherConfig->reserved = 0; + + memcpy((Cpa8U *)pCipherConfig + + sizeof(icp_qat_hw_cipher_config_t), + pHashSetupData->authModeSetupData.authKey, + pHashSetupData->authModeSetupData.authKeyLenInBytes); + + LAC_OS_BZERO( + (Cpa8U *)pCipherConfig + + sizeof(icp_qat_hw_cipher_config_t) + + pHashSetupData->authModeSetupData.authKeyLenInBytes, + ICP_QAT_HW_SNOW_3G_UEA2_IV_SZ); + } else if (CPA_CY_SYM_HASH_ZUC_EIA3 == pHashSetupData->hashAlgorithm) { + icp_qat_hw_cipher_config_t *pCipherConfig = + (icp_qat_hw_cipher_config_t *)hashBlkPtrs.pOutHashSetup; + + pCipherConfig->val = ICP_QAT_HW_CIPHER_CONFIG_BUILD( + ICP_QAT_HW_CIPHER_ECB_MODE, + ICP_QAT_HW_CIPHER_ALGO_ZUC_3G_128_EEA3, + ICP_QAT_HW_CIPHER_KEY_CONVERT, + ICP_QAT_HW_CIPHER_ENCRYPT, + aed_hash_cmp_length); + + pCipherConfig->reserved = 0; + + memcpy((Cpa8U *)pCipherConfig + + sizeof(icp_qat_hw_cipher_config_t), + pHashSetupData->authModeSetupData.authKey, + pHashSetupData->authModeSetupData.authKeyLenInBytes); + + LAC_OS_BZERO( + (Cpa8U *)pCipherConfig + + sizeof(icp_qat_hw_cipher_config_t) + + pHashSetupData->authModeSetupData.authKeyLenInBytes, + ICP_QAT_HW_ZUC_3G_EEA3_IV_SZ); + } +} + +static void +LacSymQat_HashOpHwBlockPtrsInit(icp_qat_fw_auth_cd_ctrl_hdr_t *cd_ctrl, + void *pHwBlockBase, + lac_hash_blk_ptrs_optimised_t *pHashBlkPtrs) +{ + pHashBlkPtrs->pInHashInitState1 = (((Cpa8U *)pHwBlockBase) + 16); + pHashBlkPtrs->pInHashInitState2 = + (Cpa8U *)(pHashBlkPtrs->pInHashInitState1) + + cd_ctrl->inner_state1_sz; +} + +static void +LacSymQat_HashSetupBlockOptimisedFormatInit( + const CpaCySymHashSetupData *pHashSetupData, + icp_qat_fw_auth_cd_ctrl_hdr_t *pHashControlBlock, + void *pHwBlockBase, + icp_qat_hw_auth_mode_t qatHashMode, + lac_sym_qat_hash_precompute_info_t *pPrecompute, + lac_sym_qat_hash_defs_t *pHashDefs, + lac_sym_qat_hash_defs_t *pOuterHashDefs) +{ + + Cpa32U state1PadLen = 0; + Cpa32U state2PadLen = 0; + + lac_hash_blk_ptrs_optimised_t pHashBlkPtrs = { 0 }; + + LacSymQat_HashOpHwBlockPtrsInit(pHashControlBlock, + pHwBlockBase, + &pHashBlkPtrs); + + if (pHashControlBlock->inner_state1_sz > + pHashDefs->algInfo->stateSize) { + state1PadLen = pHashControlBlock->inner_state1_sz - + pHashDefs->algInfo->stateSize; + } + + if (pHashControlBlock->inner_state2_sz > + pHashDefs->algInfo->stateSize) { + state2PadLen = pHashControlBlock->inner_state2_sz - + pHashDefs->algInfo->stateSize; + } + + if (state1PadLen > 0) { + + LAC_OS_BZERO(pHashBlkPtrs.pInHashInitState1 + + pHashDefs->algInfo->stateSize, + state1PadLen); + } + + if (state2PadLen > 0) { + + LAC_OS_BZERO(pHashBlkPtrs.pInHashInitState2 + + pHashDefs->algInfo->stateSize, + state2PadLen); + } + pPrecompute->state1Size = pHashDefs->qatInfo->state1Length; + pPrecompute->state2Size = pHashDefs->qatInfo->state2Length; + + /* Set the destination for pre-compute state1 data to be written */ + pPrecompute->pState1 = pHashBlkPtrs.pInHashInitState1; + + /* Set the destination for pre-compute state1 data to be written */ + pPrecompute->pState2 = pHashBlkPtrs.pInHashInitState2; +} + +void +LacSymQat_HashStatePrefixAadBufferSizeGet( + icp_qat_la_bulk_req_ftr_t *pMsg, + lac_sym_qat_hash_state_buffer_info_t *pHashStateBuf) +{ + const icp_qat_fw_auth_cd_ctrl_hdr_t *cd_ctrl; + icp_qat_la_auth_req_params_t *pHashReqParams; + + cd_ctrl = (icp_qat_fw_auth_cd_ctrl_hdr_t *)&(pMsg->cd_ctrl); + pHashReqParams = + (icp_qat_la_auth_req_params_t *)(&(pMsg->serv_specif_rqpars)); + + /* hash state storage needed to support partial packets. Space reserved + * for this in all cases */ + pHashStateBuf->stateStorageSzQuadWords = LAC_BYTES_TO_QUADWORDS( + sizeof(icp_qat_hw_auth_counter_t) + cd_ctrl->inner_state1_sz); + + pHashStateBuf->prefixAadSzQuadWords = pHashReqParams->hash_state_sz; +} + +void +LacSymQat_HashStatePrefixAadBufferPopulate( + lac_sym_qat_hash_state_buffer_info_t *pHashStateBuf, + icp_qat_la_bulk_req_ftr_t *pMsg, + Cpa8U *pInnerPrefixAad, + Cpa8U innerPrefixSize, + Cpa8U *pOuterPrefix, + Cpa8U outerPrefixSize) +{ + const icp_qat_fw_auth_cd_ctrl_hdr_t *cd_ctrl = + (icp_qat_fw_auth_cd_ctrl_hdr_t *)&(pMsg->cd_ctrl); + + icp_qat_la_auth_req_params_t *pHashReqParams = + (icp_qat_la_auth_req_params_t *)(&(pMsg->serv_specif_rqpars)); + + /* + * Let S be the supplied secret + * S1 = S/2 if S is even and (S/2 + 1) if S is odd. + * Set length S2 (inner prefix) = S1 and the start address + * of S2 is S[S1/2] i.e. if S is odd then S2 starts at the last byte of + * S1 + * _____________________________________________________________ + * | outer prefix | padding | + * |________________| | + * | | + * |____________________________________________________________| + * | inner prefix | padding | + * |________________| | + * | | + * |____________________________________________________________| + * + */ + if (NULL != pInnerPrefixAad) { + Cpa8U *pLocalInnerPrefix = + (Cpa8U *)(pHashStateBuf->pData) + + LAC_QUADWORDS_TO_BYTES( + pHashStateBuf->stateStorageSzQuadWords); + Cpa8U padding = + pHashReqParams->u2.inner_prefix_sz - innerPrefixSize; + /* copy the inner prefix or aad data */ + memcpy(pLocalInnerPrefix, pInnerPrefixAad, innerPrefixSize); + + /* Reset with zeroes any area reserved for padding in this block + */ + if (0 < padding) { + LAC_OS_BZERO(pLocalInnerPrefix + innerPrefixSize, + padding); + } + } + + if (NULL != pOuterPrefix) { + Cpa8U *pLocalOuterPrefix = + (Cpa8U *)pHashStateBuf->pData + + LAC_QUADWORDS_TO_BYTES( + pHashStateBuf->stateStorageSzQuadWords + + cd_ctrl->outer_prefix_offset); + Cpa8U padding = LAC_QUADWORDS_TO_BYTES( + pHashStateBuf->prefixAadSzQuadWords) - + pHashReqParams->u2.inner_prefix_sz - outerPrefixSize; + + /* copy the outer prefix */ + memcpy(pLocalOuterPrefix, pOuterPrefix, outerPrefixSize); + + /* Reset with zeroes any area reserved for padding in this block + */ + if (0 < padding) { + LAC_OS_BZERO(pLocalOuterPrefix + outerPrefixSize, + padding); + } + } +} + +inline CpaStatus +LacSymQat_HashRequestParamsPopulate( + icp_qat_fw_la_bulk_req_t *pReq, + Cpa32U authOffsetInBytes, + Cpa32U authLenInBytes, + sal_service_t *pService, + lac_sym_qat_hash_state_buffer_info_t *pHashStateBuf, + Cpa32U packetType, + Cpa32U hashResultSize, + CpaBoolean digestVerify, + Cpa8U *pAuthResult, + CpaCySymHashAlgorithm alg, + void *hkdf_secret) +{ + Cpa64U authResultPhys = 0; + icp_qat_fw_la_auth_req_params_t *pHashReqParams; + + pHashReqParams = (icp_qat_fw_la_auth_req_params_t + *)((Cpa8U *)&(pReq->serv_specif_rqpars) + + ICP_QAT_FW_HASH_REQUEST_PARAMETERS_OFFSET); + + pHashReqParams->auth_off = authOffsetInBytes; + pHashReqParams->auth_len = authLenInBytes; + + /* Set the physical location of secret for HKDF */ + if (NULL != hkdf_secret) { + LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( + (*pService), pHashReqParams->u1.aad_adr, hkdf_secret); + + if (pHashReqParams->u1.aad_adr == 0) { + LAC_LOG_ERROR( + "Unable to get the physical address of the" + " HKDF secret\n"); + return CPA_STATUS_FAIL; + } + } + + /* For a Full packet or last partial need to set the digest result + * pointer + * and the auth result field */ + if (NULL != pAuthResult) { + authResultPhys = + LAC_OS_VIRT_TO_PHYS_EXTERNAL((*pService), + (void *)pAuthResult); + + if (authResultPhys == 0) { + LAC_LOG_ERROR( + "Unable to get the physical address of the" + " auth result\n"); + return CPA_STATUS_FAIL; + } + + pHashReqParams->auth_res_addr = authResultPhys; + } else { + pHashReqParams->auth_res_addr = 0; + } + + if (CPA_TRUE == digestVerify) { + /* auth result size in bytes to be read in for a verify + * operation */ + pHashReqParams->auth_res_sz = hashResultSize; + } else { + pHashReqParams->auth_res_sz = 0; + } + + /* If there is a hash state prefix buffer */ + if (NULL != pHashStateBuf) { + /* Only write the pointer to the buffer if the size is greater + * than 0 + * this will be the case for plain and auth mode due to the + * state storage required for partial packets and for nested + * mode (when + * the prefix data is > 0) */ + if ((pHashStateBuf->stateStorageSzQuadWords + + pHashStateBuf->prefixAadSzQuadWords) > 0) { + /* For the first partial packet, the QAT expects the + * pointer to the + * inner prefix even if there is no memory allocated for + * this. The + * QAT will internally calculate where to write the + * state back. */ + if ((ICP_QAT_FW_LA_PARTIAL_START == packetType) || + (ICP_QAT_FW_LA_PARTIAL_NONE == packetType)) { + // prefix_addr changed to auth_partial_st_prefix + pHashReqParams->u1.auth_partial_st_prefix = + ((pHashStateBuf->pDataPhys) + + LAC_QUADWORDS_TO_BYTES( + pHashStateBuf + ->stateStorageSzQuadWords)); + } else { + pHashReqParams->u1.auth_partial_st_prefix = + pHashStateBuf->pDataPhys; + } + } + /* nested mode when the prefix data is 0 */ + else { + pHashReqParams->u1.auth_partial_st_prefix = 0; + } + + /* For middle & last partial, state size is the hash state + * storage + * if hash mode 2 this will include the prefix data */ + if ((ICP_QAT_FW_LA_PARTIAL_MID == packetType) || + (ICP_QAT_FW_LA_PARTIAL_END == packetType)) { + pHashReqParams->hash_state_sz = + (pHashStateBuf->stateStorageSzQuadWords + + pHashStateBuf->prefixAadSzQuadWords); + } + /* For full packets and first partials set the state size to + * that of + * the prefix/aad. prefix includes both the inner and outer + * prefix */ + else { + pHashReqParams->hash_state_sz = + pHashStateBuf->prefixAadSzQuadWords; + } + } else { + pHashReqParams->u1.auth_partial_st_prefix = 0; + pHashReqParams->hash_state_sz = 0; + } + + /* GMAC only */ + if (CPA_CY_SYM_HASH_AES_GMAC == alg) { + pHashReqParams->hash_state_sz = 0; + pHashReqParams->u1.aad_adr = 0; + } + + /* This field is only used by TLS requests */ + /* In TLS case this is set after this function is called */ + pHashReqParams->resrvd1 = 0; + return CPA_STATUS_SUCCESS; +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_hash_defs_lookup.c b/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_hash_defs_lookup.c new file mode 100644 index 000000000000..23a77f19cca6 --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_hash_defs_lookup.c @@ -0,0 +1,491 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sym_qat_hash_defs_lookup.c Hash Definitions Lookup + * + * @ingroup LacHashDefsLookup + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ + +#include "cpa.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ +#include "lac_common.h" +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" +#include "icp_adf_transport.h" +#include "lac_sym.h" +#include "icp_qat_fw_la.h" +#include "lac_sym_qat_hash_defs_lookup.h" +#include "lac_sal_types_crypto.h" +#include "lac_sym_hash_defs.h" + +/* state size for xcbc mac consists of 3 * 16 byte keys */ +#define LAC_SYM_QAT_XCBC_STATE_SIZE ((LAC_HASH_XCBC_MAC_BLOCK_SIZE)*3) + +#define LAC_SYM_QAT_CMAC_STATE_SIZE ((LAC_HASH_CMAC_BLOCK_SIZE)*3) + +/* This type is used for the mapping between the hash algorithm and + * the corresponding hash definitions structure */ +typedef struct lac_sym_qat_hash_def_map_s { + CpaCySymHashAlgorithm hashAlgorithm; + /* hash algorithm */ + lac_sym_qat_hash_defs_t hashDefs; + /* hash defintions pointers */ +} lac_sym_qat_hash_def_map_t; + +/* +******************************************************************************* +* Static Variables +******************************************************************************* +*/ + +/* initialisers as defined in FIPS and RFCS for digest operations */ + +/* md5 16 bytes - Initialiser state can be found in RFC 1321*/ +static Cpa8U md5InitialState[LAC_HASH_MD5_STATE_SIZE] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, +}; + +/* SHA1 - 20 bytes - Initialiser state can be found in FIPS stds 180-2 */ +static Cpa8U sha1InitialState[LAC_HASH_SHA1_STATE_SIZE] = { + 0x67, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x89, 0x98, 0xba, + 0xdc, 0xfe, 0x10, 0x32, 0x54, 0x76, 0xc3, 0xd2, 0xe1, 0xf0 +}; + +/* SHA 224 - 32 bytes - Initialiser state can be found in FIPS stds 180-2 */ +static Cpa8U sha224InitialState[LAC_HASH_SHA224_STATE_SIZE] = { + 0xc1, 0x05, 0x9e, 0xd8, 0x36, 0x7c, 0xd5, 0x07, 0x30, 0x70, 0xdd, + 0x17, 0xf7, 0x0e, 0x59, 0x39, 0xff, 0xc0, 0x0b, 0x31, 0x68, 0x58, + 0x15, 0x11, 0x64, 0xf9, 0x8f, 0xa7, 0xbe, 0xfa, 0x4f, 0xa4 +}; + +/* SHA 256 - 32 bytes - Initialiser state can be found in FIPS stds 180-2 */ +static Cpa8U sha256InitialState[LAC_HASH_SHA256_STATE_SIZE] = + { 0x6a, 0x09, 0xe6, 0x67, 0xbb, 0x67, 0xae, 0x85, 0x3c, 0x6e, 0xf3, + 0x72, 0xa5, 0x4f, 0xf5, 0x3a, 0x51, 0x0e, 0x52, 0x7f, 0x9b, 0x05, + 0x68, 0x8c, 0x1f, 0x83, 0xd9, 0xab, 0x5b, 0xe0, 0xcd, 0x19 }; + +/* SHA 384 - 64 bytes - Initialiser state can be found in FIPS stds 180-2 */ +static Cpa8U sha384InitialState[LAC_HASH_SHA384_STATE_SIZE] = + { 0xcb, 0xbb, 0x9d, 0x5d, 0xc1, 0x05, 0x9e, 0xd8, 0x62, 0x9a, 0x29, + 0x2a, 0x36, 0x7c, 0xd5, 0x07, 0x91, 0x59, 0x01, 0x5a, 0x30, 0x70, + 0xdd, 0x17, 0x15, 0x2f, 0xec, 0xd8, 0xf7, 0x0e, 0x59, 0x39, 0x67, + 0x33, 0x26, 0x67, 0xff, 0xc0, 0x0b, 0x31, 0x8e, 0xb4, 0x4a, 0x87, + 0x68, 0x58, 0x15, 0x11, 0xdb, 0x0c, 0x2e, 0x0d, 0x64, 0xf9, 0x8f, + 0xa7, 0x47, 0xb5, 0x48, 0x1d, 0xbe, 0xfa, 0x4f, 0xa4 }; + +/* SHA 512 - 64 bytes - Initialiser state can be found in FIPS stds 180-2 */ +static Cpa8U sha512InitialState[LAC_HASH_SHA512_STATE_SIZE] = + { 0x6a, 0x09, 0xe6, 0x67, 0xf3, 0xbc, 0xc9, 0x08, 0xbb, 0x67, 0xae, + 0x85, 0x84, 0xca, 0xa7, 0x3b, 0x3c, 0x6e, 0xf3, 0x72, 0xfe, 0x94, + 0xf8, 0x2b, 0xa5, 0x4f, 0xf5, 0x3a, 0x5f, 0x1d, 0x36, 0xf1, 0x51, + 0x0e, 0x52, 0x7f, 0xad, 0xe6, 0x82, 0xd1, 0x9b, 0x05, 0x68, 0x8c, + 0x2b, 0x3e, 0x6c, 0x1f, 0x1f, 0x83, 0xd9, 0xab, 0xfb, 0x41, 0xbd, + 0x6b, 0x5b, 0xe0, 0xcd, 0x19, 0x13, 0x7e, 0x21, 0x79 }; + +/* SHA3 224 - 28 bytes */ +static Cpa8U sha3_224InitialState[LAC_HASH_SHA3_224_STATE_SIZE] = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +/* SHA3 256 - 32 bytes */ +static Cpa8U sha3_256InitialState[LAC_HASH_SHA3_256_STATE_SIZE] = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +/* SHA3 384 - 48 bytes */ +static Cpa8U sha3_384InitialState[LAC_HASH_SHA3_384_STATE_SIZE] = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +/* SHA3 512 - 64 bytes */ +static Cpa8U sha3_512InitialState[LAC_HASH_SHA3_512_STATE_SIZE] = + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +/* SM3 - 32 bytes */ +static Cpa8U sm3InitialState[LAC_HASH_SM3_STATE_SIZE] = + { 0x73, 0x80, 0x16, 0x6f, 0x49, 0x14, 0xb2, 0xb9, 0x17, 0x24, 0x42, + 0xd7, 0xda, 0x8a, 0x06, 0x00, 0xa9, 0x6f, 0x30, 0xbc, 0x16, 0x31, + 0x38, 0xaa, 0xe3, 0x8d, 0xee, 0x4d, 0xb0, 0xfb, 0x0e, 0x4e }; + +/* Constants used in generating K1, K2, K3 from a Key for AES_XCBC_MAC + * State defined in RFC 3566 */ +static Cpa8U aesXcbcKeySeed[LAC_SYM_QAT_XCBC_STATE_SIZE] = { + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, +}; + +static Cpa8U aesCmacKeySeed[LAC_HASH_CMAC_BLOCK_SIZE] = { 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00 }; + +/* Hash Algorithm specific structure */ + +static lac_sym_qat_hash_alg_info_t md5Info = { LAC_HASH_MD5_DIGEST_SIZE, + LAC_HASH_MD5_BLOCK_SIZE, + md5InitialState, + LAC_HASH_MD5_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t sha1Info = { LAC_HASH_SHA1_DIGEST_SIZE, + LAC_HASH_SHA1_BLOCK_SIZE, + sha1InitialState, + LAC_HASH_SHA1_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t sha224Info = { LAC_HASH_SHA224_DIGEST_SIZE, + LAC_HASH_SHA224_BLOCK_SIZE, + sha224InitialState, + LAC_HASH_SHA224_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t sha256Info = { LAC_HASH_SHA256_DIGEST_SIZE, + LAC_HASH_SHA256_BLOCK_SIZE, + sha256InitialState, + LAC_HASH_SHA256_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t sha384Info = { LAC_HASH_SHA384_DIGEST_SIZE, + LAC_HASH_SHA384_BLOCK_SIZE, + sha384InitialState, + LAC_HASH_SHA384_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t sha512Info = { LAC_HASH_SHA512_DIGEST_SIZE, + LAC_HASH_SHA512_BLOCK_SIZE, + sha512InitialState, + LAC_HASH_SHA512_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t sha3_224Info = + { LAC_HASH_SHA3_224_DIGEST_SIZE, + LAC_HASH_SHA3_224_BLOCK_SIZE, + sha3_224InitialState, + LAC_HASH_SHA3_224_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t sha3_256Info = + { LAC_HASH_SHA3_256_DIGEST_SIZE, + LAC_HASH_SHA3_256_BLOCK_SIZE, + sha3_256InitialState, + LAC_HASH_SHA3_256_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t sha3_384Info = + { LAC_HASH_SHA3_384_DIGEST_SIZE, + LAC_HASH_SHA3_384_BLOCK_SIZE, + sha3_384InitialState, + LAC_HASH_SHA3_384_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t sha3_512Info = + { LAC_HASH_SHA3_512_DIGEST_SIZE, + LAC_HASH_SHA3_512_BLOCK_SIZE, + sha3_512InitialState, + LAC_HASH_SHA3_512_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t polyInfo = { LAC_HASH_POLY_DIGEST_SIZE, + LAC_HASH_POLY_BLOCK_SIZE, + NULL, /* intial state */ + LAC_HASH_POLY_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t shake_128Info = + { LAC_HASH_SHAKE_128_DIGEST_SIZE, LAC_HASH_SHAKE_128_BLOCK_SIZE, NULL, 0 }; + +static lac_sym_qat_hash_alg_info_t shake_256Info = + { LAC_HASH_SHAKE_256_DIGEST_SIZE, LAC_HASH_SHAKE_256_BLOCK_SIZE, NULL, 0 }; + +static lac_sym_qat_hash_alg_info_t sm3Info = { LAC_HASH_SM3_DIGEST_SIZE, + LAC_HASH_SM3_BLOCK_SIZE, + sm3InitialState, + LAC_HASH_SM3_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t xcbcMacInfo = + { LAC_HASH_XCBC_MAC_128_DIGEST_SIZE, + LAC_HASH_XCBC_MAC_BLOCK_SIZE, + aesXcbcKeySeed, + LAC_SYM_QAT_XCBC_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t aesCmacInfo = + { LAC_HASH_CMAC_128_DIGEST_SIZE, + LAC_HASH_CMAC_BLOCK_SIZE, + aesCmacKeySeed, + LAC_SYM_QAT_CMAC_STATE_SIZE }; + +static lac_sym_qat_hash_alg_info_t aesCcmInfo = { + LAC_HASH_AES_CCM_DIGEST_SIZE, + LAC_HASH_AES_CCM_BLOCK_SIZE, + NULL, /* intial state */ + 0 /* state size */ +}; + +static lac_sym_qat_hash_alg_info_t aesGcmInfo = { + LAC_HASH_AES_GCM_DIGEST_SIZE, + LAC_HASH_AES_GCM_BLOCK_SIZE, + NULL, /* initial state */ + 0 /* state size */ +}; + +static lac_sym_qat_hash_alg_info_t kasumiF9Info = { + LAC_HASH_KASUMI_F9_DIGEST_SIZE, + LAC_HASH_KASUMI_F9_BLOCK_SIZE, + NULL, /* initial state */ + 0 /* state size */ +}; + +static lac_sym_qat_hash_alg_info_t snow3gUia2Info = { + LAC_HASH_SNOW3G_UIA2_DIGEST_SIZE, + LAC_HASH_SNOW3G_UIA2_BLOCK_SIZE, + NULL, /* initial state */ + 0 /* state size */ +}; + +static lac_sym_qat_hash_alg_info_t aesCbcMacInfo = + { LAC_HASH_AES_CBC_MAC_DIGEST_SIZE, + LAC_HASH_AES_CBC_MAC_BLOCK_SIZE, + NULL, + 0 }; + +static lac_sym_qat_hash_alg_info_t zucEia3Info = { + LAC_HASH_ZUC_EIA3_DIGEST_SIZE, + LAC_HASH_ZUC_EIA3_BLOCK_SIZE, + NULL, /* initial state */ + 0 /* state size */ +}; +/* Hash QAT specific structures */ + +static lac_sym_qat_hash_qat_info_t md5Config = { ICP_QAT_HW_AUTH_ALGO_MD5, + LAC_HASH_MD5_BLOCK_SIZE, + ICP_QAT_HW_MD5_STATE1_SZ, + ICP_QAT_HW_MD5_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t sha1Config = { ICP_QAT_HW_AUTH_ALGO_SHA1, + LAC_HASH_SHA1_BLOCK_SIZE, + ICP_QAT_HW_SHA1_STATE1_SZ, + ICP_QAT_HW_SHA1_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t sha224Config = + { ICP_QAT_HW_AUTH_ALGO_SHA224, + LAC_HASH_SHA224_BLOCK_SIZE, + ICP_QAT_HW_SHA224_STATE1_SZ, + ICP_QAT_HW_SHA224_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t sha256Config = + { ICP_QAT_HW_AUTH_ALGO_SHA256, + LAC_HASH_SHA256_BLOCK_SIZE, + ICP_QAT_HW_SHA256_STATE1_SZ, + ICP_QAT_HW_SHA256_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t sha384Config = + { ICP_QAT_HW_AUTH_ALGO_SHA384, + LAC_HASH_SHA384_BLOCK_SIZE, + ICP_QAT_HW_SHA384_STATE1_SZ, + ICP_QAT_HW_SHA384_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t sha512Config = + { ICP_QAT_HW_AUTH_ALGO_SHA512, + LAC_HASH_SHA512_BLOCK_SIZE, + ICP_QAT_HW_SHA512_STATE1_SZ, + ICP_QAT_HW_SHA512_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t sha3_224Config = + { ICP_QAT_HW_AUTH_ALGO_SHA3_224, + LAC_HASH_SHA3_224_BLOCK_SIZE, + ICP_QAT_HW_SHA3_224_STATE1_SZ, + ICP_QAT_HW_SHA3_224_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t sha3_256Config = + { ICP_QAT_HW_AUTH_ALGO_SHA3_256, + LAC_HASH_SHA3_256_BLOCK_SIZE, + ICP_QAT_HW_SHA3_256_STATE1_SZ, + ICP_QAT_HW_SHA3_256_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t sha3_384Config = + { ICP_QAT_HW_AUTH_ALGO_SHA3_384, + LAC_HASH_SHA3_384_BLOCK_SIZE, + ICP_QAT_HW_SHA3_384_STATE1_SZ, + ICP_QAT_HW_SHA3_384_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t sha3_512Config = + { ICP_QAT_HW_AUTH_ALGO_SHA3_512, + LAC_HASH_SHA3_512_BLOCK_SIZE, + ICP_QAT_HW_SHA3_512_STATE1_SZ, + ICP_QAT_HW_SHA3_512_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t shake_128Config = + { ICP_QAT_HW_AUTH_ALGO_SHAKE_128, LAC_HASH_SHAKE_128_BLOCK_SIZE, 0, 0 }; + +static lac_sym_qat_hash_qat_info_t shake_256Config = + { ICP_QAT_HW_AUTH_ALGO_SHAKE_256, LAC_HASH_SHAKE_256_BLOCK_SIZE, 0, 0 }; + +static lac_sym_qat_hash_qat_info_t polyConfig = { ICP_QAT_HW_AUTH_ALGO_POLY, + LAC_HASH_POLY_BLOCK_SIZE, + 0, + 0 }; + +static lac_sym_qat_hash_qat_info_t sm3Config = { ICP_QAT_HW_AUTH_ALGO_SM3, + LAC_HASH_SM3_BLOCK_SIZE, + ICP_QAT_HW_SM3_STATE1_SZ, + ICP_QAT_HW_SM3_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t xcbcMacConfig = + { ICP_QAT_HW_AUTH_ALGO_AES_XCBC_MAC, + 0, + ICP_QAT_HW_AES_XCBC_MAC_STATE1_SZ, + LAC_SYM_QAT_XCBC_STATE_SIZE }; + +static lac_sym_qat_hash_qat_info_t aesCmacConfig = + { ICP_QAT_HW_AUTH_ALGO_AES_XCBC_MAC, + 0, + ICP_QAT_HW_AES_XCBC_MAC_STATE1_SZ, + LAC_SYM_QAT_CMAC_STATE_SIZE }; + +static lac_sym_qat_hash_qat_info_t aesCcmConfig = + { ICP_QAT_HW_AUTH_ALGO_AES_CBC_MAC, + 0, + ICP_QAT_HW_AES_CBC_MAC_STATE1_SZ, + ICP_QAT_HW_AES_CBC_MAC_KEY_SZ + ICP_QAT_HW_AES_CCM_CBC_E_CTR0_SZ }; + +static lac_sym_qat_hash_qat_info_t aesGcmConfig = + { ICP_QAT_HW_AUTH_ALGO_GALOIS_128, + 0, + ICP_QAT_HW_GALOIS_128_STATE1_SZ, + ICP_QAT_HW_GALOIS_H_SZ + ICP_QAT_HW_GALOIS_LEN_A_SZ + + ICP_QAT_HW_GALOIS_E_CTR0_SZ }; + +static lac_sym_qat_hash_qat_info_t kasumiF9Config = + { ICP_QAT_HW_AUTH_ALGO_KASUMI_F9, + 0, + ICP_QAT_HW_KASUMI_F9_STATE1_SZ, + ICP_QAT_HW_KASUMI_F9_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t snow3gUia2Config = + { ICP_QAT_HW_AUTH_ALGO_SNOW_3G_UIA2, + 0, + ICP_QAT_HW_SNOW_3G_UIA2_STATE1_SZ, + ICP_QAT_HW_SNOW_3G_UIA2_STATE2_SZ }; + +static lac_sym_qat_hash_qat_info_t aesCbcMacConfig = + { ICP_QAT_HW_AUTH_ALGO_AES_CBC_MAC, + 0, + ICP_QAT_HW_AES_CBC_MAC_STATE1_SZ, + ICP_QAT_HW_AES_CBC_MAC_STATE1_SZ + ICP_QAT_HW_AES_CBC_MAC_STATE1_SZ }; + +static lac_sym_qat_hash_qat_info_t zucEia3Config = + { ICP_QAT_HW_AUTH_ALGO_ZUC_3G_128_EIA3, + 0, + ICP_QAT_HW_ZUC_3G_EIA3_STATE1_SZ, + ICP_QAT_HW_ZUC_3G_EIA3_STATE2_SZ }; + +/* Array of mappings between algorithm and info structure + * This array is used to populate the lookup table */ +static lac_sym_qat_hash_def_map_t lacHashDefsMapping[] = + { { CPA_CY_SYM_HASH_MD5, { &md5Info, &md5Config } }, + { CPA_CY_SYM_HASH_SHA1, { &sha1Info, &sha1Config } }, + { CPA_CY_SYM_HASH_SHA224, { &sha224Info, &sha224Config } }, + { CPA_CY_SYM_HASH_SHA256, { &sha256Info, &sha256Config } }, + { CPA_CY_SYM_HASH_SHA384, { &sha384Info, &sha384Config } }, + { CPA_CY_SYM_HASH_SHA512, { &sha512Info, &sha512Config } }, + { CPA_CY_SYM_HASH_SHA3_224, { &sha3_224Info, &sha3_224Config } }, + { CPA_CY_SYM_HASH_SHA3_256, { &sha3_256Info, &sha3_256Config } }, + { CPA_CY_SYM_HASH_SHA3_384, { &sha3_384Info, &sha3_384Config } }, + { CPA_CY_SYM_HASH_SHA3_512, { &sha3_512Info, &sha3_512Config } }, + { CPA_CY_SYM_HASH_SHAKE_128, { &shake_128Info, &shake_128Config } }, + { CPA_CY_SYM_HASH_SHAKE_256, { &shake_256Info, &shake_256Config } }, + { CPA_CY_SYM_HASH_POLY, { &polyInfo, &polyConfig } }, + { CPA_CY_SYM_HASH_SM3, { &sm3Info, &sm3Config } }, + { CPA_CY_SYM_HASH_AES_XCBC, { &xcbcMacInfo, &xcbcMacConfig } }, + { CPA_CY_SYM_HASH_AES_CMAC, { &aesCmacInfo, &aesCmacConfig } }, + { CPA_CY_SYM_HASH_AES_CCM, { &aesCcmInfo, &aesCcmConfig } }, + { CPA_CY_SYM_HASH_AES_GCM, { &aesGcmInfo, &aesGcmConfig } }, + { CPA_CY_SYM_HASH_KASUMI_F9, { &kasumiF9Info, &kasumiF9Config } }, + { CPA_CY_SYM_HASH_SNOW3G_UIA2, { &snow3gUia2Info, &snow3gUia2Config } }, + { CPA_CY_SYM_HASH_AES_GMAC, { &aesGcmInfo, &aesGcmConfig } }, + { CPA_CY_SYM_HASH_ZUC_EIA3, { &zucEia3Info, &zucEia3Config } }, + { CPA_CY_SYM_HASH_AES_CBC_MAC, { &aesCbcMacInfo, &aesCbcMacConfig } } }; + +/* + * LacSymQat_HashLookupInit + */ +CpaStatus +LacSymQat_HashLookupInit(CpaInstanceHandle instanceHandle) +{ + Cpa32U entry = 0; + Cpa32U numEntries = 0; + Cpa32U arraySize = 0; + CpaStatus status = CPA_STATUS_SUCCESS; + CpaCySymHashAlgorithm hashAlg = CPA_CY_SYM_HASH_NONE; + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + + arraySize = + (CPA_CY_HASH_ALG_END + 1) * sizeof(lac_sym_qat_hash_defs_t *); + /* Size round up for performance */ + arraySize = LAC_ALIGN_POW2_ROUNDUP(arraySize, LAC_64BYTE_ALIGNMENT); + + pService->pLacHashLookupDefs = LAC_OS_MALLOC(arraySize); + + if (NULL != pService->pLacHashLookupDefs) { + LAC_OS_BZERO(pService->pLacHashLookupDefs, arraySize); + + numEntries = sizeof(lacHashDefsMapping) / + sizeof(lac_sym_qat_hash_def_map_t); + + /* initialise the hash lookup definitions table so that the + * algorithm + * can be used to index into the table */ + for (entry = 0; entry < numEntries; entry++) { + hashAlg = lacHashDefsMapping[entry].hashAlgorithm; + + pService->pLacHashLookupDefs[hashAlg] = + &(lacHashDefsMapping[entry].hashDefs); + } + } else { + status = CPA_STATUS_RESOURCE; + } + return status; +} + +/* + * LacSymQat_HashAlgLookupGet + */ +void +LacSymQat_HashAlgLookupGet(CpaInstanceHandle instanceHandle, + CpaCySymHashAlgorithm hashAlgorithm, + lac_sym_qat_hash_alg_info_t **ppHashAlgInfo) +{ + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + + *ppHashAlgInfo = pService->pLacHashLookupDefs[hashAlgorithm]->algInfo; +} + +/* + * LacSymQat_HashDefsLookupGet + */ +void +LacSymQat_HashDefsLookupGet(CpaInstanceHandle instanceHandle, + CpaCySymHashAlgorithm hashAlgorithm, + lac_sym_qat_hash_defs_t **ppHashDefsInfo) +{ + sal_crypto_service_t *pService = (sal_crypto_service_t *)instanceHandle; + + *ppHashDefsInfo = pService->pLacHashLookupDefs[hashAlgorithm]; +} diff --git a/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_key.c b/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_key.c new file mode 100644 index 000000000000..abc7710aa96d --- /dev/null +++ b/sys/dev/qat/qat_api/common/crypto/sym/qat/lac_sym_qat_key.c @@ -0,0 +1,196 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + ***************************************************************************** + * @file lac_sym_qat_key.c Interfaces for populating the symmetric qat key + * structures + * + * @ingroup LacSymQatKey + * + *****************************************************************************/ + +#include "cpa.h" +#include "cpa_cy_key.h" +#include "lac_mem.h" +#include "icp_qat_fw_la.h" +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" +#include "lac_list.h" +#include "lac_sal_types.h" +#include "lac_sym_qat_key.h" +#include "lac_sym_hash_defs.h" + +void +LacSymQat_KeySslRequestPopulate(icp_qat_la_bulk_req_hdr_t *pKeyGenReqHdr, + icp_qat_fw_la_key_gen_common_t *pKeyGenReqMid, + Cpa32U generatedKeyLenInBytes, + Cpa32U labelLenInBytes, + Cpa32U secretLenInBytes, + Cpa32U iterations) +{ + /* Rounded to nearest 8 byte boundary */ + Cpa8U outLenRounded = 0; + outLenRounded = LAC_ALIGN_POW2_ROUNDUP(generatedKeyLenInBytes, + LAC_QUAD_WORD_IN_BYTES); + + pKeyGenReqMid->u.secret_lgth_ssl = secretLenInBytes; + pKeyGenReqMid->u1.s1.output_lgth_ssl = outLenRounded; + pKeyGenReqMid->u1.s1.label_lgth_ssl = labelLenInBytes; + pKeyGenReqMid->u2.iter_count = iterations; + pKeyGenReqMid->u3.resrvd2 = 0; + pKeyGenReqMid->resrvd3 = 0; + + /* Set up the common LA flags */ + pKeyGenReqHdr->comn_hdr.service_cmd_id = + ICP_QAT_FW_LA_CMD_SSL3_KEY_DERIVE; + pKeyGenReqHdr->comn_hdr.resrvd1 = 0; +} + +void +LacSymQat_KeyTlsRequestPopulate( + icp_qat_fw_la_key_gen_common_t *pKeyGenReqParams, + Cpa32U generatedKeyLenInBytes, + Cpa32U labelInfo, /* Generic name, can be num of labels or label length */ + Cpa32U secretLenInBytes, + Cpa8U seedLenInBytes, + icp_qat_fw_la_cmd_id_t cmdId) +{ + pKeyGenReqParams->u1.s3.output_lgth_tls = + LAC_ALIGN_POW2_ROUNDUP(generatedKeyLenInBytes, + LAC_QUAD_WORD_IN_BYTES); + + /* For TLS u param of auth_req_params is set to secretLen */ + pKeyGenReqParams->u.secret_lgth_tls = secretLenInBytes; + + switch (cmdId) { + case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT: + pKeyGenReqParams->u2.hkdf_ikm_length = secretLenInBytes; + pKeyGenReqParams->u3.resrvd2 = 0; + break; + case ICP_QAT_FW_LA_CMD_HKDF_EXPAND: + pKeyGenReqParams->u1.hkdf.info_length = labelInfo; + break; + case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND: + pKeyGenReqParams->u2.hkdf_ikm_length = secretLenInBytes; + pKeyGenReqParams->u1.hkdf.info_length = labelInfo; + break; + case ICP_QAT_FW_LA_CMD_HKDF_EXPAND_LABEL: + /* Num of Labels */ + pKeyGenReqParams->u1.hkdf_label.num_labels = labelInfo; + pKeyGenReqParams->u3.hkdf_num_sublabels = 4; /* 4 subLabels */ + break; + case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL: + pKeyGenReqParams->u2.hkdf_ikm_length = secretLenInBytes; + /* Num of Labels */ + pKeyGenReqParams->u1.hkdf_label.num_labels = labelInfo; + pKeyGenReqParams->u3.hkdf_num_sublabels = 4; /* 4 subLabels */ + break; + default: + pKeyGenReqParams->u1.s3.label_lgth_tls = labelInfo; + pKeyGenReqParams->u2.tls_seed_length = seedLenInBytes; + pKeyGenReqParams->u3.resrvd2 = 0; + break; + } + pKeyGenReqParams->resrvd3 = 0; +} + +void +LacSymQat_KeyMgfRequestPopulate(icp_qat_la_bulk_req_hdr_t *pKeyGenReqHdr, + icp_qat_fw_la_key_gen_common_t *pKeyGenReqMid, + Cpa8U seedLenInBytes, + Cpa16U maskLenInBytes, + Cpa8U hashLenInBytes) +{ + pKeyGenReqHdr->comn_hdr.service_cmd_id = ICP_QAT_FW_LA_CMD_MGF1; + pKeyGenReqMid->u.mask_length = + LAC_ALIGN_POW2_ROUNDUP(maskLenInBytes, LAC_QUAD_WORD_IN_BYTES); + + pKeyGenReqMid->u1.s2.hash_length = hashLenInBytes; + pKeyGenReqMid->u1.s2.seed_length = seedLenInBytes; +} + +void +LacSymQat_KeySslKeyMaterialInputPopulate( + sal_service_t *pService, + icp_qat_fw_la_ssl_key_material_input_t *pSslKeyMaterialInput, + void *pSeed, + Cpa64U labelPhysAddr, + void *pSecret) +{ + LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( + (*pService), pSslKeyMaterialInput->seed_addr, pSeed); + + pSslKeyMaterialInput->label_addr = labelPhysAddr; + + LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( + (*pService), pSslKeyMaterialInput->secret_addr, pSecret); +} + +void +LacSymQat_KeyTlsKeyMaterialInputPopulate( + sal_service_t *pService, + icp_qat_fw_la_tls_key_material_input_t *pTlsKeyMaterialInput, + void *pSeed, + Cpa64U labelPhysAddr) +{ + LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( + (*pService), pTlsKeyMaterialInput->seed_addr, pSeed); + + pTlsKeyMaterialInput->label_addr = labelPhysAddr; +} + +void +LacSymQat_KeyTlsHKDFKeyMaterialInputPopulate( + sal_service_t *pService, + icp_qat_fw_la_hkdf_key_material_input_t *pTlsKeyMaterialInput, + CpaCyKeyGenHKDFOpData *pKeyGenTlsOpData, + Cpa64U subLabelsPhysAddr, + icp_qat_fw_la_cmd_id_t cmdId) +{ + switch (cmdId) { + case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT: + LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( + (*pService), + pTlsKeyMaterialInput->ikm_addr, + pKeyGenTlsOpData->secret); + break; + case ICP_QAT_FW_LA_CMD_HKDF_EXPAND: + LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( + (*pService), + pTlsKeyMaterialInput->labels_addr, + pKeyGenTlsOpData->info); + break; + case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND: + LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( + (*pService), + pTlsKeyMaterialInput->ikm_addr, + pKeyGenTlsOpData->secret); + pTlsKeyMaterialInput->labels_addr = + pTlsKeyMaterialInput->ikm_addr + + ((uint64_t)&pKeyGenTlsOpData->info - + (uint64_t)&pKeyGenTlsOpData->secret); + break; + case ICP_QAT_FW_LA_CMD_HKDF_EXPAND_LABEL: + pTlsKeyMaterialInput->sublabels_addr = subLabelsPhysAddr; + LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( + (*pService), + pTlsKeyMaterialInput->labels_addr, + pKeyGenTlsOpData->label); + break; + case ICP_QAT_FW_LA_CMD_HKDF_EXTRACT_AND_EXPAND_LABEL: + pTlsKeyMaterialInput->sublabels_addr = subLabelsPhysAddr; + LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL( + (*pService), + pTlsKeyMaterialInput->ikm_addr, + pKeyGenTlsOpData->secret); + pTlsKeyMaterialInput->labels_addr = + pTlsKeyMaterialInput->ikm_addr + + ((uint64_t)&pKeyGenTlsOpData->label - + (uint64_t)&pKeyGenTlsOpData->secret); + break; + default: + break; + } +} diff --git a/sys/dev/qat/qat_api/common/ctrl/sal_compression.c b/sys/dev/qat/qat_api/common/ctrl/sal_compression.c new file mode 100644 index 000000000000..d8523d23b0e0 --- /dev/null +++ b/sys/dev/qat/qat_api/common/ctrl/sal_compression.c @@ -0,0 +1,1554 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file sal_compression.c + * + * @ingroup SalCtrl + * + * @description + * This file contains the sal implementation for compression. + * + *****************************************************************************/ + +/* QAT-API includes */ +#include "cpa.h" +#include "cpa_dc.h" + +/* QAT utils includes */ +#include "qat_utils.h" + +/* ADF includes */ +#include "icp_adf_init.h" +#include "icp_adf_transport.h" +#include "icp_accel_devices.h" +#include "icp_adf_cfg.h" +#include "icp_adf_accel_mgr.h" +#include "icp_adf_poll.h" +#include "icp_adf_debug.h" +#include "icp_adf_esram.h" +#include "icp_qat_hw.h" + +/* SAL includes */ +#include "lac_mem.h" +#include "lac_common.h" +#include "lac_mem_pools.h" +#include "sal_statistics.h" +#include "lac_list.h" +#include "icp_sal_poll.h" +#include "sal_types_compression.h" +#include "dc_session.h" +#include "dc_datapath.h" +#include "dc_stats.h" +#include "lac_sal.h" +#include "lac_sal_ctrl.h" +#include "sal_string_parse.h" +#include "sal_service_state.h" +#include "lac_buffer_desc.h" +#include "icp_qat_fw_comp.h" +#include "icp_sal_versions.h" + +/* C string null terminator size */ +#define SAL_NULL_TERM_SIZE 1 + +/* Type to access extended features bit fields */ +typedef struct dc_extended_features_s { + unsigned is_cnv : 1; /* Bit<0> */ + unsigned padding : 7; + unsigned is_cnvnr : 1; /* Bit<8> */ + unsigned not_used : 23; +} dc_extd_ftrs_t; + +/* + * Prints statistics for a compression instance + */ +static int +SalCtrl_CompresionDebug(void *private_data, char *data, int size, int offset) +{ + sal_compression_service_t *pCompressionService = + (sal_compression_service_t *)private_data; + CpaStatus status = CPA_STATUS_SUCCESS; + CpaDcStats dcStats = { 0 }; + Cpa32S len = 0; + + status = cpaDcGetStats(pCompressionService, &dcStats); + if (status != CPA_STATUS_SUCCESS) { + QAT_UTILS_LOG("cpaDcGetStats returned error.\n"); + return (-1); + } + + /* Engine Info */ + if (NULL != pCompressionService->debug_file) { + len += snprintf(data + len, + size - len, + SEPARATOR BORDER + " Statistics for Instance %24s | \n" SEPARATOR, + pCompressionService->debug_file->name); + } + + /* Perform Info */ + len += snprintf(data + len, + size - len, + BORDER " DC comp Requests: %16llu " BORDER + "\n" BORDER + " DC comp Request Errors: %16llu " BORDER + "\n" BORDER + " DC comp Completed: %16llu " BORDER + "\n" BORDER + " DC comp Completed Errors: %16llu " BORDER + "\n" SEPARATOR, + (long long unsigned int)dcStats.numCompRequests, + (long long unsigned int)dcStats.numCompRequestsErrors, + (long long unsigned int)dcStats.numCompCompleted, + (long long unsigned int)dcStats.numCompCompletedErrors); + + /* Perform Info */ + len += snprintf( + data + len, + size - len, + BORDER " DC decomp Requests: %16llu " BORDER "\n" BORDER + " DC decomp Request Errors: %16llu " BORDER "\n" BORDER + " DC decomp Completed: %16llu " BORDER "\n" BORDER + " DC decomp Completed Errors: %16llu " BORDER + "\n" SEPARATOR, + (long long unsigned int)dcStats.numDecompRequests, + (long long unsigned int)dcStats.numDecompRequestsErrors, + (long long unsigned int)dcStats.numDecompCompleted, + (long long unsigned int)dcStats.numDecompCompletedErrors); + return 0; +} + +/* Initialise device specific information needed by compression service */ +static CpaStatus +SalCtrl_CompressionInit_CompData(icp_accel_dev_t *device, + sal_compression_service_t *pCompService) +{ + switch (device->deviceType) { + case DEVICE_DH895XCC: + case DEVICE_DH895XCCVF: + pCompService->generic_service_info.integrityCrcCheck = + CPA_FALSE; + pCompService->numInterBuffs = + DC_QAT_MAX_NUM_INTER_BUFFERS_6COMP_SLICES; + pCompService->comp_device_data.minOutputBuffSize = + DC_DEST_BUFFER_STA_MIN_SIZE; + pCompService->comp_device_data.oddByteDecompNobFinal = CPA_TRUE; + pCompService->comp_device_data.oddByteDecompInterim = CPA_FALSE; + pCompService->comp_device_data.translatorOverflow = CPA_FALSE; + pCompService->comp_device_data.useDevRam = + ICP_QAT_FW_COMP_ENABLE_SECURE_RAM_USED_AS_INTMD_BUF; + pCompService->comp_device_data.enableDmm = + ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_DISABLED; + + pCompService->comp_device_data.inflateContextSize = + DC_INFLATE_CONTEXT_SIZE; + pCompService->comp_device_data.highestHwCompressionDepth = + ICP_QAT_HW_COMPRESSION_DEPTH_16; + + pCompService->comp_device_data.windowSizeMask = + (1 << DC_8K_WINDOW_SIZE | 1 << DC_32K_WINDOW_SIZE); + pCompService->comp_device_data.cnvnrSupported = CPA_FALSE; + break; + case DEVICE_C3XXX: + case DEVICE_C3XXXVF: + case DEVICE_200XX: + case DEVICE_200XXVF: + pCompService->generic_service_info.integrityCrcCheck = + CPA_FALSE; + pCompService->numInterBuffs = + DC_QAT_MAX_NUM_INTER_BUFFERS_6COMP_SLICES; + pCompService->comp_device_data.oddByteDecompNobFinal = + CPA_FALSE; + pCompService->comp_device_data.oddByteDecompInterim = CPA_TRUE; + pCompService->comp_device_data.translatorOverflow = CPA_FALSE; + pCompService->comp_device_data.useDevRam = + ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_USED_AS_INTMD_BUF; + pCompService->comp_device_data.inflateContextSize = + DC_INFLATE_EH_CONTEXT_SIZE; + pCompService->comp_device_data.highestHwCompressionDepth = + ICP_QAT_HW_COMPRESSION_DEPTH_16; + pCompService->comp_device_data.windowSizeMask = + (1 << DC_16K_WINDOW_SIZE | 1 << DC_32K_WINDOW_SIZE); + pCompService->comp_device_data.minOutputBuffSize = + DC_DEST_BUFFER_STA_MIN_SIZE; + pCompService->comp_device_data.enableDmm = + ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_ENABLED; + + pCompService->comp_device_data.cnvnrSupported = CPA_TRUE; + break; + case DEVICE_C62X: + case DEVICE_C62XVF: + pCompService->generic_service_info.integrityCrcCheck = + CPA_FALSE; + pCompService->numInterBuffs = + DC_QAT_MAX_NUM_INTER_BUFFERS_10COMP_SLICES; + pCompService->comp_device_data.oddByteDecompNobFinal = + CPA_FALSE; + pCompService->comp_device_data.oddByteDecompInterim = CPA_TRUE; + pCompService->comp_device_data.translatorOverflow = CPA_FALSE; + pCompService->comp_device_data.useDevRam = + ICP_QAT_FW_COMP_ENABLE_SECURE_RAM_USED_AS_INTMD_BUF; + pCompService->comp_device_data.inflateContextSize = + DC_INFLATE_EH_CONTEXT_SIZE; + pCompService->comp_device_data.windowSizeMask = + (1 << DC_16K_WINDOW_SIZE | 1 << DC_32K_WINDOW_SIZE); + pCompService->comp_device_data.minOutputBuffSize = + DC_DEST_BUFFER_STA_MIN_SIZE; + pCompService->comp_device_data.enableDmm = + ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_ENABLED; + pCompService->comp_device_data.cnvnrSupported = CPA_TRUE; + break; + case DEVICE_C4XXX: + case DEVICE_C4XXXVF: + pCompService->generic_service_info.integrityCrcCheck = CPA_TRUE; + pCompService->numInterBuffs = + DC_QAT_MAX_NUM_INTER_BUFFERS_24COMP_SLICES; + pCompService->comp_device_data.minOutputBuffSize = + DC_DEST_BUFFER_MIN_SIZE; + pCompService->comp_device_data.oddByteDecompNobFinal = CPA_TRUE; + pCompService->comp_device_data.oddByteDecompInterim = CPA_TRUE; + pCompService->comp_device_data.translatorOverflow = CPA_TRUE; + if (pCompService->generic_service_info.capabilitiesMask & + ICP_ACCEL_CAPABILITIES_INLINE) { + pCompService->comp_device_data.useDevRam = + ICP_QAT_FW_COMP_DISABLE_SECURE_RAM_USED_AS_INTMD_BUF; + } else { + pCompService->comp_device_data.useDevRam = + ICP_QAT_FW_COMP_ENABLE_SECURE_RAM_USED_AS_INTMD_BUF; + } + pCompService->comp_device_data.enableDmm = + ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_ENABLED; + pCompService->comp_device_data.inflateContextSize = + DC_INFLATE_EH_CONTEXT_SIZE; + pCompService->comp_device_data.highestHwCompressionDepth = + ICP_QAT_HW_COMPRESSION_DEPTH_128; + pCompService->comp_device_data.windowSizeMask = + (1 << DC_16K_WINDOW_SIZE | 1 << DC_32K_WINDOW_SIZE); + pCompService->comp_device_data.cnvnrSupported = CPA_TRUE; + break; + default: + QAT_UTILS_LOG("Unknown device type! - %d.\n", + device->deviceType); + return CPA_STATUS_FAIL; + } + return CPA_STATUS_SUCCESS; +} + +CpaStatus +SalCtrl_CompressionInit(icp_accel_dev_t *device, sal_service_t *service) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + Cpa32U numCompConcurrentReq = 0; + Cpa32U request_ring_id = 0; + Cpa32U response_ring_id = 0; + + char adfGetParam[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + char compMemPool[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + char temp_string2[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + char *instance_name = NULL; + sal_statistics_collection_t *pStatsCollection = + (sal_statistics_collection_t *)device->pQatStats; + icp_resp_deliv_method rx_resp_type = ICP_RESP_TYPE_IRQ; + sal_compression_service_t *pCompressionService = + (sal_compression_service_t *)service; + Cpa32U msgSize = 0; + char *section = DYN_SEC; + + SAL_SERVICE_GOOD_FOR_INIT(pCompressionService); + + pCompressionService->generic_service_info.state = + SAL_SERVICE_STATE_INITIALIZING; + + if (CPA_FALSE == pCompressionService->generic_service_info.is_dyn) { + section = icpGetProcessName(); + } + + if (pStatsCollection == NULL) { + return CPA_STATUS_FAIL; + } + + /* Get Config Info: Accel Num, bank Num, packageID, + coreAffinity, nodeAffinity and response mode + */ + + pCompressionService->acceleratorNum = 0; + + /* Initialise device specific compression data */ + SalCtrl_CompressionInit_CompData(device, pCompressionService); + + status = Sal_StringParsing( + "Dc", + pCompressionService->generic_service_info.instance, + "BankNumber", + temp_string); + LAC_CHECK_STATUS(status); + status = + icp_adf_cfgGetParamValue(device, section, temp_string, adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration.\n", + temp_string); + return status; + } + + pCompressionService->bankNum = + Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); + + status = Sal_StringParsing( + "Dc", + pCompressionService->generic_service_info.instance, + "IsPolled", + temp_string); + LAC_CHECK_STATUS(status); + status = + icp_adf_cfgGetParamValue(device, section, temp_string, adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration.\n", + temp_string); + return status; + } + pCompressionService->isPolled = + (Cpa8U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); + + /* User instances only support poll and epoll mode */ + if (SAL_RESP_POLL_CFG_FILE != pCompressionService->isPolled) { + QAT_UTILS_LOG( + "IsPolled %u is not supported for user instance %s.\n", + pCompressionService->isPolled, + temp_string); + return CPA_STATUS_FAIL; + } + + if (SAL_RESP_POLL_CFG_FILE == pCompressionService->isPolled) { + rx_resp_type = ICP_RESP_TYPE_POLL; + } + + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + ADF_DEV_PKG_ID, + adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration.\n", + ADF_DEV_PKG_ID); + return status; + } + pCompressionService->pkgID = + (Cpa16U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); + + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + ADF_DEV_NODE_ID, + adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration.\n", + ADF_DEV_NODE_ID); + return status; + } + pCompressionService->nodeAffinity = + (Cpa32U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); + + /* In case of interrupt instance, use the bank affinity set by adf_ctl + * Otherwise, use the instance affinity for backwards compatibility */ + if (SAL_RESP_POLL_CFG_FILE != pCompressionService->isPolled) { + /* Next need to read the [AcceleratorX] section of the config + * file */ + status = Sal_StringParsing("Accelerator", + pCompressionService->acceleratorNum, + "", + temp_string2); + LAC_CHECK_STATUS(status); + + status = Sal_StringParsing("Bank", + pCompressionService->bankNum, + "CoreAffinity", + temp_string); + LAC_CHECK_STATUS(status); + } else { + strncpy(temp_string2, + section, + sizeof(temp_string2) - SAL_NULL_TERM_SIZE); + temp_string2[SAL_CFG_MAX_VAL_LEN_IN_BYTES - + SAL_NULL_TERM_SIZE] = '\0'; + + status = Sal_StringParsing( + "Dc", + pCompressionService->generic_service_info.instance, + "CoreAffinity", + temp_string); + LAC_CHECK_STATUS(status); + } + + status = icp_adf_cfgGetParamValue(device, + temp_string2, + temp_string, + adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration.\n", + temp_string); + return status; + } + pCompressionService->coreAffinity = + (Cpa32U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); + + status = Sal_StringParsing( + "Dc", + pCompressionService->generic_service_info.instance, + "NumConcurrentRequests", + temp_string); + LAC_CHECK_STATUS(status); + status = + icp_adf_cfgGetParamValue(device, section, temp_string, adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration.\n", + temp_string); + return status; + } + + numCompConcurrentReq = + (Cpa32U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); + if (validateConcurrRequest(numCompConcurrentReq)) { + QAT_UTILS_LOG( + "Invalid NumConcurrentRequests, valid values are: {64, 128, 256, ... 32768, 65536}.\n"); + return CPA_STATUS_FAIL; + } + + /* ADF does not allow us to completely fill the ring for batch requests + */ + pCompressionService->maxNumCompConcurrentReq = + (numCompConcurrentReq - SAL_BATCH_SUBMIT_FREE_SPACE); + + /* 1. Create transport handles */ + status = Sal_StringParsing( + "Dc", + pCompressionService->generic_service_info.instance, + "RingTx", + temp_string); + LAC_CHECK_STATUS(status); + + msgSize = LAC_QAT_DC_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES; + status = icp_adf_transCreateHandle( + device, + ICP_TRANS_TYPE_ETR, + section, + pCompressionService->acceleratorNum, + pCompressionService->bankNum, + temp_string, + lac_getRingType(SAL_RING_TYPE_DC), + NULL, + ICP_RESP_TYPE_NONE, + numCompConcurrentReq, + msgSize, + (icp_comms_trans_handle *)&( + pCompressionService->trans_handle_compression_tx)); + LAC_CHECK_STATUS(status); + + if (icp_adf_transGetRingNum( + pCompressionService->trans_handle_compression_tx, + &request_ring_id) != CPA_STATUS_SUCCESS) { + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + + QAT_UTILS_LOG("Failed to get DC TX ring number.\n"); + return CPA_STATUS_FAIL; + } + + status = Sal_StringParsing( + "Dc", + pCompressionService->generic_service_info.instance, + "RingRx", + temp_string); + if (CPA_STATUS_SUCCESS != status) { + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + return status; + } + + msgSize = LAC_QAT_DC_RESP_SZ_LW * LAC_LONG_WORD_IN_BYTES; + status = icp_adf_transCreateHandle( + device, + ICP_TRANS_TYPE_ETR, + section, + pCompressionService->acceleratorNum, + pCompressionService->bankNum, + temp_string, + lac_getRingType(SAL_RING_TYPE_NONE), + (icp_trans_callback)dcCompression_ProcessCallback, + rx_resp_type, + numCompConcurrentReq, + msgSize, + (icp_comms_trans_handle *)&( + pCompressionService->trans_handle_compression_rx)); + if (CPA_STATUS_SUCCESS != status) { + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + return status; + } + + if (icp_adf_transGetRingNum( + pCompressionService->trans_handle_compression_rx, + &response_ring_id) != CPA_STATUS_SUCCESS) { + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_rx); + + QAT_UTILS_LOG("Failed to get DC RX ring number.\n"); + return CPA_STATUS_FAIL; + } + + /* 2. Allocates memory pools */ + + /* Valid initialisation value for a pool ID */ + pCompressionService->compression_mem_pool = LAC_MEM_POOL_INIT_POOL_ID; + + status = Sal_StringParsing( + "Comp", + pCompressionService->generic_service_info.instance, + "_MemPool", + compMemPool); + if (CPA_STATUS_SUCCESS != status) { + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_rx); + + return status; + } + + status = Lac_MemPoolCreate(&pCompressionService->compression_mem_pool, + compMemPool, + (numCompConcurrentReq + 1), + sizeof(dc_compression_cookie_t), + LAC_64BYTE_ALIGNMENT, + CPA_FALSE, + pCompressionService->nodeAffinity); + if (CPA_STATUS_SUCCESS != status) { + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_rx); + + return status; + } + + /* Init compression statistics */ + status = dcStatsInit(pCompressionService); + if (CPA_STATUS_SUCCESS != status) { + Lac_MemPoolDestroy(pCompressionService->compression_mem_pool); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_rx); + + return status; + } + if (CPA_TRUE == pStatsCollection->bDcStatsEnabled) { + /* Get instance name for stats */ + instance_name = LAC_OS_MALLOC(ADF_CFG_MAX_VAL_LEN_IN_BYTES); + if (NULL == instance_name) { + Lac_MemPoolDestroy( + pCompressionService->compression_mem_pool); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_rx); + + return CPA_STATUS_RESOURCE; + } + + status = Sal_StringParsing( + "Dc", + pCompressionService->generic_service_info.instance, + "Name", + temp_string); + if (CPA_STATUS_SUCCESS != status) { + Lac_MemPoolDestroy( + pCompressionService->compression_mem_pool); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_rx); + LAC_OS_FREE(instance_name); + return status; + } + status = icp_adf_cfgGetParamValue(device, + section, + temp_string, + adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration.\n", + temp_string); + + Lac_MemPoolDestroy( + pCompressionService->compression_mem_pool); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_rx); + LAC_OS_FREE(instance_name); + return status; + } + + snprintf(instance_name, + ADF_CFG_MAX_VAL_LEN_IN_BYTES, + "%s", + adfGetParam); + + pCompressionService->debug_file = + LAC_OS_MALLOC(sizeof(debug_file_info_t)); + if (NULL == pCompressionService->debug_file) { + Lac_MemPoolDestroy( + pCompressionService->compression_mem_pool); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_rx); + LAC_OS_FREE(instance_name); + return CPA_STATUS_RESOURCE; + } + + memset(pCompressionService->debug_file, + 0, + sizeof(debug_file_info_t)); + pCompressionService->debug_file->name = instance_name; + pCompressionService->debug_file->seq_read = + SalCtrl_CompresionDebug; + pCompressionService->debug_file->private_data = + pCompressionService; + pCompressionService->debug_file->parent = + pCompressionService->generic_service_info.debug_parent_dir; + + status = icp_adf_debugAddFile(device, + pCompressionService->debug_file); + if (CPA_STATUS_SUCCESS != status) { + Lac_MemPoolDestroy( + pCompressionService->compression_mem_pool); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + + icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_rx); + LAC_OS_FREE(instance_name); + LAC_OS_FREE(pCompressionService->debug_file); + return status; + } + } + pCompressionService->generic_service_info.stats = pStatsCollection; + pCompressionService->generic_service_info.state = + SAL_SERVICE_STATE_INITIALIZED; + + return status; +} + +CpaStatus +SalCtrl_CompressionStart(icp_accel_dev_t *device, sal_service_t *service) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + sal_compression_service_t *pCompressionService = + (sal_compression_service_t *)service; + + if (SAL_SERVICE_STATE_INITIALIZED != + pCompressionService->generic_service_info.state) { + QAT_UTILS_LOG("Not in the correct state to call start.\n"); + return CPA_STATUS_FAIL; + } + /**************************************************************/ + /* Obtain Extended Features. I.e. Compress And Verify */ + /**************************************************************/ + pCompressionService->generic_service_info.dcExtendedFeatures = + device->dcExtendedFeatures; + pCompressionService->generic_service_info.state = + SAL_SERVICE_STATE_RUNNING; + + return status; +} + +CpaStatus +SalCtrl_CompressionStop(icp_accel_dev_t *device, sal_service_t *service) +{ + sal_compression_service_t *pCompressionService = + (sal_compression_service_t *)service; + + if (SAL_SERVICE_STATE_RUNNING != + pCompressionService->generic_service_info.state) { + QAT_UTILS_LOG("Not in the correct state to call stop.\n"); + return CPA_STATUS_FAIL; + } + + if (icp_adf_is_dev_in_reset(device)) { + pCompressionService->generic_service_info.state = + SAL_SERVICE_STATE_RESTARTING; + return CPA_STATUS_SUCCESS; + } + + pCompressionService->generic_service_info.state = + SAL_SERVICE_STATE_SHUTTING_DOWN; + return CPA_STATUS_RETRY; +} + +CpaStatus +SalCtrl_CompressionShutdown(icp_accel_dev_t *device, sal_service_t *service) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + sal_compression_service_t *pCompressionService = + (sal_compression_service_t *)service; + sal_statistics_collection_t *pStatsCollection = + (sal_statistics_collection_t *)device->pQatStats; + + if ((SAL_SERVICE_STATE_INITIALIZED != + pCompressionService->generic_service_info.state) && + (SAL_SERVICE_STATE_SHUTTING_DOWN != + pCompressionService->generic_service_info.state) && + (SAL_SERVICE_STATE_RESTARTING != + pCompressionService->generic_service_info.state)) { + QAT_UTILS_LOG("Not in the correct state to call shutdown.\n"); + return CPA_STATUS_FAIL; + } + + Lac_MemPoolDestroy(pCompressionService->compression_mem_pool); + + status = icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_tx); + LAC_CHECK_STATUS(status); + + status = icp_adf_transReleaseHandle( + pCompressionService->trans_handle_compression_rx); + LAC_CHECK_STATUS(status); + + if (CPA_TRUE == pStatsCollection->bDcStatsEnabled) { + /* Clean stats */ + if (NULL != pCompressionService->debug_file) { + icp_adf_debugRemoveFile( + pCompressionService->debug_file); + LAC_OS_FREE(pCompressionService->debug_file->name); + LAC_OS_FREE(pCompressionService->debug_file); + pCompressionService->debug_file = NULL; + } + } + pCompressionService->generic_service_info.stats = NULL; + dcStatsFree(pCompressionService); + + if (icp_adf_is_dev_in_reset(device)) { + pCompressionService->generic_service_info.state = + SAL_SERVICE_STATE_RESTARTING; + return CPA_STATUS_SUCCESS; + } + pCompressionService->generic_service_info.state = + SAL_SERVICE_STATE_SHUTDOWN; + return status; +} + +CpaStatus +cpaDcGetStatusText(const CpaInstanceHandle dcInstance, + const CpaStatus errStatus, + Cpa8S *pStatusText) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + LAC_CHECK_NULL_PARAM(pStatusText); + + switch (errStatus) { + case CPA_STATUS_SUCCESS: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_SUCCESS); + break; + case CPA_STATUS_FAIL: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_FAIL); + break; + case CPA_STATUS_RETRY: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_RETRY); + break; + case CPA_STATUS_RESOURCE: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_RESOURCE); + break; + case CPA_STATUS_INVALID_PARAM: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_INVALID_PARAM); + break; + case CPA_STATUS_FATAL: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_FATAL); + break; + case CPA_STATUS_UNSUPPORTED: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_UNSUPPORTED); + break; + default: + status = CPA_STATUS_INVALID_PARAM; + break; + } + + return status; +} + +CpaStatus +cpaDcGetNumIntermediateBuffers(CpaInstanceHandle dcInstance, + Cpa16U *pNumBuffers) +{ + CpaInstanceHandle insHandle = NULL; + sal_compression_service_t *pService = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = dcInstance; + } + + LAC_CHECK_NULL_PARAM(insHandle); + LAC_CHECK_NULL_PARAM(pNumBuffers); + + pService = (sal_compression_service_t *)insHandle; + *pNumBuffers = pService->numInterBuffs; + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcStartInstance(CpaInstanceHandle instanceHandle, + Cpa16U numBuffers, + CpaBufferList **pIntermediateBufferPtrsArray) +{ + icp_qat_addr_width_t *pInterBuffPtrsArray = NULL; + icp_qat_addr_width_t pArrayBufferListDescPhyAddr = 0; + icp_qat_addr_width_t bufListDescPhyAddr; + icp_qat_addr_width_t bufListAlignedPhyAddr; + CpaFlatBuffer *pClientCurrFlatBuffer = NULL; + icp_buffer_list_desc_t *pBufferListDesc = NULL; + icp_flat_buffer_desc_t *pCurrFlatBufDesc = NULL; + CpaInstanceInfo2 info = { 0 }; + icp_accel_dev_t *dev = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + sal_compression_service_t *pService = NULL; + CpaInstanceHandle insHandle = NULL; + Cpa16U bufferIndex = 0; + Cpa32U numFlatBuffers = 0; + Cpa64U clientListSize = 0; + CpaBufferList *pClientCurrentIntermediateBuffer = NULL; + Cpa32U bufferIndex2 = 0; + CpaBufferList **pTempIntermediateBufferPtrsArray; + Cpa64U lastClientListSize = 0; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = instanceHandle; + } + LAC_CHECK_NULL_PARAM(insHandle); + + status = cpaDcInstanceGetInfo2(insHandle, &info); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Can not get instance info.\n"); + return status; + } + + dev = icp_adf_getAccelDevByAccelId(info.physInstId.packageId); + if (NULL == dev) { + QAT_UTILS_LOG("Can not find device for the instance\n"); + return CPA_STATUS_FAIL; + } + + if (NULL == pIntermediateBufferPtrsArray) { + /* Increment dev ref counter and return - DRAM is not used */ + icp_qa_dev_get(dev); + return CPA_STATUS_SUCCESS; + } + + if (0 == numBuffers) { + /* Increment dev ref counter and return - DRAM is not used */ + icp_qa_dev_get(dev); + return CPA_STATUS_SUCCESS; + } + + pService = (sal_compression_service_t *)insHandle; + + LAC_CHECK_NULL_PARAM(insHandle); + + if ((numBuffers > 0) && (NULL == pIntermediateBufferPtrsArray)) { + QAT_UTILS_LOG("Invalid Intermediate Buffers Array pointer\n"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Check number of intermediate buffers allocated by user */ + if ((pService->numInterBuffs != numBuffers)) { + QAT_UTILS_LOG("Invalid number of buffers\n"); + return CPA_STATUS_INVALID_PARAM; + } + + pTempIntermediateBufferPtrsArray = pIntermediateBufferPtrsArray; + for (bufferIndex = 0; bufferIndex < numBuffers; bufferIndex++) { + if (NULL == *pTempIntermediateBufferPtrsArray) { + QAT_UTILS_LOG( + "Intermediate Buffer - Invalid Buffer List pointer\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (NULL == (*pTempIntermediateBufferPtrsArray)->pBuffers) { + QAT_UTILS_LOG( + "Intermediate Buffer - Invalid Flat Buffer descriptor pointer\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (NULL == + (*pTempIntermediateBufferPtrsArray)->pPrivateMetaData) { + QAT_UTILS_LOG( + "Intermediate Buffer - Invalid Private MetaData descriptor pointer\n"); + return CPA_STATUS_INVALID_PARAM; + } + + clientListSize = 0; + for (bufferIndex2 = 0; bufferIndex2 < + (*pTempIntermediateBufferPtrsArray)->numBuffers; + bufferIndex2++) { + + if ((0 != + (*pTempIntermediateBufferPtrsArray) + ->pBuffers[bufferIndex2] + .dataLenInBytes) && + NULL == + (*pTempIntermediateBufferPtrsArray) + ->pBuffers[bufferIndex2] + .pData) { + QAT_UTILS_LOG( + "Intermediate Buffer - Invalid Flat Buffer pointer\n"); + return CPA_STATUS_INVALID_PARAM; + } + + clientListSize += (*pTempIntermediateBufferPtrsArray) + ->pBuffers[bufferIndex2] + .dataLenInBytes; + } + + if (bufferIndex != 0) { + if (lastClientListSize != clientListSize) { + QAT_UTILS_LOG( + "SGLs have to be of the same size.\n"); + return CPA_STATUS_INVALID_PARAM; + } + } else { + lastClientListSize = clientListSize; + } + pTempIntermediateBufferPtrsArray++; + } + + /* Allocate array of physical pointers to icp_buffer_list_desc_t */ + status = LAC_OS_CAMALLOC(&pInterBuffPtrsArray, + (numBuffers * sizeof(icp_qat_addr_width_t)), + LAC_64BYTE_ALIGNMENT, + pService->nodeAffinity); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Can not allocate Intermediate Buffers array.\n"); + return status; + } + + /* Get physical address of the intermediate buffer pointers array */ + pArrayBufferListDescPhyAddr = LAC_MEM_CAST_PTR_TO_UINT64( + LAC_OS_VIRT_TO_PHYS_INTERNAL(pInterBuffPtrsArray)); + + pService->pInterBuffPtrsArray = pInterBuffPtrsArray; + pService->pInterBuffPtrsArrayPhyAddr = pArrayBufferListDescPhyAddr; + + /* Get the full size of the buffer list */ + /* Assumption: all the SGLs allocated by the user have the same size */ + clientListSize = 0; + for (bufferIndex = 0; + bufferIndex < (*pIntermediateBufferPtrsArray)->numBuffers; + bufferIndex++) { + clientListSize += ((*pIntermediateBufferPtrsArray) + ->pBuffers[bufferIndex] + .dataLenInBytes); + } + pService->minInterBuffSizeInBytes = clientListSize; + + for (bufferIndex = 0; bufferIndex < numBuffers; bufferIndex++) { + + /* Get pointer to the client Intermediate Buffer List + * (CpaBufferList) */ + pClientCurrentIntermediateBuffer = + *pIntermediateBufferPtrsArray; + + /* Get number of flat buffers in the buffer list */ + numFlatBuffers = pClientCurrentIntermediateBuffer->numBuffers; + + /* Get pointer to the client array of CpaFlatBuffers */ + pClientCurrFlatBuffer = + pClientCurrentIntermediateBuffer->pBuffers; + + /* Calculate Physical address of current private SGL */ + bufListDescPhyAddr = LAC_OS_VIRT_TO_PHYS_EXTERNAL( + (*pService), + pClientCurrentIntermediateBuffer->pPrivateMetaData); + if (bufListDescPhyAddr == 0) { + QAT_UTILS_LOG( + "Unable to get the physical address of the metadata.\n"); + return CPA_STATUS_FAIL; + } + + /* Align SGL physical address */ + bufListAlignedPhyAddr = + LAC_ALIGN_POW2_ROUNDUP(bufListDescPhyAddr, + ICP_DESCRIPTOR_ALIGNMENT_BYTES); + + /* Set physical address of the Intermediate Buffer SGL in the + * SGLs array + */ + *pInterBuffPtrsArray = + LAC_MEM_CAST_PTR_TO_UINT64(bufListAlignedPhyAddr); + + /* Calculate (virtual) offset to the buffer list descriptor */ + pBufferListDesc = + (icp_buffer_list_desc_t + *)((LAC_ARCH_UINT)pClientCurrentIntermediateBuffer + ->pPrivateMetaData + + (LAC_ARCH_UINT)(bufListAlignedPhyAddr - + bufListDescPhyAddr)); + + /* Set number of flat buffers in the physical Buffer List + * descriptor */ + pBufferListDesc->numBuffers = numFlatBuffers; + + /* Go past the Buffer List descriptor to the list of buffer + * descriptors + */ + pCurrFlatBufDesc = + (icp_flat_buffer_desc_t *)((pBufferListDesc->phyBuffers)); + + /* Loop for each flat buffer in the SGL */ + while (0 != numFlatBuffers) { + /* Set length of the current flat buffer */ + pCurrFlatBufDesc->dataLenInBytes = + pClientCurrFlatBuffer->dataLenInBytes; + + /* Set physical address of the flat buffer */ + pCurrFlatBufDesc->phyBuffer = + LAC_MEM_CAST_PTR_TO_UINT64( + LAC_OS_VIRT_TO_PHYS_EXTERNAL( + (*pService), pClientCurrFlatBuffer->pData)); + + if (pCurrFlatBufDesc->phyBuffer == 0) { + QAT_UTILS_LOG( + "Unable to get the physical address of the flat buffer.\n"); + return CPA_STATUS_FAIL; + } + + pCurrFlatBufDesc++; + pClientCurrFlatBuffer++; + numFlatBuffers--; + } + pIntermediateBufferPtrsArray++; + pInterBuffPtrsArray++; + } + + pService->generic_service_info.isInstanceStarted = CPA_TRUE; + + /* Increment dev ref counter */ + icp_qa_dev_get(dev); + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcStopInstance(CpaInstanceHandle instanceHandle) +{ + CpaInstanceHandle insHandle = NULL; + CpaInstanceInfo2 info = { 0 }; + icp_accel_dev_t *dev = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + sal_compression_service_t *pService = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = instanceHandle; + } + + LAC_CHECK_NULL_PARAM(insHandle); + pService = (sal_compression_service_t *)insHandle; + + /* Free Intermediate Buffer Pointers Array */ + if (pService->pInterBuffPtrsArray != NULL) { + LAC_OS_CAFREE(pService->pInterBuffPtrsArray); + pService->pInterBuffPtrsArray = 0; + } + + pService->pInterBuffPtrsArrayPhyAddr = 0; + + status = cpaDcInstanceGetInfo2(insHandle, &info); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Can not get instance info.\n"); + return status; + } + dev = icp_adf_getAccelDevByAccelId(info.physInstId.packageId); + if (NULL == dev) { + QAT_UTILS_LOG("Can not find device for the instance.\n"); + return CPA_STATUS_FAIL; + } + + pService->generic_service_info.isInstanceStarted = CPA_FALSE; + + /* Decrement dev ref counter */ + icp_qa_dev_put(dev); + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcGetNumInstances(Cpa16U *pNumInstances) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + icp_accel_dev_t **pAdfInsts = NULL; + icp_accel_dev_t *dev_addr = NULL; + sal_t *base_addr = NULL; + sal_list_t *list_temp = NULL; + Cpa16U num_accel_dev = 0; + Cpa16U num = 0; + Cpa16U i = 0; + + LAC_CHECK_NULL_PARAM(pNumInstances); + + /* Get the number of accel_dev in the system */ + status = icp_amgr_getNumInstances(&num_accel_dev); + LAC_CHECK_STATUS(status); + + /* Allocate memory to store addr of accel_devs */ + pAdfInsts = + malloc(num_accel_dev * sizeof(icp_accel_dev_t *), M_QAT, M_WAITOK); + num_accel_dev = 0; + + /* Get ADF to return accel_devs with dc enabled */ + status = icp_amgr_getAllAccelDevByCapabilities( + ICP_ACCEL_CAPABILITIES_COMPRESSION, pAdfInsts, &num_accel_dev); + if (CPA_STATUS_SUCCESS == status) { + for (i = 0; i < num_accel_dev; i++) { + dev_addr = (icp_accel_dev_t *)pAdfInsts[i]; + if (NULL != dev_addr) { + base_addr = dev_addr->pSalHandle; + if (NULL != base_addr) { + list_temp = + base_addr->compression_services; + while (NULL != list_temp) { + num++; + list_temp = + SalList_next(list_temp); + } + } + } + } + + *pNumInstances = num; + } + + free(pAdfInsts, M_QAT); + + return status; +} + +CpaStatus +cpaDcGetInstances(Cpa16U numInstances, CpaInstanceHandle *dcInstances) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + icp_accel_dev_t **pAdfInsts = NULL; + icp_accel_dev_t *dev_addr = NULL; + sal_t *base_addr = NULL; + sal_list_t *list_temp = NULL; + Cpa16U num_accel_dev = 0; + Cpa16U index = 0; + Cpa16U i = 0; + + LAC_CHECK_NULL_PARAM(dcInstances); + if (0 == numInstances) { + QAT_UTILS_LOG("numInstances is 0.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Get the number of accel_dev in the system */ + status = icp_amgr_getNumInstances(&num_accel_dev); + LAC_CHECK_STATUS(status); + + /* Allocate memory to store addr of accel_devs */ + pAdfInsts = + malloc(num_accel_dev * sizeof(icp_accel_dev_t *), M_QAT, M_WAITOK); + + num_accel_dev = 0; + /* Get ADF to return accel_devs with dc enabled */ + status = icp_amgr_getAllAccelDevByCapabilities( + ICP_ACCEL_CAPABILITIES_COMPRESSION, pAdfInsts, &num_accel_dev); + + if (CPA_STATUS_SUCCESS == status) { + /* First check the number of instances in the system */ + for (i = 0; i < num_accel_dev; i++) { + dev_addr = (icp_accel_dev_t *)pAdfInsts[i]; + if (NULL != dev_addr) { + base_addr = dev_addr->pSalHandle; + if (NULL != base_addr) { + list_temp = + base_addr->compression_services; + while (NULL != list_temp) { + if (index > + (numInstances - 1)) { + break; + } + + dcInstances[index] = + SalList_getObject( + list_temp); + list_temp = + SalList_next(list_temp); + index++; + } + } + } + } + + if (numInstances > index) { + QAT_UTILS_LOG("Only %d dc instances available.\n", + index); + status = CPA_STATUS_RESOURCE; + } + } + + if (CPA_STATUS_SUCCESS == status) { + index = 0; + for (i = 0; i < num_accel_dev; i++) { + dev_addr = (icp_accel_dev_t *)pAdfInsts[i]; + /* Note dev_addr cannot be NULL here as numInstances=0 + is not valid and if dev_addr=NULL then index=0 (which + is less than numInstances and status is set to + _RESOURCE + above */ + base_addr = dev_addr->pSalHandle; + if (NULL != base_addr) { + list_temp = base_addr->compression_services; + while (NULL != list_temp) { + if (index > (numInstances - 1)) { + break; + } + + dcInstances[index] = + SalList_getObject(list_temp); + list_temp = SalList_next(list_temp); + index++; + } + } + } + } + + free(pAdfInsts, M_QAT); + + return status; +} + +CpaStatus +cpaDcInstanceGetInfo2(const CpaInstanceHandle instanceHandle, + CpaInstanceInfo2 *pInstanceInfo2) +{ + sal_compression_service_t *pCompressionService = NULL; + CpaInstanceHandle insHandle = NULL; + icp_accel_dev_t *dev = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + char keyStr[ADF_CFG_MAX_KEY_LEN_IN_BYTES] = { 0 }; + char valStr[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + char *section = DYN_SEC; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = instanceHandle; + } + + LAC_CHECK_NULL_PARAM(insHandle); + SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); + LAC_CHECK_NULL_PARAM(pInstanceInfo2); + + LAC_OS_BZERO(pInstanceInfo2, sizeof(CpaInstanceInfo2)); + pInstanceInfo2->accelerationServiceType = + CPA_ACC_SVC_TYPE_DATA_COMPRESSION; + + snprintf((char *)pInstanceInfo2->vendorName, + CPA_INST_VENDOR_NAME_SIZE, + "%s", + SAL_INFO2_VENDOR_NAME); + pInstanceInfo2->vendorName[CPA_INST_VENDOR_NAME_SIZE - 1] = '\0'; + + snprintf((char *)pInstanceInfo2->swVersion, + CPA_INST_SW_VERSION_SIZE, + "Version %d.%d", + SAL_INFO2_DRIVER_SW_VERSION_MAJ_NUMBER, + SAL_INFO2_DRIVER_SW_VERSION_MIN_NUMBER); + pInstanceInfo2->swVersion[CPA_INST_SW_VERSION_SIZE - 1] = '\0'; + + /* Note we can safely read the contents of the compression service + instance + here because icp_amgr_getAccelDevByCapabilities() only returns devs + that have started */ + pCompressionService = (sal_compression_service_t *)insHandle; + pInstanceInfo2->physInstId.packageId = pCompressionService->pkgID; + pInstanceInfo2->physInstId.acceleratorId = + pCompressionService->acceleratorNum; + pInstanceInfo2->physInstId.executionEngineId = 0; + pInstanceInfo2->physInstId.busAddress = + icp_adf_get_busAddress(pInstanceInfo2->physInstId.packageId); + + /* set coreAffinity to zero before use */ + LAC_OS_BZERO(pInstanceInfo2->coreAffinity, + sizeof(pInstanceInfo2->coreAffinity)); + CPA_BITMAP_BIT_SET(pInstanceInfo2->coreAffinity, + pCompressionService->coreAffinity); + + pInstanceInfo2->nodeAffinity = pCompressionService->nodeAffinity; + + if (CPA_TRUE == + pCompressionService->generic_service_info.isInstanceStarted) { + pInstanceInfo2->operState = CPA_OPER_STATE_UP; + } else { + pInstanceInfo2->operState = CPA_OPER_STATE_DOWN; + } + + pInstanceInfo2->requiresPhysicallyContiguousMemory = CPA_TRUE; + + if (SAL_RESP_POLL_CFG_FILE == pCompressionService->isPolled) { + pInstanceInfo2->isPolled = CPA_TRUE; + } else { + pInstanceInfo2->isPolled = CPA_FALSE; + } + + pInstanceInfo2->isOffloaded = CPA_TRUE; + /* Get the instance name and part name from the config file */ + dev = icp_adf_getAccelDevByAccelId(pCompressionService->pkgID); + if (NULL == dev) { + QAT_UTILS_LOG("Can not find device for the instance.\n"); + LAC_OS_BZERO(pInstanceInfo2, sizeof(CpaInstanceInfo2)); + return CPA_STATUS_FAIL; + } + snprintf((char *)pInstanceInfo2->partName, + CPA_INST_PART_NAME_SIZE, + SAL_INFO2_PART_NAME, + dev->deviceName); + pInstanceInfo2->partName[CPA_INST_PART_NAME_SIZE - 1] = '\0'; + + if (CPA_FALSE == pCompressionService->generic_service_info.is_dyn) { + section = icpGetProcessName(); + } + + status = Sal_StringParsing( + "Dc", + pCompressionService->generic_service_info.instance, + "Name", + keyStr); + LAC_CHECK_STATUS(status); + status = icp_adf_cfgGetParamValue(dev, section, keyStr, valStr); + LAC_CHECK_STATUS(status); + strncpy((char *)pInstanceInfo2->instName, + valStr, + sizeof(pInstanceInfo2->instName) - 1); + pInstanceInfo2->instName[CPA_INST_NAME_SIZE - 1] = '\0'; + +#if __GNUC__ >= 7 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-truncation" +#endif + snprintf((char *)pInstanceInfo2->instID, + CPA_INST_ID_SIZE, + "%s_%s", + section, + valStr); +#if __GNUC__ >= 7 +#pragma GCC diagnostic pop +#endif + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcQueryCapabilities(CpaInstanceHandle dcInstance, + CpaDcInstanceCapabilities *pInstanceCapabilities) +{ + CpaInstanceHandle insHandle = NULL; + sal_compression_service_t *pService = NULL; + Cpa32U capabilitiesMask = 0; + dc_extd_ftrs_t *pExtendedFtrs = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) { + insHandle = dcGetFirstHandle(); + if (NULL == insHandle) { + QAT_UTILS_LOG("Can not get the instance.\n"); + return CPA_STATUS_FAIL; + } + } else { + insHandle = dcInstance; + } + + pService = (sal_compression_service_t *)insHandle; + + LAC_CHECK_NULL_PARAM(insHandle); + SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); + LAC_CHECK_NULL_PARAM(pInstanceCapabilities); + + memset(pInstanceCapabilities, 0, sizeof(CpaDcInstanceCapabilities)); + + capabilitiesMask = pService->generic_service_info.capabilitiesMask; + + /* Set compression capabilities */ + if (capabilitiesMask & ICP_ACCEL_CAPABILITIES_CNV_INTEGRITY) { + pInstanceCapabilities->integrityCrcs = CPA_TRUE; + } + + pInstanceCapabilities->endOfLastBlock = CPA_TRUE; + pInstanceCapabilities->statefulDeflateCompression = CPA_FALSE; + pInstanceCapabilities->statefulDeflateDecompression = CPA_TRUE; + pInstanceCapabilities->statelessDeflateCompression = CPA_TRUE; + pInstanceCapabilities->statelessDeflateDecompression = CPA_TRUE; + pInstanceCapabilities->checksumCRC32 = CPA_TRUE; + pInstanceCapabilities->checksumAdler32 = CPA_TRUE; + pInstanceCapabilities->dynamicHuffman = CPA_TRUE; + pInstanceCapabilities->precompiledHuffman = CPA_FALSE; + pInstanceCapabilities->dynamicHuffmanBufferReq = CPA_TRUE; + pInstanceCapabilities->autoSelectBestHuffmanTree = CPA_TRUE; + + pInstanceCapabilities->validWindowSizeMaskCompression = + pService->comp_device_data.windowSizeMask; + pInstanceCapabilities->validWindowSizeMaskDecompression = + pService->comp_device_data.windowSizeMask; + pExtendedFtrs = (dc_extd_ftrs_t *)&( + ((sal_service_t *)insHandle)->dcExtendedFeatures); + pInstanceCapabilities->batchAndPack = CPA_FALSE; + pInstanceCapabilities->compressAndVerify = + (CpaBoolean)pExtendedFtrs->is_cnv; + pInstanceCapabilities->compressAndVerifyStrict = CPA_TRUE; + pInstanceCapabilities->compressAndVerifyAndRecover = + (CpaBoolean)pExtendedFtrs->is_cnvnr; + return CPA_STATUS_SUCCESS; +} + +CpaStatus +cpaDcSetAddressTranslation(const CpaInstanceHandle instanceHandle, + CpaVirtualToPhysical virtual2Physical) +{ + sal_service_t *pService = NULL; + CpaInstanceHandle insHandle = NULL; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle) { + insHandle = dcGetFirstHandle(); + } else { + insHandle = instanceHandle; + } + + LAC_CHECK_NULL_PARAM(insHandle); + SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION); + LAC_CHECK_NULL_PARAM(virtual2Physical); + + pService = (sal_service_t *)insHandle; + + pService->virt2PhysClient = virtual2Physical; + + return CPA_STATUS_SUCCESS; +} + +/** + ****************************************************************************** + * @ingroup cpaDcCommon + * Data compression specific polling function which polls a DC instance. + *****************************************************************************/ + +CpaStatus +icp_sal_DcPollInstance(CpaInstanceHandle instanceHandle_in, + Cpa32U response_quota) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_compression_service_t *dc_handle = NULL; + sal_service_t *gen_handle = NULL; + icp_comms_trans_handle trans_hndTable[DC_NUM_RX_RINGS]; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + dc_handle = (sal_compression_service_t *)dcGetFirstHandle(); + } else { + dc_handle = (sal_compression_service_t *)instanceHandle_in; + } + + LAC_CHECK_NULL_PARAM(dc_handle); + SAL_RUNNING_CHECK(dc_handle); + + gen_handle = &(dc_handle->generic_service_info); + if (SAL_SERVICE_TYPE_COMPRESSION != gen_handle->type) { + QAT_UTILS_LOG("Instance handle type is incorrect.\n"); + return CPA_STATUS_FAIL; + } + + /* + * From the instanceHandle we must get the trans_handle and send + * down to adf for polling. + * Populate our trans handle table with the appropriate handles. + */ + trans_hndTable[0] = dc_handle->trans_handle_compression_rx; + + /* Call adf to do the polling. */ + status = icp_adf_pollInstance(trans_hndTable, + DC_NUM_RX_RINGS, + response_quota); + return status; +} + +/** + ****************************************************************************** + * @ingroup cpaDcCommon + *****************************************************************************/ +CpaStatus +cpaDcInstanceSetNotificationCb( + const CpaInstanceHandle instanceHandle, + const CpaDcInstanceNotificationCbFunc pInstanceNotificationCb, + void *pCallbackTag) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_service_t *gen_handle = instanceHandle; + + LAC_CHECK_NULL_PARAM(gen_handle); + gen_handle->notification_cb = pInstanceNotificationCb; + gen_handle->cb_tag = pCallbackTag; + return status; +} + +CpaInstanceHandle +dcGetFirstHandle(void) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + static icp_accel_dev_t *adfInsts[ADF_MAX_DEVICES] = { 0 }; + CpaInstanceHandle dcInst = NULL; + icp_accel_dev_t *dev_addr = NULL; + sal_t *base_addr = NULL; + sal_list_t *list_temp = NULL; + Cpa16U i, num_dc = 0; + + /* Only need 1 dev with compression enabled - so check all devices */ + status = icp_amgr_getAllAccelDevByCapabilities( + ICP_ACCEL_CAPABILITIES_COMPRESSION, adfInsts, &num_dc); + if ((0 == num_dc) || (CPA_STATUS_SUCCESS != status)) { + QAT_UTILS_LOG( + "No compression devices enabled in the system.\n"); + return dcInst; + } + + for (i = 0; i < num_dc; i++) { + dev_addr = (icp_accel_dev_t *)adfInsts[i]; + if (NULL != dev_addr) { + base_addr = dev_addr->pSalHandle; + if (NULL != base_addr) { + list_temp = base_addr->compression_services; + if (NULL != list_temp) { + dcInst = SalList_getObject(list_temp); + break; + } + } + } + } + return dcInst; +} diff --git a/sys/dev/qat/qat_api/common/ctrl/sal_create_services.c b/sys/dev/qat/qat_api/common/ctrl/sal_create_services.c new file mode 100644 index 000000000000..d51cc1bcace0 --- /dev/null +++ b/sys/dev/qat/qat_api/common/ctrl/sal_create_services.c @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file sal_create_services.c + * + * @defgroup SalCtrl Service Access Layer Controller + * + * @ingroup SalCtrl + * + * @description + * This file contains the main function to create a specific service. + * + *****************************************************************************/ + +#include "cpa.h" +#include "lac_mem.h" +#include "lac_mem_pools.h" +#include "qat_utils.h" +#include "lac_list.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_qat.h" +#include "sal_types_compression.h" +#include "lac_sal_types_crypto.h" + +#include "icp_adf_init.h" + +#include "lac_sal.h" +#include "lac_sal_ctrl.h" + +CpaStatus +SalCtrl_ServiceCreate(sal_service_type_t serviceType, + Cpa32U instance, + sal_service_t **ppInst) +{ + sal_crypto_service_t *pCrypto_service = NULL; + sal_compression_service_t *pCompression_service = NULL; + + switch ((sal_service_type_t)serviceType) { + case SAL_SERVICE_TYPE_CRYPTO_ASYM: + case SAL_SERVICE_TYPE_CRYPTO_SYM: + case SAL_SERVICE_TYPE_CRYPTO: { + pCrypto_service = + malloc(sizeof(sal_crypto_service_t), M_QAT, M_WAITOK); + + /* Zero memory */ + memset(pCrypto_service, 0, sizeof(sal_crypto_service_t)); + + pCrypto_service->generic_service_info.type = + (sal_service_type_t)serviceType; + pCrypto_service->generic_service_info.state = + SAL_SERVICE_STATE_UNINITIALIZED; + pCrypto_service->generic_service_info.instance = instance; + + pCrypto_service->generic_service_info.init = SalCtrl_CryptoInit; + pCrypto_service->generic_service_info.start = + SalCtrl_CryptoStart; + pCrypto_service->generic_service_info.stop = SalCtrl_CryptoStop; + pCrypto_service->generic_service_info.shutdown = + SalCtrl_CryptoShutdown; + + *(ppInst) = &(pCrypto_service->generic_service_info); + + return CPA_STATUS_SUCCESS; + } + case SAL_SERVICE_TYPE_COMPRESSION: { + pCompression_service = + malloc(sizeof(sal_compression_service_t), M_QAT, M_WAITOK); + + /* Zero memory */ + memset(pCompression_service, + 0, + sizeof(sal_compression_service_t)); + + pCompression_service->generic_service_info.type = + (sal_service_type_t)serviceType; + pCompression_service->generic_service_info.state = + SAL_SERVICE_STATE_UNINITIALIZED; + pCompression_service->generic_service_info.instance = instance; + + pCompression_service->generic_service_info.init = + SalCtrl_CompressionInit; + pCompression_service->generic_service_info.start = + SalCtrl_CompressionStart; + pCompression_service->generic_service_info.stop = + SalCtrl_CompressionStop; + pCompression_service->generic_service_info.shutdown = + SalCtrl_CompressionShutdown; + + *(ppInst) = &(pCompression_service->generic_service_info); + return CPA_STATUS_SUCCESS; + } + + default: { + QAT_UTILS_LOG("Not a valid service type\n"); + (*ppInst) = NULL; + return CPA_STATUS_FAIL; + } + } +} diff --git a/sys/dev/qat/qat_api/common/ctrl/sal_crypto.c b/sys/dev/qat/qat_api/common/ctrl/sal_crypto.c new file mode 100644 index 000000000000..c97d36103c2b --- /dev/null +++ b/sys/dev/qat/qat_api/common/ctrl/sal_crypto.c @@ -0,0 +1,1837 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file sal_crypto.c Instance handling functions for crypto + * + * @ingroup SalCtrl + * + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ + +/* QAT-API includes */ +#include "cpa.h" +#include "cpa_types.h" +#include "cpa_cy_common.h" +#include "cpa_cy_im.h" +#include "cpa_cy_key.h" +#include "cpa_cy_sym.h" + +#include "qat_utils.h" + +/* ADF includes */ +#include "icp_adf_init.h" +#include "icp_adf_transport.h" +#include "icp_accel_devices.h" +#include "icp_adf_cfg.h" +#include "icp_adf_accel_mgr.h" +#include "icp_adf_poll.h" +#include "icp_adf_debug.h" + +/* SAL includes */ +#include "lac_log.h" +#include "lac_mem.h" +#include "lac_mem_pools.h" +#include "sal_statistics.h" +#include "lac_common.h" +#include "lac_list.h" +#include "lac_hooks.h" +#include "lac_sym_qat_hash_defs_lookup.h" +#include "lac_sym.h" +#include "lac_sym_key.h" +#include "lac_sym_hash.h" +#include "lac_sym_cb.h" +#include "lac_sym_stats.h" +#include "lac_sal_types_crypto.h" +#include "lac_sal.h" +#include "lac_sal_ctrl.h" +#include "sal_string_parse.h" +#include "sal_service_state.h" +#include "icp_sal_poll.h" +#include "lac_sync.h" +#include "lac_sym_qat.h" +#include "icp_sal_versions.h" +#include "icp_sal_user.h" + +#define TH_CY_RX_0 0 +#define TH_CY_RX_1 1 +#define MAX_CY_RX_RINGS 2 + +#define DOUBLE_INCR 2 + +#define TH_SINGLE_RX 0 +#define NUM_CRYPTO_SYM_RX_RINGS 1 +#define NUM_CRYPTO_ASYM_RX_RINGS 1 +#define NUM_CRYPTO_NRBG_RX_RINGS 1 + +static CpaInstanceHandle +Lac_CryptoGetFirstHandle(void) +{ + CpaInstanceHandle instHandle; + instHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO); + if (!instHandle) { + instHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + if (!instHandle) { + instHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM); + } + } + return instHandle; +} + + +/* Function to release the sym handles. */ +static CpaStatus +SalCtrl_SymReleaseTransHandle(sal_service_t *service) +{ + + CpaStatus status = CPA_STATUS_SUCCESS; + CpaStatus ret_status = CPA_STATUS_SUCCESS; + sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; + + if (NULL != pCryptoService->trans_handle_sym_tx) { + status = icp_adf_transReleaseHandle( + pCryptoService->trans_handle_sym_tx); + if (CPA_STATUS_SUCCESS != status) { + ret_status = status; + } + } + if (NULL != pCryptoService->trans_handle_sym_rx) { + status = icp_adf_transReleaseHandle( + pCryptoService->trans_handle_sym_rx); + if (CPA_STATUS_SUCCESS != status) { + ret_status = status; + } + } + + return ret_status; +} + + +/* + * @ingroup sal_crypto + * Frees resources (memory and transhandles) if allocated + * + * @param[in] pCryptoService Pointer to sym service instance + * @retval SUCCESS if transhandles released + * successfully. +*/ +static CpaStatus +SalCtrl_SymFreeResources(sal_crypto_service_t *pCryptoService) +{ + + CpaStatus status = CPA_STATUS_SUCCESS; + + /* Free memory pools if not NULL */ + Lac_MemPoolDestroy(pCryptoService->lac_sym_cookie_pool); + + /* Free misc memory if allocated */ + /* Frees memory allocated for Hmac precomputes */ + LacSymHash_HmacPrecompShutdown(pCryptoService); + /* Free memory allocated for key labels + Also clears key stats */ + LacSymKey_Shutdown(pCryptoService); + /* Free hash lookup table if allocated */ + if (NULL != pCryptoService->pLacHashLookupDefs) { + LAC_OS_FREE(pCryptoService->pLacHashLookupDefs); + } + + /* Free statistics */ + LacSym_StatsFree(pCryptoService); + + /* Free transport handles */ + status = SalCtrl_SymReleaseTransHandle((sal_service_t *)pCryptoService); + return status; +} + + +/** + *********************************************************************** + * @ingroup SalCtrl + * This macro verifies that the status is _SUCCESS + * If status is not _SUCCESS then Sym Instance resources are + * freed before the function returns the error + * + * @param[in] status status we are checking + * + * @return void status is ok (CPA_STATUS_SUCCESS) + * @return status The value in the status parameter is an error one + * + ****************************************************************************/ +#define LAC_CHECK_STATUS_SYM_INIT(status) \ + do { \ + if (CPA_STATUS_SUCCESS != status) { \ + SalCtrl_SymFreeResources(pCryptoService); \ + return status; \ + } \ + } while (0) + + +/* Function that creates the Sym Handles. */ +static CpaStatus +SalCtrl_SymCreateTransHandle(icp_accel_dev_t *device, + sal_service_t *service, + Cpa32U numSymRequests, + char *section) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; + icp_resp_deliv_method rx_resp_type = ICP_RESP_TYPE_IRQ; + Cpa32U msgSize = 0; + + if (SAL_RESP_POLL_CFG_FILE == pCryptoService->isPolled) { + rx_resp_type = ICP_RESP_TYPE_POLL; + } + + if (CPA_FALSE == pCryptoService->generic_service_info.is_dyn) { + section = icpGetProcessName(); + } + + /* Parse Sym ring details */ + status = + Sal_StringParsing("Cy", + pCryptoService->generic_service_info.instance, + "RingSymTx", + temp_string); + + /* Need to free resources in case not _SUCCESS from here */ + LAC_CHECK_STATUS_SYM_INIT(status); + + msgSize = LAC_QAT_SYM_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES; + status = + icp_adf_transCreateHandle(device, + ICP_TRANS_TYPE_ETR, + section, + pCryptoService->acceleratorNum, + pCryptoService->bankNum, + temp_string, + lac_getRingType(SAL_RING_TYPE_A_SYM_HI), + NULL, + ICP_RESP_TYPE_NONE, + numSymRequests, + msgSize, + (icp_comms_trans_handle *)&( + pCryptoService->trans_handle_sym_tx)); + LAC_CHECK_STATUS_SYM_INIT(status); + + status = + Sal_StringParsing("Cy", + pCryptoService->generic_service_info.instance, + "RingSymRx", + temp_string); + LAC_CHECK_STATUS_SYM_INIT(status); + + msgSize = LAC_QAT_SYM_RESP_SZ_LW * LAC_LONG_WORD_IN_BYTES; + status = icp_adf_transCreateHandle( + device, + ICP_TRANS_TYPE_ETR, + section, + pCryptoService->acceleratorNum, + pCryptoService->bankNum, + temp_string, + lac_getRingType(SAL_RING_TYPE_NONE), + (icp_trans_callback)LacSymQat_SymRespHandler, + rx_resp_type, + numSymRequests, + msgSize, + (icp_comms_trans_handle *)&(pCryptoService->trans_handle_sym_rx)); + LAC_CHECK_STATUS_SYM_INIT(status); + + return status; +} + +static int +SalCtrl_CryptoDebug(void *private_data, char *data, int size, int offset) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + Cpa32U len = 0; + sal_crypto_service_t *pCryptoService = + (sal_crypto_service_t *)private_data; + + switch (offset) { + case SAL_STATS_SYM: { + CpaCySymStats64 symStats = { 0 }; + if (CPA_TRUE != + pCryptoService->generic_service_info.stats + ->bSymStatsEnabled) { + break; + } + status = cpaCySymQueryStats64(pCryptoService, &symStats); + if (status != CPA_STATUS_SUCCESS) { + LAC_LOG_ERROR("cpaCySymQueryStats64 returned error\n"); + return 0; + } + + /* Engine Info */ + len += snprintf( + data + len, + size - len, + SEPARATOR BORDER + " Statistics for Instance %24s |\n" BORDER + " Symmetric Stats " BORDER + "\n" SEPARATOR, + pCryptoService->debug_file->name); + + /* Session Info */ + len += snprintf( + data + len, + size - len, + BORDER " Sessions Initialized: %16llu " BORDER + "\n" BORDER + " Sessions Removed: %16llu " BORDER + "\n" BORDER + " Session Errors: %16llu " BORDER + "\n" SEPARATOR, + (long long unsigned int)symStats.numSessionsInitialized, + (long long unsigned int)symStats.numSessionsRemoved, + (long long unsigned int)symStats.numSessionErrors); + + /* Session info */ + len += snprintf( + data + len, + size - len, + BORDER " Symmetric Requests: %16llu " BORDER + "\n" BORDER + " Symmetric Request Errors: %16llu " BORDER + "\n" BORDER + " Symmetric Completed: %16llu " BORDER + "\n" BORDER + " Symmetric Completed Errors: %16llu " BORDER + "\n" BORDER + " Symmetric Verify Failures: %16llu " BORDER + "\n", + (long long unsigned int)symStats.numSymOpRequests, + (long long unsigned int)symStats.numSymOpRequestErrors, + (long long unsigned int)symStats.numSymOpCompleted, + (long long unsigned int)symStats.numSymOpCompletedErrors, + (long long unsigned int)symStats.numSymOpVerifyFailures); + break; + } + default: { + len += snprintf(data + len, size - len, SEPARATOR); + return 0; + } + } + return ++offset; +} + + +static CpaStatus +SalCtrl_SymInit(icp_accel_dev_t *device, sal_service_t *service) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + Cpa32U numSymConcurrentReq = 0; + char adfGetParam[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; + char *section = DYN_SEC; + + /*Instance may not in the DYN section*/ + if (CPA_FALSE == pCryptoService->generic_service_info.is_dyn) { + section = icpGetProcessName(); + } + + + /* Register callbacks for the symmetric services + * (Hash, Cipher, Algorithm-Chaining) (returns void)*/ + LacSymCb_CallbacksRegister(); + + /* Get num concurrent requests from config file */ + status = + Sal_StringParsing("Cy", + pCryptoService->generic_service_info.instance, + "NumConcurrentSymRequests", + temp_string); + LAC_CHECK_STATUS(status); + status = + icp_adf_cfgGetParamValue(device, section, temp_string, adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration file\n", + temp_string); + return status; + } + + numSymConcurrentReq = + (Cpa32U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); + if (CPA_STATUS_FAIL == validateConcurrRequest(numSymConcurrentReq)) { + LAC_LOG_ERROR("Invalid NumConcurrentSymRequests, valid " + "values {64, 128, 256, ... 32768, 65536}"); + return CPA_STATUS_FAIL; + } + + /* ADF does not allow us to completely fill the ring for batch requests + */ + pCryptoService->maxNumSymReqBatch = + (numSymConcurrentReq - SAL_BATCH_SUBMIT_FREE_SPACE); + + /* Create transport handles */ + status = SalCtrl_SymCreateTransHandle(device, + service, + numSymConcurrentReq, + section); + LAC_CHECK_STATUS(status); + + /* Allocates memory pools */ + + /* Create and initialise symmetric cookie memory pool */ + pCryptoService->lac_sym_cookie_pool = LAC_MEM_POOL_INIT_POOL_ID; + status = + Sal_StringParsing("Cy", + pCryptoService->generic_service_info.instance, + "SymPool", + temp_string); + LAC_CHECK_STATUS_SYM_INIT(status); + /* Note we need twice (i.e. <<1) the number of sym cookies to + support sym ring pairs (and some, for partials) */ + status = + Lac_MemPoolCreate(&pCryptoService->lac_sym_cookie_pool, + temp_string, + ((numSymConcurrentReq + numSymConcurrentReq + 1) + << 1), + sizeof(lac_sym_cookie_t), + LAC_64BYTE_ALIGNMENT, + CPA_FALSE, + pCryptoService->nodeAffinity); + LAC_CHECK_STATUS_SYM_INIT(status); + /* For all sym cookies fill out the physical address of data that + will be set to QAT */ + Lac_MemPoolInitSymCookiesPhyAddr(pCryptoService->lac_sym_cookie_pool); + + /* Clear stats */ + /* Clears Key stats and allocate memory of SSL and TLS labels + These labels are initialised to standard values */ + status = LacSymKey_Init(pCryptoService); + LAC_CHECK_STATUS_SYM_INIT(status); + + /* Initialises the hash lookup table*/ + status = LacSymQat_Init(pCryptoService); + LAC_CHECK_STATUS_SYM_INIT(status); + + /* Fills out content descriptor for precomputes and registers the + hash precompute callback */ + status = LacSymHash_HmacPrecompInit(pCryptoService); + LAC_CHECK_STATUS_SYM_INIT(status); + + /* Init the Sym stats */ + status = LacSym_StatsInit(pCryptoService); + LAC_CHECK_STATUS_SYM_INIT(status); + + return status; +} + +static void +SalCtrl_DebugShutdown(icp_accel_dev_t *device, sal_service_t *service) +{ + sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; + sal_statistics_collection_t *pStatsCollection = + (sal_statistics_collection_t *)device->pQatStats; + + if (CPA_TRUE == pStatsCollection->bStatsEnabled) { + /* Clean stats */ + if (NULL != pCryptoService->debug_file) { + icp_adf_debugRemoveFile(pCryptoService->debug_file); + LAC_OS_FREE(pCryptoService->debug_file->name); + LAC_OS_FREE(pCryptoService->debug_file); + pCryptoService->debug_file = NULL; + } + } + pCryptoService->generic_service_info.stats = NULL; +} + +static CpaStatus +SalCtrl_DebugInit(icp_accel_dev_t *device, sal_service_t *service) +{ + char adfGetParam[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + char *instance_name = NULL; + sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; + sal_statistics_collection_t *pStatsCollection = + (sal_statistics_collection_t *)device->pQatStats; + CpaStatus status = CPA_STATUS_SUCCESS; + char *section = DYN_SEC; + + /*Instance may not in the DYN section*/ + if (CPA_FALSE == pCryptoService->generic_service_info.is_dyn) { + section = icpGetProcessName(); + } + + if (CPA_TRUE == pStatsCollection->bStatsEnabled) { + /* Get instance name for stats */ + instance_name = LAC_OS_MALLOC(ADF_CFG_MAX_VAL_LEN_IN_BYTES); + if (NULL == instance_name) { + return CPA_STATUS_RESOURCE; + } + + status = Sal_StringParsing( + "Cy", + pCryptoService->generic_service_info.instance, + "Name", + temp_string); + if (CPA_STATUS_SUCCESS != status) { + LAC_OS_FREE(instance_name); + return status; + } + status = icp_adf_cfgGetParamValue(device, + section, + temp_string, + adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG( + "Failed to get %s from configuration file\n", + temp_string); + LAC_OS_FREE(instance_name); + return status; + } + snprintf(instance_name, + ADF_CFG_MAX_VAL_LEN_IN_BYTES, + "%s", + adfGetParam); + + pCryptoService->debug_file = + LAC_OS_MALLOC(sizeof(debug_file_info_t)); + if (NULL == pCryptoService->debug_file) { + LAC_OS_FREE(instance_name); + return CPA_STATUS_RESOURCE; + } + + memset(pCryptoService->debug_file, + 0, + sizeof(debug_file_info_t)); + pCryptoService->debug_file->name = instance_name; + pCryptoService->debug_file->seq_read = SalCtrl_CryptoDebug; + pCryptoService->debug_file->private_data = pCryptoService; + pCryptoService->debug_file->parent = + pCryptoService->generic_service_info.debug_parent_dir; + + status = + icp_adf_debugAddFile(device, pCryptoService->debug_file); + if (CPA_STATUS_SUCCESS != status) { + LAC_OS_FREE(instance_name); + LAC_OS_FREE(pCryptoService->debug_file); + return status; + } + } + pCryptoService->generic_service_info.stats = pStatsCollection; + + return status; +} + +static CpaStatus +SalCtr_InstInit(icp_accel_dev_t *device, sal_service_t *service) +{ + char adfGetParam[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + char temp_string2[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; + CpaStatus status = CPA_STATUS_SUCCESS; + char *section = DYN_SEC; + + /*Instance may not in the DYN section*/ + if (CPA_FALSE == pCryptoService->generic_service_info.is_dyn) { + section = icpGetProcessName(); + } + + + /* Get Config Info: Accel Num, bank Num, packageID, + coreAffinity, nodeAffinity and response mode */ + + pCryptoService->acceleratorNum = 0; + + status = + Sal_StringParsing("Cy", + pCryptoService->generic_service_info.instance, + "BankNumber", + temp_string); + LAC_CHECK_STATUS(status); + status = + icp_adf_cfgGetParamValue(device, section, temp_string, adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration file\n", + temp_string); + return status; + } + pCryptoService->bankNum = + (Cpa16U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); + + status = + Sal_StringParsing("Cy", + pCryptoService->generic_service_info.instance, + "IsPolled", + temp_string); + LAC_CHECK_STATUS(status); + status = + icp_adf_cfgGetParamValue(device, section, temp_string, adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration file\n", + temp_string); + return status; + } + pCryptoService->isPolled = + (Cpa8U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); + + /* Kernel instances do not support epoll mode */ + if (SAL_RESP_EPOLL_CFG_FILE == pCryptoService->isPolled) { + QAT_UTILS_LOG( + "IsPolled %u is not supported for kernel instance %s", + pCryptoService->isPolled, + temp_string); + return CPA_STATUS_FAIL; + } + + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + ADF_DEV_PKG_ID, + adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration file\n", + ADF_DEV_PKG_ID); + return status; + } + pCryptoService->pkgID = + (Cpa16U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); + + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + ADF_DEV_NODE_ID, + adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration file\n", + ADF_DEV_NODE_ID); + return status; + } + pCryptoService->nodeAffinity = + (Cpa32U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); + /* In case of interrupt instance, use the bank affinity set by adf_ctl + * Otherwise, use the instance affinity for backwards compatibility */ + if (SAL_RESP_POLL_CFG_FILE != pCryptoService->isPolled) { + /* Next need to read the [AcceleratorX] section of the config + * file */ + status = Sal_StringParsing("Accelerator", + pCryptoService->acceleratorNum, + "", + temp_string2); + LAC_CHECK_STATUS(status); + status = Sal_StringParsing("Bank", + pCryptoService->bankNum, + "CoreAffinity", + temp_string); + LAC_CHECK_STATUS(status); + } else { + strncpy(temp_string2, section, (strlen(section) + 1)); + status = Sal_StringParsing( + "Cy", + pCryptoService->generic_service_info.instance, + "CoreAffinity", + temp_string); + LAC_CHECK_STATUS(status); + } + + status = icp_adf_cfgGetParamValue(device, + temp_string2, + temp_string, + adfGetParam); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration file\n", + temp_string); + return status; + } + pCryptoService->coreAffinity = + (Cpa32U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC); + + /*No Execution Engine in DH895xcc, so make sure it is zero*/ + pCryptoService->executionEngine = 0; + + return status; +} + +/* This function: + * 1. Creates sym and asym transport handles + * 2. Allocates memory pools required by sym and asym services +.* 3. Clears the sym and asym stats counters + * 4. In case service asym or sym is enabled then this function + * only allocates resources for these services. i.e if the + * service asym is enabled then only asym transport handles + * are created and vice versa. + */ +CpaStatus +SalCtrl_CryptoInit(icp_accel_dev_t *device, sal_service_t *service) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; + sal_service_type_t svc_type = service->type; + + SAL_SERVICE_GOOD_FOR_INIT(pCryptoService); + pCryptoService->generic_service_info.state = + SAL_SERVICE_STATE_INITIALIZING; + + /* Set up the instance parameters such as bank number, + * coreAffinity, pkgId and node affinity etc + */ + status = SalCtr_InstInit(device, service); + LAC_CHECK_STATUS(status); + /* Create debug directory for service */ + status = SalCtrl_DebugInit(device, service); + LAC_CHECK_STATUS(status); + + switch (svc_type) { + case SAL_SERVICE_TYPE_CRYPTO_ASYM: + break; + case SAL_SERVICE_TYPE_CRYPTO_SYM: + status = SalCtrl_SymInit(device, service); + if (CPA_STATUS_SUCCESS != status) { + SalCtrl_DebugShutdown(device, service); + return status; + } + break; + case SAL_SERVICE_TYPE_CRYPTO: + status = SalCtrl_SymInit(device, service); + if (CPA_STATUS_SUCCESS != status) { + SalCtrl_DebugShutdown(device, service); + return status; + } + break; + default: + LAC_LOG_ERROR("Invalid service type\n"); + status = CPA_STATUS_FAIL; + break; + } + + pCryptoService->generic_service_info.state = + SAL_SERVICE_STATE_INITIALIZED; + + return status; +} + +CpaStatus +SalCtrl_CryptoStart(icp_accel_dev_t *device, sal_service_t *service) +{ + sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; + CpaStatus status = CPA_STATUS_SUCCESS; + + if (pCryptoService->generic_service_info.state != + SAL_SERVICE_STATE_INITIALIZED) { + LAC_LOG_ERROR("Not in the correct state to call start\n"); + return CPA_STATUS_FAIL; + } + + pCryptoService->generic_service_info.state = SAL_SERVICE_STATE_RUNNING; + return status; +} + +CpaStatus +SalCtrl_CryptoStop(icp_accel_dev_t *device, sal_service_t *service) +{ + sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; + + if (SAL_SERVICE_STATE_RUNNING != + pCryptoService->generic_service_info.state) { + LAC_LOG_ERROR("Not in the correct state to call stop"); + } + + pCryptoService->generic_service_info.state = + SAL_SERVICE_STATE_SHUTTING_DOWN; + return CPA_STATUS_SUCCESS; +} + +CpaStatus +SalCtrl_CryptoShutdown(icp_accel_dev_t *device, sal_service_t *service) +{ + sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service; + CpaStatus status = CPA_STATUS_SUCCESS; + sal_service_type_t svc_type = service->type; + + if ((SAL_SERVICE_STATE_INITIALIZED != + pCryptoService->generic_service_info.state) && + (SAL_SERVICE_STATE_SHUTTING_DOWN != + pCryptoService->generic_service_info.state)) { + LAC_LOG_ERROR("Not in the correct state to call shutdown \n"); + return CPA_STATUS_FAIL; + } + + + /* Free memory and transhandles */ + switch (svc_type) { + case SAL_SERVICE_TYPE_CRYPTO_ASYM: + break; + case SAL_SERVICE_TYPE_CRYPTO_SYM: + if (SalCtrl_SymFreeResources(pCryptoService)) { + status = CPA_STATUS_FAIL; + } + break; + case SAL_SERVICE_TYPE_CRYPTO: + if (SalCtrl_SymFreeResources(pCryptoService)) { + status = CPA_STATUS_FAIL; + } + break; + default: + LAC_LOG_ERROR("Invalid service type\n"); + status = CPA_STATUS_FAIL; + break; + } + + SalCtrl_DebugShutdown(device, service); + + pCryptoService->generic_service_info.state = SAL_SERVICE_STATE_SHUTDOWN; + + return status; +} + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + *****************************************************************************/ +CpaStatus +cpaCyGetStatusText(const CpaInstanceHandle instanceHandle, + CpaStatus errStatus, + Cpa8S *pStatusText) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + + LAC_CHECK_NULL_PARAM(pStatusText); + + switch (errStatus) { + case CPA_STATUS_SUCCESS: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_SUCCESS); + break; + case CPA_STATUS_FAIL: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_FAIL); + break; + case CPA_STATUS_RETRY: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_RETRY); + break; + case CPA_STATUS_RESOURCE: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_RESOURCE); + break; + case CPA_STATUS_INVALID_PARAM: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_INVALID_PARAM); + break; + case CPA_STATUS_FATAL: + LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_FATAL); + break; + default: + status = CPA_STATUS_INVALID_PARAM; + break; + } + return status; +} + +void +SalCtrl_CyQueryCapabilities(sal_service_t *pGenericService, + CpaCyCapabilitiesInfo *pCapInfo) +{ + memset(pCapInfo, 0, sizeof(CpaCyCapabilitiesInfo)); + + if (SAL_SERVICE_TYPE_CRYPTO == pGenericService->type || + SAL_SERVICE_TYPE_CRYPTO_SYM == pGenericService->type) { + pCapInfo->symSupported = CPA_TRUE; + if (pGenericService->capabilitiesMask & + ICP_ACCEL_CAPABILITIES_EXT_ALGCHAIN) { + pCapInfo->extAlgchainSupported = CPA_TRUE; + } + + if (pGenericService->capabilitiesMask & + ICP_ACCEL_CAPABILITIES_HKDF) { + pCapInfo->hkdfSupported = CPA_TRUE; + } + } + + if (pGenericService->capabilitiesMask & + ICP_ACCEL_CAPABILITIES_ECEDMONT) { + pCapInfo->ecEdMontSupported = CPA_TRUE; + } + + if (pGenericService->capabilitiesMask & + ICP_ACCEL_CAPABILITIES_RANDOM_NUMBER) { + pCapInfo->nrbgSupported = CPA_TRUE; + } + + pCapInfo->drbgSupported = CPA_FALSE; + pCapInfo->randSupported = CPA_FALSE; + pCapInfo->nrbgSupported = CPA_FALSE; +} + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + *****************************************************************************/ +CpaStatus +cpaCyStartInstance(CpaInstanceHandle instanceHandle_in) +{ + CpaInstanceHandle instanceHandle = NULL; +/* Structure initializer is supported by C99, but it is + * not supported by some former Intel compilers. + */ + CpaInstanceInfo2 info = { 0 }; + icp_accel_dev_t *dev = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + sal_crypto_service_t *pService = NULL; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO); + if (!instanceHandle) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } + } else { + instanceHandle = instanceHandle_in; + } + LAC_CHECK_NULL_PARAM(instanceHandle); + + pService = (sal_crypto_service_t *)instanceHandle; + + status = cpaCyInstanceGetInfo2(instanceHandle, &info); + if (CPA_STATUS_SUCCESS != status) { + LAC_LOG_ERROR("Can not get instance info\n"); + return status; + } + dev = icp_adf_getAccelDevByAccelId(info.physInstId.packageId); + if (NULL == dev) { + LAC_LOG_ERROR("Can not find device for the instance\n"); + return CPA_STATUS_FAIL; + } + + pService->generic_service_info.isInstanceStarted = CPA_TRUE; + + /* Increment dev ref counter */ + icp_qa_dev_get(dev); + return CPA_STATUS_SUCCESS; +} + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + *****************************************************************************/ +CpaStatus +cpaCyStopInstance(CpaInstanceHandle instanceHandle_in) +{ + CpaInstanceHandle instanceHandle = NULL; +/* Structure initializer is supported by C99, but it is + * not supported by some former Intel compilers. + */ + CpaInstanceInfo2 info = { 0 }; + icp_accel_dev_t *dev = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + sal_crypto_service_t *pService = NULL; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = Lac_CryptoGetFirstHandle(); + } else { + instanceHandle = instanceHandle_in; + } + LAC_CHECK_NULL_PARAM(instanceHandle); + + status = cpaCyInstanceGetInfo2(instanceHandle, &info); + if (CPA_STATUS_SUCCESS != status) { + LAC_LOG_ERROR("Can not get instance info\n"); + return status; + } + dev = icp_adf_getAccelDevByAccelId(info.physInstId.packageId); + if (NULL == dev) { + LAC_LOG_ERROR("Can not find device for the instance\n"); + return CPA_STATUS_FAIL; + } + + pService = (sal_crypto_service_t *)instanceHandle; + + pService->generic_service_info.isInstanceStarted = CPA_FALSE; + + /* Decrement dev ref counter */ + icp_qa_dev_put(dev); + return CPA_STATUS_SUCCESS; +} + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + *****************************************************************************/ +CpaStatus +cpaCyInstanceSetNotificationCb( + const CpaInstanceHandle instanceHandle, + const CpaCyInstanceNotificationCbFunc pInstanceNotificationCb, + void *pCallbackTag) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_service_t *gen_handle = instanceHandle; + + + LAC_CHECK_NULL_PARAM(gen_handle); + gen_handle->notification_cb = pInstanceNotificationCb; + gen_handle->cb_tag = pCallbackTag; + return status; +} + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + *****************************************************************************/ +CpaStatus +cpaCyGetNumInstances(Cpa16U *pNumInstances) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + CpaInstanceHandle cyInstanceHandle; + CpaInstanceInfo2 info; + icp_accel_dev_t **pAdfInsts = NULL; + icp_accel_dev_t *dev_addr = NULL; + sal_t *base_addr = NULL; + sal_list_t *list_temp = NULL; + Cpa16U num_accel_dev = 0; + Cpa16U num_inst = 0; + Cpa16U i = 0; + + LAC_CHECK_NULL_PARAM(pNumInstances); + + /* Get the number of accel_dev in the system */ + status = icp_amgr_getNumInstances(&num_accel_dev); + LAC_CHECK_STATUS(status); + + /* Allocate memory to store addr of accel_devs */ + pAdfInsts = + malloc(num_accel_dev * sizeof(icp_accel_dev_t *), M_QAT, M_WAITOK); + num_accel_dev = 0; + /* Get ADF to return all accel_devs that support either + * symmetric or asymmetric crypto */ + status = icp_amgr_getAllAccelDevByCapabilities( + (ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC | + ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC), + pAdfInsts, + &num_accel_dev); + if (CPA_STATUS_SUCCESS != status) { + LAC_LOG_ERROR("No support for crypto\n"); + *pNumInstances = 0; + free(pAdfInsts, M_QAT); + return status; + } + + for (i = 0; i < num_accel_dev; i++) { + dev_addr = (icp_accel_dev_t *)pAdfInsts[i]; + if (NULL == dev_addr || NULL == dev_addr->pSalHandle) { + continue; + } + + base_addr = dev_addr->pSalHandle; + list_temp = base_addr->crypto_services; + while (NULL != list_temp) { + cyInstanceHandle = SalList_getObject(list_temp); + status = cpaCyInstanceGetInfo2(cyInstanceHandle, &info); + if (CPA_STATUS_SUCCESS == status && + CPA_TRUE == info.isPolled) { + num_inst++; + } + list_temp = SalList_next(list_temp); + } + list_temp = base_addr->asym_services; + while (NULL != list_temp) { + cyInstanceHandle = SalList_getObject(list_temp); + status = cpaCyInstanceGetInfo2(cyInstanceHandle, &info); + if (CPA_STATUS_SUCCESS == status && + CPA_TRUE == info.isPolled) { + num_inst++; + } + list_temp = SalList_next(list_temp); + } + list_temp = base_addr->sym_services; + while (NULL != list_temp) { + cyInstanceHandle = SalList_getObject(list_temp); + status = cpaCyInstanceGetInfo2(cyInstanceHandle, &info); + if (CPA_STATUS_SUCCESS == status && + CPA_TRUE == info.isPolled) { + num_inst++; + } + list_temp = SalList_next(list_temp); + } + } + *pNumInstances = num_inst; + free(pAdfInsts, M_QAT); + + + return status; +} + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + *****************************************************************************/ +CpaStatus +cpaCyGetInstances(Cpa16U numInstances, CpaInstanceHandle *pCyInstances) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + CpaInstanceHandle cyInstanceHandle; + CpaInstanceInfo2 info; + icp_accel_dev_t **pAdfInsts = NULL; + icp_accel_dev_t *dev_addr = NULL; + sal_t *base_addr = NULL; + sal_list_t *list_temp = NULL; + Cpa16U num_accel_dev = 0; + Cpa16U num_allocated_instances = 0; + Cpa16U index = 0; + Cpa16U i = 0; + + + LAC_CHECK_NULL_PARAM(pCyInstances); + if (0 == numInstances) { + LAC_INVALID_PARAM_LOG("NumInstances is 0"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Get the number of crypto instances */ + status = cpaCyGetNumInstances(&num_allocated_instances); + if (CPA_STATUS_SUCCESS != status) { + return status; + } + + if (numInstances > num_allocated_instances) { + QAT_UTILS_LOG("Only %d crypto instances available\n", + num_allocated_instances); + return CPA_STATUS_RESOURCE; + } + + /* Get the number of accel devices in the system */ + status = icp_amgr_getNumInstances(&num_accel_dev); + LAC_CHECK_STATUS(status); + + /* Allocate memory to store addr of accel_devs */ + pAdfInsts = + malloc(num_accel_dev * sizeof(icp_accel_dev_t *), M_QAT, M_WAITOK); + + num_accel_dev = 0; + /* Get ADF to return all accel_devs that support either + * symmetric or asymmetric crypto */ + status = icp_amgr_getAllAccelDevByCapabilities( + (ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC | + ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC), + pAdfInsts, + &num_accel_dev); + if (CPA_STATUS_SUCCESS != status) { + LAC_LOG_ERROR("No support for crypto\n"); + free(pAdfInsts, M_QAT); + return status; + } + + for (i = 0; i < num_accel_dev; i++) { + dev_addr = (icp_accel_dev_t *)pAdfInsts[i]; + /* Note dev_addr cannot be NULL here as numInstances = 0 + * is not valid and if dev_addr = NULL then index = 0 (which + * is less than numInstances and status is set to _RESOURCE + * above + */ + base_addr = dev_addr->pSalHandle; + if (NULL == base_addr) { + continue; + } + list_temp = base_addr->crypto_services; + while (NULL != list_temp) { + if (index > (numInstances - 1)) { + break; + } + cyInstanceHandle = SalList_getObject(list_temp); + status = cpaCyInstanceGetInfo2(cyInstanceHandle, &info); + list_temp = SalList_next(list_temp); + if (CPA_STATUS_SUCCESS != status || + CPA_TRUE != info.isPolled) { + continue; + } + pCyInstances[index] = cyInstanceHandle; + index++; + } + list_temp = base_addr->asym_services; + while (NULL != list_temp) { + if (index > (numInstances - 1)) { + break; + } + cyInstanceHandle = SalList_getObject(list_temp); + status = cpaCyInstanceGetInfo2(cyInstanceHandle, &info); + list_temp = SalList_next(list_temp); + if (CPA_STATUS_SUCCESS != status || + CPA_TRUE != info.isPolled) { + continue; + } + pCyInstances[index] = cyInstanceHandle; + index++; + } + list_temp = base_addr->sym_services; + while (NULL != list_temp) { + if (index > (numInstances - 1)) { + break; + } + cyInstanceHandle = SalList_getObject(list_temp); + status = cpaCyInstanceGetInfo2(cyInstanceHandle, &info); + list_temp = SalList_next(list_temp); + if (CPA_STATUS_SUCCESS != status || + CPA_TRUE != info.isPolled) { + continue; + } + pCyInstances[index] = cyInstanceHandle; + index++; + } + } + free(pAdfInsts, M_QAT); + + return status; +} + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + *****************************************************************************/ +CpaStatus +cpaCyInstanceGetInfo(const CpaInstanceHandle instanceHandle_in, + struct _CpaInstanceInfo *pInstanceInfo) +{ + CpaInstanceHandle instanceHandle = NULL; + sal_crypto_service_t *pCryptoService = NULL; + sal_service_t *pGenericService = NULL; + + Cpa8U name[CPA_INST_NAME_SIZE] = + "Intel(R) DH89XXCC instance number: %02x, type: Crypto"; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = Lac_CryptoGetFirstHandle(); + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_NULL_PARAM(instanceHandle); + LAC_CHECK_NULL_PARAM(pInstanceInfo); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_ASYM | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + + pCryptoService = (sal_crypto_service_t *)instanceHandle; + + pInstanceInfo->type = CPA_INSTANCE_TYPE_CRYPTO; + + /* According to cpa.h instance state is initialized and ready for use + * or shutdown. Therefore need to map our running state to initialised + * or shutdown */ + if (SAL_SERVICE_STATE_RUNNING == + pCryptoService->generic_service_info.state) { + pInstanceInfo->state = CPA_INSTANCE_STATE_INITIALISED; + } else { + pInstanceInfo->state = CPA_INSTANCE_STATE_SHUTDOWN; + } + + pGenericService = (sal_service_t *)instanceHandle; + snprintf((char *)pInstanceInfo->name, + CPA_INST_NAME_SIZE, + (char *)name, + pGenericService->instance); + + pInstanceInfo->name[CPA_INST_NAME_SIZE - 1] = '\0'; + + snprintf((char *)pInstanceInfo->version, + CPA_INSTANCE_MAX_NAME_SIZE_IN_BYTES, + "%d.%d", + CPA_CY_API_VERSION_NUM_MAJOR, + CPA_CY_API_VERSION_NUM_MINOR); + + pInstanceInfo->version[CPA_INSTANCE_MAX_VERSION_SIZE_IN_BYTES - 1] = + '\0'; + return CPA_STATUS_SUCCESS; +} + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + *****************************************************************************/ +CpaStatus +cpaCyInstanceGetInfo2(const CpaInstanceHandle instanceHandle_in, + CpaInstanceInfo2 *pInstanceInfo2) +{ + CpaInstanceHandle instanceHandle = NULL; + sal_crypto_service_t *pCryptoService = NULL; + icp_accel_dev_t *dev = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + char keyStr[ADF_CFG_MAX_KEY_LEN_IN_BYTES] = { 0 }; + char valStr[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + char *section = DYN_SEC; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = Lac_CryptoGetFirstHandle(); + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_NULL_PARAM(instanceHandle); + LAC_CHECK_NULL_PARAM(pInstanceInfo2); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_ASYM | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + + LAC_OS_BZERO(pInstanceInfo2, sizeof(CpaInstanceInfo2)); + pInstanceInfo2->accelerationServiceType = CPA_ACC_SVC_TYPE_CRYPTO; + snprintf((char *)pInstanceInfo2->vendorName, + CPA_INST_VENDOR_NAME_SIZE, + "%s", + SAL_INFO2_VENDOR_NAME); + pInstanceInfo2->vendorName[CPA_INST_VENDOR_NAME_SIZE - 1] = '\0'; + + snprintf((char *)pInstanceInfo2->swVersion, + CPA_INST_SW_VERSION_SIZE, + "Version %d.%d", + SAL_INFO2_DRIVER_SW_VERSION_MAJ_NUMBER, + SAL_INFO2_DRIVER_SW_VERSION_MIN_NUMBER); + pInstanceInfo2->swVersion[CPA_INST_SW_VERSION_SIZE - 1] = '\0'; + + /* Note we can safely read the contents of the crypto service instance + here because icp_amgr_getAllAccelDevByCapabilities() only returns + devs + that have started */ + pCryptoService = (sal_crypto_service_t *)instanceHandle; + pInstanceInfo2->physInstId.packageId = pCryptoService->pkgID; + pInstanceInfo2->physInstId.acceleratorId = + pCryptoService->acceleratorNum; + pInstanceInfo2->physInstId.executionEngineId = + pCryptoService->executionEngine; + pInstanceInfo2->physInstId.busAddress = + icp_adf_get_busAddress(pInstanceInfo2->physInstId.packageId); + + /*set coreAffinity to zero before use */ + LAC_OS_BZERO(pInstanceInfo2->coreAffinity, + sizeof(pInstanceInfo2->coreAffinity)); + CPA_BITMAP_BIT_SET(pInstanceInfo2->coreAffinity, + pCryptoService->coreAffinity); + pInstanceInfo2->nodeAffinity = pCryptoService->nodeAffinity; + + if (SAL_SERVICE_STATE_RUNNING == + pCryptoService->generic_service_info.state) { + pInstanceInfo2->operState = CPA_OPER_STATE_UP; + } else { + pInstanceInfo2->operState = CPA_OPER_STATE_DOWN; + } + + pInstanceInfo2->requiresPhysicallyContiguousMemory = CPA_TRUE; + if (SAL_RESP_POLL_CFG_FILE == pCryptoService->isPolled) { + pInstanceInfo2->isPolled = CPA_TRUE; + } else { + pInstanceInfo2->isPolled = CPA_FALSE; + } + pInstanceInfo2->isOffloaded = CPA_TRUE; + + /* Get the instance name and part name*/ + dev = icp_adf_getAccelDevByAccelId(pCryptoService->pkgID); + if (NULL == dev) { + LAC_LOG_ERROR("Can not find device for the instance\n"); + LAC_OS_BZERO(pInstanceInfo2, sizeof(CpaInstanceInfo2)); + return CPA_STATUS_FAIL; + } + snprintf((char *)pInstanceInfo2->partName, + CPA_INST_PART_NAME_SIZE, + SAL_INFO2_PART_NAME, + dev->deviceName); + pInstanceInfo2->partName[CPA_INST_PART_NAME_SIZE - 1] = '\0'; + + status = + Sal_StringParsing("Cy", + pCryptoService->generic_service_info.instance, + "Name", + keyStr); + LAC_CHECK_STATUS(status); + + if (CPA_FALSE == pCryptoService->generic_service_info.is_dyn) { + section = icpGetProcessName(); + } + + status = icp_adf_cfgGetParamValue(dev, section, keyStr, valStr); + LAC_CHECK_STATUS(status); + + snprintf((char *)pInstanceInfo2->instName, + CPA_INST_NAME_SIZE, + "%s", + valStr); + snprintf((char *)pInstanceInfo2->instID, + CPA_INST_ID_SIZE, + "%s_%s", + section, + valStr); + return CPA_STATUS_SUCCESS; +} + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + *****************************************************************************/ + +CpaStatus +cpaCyQueryCapabilities(const CpaInstanceHandle instanceHandle_in, + CpaCyCapabilitiesInfo *pCapInfo) +{ + /* Verify Instance exists */ + CpaInstanceHandle instanceHandle = NULL; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = Lac_CryptoGetFirstHandle(); + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_NULL_PARAM(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_ASYM | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(pCapInfo); + + SalCtrl_CyQueryCapabilities((sal_service_t *)instanceHandle, pCapInfo); + + return CPA_STATUS_SUCCESS; +} + +/** + ****************************************************************************** + * @ingroup cpaCySym + *****************************************************************************/ +CpaStatus +cpaCySymQueryCapabilities(const CpaInstanceHandle instanceHandle_in, + CpaCySymCapabilitiesInfo *pCapInfo) +{ + sal_crypto_service_t *pCryptoService = NULL; + sal_service_t *pGenericService = NULL; + CpaInstanceHandle instanceHandle = NULL; + + /* Verify Instance exists */ + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO); + if (!instanceHandle) { + instanceHandle = + Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM); + } + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_NULL_PARAM(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_ASYM | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(pCapInfo); + + pCryptoService = (sal_crypto_service_t *)instanceHandle; + pGenericService = &(pCryptoService->generic_service_info); + + memset(pCapInfo, '\0', sizeof(CpaCySymCapabilitiesInfo)); + /* An asym crypto instance does not support sym service */ + if (SAL_SERVICE_TYPE_CRYPTO_ASYM == pGenericService->type) { + return CPA_STATUS_SUCCESS; + } + + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_NULL); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_ARC4); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_ECB); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_CBC); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_CTR); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_CCM); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_GCM); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_DES_ECB); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_DES_CBC); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_3DES_ECB); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_3DES_CBC); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_3DES_CTR); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_KASUMI_F8); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_SNOW3G_UEA2); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_F8); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_XTS); + + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_MD5); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA1); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA224); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA256); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA384); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA512); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_AES_XCBC); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_AES_CCM); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_AES_GCM); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_KASUMI_F9); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SNOW3G_UIA2); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_AES_CMAC); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_AES_GMAC); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_AES_CBC_MAC); + + if (pGenericService->capabilitiesMask & + ICP_ACCEL_CAPABILITIES_CRYPTO_ZUC) { + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, + CPA_CY_SYM_CIPHER_ZUC_EEA3); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_ZUC_EIA3); + } + + if (pGenericService->capabilitiesMask & + ICP_ACCEL_CAPABILITIES_CHACHA_POLY) { + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_POLY); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_CHACHA); + } + + if (pGenericService->capabilitiesMask & ICP_ACCEL_CAPABILITIES_SM3) { + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SM3); + } + + pCapInfo->partialPacketSupported = CPA_TRUE; + + if (pGenericService->capabilitiesMask & ICP_ACCEL_CAPABILITIES_SHA3) { + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA3_256); + pCapInfo->partialPacketSupported = CPA_FALSE; + } + + if (pGenericService->capabilitiesMask & + ICP_ACCEL_CAPABILITIES_SHA3_EXT) { + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA3_224); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA3_256); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA3_384); + CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA3_512); + pCapInfo->partialPacketSupported = CPA_FALSE; + } + + if (pGenericService->capabilitiesMask & ICP_ACCEL_CAPABILITIES_SM4) { + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, + CPA_CY_SYM_CIPHER_SM4_ECB); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, + CPA_CY_SYM_CIPHER_SM4_CBC); + CPA_BITMAP_BIT_SET(pCapInfo->ciphers, + CPA_CY_SYM_CIPHER_SM4_CTR); + pCapInfo->partialPacketSupported = CPA_FALSE; + } + + return CPA_STATUS_SUCCESS; +} + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + *****************************************************************************/ +CpaStatus +cpaCySetAddressTranslation(const CpaInstanceHandle instanceHandle_in, + CpaVirtualToPhysical virtual2physical) +{ + + CpaInstanceHandle instanceHandle = NULL; + sal_service_t *pService = NULL; + + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + instanceHandle = Lac_CryptoGetFirstHandle(); + } else { + instanceHandle = instanceHandle_in; + } + + LAC_CHECK_NULL_PARAM(instanceHandle); + SAL_CHECK_INSTANCE_TYPE(instanceHandle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_ASYM | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + LAC_CHECK_NULL_PARAM(virtual2physical); + + pService = (sal_service_t *)instanceHandle; + + pService->virt2PhysClient = virtual2physical; + + return CPA_STATUS_SUCCESS; +} + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + * Crypto specific polling function which polls a crypto instance. + *****************************************************************************/ +CpaStatus +icp_sal_CyPollInstance(CpaInstanceHandle instanceHandle_in, + Cpa32U response_quota) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_crypto_service_t *crypto_handle = NULL; + sal_service_t *gen_handle = NULL; + icp_comms_trans_handle trans_hndTable[MAX_CY_RX_RINGS] = { 0 }; + Cpa32U num_rx_rings = 0; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + crypto_handle = + (sal_crypto_service_t *)Lac_CryptoGetFirstHandle(); + } else { + crypto_handle = (sal_crypto_service_t *)instanceHandle_in; + } + LAC_CHECK_NULL_PARAM(crypto_handle); + SAL_RUNNING_CHECK(crypto_handle); + SAL_CHECK_INSTANCE_TYPE(crypto_handle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_ASYM | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + + gen_handle = &(crypto_handle->generic_service_info); + + /* + * From the instanceHandle we must get the trans_handle and send + * down to adf for polling. + * Populate our trans handle table with the appropriate handles. + */ + + switch (gen_handle->type) { + case SAL_SERVICE_TYPE_CRYPTO_ASYM: + trans_hndTable[TH_CY_RX_0] = + crypto_handle->trans_handle_asym_rx; + num_rx_rings = 1; + break; + case SAL_SERVICE_TYPE_CRYPTO_SYM: + trans_hndTable[TH_CY_RX_0] = crypto_handle->trans_handle_sym_rx; + num_rx_rings = 1; + break; + case SAL_SERVICE_TYPE_CRYPTO: + trans_hndTable[TH_CY_RX_0] = crypto_handle->trans_handle_sym_rx; + trans_hndTable[TH_CY_RX_1] = + crypto_handle->trans_handle_asym_rx; + num_rx_rings = MAX_CY_RX_RINGS; + break; + default: + break; + } + + /* Call adf to do the polling. */ + status = + icp_adf_pollInstance(trans_hndTable, num_rx_rings, response_quota); + + return status; +} + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + * Crypto specific polling function which polls sym crypto ring. + *****************************************************************************/ +CpaStatus +icp_sal_CyPollSymRing(CpaInstanceHandle instanceHandle_in, + Cpa32U response_quota) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_crypto_service_t *crypto_handle = NULL; + icp_comms_trans_handle trans_hndTable[NUM_CRYPTO_SYM_RX_RINGS] = { 0 }; + + if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) { + crypto_handle = (sal_crypto_service_t *)Lac_GetFirstHandle( + SAL_SERVICE_TYPE_CRYPTO_SYM); + } else { + crypto_handle = (sal_crypto_service_t *)instanceHandle_in; + } + LAC_CHECK_NULL_PARAM(crypto_handle); + SAL_CHECK_INSTANCE_TYPE(crypto_handle, + (SAL_SERVICE_TYPE_CRYPTO | + SAL_SERVICE_TYPE_CRYPTO_SYM)); + SAL_RUNNING_CHECK(crypto_handle); + + /* + * From the instanceHandle we must get the trans_handle and send + * down to adf for polling. + * Populate our trans handle table with the appropriate handles. + */ + trans_hndTable[TH_SINGLE_RX] = crypto_handle->trans_handle_sym_rx; + /* Call adf to do the polling. */ + status = icp_adf_pollInstance(trans_hndTable, + NUM_CRYPTO_SYM_RX_RINGS, + response_quota); + return status; +} + + +/** + ****************************************************************************** + * @ingroup cpaCyCommon + * Crypto specific polling function which polls an nrbg crypto ring. + *****************************************************************************/ +CpaStatus +icp_sal_CyPollNRBGRing(CpaInstanceHandle instanceHandle_in, + Cpa32U response_quota) +{ + return CPA_STATUS_UNSUPPORTED; +} + +/* Returns the handle to the first asym crypto instance */ +static CpaInstanceHandle +Lac_GetFirstAsymHandle(icp_accel_dev_t *adfInsts[ADF_MAX_DEVICES], + Cpa16U num_dev) +{ + icp_accel_dev_t *dev_addr = NULL; + sal_t *base_addr = NULL; + sal_list_t *list_temp = NULL; + CpaInstanceHandle cyInst = NULL; + Cpa16U i = 0; + + for (i = 0; i < num_dev; i++) { + dev_addr = (icp_accel_dev_t *)adfInsts[i]; + base_addr = dev_addr->pSalHandle; + if ((NULL != base_addr) && (NULL != base_addr->asym_services)) { + list_temp = base_addr->asym_services; + cyInst = SalList_getObject(list_temp); + break; + } + } + + return cyInst; +} + +/* Returns the handle to the first sym crypto instance */ +static CpaInstanceHandle +Lac_GetFirstSymHandle(icp_accel_dev_t *adfInsts[ADF_MAX_DEVICES], + Cpa16U num_dev) +{ + icp_accel_dev_t *dev_addr = NULL; + sal_t *base_addr = NULL; + sal_list_t *list_temp = NULL; + CpaInstanceHandle cyInst = NULL; + Cpa16U i = 0; + + for (i = 0; i < num_dev; i++) { + dev_addr = (icp_accel_dev_t *)adfInsts[i]; + base_addr = dev_addr->pSalHandle; + if ((NULL != base_addr) && (NULL != base_addr->sym_services)) { + list_temp = base_addr->sym_services; + cyInst = SalList_getObject(list_temp); + break; + } + } + + return cyInst; +} + +/* Returns the handle to the first crypto instance + * Note that the crypto instance in this case supports + * both asym and sym services */ +static CpaInstanceHandle +Lac_GetFirstCyHandle(icp_accel_dev_t *adfInsts[ADF_MAX_DEVICES], Cpa16U num_dev) +{ + icp_accel_dev_t *dev_addr = NULL; + sal_t *base_addr = NULL; + sal_list_t *list_temp = NULL; + CpaInstanceHandle cyInst = NULL; + Cpa16U i = 0; + + for (i = 0; i < num_dev; i++) { + dev_addr = (icp_accel_dev_t *)adfInsts[i]; + base_addr = dev_addr->pSalHandle; + if ((NULL != base_addr) && + (NULL != base_addr->crypto_services)) { + list_temp = base_addr->crypto_services; + cyInst = SalList_getObject(list_temp); + break; + } + } + return cyInst; +} + +CpaInstanceHandle +Lac_GetFirstHandle(sal_service_type_t svc_type) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + static icp_accel_dev_t *adfInsts[ADF_MAX_DEVICES] = { 0 }; + CpaInstanceHandle cyInst = NULL; + Cpa16U num_cy_dev = 0; + Cpa32U capabilities = 0; + + switch (svc_type) { + case SAL_SERVICE_TYPE_CRYPTO_ASYM: + capabilities = ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC; + break; + case SAL_SERVICE_TYPE_CRYPTO_SYM: + capabilities = ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC; + break; + case SAL_SERVICE_TYPE_CRYPTO: + capabilities = ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC; + capabilities |= ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC; + break; + default: + LAC_LOG_ERROR("Invalid service type\n"); + return NULL; + break; + } + /* Only need 1 dev with crypto enabled - so check all devices*/ + status = icp_amgr_getAllAccelDevByEachCapability(capabilities, + adfInsts, + &num_cy_dev); + if ((0 == num_cy_dev) || (CPA_STATUS_SUCCESS != status)) { + LAC_LOG_ERROR("No crypto devices enabled in the system\n"); + return NULL; + } + + switch (svc_type) { + case SAL_SERVICE_TYPE_CRYPTO_ASYM: + /* Try to find an asym only instance first */ + cyInst = Lac_GetFirstAsymHandle(adfInsts, num_cy_dev); + /* Try to find a cy instance since it also supports asym */ + if (NULL == cyInst) { + cyInst = Lac_GetFirstCyHandle(adfInsts, num_cy_dev); + } + break; + case SAL_SERVICE_TYPE_CRYPTO_SYM: + /* Try to find a sym only instance first */ + cyInst = Lac_GetFirstSymHandle(adfInsts, num_cy_dev); + /* Try to find a cy instance since it also supports sym */ + if (NULL == cyInst) { + cyInst = Lac_GetFirstCyHandle(adfInsts, num_cy_dev); + } + break; + case SAL_SERVICE_TYPE_CRYPTO: + /* Try to find a cy instance */ + cyInst = Lac_GetFirstCyHandle(adfInsts, num_cy_dev); + break; + default: + break; + } + if (NULL == cyInst) { + LAC_LOG_ERROR("No remaining crypto instances available\n"); + } + return cyInst; +} + +CpaStatus +icp_sal_NrbgGetInflightRequests(CpaInstanceHandle instanceHandle_in, + Cpa32U *maxInflightRequests, + Cpa32U *numInflightRequests) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +icp_sal_SymGetInflightRequests(CpaInstanceHandle instanceHandle, + Cpa32U *maxInflightRequests, + Cpa32U *numInflightRequests) +{ + sal_crypto_service_t *crypto_handle = NULL; + + crypto_handle = (sal_crypto_service_t *)instanceHandle; + + LAC_CHECK_NULL_PARAM(crypto_handle); + LAC_CHECK_NULL_PARAM(maxInflightRequests); + LAC_CHECK_NULL_PARAM(numInflightRequests); + SAL_RUNNING_CHECK(crypto_handle); + + return icp_adf_getInflightRequests(crypto_handle->trans_handle_sym_tx, + maxInflightRequests, + numInflightRequests); +} + + +CpaStatus +icp_sal_dp_SymGetInflightRequests(CpaInstanceHandle instanceHandle, + Cpa32U *maxInflightRequests, + Cpa32U *numInflightRequests) +{ + sal_crypto_service_t *crypto_handle = NULL; + + crypto_handle = (sal_crypto_service_t *)instanceHandle; + + return icp_adf_dp_getInflightRequests( + crypto_handle->trans_handle_sym_tx, + maxInflightRequests, + numInflightRequests); +} + diff --git a/sys/dev/qat/qat_api/common/ctrl/sal_ctrl_services.c b/sys/dev/qat/qat_api/common/ctrl/sal_ctrl_services.c new file mode 100644 index 000000000000..4a41340dfabb --- /dev/null +++ b/sys/dev/qat/qat_api/common/ctrl/sal_ctrl_services.c @@ -0,0 +1,1344 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file sal_ctrl_services.c + * + * @ingroup SalCtrl + * + * @description + * This file contains the core of the service controller implementation. + * + *****************************************************************************/ + +/* QAT-API includes */ +#include "cpa.h" +#include "cpa_cy_key.h" +#include "cpa_cy_ln.h" +#include "cpa_cy_dh.h" +#include "cpa_cy_dsa.h" +#include "cpa_cy_rsa.h" +#include "cpa_cy_ec.h" +#include "cpa_cy_prime.h" +#include "cpa_cy_sym.h" +#include "cpa_dc.h" + +/* QAT utils includes */ +#include "qat_utils.h" + +/* ADF includes */ +#include "icp_adf_init.h" +#include "icp_adf_transport.h" +#include "icp_accel_devices.h" +#include "icp_adf_cfg.h" +#include "icp_adf_init.h" +#include "icp_adf_accel_mgr.h" +#include "icp_adf_debug.h" + +/* FW includes */ +#include "icp_qat_fw_la.h" + +/* SAL includes */ +#include "lac_mem.h" +#include "lac_mem_pools.h" +#include "lac_list.h" +#include "lac_hooks.h" +#include "sal_string_parse.h" +#include "lac_common.h" +#include "lac_sal_types.h" +#include "lac_sal.h" +#include "lac_sal_ctrl.h" +#include "icp_sal_versions.h" + +#define MAX_SUBSYSTEM_RETRY 64 + +static char *subsystem_name = "SAL"; +/**< Name used by ADF to identify this component. */ +static char *cy_dir_name = "cy"; +static char *asym_dir_name = "asym"; +static char *sym_dir_name = "sym"; +static char *dc_dir_name = "dc"; +/**< Stats dir names. */ +static char *ver_file_name = "version"; + +static subservice_registation_handle_t sal_service_reg_handle; +/**< Data structure used by ADF to keep a reference to this component. */ + +/* + * @ingroup SalCtrl + * @description + * This function is used to parse the results from ADF + * in response to ServiceEnabled query.The results are + * semi-colon separated. Internally, the bitmask represented + * by the enabled_service is used to track which features are enabled. + * + * @context + * This functions is called from the SalCtrl_ServiceEventInit function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] device pointer to icp_accel_dev_t structure + * @param[in] pEnabledServices pointer to memory where enabled services will + * be written. + * @retval Status + */ +CpaStatus +SalCtrl_GetEnabledServices(icp_accel_dev_t *device, Cpa32U *pEnabledServices) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + char param_value[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + char *token = NULL; + char *running = NULL; + + *pEnabledServices = 0; + + memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES); + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + "ServicesEnabled", + param_value); + + if (CPA_STATUS_SUCCESS == status) { + running = param_value; + + token = strsep(&running, ";"); + + while (NULL != token) { + do { + if (strncmp(token, "asym", strlen("asym")) == + 0) { + *pEnabledServices |= + SAL_SERVICE_TYPE_CRYPTO_ASYM; + break; + } + if (strncmp(token, "sym", strlen("sym")) == 0) { + *pEnabledServices |= + SAL_SERVICE_TYPE_CRYPTO_SYM; + break; + } + if (strncmp(token, "cy", strlen("cy")) == 0) { + *pEnabledServices |= + SAL_SERVICE_TYPE_CRYPTO; + break; + } + if (strncmp(token, "dc", strlen("dc")) == 0) { + *pEnabledServices |= + SAL_SERVICE_TYPE_COMPRESSION; + break; + } + + QAT_UTILS_LOG( + "Error parsing enabled services from ADF.\n"); + return CPA_STATUS_FAIL; + + } while (0); + token = strsep(&running, ";"); + } + } else { + QAT_UTILS_LOG("Failed to get enabled services from ADF.\n"); + } + return status; +} + +/* + * @ingroup SalCtrl + * @description + * This function is used to check whether a service is enabled + * + * @context + * This functions is called from the SalCtrl_ServiceEventInit function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * param[in] enabled_services It is the bitmask for the enabled services + * param[in] service It is the service we want to check for + */ +CpaBoolean +SalCtrl_IsServiceEnabled(Cpa32U enabled_services, sal_service_type_t service) +{ + return (CpaBoolean)((enabled_services & (Cpa32U)(service)) != 0); +} + +/* + * @ingroup SalCtrl + * @description + * This function is used to check whether enabled services has associated + * hardware capability support + * + * @context + * This functions is called from the SalCtrl_ServiceEventInit function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * param[in] device A pointer to an icp_accel_dev_t + * param[in] enabled_services It is the bitmask for the enabled services + */ + +CpaStatus +SalCtrl_GetSupportedServices(icp_accel_dev_t *device, Cpa32U enabled_services) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + Cpa32U capabilitiesMask = 0; + + status = icp_amgr_getAccelDevCapabilities(device, &capabilitiesMask); + + if (CPA_STATUS_SUCCESS == status) { + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO)) { + if (!(capabilitiesMask & + ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC) || + !(capabilitiesMask & + ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC)) { + QAT_UTILS_LOG( + "Device does not support Crypto service\n"); + status = CPA_STATUS_FAIL; + } + } + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO_ASYM)) { + if (!(capabilitiesMask & + ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC)) { + QAT_UTILS_LOG( + "Device does not support Asym service\n"); + status = CPA_STATUS_FAIL; + } + } + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO_SYM)) { + if (!(capabilitiesMask & + ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC)) { + QAT_UTILS_LOG( + "Device does not support Sym service\n"); + status = CPA_STATUS_FAIL; + } + } + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_COMPRESSION)) { + if (!(capabilitiesMask & + ICP_ACCEL_CAPABILITIES_COMPRESSION)) { + QAT_UTILS_LOG( + "Device does not support Compression service.\n"); + status = CPA_STATUS_FAIL; + } + } + } + + return status; +} + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to check if a service is supported + * on the device. The key difference between this and + * SalCtrl_GetSupportedServices() is that the latter treats it as + * an error if the service is unsupported. + * + * @context + * This can be called anywhere. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * param[in] device + * param[in] service service or services to check + * + *************************************************************************/ +CpaBoolean +SalCtrl_IsServiceSupported(icp_accel_dev_t *device, + sal_service_type_t service_to_check) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + Cpa32U capabilitiesMask = 0; + CpaBoolean service_supported = CPA_TRUE; + + if (!(SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, + SAL_SERVICE_TYPE_CRYPTO)) && + !(SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, + SAL_SERVICE_TYPE_CRYPTO_ASYM)) && + !(SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, + SAL_SERVICE_TYPE_CRYPTO_SYM)) && + !(SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, + SAL_SERVICE_TYPE_COMPRESSION))) { + QAT_UTILS_LOG("Invalid service type\n"); + service_supported = CPA_FALSE; + } + + status = icp_amgr_getAccelDevCapabilities(device, &capabilitiesMask); + + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Can not get device capabilities.\n"); + return CPA_FALSE; + } + + if (SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, + SAL_SERVICE_TYPE_CRYPTO)) { + if (!(capabilitiesMask & + ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC) || + !(capabilitiesMask & + ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC)) { + QAT_UTILS_LOG( + "Device does not support Crypto service\n"); + service_supported = CPA_FALSE; + } + } + if (SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, + SAL_SERVICE_TYPE_CRYPTO_ASYM)) { + if (!(capabilitiesMask & + ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC)) { + QAT_UTILS_LOG("Device does not support Asym service\n"); + service_supported = CPA_FALSE; + } + } + if (SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, + SAL_SERVICE_TYPE_CRYPTO_SYM)) { + if (!(capabilitiesMask & + ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC)) { + QAT_UTILS_LOG("Device does not support Sym service\n"); + service_supported = CPA_FALSE; + } + } + if (SalCtrl_IsServiceEnabled((Cpa32U)service_to_check, + SAL_SERVICE_TYPE_COMPRESSION)) { + if (!(capabilitiesMask & ICP_ACCEL_CAPABILITIES_COMPRESSION)) { + QAT_UTILS_LOG( + "Device does not support Compression service.\n"); + service_supported = CPA_FALSE; + } + } + + return service_supported; +} + +/* + * @ingroup SalCtrl + * @description + * This function is used to retrieve how many instances are + * to be configured for process specific service. + * + * @context + * This functions is called from the SalCtrl_ServiceEventInit function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] device A pointer to an icp_accel_dev_t + * @param[in] key Represents the parameter's name we want to query + * @param[out] pCount Pointer to memory where num instances will be stored + * @retval status returned status from ADF or _FAIL if number of instances + * is out of range for the device. + */ +static CpaStatus +SalCtrl_GetInstanceCount(icp_accel_dev_t *device, char *key, Cpa32U *pCount) +{ + CpaStatus status = CPA_STATUS_FAIL; + char param_value[ADF_CFG_MAX_VAL_LEN_IN_BYTES]; + + memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES); + status = icp_adf_cfgGetParamValue(device, + icpGetProcessName(), + key, + param_value); + if (CPA_STATUS_SUCCESS == status) { + *pCount = + (Cpa32U)(Sal_Strtoul(param_value, NULL, SAL_CFG_BASE_DEC)); + if (*pCount > SAL_MAX_NUM_INSTANCES_PER_DEV) { + QAT_UTILS_LOG("Number of instances is out of range.\n"); + status = CPA_STATUS_FAIL; + } + } + return status; +} + +/************************************************************************** + * @ingroup SalCtrl + * @description + * This function calls the shutdown function on all the + * service instances. + * It also frees all service instance memory allocated at Init. + * + * @context + * This function is called from the SalCtrl_ServiceEventShutdown + * function. + * + * @assumptions + * params[in] should not be NULL + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] services A pointer to the container of services + * @param[in] dbg_dir A pointer to the debug directory + * @param[in] svc_type The type of the service instance + * + ****************************************************************************/ +static CpaStatus +SalCtrl_ServiceShutdown(icp_accel_dev_t *device, + sal_list_t **services, + debug_dir_info_t **debug_dir, + sal_service_type_t svc_type) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_list_t *dyn_service = NULL; + sal_service_t *inst = NULL; + + /* Call Shutdown function for each service instance */ + SAL_FOR_EACH(*services, sal_service_t, device, shutdown, status); + + if (*debug_dir) { + icp_adf_debugRemoveDir(*debug_dir); + LAC_OS_FREE(*debug_dir); + *debug_dir = NULL; + } + + if (!icp_adf_is_dev_in_reset(device)) { + dyn_service = *services; + while (dyn_service) { + inst = (sal_service_t *)SalList_getObject(dyn_service); + if (CPA_TRUE == inst->is_dyn) { + icp_adf_putDynInstance(device, + (adf_service_type_t) + svc_type, + inst->instance); + } + dyn_service = SalList_next(dyn_service); + } + /* Free Sal services controller memory */ + SalList_free(services); + } else { + sal_list_t *curr_element = NULL; + sal_service_t *service = NULL; + curr_element = *services; + while (NULL != curr_element) { + service = + (sal_service_t *)SalList_getObject(curr_element); + service->state = SAL_SERVICE_STATE_RESTARTING; + curr_element = SalList_next(curr_element); + } + } + + return status; +} + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to initialise the service instances. + * It allocates memory for service instances and invokes the + * Init function on them. + * + * @context + * This function is called from the SalCtrl_ServiceEventInit function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] services A pointer to the container of services + * @param[in] dbg_dir A pointer to the debug directory + * @param[in] dbg_dir_name Name of the debug directory + * @param[in] tail_list SAL's list of services + * @param[in] instance_count Number of instances + * @param[in] svc_type The type of the service instance + * + *************************************************************************/ +static CpaStatus +SalCtrl_ServiceInit(icp_accel_dev_t *device, + sal_list_t **services, + debug_dir_info_t **dbg_dir, + char *dbg_dir_name, + sal_list_t *tail_list, + Cpa32U instance_count, + sal_service_type_t svc_type) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_service_t *pInst = NULL; + Cpa32U i = 0; + debug_dir_info_t *debug_dir = NULL; + + debug_dir = LAC_OS_MALLOC(sizeof(debug_dir_info_t)); + if (NULL == debug_dir) { + QAT_UTILS_LOG("Failed to allocate memory for debug dir.\n"); + return CPA_STATUS_RESOURCE; + } + debug_dir->name = dbg_dir_name; + debug_dir->parent = NULL; + status = icp_adf_debugAddDir(device, debug_dir); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to add debug dir.\n"); + LAC_OS_FREE(debug_dir); + debug_dir = NULL; + return status; + } + + if (!icp_adf_is_dev_in_reset(device)) { + for (i = 0; i < instance_count; i++) { + status = SalCtrl_ServiceCreate(svc_type, i, &pInst); + if (CPA_STATUS_SUCCESS != status) { + break; + } + pInst->debug_parent_dir = debug_dir; + pInst->capabilitiesMask = device->accelCapabilitiesMask; + status = SalList_add(services, &tail_list, pInst); + if (CPA_STATUS_SUCCESS != status) { + free(pInst, M_QAT); + } + } + } else { + sal_list_t *curr_element = *services; + sal_service_t *service = NULL; + while (NULL != curr_element) { + service = + (sal_service_t *)SalList_getObject(curr_element); + service->debug_parent_dir = debug_dir; + + if (CPA_TRUE == service->isInstanceStarted) { + icp_qa_dev_get(device); + } + + curr_element = SalList_next(curr_element); + } + } + + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to allocate all instances.\n"); + icp_adf_debugRemoveDir(debug_dir); + LAC_OS_FREE(debug_dir); + debug_dir = NULL; + SalList_free(services); + return status; + } + + /* Call init function for each service instance */ + SAL_FOR_EACH(*services, sal_service_t, device, init, status); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to initialise all service instances.\n"); + /* shutdown all instances initialised before error */ + SAL_FOR_EACH_STATE(*services, + sal_service_t, + device, + shutdown, + SAL_SERVICE_STATE_INITIALIZED); + icp_adf_debugRemoveDir(debug_dir); + LAC_OS_FREE(debug_dir); + debug_dir = NULL; + SalList_free(services); + return status; + } + /* initialize the debug directory for relevant service */ + *dbg_dir = debug_dir; + + return status; +} + +/************************************************************************** + * @ingroup SalCtrl + * @description + * This function calls the start function on all the service instances. + * + * @context + * This function is called from the SalCtrl_ServiceEventStart function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] services A pointer to the container of services + * + **************************************************************************/ +static CpaStatus +SalCtrl_ServiceStart(icp_accel_dev_t *device, sal_list_t *services) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + /* Call Start function for each service instance */ + SAL_FOR_EACH(services, sal_service_t, device, start, status); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to start all instances.\n"); + /* stop all instances started before error */ + SAL_FOR_EACH_STATE(services, + sal_service_t, + device, + stop, + SAL_SERVICE_STATE_RUNNING); + return status; + } + + if (icp_adf_is_dev_in_reset(device)) { + sal_list_t *curr_element = services; + sal_service_t *service = NULL; + while (NULL != curr_element) { + service = + (sal_service_t *)SalList_getObject(curr_element); + if (service->notification_cb) { + service->notification_cb( + service, + service->cb_tag, + CPA_INSTANCE_EVENT_RESTARTED); + } + curr_element = SalList_next(curr_element); + } + } + + return status; +} + +/**************************************************************************** + * @ingroup SalCtrl + * @description + * This function calls the stop function on all the + * service instances. + * + * @context + * This function is called from the SalCtrl_ServiceEventStop function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] services A pointer to the container of services + * + *************************************************************************/ +static CpaStatus +SalCtrl_ServiceStop(icp_accel_dev_t *device, sal_list_t *services) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + /* Calling restarting functions */ + if (icp_adf_is_dev_in_reset(device)) { + sal_list_t *curr_element = services; + sal_service_t *service = NULL; + while (NULL != curr_element) { + service = + (sal_service_t *)SalList_getObject(curr_element); + if (service->notification_cb) { + service->notification_cb( + service, + service->cb_tag, + CPA_INSTANCE_EVENT_RESTARTING); + } + curr_element = SalList_next(curr_element); + } + } + + /* Call Stop function for each service instance */ + SAL_FOR_EACH(services, sal_service_t, device, stop, status); + + return status; +} + +/* + * @ingroup SalCtrl + * @description + * This function is used to print hardware and software versions in proc + * filesystem entry via ADF Debug interface + * + * @context + * This functions is called from proc filesystem interface + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] private_data A pointer to a private data passed to the + * function while adding a debug file. + * @param[out] data Pointer to a buffer where version information + * needs to be printed to. + * @param[in] size Size of a buffer pointed by data. + * @param[in] offset Offset in a debug file + * + * @retval 0 This function always returns 0 + */ +static int +SalCtrl_VersionDebug(void *private_data, char *data, int size, int offset) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + Cpa32U len = 0; + icp_accel_dev_t *device = (icp_accel_dev_t *)private_data; + char param_value[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + + len += snprintf( + data + len, + size - len, + SEPARATOR BORDER + " Hardware and Software versions for device %d " BORDER + "\n" SEPARATOR, + device->accelId); + + memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES); + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + ICP_CFG_HW_REV_ID_KEY, + param_value); + LAC_CHECK_STATUS(status); + + len += snprintf(data + len, + size - len, + " Hardware Version: %s %s \n", + param_value, + get_sku_info(device->sku)); + + memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES); + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + ICP_CFG_UOF_VER_KEY, + param_value); + LAC_CHECK_STATUS(status); + + len += snprintf(data + len, + size - len, + " Firmware Version: %s \n", + param_value); + memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES); + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + ICP_CFG_MMP_VER_KEY, + param_value); + LAC_CHECK_STATUS(status); + + len += snprintf(data + len, + size - len, + " MMP Version: %s \n", + param_value); + len += snprintf(data + len, + size - len, + " Driver Version: %d.%d.%d \n", + SAL_INFO2_DRIVER_SW_VERSION_MAJ_NUMBER, + SAL_INFO2_DRIVER_SW_VERSION_MIN_NUMBER, + SAL_INFO2_DRIVER_SW_VERSION_PATCH_NUMBER); + + memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES); + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + ICP_CFG_LO_COMPATIBLE_DRV_KEY, + param_value); + LAC_CHECK_STATUS(status); + + len += snprintf(data + len, + size - len, + " Lowest Compatible Driver: %s \n", + param_value); + + len += snprintf(data + len, + size - len, + " QuickAssist API CY Version: %d.%d \n", + CPA_CY_API_VERSION_NUM_MAJOR, + CPA_CY_API_VERSION_NUM_MINOR); + len += snprintf(data + len, + size - len, + " QuickAssist API DC Version: %d.%d \n", + CPA_DC_API_VERSION_NUM_MAJOR, + CPA_DC_API_VERSION_NUM_MINOR); + + len += snprintf(data + len, size - len, SEPARATOR); + return 0; +} + +/************************************************************************** + * @ingroup SalCtrl + * @description + * This function calls the shutdown function on all the service + * instances. It also frees all service instance memory + * allocated at Init. + * + * @context + * This function is called from the SalCtrl_ServiceEventHandler function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] enabled_services Services enabled by user + * + ****************************************************************************/ +static CpaStatus +SalCtrl_ServiceEventShutdown(icp_accel_dev_t *device, Cpa32U enabled_services) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + CpaStatus ret_status = CPA_STATUS_SUCCESS; + sal_t *service_container = (sal_t *)device->pSalHandle; + + if (NULL == service_container) { + QAT_UTILS_LOG("Private data is NULL\n"); + return CPA_STATUS_FATAL; + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO)) { + status = + SalCtrl_ServiceShutdown(device, + &service_container->crypto_services, + &service_container->cy_dir, + SAL_SERVICE_TYPE_CRYPTO); + if (CPA_STATUS_SUCCESS != status) { + ret_status = status; + } + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO_ASYM)) { + status = + SalCtrl_ServiceShutdown(device, + &service_container->asym_services, + &service_container->asym_dir, + SAL_SERVICE_TYPE_CRYPTO_ASYM); + if (CPA_STATUS_SUCCESS != status) { + ret_status = status; + } + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO_SYM)) { + status = + SalCtrl_ServiceShutdown(device, + &service_container->sym_services, + &service_container->sym_dir, + SAL_SERVICE_TYPE_CRYPTO_SYM); + if (CPA_STATUS_SUCCESS != status) { + ret_status = status; + } + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_COMPRESSION)) { + status = SalCtrl_ServiceShutdown( + device, + &service_container->compression_services, + &service_container->dc_dir, + SAL_SERVICE_TYPE_COMPRESSION); + if (CPA_STATUS_SUCCESS != status) { + ret_status = status; + } + } + + if (service_container->ver_file) { + icp_adf_debugRemoveFile(service_container->ver_file); + LAC_OS_FREE(service_container->ver_file); + service_container->ver_file = NULL; + } + + if (!icp_adf_is_dev_in_reset(device)) { + /* Free container also */ + free(service_container, M_QAT); + device->pSalHandle = NULL; + } + + return ret_status; +} + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to initialize the service instances. + * It first checks (via ADF query) which services are enabled in the + * system and the number of each services. + * It then invokes the init function on them which creates the + * instances and allocates memory for them. + * + * @context + * This function is called from the SalCtrl_ServiceEventHandler function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] enabled_services Services enabled by user + * + *************************************************************************/ +static CpaStatus +SalCtrl_ServiceEventInit(icp_accel_dev_t *device, Cpa32U enabled_services) +{ + sal_t *service_container = NULL; + CpaStatus status = CPA_STATUS_SUCCESS; + sal_list_t *tail_list = NULL; + Cpa32U instance_count = 0; + + status = SalCtrl_GetSupportedServices(device, enabled_services); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get supported services.\n"); + return status; + } + + if (!icp_adf_is_dev_in_reset(device)) { + service_container = malloc(sizeof(sal_t), M_QAT, M_WAITOK); + device->pSalHandle = service_container; + service_container->asym_services = NULL; + service_container->sym_services = NULL; + service_container->crypto_services = NULL; + service_container->compression_services = NULL; + } else { + service_container = device->pSalHandle; + } + service_container->asym_dir = NULL; + service_container->sym_dir = NULL; + service_container->cy_dir = NULL; + service_container->dc_dir = NULL; + service_container->ver_file = NULL; + + service_container->ver_file = LAC_OS_MALLOC(sizeof(debug_file_info_t)); + if (NULL == service_container->ver_file) { + free(service_container, M_QAT); + return CPA_STATUS_RESOURCE; + } + + memset(service_container->ver_file, 0, sizeof(debug_file_info_t)); + service_container->ver_file->name = ver_file_name; + service_container->ver_file->seq_read = SalCtrl_VersionDebug; + service_container->ver_file->private_data = device; + service_container->ver_file->parent = NULL; + + status = icp_adf_debugAddFile(device, service_container->ver_file); + if (CPA_STATUS_SUCCESS != status) { + LAC_OS_FREE(service_container->ver_file); + free(service_container, M_QAT); + return status; + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO_ASYM)) { + status = SalCtrl_GetInstanceCount(device, + "NumberCyInstances", + &instance_count); + if (CPA_STATUS_SUCCESS != status) { + instance_count = 0; + } + status = SalCtrl_ServiceInit(device, + &service_container->asym_services, + &service_container->asym_dir, + asym_dir_name, + tail_list, + instance_count, + SAL_SERVICE_TYPE_CRYPTO_ASYM); + if (CPA_STATUS_SUCCESS != status) { + goto err_init; + } + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO_SYM)) { + status = SalCtrl_GetInstanceCount(device, + "NumberCyInstances", + &instance_count); + if (CPA_STATUS_SUCCESS != status) { + instance_count = 0; + } + status = SalCtrl_ServiceInit(device, + &service_container->sym_services, + &service_container->sym_dir, + sym_dir_name, + tail_list, + instance_count, + SAL_SERVICE_TYPE_CRYPTO_SYM); + if (CPA_STATUS_SUCCESS != status) { + goto err_init; + } + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO)) { + status = SalCtrl_GetInstanceCount(device, + "NumberCyInstances", + &instance_count); + if (CPA_STATUS_SUCCESS != status) { + instance_count = 0; + } + status = + SalCtrl_ServiceInit(device, + &service_container->crypto_services, + &service_container->cy_dir, + cy_dir_name, + tail_list, + instance_count, + SAL_SERVICE_TYPE_CRYPTO); + if (CPA_STATUS_SUCCESS != status) { + goto err_init; + } + } + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_COMPRESSION)) { + status = SalCtrl_GetInstanceCount(device, + "NumberDcInstances", + &instance_count); + if (CPA_STATUS_SUCCESS != status) { + instance_count = 0; + } + status = SalCtrl_ServiceInit( + device, + &service_container->compression_services, + &service_container->dc_dir, + dc_dir_name, + tail_list, + instance_count, + SAL_SERVICE_TYPE_COMPRESSION); + if (CPA_STATUS_SUCCESS != status) { + goto err_init; + } + } + + return status; + +err_init: + SalCtrl_ServiceEventShutdown(device, enabled_services); + return status; +} + +/**************************************************************************** + * @ingroup SalCtrl + * @description + * This function calls the stop function on all the service instances. + * + * @context + * This function is called from the SalCtrl_ServiceEventHandler function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] enabled_services Enabled services by user + * + *************************************************************************/ +static CpaStatus +SalCtrl_ServiceEventStop(icp_accel_dev_t *device, Cpa32U enabled_services) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + CpaStatus ret_status = CPA_STATUS_SUCCESS; + sal_t *service_container = device->pSalHandle; + + if (service_container == NULL) { + QAT_UTILS_LOG("Private data is NULL.\n"); + return CPA_STATUS_FATAL; + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO_ASYM)) { + status = SalCtrl_ServiceStop(device, + service_container->asym_services); + if (CPA_STATUS_SUCCESS != status) { + ret_status = status; + } + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO_SYM)) { + status = SalCtrl_ServiceStop(device, + service_container->sym_services); + if (CPA_STATUS_SUCCESS != status) { + ret_status = status; + } + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO)) { + status = + SalCtrl_ServiceStop(device, + service_container->crypto_services); + if (CPA_STATUS_SUCCESS != status) { + ret_status = status; + } + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_COMPRESSION)) { + status = SalCtrl_ServiceStop( + device, service_container->compression_services); + if (CPA_STATUS_SUCCESS != status) { + ret_status = status; + } + } + + return ret_status; +} + +/************************************************************************** + * @ingroup SalCtrl + * @description + * This function calls the start function on all the service instances. + * + * @context + * This function is called from the SalCtrl_ServiceEventHandler function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] enabled_services Enabled services by user + * + **************************************************************************/ +static CpaStatus +SalCtrl_ServiceEventStart(icp_accel_dev_t *device, Cpa32U enabled_services) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_t *service_container = device->pSalHandle; + + if (service_container == NULL) { + QAT_UTILS_LOG("Private data is NULL.\n"); + return CPA_STATUS_FATAL; + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO_ASYM)) { + status = SalCtrl_ServiceStart(device, + service_container->asym_services); + if (CPA_STATUS_SUCCESS != status) { + goto err_start; + } + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO_SYM)) { + status = SalCtrl_ServiceStart(device, + service_container->sym_services); + if (CPA_STATUS_SUCCESS != status) { + goto err_start; + } + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO)) { + status = + SalCtrl_ServiceStart(device, + service_container->crypto_services); + if (CPA_STATUS_SUCCESS != status) { + goto err_start; + } + } + + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_COMPRESSION)) { + status = SalCtrl_ServiceStart( + device, service_container->compression_services); + if (CPA_STATUS_SUCCESS != status) { + goto err_start; + } + } + + return status; +err_start: + SalCtrl_ServiceEventStop(device, enabled_services); + return status; +} + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is the events handler registered with ADF + * for the QA API services (cy, dc) - kernel and user + * + * @context + * This function is called from an ADF context. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] event Event from ADF + * @param[in] param Parameter used for back compatibility + * + ***********************************************************************/ +static CpaStatus +SalCtrl_ServiceEventHandler(icp_accel_dev_t *device, + icp_adf_subsystemEvent_t event, + void *param) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + CpaStatus stats_status = CPA_STATUS_SUCCESS; + Cpa32U enabled_services = 0; + + status = SalCtrl_GetEnabledServices(device, &enabled_services); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get enabled services.\n"); + return status; + } + + switch (event) { + case ICP_ADF_EVENT_INIT: { + /* In case there is no QAT SAL needs to call InitStats */ + if (NULL == device->pQatStats) { + status = SalStatistics_InitStatisticsCollection(device); + } + if (CPA_STATUS_SUCCESS != status) { + return status; + } + + status = SalCtrl_ServiceEventInit(device, enabled_services); + break; + } + case ICP_ADF_EVENT_START: { + status = SalCtrl_ServiceEventStart(device, enabled_services); + break; + } + case ICP_ADF_EVENT_STOP: { + status = SalCtrl_ServiceEventStop(device, enabled_services); + break; + } + case ICP_ADF_EVENT_SHUTDOWN: { + status = SalCtrl_ServiceEventShutdown(device, enabled_services); + stats_status = SalStatistics_CleanStatisticsCollection(device); + if (CPA_STATUS_SUCCESS != status || + CPA_STATUS_SUCCESS != stats_status) { + return CPA_STATUS_FAIL; + } + break; + } + default: + status = CPA_STATUS_SUCCESS; + break; + } + return status; +} + +CpaStatus +SalCtrl_AdfServicesRegister(void) +{ + /* Fill out the global sal_service_reg_handle structure */ + sal_service_reg_handle.subserviceEventHandler = + SalCtrl_ServiceEventHandler; + /* Set subsystem name to globally defined name */ + sal_service_reg_handle.subsystem_name = subsystem_name; + + return icp_adf_subsystemRegister(&sal_service_reg_handle); +} + +CpaStatus +SalCtrl_AdfServicesUnregister(void) +{ + return icp_adf_subsystemUnregister(&sal_service_reg_handle); +} + +CpaStatus +SalCtrl_AdfServicesStartedCheck(void) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + Cpa32U retry_num = 0; + CpaBoolean state = CPA_FALSE; + + do { + state = icp_adf_isSubsystemStarted(&sal_service_reg_handle); + retry_num++; + } while ((CPA_FALSE == state) && (retry_num < MAX_SUBSYSTEM_RETRY)); + + if (CPA_FALSE == state) { + QAT_UTILS_LOG("Sal Ctrl failed to start in given time.\n"); + status = CPA_STATUS_FAIL; + } + + return status; +} + +CpaStatus +validateConcurrRequest(Cpa32U numConcurrRequests) +{ + Cpa32U baseReq = SAL_64_CONCURR_REQUESTS; + + if (SAL_64_CONCURR_REQUESTS > numConcurrRequests) { + QAT_UTILS_LOG( + "Invalid numConcurrRequests, it is less than min value.\n"); + return CPA_STATUS_FAIL; + } + + while (SAL_MAX_CONCURR_REQUESTS >= baseReq) { + if (baseReq != numConcurrRequests) { + baseReq = baseReq << 1; + } else { + break; + } + } + if (SAL_MAX_CONCURR_REQUESTS < baseReq) { + QAT_UTILS_LOG( + "Invalid baseReg, it is greater than max value.\n"); + return CPA_STATUS_FAIL; + } + + return CPA_STATUS_SUCCESS; +} diff --git a/sys/dev/qat/qat_api/common/ctrl/sal_list.c b/sys/dev/qat/qat_api/common/ctrl/sal_list.c new file mode 100644 index 000000000000..022e271c1639 --- /dev/null +++ b/sys/dev/qat/qat_api/common/ctrl/sal_list.c @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file sal_list.c + * + * @ingroup SalCtrl + * + * List implementations for SAL + * + *****************************************************************************/ + +#include "lac_mem.h" +#include "lac_list.h" + +CpaStatus +SalList_add(sal_list_t **list, sal_list_t **tail, void *pObj) +{ + sal_list_t *new_element = NULL; + + if (NULL == *list) { + /* First element in list */ + *list = malloc(sizeof(sal_list_t), M_QAT, M_WAITOK); + (*list)->next = NULL; + (*list)->pObj = pObj; + *tail = *list; + } else { + /* add to tail of the list */ + new_element = malloc(sizeof(sal_list_t), M_QAT, M_WAITOK); + new_element->pObj = pObj; + new_element->next = NULL; + + (*tail)->next = new_element; + + *tail = new_element; + } + + return CPA_STATUS_SUCCESS; +} + +void * +SalList_getObject(sal_list_t *list) +{ + if (list == NULL) { + return NULL; + } + + return list->pObj; +} + +void +SalList_delObject(sal_list_t **list) +{ + if (*list == NULL) { + return; + } + + (*list)->pObj = NULL; + return; +} + +void * +SalList_next(sal_list_t *list) +{ + return list->next; +} + +void +SalList_free(sal_list_t **list) +{ + sal_list_t *next_element = NULL; + void *pObj = NULL; + while (NULL != (*list)) { + next_element = SalList_next(*list); + pObj = SalList_getObject((*list)); + LAC_OS_FREE(pObj); + LAC_OS_FREE(*list); + *list = next_element; + } +} + +void +SalList_del(sal_list_t **head_list, sal_list_t **pre_list, sal_list_t *list) +{ + void *pObj = NULL; + if ((NULL == *head_list) || (NULL == *pre_list) || (NULL == list)) { + return; + } + if (*head_list == list) { /* delete the first node in list */ + *head_list = list->next; + } else { + (*pre_list)->next = list->next; + } + pObj = SalList_getObject(list); + LAC_OS_FREE(pObj); + LAC_OS_FREE(list); + return; +} diff --git a/sys/dev/qat/qat_api/common/include/lac_buffer_desc.h b/sys/dev/qat/qat_api/common/include/lac_buffer_desc.h new file mode 100644 index 000000000000..079d537d7824 --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_buffer_desc.h @@ -0,0 +1,252 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file lac_buffer_desc.h + * + * @defgroup LacBufferDesc Buffer Descriptors + * + * @ingroup LacCommon + * + * Functions which handle updating a user supplied buffer with the QAT + * descriptor representation. + * + ***************************************************************************/ + +/***************************************************************************/ + +#ifndef LAC_BUFFER_DESC_H +#define LAC_BUFFER_DESC_H + +/*************************************************************************** + * Include header files + ***************************************************************************/ +#include "cpa.h" +#include "icp_buffer_desc.h" +#include "cpa_cy_sym.h" +#include "lac_common.h" + +/** +******************************************************************************* +* @ingroup LacBufferDesc +* Write the buffer descriptor in QAT friendly format. +* +* @description +* Updates the Meta Data associated with the pUserBufferList CpaBufferList +* This function will also return the (aligned) physical address +* associated with this CpaBufferList. +* +* @param[in] pUserBufferList A pointer to the buffer list to +* create the meta data for the QAT. +* @param[out] pBufferListAlignedPhyAddr The pointer to the aligned physical +* address. +* @param[in] isPhysicalAddress Type of address +* @param[in] pService Pointer to generic service +* +*****************************************************************************/ +CpaStatus LacBuffDesc_BufferListDescWrite(const CpaBufferList *pUserBufferList, + Cpa64U *pBufferListAlignedPhyAddr, + CpaBoolean isPhysicalAddress, + sal_service_t *pService); + +/** +******************************************************************************* +* @ingroup LacBufferDesc +* Write the buffer descriptor in QAT friendly format. +* +* @description +* Updates the Meta Data associated with the pUserBufferList CpaBufferList +* This function will also return the (aligned) physical address +* associated with this CpaBufferList. Zero length buffers are allowed. +* Should be used for CHA-CHA-POLY and GCM algorithms. +* +* @param[in] pUserBufferList A pointer to the buffer list to +* create the meta data for the QAT. +* @param[out] pBufferListAlignedPhyAddr The pointer to the aligned physical +* address. +* @param[in] isPhysicalAddress Type of address +* @param[in] pService Pointer to generic service +* +*****************************************************************************/ +CpaStatus LacBuffDesc_BufferListDescWriteAndAllowZeroBuffer( + const CpaBufferList *pUserBufferList, + Cpa64U *pBufferListAlignedPhyAddr, + CpaBoolean isPhysicalAddress, + sal_service_t *pService); + +/** +******************************************************************************* + * @ingroup LacBufferDesc + * Write the buffer descriptor in QAT friendly format. + * + * @description + * Updates the Meta Data associated with the PClientList CpaBufferList + * This function will also return the (aligned) physical address + * associated with this CpaBufferList and the total data length of the + * buffer list. + * + * @param[in] pUserBufferList A pointer to the buffer list to + * create the meta data for the QAT. + * @param[out] pBufListAlignedPhyAddr The pointer to the aligned physical + * address. + * @param[in] isPhysicalAddress Type of address + * @param[out] totalDataLenInBytes The pointer to the total data length + * of the buffer list + * @param[in] pService Pointer to generic service + * + *****************************************************************************/ +CpaStatus +LacBuffDesc_BufferListDescWriteAndGetSize(const CpaBufferList *pUserBufferList, + Cpa64U *pBufListAlignedPhyAddr, + CpaBoolean isPhysicalAddress, + Cpa64U *totalDataLenInBytes, + sal_service_t *pService); + +/** +******************************************************************************* + * @ingroup LacBufferDesc + * Ensure the CpaFlatBuffer is correctly formatted. + * + * @description + * Ensures the CpaFlatBuffer is correctly formatted + * This function will also return the total size of the buffers + * in the scatter gather list. + * + * @param[in] pUserFlatBuffer A pointer to the flat buffer to + * validate. + * @param[out] pPktSize The total size of the packet. + * @param[in] alignmentShiftExpected The expected alignment shift of each + * of the elements of the scatter gather + * + * @retval CPA_STATUS_INVALID_PARAM BufferList failed checks + * @retval CPA_STATUS_SUCCESS Function executed successfully + * + *****************************************************************************/ +CpaStatus +LacBuffDesc_FlatBufferVerify(const CpaFlatBuffer *pUserFlatBuffer, + Cpa64U *pPktSize, + lac_aligment_shift_t alignmentShiftExpected); + +/** +******************************************************************************* + * @ingroup LacBufferDesc + * Ensure the CpaFlatBuffer is correctly formatted. + * This function will allow a size of zero bytes to any of the Flat + * buffers. + * + * @description + * Ensures the CpaFlatBuffer is correctly formatted + * This function will also return the total size of the buffers + * in the scatter gather list. + * + * @param[in] pUserFlatBuffer A pointer to the flat buffer to + * validate. + * @param[out] pPktSize The total size of the packet. + * @param[in] alignmentShiftExpected The expected alignment shift of each + * of the elements of the scatter gather + * + * @retval CPA_STATUS_INVALID_PARAM BufferList failed checks + * @retval CPA_STATUS_SUCCESS Function executed successfully + * + *****************************************************************************/ +CpaStatus +LacBuffDesc_FlatBufferVerifyNull(const CpaFlatBuffer *pUserFlatBuffer, + Cpa64U *pPktSize, + lac_aligment_shift_t alignmentShiftExpected); + +/** +******************************************************************************* + * @ingroup LacBufferDesc + * Ensure the CpaBufferList is correctly formatted. + * + * @description + * Ensures the CpaBufferList pUserBufferList is correctly formatted + * including the user supplied metaData. + * This function will also return the total size of the buffers + * in the scatter gather list. + * + * @param[in] pUserBufferList A pointer to the buffer list to + * validate. + * @param[out] pPktSize The total size of the buffers in the + * scatter gather list. + * @param[in] alignmentShiftExpected The expected alignment shift of each + * of the elements of the scatter gather + * list. + * @retval CPA_STATUS_INVALID_PARAM BufferList failed checks + * @retval CPA_STATUS_SUCCESS Function executed successfully + * + *****************************************************************************/ +CpaStatus +LacBuffDesc_BufferListVerify(const CpaBufferList *pUserBufferList, + Cpa64U *pPktSize, + lac_aligment_shift_t alignmentShiftExpected); + +/** +******************************************************************************* + * @ingroup LacBufferDesc + * Ensure the CpaBufferList is correctly formatted. + * + * @description + * Ensures the CpaBufferList pUserBufferList is correctly formatted + * including the user supplied metaData. + * This function will also return the total size of the buffers + * in the scatter gather list. + * + * @param[in] pUserBufferList A pointer to the buffer list to + * validate. + * @param[out] pPktSize The total size of the buffers in the + * scatter gather list. + * @param[in] alignmentShiftExpected The expected alignment shift of each + * of the elements of the scatter gather + * list. + * @retval CPA_STATUS_INVALID_PARAM BufferList failed checks + * @retval CPA_STATUS_SUCCESS Function executed successfully + * + *****************************************************************************/ +CpaStatus +LacBuffDesc_BufferListVerifyNull(const CpaBufferList *pUserBufferList, + Cpa64U *pPktSize, + lac_aligment_shift_t alignmentShiftExpected); + +/** +******************************************************************************* + * @ingroup LacBufferDesc + * Get the total size of a CpaBufferList. + * + * @description + * This function returns the total size of the buffers + * in the scatter gather list. + * + * @param[in] pUserBufferList A pointer to the buffer list to + * calculate the total size for. + * @param[out] pPktSize The total size of the buffers in the + * scatter gather list. + * + *****************************************************************************/ +void LacBuffDesc_BufferListTotalSizeGet(const CpaBufferList *pUserBufferList, + Cpa64U *pPktSize); + +/** +******************************************************************************* + * @ingroup LacBufferDesc + * Zero some of the CpaBufferList. + * + * @description + * Zero a section of data within the CpaBufferList from an offset for + * a specific length. + * + * @param[in] pBuffList A pointer to the buffer list to + * zero an area of. + * @param[in] offset Number of bytes from start of buffer to where + * to start zeroing. + * + * @param[in] lenToZero Number of bytes that will be set to zero + * after the call to this function. + *****************************************************************************/ + +void LacBuffDesc_BufferListZeroFromOffset(CpaBufferList *pBuffList, + Cpa32U offset, + Cpa32U lenToZero); + +#endif /* LAC_BUFFER_DESC_H */ diff --git a/sys/dev/qat/qat_api/common/include/lac_common.h b/sys/dev/qat/qat_api/common/include/lac_common.h new file mode 100644 index 000000000000..fb2fdd95300e --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_common.h @@ -0,0 +1,847 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file lac_common.h Common macros + * + * @defgroup Lac Look Aside Crypto LLD Doc + * + *****************************************************************************/ + +/** + ***************************************************************************** + * @defgroup LacCommon LAC Common + * Common code for Lac which includes init/shutdown, memory, logging and + * hooks. + * + * @ingroup Lac + * + *****************************************************************************/ + +/***************************************************************************/ + +#ifndef LAC_COMMON_H +#define LAC_COMMON_H + +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ + +#include "cpa.h" +#include "qat_utils.h" +#include "cpa_cy_common.h" +#include "icp_adf_init.h" + +#define LAC_ARCH_UINT uintptr_t +#define LAC_ARCH_INT intptr_t + +/* +***************************************************************************** +* Max range values for some primitive param checking +***************************************************************************** +*/ + +/**< Maximum number of instances */ +#define SAL_MAX_NUM_INSTANCES_PER_DEV 512 + +#define SAL_DEFAULT_RING_SIZE 256 +/**< Default ring size */ + +#define SAL_64_CONCURR_REQUESTS 64 +#define SAL_128_CONCURR_REQUESTS 128 +#define SAL_256_CONCURR_REQUESTS 256 +#define SAL_512_CONCURR_REQUESTS 512 +#define SAL_1024_CONCURR_REQUESTS 1024 +#define SAL_2048_CONCURR_REQUESTS 2048 +#define SAL_4096_CONCURR_REQUESTS 4096 +#define SAL_MAX_CONCURR_REQUESTS 65536 +/**< Valid options for the num of concurrent requests per ring pair read + from the config file. These values are used to size the rings */ + +#define SAL_BATCH_SUBMIT_FREE_SPACE 2 +/**< For data plane batch submissions ADF leaves 2 spaces free on the ring */ + +/* +****************************************************************************** +* Some common settings for QA API queries +****************************************************************************** +*/ + +#define SAL_INFO2_VENDOR_NAME "Intel(R)" +/**< @ingroup LacCommon + * Name of vendor of this driver */ +#define SAL_INFO2_PART_NAME "%s with Intel(R) QuickAssist Technology" +/**< @ingroup LacCommon + */ + +/* +******************************************************************************** +* User process name defines and functions +******************************************************************************** +*/ + +#define LAC_USER_PROCESS_NAME_MAX_LEN 32 +/**< @ingroup LacCommon + * Max length of user process name */ + +#define LAC_KERNEL_PROCESS_NAME "KERNEL_QAT" +/**< @ingroup LacCommon + * Default name for kernel process */ + +/* +******************************************************************************** +* response mode indicator from Config file +******************************************************************************** +*/ + +#define SAL_RESP_POLL_CFG_FILE 1 +#define SAL_RESP_EPOLL_CFG_FILE 2 + +/* + * @ingroup LacCommon + * @description + * This function sets the process name + * + * @context + * This functions is called from module_init or from user space process + * initialization function + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No + * + * param[in] processName Process name to be set +*/ +CpaStatus icpSetProcessName(const char *processName); + +/* + * @ingroup LacCommon + * @description + * This function gets the process name + * + * @context + * This functions is called from LAC context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * Yes + * @threadSafe + * Yes + * +*/ +char *icpGetProcessName(void); + +/* Sections of the config file */ +#define LAC_CFG_SECTION_GENERAL "GENERAL" +#define LAC_CFG_SECTION_INTERNAL "INTERNAL" + +/* +******************************************************************************** +* Debug Macros and settings +******************************************************************************** +*/ + +#define SEPARATOR "+--------------------------------------------------+\n" +/**< @ingroup LacCommon + * separator used for printing stats to standard output*/ + +#define BORDER "|" +/**< @ingroup LacCommon + * separator used for printing stats to standard output*/ + +/** +***************************************************************************** + * @ingroup LacCommon + * Component state + * + * @description + * This enum is used to indicate the state that the component is in. Its + * purpose is to prevent components from being initialised or shutdown + * incorrectly. + * + *****************************************************************************/ +typedef enum { + LAC_COMP_SHUT_DOWN = 0, + /**< Component in the Shut Down state */ + LAC_COMP_SHUTTING_DOWN, + /**< Component in the Process of Shutting down */ + LAC_COMP_INITIALISING, + /**< Component in the Process of being initialised */ + LAC_COMP_INITIALISED, + /**< Component in the initialised state */ +} lac_comp_state_t; + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro checks if a parameter is NULL + * + * @param[in] param Parameter + * + * @return CPA_STATUS_INVALID_PARAM Parameter is NULL + * @return void Parameter is not NULL + ******************************************************************************/ +#define LAC_CHECK_NULL_PARAM(param) \ + do { \ + if (NULL == (param)) { \ + return CPA_STATUS_INVALID_PARAM; \ + } \ + } while (0) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro checks if a parameter is within a specified range + * + * @param[in] param Parameter + * @param[in] min Parameter must be greater than OR equal to + *min + * @param[in] max Parameter must be less than max + * + * @return CPA_STATUS_INVALID_PARAM Parameter is outside range + * @return void Parameter is within range + ******************************************************************************/ +#define LAC_CHECK_PARAM_RANGE(param, min, max) \ + do { \ + if (((param) < (min)) || ((param) >= (max))) { \ + return CPA_STATUS_INVALID_PARAM; \ + } \ + } while (0) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This checks if a param is 8 byte aligned. + * + ******************************************************************************/ +#define LAC_CHECK_8_BYTE_ALIGNMENT(param) \ + do { \ + if ((Cpa64U)param % 8 != 0) { \ + return CPA_STATUS_INVALID_PARAM; \ + } \ + } while (0) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This checks if a param is 64 byte aligned. + * + ******************************************************************************/ +#define LAC_CHECK_64_BYTE_ALIGNMENT(param) \ + do { \ + if ((LAC_ARCH_UINT)param % 64 != 0) { \ + return CPA_STATUS_INVALID_PARAM; \ + } \ + } while (0) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro returns the size of the buffer list structure given the + * number of elements in the buffer list - note: only the sizeof the + * buffer list structure is returned. + * + * @param[in] numBuffers The number of flatbuffers in a buffer list + * + * @return size of the buffer list structure + ******************************************************************************/ +#define LAC_BUFFER_LIST_SIZE_GET(numBuffers) \ + (sizeof(CpaBufferList) + (numBuffers * sizeof(CpaFlatBuffer))) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro checks that a flatbuffer is valid i.e. that it is not + * null and the data it points to is not null + * + * @param[in] pFlatBuffer Pointer to flatbuffer + * + * @return CPA_STATUS_INVALID_PARAM Invalid flatbuffer pointer + * @return void flatbuffer is ok + ******************************************************************************/ +#define LAC_CHECK_FLAT_BUFFER(pFlatBuffer) \ + do { \ + LAC_CHECK_NULL_PARAM((pFlatBuffer)); \ + LAC_CHECK_NULL_PARAM((pFlatBuffer)->pData); \ + } while (0) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro verifies that the status is ok i.e. equal to CPA_STATUS_SUCCESS + * + * @param[in] status status we are checking + * + * @return void status is ok (CPA_STATUS_SUCCESS) + * @return status The value in the status parameter is an error one + * + ******************************************************************************/ +#define LAC_CHECK_STATUS(status) \ + do { \ + if (CPA_STATUS_SUCCESS != (status)) { \ + return status; \ + } \ + } while (0) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro verifies that the Instance Handle is valid. + * + * @param[in] instanceHandle Instance Handle + * + * @return CPA_STATUS_INVALID_PARAM Parameter is NULL + * @return void Parameter is not NULL + * + ******************************************************************************/ +#define LAC_CHECK_INSTANCE_HANDLE(instanceHandle) \ + do { \ + if (NULL == (instanceHandle)) { \ + return CPA_STATUS_INVALID_PARAM; \ + } \ + } while (0) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro copies a string from one location to another + * + * @param[out] pDestinationBuffer Pointer to destination buffer + * @param[in] pSource Pointer to source buffer + * + ******************************************************************************/ +#define LAC_COPY_STRING(pDestinationBuffer, pSource) \ + do { \ + memcpy(pDestinationBuffer, pSource, (sizeof(pSource) - 1)); \ + pDestinationBuffer[(sizeof(pSource) - 1)] = '\0'; \ + } while (0) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro fills a memory zone with ZEROES + * + * @param[in] pBuffer Pointer to buffer + * @param[in] count Buffer length + * + * @return void + * + ******************************************************************************/ +#define LAC_OS_BZERO(pBuffer, count) memset(pBuffer, 0, count); + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro calculates the position of the given member in a struct + * Only for use on a struct where all members are of equal size to map + * the struct member position to an array index + * + * @param[in] structType the struct + * @param[in] member the member of the given struct + * + ******************************************************************************/ +#define LAC_IDX_OF(structType, member) \ + (offsetof(structType, member) / sizeof(((structType *)0)->member)) + +/* +******************************************************************************** +* Alignment, Bid define and Bit Operation Macros +******************************************************************************** +*/ + +#define LAC_BIT31_SET 0x80000000 /**< bit 31 == 1 */ +#define LAC_BIT7_SET 0x80 /**< bit 7 == 1 */ +#define LAC_BIT6_SET 0x40 /**< bit 6 == 1 */ +#define LAC_BIT5_SET 0x20 /**< bit 5 == 1 */ +#define LAC_BIT4_SET 0x10 /**< bit 4 == 1 */ +#define LAC_BIT3_SET 0x08 /**< bit 3 == 1 */ +#define LAC_BIT2_SET 0x04 /**< bit 2 == 1 */ +#define LAC_BIT1_SET 0x02 /**< bit 1 == 1 */ +#define LAC_BIT0_SET 0x01 /**< bit 0 == 1 */ + +#define LAC_NUM_BITS_IN_BYTE (8) +/**< @ingroup LacCommon + * Number of bits in a byte */ + +#define LAC_LONG_WORD_IN_BYTES (4) +/**< @ingroup LacCommon + * Number of bytes in an IA word */ + +#define LAC_QUAD_WORD_IN_BYTES (8) +/**< @ingroup LacCommon + * Number of bytes in a QUAD word */ + +#define LAC_QAT_MAX_MSG_SZ_LW (32) +/**< @ingroup LacCommon + * Maximum size in Long Words for a QAT message */ + +/** +***************************************************************************** + * @ingroup LacCommon + * Alignment shift requirements of a buffer. + * + * @description + * This enum is used to indicate the alignment shift of a buffer. + * All alignments are to power of 2 + * + *****************************************************************************/ +typedef enum lac_aligment_shift_s { + LAC_NO_ALIGNMENT_SHIFT = 0, + /**< No alignment shift (to a power of 2)*/ + LAC_8BYTE_ALIGNMENT_SHIFT = 3, + /**< 8 byte alignment shift (to a power of 2)*/ + LAC_16BYTE_ALIGNMENT_SHIFT = 4, + /**< 16 byte alignment shift (to a power of 2)*/ + LAC_64BYTE_ALIGNMENT_SHIFT = 6, + /**< 64 byte alignment shift (to a power of 2)*/ + LAC_4KBYTE_ALIGNMENT_SHIFT = 12, + /**< 4k byte alignment shift (to a power of 2)*/ +} lac_aligment_shift_t; + +/** +***************************************************************************** + * @ingroup LacCommon + * Alignment of a buffer. + * + * @description + * This enum is used to indicate the alignment requirements of a buffer. + * + *****************************************************************************/ +typedef enum lac_aligment_s { + LAC_NO_ALIGNMENT = 0, + /**< No alignment */ + LAC_1BYTE_ALIGNMENT = 1, + /**< 1 byte alignment */ + LAC_8BYTE_ALIGNMENT = 8, + /**< 8 byte alignment*/ + LAC_64BYTE_ALIGNMENT = 64, + /**< 64 byte alignment*/ + LAC_4KBYTE_ALIGNMENT = 4096, + /**< 4k byte alignment */ +} lac_aligment_t; + +/** +***************************************************************************** + * @ingroup LacCommon + * Size of a buffer. + * + * @description + * This enum is used to indicate the required size. + * The buffer must be a multiple of the required size. + * + *****************************************************************************/ +typedef enum lac_expected_size_s { + LAC_NO_LENGTH_REQUIREMENTS = 0, + /**< No requirement for size */ + LAC_4KBYTE_MULTIPLE_REQUIRED = 4096, + /**< 4k multiple requirement for size */ +} lac_expected_size_t; + +#define LAC_OPTIMAL_ALIGNMENT_SHIFT LAC_64BYTE_ALIGNMENT_SHIFT +/**< @ingroup LacCommon + * optimal alignment to a power of 2 */ + +#define LAC_SHIFT_8 (1 << LAC_8BYTE_ALIGNMENT_SHIFT) +/**< shift by 8 bits */ +#define LAC_SHIFT_24 \ + ((1 << LAC_8BYTE_ALIGNMENT_SHIFT) + (1 << LAC_16BYTE_ALIGNMENT_SHIFT)) +/**< shift by 24 bits */ + +#define LAC_MAX_16_BIT_VALUE ((1 << 16) - 1) +/**< @ingroup LacCommon + * maximum value a 16 bit type can hold */ + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro can be used to avoid an unused variable warning from the + * compiler + * + * @param[in] variable unused variable + * + ******************************************************************************/ +#define LAC_UNUSED_VARIABLE(x) (void)(x) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro checks if an address is aligned to the specified power of 2 + * Returns 0 if alignment is ok, or non-zero otherwise + * + * @param[in] address the address we are checking + * + * @param[in] alignment the byte alignment to check (specified as power of 2) + * + ******************************************************************************/ +#define LAC_ADDRESS_ALIGNED(address, alignment) \ + (!((LAC_ARCH_UINT)(address) & ((1 << (alignment)) - 1))) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro rounds up a number to a be a multiple of the alignment when + * the alignment is a power of 2. + * + * @param[in] num Number + * @param[in] align Alignment (must be a power of 2) + * + ******************************************************************************/ +#define LAC_ALIGN_POW2_ROUNDUP(num, align) (((num) + (align)-1) & ~((align)-1)) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro generates a bit mask to select a particular bit + * + * @param[in] bitPos Bit position to select + * + ******************************************************************************/ +#define LAC_BIT(bitPos) (0x1 << (bitPos)) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro converts a size in bits to the equivalent size in bytes, + * using a bit shift to divide by 8 + * + * @param[in] x size in bits + * + ******************************************************************************/ +#define LAC_BITS_TO_BYTES(x) ((x) >> 3) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro converts a size in bytes to the equivalent size in bits, + * using a bit shift to multiply by 8 + * + * @param[in] x size in bytes + * + ******************************************************************************/ +#define LAC_BYTES_TO_BITS(x) ((x) << 3) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro converts a size in bytes to the equivalent size in longwords, + * using a bit shift to divide by 4 + * + * @param[in] x size in bytes + * + ******************************************************************************/ +#define LAC_BYTES_TO_LONGWORDS(x) ((x) >> 2) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro converts a size in longwords to the equivalent size in bytes, + * using a bit shift to multiply by 4 + * + * @param[in] x size in long words + * + ******************************************************************************/ +#define LAC_LONGWORDS_TO_BYTES(x) ((x) << 2) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro converts a size in bytes to the equivalent size in quadwords, + * using a bit shift to divide by 8 + * + * @param[in] x size in bytes + * + ******************************************************************************/ +#define LAC_BYTES_TO_QUADWORDS(x) (((x) >> 3) + (((x) % 8) ? 1 : 0)) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro converts a size in quadwords to the equivalent size in bytes, + * using a bit shift to multiply by 8 + * + * @param[in] x size in quad words + * + ******************************************************************************/ +#define LAC_QUADWORDS_TO_BYTES(x) ((x) << 3) + + +/******************************************************************************/ + +/* +******************************************************************************* +* Mutex Macros +******************************************************************************* +*/ + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro tries to acquire a mutex and returns the status + * + * @param[in] pLock Pointer to Lock + * @param[in] timeout Timeout + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_RESOURCE Error with Mutex + ******************************************************************************/ +#define LAC_LOCK_MUTEX(pLock, timeout) \ + ((CPA_STATUS_SUCCESS != qatUtilsMutexLock((pLock), (timeout))) ? \ + CPA_STATUS_RESOURCE : \ + CPA_STATUS_SUCCESS) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro unlocks a mutex and returns the status + * + * @param[in] pLock Pointer to Lock + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_RESOURCE Error with Mutex + ******************************************************************************/ +#define LAC_UNLOCK_MUTEX(pLock) \ + ((CPA_STATUS_SUCCESS != qatUtilsMutexUnlock((pLock))) ? \ + CPA_STATUS_RESOURCE : \ + CPA_STATUS_SUCCESS) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro initialises a mutex and returns the status + * + * @param[in] pLock Pointer to Lock + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_RESOURCE Error with Mutex + ******************************************************************************/ +#define LAC_INIT_MUTEX(pLock) \ + ((CPA_STATUS_SUCCESS != qatUtilsMutexInit((pLock))) ? \ + CPA_STATUS_RESOURCE : \ + CPA_STATUS_SUCCESS) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro destroys a mutex and returns the status + * + * @param[in] pLock Pointer to Lock + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_RESOURCE Error with Mutex + ******************************************************************************/ +#define LAC_DESTROY_MUTEX(pLock) \ + ((CPA_STATUS_SUCCESS != qatUtilsMutexDestroy((pLock))) ? \ + CPA_STATUS_RESOURCE : \ + CPA_STATUS_SUCCESS) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro calls a trylock on a mutex + * + * @param[in] pLock Pointer to Lock + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_RESOURCE Error with Mutex + ******************************************************************************/ +#define LAC_TRYLOCK_MUTEX(pLock) \ + ((CPA_STATUS_SUCCESS != \ + qatUtilsMutexTryLock((pLock), QAT_UTILS_WAIT_NONE)) ? \ + CPA_STATUS_RESOURCE : \ + CPA_STATUS_SUCCESS) + +/* +******************************************************************************* +* Semaphore Macros +******************************************************************************* +*/ + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro waits on a semaphore and returns the status + * + * @param[in] sid The semaphore + * @param[in] timeout Timeout + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_RESOURCE Error with semaphore + ******************************************************************************/ +#define LAC_WAIT_SEMAPHORE(sid, timeout) \ + ((CPA_STATUS_SUCCESS != qatUtilsSemaphoreWait(&sid, (timeout))) ? \ + CPA_STATUS_RESOURCE : \ + CPA_STATUS_SUCCESS) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro checks a semaphore and returns the status + * + * @param[in] sid The semaphore + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_RESOURCE Error with semaphore + ******************************************************************************/ +#define LAC_CHECK_SEMAPHORE(sid) \ + ((CPA_STATUS_SUCCESS != qatUtilsSemaphoreTryWait(&sid)) ? \ + CPA_STATUS_RETRY : \ + CPA_STATUS_SUCCESS) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro post a semaphore and returns the status + * + * @param[in] sid The semaphore + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_RESOURCE Error with semaphore + ******************************************************************************/ +#define LAC_POST_SEMAPHORE(sid) \ + ((CPA_STATUS_SUCCESS != qatUtilsSemaphorePost(&sid)) ? \ + CPA_STATUS_RESOURCE : \ + CPA_STATUS_SUCCESS) +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro initialises a semaphore and returns the status + * + * @param[in] sid The semaphore + * @param[in] semValue Initial semaphore value + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_RESOURCE Error with semaphore + ******************************************************************************/ +#define LAC_INIT_SEMAPHORE(sid, semValue) \ + ((CPA_STATUS_SUCCESS != qatUtilsSemaphoreInit(&sid, semValue)) ? \ + CPA_STATUS_RESOURCE : \ + CPA_STATUS_SUCCESS) + +/** + ******************************************************************************* + * @ingroup LacCommon + * This macro destroys a semaphore and returns the status + * + * @param[in] sid The semaphore + * + * @retval CPA_STATUS_SUCCESS Function executed successfully. + * @retval CPA_STATUS_RESOURCE Error with semaphore + ******************************************************************************/ +#define LAC_DESTROY_SEMAPHORE(sid) \ + ((CPA_STATUS_SUCCESS != qatUtilsSemaphoreDestroy(&sid)) ? \ + CPA_STATUS_RESOURCE : \ + CPA_STATUS_SUCCESS) + +/* +******************************************************************************* +* Spinlock Macros +******************************************************************************* +*/ +typedef struct mtx *lac_lock_t; +#define LAC_SPINLOCK_INIT(lock) \ + ((CPA_STATUS_SUCCESS != qatUtilsLockInit(lock)) ? \ + CPA_STATUS_RESOURCE : \ + CPA_STATUS_SUCCESS) +#define LAC_SPINLOCK(lock) \ + ({ \ + (void)qatUtilsLock(lock); \ + CPA_STATUS_SUCCESS; \ + }) +#define LAC_SPINUNLOCK(lock) \ + ({ \ + (void)qatUtilsUnlock(lock); \ + CPA_STATUS_SUCCESS; \ + }) +#define LAC_SPINLOCK_DESTROY(lock) \ + ({ \ + (void)qatUtilsLockDestroy(lock); \ + CPA_STATUS_SUCCESS; \ + }) + +#define LAC_CONST_PTR_CAST(castee) ((void *)(LAC_ARCH_UINT)(castee)) +#define LAC_CONST_VOLATILE_PTR_CAST(castee) ((void *)(LAC_ARCH_UINT)(castee)) + +/* Type of ring */ +#define SAL_RING_TYPE_NONE 0 +#define SAL_RING_TYPE_A_SYM_HI 1 +#define SAL_RING_TYPE_A_SYM_LO 2 +#define SAL_RING_TYPE_A_ASYM 3 +#define SAL_RING_TYPE_B_SYM_HI 4 +#define SAL_RING_TYPE_B_SYM_LO 5 +#define SAL_RING_TYPE_B_ASYM 6 +#define SAL_RING_TYPE_DC 7 +#define SAL_RING_TYPE_ADMIN 8 +#define SAL_RING_TYPE_TRNG 9 + +/* Maps Ring Service to generic service type */ +static inline icp_adf_ringInfoService_t +lac_getRingType(int type) +{ + switch (type) { + case SAL_RING_TYPE_NONE: + return ICP_ADF_RING_SERVICE_0; + case SAL_RING_TYPE_A_SYM_HI: + return ICP_ADF_RING_SERVICE_1; + case SAL_RING_TYPE_A_SYM_LO: + return ICP_ADF_RING_SERVICE_2; + case SAL_RING_TYPE_A_ASYM: + return ICP_ADF_RING_SERVICE_3; + case SAL_RING_TYPE_B_SYM_HI: + return ICP_ADF_RING_SERVICE_4; + case SAL_RING_TYPE_B_SYM_LO: + return ICP_ADF_RING_SERVICE_5; + case SAL_RING_TYPE_B_ASYM: + return ICP_ADF_RING_SERVICE_6; + case SAL_RING_TYPE_DC: + return ICP_ADF_RING_SERVICE_7; + case SAL_RING_TYPE_ADMIN: + return ICP_ADF_RING_SERVICE_8; + case SAL_RING_TYPE_TRNG: + return ICP_ADF_RING_SERVICE_9; + default: + return ICP_ADF_RING_SERVICE_0; + } + return ICP_ADF_RING_SERVICE_0; +} + +/* Maps generic service type to Ring Service type */ +static inline int +lac_getServiceType(icp_adf_ringInfoService_t type) +{ + switch (type) { + case ICP_ADF_RING_SERVICE_0: + return SAL_RING_TYPE_NONE; + case ICP_ADF_RING_SERVICE_1: + return SAL_RING_TYPE_A_SYM_HI; + case ICP_ADF_RING_SERVICE_2: + return SAL_RING_TYPE_A_SYM_LO; + case ICP_ADF_RING_SERVICE_3: + return SAL_RING_TYPE_A_ASYM; + case ICP_ADF_RING_SERVICE_4: + return SAL_RING_TYPE_B_SYM_HI; + case ICP_ADF_RING_SERVICE_5: + return SAL_RING_TYPE_B_SYM_LO; + case ICP_ADF_RING_SERVICE_6: + return SAL_RING_TYPE_B_ASYM; + case ICP_ADF_RING_SERVICE_7: + return SAL_RING_TYPE_DC; + case ICP_ADF_RING_SERVICE_8: + return SAL_RING_TYPE_ADMIN; + default: + return SAL_RING_TYPE_NONE; + } + return SAL_RING_TYPE_NONE; +} + +#endif /* LAC_COMMON_H */ diff --git a/sys/dev/qat/qat_api/common/include/lac_hooks.h b/sys/dev/qat/qat_api/common/include/lac_hooks.h new file mode 100644 index 000000000000..7018b77a480e --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_hooks.h @@ -0,0 +1,234 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ******************************************************************************* + * @file lac_hooks.h + * + * @defgroup LacHooks Hooks + * + * @ingroup LacCommon + * + * Component Init/Shutdown functions. These are: + * - an init function which is called during the intialisation sequence, + * - a shutdown function which is called by the overall shutdown function, + * + ******************************************************************************/ + +#ifndef LAC_HOOKS_H +#define LAC_HOOKS_H + +/* +******************************************************************************** +* Include public/global header files +******************************************************************************** +*/ + +#include "cpa.h" + +/* +******************************************************************************** +* Include private header files +******************************************************************************** +*/ + +/******************************************************************************/ + +/** + ******************************************************************************* + * @ingroup LacHooks + * This function initialises the Large Number (ModExp and ModInv) module + * + * @description + * This function clears the Large Number statistics + * + * @param[in] instanceHandle + * + ******************************************************************************/ +CpaStatus LacLn_Init(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacHooks + * This function frees statistics array for Large Number module + * + * @description + * This function frees statistics array for Large Number module + * + * @param[in] instanceHandle + * + ******************************************************************************/ +void LacLn_StatsFree(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacHooks + * This function initialises the Prime module + * + * @description + * This function clears the Prime statistics + * + * @param[in] instanceHandle + * + ******************************************************************************/ +CpaStatus LacPrime_Init(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacHooks + * This function frees the Prime module statistics array + * + * @description + * This function frees the Prime module statistics array + * + * @param[in] instanceHandle + * + ******************************************************************************/ +void LacPrime_StatsFree(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacHooks + * This function initialises the DSA module + * + * @param[in] instanceHandle + * + * @description + * This function clears the DSA statistics + * + ******************************************************************************/ +CpaStatus LacDsa_Init(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacHooks + * This function frees the DSA module statistics array + * + * @param[in] instanceHandle + * + * @description + * This function frees the DSA statistics array + * + ******************************************************************************/ +void LacDsa_StatsFree(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacHooks + * This function initialises the Diffie Hellmann module + * + * @description + * This function initialises the Diffie Hellman statistics + * + * @param[in] instanceHandle + * + ******************************************************************************/ +CpaStatus LacDh_Init(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacHooks + * This function frees the Diffie Hellmann module statistics + * + * @description + * This function frees the Diffie Hellmann module statistics + * + * @param[in] instanceHandle + * + ******************************************************************************/ +void LacDh_StatsFree(CpaInstanceHandle instanceHandle); + +/** + ****************************************************************************** + * @ingroup LacSymKey + * This function registers the callback handlers to SSL/TLS and MGF, + * allocates resources that are needed for the component and clears + * the stats. + * + * @param[in] instanceHandle + * + * @retval CPA_STATUS_SUCCESS Status Success + * @retval CPA_STATUS_FAIL General failure + * @retval CPA_STATUS_RESOURCE Resource allocation failure + * + *****************************************************************************/ +CpaStatus LacSymKey_Init(CpaInstanceHandle instanceHandle); + +/** + ****************************************************************************** + * @ingroup LacSymKey + * This function frees up resources obtained by the key gen component + * and clears the stats + * + * @param[in] instanceHandle + * + * @retval CPA_STATUS_SUCCESS Status Success + * + *****************************************************************************/ +CpaStatus LacSymKey_Shutdown(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacHooks + * This function initialises the RSA module + * + * @description + * This function clears the RSA statistics + * + * @param[in] instanceHandle + * + ******************************************************************************/ +CpaStatus LacRsa_Init(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacHooks + * This function frees the RSA module statistics + * + * @description + * This function frees the RSA module statistics + * + * @param[in] instanceHandle + * + ******************************************************************************/ +void LacRsa_StatsFree(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacHooks + * This function initialises the EC module + * + * @description + * This function clears the EC statistics + * + * @param[in] instanceHandle + * + ******************************************************************************/ +CpaStatus LacEc_Init(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacHooks + * This function frees the EC module stats array + * + * @description + * This function frees the EC module stats array + * + * @param[in] instanceHandle + * + ******************************************************************************/ +void LacEc_StatsFree(CpaInstanceHandle instanceHandle); + +/** +******************************************************************************* + * @ingroup LacSymNrbg + * Initialise the NRBG module + * + * @description + * This function registers NRBG callback handlers. + * + * + *****************************************************************************/ +void LacSymNrbg_Init(void); + +#endif /* LAC_HOOKS_H */ diff --git a/sys/dev/qat/qat_api/common/include/lac_list.h b/sys/dev/qat/qat_api/common/include/lac_list.h new file mode 100644 index 000000000000..2af91df155c6 --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_list.h @@ -0,0 +1,137 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file lac_list.h + * + * @defgroup SalList + * + * @ingroup SalCtrl + * + * List structure and list functions. + * + ***************************************************************************/ + +#ifndef LAC_LIST_H +#define LAC_LIST_H + +/** + ***************************************************************************** + * @ingroup SalList + * + * @description + * List structure + * + *****************************************************************************/ +typedef struct sal_list_s { + + struct sal_list_s *next; + void *pObj; + +} sal_list_t; + +/** +******************************************************************************* + * @ingroup SalList + * Add a structure to tail of a list. + * + * @description + * Adds pObj to the tail of list (if it exists). Allocates and sets a + * new sal_list_t structure. + * + * @param[in] list Pointer to the head pointer of the list. + * Can be NULL if no elements yet in list. + * @param[in/out] tail Pointer to tail pointer of the list. + * Can be NULL if no elements yet in list. + * Is updated by the function to point to +*tail + * of list if pObj has been successfully +*added. + * @param[in] pObj Pointer to structure to add to tail of + * the list. + * @retval status + * + *****************************************************************************/ +CpaStatus SalList_add(sal_list_t **list, sal_list_t **tail, void *pObj); + +/** +******************************************************************************* + * @ingroup SalList + * Delete an element from the list. + * + * @description + * Delete an element from the list. + * + * @param[in/out] head_list Pointer to the head pointer of the list. + * Can be NULL if no elements yet in list. + * Is updated by the function + * to point to list->next if head_list is +*list. + * @param[in/out] pre_list Pointer to the previous pointer of the +*list. + * Can be NULL if no elements yet in list. + * (*pre_list)->next is updated + * by the function to point to list->next + * @param[in] list Pointer to list. + * + *****************************************************************************/ +void +SalList_del(sal_list_t **head_list, sal_list_t **pre_list, sal_list_t *list); + +/** +******************************************************************************* + * @ingroup SalList + * Returns pObj element in list structure. + * + * @description + * Returns pObj associated with sal_list_t structure. + * + * @param[in] list Pointer to list element. + * @retval void* pObj member of list structure. + * + *****************************************************************************/ +void *SalList_getObject(sal_list_t *list); + +/** +******************************************************************************* + * @ingroup SalList + * Set pObj to be NULL in the list. + * + * @description + * Set pObj of a element in the list to be NULL. + * + * @param[in] list Pointer to list element. + * + *****************************************************************************/ +void SalList_delObject(sal_list_t **list); + +/** +******************************************************************************* + * @ingroup SalList + * Returns next element in list structure. + * + * @description + * Returns next associated with sal_list_t structure. + * + * @param[in] list Pointer to list element. + * @retval void* next member of list structure. + * + *****************************************************************************/ +void *SalList_next(sal_list_t *); + +/** +******************************************************************************* + * @ingroup SalList + * Frees memory associated with list structure. + * + * @description + * Frees memory associated with list structure and the Obj pointed to by + * the list. + * + * @param[in] list Pointer to list. + * + *****************************************************************************/ +void SalList_free(sal_list_t **); + +#endif diff --git a/sys/dev/qat/qat_api/common/include/lac_log.h b/sys/dev/qat/qat_api/common/include/lac_log.h new file mode 100644 index 000000000000..2593c7b54963 --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_log.h @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_log.h + * + * @defgroup LacLog Log + * + * @ingroup LacCommon + * + * Logging Macros. These macros also log the function name they are called in. + * + ***************************************************************************/ + +/***************************************************************************/ + +#ifndef LAC_LOG_H +#define LAC_LOG_H + +/*************************************************************************** + * Include public/global header files + ***************************************************************************/ +#include "cpa.h" +#include "lac_common.h" +#include "icp_accel_devices.h" + +#define LAC_INVALID_PARAM_LOG_(log, args...) \ + QAT_UTILS_LOG("[error] %s() - : Invalid API Param - " log "\n", \ + __func__, \ + ##args) + +#define LAC_INVALID_PARAM_LOG(log) LAC_INVALID_PARAM_LOG_(log) + +#define LAC_INVALID_PARAM_LOG1(log, param1) LAC_INVALID_PARAM_LOG_(log, param1) + +#define LAC_INVALID_PARAM_LOG2(log, param1, param2) \ + LAC_INVALID_PARAM_LOG_(log, param1, param2) + +#define LAC_UNSUPPORTED_PARAM_LOG(log) \ + QAT_UTILS_LOG("%s() - : UnSupported API Param - " log "\n", __func__) + +#define LAC_LOG_ERROR(log) QAT_UTILS_LOG("%s() - : " log "\n", __func__) + +#endif /* LAC_LOG_H */ diff --git a/sys/dev/qat/qat_api/common/include/lac_mem.h b/sys/dev/qat/qat_api/common/include/lac_mem.h new file mode 100644 index 000000000000..39be4d9ba651 --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_mem.h @@ -0,0 +1,577 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file lac_mem.h + * + * @defgroup LacMem Memory + * + * @ingroup LacCommon + * + * Memory re-sizing functions and memory accessor macros. + * + ***************************************************************************/ + +#ifndef LAC_MEM_H +#define LAC_MEM_H + +/*************************************************************************** + * Include header files + ***************************************************************************/ +#include "cpa.h" +#include "qat_utils.h" +#include "lac_common.h" + +/** + ******************************************************************************* + * @ingroup LacMem + * These macros are used to Endian swap variables from IA to QAT. + * + * @param[out] x The variable to be swapped. + * + * @retval none + ******************************************************************************/ +#if (BYTE_ORDER == LITTLE_ENDIAN) +#define LAC_MEM_WR_64(x) QAT_UTILS_HOST_TO_NW_64(x) +#define LAC_MEM_WR_32(x) QAT_UTILS_HOST_TO_NW_32(x) +#define LAC_MEM_WR_16(x) QAT_UTILS_HOST_TO_NW_16(x) +#define LAC_MEM_RD_64(x) QAT_UTILS_NW_TO_HOST_64(x) +#define LAC_MEM_RD_32(x) QAT_UTILS_NW_TO_HOST_32(x) +#define LAC_MEM_RD_16(x) QAT_UTILS_NW_TO_HOST_16(x) +#else +#define LAC_MEM_WR_64(x) (x) +#define LAC_MEM_WR_32(x) (x) +#define LAC_MEM_WR_16(x) (x) +#define LAC_MEM_RD_64(x) (x) +#define LAC_MEM_RD_32(x) (x) +#define LAC_MEM_RD_16(x) (x) +#endif + +/* +******************************************************************************* +* Shared Memory Macros (memory accessible by Acceleration Engines, e.g. QAT) +******************************************************************************* +*/ + +/** + ******************************************************************************* + * @ingroup LacMem + * This macro can be used to write to a variable that will be read by the + * QAT. The macro will automatically detect the size of the target variable and + * will select the correct method for performing the write. The data is cast to + * the type of the field that it will be written to. + * This macro swaps data if required. + * + * @param[out] var The variable to be written. Can be a field of a struct. + * + * @param[in] data The value to be written. Will be cast to the size of the + * target. + * + * @retval none + ******************************************************************************/ +#define LAC_MEM_SHARED_WRITE_SWAP(var, data) \ + do { \ + switch (sizeof(var)) { \ + case 1: \ + (var) = (Cpa8U)(data); \ + break; \ + case 2: \ + (var) = (Cpa16U)(data); \ + (var) = LAC_MEM_WR_16(((Cpa16U)var)); \ + break; \ + case 4: \ + (var) = (Cpa32U)(data); \ + (var) = LAC_MEM_WR_32(((Cpa32U)var)); \ + break; \ + case 8: \ + (var) = (Cpa64U)(data); \ + (var) = LAC_MEM_WR_64(((Cpa64U)var)); \ + break; \ + default: \ + break; \ + } \ + } while (0) + +/** + ******************************************************************************* + * @ingroup LacMem + * This macro can be used to read a variable that was written by the QAT. + * The macro will automatically detect the size of the data to be read and will + * select the correct method for performing the read. The value read from the + * variable is cast to the size of the data type it will be stored in. + * This macro swaps data if required. + * + * @param[in] var The variable to be read. Can be a field of a struct. + * + * @param[out] data The variable to hold the result of the read. Data read + * will be cast to the size of this variable + * + * @retval none + ******************************************************************************/ +#define LAC_MEM_SHARED_READ_SWAP(var, data) \ + do { \ + switch (sizeof(var)) { \ + case 1: \ + (data) = (var); \ + break; \ + case 2: \ + (data) = LAC_MEM_RD_16(((Cpa16U)var)); \ + break; \ + case 4: \ + (data) = LAC_MEM_RD_32(((Cpa32U)var)); \ + break; \ + case 8: \ + (data) = LAC_MEM_RD_64(((Cpa64U)var)); \ + break; \ + default: \ + break; \ + } \ + } while (0) + +/** + ******************************************************************************* + * @ingroup LacMem + * This macro can be used to write a pointer to a QAT request. The fields + * for pointers in the QAT request and response messages are always 64 bits + * + * @param[out] var The variable to be written to. Can be a field of a struct. + * + * @param[in] data The value to be written. Will be cast to size of target + * variable + * + * @retval none + ******************************************************************************/ +/* cast pointer to scalar of same size of the native pointer */ +#define LAC_MEM_SHARED_WRITE_FROM_PTR(var, data) \ + ((var) = (Cpa64U)(LAC_ARCH_UINT)(data)) + +/* Note: any changes to this macro implementation should also be made to the + * similar LAC_MEM_CAST_PTR_TO_UINT64 macro + */ + +/** + ******************************************************************************* + * @ingroup LacMem + * This macro can be used to read a pointer from a QAT response. The fields + * for pointers in the QAT request and response messages are always 64 bits + * + * @param[in] var The variable to be read. Can be a field of a struct. + * + * @param[out] data The variable to hold the result of the read. Data read + * will be cast to the size of this variable + * + * @retval none + ******************************************************************************/ +/* Cast back to native pointer */ +#define LAC_MEM_SHARED_READ_TO_PTR(var, data) \ + ((data) = (void *)(LAC_ARCH_UINT)(var)) + +/** + ******************************************************************************* + * @ingroup LacMem + * This macro safely casts a pointer to a Cpa64U type. + * + * @param[in] pPtr The pointer to be cast. + * + * @retval pointer cast to Cpa64U + ******************************************************************************/ +#define LAC_MEM_CAST_PTR_TO_UINT64(pPtr) ((Cpa64U)(pPtr)) + +/** + ******************************************************************************* + * @ingroup LacMem + * This macro uses an QAT Utils macro to convert from a virtual address to + *a + * physical address for internally allocated memory. + * + * @param[in] pVirtAddr The address to be converted. + * + * @retval The converted physical address + ******************************************************************************/ +#define LAC_OS_VIRT_TO_PHYS_INTERNAL(pVirtAddr) \ + (QAT_UTILS_MMU_VIRT_TO_PHYS(pVirtAddr)) + +/** + ******************************************************************************* + * @ingroup LacMem + * This macro should be called on all externally allocated memory it calls + * SalMem_virt2PhysExternal function which allows a user + * to set the virt2phys function used by an instance. + * Defaults to virt to phys for kernel. + * + * @param[in] genService Generic sal_service_t structure. + * @param[in] pVirtAddr The address to be converted. + * + * @retval The converted physical address + ******************************************************************************/ +#define LAC_OS_VIRT_TO_PHYS_EXTERNAL(genService, pVirtAddr) \ + ((SalMem_virt2PhysExternal(pVirtAddr, &(genService)))) + +/** + ******************************************************************************* + * @ingroup LacMem + * This macro can be used to write an address variable that will be read by + * the QAT. The macro will perform the necessary virt2phys address translation + * This macro is only to be called on memory allocated internally by the driver. + * + * @param[out] var The address variable to write. Can be a field of a struct. + * + * @param[in] pPtr The pointer variable to containing the address to be + * written + * + * @retval none + ******************************************************************************/ +#define LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_INTERNAL(var, pPtr) \ + do { \ + Cpa64U physAddr = 0; \ + physAddr = LAC_MEM_CAST_PTR_TO_UINT64( \ + LAC_OS_VIRT_TO_PHYS_INTERNAL(pPtr)); \ + var = physAddr; \ + } while (0) + +/** + ******************************************************************************* + * @ingroup LacMem + * This macro can be used to write an address variable that will be read by + * the QAT. The macro will perform the necessary virt2phys address translation + * This macro is to be used on memory allocated externally by the user. It calls + * the user supplied virt2phys address translation. + * + * @param[in] pService The pointer to the service + * @param[out] var The address variable to write. Can be a field of a struct + * @param[in] pPtr The pointer variable to containing the address to be + * written + * + * @retval none + ******************************************************************************/ +#define LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL(pService, var, pPtr) \ + do { \ + Cpa64U physAddr = 0; \ + physAddr = LAC_MEM_CAST_PTR_TO_UINT64( \ + LAC_OS_VIRT_TO_PHYS_EXTERNAL(pService, pPtr)); \ + var = physAddr; \ + } while (0) + +/* +******************************************************************************* +* OS Memory Macros +******************************************************************************* +*/ + +/** + ******************************************************************************* + * @ingroup LacMem + * This function and associated macro allocates the memory for the given + * size and stores the address of the memory allocated in the pointer. + * + * @param[out] ppMemAddr address of pointer where address will be stored + * @param[in] sizeBytes the size of the memory to be allocated. + * + * @retval CPA_STATUS_RESOURCE Macro failed to allocate Memory + * @retval CPA_STATUS_SUCCESS Macro executed successfully + * + ******************************************************************************/ +static __inline CpaStatus +LacMem_OsMemAlloc(void **ppMemAddr, Cpa32U sizeBytes) +{ + *ppMemAddr = malloc(sizeBytes, M_QAT, M_WAITOK); + + return CPA_STATUS_SUCCESS; +} + +/** + ******************************************************************************* + * @ingroup LacMem + * This function and associated macro allocates the contiguous + * memory for the given + * size and stores the address of the memory allocated in the pointer. + * + * @param[out] ppMemAddr address of pointer where address will be stored + * @param[in] sizeBytes the size of the memory to be allocated. + * @param[in] alignmentBytes the alignment + * @param[in] node node to allocate from + * + * @retval CPA_STATUS_RESOURCE Macro failed to allocate Memory + * @retval CPA_STATUS_SUCCESS Macro executed successfully + * + ******************************************************************************/ +static __inline CpaStatus +LacMem_OsContigAlignMemAlloc(void **ppMemAddr, + Cpa32U sizeBytes, + Cpa32U alignmentBytes, + Cpa32U node) +{ + if ((alignmentBytes & (alignmentBytes - 1)) != + 0) /* if is not power of 2 */ + { + *ppMemAddr = NULL; + QAT_UTILS_LOG("alignmentBytes MUST be the power of 2\n"); + return CPA_STATUS_INVALID_PARAM; + } + + *ppMemAddr = + qatUtilsMemAllocContiguousNUMA(sizeBytes, node, alignmentBytes); + + if (NULL == *ppMemAddr) { + return CPA_STATUS_RESOURCE; + } + + return CPA_STATUS_SUCCESS; +} + +/** + ******************************************************************************* + * @ingroup LacMem + * Macro from the malloc() function + * + ******************************************************************************/ +#define LAC_OS_MALLOC(sizeBytes) malloc(sizeBytes, M_QAT, M_WAITOK) + +/** + ******************************************************************************* + * @ingroup LacMem + * Macro from the LacMem_OsContigAlignMemAlloc function + * + ******************************************************************************/ +#define LAC_OS_CAMALLOC(ppMemAddr, sizeBytes, alignmentBytes, node) \ + LacMem_OsContigAlignMemAlloc((void *)ppMemAddr, \ + sizeBytes, \ + alignmentBytes, \ + node) + +/** + ******************************************************************************* + * @ingroup LacMem + * Macro for declaration static const unsigned int constant. One provides + * the compilation time computation with the highest bit set in the + * sizeof(TYPE) value. The constant is being put by the linker by default in + * .rodata section + * + * E.g. Statement LAC_DECLARE_HIGHEST_BIT_OF(lac_mem_blk_t) + * results in following entry: + * static const unsigned int highest_bit_of_lac_mem_blk_t = 3 + * + * CAUTION!! + * Macro is prepared only for type names NOT-containing ANY + * special characters. Types as amongst others: + * - void * + * - unsigned long + * - unsigned int + * are strictly forbidden and will result in compilation error. + * Use typedef to provide one-word type name for MACRO's usage. + ******************************************************************************/ +#define LAC_DECLARE_HIGHEST_BIT_OF(TYPE) \ + static const unsigned int highest_bit_of_##TYPE = \ + (sizeof(TYPE) & 0x80000000 ? 31 : (sizeof(TYPE) & 0x40000000 ? 30 : (sizeof(TYPE) & 0x20000000 ? 29 : ( \ + sizeof(TYPE) & 0x10000000 ? 28 : ( \ + sizeof(TYPE) & 0x08000000 ? 27 : ( \ + sizeof(TYPE) & 0x04000000 ? 26 : ( \ + sizeof(TYPE) & 0x02000000 ? 25 : ( \ + sizeof(TYPE) & 0x01000000 ? 24 : ( \ + sizeof(TYPE) & 0x00800000 ? \ + 23 : \ + (sizeof(TYPE) & 0x00400000 ? 22 : ( \ + sizeof( \ + TYPE) & \ + 0x00200000 ? \ + 21 : \ + ( \ + sizeof(TYPE) & 0x00100000 ? 20 : (sizeof(TYPE) & 0x00080000 ? 19 : ( \ + sizeof( \ + TYPE) & \ + 0x00040000 ? \ + 18 : \ + ( \ + sizeof(TYPE) & 0x00020000 ? 17 : ( \ + sizeof(TYPE) & 0x00010000 ? 16 : (sizeof(TYPE) & \ + 0x00008000 ? \ + 15 : \ + (sizeof(TYPE) & 0x00004000 ? 14 : ( \ + sizeof(TYPE) & 0x00002000 ? 13 : \ + ( \ + sizeof(TYPE) & 0x00001000 ? 12 : ( \ + sizeof(TYPE) & 0x00000800 ? 11 : ( \ + sizeof(TYPE) & 0x00000400 ? 10 : \ + ( \ + sizeof(TYPE) & \ + 0x00000200 ? \ + 9 : \ + (sizeof( \ + TYPE) & \ + 0x00000100 ? \ + 8 : \ + (sizeof(TYPE) & 0x00000080 ? 7 : \ + ( \ + sizeof(TYPE) & 0x00000040 ? \ + 6 : \ + ( \ + sizeof(TYPE) & 0x00000020 ? 5 : \ + ( \ + sizeof(TYPE) & 0x00000010 ? 4 : \ + ( \ + sizeof(TYPE) & 0x00000008 ? 3 : \ + ( \ + sizeof(TYPE) & 0x00000004 ? 2 : \ + ( \ + sizeof(TYPE) & 0x00000002 ? 1 : ( \ + sizeof(TYPE) & 0x00000001 ? 0 : 32))))))))))))))))) /*16*/))))))))))))))) /* 31 */ + +/** + ******************************************************************************* + * @ingroup LacMem + * This function and associated macro frees the memory at the given address + * and resets the pointer to NULL + * + * @param[out] ppMemAddr address of pointer where mem address is stored. + * If pointer is NULL, the function will exit silently + * + * @retval void + * + ******************************************************************************/ +static __inline void +LacMem_OsMemFree(void **ppMemAddr) +{ + free(*ppMemAddr, M_QAT); + *ppMemAddr = NULL; +} + +/** + ******************************************************************************* + * @ingroup LacMem + * This function and associated macro frees the contiguous memory at the + * given address and resets the pointer to NULL + * + * @param[out] ppMemAddr address of pointer where mem address is stored. + * If pointer is NULL, the function will exit silently + * + * @retval void + * + ******************************************************************************/ +static __inline void +LacMem_OsContigAlignMemFree(void **ppMemAddr) +{ + if (NULL != *ppMemAddr) { + qatUtilsMemFreeNUMA(*ppMemAddr); + *ppMemAddr = NULL; + } +} + +#define LAC_OS_FREE(pMemAddr) LacMem_OsMemFree((void *)&pMemAddr) + +#define LAC_OS_CAFREE(pMemAddr) LacMem_OsContigAlignMemFree((void *)&pMemAddr) + +/** +******************************************************************************* + * @ingroup LacMem + * Copies user data to a working buffer of the correct size (required by + * PKE services) + * + * @description + * This function produces a correctly sized working buffer from the input + * user buffer. If the original buffer is too small a new buffer shall + * be allocated and memory is copied (left padded with zeros to the +*required + * length). + * + * The returned working buffer is guaranteed to be of the desired size for + * QAT. + * + * When this function is called pInternalMem describes the user_buffer and + * when the function returns pInternalMem describes the working buffer. + * This is because pInternalMem describes the memory that will be sent to + * QAT. + * + * The caller must keep the original buffer pointer. The alllocated buffer +*is + * freed (as necessary) using icp_LacBufferRestore(). + * + * @param[in] instanceHandle Handle to crypto instance so pke_resize mem pool +*can + * be located + * @param[in] pUserBuffer Pointer on the user buffer + * @param[in] userLen length of the user buffer + * @param[in] workingLen length of the working (correctly sized) buffer + * @param[in/out] pInternalMem pointer to boolean if TRUE on input then + * user_buffer is internally allocated memory + * if false then it is externally allocated. + * This value gets updated by the function + * if the returned pointer references internally + * allocated memory. + * + * @return a pointer to the working (correctly sized) buffer or NULL if the + * allocation failed + * + * @note the working length cannot be smaller than the user buffer length + * + * @warning the working buffer may be the same or different from the original + * user buffer; the caller should make no assumptions in this regard + * + * @see icp_LacBufferRestore() + * + ******************************************************************************/ +Cpa8U *icp_LacBufferResize(CpaInstanceHandle instanceHandle, + Cpa8U *pUserBuffer, + Cpa32U userLen, + Cpa32U workingLen, + CpaBoolean *pInternalMemory); + +/** +******************************************************************************* + * @ingroup LacMem + * Restores a user buffer + * + * @description + * This function restores a user buffer and releases its + * corresponding working buffer. The working buffer, assumed to be + * previously obtained using icp_LacBufferResize(), is freed as necessary. + * + * The contents are copied in the process. + * + * @note the working length cannot be smaller than the user buffer length + * + * @param[out] pUserBuffer Pointer on the user buffer + * @param[in] userLen length of the user buffer + * @param[in] pWorkingBuffer Pointer on the working buffer + * @param[in] workingLen working buffer length + * @param[in] copyBuf if set _TRUE the data in the workingBuffer + * will be copied to the userBuffer before the + * workingBuffer is freed. + * + * @return the status of the operation + * + * @see icp_LacBufferResize() + * + ******************************************************************************/ +CpaStatus icp_LacBufferRestore(Cpa8U *pUserBuffer, + Cpa32U userLen, + Cpa8U *pWorkingBuffer, + Cpa32U workingLen, + CpaBoolean copyBuf); + +/** +******************************************************************************* + * @ingroup LacMem + * Uses an instance specific user supplied virt2phys function to convert a + * virtual address to a physical address. + * + * @description + * Uses an instance specific user supplied virt2phys function to convert a + * virtual address to a physical address. A client of QA API can set the + * virt2phys function for an instance by using the + * cpaXxSetAddressTranslation() function. If the client does not set the + * virt2phys function and the instance is in kernel space then OS specific + * virt2phys function will be used. In user space the virt2phys function + * MUST be set by the user. + * + * @param[in] pVirtAddr the virtual addr to be converted + * @param[in] pServiceGen Pointer on the sal_service_t structure + * so client supplied virt2phys function can be + * called. + * + * @return the physical address + * + ******************************************************************************/ +CpaPhysicalAddr SalMem_virt2PhysExternal(void *pVirtAddr, void *pServiceGen); + +#endif /* LAC_MEM_H */ diff --git a/sys/dev/qat/qat_api/common/include/lac_mem_pools.h b/sys/dev/qat/qat_api/common/include/lac_mem_pools.h new file mode 100644 index 000000000000..e66769e3a265 --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_mem_pools.h @@ -0,0 +1,278 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file lac_mem_pools.h + * + * @defgroup LacMemPool Memory Pool Mgmt + * + * @ingroup LacCommon + * + * Memory Pool creation and mgmt functions + * + * @lld_start + * @lld_overview + * This component is designed as a set of utility functions for the + * creation of pre-allocated memory pools. Each pool will be created using OS + * memory with a user specified number of elements, element size and element + * alignment(alignmnet is at byte granularity). + * @lld_dependencies + * These utilities rely on QAT Utils for locking mechanisms and memory + *allocation + * @lld_initialisation + * Pool creation needs to be done by each component. There is no specific + * initialisation required for this feature. + * @lld_module_algorithms + * The following is a diagram of how the memory is layed out for each block + * in a pool. Each element must be aligned on the boundary requested for in the + * create call. In order to hide the management of the pools from the user, + * the memory block data is hidden prior to the + * data pointer. This way it can be accessed easily on a free call with pointer + * arithmatic. The Padding at the start is simply there for alignment and is + * unused in the pools. + * + * ------------------------------------------------------- + * + * |Padding |lac_mem_blk_t | client memory | + * + * @lld_process_context + * @lld_end + ***************************************************************************/ + +/** + ******************************************************************************* + * @ingroup LacMemPool + * + * + ******************************************************************************/ + +/***************************************************************************/ + +#ifndef LAC_MEM_POOLS_H +#define LAC_MEM_POOLS_H + +#include "cpa.h" +#include "lac_common.h" +struct lac_mem_pool_hdr_s; +/**< @ingroup LacMemPool + * This is a forward declaration of the structure type lac_mem_pool_hdr_s */ + +typedef LAC_ARCH_UINT lac_memory_pool_id_t; +/**< @ingroup LacMemPool + * Pool ID type to be used by all clients */ + +/**< @ingroup LacMemPool + * This structure is used to link each memory block in the created pool + * together and contain the necessary information for deletion of the block + */ +typedef struct lac_mem_blk_s { + CpaPhysicalAddr physDataPtr; + /**< physical address of data pointer for client */ + void *pMemAllocPtr; + /**< virtual address of the memory block actually allocated */ + CpaBoolean isInUse; + /**< indicates if the pool item is in use */ + struct lac_mem_blk_s *pNext; + /**< link to next blcok in the pool */ + struct lac_mem_pool_hdr_s *pPoolID; + /**< identifier of the pool that this block was allocated from */ +} lac_mem_blk_t; + +#define LAC_MEM_POOL_VIRT_TO_PHYS(pVirtAddr) \ + (((lac_mem_blk_t *)((LAC_ARCH_UINT)pVirtAddr - sizeof(lac_mem_blk_t))) \ + ->physDataPtr) +/**< @ingroup LacMemPool + * macro for retreiving the physical address of the memory block. */ + +#define LAC_MEM_POOL_INIT_POOL_ID 0 +/**< @ingroup LacMemPool + * macro which defines the valid initialisation value for a pool ID. This is + * used as a level of abstraction for the user of this interface */ + +/** + ******************************************************************************* + * @ingroup LacMemPool + * This function creates a memory pool containing a specified number of + * elements of specific size and byte alignment. This function is not reentrant + * or thread safe and is only intended to be called during initialisation. + * + * @blocking + * Yes + * @reentrant + * No + * @threadSafe + * No + * @param[out] poolID on successful creation of a pool this will + * be the ID used for all subsequent accesses + * @param[in] poolName The name of the memory pool + * @param[in] numElementsInPool number of elements to provision in the pool + * @param[in] blkSizeInBytes size in bytes of each element in the pool + * @param[in] blkAlignmentInBytes byte alignment required for each element + * @param[in] trackMemory track the memory in use by this pool + * @param[in] node node to allocate from + * + * @retval CPA_STATUS_INVALID_PARAM invalid input parameter + * @retval CPA_STATUS_RESOURCE error in provisioning resources + * @retval CPA_STATUS_SUCCESS function executed successfully + * + ******************************************************************************/ +CpaStatus Lac_MemPoolCreate(lac_memory_pool_id_t *poolID, + char *poolName, + unsigned int numElementsInPool, + unsigned int blkSizeInBytes, + unsigned int blkAlignmentInBytes, + CpaBoolean trackMemory, + Cpa32U node); + +/** + ******************************************************************************* + * @ingroup LacMemPool + * This function will destroy the memory pool in it's current state. All memory + * blocks which have been returned to the memory pool will be de-allocated and + * the pool indetifier will be freed and assigned to NULL. It is the + * responsibility of the pool creators to return all memory before a destroy or + * memory will be leaked. + * + * @blocking + * Yes + * @reentrant + * No + * @threadSafe + * No + + * @param[in] poolID Pointer to the memory pool to destroy + * + ******************************************************************************/ +void Lac_MemPoolDestroy(lac_memory_pool_id_t poolID); + +/** + ******************************************************************************* + * @ingroup LacMemPool + * This function allocates a block from the pool which has been previously + * created. It does not check the validity of the pool Id prior to accessing the + * pool. It is up to the calling code to ensure the value is correct. + * + * @blocking + * Yes + * @reentrant + * Yes + * @threadSafe + * Yes + * @param[in] poolID ID of the pool to allocate memory from + * + * @retval pointer to the memory which has been allocated from the pool + * + ******************************************************************************/ +void *Lac_MemPoolEntryAlloc(lac_memory_pool_id_t poolID); + +/** + ******************************************************************************* + * @ingroup LacMemPool + * This function de-allocates the memory passed in back to the pool from which + * it was allocated. + * + * @blocking + * Yes + * @reentrant + * Yes + * @threadSafe + * Yes + * @param[in] entry memory address of the block to be freed + * + ******************************************************************************/ +void Lac_MemPoolEntryFree(void *entry); + +/** + ******************************************************************************* + * @ingroup LacMemPool + * This function returns the number of available entries in a particular pool + * + * @blocking + * No + * @reentrant + * No + * @threadSafe + * No + * @param[in] poolID ID of the pool + * + * @retval number of elements left for allocation from the pool + * + ******************************************************************************/ +unsigned int Lac_MemPoolAvailableEntries(lac_memory_pool_id_t poolID); + +/** + ******************************************************************************* + * @ingroup LacMemPool + * This function displays the stats associated with the memory pools + * + * @blocking + * No + * @reentrant + * No + * @threadSafe + * No + * + ******************************************************************************/ +void Lac_MemPoolStatsShow(void); + +/** + ******************************************************************************* + * @ingroup LacMemPool + * This function initialises the physical addresses of the symmetric cookie + * + * @blocking + * No + * @reentrant + * No + * @threadSafe + * No + * @param[in] poolID ID of the pool + * + * @retval CPA_STATUS_FAIL function failed + * @retval CPA_STATUS_SUCCESS function executed successfully + * + ******************************************************************************/ +CpaStatus Lac_MemPoolInitSymCookiesPhyAddr(lac_memory_pool_id_t poolID); + +/** + ******************************************************************************* + * @ingroup LacMemPool + * This function populates all PKE requests with instance constant parameters + * + * @blocking + * No + * @reentrant + * No + * @threadSafe + * No + * @param[in] poolID ID of the pool + * @param[in] instanceHandle instanceHandle + * + * @retval CPA_STATUS_FAIL function failed + * @retval CPA_STATUS_SUCCESS function executed successfully + * + ******************************************************************************/ +CpaStatus Lac_MemPoolInitAsymCookies(lac_memory_pool_id_t poolID, + CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup LacMemPool + * This function initialises the physical addresses of the compression cookie + * + * @blocking + * No + * @reentrant + * No + * @threadSafe + * No + * @param[in] poolID ID of the pool + * + * @retval CPA_STATUS_FAIL function failed + * @retval CPA_STATUS_SUCCESS function executed successfully + * + ******************************************************************************/ +CpaStatus Lac_MemPoolInitDcCookiePhyAddr(lac_memory_pool_id_t poolID); + +#endif /*LAC_MEM_POOLS_H*/ diff --git a/sys/dev/qat/qat_api/common/include/lac_module.h b/sys/dev/qat/qat_api/common/include/lac_module.h new file mode 100644 index 000000000000..8fe95c2e4cf5 --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_module.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef __LAC_MODULE_H__ +#define __LAC_MODULE_H__ + +#include "icp_qat_hw.h" + +/* Lac module getter/setter for TUNABLE_INT in lac_module.c */ +icp_qat_hw_auth_mode_t Lac_GetQatHmacMode(void); +void Lac_SetQatHmacMode(const icp_qat_hw_auth_mode_t); + +#endif diff --git a/sys/dev/qat/qat_api/common/include/lac_sal.h b/sys/dev/qat/qat_api/common/include/lac_sal.h new file mode 100644 index 000000000000..0c431dd688e4 --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_sal.h @@ -0,0 +1,498 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file lac_sal.h + * + * @defgroup SalCtrl Service Access Layer Controller + * + * @ingroup SalCtrl + * + * @description + * These functions are the functions to be executed for each state + * of the state machine for each service. + * + *****************************************************************************/ + +#ifndef LAC_SAL_H +#define LAC_SAL_H + +#include "cpa_cy_im.h" + +/** +******************************************************************************* + * @ingroup SalCtrl + * @description + * This function allocates memory for a specific instance type. + * Zeros this memory and sets the generic service section of + * the instance memory. + * + * @context + * This function is called from the generic services init. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] service The type of the service to be created + * (e.g. CRYPTO) + * @param[in] instance_num The logical instance number which will + * run the service + * @param[out] pObj Pointer to specific service instance memory + * @retVal CPA_STATUS_SUCCESS Instance memory successfully allocated + * @retVal CPA_STATUS_RESOURCE Instance memory not successfully allocated + * @retVal CPA_STATUS_FAIL Unsupported service type + * + *****************************************************************************/ +CpaStatus SalCtrl_ServiceCreate(sal_service_type_t service, + Cpa32U instance_num, + sal_service_t **pObj); + +/** +******************************************************************************* + * @ingroup SalCtl + * @description + * This macro goes through the 'list' passed in as a parameter. For each + * element found in the list, it peforms a cast to the type of the element + * given by the 'type' parameter. Finally, it calls the function given by + * the 'function' parameter, passing itself and the device as parameters. + * + * In case of error (i.e. 'function' does not return _SUCCESS or _RETRY) + * processing of the 'list' elements will stop and the status_ret will be + * updated. + * + * In case of _RETRY status_ret will be updated but the 'list' + * will continue to be processed. _RETRY is only expected when + * 'function' is stop. + * + * @context + * This macro is used by both the service and qat event handlers. + * + * @assumptions + * None + * @sideEffects + * None + * + * @param[in] list The list of services or qats as a type of list_t + * @param[in] type It identifies the type of the object inside the + * list: service or qat + * @param[in] device The ADF accelerator handle for the device + * @param[in] function The function pointer to call + * @param[in/out] status_ret If an error occured (i.e. status returned from + * function is not _SUCCESS) then status_ret is + * overwritten with status returned from function. + * + *****************************************************************************/ +#define SAL_FOR_EACH(list, type, device, function, status_ret) \ + do { \ + sal_list_t *curr_element = list; \ + CpaStatus status_temp = CPA_STATUS_SUCCESS; \ + typeof(type) *process = NULL; \ + while (NULL != curr_element) { \ + process = \ + (typeof(type) *)SalList_getObject(curr_element); \ + status_temp = process->function(device, process); \ + if ((CPA_STATUS_SUCCESS != status_temp) && \ + (CPA_STATUS_RETRY != status_temp)) { \ + status_ret = status_temp; \ + break; \ + } else { \ + if (CPA_STATUS_RETRY == status_temp) { \ + status_ret = status_temp; \ + } \ + } \ + curr_element = SalList_next(curr_element); \ + } \ + } while (0) + +/** +******************************************************************************* + * @ingroup SalCtl + * @description + * This macro goes through the 'list' passed in as a parameter. For each + * element found in the list, it peforms a cast to the type of the element + * given by the 'type' parameter. Finally, it checks the state of the + * element and if it is in state 'state_check' then it calls the + * function given by the 'function' parameter, passing itself + * and the device as parameters. + * If the element is not in 'state_check' it returns from the macro. + * + * In case of error (i.e. 'function' does not return _SUCCESS) + * processing of the 'list' elements will continue. + * + * @context + * This macro is used by both the service and qat event handlers. + * + * @assumptions + * None + * @sideEffects + * None + * + * @param[in] list The list of services or qats as a type of list_t + * @param[in] type It identifies the type of the object + * inside the list: service or qat + * @param[in] device The ADF accelerator handle for the device + * @param[in] function The function pointer to call + * @param[in] state_check The state to check for + * + *****************************************************************************/ +#define SAL_FOR_EACH_STATE(list, type, device, function, state_check) \ + do { \ + sal_list_t *curr_element = list; \ + typeof(type) *process = NULL; \ + while (NULL != curr_element) { \ + process = \ + (typeof(type) *)SalList_getObject(curr_element); \ + if (process->state == state_check) { \ + process->function(device, process); \ + } else { \ + break; \ + } \ + curr_element = SalList_next(curr_element); \ + } \ + } while (0) + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to initialize an instance of crypto service. + * It creates a crypto instance's memory pools. It calls ADF to create + * its required transport handles. It calls the sub crypto service init + * functions. Resets the stats. + * + * @context + * This function is called from the SalCtrl_ServiceEventInit function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No (ADF ensures that this function doesn't need to be thread safe) + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] service A crypto instance + * + *************************************************************************/ +CpaStatus SalCtrl_CryptoInit(icp_accel_dev_t *device, sal_service_t *service); + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to start an instance of crypto service. + * It sends the first messages to FW on its crypto instance transport + * handles. For asymmetric crypto it verifies the header on the downloaded + * MMP library. + * + * @context + * This function is called from the SalCtrl_ServiceEventStart function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No (ADF ensures that this function doesn't need to be thread safe) + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] service A crypto instance + * + *************************************************************************/ +CpaStatus SalCtrl_CryptoStart(icp_accel_dev_t *device, sal_service_t *service); + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to stop an instance of crypto service. + * It checks for inflight messages to the FW. If no messages are pending + * it returns success. If messages are pending it returns retry. + * + * @context + * This function is called from the SalCtrl_ServiceEventStop function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No (ADF ensures that this function doesn't need to be thread safe) + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] service A crypto instance + * + *************************************************************************/ +CpaStatus SalCtrl_CryptoStop(icp_accel_dev_t *device, sal_service_t *service); + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to shutdown an instance of crypto service. + * It frees resources allocated at initialisation - e.g. frees the + * memory pools and ADF transport handles. + * + * @context + * This function is called from the SalCtrl_ServiceEventShutdown function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No (ADF ensures that this function doesn't need to be thread safe) + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] service A crypto instance + * + *************************************************************************/ +CpaStatus SalCtrl_CryptoShutdown(icp_accel_dev_t *device, + sal_service_t *service); + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function sets the capability info of crypto instances. + * + * @context + * This function is called from the cpaCyQueryCapabilities and + * LacSymSession_ParamCheck function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No (ADF ensures that this function doesn't need to be thread safe) + * + * @param[in] service A sal_service_t* type + * @param[in] cyCapabilityInfo A CpaCyCapabilitiesInfo* type + * + *************************************************************************/ +void SalCtrl_CyQueryCapabilities(sal_service_t *pGenericService, + CpaCyCapabilitiesInfo *pCapInfo); + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to initialize an instance of compression service. + * It creates a compression instance's memory pools. It calls ADF to create + * its required transport handles. It zeros an instances stats. + * + * @context + * This function is called from the SalCtrl_ServiceEventInit function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No (ADF ensures that this function doesn't need to be thread safe) + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] service A compression instance + * + *************************************************************************/ + +CpaStatus SalCtrl_CompressionInit(icp_accel_dev_t *device, + sal_service_t *service); + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to start an instance of compression service. + * + * @context + * This function is called from the SalCtrl_ServiceEventStart function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No (ADF ensures that this function doesn't need to be thread safe) + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] service A compression instance + * + *************************************************************************/ + +CpaStatus SalCtrl_CompressionStart(icp_accel_dev_t *device, + sal_service_t *service); + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to stop an instance of compression service. + * It checks for inflight messages to the FW. If no messages are pending + * it returns success. If messages are pending it returns retry. + * + * @context + * This function is called from the SalCtrl_ServiceEventStop function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No (ADF ensures that this function doesn't need to be thread safe) + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] service A compression instance + * + *************************************************************************/ + +CpaStatus SalCtrl_CompressionStop(icp_accel_dev_t *device, + sal_service_t *service); + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to shutdown an instance of compression service. + * It frees resources allocated at initialisation - e.g. frees the + * memory pools and ADF transport handles. + * + * @context + * This function is called from the SalCtrl_ServiceEventShutdown function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No (ADF ensures that this function doesn't need to be thread safe) + * + * @param[in] device An icp_accel_dev_t* type + * @param[in] service A compression instance + * + *************************************************************************/ + +CpaStatus SalCtrl_CompressionShutdown(icp_accel_dev_t *device, + sal_service_t *service); + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to get the number of services enabled + * from the config table. + * + * @context + * This function is called from the SalCtrl_QatInit + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No + * + * param[in] device An icp_accel_dev_t* type + * param[in] pEnabledServices pointer to a variable used to store + * the enabled services + * + *************************************************************************/ + +CpaStatus SalCtrl_GetEnabledServices(icp_accel_dev_t *device, + Cpa32U *pEnabledServices); + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to check if a service is enabled + * + * @context + * This function is called from the SalCtrl_QatInit + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * param[in] enabled_services + * param[in] service + * + *************************************************************************/ + +CpaBoolean SalCtrl_IsServiceEnabled(Cpa32U enabled_services, + sal_service_type_t service); + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to check if a service is supported on the device + * The key difference between this and SalCtrl_GetSupportedServices() is + * that the latter treats it as an error if the service is unsupported. + * + * @context + * This can be called anywhere. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * param[in] device + * param[in] service service or services to check + * + *************************************************************************/ +CpaBoolean SalCtrl_IsServiceSupported(icp_accel_dev_t *device, + sal_service_type_t service); + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to check whether enabled services has associated + * hardware capability support + * + * @context + * This functions is called from the SalCtrl_ServiceEventInit function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * param[in] device A pointer to an icp_accel_dev_t + * param[in] enabled_services It is the bitmask for the enabled services + *************************************************************************/ + +CpaStatus SalCtrl_GetSupportedServices(icp_accel_dev_t *device, + Cpa32U enabled_services); + +#endif diff --git a/sys/dev/qat/qat_api/common/include/lac_sal_ctrl.h b/sys/dev/qat/qat_api/common/include/lac_sal_ctrl.h new file mode 100644 index 000000000000..f6c53928edf1 --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_sal_ctrl.h @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file lac_sal_ctrl.h + * + * @ingroup SalCtrl + * + * Functions to register and deregister qat and service controllers with ADF. + * + ***************************************************************************/ + +#ifndef LAC_SAL_CTRL_H +#define LAC_SAL_CTRL_H + +/******************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to check whether the service component + * has been successfully started. + * + * @context + * This function is called from the icp_sal_userStart() function. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + ******************************************************************/ + +CpaStatus SalCtrl_AdfServicesStartedCheck(void); + +/******************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to check whether the user's parameter + * for concurrent request is valid. + * + * @context + * This function is called when crypto or compression is init + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * Yes + * @threadSafe + * Yes + * + ******************************************************************/ +CpaStatus validateConcurrRequest(Cpa32U numConcurrRequests); + +/******************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to register adf services + * + * @context + * This function is called from do_userStart() function + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * Yes + * @threadSafe + * Yes + * + ******************************************************************/ +CpaStatus SalCtrl_AdfServicesRegister(void); + +/******************************************************************* + * @ingroup SalCtrl + * @description + * This function is used to unregister adf services. + * + * @context + * This function is called from do_userStart() function + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * Yes + * @threadSafe + * Yes + * + ******************************************************************/ +CpaStatus SalCtrl_AdfServicesUnregister(void); + +#endif diff --git a/sys/dev/qat/qat_api/common/include/lac_sal_types.h b/sys/dev/qat/qat_api/common/include/lac_sal_types.h new file mode 100644 index 000000000000..36e146665787 --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_sal_types.h @@ -0,0 +1,198 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file lac_sal_types.h + * + * @ingroup SalCtrl + * + * Generic instance type definitions of SAL controller + * + ***************************************************************************/ + +#ifndef LAC_SAL_TYPES_H +#define LAC_SAL_TYPES_H + +#include "lac_sync.h" +#include "lac_list.h" +#include "icp_accel_devices.h" +#include "sal_statistics.h" +#include "icp_adf_debug.h" + +#define SAL_CFG_BASE_DEC 10 +#define SAL_CFG_BASE_HEX 16 + +/** + ***************************************************************************** + * @ingroup SalCtrl + * Instance States + * + * @description + * An enumeration containing the possible states for an instance. + * + *****************************************************************************/ +typedef enum sal_service_state_s { + SAL_SERVICE_STATE_UNINITIALIZED = 0, + SAL_SERVICE_STATE_INITIALIZING, + SAL_SERVICE_STATE_INITIALIZED, + SAL_SERVICE_STATE_RUNNING, + SAL_SERVICE_STATE_SHUTTING_DOWN, + SAL_SERVICE_STATE_SHUTDOWN, + SAL_SERVICE_STATE_RESTARTING, + SAL_SERVICE_STATE_END +} sal_service_state_t; + +/** + ***************************************************************************** + * @ingroup SalCtrl + * Service Instance Types + * + * @description + * An enumeration containing the possible types for a service. + * + *****************************************************************************/ +typedef enum { + SAL_SERVICE_TYPE_UNKNOWN = 0, + /* symmetric and asymmetric crypto service */ + SAL_SERVICE_TYPE_CRYPTO = 1, + /* compression service */ + SAL_SERVICE_TYPE_COMPRESSION = 2, + /* inline service */ + SAL_SERVICE_TYPE_INLINE = 4, + /* asymmetric crypto only service*/ + SAL_SERVICE_TYPE_CRYPTO_ASYM = 8, + /* symmetric crypto only service*/ + SAL_SERVICE_TYPE_CRYPTO_SYM = 16, + SAL_SERVICE_TYPE_QAT = 32 +} sal_service_type_t; + +/** + ***************************************************************************** + * @ingroup SalCtrl + * Generic Instance Container + * + * @description + * Contains all the common information across the different instances. + * + *****************************************************************************/ +typedef struct sal_service_s { + sal_service_type_t type; + /**< Service type (e.g. SAL_SERVICE_TYPE_CRYPTO)*/ + + Cpa8U state; + /**< Status of the service instance + (e.g. SAL_SERVICE_STATE_INITIALIZED) */ + + Cpa32U instance; + /**< Instance number */ + + CpaVirtualToPhysical virt2PhysClient; + /**< Function pointer to client supplied virt_to_phys */ + + CpaStatus (*init)(icp_accel_dev_t *device, + struct sal_service_s *service); + /**< Function pointer for instance INIT function */ + CpaStatus (*start)(icp_accel_dev_t *device, + struct sal_service_s *service); + /**< Function pointer for instance START function */ + CpaStatus (*stop)(icp_accel_dev_t *device, + struct sal_service_s *service); + /**< Function pointer for instance STOP function */ + CpaStatus (*shutdown)(icp_accel_dev_t *device, + struct sal_service_s *service); + /**< Function pointer for instance SHUTDOWN function */ + + CpaCyInstanceNotificationCbFunc notification_cb; + /**< Function pointer for instance restarting handler */ + + void *cb_tag; + /**< Restarting handler priv data */ + + sal_statistics_collection_t *stats; + /**< Pointer to device statistics configuration */ + + void *debug_parent_dir; + /**< Pointer to parent proc dir entry */ + + CpaBoolean is_dyn; + + Cpa32U capabilitiesMask; + /**< Capabilities mask of the device */ + + Cpa32U dcExtendedFeatures; + /**< Bit field of features. I.e. Compress And Verify */ + + CpaBoolean isInstanceStarted; + /**< True if user called StartInstance on this instance */ + + CpaBoolean integrityCrcCheck; + /** < True if the device supports end to end data integrity checks */ +} sal_service_t; + +/** + ***************************************************************************** + * @ingroup SalCtrl + * SAL structure + * + * @description + * Contains lists to crypto and compression instances. + * + *****************************************************************************/ +typedef struct sal_s { + sal_list_t *crypto_services; + /**< Container of sal_crypto_service_t */ + sal_list_t *asym_services; + /**< Container of sal_asym_service_t */ + sal_list_t *sym_services; + /**< Container of sal_sym_service_t */ + sal_list_t *compression_services; + /**< Container of sal_compression_service_t */ + debug_dir_info_t *cy_dir; + /**< Container for crypto proc debug */ + debug_dir_info_t *asym_dir; + /**< Container for asym proc debug */ + debug_dir_info_t *sym_dir; + /**< Container for sym proc debug */ + debug_dir_info_t *dc_dir; + /**< Container for compression proc debug */ + debug_file_info_t *ver_file; + /**< Container for version debug file */ +} sal_t; + +/** + ***************************************************************************** + * @ingroup SalCtrl + * SAL debug structure + * + * @description + * Service debug handler + * + *****************************************************************************/ +typedef struct sal_service_debug_s { + icp_accel_dev_t *accel_dev; + debug_file_info_t debug_file; +} sal_service_debug_t; + +/** + ******************************************************************************* + * @ingroup SalCtrl + * This macro verifies that the right service type has been passed in. + * + * @param[in] pService pointer to service instance + * @param[in] service_type service type to check againstx. + * + * @return CPA_STATUS_FAIL Parameter is incorrect type + * + ******************************************************************************/ +#define SAL_CHECK_INSTANCE_TYPE(pService, service_type) \ + do { \ + sal_service_t *pGenericService = NULL; \ + pGenericService = (sal_service_t *)pService; \ + if (!(service_type & pGenericService->type)) { \ + QAT_UTILS_LOG("Instance handle type is incorrect.\n"); \ + return CPA_STATUS_FAIL; \ + } \ + } while (0) + +#endif diff --git a/sys/dev/qat/qat_api/common/include/lac_sal_types_crypto.h b/sys/dev/qat/qat_api/common/include/lac_sal_types_crypto.h new file mode 100644 index 000000000000..c7db231260ed --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_sal_types_crypto.h @@ -0,0 +1,179 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ + +/** + *************************************************************************** + * @file lac_sal_types_crypto.h + * + * @ingroup SalCtrl + * + * Generic crypto instance type definition + * + ***************************************************************************/ + +#ifndef LAC_SAL_TYPES_CRYPTO_H_ +#define LAC_SAL_TYPES_CRYPTO_H_ + +#include "lac_sym_qat_hash_defs_lookup.h" +#include "lac_sym_key.h" +#include "cpa_cy_sym_dp.h" + +#include "icp_adf_debug.h" +#include "lac_sal_types.h" +#include "icp_adf_transport.h" +#include "lac_mem_pools.h" + +#define LAC_PKE_FLOW_ID_TAG 0xFFFFFFFC +#define LAC_PKE_ACCEL_ID_BIT_POS 1 +#define LAC_PKE_SLICE_ID_BIT_POS 0 + +/** + ***************************************************************************** + * @ingroup SalCtrl + * Crypto specific Service Container + * + * @description + * Contains information required per crypto service instance. + * + *****************************************************************************/ +typedef struct sal_crypto_service_s { + sal_service_t generic_service_info; + /**< An instance of the Generic Service Container */ + + lac_memory_pool_id_t lac_sym_cookie_pool; + /**< Memory pool ID used for symmetric operations */ + lac_memory_pool_id_t lac_ec_pool; + /**< Memory pool ID used for asymmetric operations */ + lac_memory_pool_id_t lac_prime_pool; + /**< Memory pool ID used for asymmetric operations */ + lac_memory_pool_id_t lac_pke_req_pool; + /**< Memory pool ID used for asymmetric operations */ + lac_memory_pool_id_t lac_pke_align_pool; + /**< Memory pool ID used for asymmetric operations */ + + QatUtilsAtomic *pLacSymStatsArr; + /**< pointer to an array of atomic stats for symmetric */ + + QatUtilsAtomic *pLacKeyStats; + /**< pointer to an array of atomic stats for key */ + + QatUtilsAtomic *pLacDhStatsArr; + /**< pointer to an array of atomic stats for DH */ + + QatUtilsAtomic *pLacDsaStatsArr; + /**< pointer to an array of atomic stats for Dsa */ + + QatUtilsAtomic *pLacRsaStatsArr; + /**< pointer to an array of atomic stats for Rsa */ + + QatUtilsAtomic *pLacEcStatsArr; + /**< pointer to an array of atomic stats for Ecc */ + + QatUtilsAtomic *pLacEcdhStatsArr; + /**< pointer to an array of atomic stats for Ecc DH */ + + QatUtilsAtomic *pLacEcdsaStatsArr; + /**< pointer to an array of atomic stats for Ecc DSA */ + + QatUtilsAtomic *pLacPrimeStatsArr; + /**< pointer to an array of atomic stats for prime */ + + QatUtilsAtomic *pLacLnStatsArr; + /**< pointer to an array of atomic stats for large number */ + + QatUtilsAtomic *pLacDrbgStatsArr; + /**< pointer to an array of atomic stats for DRBG */ + + Cpa32U pkeFlowId; + /**< Flow ID for all pke requests from this instance - identifies + accelerator + and execution engine to use */ + + icp_comms_trans_handle trans_handle_sym_tx; + icp_comms_trans_handle trans_handle_sym_rx; + + icp_comms_trans_handle trans_handle_asym_tx; + icp_comms_trans_handle trans_handle_asym_rx; + + icp_comms_trans_handle trans_handle_nrbg_tx; + icp_comms_trans_handle trans_handle_nrbg_rx; + + Cpa32U maxNumSymReqBatch; + /**< Maximum number of requests that can be placed on the sym tx ring + for any one batch request (DP api) */ + + Cpa16U acceleratorNum; + Cpa16U bankNum; + Cpa16U pkgID; + Cpa8U isPolled; + Cpa8U executionEngine; + Cpa32U coreAffinity; + Cpa32U nodeAffinity; + /**< Config Info */ + + CpaCySymDpCbFunc pSymDpCb; + /**< Sym DP Callback */ + + lac_sym_qat_hash_defs_t **pLacHashLookupDefs; + /**< table of pointers to standard defined information for all hash + algorithms. We support an extra hash algo that is not exported by + cy api which is why we need the extra +1 */ + Cpa8U **ppHmacContentDesc; + /**< table of pointers to CD for Hmac precomputes - used at session init + */ + + Cpa8U *pSslLabel; + /**< pointer to memory holding the standard SSL label ABBCCC.. */ + + lac_sym_key_tls_labels_t *pTlsLabel; + /**< pointer to memory holding the 4 standard TLS labels */ + + QatUtilsAtomic drbgErrorState; + /**< DRBG related variables */ + + lac_sym_key_tls_hkdf_sub_labels_t *pTlsHKDFSubLabel; + /**< pointer to memory holding the 4 HKDFLabels sublabels */ + + debug_file_info_t *debug_file; +/**< Statistics handler */ +} sal_crypto_service_t; + +/************************************************************************* + * @ingroup cpaCyCommon + * @description + * This function returns a valid asym/sym/crypto instance handle for the + * system if it exists. When requesting an instance handle of type sym or + * asym, if either is not found then a crypto instance handle is returned + * if found, since a crypto handle supports both sym and asym services. + * Similarly when requesting a crypto instance handle, if it is not found + * then an asym or sym crypto instance handle is returned. + * + * @performance + * To avoid calling this function the user of the QA api should not use + * instanceHandle = CPA_INSTANCE_HANDLE_SINGLE. + * + * @context + * This function is called whenever instanceHandle = + *CPA_INSTANCE_HANDLE_SINGLE + * at the QA Cy api. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @param[in] svc_type Type of crypto service requested. + * + * @retval Pointer to first crypto instance handle or NULL if no crypto + * instances in the system. + * + *************************************************************************/ + +CpaInstanceHandle Lac_GetFirstHandle(sal_service_type_t svc_type); + +#endif /*LAC_SAL_TYPES_CRYPTO_H_*/ diff --git a/sys/dev/qat/qat_api/common/include/lac_sync.h b/sys/dev/qat/qat_api/common/include/lac_sync.h new file mode 100644 index 000000000000..b842cce30d87 --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/lac_sync.h @@ -0,0 +1,376 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file lac_sync.h + * + * @defgroup LacSync LAC synchronous + * + * @ingroup LacCommon + * + * Function prototypes and defines for synchronous support + * + ***************************************************************************/ + +#ifndef LAC_SYNC_H +#define LAC_SYNC_H + +#include "cpa.h" +#include "qat_utils.h" +#include "lac_mem.h" + +/** + ***************************************************************************** + * @ingroup LacSync + * + * @description + * LAC cookie for synchronous support + * + *****************************************************************************/ +typedef struct lac_sync_op_data_s { + struct sema *sid; + /**< Semaphore to signal */ + CpaStatus status; + /**< Output - Status of the QAT response */ + CpaBoolean opResult; + /**< Output - Verification of the operation/protocol status */ + CpaBoolean complete; + /**< Output - Operation is complete */ + CpaBoolean canceled; + /**< Output - Operation canceled */ +} lac_sync_op_data_t; + +#define LAC_PKE_SYNC_CALLBACK_TIMEOUT (5000) +/**< @ingroup LacSync + * Timeout waiting for an async callbacks in msecs. + * This is derived from the max latency of a PKE request + 1 sec + */ + +#define LAC_SYM_DRBG_POLL_AND_WAIT_TIME_MS (10) +/**< @ingroup LacSyn + * Default interval DRBG polling in msecs */ + +#define LAC_SYM_SYNC_CALLBACK_TIMEOUT (300) +/**< @ingroup LacSyn + * Timeout for wait for symmetric response in msecs +*/ + +#define LAC_INIT_MSG_CALLBACK_TIMEOUT (1922) +/**< @ingroup LacSyn + * Timeout for wait for init messages response in msecs +*/ + +#define DC_SYNC_CALLBACK_TIMEOUT (1000) +/**< @ingroup LacSyn + * Timeout for wait for compression response in msecs */ + +#define LAC_SYN_INITIAL_SEM_VALUE (0) +/**< @ingroup LacSyn + * Initial value of the sync waiting semaphore */ + +/** + ******************************************************************************* + * @ingroup LacSync + * This function allocates a sync op data cookie + * and creates and initialises the QAT Utils semaphore + * + * @param[in] ppSyncCallbackCookie Pointer to synch op data + * + * @retval CPA_STATUS_RESOURCE Failed to allocate the memory for the cookie. + * @retval CPA_STATUS_SUCCESS Success + * + ******************************************************************************/ +static __inline CpaStatus +LacSync_CreateSyncCookie(lac_sync_op_data_t **ppSyncCallbackCookie) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + *ppSyncCallbackCookie = + malloc(sizeof(lac_sync_op_data_t), M_QAT, M_WAITOK); + + if (CPA_STATUS_SUCCESS == status) { + status = LAC_INIT_SEMAPHORE((*ppSyncCallbackCookie)->sid, + LAC_SYN_INITIAL_SEM_VALUE); + (*ppSyncCallbackCookie)->complete = CPA_FALSE; + (*ppSyncCallbackCookie)->canceled = CPA_FALSE; + } + + if (CPA_STATUS_SUCCESS != status) { + LAC_OS_FREE(*ppSyncCallbackCookie); + } + + return status; +} + +/** + ******************************************************************************* + * @ingroup LacSync + * This macro frees a sync op data cookie and destroys the QAT Utils + *semaphore + * + * @param[in] ppSyncCallbackCookie Pointer to sync op data + * + * @return void + ******************************************************************************/ +static __inline CpaStatus +LacSync_DestroySyncCookie(lac_sync_op_data_t **ppSyncCallbackCookie) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + /* + * If the operation has not completed, cancel it instead of destroying + * the + * cookie. Otherwise, the callback might panic. In this case, the cookie + * will leak, but it's better than a panic. + */ + if (!(*ppSyncCallbackCookie)->complete) { + QAT_UTILS_LOG( + "Attempting to destroy an incomplete sync cookie\n"); + (*ppSyncCallbackCookie)->canceled = CPA_TRUE; + return CPA_STATUS_FAIL; + } + + status = LAC_DESTROY_SEMAPHORE((*ppSyncCallbackCookie)->sid); + LAC_OS_FREE(*ppSyncCallbackCookie); + return status; +} + +/** + ***************************************************************************** + * @ingroup LacSync + * Function which will wait for a sync callback on a given cookie. + * + * @param[in] pSyncCallbackCookie Pointer to sync op data + * @param[in] timeOut Time to wait for callback (msec) + * @param[out] pStatus Status returned by the callback + * @param[out] pOpStatus Operation status returned by callback. + * + * @retval CPA_STATUS_SUCCESS Success + * @retval CPA_STATUS_SUCCESS Fail waiting for a callback + * + *****************************************************************************/ +static __inline CpaStatus +LacSync_WaitForCallback(lac_sync_op_data_t *pSyncCallbackCookie, + Cpa32S timeOut, + CpaStatus *pStatus, + CpaBoolean *pOpStatus) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + status = LAC_WAIT_SEMAPHORE(pSyncCallbackCookie->sid, timeOut); + + if (CPA_STATUS_SUCCESS == status) { + *pStatus = pSyncCallbackCookie->status; + if (NULL != pOpStatus) { + *pOpStatus = pSyncCallbackCookie->opResult; + } + pSyncCallbackCookie->complete = CPA_TRUE; + } + + return status; +} + +/** + ***************************************************************************** + * @ingroup LacSync + * Function which will check for a sync callback on a given cookie. + * Returns whether the callback has happened or not, no timeout. + * + * @param[in] pSyncCallbackCookie Pointer to sync op data + * @param[in] timeOut Time to wait for callback (msec) + * @param[out] pStatus Status returned by the callback + * @param[out] pOpStatus Operation status returned by callback. + * + * @retval CPA_STATUS_SUCCESS Success + * @retval CPA_STATUS_FAIL Fail waiting for a callback + * + *****************************************************************************/ +static __inline CpaStatus +LacSync_CheckForCallback(lac_sync_op_data_t *pSyncCallbackCookie, + CpaStatus *pStatus, + CpaBoolean *pOpStatus) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + + status = LAC_CHECK_SEMAPHORE(pSyncCallbackCookie->sid); + + if (CPA_STATUS_SUCCESS == status) { + *pStatus = pSyncCallbackCookie->status; + if (NULL != pOpStatus) { + *pOpStatus = pSyncCallbackCookie->opResult; + } + pSyncCallbackCookie->complete = CPA_TRUE; + } + + return status; +} + +/** + ***************************************************************************** + * @ingroup LacSync + * Function which will mark a sync cookie as complete. + * If it's known that the callback will not happen it's necessary + * to call this, else the cookie can't be destroyed. + * + * @param[in] pSyncCallbackCookie Pointer to sync op data + * + * @retval CPA_STATUS_SUCCESS Success + * @retval CPA_STATUS_FAIL Failed to mark as complete + * + *****************************************************************************/ +static __inline CpaStatus +LacSync_SetSyncCookieComplete(lac_sync_op_data_t *pSyncCallbackCookie) +{ + CpaStatus status = CPA_STATUS_FAIL; + + if (NULL != pSyncCallbackCookie) { + pSyncCallbackCookie->complete = CPA_TRUE; + status = CPA_STATUS_SUCCESS; + } + return status; +} +/** + ***************************************************************************** + * @ingroup LacSync + * Generic verify callback function. + * @description + * This function is used when the API is called in synchronous mode. + * It's assumed the callbackTag holds a lac_sync_op_data_t type + * and when the callback is received, this callback shall set the + * status element of that cookie structure and kick the sid. + * This function may be used directly as a callback function. + * + * @param[in] callbackTag Callback Tag + * @param[in] status Status of callback + * @param[out] pOpdata Pointer to the Op Data + * @param[out] opResult Boolean to indicate the result of the operation + * + * @return void + *****************************************************************************/ +void LacSync_GenVerifyCb(void *callbackTag, + CpaStatus status, + void *pOpdata, + CpaBoolean opResult); + +/** + ***************************************************************************** + * @ingroup LacSync + * Generic flatbuffer callback function. + * @description + * This function is used when the API is called in synchronous mode. + * It's assumed the callbackTag holds a lac_sync_op_data_t type + * and when the callback is received, this callback shall set the + * status element of that cookie structure and kick the sid. + * This function may be used directly as a callback function. + * + * @param[in] callbackTag Callback Tag + * @param[in] status Status of callback + * @param[in] pOpdata Pointer to the Op Data + * @param[out] pOut Pointer to the flat buffer + * + * @return void + *****************************************************************************/ +void LacSync_GenFlatBufCb(void *callbackTag, + CpaStatus status, + void *pOpdata, + CpaFlatBuffer *pOut); + +/** + ***************************************************************************** + * @ingroup LacSync + * Generic flatbuffer verify callback function. + * @description + * This function is used when the API is called in synchronous mode. + * It's assumed the callbackTag holds a lac_sync_op_data_t type + * and when the callback is received, this callback shall set the + * status and opResult element of that cookie structure and + * kick the sid. + * This function may be used directly as a callback function. + * + * @param[in] callbackTag Callback Tag + * @param[in] status Status of callback + * @param[in] pOpdata Pointer to the Op Data + * @param[out] opResult Boolean to indicate the result of the operation + * @param[out] pOut Pointer to the flat buffer + * + * @return void + *****************************************************************************/ +void LacSync_GenFlatBufVerifyCb(void *callbackTag, + CpaStatus status, + void *pOpdata, + CpaBoolean opResult, + CpaFlatBuffer *pOut); + +/** + ***************************************************************************** + * @ingroup LacSync + * Generic dual flatbuffer verify callback function. + * @description + * This function is used when the API is called in synchronous mode. + * It's assumed the callbackTag holds a lac_sync_op_data_t type + * and when the callback is received, this callback shall set the + * status and opResult element of that cookie structure and + * kick the sid. + * This function may be used directly as a callback function. + * + * @param[in] callbackTag Callback Tag + * @param[in] status Status of callback + * @param[in] pOpdata Pointer to the Op Data + * @param[out] opResult Boolean to indicate the result of the operation + * @param[out] pOut0 Pointer to the flat buffer + * @param[out] pOut1 Pointer to the flat buffer + * + * @return void + *****************************************************************************/ +void LacSync_GenDualFlatBufVerifyCb(void *callbackTag, + CpaStatus status, + void *pOpdata, + CpaBoolean opResult, + CpaFlatBuffer *pOut0, + CpaFlatBuffer *pOut1); + +/** + ***************************************************************************** + * @ingroup LacSync + * Generic wake up function. + * @description + * This function is used when the API is called in synchronous + * mode. + * It's assumed the callbackTag holds a lac_sync_op_data_t type + * and when the callback is received, this callback shall set + * the status element of that cookie structure and kick the + * sid. + * This function maybe called from an async callback. + * + * @param[in] callbackTag Callback Tag + * @param[in] status Status of callback + * + * @return void + *****************************************************************************/ +void LacSync_GenWakeupSyncCaller(void *callbackTag, CpaStatus status); + +/** + ***************************************************************************** + * @ingroup LacSync + * Generic wake up verify function. + * @description + * This function is used when the API is called in synchronous + * mode. + * It's assumed the callbackTag holds a lac_sync_op_data_t type + * and when the callback is received, this callback shall set + * the status element and the opResult of that cookie structure + * and kick the sid. + * This function maybe called from an async callback. + * + * @param[in] callbackTag Callback Tag + * @param[in] status Status of callback + * @param[out] opResult Boolean to indicate the result of the operation + * + * @return void + *****************************************************************************/ +void LacSync_GenVerifyWakeupSyncCaller(void *callbackTag, + CpaStatus status, + CpaBoolean opResult); + +#endif /*LAC_SYNC_H*/ diff --git a/sys/dev/qat/qat_api/common/include/sal_qat_cmn_msg.h b/sys/dev/qat/qat_api/common/include/sal_qat_cmn_msg.h new file mode 100644 index 000000000000..8cd7b08e84ea --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/sal_qat_cmn_msg.h @@ -0,0 +1,209 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file sal_qat_cmn_msg.c + * + * @ingroup SalQatCmnMessage + * + * @description + * Implementation for populating the common (across services) QAT structures. + * + *****************************************************************************/ +#ifndef SAL_QAT_CMN_MSG_H +#define SAL_QAT_CMN_MSG_H +/* + ******************************************************************************* + * Include public/global header files + ******************************************************************************* + */ +#include "cpa.h" + +/* + ******************************************************************************* + * Include private header files + ******************************************************************************* + */ +#include "lac_common.h" +#include "icp_accel_devices.h" +#include "qat_utils.h" + +#include "cpa_cy_sym.h" +#include "lac_mem.h" +#include "lac_mem_pools.h" +#include "lac_list.h" +#include "icp_adf_transport.h" +#include "icp_adf_transport_dp.h" + +#include "icp_qat_hw.h" +#include "icp_qat_fw.h" +#include "icp_qat_fw_la.h" + +/** + ****************************************************************************** + * @ingroup SalQatCmnMessage + * content descriptor info structure + * + * @description + * This structure contains generic information on the content descriptor + * + *****************************************************************************/ +typedef struct sal_qat_content_desc_info_s { + CpaPhysicalAddr hardwareSetupBlockPhys; + /**< Physical address of hardware setup block of the content descriptor + */ + void *pData; + /**< Virtual Pointer to the hardware setup block of the content + * descriptor */ + Cpa8U hwBlkSzQuadWords; + /**< Hardware Setup Block size in quad words */ +} sal_qat_content_desc_info_t; + +/** + ******************************************************************************* + * @ingroup SalQatCmnMessage + * Lookaside response handler function type + * + * @description + * This type definition specifies the function prototype for handling the + * response messages for a specific symmetric operation + * + * @param[in] lacCmdId Look Aside Command ID + * + * @param[in] pOpaqueData Pointer to Opaque Data + * + * @param[in] cmnRespFlags Common Response flags + * + * @return void + * + *****************************************************************************/ +typedef void (*sal_qat_resp_handler_func_t)(icp_qat_fw_la_cmd_id_t lacCmdId, + void *pOpaqueData, + icp_qat_fw_comn_flags cmnRespFlags); + +/******************************************************************** + * @ingroup SalQatMsg_CmnHdrWrite + * + * @description + * This function fills in all fields in the icp_qat_fw_comn_req_hdr_t + * section of the Request Msg. Build LW0 + LW1 - + * service part of the request + * + * @param[in] pMsg Pointer to 128B Request Msg buffer + * @param[in] serviceType type of service request + * @param[in] serviceCmdId id for the type of service request + * @param[in] cmnFlags common request flags + * @param[in] serviceCmdFlags service command flahgs + * + * @return + * None + * + *****************************************/ +void SalQatMsg_CmnHdrWrite(icp_qat_fw_comn_req_t *pMsg, + icp_qat_fw_comn_request_id_t serviceType, + uint8_t serviceCmdId, + icp_qat_fw_comn_flags cmnFlags, + icp_qat_fw_serv_specif_flags serviceCmdFlags); + +/******************************************************************** + * @ingroup SalQatMsg_CmnMidWrite + * + * @description + * This function fills in all fields in the icp_qat_fw_comn_req_mid_t + * section of the Request Msg and the corresponding SGL/Flat flag + * in the Hdr. + * + * @param[in] pReq Pointer to 128B Request Msg buffer + * @param[in] pOpaqueData Pointer to opaque data used by callback + * @param[in] bufferFormat src and dst Buffers are either SGL or Flat + format + * @param[in] pSrcBuffer Address of source buffer + * @param[in] pDstBuffer Address of destination buffer + * @param[in] pSrcLength Length of source buffer + * @param[in] pDstLength Length of destination buffer + * + + * @assumptions + * All fields in mid section are zero before fn is called + + * @return + * None + * + *****************************************/ +void SalQatMsg_CmnMidWrite(icp_qat_fw_la_bulk_req_t *pReq, + const void *pOpaqueData, + Cpa8U bufferFormat, + Cpa64U srcBuffer, + Cpa64U dstBuffer, + Cpa32U srcLength, + Cpa32U dstLength); + +/******************************************************************** + * @ingroup SalQatMsg_ContentDescHdrWrite + * + * @description + * This function fills in all fields in the + *icp_qat_fw_comn_req_hdr_cd_pars_t + * section of the Request Msg. + * + * @param[in] pMsg Pointer to 128B Request Msg buffer. + * @param[in] pContentDescInfo content descripter info. + * + * @return + * none + * + *****************************************/ +void SalQatMsg_ContentDescHdrWrite( + icp_qat_fw_comn_req_t *pMsg, + const sal_qat_content_desc_info_t *pContentDescInfo); + +/******************************************************************** + * @ingroup SalQatMsg_CtrlBlkSetToReserved + * + * @description + * This function set the whole contrle block to a reserved state. + * + * @param[in] _pMsg Pointer to 128B Request Msg buffer. + * + * @return + * none + * + *****************************************/ +void SalQatMsg_CtrlBlkSetToReserved(icp_qat_fw_comn_req_t *_pMsg); + +/******************************************************************** + * @ingroup SalQatMsg_transPutMsg + * + * @description + * + * + * @param[in] trans_handle + * @param[in] pqat_msg + * @param[in] size_in_lws + * @param[in] service + * + * @return + * CpaStatus + * + *****************************************/ +CpaStatus SalQatMsg_transPutMsg(icp_comms_trans_handle trans_handle, + void *pqat_msg, + Cpa32U size_in_lws, + Cpa8U service); + +/******************************************************************** + * @ingroup SalQatMsg_updateQueueTail + * + * @description + * + * + * @param[in] trans_handle + * + * + * @return + * CpaStatus + * + *****************************************/ +void SalQatMsg_updateQueueTail(icp_comms_trans_handle trans_hnd); +#endif diff --git a/sys/dev/qat/qat_api/common/include/sal_service_state.h b/sys/dev/qat/qat_api/common/include/sal_service_state.h new file mode 100644 index 000000000000..3712d38cc3ac --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/sal_service_state.h @@ -0,0 +1,94 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file sal_service_state.h + * + * @defgroup SalServiceState + * + * @ingroup SalCtrl + * + * Checks state for generic service instance + * + ***************************************************************************/ + +#ifndef SAL_SERVICE_STATE_H_ +#define SAL_SERVICE_STATE_H_ + +/** +******************************************************************************* + * @ingroup SalServiceState + * Check to see if the instance is in the running state + * + * @description + * This function checks the state of an instance to see if it is in the + * running state + * + * @param[in] instance Instance handle (assumes this is valid, i.e. checked + * before this function is called) + * @retval CPA_TRUE Instance in the RUNNING state + * @retval CPA_FALSE Instance not in RUNNING state + * + *****************************************************************************/ +CpaBoolean Sal_ServiceIsRunning(CpaInstanceHandle instanceHandle); + +/** +******************************************************************************* + * @ingroup SalServiceState + * Check to see if the instance is beign restarted + * + * @description + * This function checks the state of an instance to see if the device it + * uses is being restarted because of hardware error. + * + * @param[in] instance Instance handle (assumes this is valid, i.e. checked + * before this function is called) + * @retval CPA_TRUE Device the instance is using is restarting. + * @retval CPA_FALSE Device the instance is running. + * + *****************************************************************************/ +CpaBoolean Sal_ServiceIsRestarting(CpaInstanceHandle instanceHandle); + +/** + ******************************************************************************* + * @ingroup SalServiceState + * This macro checks if an instance is running. An error message is logged + * if it is not in a running state. + * + * @return CPA_STATUS_FAIL Instance not in RUNNING state. + * @return void Instance is in RUNNING state. + ******************************************************************************/ +#define SAL_RUNNING_CHECK(instanceHandle) \ + do { \ + if (unlikely(CPA_TRUE != \ + Sal_ServiceIsRunning(instanceHandle))) { \ + if (CPA_TRUE == \ + Sal_ServiceIsRestarting(instanceHandle)) { \ + return CPA_STATUS_RESTARTING; \ + } \ + QAT_UTILS_LOG("Instance not in a Running state\n"); \ + return CPA_STATUS_FAIL; \ + } \ + } while (0) + +/** + ******************************************************************************* + * @ingroup SalServiceState + * This macro checks if an instance is in a state to get init event. + * + * @return CPA_STATUS_FAIL Instance not in good state. + * @return void Instance is in good state. + ******************************************************************************/ +#define SAL_SERVICE_GOOD_FOR_INIT(instanceHandle) \ + do { \ + sal_service_t *pService = (sal_service_t *)instanceHandle; \ + if ((SAL_SERVICE_STATE_UNINITIALIZED != pService->state) && \ + (SAL_SERVICE_STATE_RESTARTING != pService->state)) { \ + QAT_UTILS_LOG( \ + "Not in the correct state to call init\n"); \ + return CPA_STATUS_FAIL; \ + } \ + } while (0) + +#endif /*SAL_SERVICE_STATE_H_*/ diff --git a/sys/dev/qat/qat_api/common/include/sal_statistics.h b/sys/dev/qat/qat_api/common/include/sal_statistics.h new file mode 100644 index 000000000000..47c08bc6eae5 --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/sal_statistics.h @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file sal_statistics.h + * + * @ingroup SalStats + * + * @description + * Statistics related defines, structures and functions + * + *****************************************************************************/ + +#ifndef SAL_STATISTICS_H +#define SAL_STATISTICS_H + +#include "sal_statistics_strings.h" + +#define SAL_STATS_SYM 0 +#define SAL_STATS_DSA 1 +#define SAL_STATS_DSA2 2 +#define SAL_STATS_RSA 3 +#define SAL_STATS_DH 4 +#define SAL_STATS_KEYGEN 5 +#define SAL_STATS_LN 6 +#define SAL_STATS_PRIME 7 +#define SAL_STATS_ECC 8 +#define SAL_STATS_ECDH 9 +#define SAL_STATS_ECDSA 10 +/**< Numeric values for crypto statistics */ + +#define SAL_STATISTICS_STRING_OFF "0" +/**< String representing the value for disabled statistics */ + +/** +***************************************************************************** + * @ingroup SalStats + * Structure describing stats enabled/disabled in the system + * + * @description + * Structure describing stats enabled/disabled in the system + * + *****************************************************************************/ +typedef struct sal_statistics_collection_s { + CpaBoolean bStatsEnabled; + /**< If CPA_TRUE then statistics functionality is enabled */ + CpaBoolean bDcStatsEnabled; + /**< If CPA_TRUE then Compression statistics are enabled */ + CpaBoolean bDhStatsEnabled; + /**< If CPA_TRUE then Diffie-Helman statistics are enabled */ + CpaBoolean bDsaStatsEnabled; + /**< If CPA_TRUE then DSA statistics are enabled */ + CpaBoolean bEccStatsEnabled; + /**< If CPA_TRUE then ECC statistics are enabled */ + CpaBoolean bKeyGenStatsEnabled; + /**< If CPA_TRUE then Key Gen statistics are enabled */ + CpaBoolean bLnStatsEnabled; + /**< If CPA_TRUE then Large Number statistics are enabled */ + CpaBoolean bPrimeStatsEnabled; + /**< If CPA_TRUE then Prime statistics are enabled */ + CpaBoolean bRsaStatsEnabled; + /**< If CPA_TRUE then RSA statistics are enabled */ + CpaBoolean bSymStatsEnabled; + /**< If CPA_TRUE then Symmetric Crypto statistics are enabled */ +} sal_statistics_collection_t; + +/** + ****************************************************************************** + * @ingroup SalStats + * + * @description + * Initializes structure describing which statistics + * are enabled for the acceleration device. + * + * @param[in] device Pointer to an acceleration device structure + * + * @retval CPA_STATUS_SUCCESS Operation successful + * @retval CPA_STATUS_INVALID_PARAM Invalid param provided + * @retval CPA_STATUS_RESOURCE Memory alloc failed + * @retval CPA_STATUS_FAIL Operation failed + * + ******************************************************************************/ +CpaStatus SalStatistics_InitStatisticsCollection(icp_accel_dev_t *device); + +/** + ****************************************************************************** + * @ingroup SalStats + * + * @description + * Cleans structure describing which statistics + * are enabled for the acceleration device. + * + * @param[in] device Pointer to an acceleration device structure + * + * @retval CPA_STATUS_SUCCESS Operation successful + * @retval CPA_STATUS_INVALID_PARAM Invalid param provided + * @retval CPA_STATUS_FAIL Operation failed + * + ******************************************************************************/ +CpaStatus SalStatistics_CleanStatisticsCollection(icp_accel_dev_t *device); +#endif diff --git a/sys/dev/qat/qat_api/common/include/sal_string_parse.h b/sys/dev/qat/qat_api/common/include/sal_string_parse.h new file mode 100644 index 000000000000..8654f2c09445 --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/sal_string_parse.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file sal_string_parse.h + * + * @defgroup SalStringParse + * + * @ingroup SalStringParse + * + * @description + * This file contains string parsing functions + * + *****************************************************************************/ + +#ifndef SAL_STRING_PARSE_H +#define SAL_STRING_PARSE_H + +/* Maximum size of the strings used by SAL */ +#define SAL_CFG_MAX_VAL_LEN_IN_BYTES 64 + +/** +******************************************************************************* + * @ingroup SalStringParse + * Builds a string and store it in result + * + * @description + * The result string will be the concatenation of string1, instanceNumber + * and string2. The size of result has to be SAL_CFG_MAX_VAL_LEN_IN_BYTES. + * We can't check this in this function, this is the user responsibility + * + * @param[in] string1 First string to concatenate + * @param[in] instanceNumber Instance number + * @param[in] string2 Second string to concatenate + * @param[out] result Resulting string of concatenation + * + * @retval CPA_STATUS_SUCCESS Function executed successfully + * @retval CPA_STATUS_FAIL Function failed + * + *****************************************************************************/ +CpaStatus Sal_StringParsing(char *string1, + Cpa32U instanceNumber, + char *string2, + char *result); + +/** +******************************************************************************* + * @ingroup SalStringParse + * Convert a string to an unsigned long + * + * @description + * Parses the string cp in the specified base, and returned it as an + * unsigned long value. + * + * @param[in] cp String to be converted + * @param[in] endp Pointer to the end of the string. This parameter + * can also be NULL and will not be used in this case + * @param[in] cfgBase Base to convert the string + * + * @retval The string converted to an unsigned long + * + *****************************************************************************/ +Cpa64U Sal_Strtoul(const char *cp, char **endp, unsigned int cfgBase); + +#endif /* SAL_STRING_PARSE_H */ diff --git a/sys/dev/qat/qat_api/common/include/sal_types_compression.h b/sys/dev/qat/qat_api/common/include/sal_types_compression.h new file mode 100644 index 000000000000..12f9f673ac43 --- /dev/null +++ b/sys/dev/qat/qat_api/common/include/sal_types_compression.h @@ -0,0 +1,150 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file sal_types_compression.h + * + * @ingroup SalCtrl + * + * Generic compression instance type definition + * + ***************************************************************************/ +#ifndef SAL_TYPES_COMPRESSION_H_ +#define SAL_TYPES_COMPRESSION_H_ + +#include "cpa_dc.h" +#include "cpa_dc_dp.h" +#include "lac_sal_types.h" +#include "icp_qat_hw.h" +#include "icp_buffer_desc.h" + +#include "lac_mem_pools.h" +#include "icp_adf_transport.h" + +#define DC_NUM_RX_RINGS (1) + +/** + ***************************************************************************** + * @ingroup SalCtrl + * Compression device specific data + * + * @description + * Contains device specific information for a compression service. + * + *****************************************************************************/ +typedef struct sal_compression_device_data { + /* Device specific minimum output buffer size for static compression */ + Cpa32U minOutputBuffSize; + + /* Enable/disable secureRam/acceleratorRam for intermediate buffers*/ + Cpa8U useDevRam; + + /* When set, implies device can decompress interim odd byte length + * stateful decompression requests. + */ + CpaBoolean oddByteDecompInterim; + + /* When set, implies device can decompress odd byte length + * stateful decompression requests when bFinal is absent + */ + CpaBoolean oddByteDecompNobFinal; + + /* Flag to indicate if translator slice overflow is supported */ + CpaBoolean translatorOverflow; + + /* Flag to enable/disable delayed match mode */ + icp_qat_hw_compression_delayed_match_t enableDmm; + + Cpa32U inflateContextSize; + Cpa8U highestHwCompressionDepth; + + /* Mask that reports supported window sizes for comp/decomp */ + Cpa8U windowSizeMask; + + /* Flag to indicate CompressAndVerifyAndRecover feature support */ + CpaBoolean cnvnrSupported; +} sal_compression_device_data_t; + +/** + ***************************************************************************** + * @ingroup SalCtrl + * Compression specific Service Container + * + * @description + * Contains information required per compression service instance. + * + *****************************************************************************/ +typedef struct sal_compression_service_s { + /* An instance of the Generic Service Container */ + sal_service_t generic_service_info; + + /* Memory pool ID used for compression */ + lac_memory_pool_id_t compression_mem_pool; + + /* Pointer to an array of atomic stats for compression */ + QatUtilsAtomic *pCompStatsArr; + + /* Size of the DRAM intermediate buffer in bytes */ + Cpa64U minInterBuffSizeInBytes; + + /* Number of DRAM intermediate buffers */ + Cpa16U numInterBuffs; + + /* Address of the array of DRAM intermediate buffers*/ + icp_qat_addr_width_t *pInterBuffPtrsArray; + CpaPhysicalAddr pInterBuffPtrsArrayPhyAddr; + + icp_comms_trans_handle trans_handle_compression_tx; + icp_comms_trans_handle trans_handle_compression_rx; + + /* Maximum number of in flight requests */ + Cpa32U maxNumCompConcurrentReq; + + /* Callback function defined for the DcDp API compression session */ + CpaDcDpCallbackFn pDcDpCb; + + /* Config info */ + Cpa16U acceleratorNum; + Cpa16U bankNum; + Cpa16U pkgID; + Cpa16U isPolled; + Cpa32U coreAffinity; + Cpa32U nodeAffinity; + + sal_compression_device_data_t comp_device_data; + + /* Statistics handler */ + debug_file_info_t *debug_file; +} sal_compression_service_t; + +/************************************************************************* + * @ingroup SalCtrl + * @description + * This function returns a valid compression instance handle for the system + * if it exists. + * + * @performance + * To avoid calling this function the user of the QA api should not use + * instanceHandle = CPA_INSTANCE_HANDLE_SINGLE. + * + * @context + * This function is called whenever instanceHandle = + * CPA_INSTANCE_HANDLE_SINGLE at the QA Dc api. + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * + * @retval Pointer to first compression instance handle or NULL if no + * compression instances in the system. + * + *************************************************************************/ +CpaInstanceHandle dcGetFirstHandle(void); + +#endif /*SAL_TYPES_COMPRESSION_H_*/ diff --git a/sys/dev/qat/qat_api/common/qat_comms/sal_qat_cmn_msg.c b/sys/dev/qat/qat_api/common/qat_comms/sal_qat_cmn_msg.c new file mode 100644 index 000000000000..4331f875aa67 --- /dev/null +++ b/sys/dev/qat/qat_api/common/qat_comms/sal_qat_cmn_msg.c @@ -0,0 +1,219 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file sal_qat_cmn_msg.h + * + * @defgroup SalQatCmnMessage + * + * @ingroup SalQatCmnMessage + * + * Interfaces for populating the common QAT structures for a lookaside + * operation. + * + *****************************************************************************/ + +/* +****************************************************************************** +* Include public/global header files +****************************************************************************** +*/ +#include "cpa.h" + +/* +******************************************************************************* +* Include private header files +******************************************************************************* +*/ +#include "qat_utils.h" +#include "icp_accel_devices.h" +#include "icp_qat_fw_la.h" +#include "icp_qat_hw.h" +#include "lac_common.h" +#include "lac_mem.h" +#include "sal_qat_cmn_msg.h" + +/******************************************************************** + * @ingroup SalQatMsg_CmnHdrWrite + * + * @description + * This function fills in all fields in the icp_qat_fw_comn_req_hdr_t + * section of the Request Msg. Build LW0 + LW1 - + * service part of the request + * + * @param[in] pMsg Pointer to 128B Request Msg buffer + * @param[in] serviceType type of service request + * @param[in] serviceCmdId id for the type of service request + * @param[in] cmnFlags common request flags + * @param[in] serviceCmdFlags service command flahgs + * + * @return + * None + * + *****************************************/ +void +SalQatMsg_CmnHdrWrite(icp_qat_fw_comn_req_t *pMsg, + icp_qat_fw_comn_request_id_t serviceType, + uint8_t serviceCmdId, + icp_qat_fw_comn_flags cmnFlags, + icp_qat_fw_serv_specif_flags serviceCmdFlags) +{ + icp_qat_fw_comn_req_hdr_t *pHeader = &(pMsg->comn_hdr); + + /* LW0 */ + pHeader->hdr_flags = + ICP_QAT_FW_COMN_HDR_FLAGS_BUILD(ICP_QAT_FW_COMN_REQ_FLAG_SET); + pHeader->service_type = (uint8_t)serviceType; + pHeader->service_cmd_id = serviceCmdId; + pHeader->resrvd1 = 0; + /* LW1 */ + pHeader->comn_req_flags = cmnFlags; + pHeader->serv_specif_flags = serviceCmdFlags; +} + +/******************************************************************** + * @ingroup SalQatCmnMessage + * + * @description + * This function fills in all fields in the icp_qat_fw_comn_req_mid_t + * section of the Request Msg and the corresponding SGL/Flat flag + * in the Hdr. + * + * @param[in] pReq Pointer to 128B Request Msg buffer + * @param[in] pOpaqueData Pointer to opaque data used by callback + * @param[in] bufferFormat src and dst Buffers are either SGL or Flat + * format + * @param[in] pSrcBuffer Address of source buffer + * @param[in] pDstBuffer Address of destination buffer + * @param[in] pSrcLength Length of source buffer + * @param[in] pDstLength Length of destination buffer + * + + * @assumptions + * All fields in mid section are zero before fn is called + + * @return + * None + * + *****************************************/ +void inline SalQatMsg_CmnMidWrite(icp_qat_fw_la_bulk_req_t *pReq, + const void *pOpaqueData, + Cpa8U bufferFormat, + Cpa64U srcBuffer, + Cpa64U dstBuffer, + Cpa32U srcLength, + Cpa32U dstLength) +{ + icp_qat_fw_comn_req_mid_t *pMid = &(pReq->comn_mid); + + LAC_MEM_SHARED_WRITE_FROM_PTR(pMid->opaque_data, pOpaqueData); + pMid->src_data_addr = srcBuffer; + + /* In place */ + if (0 == dstBuffer) { + pMid->dest_data_addr = srcBuffer; + } + /* Out of place */ + else { + pMid->dest_data_addr = dstBuffer; + } + + if (bufferFormat == QAT_COMN_PTR_TYPE_SGL) { + /* Using ScatterGatherLists so set flag in header */ + ICP_QAT_FW_COMN_PTR_TYPE_SET(pReq->comn_hdr.comn_req_flags, + QAT_COMN_PTR_TYPE_SGL); + + /* Assumption: No need to set src and dest length in this case + * as not + * used */ + + } else { + /* Using Flat buffers so set flag in header */ + ICP_QAT_FW_COMN_PTR_TYPE_SET(pReq->comn_hdr.comn_req_flags, + QAT_COMN_PTR_TYPE_FLAT); + + pMid->src_length = srcLength; + pMid->dst_length = dstLength; + } +} + +/******************************************************************** + * @ingroup SalQatMsg_ContentDescHdrWrite + * + * @description + * This function fills in all fields in the + * icp_qat_fw_comn_req_hdr_cd_pars_t section of the Request Msg. + * + * @param[in] pMsg Pointer to 128B Request Msg buffer. + * @param[in] pContentDescInfo content descripter info. + * + * @return + * none + * + *****************************************/ +void +SalQatMsg_ContentDescHdrWrite( + icp_qat_fw_comn_req_t *pMsg, + const sal_qat_content_desc_info_t *pContentDescInfo) +{ + icp_qat_fw_comn_req_hdr_cd_pars_t *pCd_pars = &(pMsg->cd_pars); + + pCd_pars->s.content_desc_addr = + pContentDescInfo->hardwareSetupBlockPhys; + pCd_pars->s.content_desc_params_sz = pContentDescInfo->hwBlkSzQuadWords; + pCd_pars->s.content_desc_resrvd1 = 0; + pCd_pars->s.content_desc_hdr_resrvd2 = 0; + pCd_pars->s.content_desc_resrvd3 = 0; +} + +/******************************************************************** + * @ingroup SalQatMsg_CtrlBlkSetToReserved + * + * @description + * This function sets the whole control block to a reserved state. + * + * @param[in] _pMsg Pointer to 128B Request Msg buffer. + * + * @return + * none + * + *****************************************/ +void +SalQatMsg_CtrlBlkSetToReserved(icp_qat_fw_comn_req_t *pMsg) +{ + + icp_qat_fw_comn_req_cd_ctrl_t *pCd_ctrl = &(pMsg->cd_ctrl); + + memset(pCd_ctrl, 0, sizeof(icp_qat_fw_comn_req_cd_ctrl_t)); +} + +/******************************************************************** + * @ingroup SalQatMsg_transPutMsg + * + * @description + * + * + * @param[in] trans_handle + * @param[in] pqat_msg + * @param[in] size_in_lws + * @param[in] service + * + * @return + * CpaStatus + * + *****************************************/ +CpaStatus +SalQatMsg_transPutMsg(icp_comms_trans_handle trans_handle, + void *pqat_msg, + Cpa32U size_in_lws, + Cpa8U service) +{ + return icp_adf_transPutMsg(trans_handle, pqat_msg, size_in_lws); +} + +void +SalQatMsg_updateQueueTail(icp_comms_trans_handle trans_handle) +{ + icp_adf_updateQueueTail(trans_handle); +} diff --git a/sys/dev/qat/qat_api/common/stubs/lac_stubs.c b/sys/dev/qat/qat_api/common/stubs/lac_stubs.c new file mode 100644 index 000000000000..b9c0c3237a6c --- /dev/null +++ b/sys/dev/qat/qat_api/common/stubs/lac_stubs.c @@ -0,0 +1,413 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * + * @file lac_stubs.c + * + * @defgroup kernel stubs + * + * All PKE and KPT API won't be supported in kernel API + * + *****************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ + +/* API Includes */ +#include "cpa.h" +#include "cpa_cy_dh.h" +#include "cpa_cy_dsa.h" +#include "cpa_cy_ecdh.h" +#include "cpa_cy_ecdsa.h" +#include "cpa_cy_ec.h" +#include "cpa_cy_prime.h" +#include "cpa_cy_rsa.h" +#include "cpa_cy_ln.h" +#include "cpa_dc.h" +#include "icp_accel_devices.h" +#include "icp_adf_init.h" +#include "icp_adf_transport.h" +#include "icp_sal_poll.h" +#include "cpa_cy_sym.h" +#include "cpa_cy_sym_dp.h" +#include "cpa_cy_key.h" +#include "cpa_cy_common.h" +#include "cpa_cy_im.h" +#include "icp_sal_user.h" + +/* Diffie Hellman */ +CpaStatus +cpaCyDhKeyGenPhase1(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pDhPhase1Cb, + void *pCallbackTag, + const CpaCyDhPhase1KeyGenOpData *pPhase1KeyGenData, + CpaFlatBuffer *pLocalOctetStringPV) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyDhKeyGenPhase2Secret( + const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pDhPhase2Cb, + void *pCallbackTag, + const CpaCyDhPhase2SecretKeyGenOpData *pPhase2SecretKeyGenData, + CpaFlatBuffer *pOctetStringSecretKey) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyDhQueryStats64(const CpaInstanceHandle instanceHandle, + CpaCyDhStats64 *pDhStats) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyDhQueryStats(const CpaInstanceHandle instanceHandle, + CpaCyDhStats *pDhStats) +{ + return CPA_STATUS_UNSUPPORTED; +} + +/* DSA */ +CpaStatus +cpaCyDsaGenPParam(const CpaInstanceHandle instanceHandle, + const CpaCyDsaGenCbFunc pCb, + void *pCallbackTag, + const CpaCyDsaPParamGenOpData *pOpData, + CpaBoolean *pProtocolStatus, + CpaFlatBuffer *pP) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyDsaGenGParam(const CpaInstanceHandle instanceHandle, + const CpaCyDsaGenCbFunc pCb, + void *pCallbackTag, + const CpaCyDsaGParamGenOpData *pOpData, + CpaBoolean *pProtocolStatus, + CpaFlatBuffer *pG) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyDsaGenYParam(const CpaInstanceHandle instanceHandle, + const CpaCyDsaGenCbFunc pCb, + void *pCallbackTag, + const CpaCyDsaYParamGenOpData *pOpData, + CpaBoolean *pProtocolStatus, + CpaFlatBuffer *pY) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyDsaSignR(const CpaInstanceHandle instanceHandle, + const CpaCyDsaGenCbFunc pCb, + void *pCallbackTag, + const CpaCyDsaRSignOpData *pOpData, + CpaBoolean *pProtocolStatus, + CpaFlatBuffer *pR) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyDsaSignS(const CpaInstanceHandle instanceHandle, + const CpaCyDsaGenCbFunc pCb, + void *pCallbackTag, + const CpaCyDsaSSignOpData *pOpData, + CpaBoolean *pProtocolStatus, + CpaFlatBuffer *pS) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyDsaSignRS(const CpaInstanceHandle instanceHandle, + const CpaCyDsaRSSignCbFunc pCb, + void *pCallbackTag, + const CpaCyDsaRSSignOpData *pOpData, + CpaBoolean *pProtocolStatus, + CpaFlatBuffer *pR, + CpaFlatBuffer *pS) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyDsaVerify(const CpaInstanceHandle instanceHandle, + const CpaCyDsaVerifyCbFunc pCb, + void *pCallbackTag, + const CpaCyDsaVerifyOpData *pOpData, + CpaBoolean *pVerifyStatus) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyDsaQueryStats(const CpaInstanceHandle instanceHandle, + CpaCyDsaStats *pDsaStats) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyDsaQueryStats64(const CpaInstanceHandle instanceHandle, + CpaCyDsaStats64 *pDsaStats) +{ + return CPA_STATUS_UNSUPPORTED; +} + +/* ECDH */ +CpaStatus +cpaCyEcdhPointMultiply(const CpaInstanceHandle instanceHandle, + const CpaCyEcdhPointMultiplyCbFunc pCb, + void *pCallbackTag, + const CpaCyEcdhPointMultiplyOpData *pOpData, + CpaBoolean *pMultiplyStatus, + CpaFlatBuffer *pXk, + CpaFlatBuffer *pYk) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyEcdhQueryStats64(const CpaInstanceHandle instanceHandle, + CpaCyEcdhStats64 *pEcdhStats) +{ + return CPA_STATUS_UNSUPPORTED; +} + +/* ECDSA */ +CpaStatus +cpaCyEcdsaSignR(const CpaInstanceHandle instanceHandle, + const CpaCyEcdsaGenSignCbFunc pCb, + void *pCallbackTag, + const CpaCyEcdsaSignROpData *pOpData, + CpaBoolean *pSignStatus, + CpaFlatBuffer *pR) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyEcdsaSignS(const CpaInstanceHandle instanceHandle, + const CpaCyEcdsaGenSignCbFunc pCb, + void *pCallbackTag, + const CpaCyEcdsaSignSOpData *pOpData, + CpaBoolean *pSignStatus, + CpaFlatBuffer *pS) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyEcdsaSignRS(const CpaInstanceHandle instanceHandle, + const CpaCyEcdsaSignRSCbFunc pCb, + void *pCallbackTag, + const CpaCyEcdsaSignRSOpData *pOpData, + CpaBoolean *pSignStatus, + CpaFlatBuffer *pR, + CpaFlatBuffer *pS) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyEcdsaVerify(const CpaInstanceHandle instanceHandle, + const CpaCyEcdsaVerifyCbFunc pCb, + void *pCallbackTag, + const CpaCyEcdsaVerifyOpData *pOpData, + CpaBoolean *pVerifyStatus) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyEcdsaQueryStats64(const CpaInstanceHandle instanceHandle, + CpaCyEcdsaStats64 *pEcdsaStats) +{ + return CPA_STATUS_UNSUPPORTED; +} + +/* EC */ +CpaStatus +cpaCyEcPointMultiply(const CpaInstanceHandle instanceHandle, + const CpaCyEcPointMultiplyCbFunc pCb, + void *pCallbackTag, + const CpaCyEcPointMultiplyOpData *pOpData, + CpaBoolean *pMultiplyStatus, + CpaFlatBuffer *pXk, + CpaFlatBuffer *pYk) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyEcPointVerify(const CpaInstanceHandle instanceHandle, + const CpaCyEcPointVerifyCbFunc pCb, + void *pCallbackTag, + const CpaCyEcPointVerifyOpData *pOpData, + CpaBoolean *pVerifyStatus) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyEcQueryStats64(const CpaInstanceHandle instanceHandle, + CpaCyEcStats64 *pEcStats) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyEcMontEdwdsPointMultiply( + const CpaInstanceHandle instanceHandle, + const CpaCyEcPointMultiplyCbFunc pCb, + void *pCallbackTag, + const CpaCyEcMontEdwdsPointMultiplyOpData *pOpData, + CpaBoolean *pMultiplyStatus, + CpaFlatBuffer *pXk, + CpaFlatBuffer *pYk) +{ + return CPA_STATUS_UNSUPPORTED; +} + +/* Prime */ +CpaStatus +cpaCyPrimeTest(const CpaInstanceHandle instanceHandle, + const CpaCyPrimeTestCbFunc pCb, + void *pCallbackTag, + const CpaCyPrimeTestOpData *pOpData, + CpaBoolean *pTestPassed) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyPrimeQueryStats64(const CpaInstanceHandle instanceHandle, + CpaCyPrimeStats64 *pPrimeStats) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyPrimeQueryStats(const CpaInstanceHandle instanceHandle, + CpaCyPrimeStats *pPrimeStats) +{ + return CPA_STATUS_UNSUPPORTED; +} + +/* RSA */ +CpaStatus +cpaCyRsaGenKey(const CpaInstanceHandle instanceHandle, + const CpaCyRsaKeyGenCbFunc pRsaKeyGenCb, + void *pCallbackTag, + const CpaCyRsaKeyGenOpData *pKeyGenOpData, + CpaCyRsaPrivateKey *pPrivateKey, + CpaCyRsaPublicKey *pPublicKey) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyRsaEncrypt(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pRsaEncryptCb, + void *pCallbackTag, + const CpaCyRsaEncryptOpData *pEncryptOpData, + CpaFlatBuffer *pOutputData) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyRsaDecrypt(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pRsaDecryptCb, + void *pCallbackTag, + const CpaCyRsaDecryptOpData *pDecryptOpData, + CpaFlatBuffer *pOutputData) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyRsaQueryStats64(const CpaInstanceHandle instanceHandle, + CpaCyRsaStats64 *pRsaStats) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyRsaQueryStats(const CpaInstanceHandle instanceHandle, + CpaCyRsaStats *pRsaStats) +{ + return CPA_STATUS_UNSUPPORTED; +} + +/* Large Number */ +CpaStatus +cpaCyLnModExp(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pLnModExpCb, + void *pCallbackTag, + const CpaCyLnModExpOpData *pLnModExpOpData, + CpaFlatBuffer *pResult) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyLnModInv(const CpaInstanceHandle instanceHandle, + const CpaCyGenFlatBufCbFunc pLnModInvCb, + void *pCallbackTag, + const CpaCyLnModInvOpData *pLnModInvOpData, + CpaFlatBuffer *pResult) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +cpaCyLnStatsQuery64(const CpaInstanceHandle instanceHandle, + CpaCyLnStats64 *pLnStats) +{ + return CPA_STATUS_UNSUPPORTED; +} + +/* Dynamic Instance */ +CpaStatus +icp_adf_putDynInstance(icp_accel_dev_t *accel_dev, + adf_service_type_t stype, + Cpa32U instance_id) +{ + return CPA_STATUS_FAIL; +} + +CpaStatus +icp_sal_CyPollAsymRing(CpaInstanceHandle instanceHandle_in, + Cpa32U response_quota) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +icp_sal_AsymGetInflightRequests(CpaInstanceHandle instanceHandle, + Cpa32U *maxInflightRequests, + Cpa32U *numInflightRequests) +{ + return CPA_STATUS_UNSUPPORTED; +} + +CpaStatus +icp_sal_AsymPerformOpNow(CpaInstanceHandle instanceHandle) +{ + return CPA_STATUS_UNSUPPORTED; +} diff --git a/sys/dev/qat/qat_api/common/utils/lac_buffer_desc.c b/sys/dev/qat/qat_api/common/utils/lac_buffer_desc.c new file mode 100644 index 000000000000..06a6d9bd768e --- /dev/null +++ b/sys/dev/qat/qat_api/common/utils/lac_buffer_desc.c @@ -0,0 +1,492 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file lac_buffer_desc.c Utility functions for setting buffer descriptors + * + * @ingroup LacBufferDesc + * + *****************************************************************************/ + +/* +******************************************************************************* +* Include header files +******************************************************************************* +*/ +#include "qat_utils.h" +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" +#include "icp_adf_init.h" +#include "lac_list.h" +#include "lac_sal_types.h" +#include "lac_buffer_desc.h" +#include "lac_mem.h" +#include "cpa_cy_common.h" + +/* +******************************************************************************* +* Define public/global function definitions +******************************************************************************* +*/ +/* Invalid physical address value */ +#define INVALID_PHYSICAL_ADDRESS 0 + +/* Indicates what type of buffer writes need to be perfomed */ +typedef enum lac_buff_write_op_e { + WRITE_NORMAL = 0, + WRITE_AND_GET_SIZE, + WRITE_AND_ALLOW_ZERO_BUFFER, +} lac_buff_write_op_t; + +/* This function implements the buffer description writes for the traditional + * APIs */ +static CpaStatus +LacBuffDesc_CommonBufferListDescWrite(const CpaBufferList *pUserBufferList, + Cpa64U *pBufListAlignedPhyAddr, + CpaBoolean isPhysicalAddress, + Cpa64U *totalDataLenInBytes, + sal_service_t *pService, + lac_buff_write_op_t operationType) +{ + Cpa32U numBuffers = 0; + icp_qat_addr_width_t bufListDescPhyAddr = 0; + icp_qat_addr_width_t bufListAlignedPhyAddr = 0; + CpaFlatBuffer *pCurrClientFlatBuffer = NULL; + icp_buffer_list_desc_t *pBufferListDesc = NULL; + icp_flat_buffer_desc_t *pCurrFlatBufDesc = NULL; + + if (WRITE_AND_GET_SIZE == operationType) { + *totalDataLenInBytes = 0; + } + + numBuffers = pUserBufferList->numBuffers; + pCurrClientFlatBuffer = pUserBufferList->pBuffers; + + /* + * Get the physical address of this descriptor - need to offset by the + * alignment restrictions on the buffer descriptors + */ + bufListDescPhyAddr = (icp_qat_addr_width_t)LAC_OS_VIRT_TO_PHYS_EXTERNAL( + (*pService), pUserBufferList->pPrivateMetaData); + + if (bufListDescPhyAddr == 0) { + QAT_UTILS_LOG( + "Unable to get the physical address of the metadata.\n"); + return CPA_STATUS_FAIL; + } + + bufListAlignedPhyAddr = + LAC_ALIGN_POW2_ROUNDUP(bufListDescPhyAddr, + ICP_DESCRIPTOR_ALIGNMENT_BYTES); + + pBufferListDesc = (icp_buffer_list_desc_t *)(LAC_ARCH_UINT)( + (LAC_ARCH_UINT)pUserBufferList->pPrivateMetaData + + ((LAC_ARCH_UINT)bufListAlignedPhyAddr - + (LAC_ARCH_UINT)bufListDescPhyAddr)); + + /* Go past the Buffer List descriptor to the list of buffer descriptors + */ + pCurrFlatBufDesc = + (icp_flat_buffer_desc_t *)((pBufferListDesc->phyBuffers)); + + pBufferListDesc->numBuffers = numBuffers; + + if (WRITE_AND_GET_SIZE != operationType) { + /* Defining zero buffers is useful for example if running zero + * length + * hash */ + if (0 == numBuffers) { + /* In the case where there are zero buffers within the + * BufList + * it is required by firmware that the number is set to + * 1 + * but the phyBuffer and dataLenInBytes are set to + * NULL.*/ + pBufferListDesc->numBuffers = 1; + pCurrFlatBufDesc->dataLenInBytes = 0; + pCurrFlatBufDesc->phyBuffer = 0; + } + } + + while (0 != numBuffers) { + pCurrFlatBufDesc->dataLenInBytes = + pCurrClientFlatBuffer->dataLenInBytes; + + if (WRITE_AND_GET_SIZE == operationType) { + /* Calculate the total data length in bytes */ + *totalDataLenInBytes += + pCurrClientFlatBuffer->dataLenInBytes; + } + + /* Check if providing a physical address in the function. If not + * we + * need to convert it to a physical one */ + if (CPA_TRUE == isPhysicalAddress) { + pCurrFlatBufDesc->phyBuffer = + LAC_MEM_CAST_PTR_TO_UINT64( + (LAC_ARCH_UINT)(pCurrClientFlatBuffer->pData)); + } else { + pCurrFlatBufDesc->phyBuffer = + LAC_MEM_CAST_PTR_TO_UINT64( + LAC_OS_VIRT_TO_PHYS_EXTERNAL( + (*pService), pCurrClientFlatBuffer->pData)); + + if (WRITE_AND_ALLOW_ZERO_BUFFER != operationType) { + if (INVALID_PHYSICAL_ADDRESS == + pCurrFlatBufDesc->phyBuffer) { + QAT_UTILS_LOG( + "Unable to get the physical address of the client buffer.\n"); + return CPA_STATUS_FAIL; + } + } + } + + pCurrFlatBufDesc++; + pCurrClientFlatBuffer++; + + numBuffers--; + } + + *pBufListAlignedPhyAddr = bufListAlignedPhyAddr; + return CPA_STATUS_SUCCESS; +} + +/* This function implements the buffer description writes for the traditional + * APIs Zero length buffers are allowed, should be used for CHA-CHA-POLY and + * GCM aglorithms */ +CpaStatus +LacBuffDesc_BufferListDescWriteAndAllowZeroBuffer( + const CpaBufferList *pUserBufferList, + Cpa64U *pBufListAlignedPhyAddr, + CpaBoolean isPhysicalAddress, + sal_service_t *pService) +{ + return LacBuffDesc_CommonBufferListDescWrite( + pUserBufferList, + pBufListAlignedPhyAddr, + isPhysicalAddress, + NULL, + pService, + WRITE_AND_ALLOW_ZERO_BUFFER); +} + +/* This function implements the buffer description writes for the traditional + * APIs */ +CpaStatus +LacBuffDesc_BufferListDescWrite(const CpaBufferList *pUserBufferList, + Cpa64U *pBufListAlignedPhyAddr, + CpaBoolean isPhysicalAddress, + sal_service_t *pService) +{ + return LacBuffDesc_CommonBufferListDescWrite(pUserBufferList, + pBufListAlignedPhyAddr, + isPhysicalAddress, + NULL, + pService, + WRITE_NORMAL); +} + +/* This function does the same processing as LacBuffDesc_BufferListDescWrite + * but calculate as well the total length in bytes of the buffer list. */ +CpaStatus +LacBuffDesc_BufferListDescWriteAndGetSize(const CpaBufferList *pUserBufferList, + Cpa64U *pBufListAlignedPhyAddr, + CpaBoolean isPhysicalAddress, + Cpa64U *totalDataLenInBytes, + sal_service_t *pService) +{ + Cpa32U numBuffers = 0; + icp_qat_addr_width_t bufListDescPhyAddr = 0; + icp_qat_addr_width_t bufListAlignedPhyAddr = 0; + CpaFlatBuffer *pCurrClientFlatBuffer = NULL; + icp_buffer_list_desc_t *pBufferListDesc = NULL; + icp_flat_buffer_desc_t *pCurrFlatBufDesc = NULL; + *totalDataLenInBytes = 0; + + numBuffers = pUserBufferList->numBuffers; + pCurrClientFlatBuffer = pUserBufferList->pBuffers; + + /* + * Get the physical address of this descriptor - need to offset by the + * alignment restrictions on the buffer descriptors + */ + bufListDescPhyAddr = (icp_qat_addr_width_t)LAC_OS_VIRT_TO_PHYS_EXTERNAL( + (*pService), pUserBufferList->pPrivateMetaData); + + if (INVALID_PHYSICAL_ADDRESS == bufListDescPhyAddr) { + QAT_UTILS_LOG( + "Unable to get the physical address of the metadata.\n"); + return CPA_STATUS_FAIL; + } + + bufListAlignedPhyAddr = + LAC_ALIGN_POW2_ROUNDUP(bufListDescPhyAddr, + ICP_DESCRIPTOR_ALIGNMENT_BYTES); + + pBufferListDesc = (icp_buffer_list_desc_t *)(LAC_ARCH_UINT)( + (LAC_ARCH_UINT)pUserBufferList->pPrivateMetaData + + ((LAC_ARCH_UINT)bufListAlignedPhyAddr - + (LAC_ARCH_UINT)bufListDescPhyAddr)); + + /* Go past the Buffer List descriptor to the list of buffer descriptors + */ + pCurrFlatBufDesc = + (icp_flat_buffer_desc_t *)((pBufferListDesc->phyBuffers)); + + pBufferListDesc->numBuffers = numBuffers; + + while (0 != numBuffers) { + pCurrFlatBufDesc->dataLenInBytes = + pCurrClientFlatBuffer->dataLenInBytes; + + /* Calculate the total data length in bytes */ + *totalDataLenInBytes += pCurrClientFlatBuffer->dataLenInBytes; + + if (isPhysicalAddress == CPA_TRUE) { + pCurrFlatBufDesc->phyBuffer = + LAC_MEM_CAST_PTR_TO_UINT64( + (LAC_ARCH_UINT)(pCurrClientFlatBuffer->pData)); + } else { + pCurrFlatBufDesc->phyBuffer = + LAC_MEM_CAST_PTR_TO_UINT64( + LAC_OS_VIRT_TO_PHYS_EXTERNAL( + (*pService), pCurrClientFlatBuffer->pData)); + + if (pCurrFlatBufDesc->phyBuffer == 0) { + QAT_UTILS_LOG( + "Unable to get the physical address of the client buffer.\n"); + return CPA_STATUS_FAIL; + } + } + + pCurrFlatBufDesc++; + pCurrClientFlatBuffer++; + + numBuffers--; + } + + *pBufListAlignedPhyAddr = bufListAlignedPhyAddr; + return CPA_STATUS_SUCCESS; +} + +CpaStatus +LacBuffDesc_FlatBufferVerify(const CpaFlatBuffer *pUserFlatBuffer, + Cpa64U *pPktSize, + lac_aligment_shift_t alignmentShiftExpected) +{ + LAC_CHECK_NULL_PARAM(pUserFlatBuffer); + LAC_CHECK_NULL_PARAM(pUserFlatBuffer->pData); + + if (0 == pUserFlatBuffer->dataLenInBytes) { + QAT_UTILS_LOG("FlatBuffer empty\n"); + return CPA_STATUS_INVALID_PARAM; + } + + /* Expected alignment */ + if (LAC_NO_ALIGNMENT_SHIFT != alignmentShiftExpected) { + if (!LAC_ADDRESS_ALIGNED(pUserFlatBuffer->pData, + alignmentShiftExpected)) { + QAT_UTILS_LOG( + "FlatBuffer not aligned correctly - expected alignment of %u bytes.\n", + 1 << alignmentShiftExpected); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* Update the total size of the packet. This function being called in a + * loop + * for an entire buffer list we need to increment the value */ + *pPktSize += pUserFlatBuffer->dataLenInBytes; + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +LacBuffDesc_FlatBufferVerifyNull(const CpaFlatBuffer *pUserFlatBuffer, + Cpa64U *pPktSize, + lac_aligment_shift_t alignmentShiftExpected) +{ + LAC_CHECK_NULL_PARAM(pUserFlatBuffer); + + if (0 != pUserFlatBuffer->dataLenInBytes) { + LAC_CHECK_NULL_PARAM(pUserFlatBuffer->pData); + } + + /* Expected alignment */ + if (LAC_NO_ALIGNMENT_SHIFT != alignmentShiftExpected) { + if (!LAC_ADDRESS_ALIGNED(pUserFlatBuffer->pData, + alignmentShiftExpected)) { + QAT_UTILS_LOG( + "FlatBuffer not aligned correctly - expected alignment of %u bytes.\n", + 1 << alignmentShiftExpected); + return CPA_STATUS_INVALID_PARAM; + } + } + + /* Update the total size of the packet. This function being called in a + * loop + * for an entire buffer list we need to increment the value */ + *pPktSize += pUserFlatBuffer->dataLenInBytes; + + return CPA_STATUS_SUCCESS; +} + +CpaStatus +LacBuffDesc_BufferListVerify(const CpaBufferList *pUserBufferList, + Cpa64U *pPktSize, + lac_aligment_shift_t alignmentShiftExpected) +{ + CpaFlatBuffer *pCurrClientFlatBuffer = NULL; + Cpa32U numBuffers = 0; + CpaStatus status = CPA_STATUS_SUCCESS; + + LAC_CHECK_NULL_PARAM(pUserBufferList); + LAC_CHECK_NULL_PARAM(pUserBufferList->pBuffers); + LAC_CHECK_NULL_PARAM(pUserBufferList->pPrivateMetaData); + + numBuffers = pUserBufferList->numBuffers; + + if (0 == pUserBufferList->numBuffers) { + QAT_UTILS_LOG("Number of buffers is 0.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + pCurrClientFlatBuffer = pUserBufferList->pBuffers; + + *pPktSize = 0; + while (0 != numBuffers && status == CPA_STATUS_SUCCESS) { + status = LacBuffDesc_FlatBufferVerify(pCurrClientFlatBuffer, + pPktSize, + alignmentShiftExpected); + + pCurrClientFlatBuffer++; + numBuffers--; + } + return status; +} + +CpaStatus +LacBuffDesc_BufferListVerifyNull(const CpaBufferList *pUserBufferList, + Cpa64U *pPktSize, + lac_aligment_shift_t alignmentShiftExpected) +{ + CpaFlatBuffer *pCurrClientFlatBuffer = NULL; + Cpa32U numBuffers = 0; + CpaStatus status = CPA_STATUS_SUCCESS; + + LAC_CHECK_NULL_PARAM(pUserBufferList); + LAC_CHECK_NULL_PARAM(pUserBufferList->pBuffers); + LAC_CHECK_NULL_PARAM(pUserBufferList->pPrivateMetaData); + + numBuffers = pUserBufferList->numBuffers; + + if (0 == pUserBufferList->numBuffers) { + QAT_UTILS_LOG("Number of buffers is 0.\n"); + return CPA_STATUS_INVALID_PARAM; + } + + pCurrClientFlatBuffer = pUserBufferList->pBuffers; + + *pPktSize = 0; + while (0 != numBuffers && status == CPA_STATUS_SUCCESS) { + status = + LacBuffDesc_FlatBufferVerifyNull(pCurrClientFlatBuffer, + pPktSize, + alignmentShiftExpected); + + pCurrClientFlatBuffer++; + numBuffers--; + } + return status; +} + +/** + ****************************************************************************** + * @ingroup LacBufferDesc + *****************************************************************************/ +void +LacBuffDesc_BufferListTotalSizeGet(const CpaBufferList *pUserBufferList, + Cpa64U *pPktSize) +{ + CpaFlatBuffer *pCurrClientFlatBuffer = NULL; + Cpa32U numBuffers = 0; + + pCurrClientFlatBuffer = pUserBufferList->pBuffers; + numBuffers = pUserBufferList->numBuffers; + + *pPktSize = 0; + while (0 != numBuffers) { + *pPktSize += pCurrClientFlatBuffer->dataLenInBytes; + pCurrClientFlatBuffer++; + numBuffers--; + } +} + +void +LacBuffDesc_BufferListZeroFromOffset(CpaBufferList *pBuffList, + Cpa32U offset, + Cpa32U lenToZero) +{ + Cpa32U zeroLen = 0, sizeLeftToZero = 0; + Cpa64U currentBufferSize = 0; + CpaFlatBuffer *pBuffer = NULL; + Cpa8U *pZero = NULL; + pBuffer = pBuffList->pBuffers; + + /* Take a copy of total length to zero. */ + sizeLeftToZero = lenToZero; + + while (sizeLeftToZero > 0) { + currentBufferSize = pBuffer->dataLenInBytes; + /* check where to start zeroing */ + if (offset >= currentBufferSize) { + /* Need to get to next buffer and reduce + * offset size by data len of buffer */ + offset = offset - pBuffer->dataLenInBytes; + pBuffer++; + } else { + /* Start to Zero from this position */ + pZero = (Cpa8U *)pBuffer->pData + offset; + + /* Need to calculate the correct number of bytes to zero + * for this iteration and for this location. + */ + if (sizeLeftToZero >= pBuffer->dataLenInBytes) { + /* The size to zero is spanning buffers, zeroLen + * in + * this case is from pZero (position) to end of + * buffer. + */ + zeroLen = pBuffer->dataLenInBytes - offset; + } else { + /* zeroLen is set to sizeLeftToZero, then check + * if zeroLen and + * the offset is greater or equal to the size of + * the buffer, if + * yes, adjust the zeroLen to zero out the + * remainder of this + * buffer. + */ + zeroLen = sizeLeftToZero; + if ((zeroLen + offset) >= + pBuffer->dataLenInBytes) { + zeroLen = + pBuffer->dataLenInBytes - offset; + } + } /* end inner else */ + memset((void *)pZero, 0, zeroLen); + sizeLeftToZero = sizeLeftToZero - zeroLen; + /* offset is no longer required as any data left to zero + * is now + * at the start of the next buffer. set offset to zero + * and move on + * the buffer pointer to the next buffer. + */ + offset = 0; + pBuffer++; + + } /* end outer else */ + + } /* end while */ +} diff --git a/sys/dev/qat/qat_api/common/utils/lac_lock_free_stack.h b/sys/dev/qat/qat_api/common/utils/lac_lock_free_stack.h new file mode 100644 index 000000000000..fda9b0691e03 --- /dev/null +++ b/sys/dev/qat/qat_api/common/utils/lac_lock_free_stack.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +#ifndef LAC_LOCK_FREE_STACK_H_1 +#define LAC_LOCK_FREE_STACK_H_1 +#include "lac_mem_pools.h" + +typedef union { + struct { + uint64_t ctr : 16; + uint64_t ptr : 48; + }; + uint64_t atomic; +} pointer_t; + +typedef struct { + volatile pointer_t top; +} lock_free_stack_t; + +static inline void * +PTR(const uintptr_t addr48) +{ +#ifdef __x86_64__ + const int64_t addr64 = addr48 << 16; + + /* Do arithmetic shift to restore kernel canonical address (if not NULL) + */ + return (void *)(addr64 >> 16); +#else + return (void *)(addr48); +#endif +} + +static inline lac_mem_blk_t * +pop(lock_free_stack_t *stack) +{ + pointer_t old_top; + pointer_t new_top; + lac_mem_blk_t *next; + + do { + old_top.atomic = stack->top.atomic; + next = PTR(old_top.ptr); + if (NULL == next) + return next; + + new_top.ptr = (uintptr_t)next->pNext; + new_top.ctr = old_top.ctr + 1; + } while (!__sync_bool_compare_and_swap(&stack->top.atomic, + old_top.atomic, + new_top.atomic)); + + return next; +} + +static inline void +push(lock_free_stack_t *stack, lac_mem_blk_t *val) +{ + pointer_t new_top; + pointer_t old_top; + + do { + old_top.atomic = stack->top.atomic; + val->pNext = PTR(old_top.ptr); + new_top.ptr = (uintptr_t)val; + new_top.ctr = old_top.ctr + 1; + } while (!__sync_bool_compare_and_swap(&stack->top.atomic, + old_top.atomic, + new_top.atomic)); +} + +static inline lock_free_stack_t +_init_stack(void) +{ + lock_free_stack_t stack = { { { 0 } } }; + return stack; +} + +static inline lac_mem_blk_t * +top(lock_free_stack_t *stack) +{ + pointer_t old_top = stack->top; + lac_mem_blk_t *next = PTR(old_top.ptr); + return next; +} + +#endif diff --git a/sys/dev/qat/qat_api/common/utils/lac_mem.c b/sys/dev/qat/qat_api/common/utils/lac_mem.c new file mode 100644 index 000000000000..66bd59815e6d --- /dev/null +++ b/sys/dev/qat/qat_api/common/utils/lac_mem.c @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file lac_mem.c Implementation of Memory Functions + * + * @ingroup LacMem + * + *****************************************************************************/ + +/* +******************************************************************************* +* Include header files +******************************************************************************* +*/ +#include "qat_utils.h" +#include "cpa.h" + +#include "icp_accel_devices.h" +#include "icp_adf_init.h" +#include "icp_adf_transport.h" +#include "icp_adf_debug.h" +#include "icp_sal_iommu.h" + +#include "lac_mem.h" +#include "lac_mem_pools.h" +#include "lac_common.h" +#include "lac_list.h" +#include "icp_qat_fw_la.h" +#include "lac_sal_types.h" + +/* +******************************************************************************** +* Static Variables +******************************************************************************** +*/ + +#define MAX_BUFFER_SIZE (LAC_BITS_TO_BYTES(4096)) +/**< @ingroup LacMem + * Maximum size of the buffers used in the resize function */ + +/* +******************************************************************************* +* Define public/global function definitions +******************************************************************************* +*/ +/** + * @ingroup LacMem + */ +CpaStatus +icp_LacBufferRestore(Cpa8U *pUserBuffer, + Cpa32U userLen, + Cpa8U *pWorkingBuffer, + Cpa32U workingLen, + CpaBoolean copyBuf) +{ + Cpa32U padSize = 0; + + /* NULL is a valid value for working buffer as this function may be + * called to clean up in an error case where all the resize operations + * were not completed */ + if (NULL == pWorkingBuffer) { + return CPA_STATUS_SUCCESS; + } + + if (workingLen < userLen) { + QAT_UTILS_LOG("Invalid buffer sizes\n"); + return CPA_STATUS_INVALID_PARAM; + } + + if (pUserBuffer != pWorkingBuffer) { + + if (CPA_TRUE == copyBuf) { + /* Copy from internal buffer to user buffer */ + padSize = workingLen - userLen; + memcpy(pUserBuffer, pWorkingBuffer + padSize, userLen); + } + + Lac_MemPoolEntryFree(pWorkingBuffer); + } + return CPA_STATUS_SUCCESS; +} + +/** + * @ingroup LacMem + */ +CpaPhysicalAddr +SalMem_virt2PhysExternal(void *pVirtAddr, void *pServiceGen) +{ + sal_service_t *pService = (sal_service_t *)pServiceGen; + + if (NULL != pService->virt2PhysClient) { + return pService->virt2PhysClient(pVirtAddr); + } else { + /* Use internal QAT Utils virt to phys */ + /* Ok for kernel space probably should not use for user */ + return LAC_OS_VIRT_TO_PHYS_INTERNAL(pVirtAddr); + } +} + +size_t +icp_sal_iommu_get_remap_size(size_t size) +{ + return size; +} + +CpaStatus +icp_sal_iommu_map(Cpa64U phaddr, Cpa64U iova, size_t size) +{ + return CPA_STATUS_SUCCESS; +} + +CpaStatus +icp_sal_iommu_unmap(Cpa64U iova, size_t size) +{ + return CPA_STATUS_SUCCESS; +} diff --git a/sys/dev/qat/qat_api/common/utils/lac_mem_pools.c b/sys/dev/qat/qat_api/common/utils/lac_mem_pools.c new file mode 100644 index 000000000000..7bd584bc775f --- /dev/null +++ b/sys/dev/qat/qat_api/common/utils/lac_mem_pools.c @@ -0,0 +1,430 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file lac_mem_pools.c + * + * @ingroup LacMemPool + * + * Memory Pool creation and mgmt function implementations + * + ***************************************************************************/ + +#include "cpa.h" +#include "qat_utils.h" +#include "icp_accel_devices.h" +#include "icp_adf_init.h" +#include "icp_adf_transport.h" +#include "icp_adf_debug.h" +#include "lac_lock_free_stack.h" +#include "lac_mem_pools.h" +#include "lac_mem.h" +#include "lac_common.h" +#include "cpa_dc.h" +#include "dc_session.h" +#include "dc_datapath.h" +#include "icp_qat_fw_comp.h" +#include "icp_buffer_desc.h" +#include "lac_sym.h" + +#define LAC_MEM_POOLS_NUM_SUPPORTED 32000 +/**< @ingroup LacMemPool + * Number of mem pools supported */ + +#define LAC_MEM_POOLS_NAME_SIZE 17 +/**< @ingroup LacMemPool + * 16 bytes plus '\\0' terminator */ + +/**< @ingroup LacMemPool + * This structure is used to manage each pool created using this utility + * feature. The client will maintain a pointer (identifier) to the created + * structure per pool. + */ +typedef struct lac_mem_pool_hdr_s { + lock_free_stack_t stack; + char poolName[LAC_MEM_POOLS_NAME_SIZE]; /*16 bytes of a pool name */ + /**< up to 16 bytes of a pool name */ + unsigned int numElementsInPool; + /**< number of elements in the Pool */ + unsigned int blkSizeInBytes; + /**< Block size in bytes */ + unsigned int blkAlignmentInBytes; + /**< block alignment in bytes */ + lac_mem_blk_t **trackBlks; + /* An array of mem block pointers to track the allocated entries in pool + */ + volatile size_t availBlks; + /* Number of blocks available for allocation in this pool */ +} lac_mem_pool_hdr_t; + +static lac_mem_pool_hdr_t *lac_mem_pools[LAC_MEM_POOLS_NUM_SUPPORTED] = { + NULL +}; +/**< @ingroup LacMemPool + * Array of pointers to the mem pool header structure + */ + +LAC_DECLARE_HIGHEST_BIT_OF(lac_mem_blk_t); +/**< @ingroup LacMemPool + * local constant for quickening computation of additional space allocated + * for holding lac_mem_blk_t container-structure + */ + +/** + ******************************************************************************* + * @ingroup LacMemPool + * This function cleans up a mem pool. + ******************************************************************************/ +void Lac_MemPoolCleanUpInternal(lac_mem_pool_hdr_t *pPoolID); + +static inline Cpa32U +Lac_MemPoolGetElementRealSize(Cpa32U blkSizeInBytes, Cpa32U blkAlignmentInBytes) +{ + Cpa32U addSize = (blkAlignmentInBytes >= sizeof(lac_mem_blk_t) ? + blkAlignmentInBytes : + 1 << (highest_bit_of_lac_mem_blk_t + 1)); + return blkSizeInBytes + addSize; +} + +CpaStatus +Lac_MemPoolCreate(lac_memory_pool_id_t *pPoolID, + char *poolName, + unsigned int numElementsInPool, /*Number of elements*/ + unsigned int blkSizeInBytes, /*Block Size in bytes*/ + unsigned int blkAlignmentInBytes, /*Block alignment (bytes)*/ + CpaBoolean trackMemory, + Cpa32U node) +{ + unsigned int poolSearch = 0; + unsigned int counter = 0; + lac_mem_blk_t *pMemBlkCurrent = NULL; + + void *pMemBlk = NULL; + + if (pPoolID == NULL) { + QAT_UTILS_LOG("Invalid Pool ID param\n"); + return CPA_STATUS_INVALID_PARAM; /*Error*/ + } + + /* Find First available Pool return error otherwise */ + while (lac_mem_pools[poolSearch] != NULL) { + poolSearch++; + if (LAC_MEM_POOLS_NUM_SUPPORTED == poolSearch) { + QAT_UTILS_LOG( + "No more memory pools available for allocation.\n"); + return CPA_STATUS_FAIL; + } + } + + /* Allocate a Pool header */ + lac_mem_pools[poolSearch] = LAC_OS_MALLOC(sizeof(lac_mem_pool_hdr_t)); + if (NULL == lac_mem_pools[poolSearch]) { + QAT_UTILS_LOG( + "Unable to allocate memory for creation of the pool.\n"); + return CPA_STATUS_RESOURCE; /*Error*/ + } + memset(lac_mem_pools[poolSearch], 0, sizeof(lac_mem_pool_hdr_t)); + + /* Copy in Pool Name */ + if (poolName != NULL) { + snprintf(lac_mem_pools[poolSearch]->poolName, + LAC_MEM_POOLS_NAME_SIZE, + "%s", + poolName); + } else { + LAC_OS_FREE(lac_mem_pools[poolSearch]); + lac_mem_pools[poolSearch] = NULL; + QAT_UTILS_LOG("Invalid Pool Name pointer\n"); + return CPA_STATUS_INVALID_PARAM; /*Error*/ + } + + /* Allocate table for tracking memory blocks */ + if (CPA_TRUE == trackMemory) { + lac_mem_pools[poolSearch]->trackBlks = LAC_OS_MALLOC( + (sizeof(lac_mem_blk_t *) * numElementsInPool)); + if (NULL == lac_mem_pools[poolSearch]->trackBlks) { + LAC_OS_FREE(lac_mem_pools[poolSearch]); + lac_mem_pools[poolSearch] = NULL; + QAT_UTILS_LOG( + "Unable to allocate memory for tracking memory blocks.\n"); + return CPA_STATUS_RESOURCE; /*Error*/ + } + } else { + lac_mem_pools[poolSearch]->trackBlks = NULL; + } + + lac_mem_pools[poolSearch]->availBlks = 0; + lac_mem_pools[poolSearch]->stack = _init_stack(); + + /* Calculate alignment needed for allocation */ + for (counter = 0; counter < numElementsInPool; counter++) { + CpaPhysicalAddr physAddr = 0; + /* realSize is computed for allocation of blkSize bytes + + additional + capacity for lac_mem_blk_t structure storage due to the some + OSes + (BSD) limitations for memory alignment to be power of 2; + sizeof(lac_mem_blk_t) is being round up to the closest power + of 2 - + optimised towards the least CPU overhead but at additional + memory + cost + */ + Cpa32U realSize = + Lac_MemPoolGetElementRealSize(blkSizeInBytes, + blkAlignmentInBytes); + Cpa32U addSize = realSize - blkSizeInBytes; + + if (CPA_STATUS_SUCCESS != LAC_OS_CAMALLOC(&pMemBlk, + realSize, + blkAlignmentInBytes, + node)) { + Lac_MemPoolCleanUpInternal(lac_mem_pools[poolSearch]); + lac_mem_pools[poolSearch] = NULL; + QAT_UTILS_LOG( + "Unable to allocate contiguous chunk of memory.\n"); + return CPA_STATUS_RESOURCE; + } + + /* Calcaulate various offsets */ + physAddr = LAC_OS_VIRT_TO_PHYS_INTERNAL( + (void *)((LAC_ARCH_UINT)pMemBlk + addSize)); + + /* physAddr is now already aligned to the greater power of 2: + blkAlignmentInBytes or sizeof(lac_mem_blk_t) round up + We safely put the structure right before the blkSize + real data block + */ + pMemBlkCurrent = + (lac_mem_blk_t *)(((LAC_ARCH_UINT)(pMemBlk)) + addSize - + sizeof(lac_mem_blk_t)); + + pMemBlkCurrent->physDataPtr = physAddr; + pMemBlkCurrent->pMemAllocPtr = pMemBlk; + pMemBlkCurrent->pPoolID = lac_mem_pools[poolSearch]; + pMemBlkCurrent->isInUse = CPA_FALSE; + pMemBlkCurrent->pNext = NULL; + + push(&lac_mem_pools[poolSearch]->stack, pMemBlkCurrent); + + /* Store allocated memory pointer */ + if (lac_mem_pools[poolSearch]->trackBlks != NULL) { + (lac_mem_pools[poolSearch]->trackBlks[counter]) = + (lac_mem_blk_t *)pMemBlkCurrent; + } + __sync_add_and_fetch(&lac_mem_pools[poolSearch]->availBlks, 1); + (lac_mem_pools[poolSearch])->numElementsInPool = counter + 1; + } + + /* Set Pool details in the header */ + (lac_mem_pools[poolSearch])->blkSizeInBytes = blkSizeInBytes; + (lac_mem_pools[poolSearch])->blkAlignmentInBytes = blkAlignmentInBytes; + /* Set the Pool ID output parameter */ + *pPoolID = (LAC_ARCH_UINT)(lac_mem_pools[poolSearch]); + /* Success */ + return CPA_STATUS_SUCCESS; +} + +void * +Lac_MemPoolEntryAlloc(lac_memory_pool_id_t poolID) +{ + lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)poolID; + lac_mem_blk_t *pMemBlkCurrent = NULL; + + /* Explicitly removing NULL PoolID check for speed */ + if (pPoolID == NULL) { + QAT_UTILS_LOG("Invalid Pool ID"); + return NULL; + } + + /* Remove block from pool */ + pMemBlkCurrent = pop(&pPoolID->stack); + if (NULL == pMemBlkCurrent) { + return (void *)CPA_STATUS_RETRY; + } + __sync_sub_and_fetch(&pPoolID->availBlks, 1); + pMemBlkCurrent->isInUse = CPA_TRUE; + return (void *)((LAC_ARCH_UINT)(pMemBlkCurrent) + + sizeof(lac_mem_blk_t)); +} + +void +Lac_MemPoolEntryFree(void *pEntry) +{ + lac_mem_blk_t *pMemBlk = NULL; + + /* Explicitly NULL pointer check */ + if (pEntry == NULL) { + QAT_UTILS_LOG("Memory Handle NULL"); + return; + } + + pMemBlk = + (lac_mem_blk_t *)((LAC_ARCH_UINT)pEntry - sizeof(lac_mem_blk_t)); + pMemBlk->isInUse = CPA_FALSE; + + push(&pMemBlk->pPoolID->stack, pMemBlk); + __sync_add_and_fetch(&pMemBlk->pPoolID->availBlks, 1); +} + +void +Lac_MemPoolDestroy(lac_memory_pool_id_t poolID) +{ + unsigned int poolSearch = 0; + lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)poolID; + + if (pPoolID != NULL) { + /*Remove entry from table*/ + while (lac_mem_pools[poolSearch] != pPoolID) { + poolSearch++; + + if (LAC_MEM_POOLS_NUM_SUPPORTED == poolSearch) { + QAT_UTILS_LOG("Invalid Pool ID submitted.\n"); + return; + } + } + + lac_mem_pools[poolSearch] = NULL; /*Remove handle from pool*/ + + Lac_MemPoolCleanUpInternal(pPoolID); + } +} + +void +Lac_MemPoolCleanUpInternal(lac_mem_pool_hdr_t *pPoolID) +{ + lac_mem_blk_t *pCurrentBlk = NULL; + void *pFreePtr = NULL; + Cpa32U count = 0; + + if (pPoolID->trackBlks == NULL) { + pCurrentBlk = pop(&pPoolID->stack); + + while (pCurrentBlk != NULL) { + /* Free Data Blocks */ + pFreePtr = pCurrentBlk->pMemAllocPtr; + pCurrentBlk = pop(&pPoolID->stack); + LAC_OS_CAFREE(pFreePtr); + } + } else { + for (count = 0; count < pPoolID->numElementsInPool; count++) { + pFreePtr = (pPoolID->trackBlks[count])->pMemAllocPtr; + LAC_OS_CAFREE(pFreePtr); + } + LAC_OS_FREE(pPoolID->trackBlks); + } + LAC_OS_FREE(pPoolID); +} + +unsigned int +Lac_MemPoolAvailableEntries(lac_memory_pool_id_t poolID) +{ + lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)poolID; + if (pPoolID == NULL) { + QAT_UTILS_LOG("Invalid Pool ID\n"); + return 0; + } + return pPoolID->availBlks; +} + +void +Lac_MemPoolStatsShow(void) +{ + unsigned int index = 0; + QAT_UTILS_LOG(SEPARATOR BORDER + " Memory Pools Stats\n" SEPARATOR); + + while (index < LAC_MEM_POOLS_NUM_SUPPORTED) { + if (lac_mem_pools[index] != NULL) { + QAT_UTILS_LOG( + BORDER " Pool Name: %s \n" BORDER + " No. Elements in Pool: %10u \n" BORDER + " Element Size in Bytes: %10u \n" BORDER + " Alignment in Bytes: %10u \n" BORDER + " No. Available Blocks: %10zu \n" SEPARATOR, + lac_mem_pools[index]->poolName, + lac_mem_pools[index]->numElementsInPool, + lac_mem_pools[index]->blkSizeInBytes, + lac_mem_pools[index]->blkAlignmentInBytes, + lac_mem_pools[index]->availBlks); + } + index++; + } +} + +static void +Lac_MemPoolInitSymCookies(lac_sym_cookie_t *pSymCookie) +{ + pSymCookie->keyContentDescPhyAddr = + LAC_OS_VIRT_TO_PHYS_INTERNAL(pSymCookie->u.keyCookie.contentDesc); + pSymCookie->keyHashStateBufferPhyAddr = LAC_OS_VIRT_TO_PHYS_INTERNAL( + pSymCookie->u.keyCookie.hashStateBuffer); + pSymCookie->keySslKeyInputPhyAddr = LAC_OS_VIRT_TO_PHYS_INTERNAL( + &(pSymCookie->u.keyCookie.u.sslKeyInput)); + pSymCookie->keyTlsKeyInputPhyAddr = LAC_OS_VIRT_TO_PHYS_INTERNAL( + &(pSymCookie->u.keyCookie.u.tlsKeyInput)); +} + +CpaStatus +Lac_MemPoolInitSymCookiesPhyAddr(lac_memory_pool_id_t poolID) +{ + lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)poolID; + lac_sym_cookie_t *pSymCookie = NULL; + lac_mem_blk_t *pCurrentBlk = NULL; + + if (NULL == pPoolID) { + QAT_UTILS_LOG("Invalid Pool ID\n"); + return CPA_STATUS_FAIL; + } + + if (pPoolID->trackBlks == NULL) { + pCurrentBlk = top(&pPoolID->stack); + + while (pCurrentBlk != NULL) { + pSymCookie = + (lac_sym_cookie_t *)((LAC_ARCH_UINT)(pCurrentBlk) + + sizeof(lac_mem_blk_t)); + pCurrentBlk = pCurrentBlk->pNext; + Lac_MemPoolInitSymCookies(pSymCookie); + } + } else { + Cpa32U count = 0; + + for (count = 0; count < pPoolID->numElementsInPool; count++) { + pCurrentBlk = pPoolID->trackBlks[count]; + pSymCookie = + (lac_sym_cookie_t *)((LAC_ARCH_UINT)(pCurrentBlk) + + sizeof(lac_mem_blk_t)); + Lac_MemPoolInitSymCookies(pSymCookie); + } + } + return CPA_STATUS_SUCCESS; +} + +CpaStatus +Lac_MemPoolInitDcCookiePhyAddr(lac_memory_pool_id_t poolID) +{ + lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)poolID; + lac_mem_blk_t *pCurrentBlk = NULL; + + if (NULL == pPoolID) { + QAT_UTILS_LOG("Invalid Pool ID\n"); + return CPA_STATUS_FAIL; + } + + if (NULL == pPoolID->trackBlks) { + pCurrentBlk = top(&pPoolID->stack); + + while (pCurrentBlk != NULL) { + pCurrentBlk = pCurrentBlk->pNext; + } + } else { + Cpa32U count = 0; + + for (count = 0; count < pPoolID->numElementsInPool; count++) { + pCurrentBlk = pPoolID->trackBlks[count]; + } + } + return CPA_STATUS_SUCCESS; +} diff --git a/sys/dev/qat/qat_api/common/utils/lac_sync.c b/sys/dev/qat/qat_api/common/utils/lac_sync.c new file mode 100644 index 000000000000..25a2f9764bee --- /dev/null +++ b/sys/dev/qat/qat_api/common/utils/lac_sync.c @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file lac_sync.c Utility functions containing synchronous callback support + * functions + * + * @ingroup LacSync + * + *****************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ +#include "lac_sync.h" +#include "lac_common.h" + +/* +******************************************************************************* +* Define public/global function definitions +******************************************************************************* +*/ + +/** + ***************************************************************************** + * @ingroup LacSync + *****************************************************************************/ +void +LacSync_GenWakeupSyncCaller(void *pCallbackTag, CpaStatus status) +{ + lac_sync_op_data_t *pSc = (lac_sync_op_data_t *)pCallbackTag; + if (pSc != NULL) { + if (pSc->canceled) { + QAT_UTILS_LOG("Synchronous operation cancelled.\n"); + return; + } + pSc->status = status; + if (CPA_STATUS_SUCCESS != LAC_POST_SEMAPHORE(pSc->sid)) { + QAT_UTILS_LOG("Failed to post semaphore.\n"); + } + } +} + +/** + ***************************************************************************** + * @ingroup LacSync + *****************************************************************************/ +void +LacSync_GenVerifyWakeupSyncCaller(void *pCallbackTag, + CpaStatus status, + CpaBoolean opResult) +{ + lac_sync_op_data_t *pSc = (lac_sync_op_data_t *)pCallbackTag; + if (pSc != NULL) { + if (pSc->canceled) { + QAT_UTILS_LOG("Synchronous operation cancelled.\n"); + return; + } + pSc->status = status; + pSc->opResult = opResult; + if (CPA_STATUS_SUCCESS != LAC_POST_SEMAPHORE(pSc->sid)) { + QAT_UTILS_LOG("Failed to post semaphore.\n"); + } + } +} + +/** + ***************************************************************************** + * @ingroup LacSync + *****************************************************************************/ +void +LacSync_GenVerifyCb(void *pCallbackTag, + CpaStatus status, + void *pOpData, + CpaBoolean opResult) +{ + LacSync_GenVerifyWakeupSyncCaller(pCallbackTag, status, opResult); +} + +/** + ***************************************************************************** + * @ingroup LacSync + *****************************************************************************/ +void +LacSync_GenFlatBufCb(void *pCallbackTag, + CpaStatus status, + void *pOpData, + CpaFlatBuffer *pOut) +{ + LacSync_GenWakeupSyncCaller(pCallbackTag, status); +} + +/** + ***************************************************************************** + * @ingroup LacSync + *****************************************************************************/ +void +LacSync_GenFlatBufVerifyCb(void *pCallbackTag, + CpaStatus status, + void *pOpData, + CpaBoolean opResult, + CpaFlatBuffer *pOut) +{ + LacSync_GenVerifyWakeupSyncCaller(pCallbackTag, status, opResult); +} + +/** + ***************************************************************************** + * @ingroup LacSync + *****************************************************************************/ +void +LacSync_GenDualFlatBufVerifyCb(void *pCallbackTag, + CpaStatus status, + void *pOpdata, + CpaBoolean opResult, + CpaFlatBuffer *pOut0, + CpaFlatBuffer *pOut1) +{ + LacSync_GenVerifyWakeupSyncCaller(pCallbackTag, status, opResult); +} diff --git a/sys/dev/qat/qat_api/common/utils/sal_service_state.c b/sys/dev/qat/qat_api/common/utils/sal_service_state.c new file mode 100644 index 000000000000..c2fa491e7b73 --- /dev/null +++ b/sys/dev/qat/qat_api/common/utils/sal_service_state.c @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + *************************************************************************** + * @file sal_service_state.c Service state checks + * + * @ingroup SalServiceState + * + ***************************************************************************/ + +/* +******************************************************************************* +* Include public/global header files +******************************************************************************* +*/ + +#include "cpa.h" +#include "qat_utils.h" +#include "lac_list.h" +#include "icp_accel_devices.h" +#include "icp_adf_debug.h" +#include "lac_sal_types.h" +#include "sal_service_state.h" + +CpaBoolean +Sal_ServiceIsRunning(CpaInstanceHandle instanceHandle) +{ + sal_service_t *pService = (sal_service_t *)instanceHandle; + + if (SAL_SERVICE_STATE_RUNNING == pService->state) { + return CPA_TRUE; + } + return CPA_FALSE; +} + +CpaBoolean +Sal_ServiceIsRestarting(CpaInstanceHandle instanceHandle) +{ + sal_service_t *pService = (sal_service_t *)instanceHandle; + + if (SAL_SERVICE_STATE_RESTARTING == pService->state) { + return CPA_TRUE; + } + return CPA_FALSE; +} diff --git a/sys/dev/qat/qat_api/common/utils/sal_statistics.c b/sys/dev/qat/qat_api/common/utils/sal_statistics.c new file mode 100644 index 000000000000..e311f22283be --- /dev/null +++ b/sys/dev/qat/qat_api/common/utils/sal_statistics.c @@ -0,0 +1,203 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file sal_statistics.c + * + * @defgroup SalStats Sal Statistics + * + * @ingroup SalStats + * + * @description + * This file contains implementation of statistic related functions + * + *****************************************************************************/ + +#include "cpa.h" +#include "lac_common.h" +#include "lac_mem.h" +#include "icp_adf_cfg.h" +#include "icp_accel_devices.h" +#include "sal_statistics.h" + +#include "icp_adf_debug.h" +#include "lac_sal_types.h" +#include "lac_sal.h" + +/** + ****************************************************************************** + * @ingroup SalStats + * Reads from the config file if the given statistic is enabled + * + * @description + * Reads from the config file if the given statistic is enabled + * + * @param[in] device Pointer to an acceleration device structure + * @param[in] statsName Name of the config value to read the value from + * @param[out] pIsEnabled Pointer to a variable where information if the + * given stat is enabled or disabled will be stored + * + * @retval CPA_STATUS_SUCCESS Operation successful + * @retval CPA_STATUS_INVALID_PARAM Invalid param provided + * @retval CPA_STATUS_FAIL Operation failed + * + ******************************************************************************/ +static CpaStatus +SalStatistics_GetStatEnabled(icp_accel_dev_t *device, + const char *statsName, + CpaBoolean *pIsEnabled) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + char param_value[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + + LAC_CHECK_NULL_PARAM(pIsEnabled); + LAC_CHECK_NULL_PARAM(statsName); + + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + statsName, + param_value); + + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get %s from configuration.\n", + statsName); + return status; + } + + if (0 == strncmp(param_value, + SAL_STATISTICS_STRING_OFF, + strlen(SAL_STATISTICS_STRING_OFF))) { + *pIsEnabled = CPA_FALSE; + } else { + *pIsEnabled = CPA_TRUE; + } + + return status; +} + +/* @ingroup SalStats */ +CpaStatus +SalStatistics_InitStatisticsCollection(icp_accel_dev_t *device) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + sal_statistics_collection_t *pStatsCollection = NULL; + Cpa32U enabled_services = 0; + + LAC_CHECK_NULL_PARAM(device); + + pStatsCollection = LAC_OS_MALLOC(sizeof(sal_statistics_collection_t)); + if (NULL == pStatsCollection) { + QAT_UTILS_LOG("Failed to allocate memory for statistic.\n"); + return CPA_STATUS_RESOURCE; + } + device->pQatStats = pStatsCollection; + + status = SalStatistics_GetStatEnabled(device, + SAL_STATS_CFG_ENABLED, + &pStatsCollection->bStatsEnabled); + LAC_CHECK_STATUS(status); + + if (CPA_FALSE == pStatsCollection->bStatsEnabled) { + pStatsCollection->bDcStatsEnabled = CPA_FALSE; + pStatsCollection->bDhStatsEnabled = CPA_FALSE; + pStatsCollection->bDsaStatsEnabled = CPA_FALSE; + pStatsCollection->bEccStatsEnabled = CPA_FALSE; + pStatsCollection->bKeyGenStatsEnabled = CPA_FALSE; + pStatsCollection->bLnStatsEnabled = CPA_FALSE; + pStatsCollection->bPrimeStatsEnabled = CPA_FALSE; + pStatsCollection->bRsaStatsEnabled = CPA_FALSE; + pStatsCollection->bSymStatsEnabled = CPA_FALSE; + + return status; + } + + /* What services are enabled */ + status = SalCtrl_GetEnabledServices(device, &enabled_services); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Failed to get enabled services.\n"); + return CPA_STATUS_FAIL; + } + + /* Check if the compression service is enabled */ + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_COMPRESSION)) { + status = SalStatistics_GetStatEnabled( + device, + SAL_STATS_CFG_DC, + &pStatsCollection->bDcStatsEnabled); + LAC_CHECK_STATUS(status); + } + /* Check if the asym service is enabled */ + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO_ASYM) || + SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO)) { + status = SalStatistics_GetStatEnabled( + device, + SAL_STATS_CFG_DH, + &pStatsCollection->bDhStatsEnabled); + LAC_CHECK_STATUS(status); + + status = SalStatistics_GetStatEnabled( + device, + SAL_STATS_CFG_DSA, + &pStatsCollection->bDsaStatsEnabled); + LAC_CHECK_STATUS(status); + + status = SalStatistics_GetStatEnabled( + device, + SAL_STATS_CFG_ECC, + &pStatsCollection->bEccStatsEnabled); + LAC_CHECK_STATUS(status); + + status = SalStatistics_GetStatEnabled( + device, + SAL_STATS_CFG_KEYGEN, + &pStatsCollection->bKeyGenStatsEnabled); + LAC_CHECK_STATUS(status); + + status = SalStatistics_GetStatEnabled( + device, + SAL_STATS_CFG_LN, + &pStatsCollection->bLnStatsEnabled); + LAC_CHECK_STATUS(status); + + status = SalStatistics_GetStatEnabled( + device, + SAL_STATS_CFG_PRIME, + &pStatsCollection->bPrimeStatsEnabled); + LAC_CHECK_STATUS(status); + + status = SalStatistics_GetStatEnabled( + device, + SAL_STATS_CFG_RSA, + &pStatsCollection->bRsaStatsEnabled); + LAC_CHECK_STATUS(status); + } + + /* Check if the sym service is enabled */ + if (SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO_SYM) || + SalCtrl_IsServiceEnabled(enabled_services, + SAL_SERVICE_TYPE_CRYPTO)) { + status = SalStatistics_GetStatEnabled( + device, + SAL_STATS_CFG_SYM, + &pStatsCollection->bSymStatsEnabled); + LAC_CHECK_STATUS(status); + } + return status; +}; + +/* @ingroup SalStats */ +CpaStatus +SalStatistics_CleanStatisticsCollection(icp_accel_dev_t *device) +{ + sal_statistics_collection_t *pStatsCollection = NULL; + LAC_CHECK_NULL_PARAM(device); + pStatsCollection = (sal_statistics_collection_t *)device->pQatStats; + LAC_OS_FREE(pStatsCollection); + device->pQatStats = NULL; + return CPA_STATUS_SUCCESS; +} diff --git a/sys/dev/qat/qat_api/common/utils/sal_string_parse.c b/sys/dev/qat/qat_api/common/utils/sal_string_parse.c new file mode 100644 index 000000000000..b6161aa8d88c --- /dev/null +++ b/sys/dev/qat/qat_api/common/utils/sal_string_parse.c @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file sal_string_parse.c + * + * @ingroup SalStringParse + * + * @description + * This file contains string parsing functions for both user space and kernel + * space + * + *****************************************************************************/ +#include "cpa.h" +#include "lac_mem.h" +#include "sal_string_parse.h" + +CpaStatus +Sal_StringParsing(char *string1, + Cpa32U instanceNumber, + char *string2, + char *result) +{ + char instNumString[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + Cpa32U instNumStringLen = 0; + + snprintf(instNumString, + SAL_CFG_MAX_VAL_LEN_IN_BYTES, + "%d", + instanceNumber); + instNumStringLen = strnlen(instNumString, SAL_CFG_MAX_VAL_LEN_IN_BYTES); + if ((strnlen(string1, SAL_CFG_MAX_VAL_LEN_IN_BYTES) + instNumStringLen + + strnlen(string2, SAL_CFG_MAX_VAL_LEN_IN_BYTES)) > + SAL_CFG_MAX_VAL_LEN_IN_BYTES) { + QAT_UTILS_LOG("Size of result too small.\n"); + return CPA_STATUS_FAIL; + } + + LAC_OS_BZERO(result, SAL_CFG_MAX_VAL_LEN_IN_BYTES); + snprintf(result, + SAL_CFG_MAX_VAL_LEN_IN_BYTES, + "%s%d%s", + string1, + instanceNumber, + string2); + + return CPA_STATUS_SUCCESS; +} + +Cpa64U +Sal_Strtoul(const char *cp, char **endp, unsigned int cfgBase) +{ + Cpa64U ulResult = 0; + + ulResult = (Cpa64U)simple_strtoull(cp, endp, cfgBase); + + return ulResult; +} diff --git a/sys/dev/qat/qat_api/common/utils/sal_user_process.c b/sys/dev/qat/qat_api/common/utils/sal_user_process.c new file mode 100644 index 000000000000..09728f346c13 --- /dev/null +++ b/sys/dev/qat/qat_api/common/utils/sal_user_process.c @@ -0,0 +1,84 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file sal_user_process.c + * + * @ingroup SalUserProcess + * + * @description + * This file contains implementation of functions to set/get user process + * name + * + *****************************************************************************/ + +#include "qat_utils.h" +#include "lac_common.h" +static char lacProcessName[LAC_USER_PROCESS_NAME_MAX_LEN + 1] = + LAC_KERNEL_PROCESS_NAME; + +/**< Process name used to obtain values from correct section of config file. */ + +/* + * @ingroup LacCommon + * @description + * This function sets the process name + * + * @context + * This functions is called from module_init or from user space process + * initialisation function + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * No + * + * param[in] processName Process name to be set +*/ +CpaStatus +icpSetProcessName(const char *processName) +{ + LAC_CHECK_NULL_PARAM(processName); + + if (strnlen(processName, LAC_USER_PROCESS_NAME_MAX_LEN) == + LAC_USER_PROCESS_NAME_MAX_LEN) { + QAT_UTILS_LOG( + "Process name too long, maximum process name is %d>\n", + LAC_USER_PROCESS_NAME_MAX_LEN); + return CPA_STATUS_FAIL; + } + + strncpy(lacProcessName, processName, LAC_USER_PROCESS_NAME_MAX_LEN); + lacProcessName[LAC_USER_PROCESS_NAME_MAX_LEN] = '\0'; + + return CPA_STATUS_SUCCESS; +} + +/* + * @ingroup LacCommon + * @description + * This function gets the process name + * + * @context + * This functions is called from LAC context + * + * @assumptions + * None + * @sideEffects + * None + * @reentrant + * No + * @threadSafe + * Yes + * +*/ +char * +icpGetProcessName(void) +{ + return lacProcessName; +} diff --git a/sys/dev/qat/qat_api/common/utils/sal_versions.c b/sys/dev/qat/qat_api/common/utils/sal_versions.c new file mode 100644 index 000000000000..8e274eb8705d --- /dev/null +++ b/sys/dev/qat/qat_api/common/utils/sal_versions.c @@ -0,0 +1,177 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* Copyright(c) 2007-2022 Intel Corporation */ +/* $FreeBSD$ */ +/** + ***************************************************************************** + * @file sal_versions.c + * + * @ingroup SalVersions + * + * @description + * This file contains implementation of functions used to obtain version + * information + * + *****************************************************************************/ + +#include "cpa.h" +#include "qat_utils.h" + +#include "icp_accel_devices.h" +#include "icp_adf_accel_mgr.h" +#include "icp_adf_cfg.h" + +#include "lac_common.h" + +#include "icp_sal_versions.h" + +#define ICP_SAL_VERSIONS_ALL_CAP_MASK 0xFFFFFFFF +/**< Mask used to get all devices from ADF */ + +/** +******************************************************************************* + * @ingroup SalVersions + * Fills in the version info structure + * @description + * This function obtains hardware and software information associated with + * a given device and fills in the version info structure + * + * @param[in] device Pointer to the device for which version information + * is to be obtained. + * @param[out] pVerInfo Pointer to a structure that will hold version + * information + * + * @context + * This function might sleep. It cannot be executed in a context that + * does not permit sleeping. + * @assumptions + * The system has been started + * @sideEffects + * None + * @blocking + * No + * @reentrant + * No + * @threadSafe + * Yes + * + * @return CPA_STATUS_SUCCESS Operation finished successfully + * @return CPA_STATUS_FAIL Operation failed + * + *****************************************************************************/ +static CpaStatus +SalVersions_FillVersionInfo(icp_accel_dev_t *device, + icp_sal_dev_version_info_t *pVerInfo) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + char param_value[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 }; + Cpa32S strSize = 0; + + memset(pVerInfo, 0, sizeof(icp_sal_dev_version_info_t)); + pVerInfo->devId = device->accelId; + + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + ICP_CFG_HW_REV_ID_KEY, + param_value); + LAC_CHECK_STATUS(status); + + strSize = snprintf((char *)pVerInfo->hardwareVersion, + ICP_SAL_VERSIONS_HW_VERSION_SIZE, + "%s", + param_value); + LAC_CHECK_PARAM_RANGE(strSize, 1, ICP_SAL_VERSIONS_HW_VERSION_SIZE); + + memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES); + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + ICP_CFG_UOF_VER_KEY, + param_value); + LAC_CHECK_STATUS(status); + + strSize = snprintf((char *)pVerInfo->firmwareVersion, + ICP_SAL_VERSIONS_FW_VERSION_SIZE, + "%s", + param_value); + LAC_CHECK_PARAM_RANGE(strSize, 1, ICP_SAL_VERSIONS_FW_VERSION_SIZE); + + memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES); + status = icp_adf_cfgGetParamValue(device, + LAC_CFG_SECTION_GENERAL, + ICP_CFG_MMP_VER_KEY, + param_value); + LAC_CHECK_STATUS(status); + + strSize = snprintf((char *)pVerInfo->mmpVersion, + ICP_SAL_VERSIONS_MMP_VERSION_SIZE, + "%s", + param_value); + LAC_CHECK_PARAM_RANGE(strSize, 1, ICP_SAL_VERSIONS_MMP_VERSION_SIZE); + + snprintf((char *)pVerInfo->softwareVersion, + ICP_SAL_VERSIONS_SW_VERSION_SIZE, + "%d.%d.%d", + SAL_INFO2_DRIVER_SW_VERSION_MAJ_NUMBER, + SAL_INFO2_DRIVER_SW_VERSION_MIN_NUMBER, + SAL_INFO2_DRIVER_SW_VERSION_PATCH_NUMBER); + + return status; +} + +CpaStatus +icp_sal_getDevVersionInfo(Cpa32U devId, icp_sal_dev_version_info_t *pVerInfo) +{ + CpaStatus status = CPA_STATUS_SUCCESS; + Cpa16U numInstances = 0; + icp_accel_dev_t **pAccel_dev = NULL; + Cpa16U num_accel_dev = 0, index = 0; + icp_accel_dev_t *pDevice = NULL; + + LAC_CHECK_NULL_PARAM(pVerInfo); + + status = icp_amgr_getNumInstances(&numInstances); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG("Error while getting number of devices.\n"); + return CPA_STATUS_FAIL; + } + + if (devId >= ADF_MAX_DEVICES) { + QAT_UTILS_LOG("Invalid devId\n"); + return CPA_STATUS_INVALID_PARAM; + } + + pAccel_dev = + malloc(numInstances * sizeof(icp_accel_dev_t *), M_QAT, M_WAITOK); + + /* Get ADF to return all accel_devs */ + status = + icp_amgr_getAllAccelDevByCapabilities(ICP_SAL_VERSIONS_ALL_CAP_MASK, + pAccel_dev, + &num_accel_dev); + + if (CPA_STATUS_SUCCESS == status) { + for (index = 0; index < num_accel_dev; index++) { + pDevice = (icp_accel_dev_t *)pAccel_dev[index]; + + if (pDevice->accelId == devId) { + status = SalVersions_FillVersionInfo(pDevice, + pVerInfo); + if (CPA_STATUS_SUCCESS != status) { + QAT_UTILS_LOG( + "Error while filling in version info.\n"); + } + break; + } + } + + if (index == num_accel_dev) { + QAT_UTILS_LOG("Device %d not found or not started.\n", + devId); + status = CPA_STATUS_FAIL; + } + } else { + QAT_UTILS_LOG("Error while getting devices.\n"); + } + + free(pAccel_dev, M_QAT); + return status; +} |
