600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > Intel® QAT 加速卡之IPSec示例

Intel® QAT 加速卡之IPSec示例

时间:2019-09-13 08:15:07

相关推荐

Intel® QAT 加速卡之IPSec示例

Intel® QAT 加速卡之IPSec示例

文章目录

Intel® QAT 加速卡之IPSec示例1. QAT处理IPSec入站报文2. QAT处理IPSec出站报文3. 组织架构4. 示例源码

在IPSec的使用过程中需要频繁的加解密操作,而加解密操作会极大的消耗CPU的资源。因此很多提供IPSec服务的设备厂商尝试用多种方式来提高加解密性能,从而缓解CPU的压力,提高设备的IPSec的性能和吞吐量。其中既有软件加速方式,也有硬件加速方式。而Intel® QAT 加速卡便是之中的一款,这是Intel推出的硬件加速设备(Intel也推出过很多其他牛逼的加速设备)。使用专门的硬件加解密卡,从而将CPU解放出来处理其他的任务,这便是加速卡的基本思路。

下面我们就在IPSec中如何使用QAT加速技术流程做一个简单示例。(示例是人家Intel官方文档中提供的)

1. QAT处理IPSec入站报文

2. QAT处理IPSec出站报文

3. 组织架构

QAT相关的重要数据结构组织关系:

4. 示例源码

对于出站方向,此示例将使用对称API来执行链式密码和哈希操作。 它在CBC模式下使用高级加密标准(AES)算法对一些纯文本进行加密,然后对密文,初始化向量和ESP头部执行SHA1 HMAC操作,并在密文之后立即将完整性检查值(ICV)写入缓冲区。对于入站方向,此示例将再次使用对称API来执行链式哈希和密码操作。 它对密文,初始化向量和ESP头部执行SHA1 HMAC操作,并将结果与输入的ICV进行比较,从而实现了完整性校验的功能。 然后,它在CBC模式下使用AES算法解密密文。

#include "cpa.h"#include "cpa_cy_im.h"#include "cpa_cy_sym.h"#include "cpa_sample_utils.h"#define TIMEOUT_MS 5000#define ICV_LENGTH 12/* For IPSec outbound direction we encrypt the payload and thengenerate the ICV. For IPSec inbound direction we compare theICV and decrypt the payload*/#define IPSEC_OUTBOUND_DIR 0#define IPSEC_INBOUND_DIR 1extern int gDebugParam;static Cpa8U sampleCipherKey[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,0x88, 0x99, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55};static Cpa8U sampleCipherIv[] = {0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,0xde, 0xca, 0xf8, 0x88, 0x3d, 0x11, 0x59, 0x04};static Cpa8U sampleAuthKey[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF,0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF,0xDE, 0xAD, 0xBE, 0xEF};static Cpa8U sampleEspHdrData[] = {0x00, 0x00, 0x01, 0x2c, 0x00, 0x00, 0x00, 0x05};/* Payload padded to a multiple of the cipher block size(16), 2nd last byte gives pad length, last byte givesnext header info */static Cpa8U samplePayload[] = {0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5,0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a,0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda,0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72,0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53,0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25,0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57,0xba, 0x63, 0x7b, 0x39, 0x01, 0x02, 0x02, 0x61};static Cpa8U expectedOutput[] = {/* ESP header unmodified */0x00, 0x00, 0x01, 0x2c, 0x00, 0x00, 0x00, 0x05,/* IV unmodified */0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad,0xde, 0xca, 0xf8, 0x88, 0x3d, 0x11, 0x59, 0x04,/* Ciphertext */0x39, 0x8E, 0x4C, 0x1B, 0x7B, 0x28, 0x94, 0x52,0x97, 0xAD, 0x95, 0x97, 0xD7, 0xF9, 0xB9, 0x4A,0x49, 0x03, 0x51, 0x47, 0x45, 0xC7, 0x58, 0x6A,0x9A, 0x48, 0xB6, 0x38, 0xB4, 0xD5, 0xEE, 0x42,0x4F, 0x39, 0x09, 0x3D, 0xAB, 0x1E, 0xB3, 0x6A,0x71, 0x0B, 0xFC, 0x80, 0xAD, 0x2E, 0x4C, 0xA5,0xAB, 0x78, 0xB8, 0xAB, 0x87, 0xCC, 0x37, 0xF0,0xB9, 0x61, 0xDC, 0xB1, 0xA7, 0x24, 0x26, 0x23,/* ICV */0xE6, 0x55, 0xBD, 0x90, 0x33, 0x2D, 0x04, 0x8C,0x34, 0x06, 0xE3, 0x2D};CpaStatusalgChainSample(void);/** Callback function** This function is "called back" (invoked by the implementation of* the API) when the asynchronous operation has completed. The* context in which it is invoked depends on the implementation, but* as described in the API it should not sleep (since it may be called* in a context which does not permit sleeping, e.g. a Linux bottom* half).** This function can perform whatever processing is appropriate to the* application. For example, it may free memory, continue processing* of a decrypted packet, etc. In this example, the function checks* verifyResult returned and sets the complete variable to indicate it* has been called.*/static voidsymCallback(void *pCallbackTag,CpaStatus status,const CpaCySymOp operationType,void *pOpData,CpaBufferList *pDstBuffer,CpaBoolean verifyResult){PRINT_DBG("Callback called with status = %d.\n", status);/* For this implementation verifyResult is true by default. Inthe digest generate case verifyDigest will never be false. Inthe digest verify case verifyDigest can be false if digestverification fails */if(CPA_FALSE == verifyResult){PRINT_ERR("Callback verify result error\n");}if (NULL != pCallbackTag){/** indicate that the function has been called */COMPLETE((struct COMPLETION_STRUCT *)pCallbackTag);}}/** Perform an algorithm chaining operation*/static CpaStatusalgChainPerformOp(CpaInstanceHandle cyInstHandle, CpaCySymSessionCtx sessionCtx, int dir){CpaStatus status = CPA_STATUS_SUCCESS;Cpa8U *pBufferMeta = NULL;Cpa32U bufferMetaSize = 0;CpaBufferList *pBufferList = NULL;CpaFlatBuffer *pFlatBuffer = NULL;CpaCySymOpData *pOpData = NULL;/* buffer size includes space for hdr, iv, payload and icv */Cpa32U bufferSize = sizeof(sampleEspHdrData) + sizeof(sampleCipherIv)+ sizeof(samplePayload) + ICV_LENGTH;Cpa32U numBuffers = 1; /* only using 1 buffer in this case *//* allocate memory for bufferlist and array of flat buffers in a contiguous* area and carve it up to reduce number of memory allocations required. */Cpa32U bufferListMemSize = sizeof(CpaBufferList) +(numBuffers * sizeof(CpaFlatBuffer));Cpa8U *pSrcBuffer = NULL;Cpa8U *pIvBuffer = NULL;/* The following variables are allocated on the stack because we block* until the callback comes back. If a non-blocking approach was to be* used then these variables should be dynamically allocated */struct COMPLETION_STRUCT complete;/* get meta information size */status = cpaCyBufferListGetMetaSize( cyInstHandle,numBuffers, &bufferMetaSize);if (CPA_STATUS_SUCCESS == status){status = PHYS_CONTIG_ALLOC(&pBufferMeta, bufferMetaSize);}if (CPA_STATUS_SUCCESS == status){status = OS_MALLOC(&pBufferList, bufferListMemSize);}if (CPA_STATUS_SUCCESS == status){status = PHYS_CONTIG_ALLOC(&pSrcBuffer, bufferSize);}if (CPA_STATUS_SUCCESS == status){/* increment by sizeof(CpaBufferList) to get at the* array of flatbuffers */pFlatBuffer = (CpaFlatBuffer *) (pBufferList + 1);pBufferList->pBuffers = pFlatBuffer;pBufferList->numBuffers = 1;pBufferList->pPrivateMetaData = pBufferMeta;pFlatBuffer->dataLenInBytes = bufferSize;pFlatBuffer->pData = pSrcBuffer;/* copy source into buffer */if(IPSEC_OUTBOUND_DIR == dir){memcpy(pSrcBuffer, sampleEspHdrData, sizeof(sampleEspHdrData));memcpy(pSrcBuffer+sizeof(sampleEspHdrData), sampleCipherIv, sizeof(sampleCipherIv));memcpy(pSrcBuffer+(sizeof(sampleEspHdrData)+sizeof(sampleCipherIv)),samplePayload, sizeof(samplePayload));}else{memcpy(pSrcBuffer, expectedOutput, sizeof(expectedOutput));}pIvBuffer = pSrcBuffer + sizeof(sampleEspHdrData);status = OS_MALLOC(&pOpData, sizeof(CpaCySymOpData));}if (CPA_STATUS_SUCCESS == status){if(IPSEC_OUTBOUND_DIR == dir){//<snippet name="opDataIPSecOut">/** Populate the structure containing the operational data that is* needed to run the algorithm in outbound direction */pOpData->sessionCtx = sessionCtx;pOpData->packetType = CPA_CY_SYM_PACKET_TYPE_FULL;pOpData->pIv = pIvBuffer;pOpData->ivLenInBytes = sizeof(sampleCipherIv);pOpData->cryptoStartSrcOffsetInBytes = sizeof(sampleEspHdrData)+sizeof(sampleCipherIv);pOpData->messageLenToCipherInBytes = sizeof(samplePayload);pOpData->hashStartSrcOffsetInBytes = 0;pOpData->messageLenToHashInBytes = sizeof(sampleEspHdrData)+sizeof(sampleCipherIv)+sizeof(samplePayload);/* Even though ICV follows immediately after the region to hashdigestIsAppended is set to false in this case to workarounderrata number IXA00378322 */pOpData->pDigestResult = pSrcBuffer+(sizeof(sampleEspHdrData)+sizeof(sampleCipherIv)+sizeof(samplePayload));//</snippet>}else{//<snippet name="opDataIPSecIn">/** Populate the structure containing the operational data that is* needed to run the algorithm in inbound direction */pOpData->sessionCtx = sessionCtx;pOpData->packetType = CPA_CY_SYM_PACKET_TYPE_FULL;pOpData->pIv = pIvBuffer;pOpData->ivLenInBytes = sizeof(sampleCipherIv);pOpData->cryptoStartSrcOffsetInBytes = sizeof(sampleEspHdrData)+sizeof(sampleCipherIv);pOpData->messageLenToCipherInBytes = bufferSize -(sizeof(sampleEspHdrData)+sizeof(sampleCipherIv)+ICV_LENGTH);pOpData->hashStartSrcOffsetInBytes = 0;pOpData->messageLenToHashInBytes = bufferSize - ICV_LENGTH;//</snippet>}}if (CPA_STATUS_SUCCESS == status){/** initialisation for callback; the "complete" variable is used by the* callback function to indicate it has been called*/COMPLETION_INIT(&complete);PRINT_DBG("cpaCySymPerformOp\n");/** Perform symmetric operation */status = cpaCySymPerformOp(cyInstHandle,(void *)&complete, /* data sent as is to the callback function*/pOpData, /* operational data struct */pBufferList, /* source buffer list */pBufferList, /* same src & dst for an in-place operation*/NULL); /* pVerifyResult not required in async mode */if (CPA_STATUS_SUCCESS != status){PRINT_ERR("cpaCySymPerformOp failed. (status = %d)\n", status);}if (CPA_STATUS_SUCCESS == status){/** wait until the completion of the operation*/if (!COMPLETION_WAIT(&complete, TIMEOUT_MS)){PRINT_ERR("timeout or interruption in cpaCySymPerformOp\n");status = CPA_STATUS_FAIL;}}if (CPA_STATUS_SUCCESS == status){if(IPSEC_OUTBOUND_DIR == dir){if (0 == memcmp(pSrcBuffer, expectedOutput, bufferSize)){PRINT_DBG("Output matches expected output encrypt generate\n");}else{PRINT_DBG("Output does not match expected output encrypt generate\n");status = CPA_STATUS_FAIL;}}else{if (0 == memcmp(pSrcBuffer+(sizeof(sampleEspHdrData)+sizeof(sampleCipherIv)),samplePayload, sizeof(samplePayload))){PRINT_DBG("Output matches expected output decrypt verify\n");}else{PRINT_DBG("Output does not match expected output decrypt verify\n");status = CPA_STATUS_FAIL;}}}}/* at this stage, the callback function has returned, so it is sure that* the structures won't be needed any more*/PHYS_CONTIG_FREE(pSrcBuffer);OS_FREE(pBufferList);PHYS_CONTIG_FREE(pBufferMeta);OS_FREE(pOpData);COMPLETION_DESTROY(&complete);return status;}CpaStatusalgChainSample(void){CpaStatus status = CPA_STATUS_FAIL;CpaCySymSessionCtx sessionCtx = NULL;Cpa32U sessionCtxSize = 0;CpaInstanceHandle cyInstHandle = NULL;CpaCySymSessionSetupData sessionSetupData = {0};CpaCySymStats64 symStats = {0};/** In this simplified version of instance discovery, we discover* exactly one instance of a crypto service.*/sampleCyGetInstance(&cyInstHandle);if (cyInstHandle == NULL){PRINT_DBG("No crypto instances available\n");return CPA_STATUS_FAIL;}/* Start Cryptographic component */PRINT_DBG("cpaCyStartInstance\n");status = cpaCyStartInstance(cyInstHandle);if(CPA_STATUS_SUCCESS == status){/** Set the address translation function for the instance*/status = cpaCySetAddressTranslation(cyInstHandle, sampleVirtToPhys);}if (CPA_STATUS_SUCCESS == status){/** If the instance is polled start the polling thread. Note that* how the polling is done is implementation-dependant.*/sampleCyStartPolling(cyInstHandle);PRINT_DBG("Encrypt-Generate ICV\n");/* populate symmetric session data structure */sessionSetupData.sessionPriority = CPA_CY_PRIORITY_HIGH;//<snippet name="initSessionIPSecEnc">sessionSetupData.symOperation = CPA_CY_SYM_OP_ALGORITHM_CHAINING;sessionSetupData.algChainOrder =CPA_CY_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH;sessionSetupData.cipherSetupData.cipherAlgorithm =CPA_CY_SYM_CIPHER_AES_CBC;sessionSetupData.cipherSetupData.pCipherKey = sampleCipherKey;sessionSetupData.cipherSetupData.cipherKeyLenInBytes =sizeof(sampleCipherKey);sessionSetupData.cipherSetupData.cipherDirection =CPA_CY_SYM_CIPHER_DIRECTION_ENCRYPT;sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA1;sessionSetupData.hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH;sessionSetupData.hashSetupData.digestResultLenInBytes = ICV_LENGTH;sessionSetupData.hashSetupData.authModeSetupData.authKey = sampleAuthKey;sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes =sizeof(sampleAuthKey);/* Even though ICV follows immediately after the region to hashdigestIsAppended is set to false in this case to workarounderrata number IXA00378322 */sessionSetupData.digestIsAppended = CPA_FALSE;/* Generate the ICV in outbound direction */sessionSetupData.verifyDigest = CPA_FALSE;//</snippet>/* Determine size of session context to allocate */status = cpaCySymSessionCtxGetSize(cyInstHandle,&sessionSetupData, &sessionCtxSize);}if (CPA_STATUS_SUCCESS == status){/* Allocate session context */status = PHYS_CONTIG_ALLOC(&sessionCtx, sessionCtxSize);}if (CPA_STATUS_SUCCESS == status){/* Initialize the session */status = cpaCySymInitSession(cyInstHandle,symCallback, &sessionSetupData, sessionCtx);}if (CPA_STATUS_SUCCESS == status){CpaStatus sessionStatus = CPA_STATUS_SUCCESS;/* Perform algchaining operation */status = algChainPerformOp(cyInstHandle, sessionCtx,IPSEC_OUTBOUND_DIR);/* Remove the session - session init has already succeeded */sessionStatus = cpaCySymRemoveSession(cyInstHandle, sessionCtx);/* maintain status of remove session only when status of all operations* before it are successful. */if (CPA_STATUS_SUCCESS == status){status = sessionStatus;}}if(CPA_STATUS_SUCCESS == status){PRINT_DBG("Decrypt-Verify ICV\n");/* populate symmetric session data structure */sessionSetupData.sessionPriority = CPA_CY_PRIORITY_HIGH;//<snippet name="initSessionIPSecDec">sessionSetupData.symOperation = CPA_CY_SYM_OP_ALGORITHM_CHAINING;sessionSetupData.algChainOrder =CPA_CY_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER;sessionSetupData.cipherSetupData.cipherAlgorithm =CPA_CY_SYM_CIPHER_AES_CBC;sessionSetupData.cipherSetupData.pCipherKey = sampleCipherKey;sessionSetupData.cipherSetupData.cipherKeyLenInBytes =sizeof(sampleCipherKey);sessionSetupData.cipherSetupData.cipherDirection =CPA_CY_SYM_CIPHER_DIRECTION_DECRYPT;sessionSetupData.hashSetupData.hashAlgorithm = CPA_CY_SYM_HASH_SHA1;sessionSetupData.hashSetupData.hashMode = CPA_CY_SYM_HASH_MODE_AUTH;sessionSetupData.hashSetupData.digestResultLenInBytes = ICV_LENGTH;sessionSetupData.hashSetupData.authModeSetupData.authKey = sampleAuthKey;sessionSetupData.hashSetupData.authModeSetupData.authKeyLenInBytes= sizeof(sampleAuthKey);/* ICV follows immediately after the region to hash */sessionSetupData.digestIsAppended = CPA_TRUE;/* Verify the ICV in the inbound direction */sessionSetupData.verifyDigest = CPA_TRUE;//</snippet>}if (CPA_STATUS_SUCCESS == status){/* Initialize the session */status = cpaCySymInitSession(cyInstHandle,symCallback, &sessionSetupData, sessionCtx);}if (CPA_STATUS_SUCCESS == status){CpaStatus sessionStatus = CPA_STATUS_SUCCESS;/* Perform algchaining operation */status = algChainPerformOp(cyInstHandle, sessionCtx,IPSEC_INBOUND_DIR);/* Remove the session - session init has already succeeded */sessionStatus = cpaCySymRemoveSession(cyInstHandle, sessionCtx);/* maintain status of remove session only when status of all operations* before it are successful. */if (CPA_STATUS_SUCCESS == status){status = sessionStatus;}}if (CPA_STATUS_SUCCESS == status){/* Query symmetric statistics */status = cpaCySymQueryStats64(cyInstHandle, &symStats);if (CPA_STATUS_SUCCESS != status){PRINT_ERR("cpaCySymQueryStats failed, status = %d\n", status);}else{PRINT_DBG("Number of symmetric operations completed: %llu\n",(unsigned long long)symStats.numSymOpCompleted);}}/* Clean up *//* Free session Context */PHYS_CONTIG_FREE(sessionCtx);/* Stop the polling thread */sampleCyStopPolling();PRINT_DBG("cpaCyStopInstance\n");cpaCyStopInstance(cyInstHandle);if (CPA_STATUS_SUCCESS == status){PRINT_DBG("Sample code ran successfully\n");}else{PRINT_DBG("Sample code failed with status of %d\n", status);}return status;}

示例路径:qat1.5.l.1.13.0-19\quickassist\lookaside\access_layer\src\sample_code\functional\sym\ipsec_sample

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。