[][openwrt][mt7988][crypto][Refactor to unify EIP driver]
[Description]
Refactor to unify EIP driver.
1. Sync CAPWAP-DTLS functions for TOPS from neptune/eip_driver
2. Decoupled with hnat, IPSec inline mode is available even when hnat is
not activated now.
[Release-log]
N/A
Change-Id: Id53b483924fb90bc784570545b37e67e860a6024
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/8868628
diff --git a/feed/kernel/crypto-eip/src/ddk-wrapper.c b/feed/kernel/crypto-eip/src/ddk-wrapper.c
index c07b2de..b3c5b90 100644
--- a/feed/kernel/crypto-eip/src/ddk-wrapper.c
+++ b/feed/kernel/crypto-eip/src/ddk-wrapper.c
@@ -2133,7 +2133,23 @@
PEC_Capabilities_t pec_cap;
PEC_Status_t pec_sta;
u32 i = MTK_EIP197_INLINE_NOF_TRIES;
+#ifdef PEC_PCL_EIP197
+ PCL_Status_t pcl_sta;
+#endif
+#ifdef PEC_PCL_EIP197
+ pcl_sta = PCL_Init(PCL_INTERFACE_ID, 1);
+ if (pcl_sta != PCL_STATUS_OK) {
+ CRYPTO_ERR("PCL could not be initialized, error=%d\n", pcl_sta);
+ return 0;
+ }
+
+ pcl_sta = PCL_DTL_Init(PCL_INTERFACE_ID);
+ if (pcl_sta != PCL_STATUS_OK) {
+ CRYPTO_ERR("PCL-DTL could not be initialized, error=%d\n", pcl_sta);
+ return -1;
+ }
+#endif
while (i) {
pec_sta = PEC_Init(PEC_INTERFACE_ID, &pec_init_blk);
if (pec_sta == PEC_STATUS_OK) {
@@ -2155,6 +2171,9 @@
pec_sta = PEC_Capabilities_Get(&pec_cap);
if (pec_sta != PEC_STATUS_OK) {
CRYPTO_ERR("PEC capability could not be obtained: %d\n", pec_sta);
+#ifdef PEC_PCL_EIP197
+ PCL_UnInit(PCL_INTERFACE_ID);
+#endif
return pec_sta;
}
@@ -2165,4 +2184,1144 @@
void mtk_ddk_pec_deinit(void)
{
+ unsigned int LoopCounter = MTK_EIP197_INLINE_NOF_TRIES;
+ PEC_Status_t PEC_Status;
+
+ while (LoopCounter > 0) {
+ PEC_Status = PEC_UnInit(PEC_INTERFACE_ID);
+ if (PEC_Status == PEC_STATUS_OK)
+ break;
+ else if (PEC_Status != PEC_STATUS_OK && PEC_Status != PEC_STATUS_BUSY) {
+ CRYPTO_ERR("PEC could not be un-initialized, error=%d\n", PEC_Status);
+ return;
+ }
+ // Wait for MTK_EIP197_INLINE_RETRY_DELAY_MS milliseconds
+ udelay(MTK_EIP197_INLINE_RETRY_DELAY_MS * 1000);
+ LoopCounter--;
+ }
+ // Check for timeout
+ if (LoopCounter == 0) {
+ CRYPTO_ERR("PEC could not be un-initialized, timeout\n");
+ return;
+ }
+
+#ifdef PEC_PCL_EIP197
+ PCL_DTL_UnInit(PCL_INTERFACE_ID);
+ PCL_UnInit(PCL_INTERFACE_ID);
+#endif
+}
+
+bool
+mtk_ddk_aes_block_encrypt(uint8_t *Key_p,
+ unsigned int KeyByteCount,
+ uint8_t *InData_p,
+ uint8_t *OutData_p)
+{
+ int rc;
+ SABuilder_Params_t params;
+ SABuilder_Params_Basic_t ProtocolParams;
+ unsigned int SAWords = 0;
+
+ DMABuf_Status_t DMAStatus;
+ DMABuf_Properties_t DMAProperties = {0, 0, 0, 0};
+ DMABuf_HostAddress_t SAHostAddress;
+ DMABuf_HostAddress_t TokenHostAddress;
+ DMABuf_HostAddress_t PktHostAddress;
+
+ DMABuf_Handle_t SAHandle = {0};
+ DMABuf_Handle_t TokenHandle = {0};
+ DMABuf_Handle_t PktHandle = {0};
+
+ unsigned int TCRWords = 0;
+ void *TCRData = 0;
+ unsigned int TokenWords = 0;
+ unsigned int TokenHeaderWord;
+ unsigned int TokenMaxWords = 0;
+
+ TokenBuilder_Params_t TokenParams;
+ PEC_CommandDescriptor_t Cmd;
+ PEC_ResultDescriptor_t Res;
+ unsigned int count;
+
+ IOToken_Input_Dscr_t InTokenDscr;
+ IOToken_Output_Dscr_t OutTokenDscr;
+ uint32_t InputToken[IOTOKEN_IN_WORD_COUNT];
+ uint32_t OutputToken[IOTOKEN_OUT_WORD_COUNT];
+ IOToken_Output_Dscr_Ext_t OutTokenDscrExt;
+ IOToken_Input_Dscr_Ext_t InTokenDscrExt;
+
+ ZEROINIT(InTokenDscrExt);
+ ZEROINIT(OutTokenDscrExt);
+
+ ZEROINIT(InTokenDscr);
+ ZEROINIT(OutTokenDscr);
+
+ rc = SABuilder_Init_Basic(¶ms, &ProtocolParams, SAB_DIRECTION_OUTBOUND);
+ if (rc != 0) {
+ CRYPTO_ERR("SABuilder_Init_Basic failed\n");
+ goto error_exit;
+ }
+ // Add crypto key and parameters.
+ params.CryptoAlgo = SAB_CRYPTO_AES;
+ params.CryptoMode = SAB_CRYPTO_MODE_ECB;
+ params.KeyByteCount = KeyByteCount;
+ params.Key_p = Key_p;
+
+ rc = SABuilder_GetSizes(¶ms, &SAWords, NULL, NULL);
+
+ if (rc != 0) {
+ CRYPTO_ERR("SA not created because of errors\n");
+ goto error_exit;
+ }
+
+ DMAProperties.fCached = true;
+ DMAProperties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
+ DMAProperties.Bank = MTK_EIP197_INLINE_BANK_TRANSFORM;
+ DMAProperties.Size = 4*SAWords;
+
+ DMAStatus = DMABuf_Alloc(DMAProperties, &SAHostAddress, &SAHandle);
+ if (DMAStatus != DMABUF_STATUS_OK) {
+ rc = 1;
+ CRYPTO_ERR("Allocation of SA failed\n");
+ goto error_exit;
+ }
+
+ rc = SABuilder_BuildSA(¶ms, (uint32_t *)SAHostAddress.p, NULL, NULL);
+
+ if (rc != 0) {
+ LOG_CRIT("SA not created because of errors\n");
+ goto error_exit;
+ }
+
+ rc = TokenBuilder_GetContextSize(¶ms, &TCRWords);
+
+ if (rc != 0) {
+ CRYPTO_ERR("TokenBuilder_GetContextSize returned errors\n");
+ goto error_exit;
+ }
+
+ // The Token Context Record does not need to be allocated
+ // in a DMA-safe buffer.
+ TCRData = kcalloc(4*TCRWords, sizeof(uint8_t), GFP_KERNEL);
+ if (!TCRData) {
+ rc = 1;
+ CRYPTO_ERR("Allocation of TCR failed\n");
+ goto error_exit;
+ }
+
+ rc = TokenBuilder_BuildContext(¶ms, TCRData);
+
+ if (rc != 0) {
+ CRYPTO_ERR("TokenBuilder_BuildContext failed\n");
+ goto error_exit;
+ }
+
+ rc = TokenBuilder_GetSize(TCRData, &TokenMaxWords);
+ if (rc != 0) {
+ CRYPTO_ERR("TokenBuilder_GetSize failed\n");
+ goto error_exit;
+ }
+
+ // Allocate one buffer for the token and two packet buffers.
+
+ DMAProperties.fCached = true;
+ DMAProperties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
+ DMAProperties.Bank = MTK_EIP197_INLINE_BANK_PACKET;
+ DMAProperties.Size = 4*TokenMaxWords;
+
+ DMAStatus = DMABuf_Alloc(DMAProperties, &TokenHostAddress, &TokenHandle);
+ if (DMAStatus != DMABUF_STATUS_OK) {
+ rc = 1;
+ CRYPTO_ERR("Allocation of token buffer failed.\n");
+ goto error_exit;
+ }
+
+ DMAProperties.fCached = true;
+ DMAProperties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
+ DMAProperties.Bank = MTK_EIP197_INLINE_BANK_PACKET;
+ DMAProperties.Size = 16;
+
+ DMAStatus = DMABuf_Alloc(DMAProperties, &PktHostAddress,
+ &PktHandle);
+ if (DMAStatus != DMABUF_STATUS_OK) {
+ rc = 1;
+ CRYPTO_ERR("Allocation of source packet buffer failed.\n");
+ goto error_exit;
+ }
+
+ // Register the SA
+ rc = PEC_SA_Register(PEC_INTERFACE_ID, SAHandle, DMABuf_NULLHandle,
+ DMABuf_NULLHandle);
+ if (rc != PEC_STATUS_OK) {
+ CRYPTO_ERR("PEC_SA_Register failed\n");
+ goto error_exit;
+ }
+
+ // Copy input packet into source packet buffer.
+ memcpy(PktHostAddress.p, InData_p, 16);
+
+ // Set Token Parameters if specified in test vector.
+ ZEROINIT(TokenParams);
+
+
+ // Prepare a token to process the packet.
+ rc = TokenBuilder_BuildToken(TCRData,
+ (uint8_t *)PktHostAddress.p,
+ 16,
+ &TokenParams,
+ (uint32_t *)TokenHostAddress.p,
+ &TokenWords,
+ &TokenHeaderWord);
+ if (rc != TKB_STATUS_OK) {
+ if (rc == TKB_BAD_PACKET)
+ CRYPTO_ERR("Token not created because packet size is invalid\n");
+ else
+ CRYPTO_ERR("Token builder failed\n");
+ goto error_exit_unregister;
+ }
+
+ ZEROINIT(Cmd);
+ Cmd.Token_Handle = TokenHandle;
+ Cmd.Token_WordCount = TokenWords;
+ Cmd.SrcPkt_Handle = PktHandle;
+ Cmd.SrcPkt_ByteCount = 16;
+ Cmd.DstPkt_Handle = PktHandle;
+ Cmd.SA_Handle1 = SAHandle;
+ Cmd.SA_Handle2 = DMABuf_NULLHandle;
+
+ InTokenDscrExt.HW_Services = IOTOKEN_CMD_PKT_LAC;
+ InTokenDscr.TknHdrWordInit = TokenHeaderWord;
+
+ if (!crypto_iotoken_create(&InTokenDscr,
+ &InTokenDscrExt,
+ InputToken,
+ &Cmd)) {
+ rc = 1;
+ goto error_exit_unregister;
+ }
+
+ rc = PEC_Packet_Put(PEC_INTERFACE_ID,
+ &Cmd,
+ 1,
+ &count);
+ if (rc != PEC_STATUS_OK && count != 1) {
+ rc = 1;
+ CRYPTO_ERR("PEC_Packet_Put error\n");
+ goto error_exit_unregister;
+ }
+
+ if (crypto_pe_busy_get_one(&OutTokenDscr, OutputToken, &Res) < 1) {
+ rc = 1;
+ CRYPTO_ERR("error from crypto_pe_busy_get_one\n");
+ goto error_exit_unregister;
+ }
+ memcpy(OutData_p, PktHostAddress.p, 16);
+
+
+error_exit_unregister:
+ PEC_SA_UnRegister(PEC_INTERFACE_ID, SAHandle, DMABuf_NULLHandle,
+ DMABuf_NULLHandle);
+
+error_exit:
+ DMABuf_Release(SAHandle);
+ DMABuf_Release(TokenHandle);
+ DMABuf_Release(PktHandle);
+
+ if (TCRData != NULL)
+ kfree(TCRData);
+
+ return rc == 0;
+
+}
+
+bool
+mtk_ddk_invalidate_rec(
+ const DMABuf_Handle_t Rec_p,
+ const bool IsTransform)
+{
+ PEC_Status_t PEC_Rc;
+ PEC_CommandDescriptor_t Cmd;
+ PEC_ResultDescriptor_t Res;
+ unsigned int count;
+ IOToken_Input_Dscr_t InTokenDscr;
+ IOToken_Output_Dscr_t OutTokenDscr;
+ uint32_t InputToken[IOTOKEN_IN_WORD_COUNT_IL];
+ uint32_t OutputToken[IOTOKEN_OUT_WORD_COUNT_IL];
+ void *InTokenDscrExt_p = NULL;
+ void *OutTokenDscrExt_p = NULL;
+ IOToken_Input_Dscr_Ext_t InTokenDscrExt;
+ IOToken_Output_Dscr_Ext_t OutTokenDscrExt;
+
+ ZEROINIT(InTokenDscrExt);
+ InTokenDscrExt_p = &InTokenDscrExt;
+ OutTokenDscrExt_p = &OutTokenDscrExt;
+
+ ZEROINIT(InTokenDscr);
+
+ // Fill in the command descriptor for the Invalidate command
+ ZEROINIT(Cmd);
+
+ Cmd.SrcPkt_Handle = DMABuf_NULLHandle;
+ Cmd.DstPkt_Handle = DMABuf_NULLHandle;
+ Cmd.SA_Handle1 = Rec_p;
+ Cmd.SA_Handle2 = DMABuf_NULLHandle;
+ Cmd.Token_Handle = DMABuf_NULLHandle;
+ Cmd.SrcPkt_ByteCount = 0;
+
+#if defined(IOTOKEN_USE_HW_SERVICE)
+ if (IsTransform)
+ InTokenDscrExt.HW_Services = IOTOKEN_CMD_INV_TR;
+ else
+ InTokenDscrExt.HW_Services = IOTOKEN_CMD_INV_FR;
+#endif
+
+ if (!crypto_iotoken_create(&InTokenDscr, InTokenDscrExt_p, InputToken, &Cmd))
+ return false;
+
+ // Issue command
+ PEC_Rc = PEC_Packet_Put(PEC_INTERFACE_ID,
+ &Cmd,
+ 1,
+ &count);
+ if (PEC_Rc != PEC_STATUS_OK || count != 1) {
+ CRYPTO_ERR("%s: PEC_Packet_Put() error %d, count %d\n",
+ __func__,
+ PEC_Rc,
+ count);
+ return false;
+ }
+
+ // Receive the result packet ... do we care about contents ?
+ if (crypto_pe_busy_get_one(&OutTokenDscr, OutputToken, &Res) < 1) {
+ CRYPTO_ERR("%s: crypto_pe_busy_get_one() failed\n", __func__);
+ return false;
+ }
+
+ return true;
+}
+
+bool mtk_capwap_dtls_offload(
+ const bool fVerbose,
+ const bool fCAPWAP,
+ const bool fPktCfy,
+ const bool fInline,
+ const bool fContinuousScatter,
+ struct DTLS_param *DTLSParam_p,
+ struct DTLSResourceMgmt **DTLSResource)
+{
+ bool success = false;
+ SABuilder_Status_t SAStatus;
+ SABuilder_Params_t params;
+ SABuilder_Params_SSLTLS_t SSLTLSParams;
+ uint8_t Offset;
+ uint16_t DTLSVersion;
+ uint32_t SAWords = 0;
+ bool fInlinePlain, fInlineCipher;
+
+ DMABuf_Status_t DMAStatus;
+ DMABuf_Properties_t DMAProperties = {0, 0, 0, 0};
+ DMABuf_HostAddress_t SAHostAddress;
+
+ static uint8_t Zero[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ uint8_t *InboundHKey = NULL;
+ uint8_t *OutboundHKey = NULL;
+ uint8_t *InnerDigest = NULL;
+ uint8_t *OuterDigest = NULL;
+
+ PCL_Status_t PCL_Status;
+ PCL_SelectorParams_t SelectorParams;
+ PCL_DTL_TransformParams_t DTLTransformParams;
+ PCL_TransformParams_t TransformParams;
+ PCL_DTL_Hash_Handle_t SAHashHandle;
+
+
+ struct DTLSResourceMgmt *DTLSResourceEntity_p = NULL;
+
+ DTLSResourceEntity_p = kmalloc(sizeof(struct DTLSResourceMgmt), GFP_KERNEL);
+ if (DTLSResourceEntity_p == NULL) {
+ CRYPTO_ERR("%s: kmalloc for DTLSResourceEntity failed\n", __func__);
+ goto error_exit;
+ }
+ memset(DTLSResourceEntity_p, 0, sizeof(struct DTLSResourceMgmt));
+
+ if (fCAPWAP)
+ CRYPTO_INFO("Preparing Transforms and DTL for DTLS-CAPWAP\n");
+ else
+ CRYPTO_INFO("Preparing Transforms and DTL for DTLS\n");
+
+ if (fVerbose)
+ CRYPTO_INFO("*** fVerbose Preparing Transforms and DTL ***\n\n");
+
+ Offset = 14;
+
+ if (fInline) {
+ if (fContinuousScatter) {
+ /* inline + continuous scatter:
+ Redirect outbound packets ring->inline
+ Redirect inbound packets inline->ring
+ */
+ fInlinePlain = false;
+ fInlineCipher = true;
+ } else {
+ fInlinePlain = true;
+ fInlineCipher = true;
+ }
+ } else {
+ fInlinePlain = false;
+ fInlineCipher = false;
+ }
+
+ // Prepare the Outbound SA
+ if (DTLSParam_p->dtls_version == MTK_DTLS_VERSION_1_0)
+ DTLSVersion = SAB_DTLS_VERSION_1_0;
+ else if (DTLSParam_p->dtls_version == MTK_DTLS_VERSION_1_2)
+ DTLSVersion = SAB_DTLS_VERSION_1_2;
+ else {
+ CRYPTO_ERR("%s: Unknown DTLSParam_p->dtls_version: %u\n", __func__,
+ DTLSParam_p->dtls_version);
+ goto error_exit;
+ }
+
+ // Initialize the SA parameters for ESP.The call to SABuilder_Init_ESP
+ // will initialize many parameters, next fill in more parameters, such
+ // as cryptographic keys.
+ SAStatus = SABuilder_Init_SSLTLS(¶ms,
+ &SSLTLSParams,
+ DTLSVersion,
+ SAB_DIRECTION_OUTBOUND);
+ if (SAStatus != SAB_STATUS_OK) {
+ CRYPTO_ERR("%s: SABuilder_Init_ESP failed\n", __func__);
+ goto error_exit;
+ }
+
+ /* Set DTLS-CAPWAP param from cmd handler */
+ if (DTLSParam_p->sec_mode == AES128_CBC_HMAC_SHA1) {
+ params.CryptoAlgo = SAB_CRYPTO_AES;
+ params.CryptoMode = SAB_CRYPTO_MODE_CBC;
+ params.KeyByteCount = 16;
+ params.AuthAlgo = SAB_AUTH_HMAC_SHA1;
+ params.AuthKeyByteCount = 20;
+ } else if (DTLSParam_p->sec_mode == AES128_CBC_HMAC_SHA2_256) {
+ params.CryptoAlgo = SAB_CRYPTO_AES;
+ params.CryptoMode = SAB_CRYPTO_MODE_CBC;
+ params.KeyByteCount = 16;
+ params.AuthAlgo = SAB_AUTH_HMAC_SHA2_256;
+ params.AuthKeyByteCount = 32;
+ } else if (DTLSParam_p->sec_mode == AES256_CBC_HMAC_SHA1) {
+ params.CryptoAlgo = SAB_CRYPTO_AES;
+ params.CryptoMode = SAB_CRYPTO_MODE_CBC;
+ params.KeyByteCount = 32;
+ params.AuthAlgo = SAB_AUTH_HMAC_SHA1;
+ params.AuthKeyByteCount = 20;
+ } else if (DTLSParam_p->sec_mode == AES256_CBC_HMAC_SHA2_256) {
+ params.CryptoAlgo = SAB_CRYPTO_AES;
+ params.CryptoMode = SAB_CRYPTO_MODE_CBC;
+ params.KeyByteCount = 32;
+ params.AuthAlgo = SAB_AUTH_HMAC_SHA2_256;
+ params.AuthKeyByteCount = 32;
+ } else if (DTLSParam_p->sec_mode == AES128_GCM || DTLSParam_p->sec_mode == AES256_GCM) {
+ params.CryptoAlgo = SAB_CRYPTO_AES;
+ params.CryptoMode = SAB_CRYPTO_MODE_GCM;
+ params.AuthAlgo = SAB_AUTH_AES_GCM;
+ if (DTLSParam_p->sec_mode == AES128_GCM)
+ params.KeyByteCount = 16;
+ else if (DTLSParam_p->sec_mode == AES256_GCM)
+ params.KeyByteCount = 32;
+
+ params.Nonce_p = DTLSParam_p->dtls_encrypt_nonce;
+
+ OutboundHKey = kcalloc(16, sizeof(uint8_t), GFP_KERNEL);
+ if (OutboundHKey == NULL) {
+ CRYPTO_ERR("%s: kmalloc for OutboundHKey failed\n", __func__);
+ goto error_exit;
+ }
+
+ mtk_ddk_aes_block_encrypt(DTLSParam_p->key_encrypt, 16, Zero, OutboundHKey);
+ if (fVerbose)
+ Log_HexDump("OutboundHKey", 0, OutboundHKey, 16);
+ // Byte-swap the HKEY
+ {
+ uint8_t t;
+ unsigned int i;
+
+ for (i = 0; i < 4; i++) {
+ t = OutboundHKey[4*i+3];
+ OutboundHKey[4*i+3] = OutboundHKey[4*i];
+ OutboundHKey[4*i] = t;
+ t = OutboundHKey[4*i+2];
+ OutboundHKey[4*i+2] = OutboundHKey[4*i+1];
+ OutboundHKey[4*i+1] = t;
+ }
+ }
+ if (fVerbose)
+ Log_HexDump("OutboundHKey (swapped)", 0, OutboundHKey, 16);
+ params.AuthKey1_p = OutboundHKey;
+ DTLSResourceEntity_p->HKeyOutbound = OutboundHKey;
+ } else {
+ CRYPTO_ERR("%s: Unknown DTLSParam_p->sec_mode: %u\n", __func__,
+ DTLSParam_p->sec_mode);
+ goto error_exit;
+ }
+ // Add crypto key and parameters.
+ params.Key_p = DTLSParam_p->key_encrypt;
+ // Add authentication key and paramters.
+ if (params.AuthAlgo == SAB_AUTH_HMAC_SHA1 || params.AuthAlgo == SAB_AUTH_HMAC_SHA2_256) {
+#ifdef EIP197_INLINE_HMAC_DIGEST_PRECOMPUTE
+ params.AuthKey1_p = DTLSParam_p->key_auth_encrypt_1; // inner digest directly
+ params.AuthKey2_p = DTLSParam_p->key_auth_encrypt_2; // outer digest directly
+#else
+ // No hardware precompute support, so preform HMAC precompute in
+ // the traditional way.
+ InnerDigest = kcalloc((size_t)params.AuthKeyByteCount, sizeof(uint8_t), GFP_KERNEL);
+ if (InnerDigest == NULL) {
+ CRYPTO_ERR("%s: kmalloc for InnerDigest failed\n", __func__);
+ goto error_exit;
+ }
+ memset(InnerDigest, 0, params.AuthKeyByteCount);
+ DTLSResourceEntity_p->InnerDigestOutbound = InnerDigest;
+ OuterDigest = kcalloc((size_t)params.AuthKeyByteCount, sizeof(uint8_t), GFP_KERNEL);
+ if (OuterDigest == NULL) {
+ CRYPTO_ERR("%s: kmalloc for OuterDigest failed\n", __func__);
+ goto error_exit;
+ }
+ memset(OuterDigest, 0, params.AuthKeyByteCount);
+ DTLSResourceEntity_p->OuterDigestOutbound = OuterDigest;
+ crypto_hmac_precompute(params.AuthAlgo,
+ DTLSParam_p->key_auth_encrypt_1,
+ params.AuthKeyByteCount,
+ InnerDigest,
+ OuterDigest);
+ if (fVerbose) {
+ Log_HexDump("Inner Digest", 0, InnerDigest, params.AuthKeyByteCount);
+ Log_HexDump("Outer Digest", 0, OuterDigest, params.AuthKeyByteCount);
+ }
+ params.AuthKey1_p = InnerDigest;
+ params.AuthKey2_p = OuterDigest;
+ InnerDigest = NULL;
+ OuterDigest = NULL;
+#endif
+ }
+
+ // Create a reference to the header processor context.
+ SSLTLSParams.epoch = DTLSParam_p->dtls_epoch;
+
+ SSLTLSParams.SSLTLSFlags |= SAB_DTLS_PROCESS_IP_HEADERS |
+ SAB_DTLS_EXT_PROCESSING | SAB_DTLS_IPV4;
+ if (fCAPWAP)
+ SSLTLSParams.SSLTLSFlags |= SAB_DTLS_CAPWAP;
+
+ // Now the SA parameters are completely filled in.
+
+ // We are ready to probe the size required for the transform
+ // record (SA).
+ SAStatus = SABuilder_GetSizes(¶ms, &SAWords, NULL, NULL);
+
+ if (fVerbose)
+ CRYPTO_INFO(
+ "%s: SABuilder_GetSizes returned %d SA size=%u words for outbound\n",
+ __func__,
+ SAStatus,
+ SAWords);
+ if (SAStatus != SAB_STATUS_OK) {
+ CRYPTO_ERR("%s: SA not created because of errors\n", __func__);
+ goto error_exit;
+ }
+
+ // Allocate a DMA-safe buffer for the SA.
+ DMAProperties.fCached = true;
+ DMAProperties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
+ DMAProperties.Bank = MTK_EIP197_INLINE_BANK_TRANSFORM;
+ DMAProperties.Size = SAWords * sizeof(uint32_t);
+
+ DMAStatus = DMABuf_Alloc(DMAProperties, &SAHostAddress,
+ &DTLSResourceEntity_p->DTLSHandleSAOutbound);
+ if (DMAStatus != DMABUF_STATUS_OK || DTLSResourceEntity_p->DTLSHandleSAOutbound.p == NULL) {
+ CRYPTO_ERR("%s Allocation of outbound SA failed\n", __func__);
+ goto error_exit;
+ }
+
+ // Now we can actually build the SA in the DMA-safe buffer.
+ SAStatus = SABuilder_BuildSA(¶ms, (uint32_t *)SAHostAddress.p, NULL, NULL);
+
+ if (SAStatus != SAB_STATUS_OK) {
+ CRYPTO_ERR("%s: SA not created because of errors\n", __func__);
+ goto error_exit;
+ }
+ if (fVerbose) {
+ CRYPTO_INFO("Outbound transform record created\n");
+
+ Log_HexDump("Outbound transform record",
+ 0,
+ SAHostAddress.p,
+ SAWords * sizeof(uint32_t));
+ }
+
+ // Prepare the Inbound SA
+ if (DTLSParam_p->dtls_version == MTK_DTLS_VERSION_1_0)
+ DTLSVersion = SAB_DTLS_VERSION_1_0;
+ else if (DTLSParam_p->dtls_version == MTK_DTLS_VERSION_1_2)
+ DTLSVersion = SAB_DTLS_VERSION_1_2;
+ else {
+ CRYPTO_ERR("%s: Unknown DTLSParam_p->dtls_version: %u\n", __func__,
+ DTLSParam_p->dtls_version);
+ goto error_exit;
+ }
+
+ // Initialize the SA parameters for ESP.The call to SABuilder_Init_ESP
+ // will initialize many parameters, next fill in more parameters, such
+ // as cryptographic keys.
+ SAStatus = SABuilder_Init_SSLTLS(¶ms,
+ &SSLTLSParams,
+ DTLSVersion,
+ SAB_DIRECTION_INBOUND);
+ if (SAStatus != SAB_STATUS_OK) {
+ CRYPTO_ERR("%s: SABuilder_Init_ESP failed\n", __func__);
+ goto error_exit;
+ }
+
+ /* Set DTLS-CAPWAP param from cmd handler */
+ if (DTLSParam_p->sec_mode == AES128_CBC_HMAC_SHA1) {
+ params.CryptoAlgo = SAB_CRYPTO_AES;
+ params.CryptoMode = SAB_CRYPTO_MODE_CBC;
+ params.KeyByteCount = 16;
+ params.AuthAlgo = SAB_AUTH_HMAC_SHA1;
+ params.AuthKeyByteCount = 20;
+ } else if (DTLSParam_p->sec_mode == AES128_CBC_HMAC_SHA2_256) {
+ params.CryptoAlgo = SAB_CRYPTO_AES;
+ params.CryptoMode = SAB_CRYPTO_MODE_CBC;
+ params.KeyByteCount = 16;
+ params.AuthAlgo = SAB_AUTH_HMAC_SHA2_256;
+ params.AuthKeyByteCount = 32;
+ } else if (DTLSParam_p->sec_mode == AES256_CBC_HMAC_SHA1) {
+ params.CryptoAlgo = SAB_CRYPTO_AES;
+ params.CryptoMode = SAB_CRYPTO_MODE_CBC;
+ params.KeyByteCount = 32;
+ params.AuthAlgo = SAB_AUTH_HMAC_SHA1;
+ params.AuthKeyByteCount = 20;
+ } else if (DTLSParam_p->sec_mode == AES256_CBC_HMAC_SHA2_256) {
+ params.CryptoAlgo = SAB_CRYPTO_AES;
+ params.CryptoMode = SAB_CRYPTO_MODE_CBC;
+ params.KeyByteCount = 32;
+ params.AuthAlgo = SAB_AUTH_HMAC_SHA2_256;
+ params.AuthKeyByteCount = 32;
+ } else if (DTLSParam_p->sec_mode == AES128_GCM || DTLSParam_p->sec_mode == AES256_GCM) {
+ params.CryptoAlgo = SAB_CRYPTO_AES;
+ params.CryptoMode = SAB_CRYPTO_MODE_GCM;
+ params.AuthAlgo = SAB_AUTH_AES_GCM;
+ if (DTLSParam_p->sec_mode == AES128_GCM)
+ params.KeyByteCount = 16;
+ else if (DTLSParam_p->sec_mode == AES256_GCM)
+ params.KeyByteCount = 32;
+
+ params.Nonce_p = DTLSParam_p->dtls_decrypt_nonce;
+
+ InboundHKey = kcalloc(16, sizeof(uint8_t), GFP_KERNEL);
+ if (InboundHKey == NULL) {
+ CRYPTO_ERR("%s: kmalloc for InboundHKey failed\n", __func__);
+ goto error_exit;
+ }
+
+ mtk_ddk_aes_block_encrypt(DTLSParam_p->key_decrypt, 16, Zero, InboundHKey);
+ if (fVerbose)
+ Log_HexDump("InboundHKey", 0, InboundHKey, 16);
+ // Byte-swap the HKEY
+ {
+ uint8_t t;
+ unsigned int i;
+
+ for (i = 0; i < 4; i++) {
+ t = InboundHKey[4*i+3];
+ InboundHKey[4*i+3] = InboundHKey[4*i];
+ InboundHKey[4*i] = t;
+ t = InboundHKey[4*i+2];
+ InboundHKey[4*i+2] = InboundHKey[4*i+1];
+ InboundHKey[4*i+1] = t;
+ }
+ }
+ if (fVerbose)
+ Log_HexDump("InboundHKey (swapped)", 0, InboundHKey, 16);
+ params.AuthKey1_p = InboundHKey;
+ DTLSResourceEntity_p->HKeyInbound = InboundHKey;
+ } else {
+ CRYPTO_ERR("%s: Unknown DTLSParam_p->sec_mode: %u\n", __func__,
+ DTLSParam_p->sec_mode);
+ goto error_exit;
+ }
+
+ // Add crypto key and parameters.
+ params.Key_p = DTLSParam_p->key_decrypt;
+ // Add authentication key and paramters.
+ if (params.AuthAlgo == SAB_AUTH_HMAC_SHA1 || params.AuthAlgo == SAB_AUTH_HMAC_SHA2_256) {
+#ifdef EIP197_INLINE_HMAC_DIGEST_PRECOMPUTE
+ params.AuthKey1_p = DTLSParam_p->key_auth_decrypt_1;
+ params.AuthKey2_p = DTLSParam_p->key_auth_decrypt_2;
+#else
+ // No hardware precompute support, so preform HMAC precompute in
+ // the traditional way.
+ InnerDigest = kcalloc(params.AuthKeyByteCount, sizeof(uint8_t), GFP_KERNEL);
+ if (InnerDigest == NULL) {
+ CRYPTO_ERR("%s: kmalloc for InnerDigest failed\n", __func__);
+ goto error_exit;
+ }
+ memset(InnerDigest, 0, params.AuthKeyByteCount);
+ DTLSResourceEntity_p->InnerDigestInbound = InnerDigest;
+ OuterDigest = kcalloc(params.AuthKeyByteCount, sizeof(uint8_t), GFP_KERNEL);
+ if (OuterDigest == NULL) {
+ CRYPTO_ERR("%s: kmalloc for OuterDigest failed\n", __func__);
+ goto error_exit;
+ }
+ memset(OuterDigest, 0, params.AuthKeyByteCount);
+ DTLSResourceEntity_p->OuterDigestInbound = OuterDigest;
+ crypto_hmac_precompute(params.AuthAlgo,
+ DTLSParam_p->key_auth_decrypt_1,
+ params.AuthKeyByteCount,
+ InnerDigest,
+ OuterDigest);
+ if (fVerbose) {
+ Log_HexDump("Inner Digest", 0, InnerDigest, params.AuthKeyByteCount);
+ Log_HexDump("Outer Digest", 0, OuterDigest, params.AuthKeyByteCount);
+ }
+ params.AuthKey1_p = InnerDigest;
+ params.AuthKey2_p = OuterDigest;
+ InnerDigest = NULL;
+ OuterDigest = NULL;
+ }
+#endif
+
+ if (fInlinePlain != fInlineCipher) {
+ params.flags |= SAB_FLAG_REDIRECT;
+ params.RedirectInterface = PEC_INTERFACE_ID; /*redirect to ring */
+ }
+
+ SSLTLSParams.SSLTLSFlags |= SAB_DTLS_PROCESS_IP_HEADERS |
+ SAB_DTLS_EXT_PROCESSING | SAB_DTLS_IPV4;
+
+ // Create a reference to the header processor context.
+ SSLTLSParams.epoch = DTLSParam_p->dtls_epoch;
+
+ if (fCAPWAP)
+ SSLTLSParams.SSLTLSFlags |= SAB_DTLS_CAPWAP;
+
+ // Now the SA parameters are completely filled in.
+
+ // We are ready to probe the size required for the transform
+ // record (SA).
+ SAStatus = SABuilder_GetSizes(¶ms, &SAWords, NULL, NULL);
+
+ if (fVerbose)
+ CRYPTO_INFO("%s: SABuilder_GetSizes returned %d SA size=%u words for inbound\n",
+ __func__,
+ SAStatus,
+ SAWords);
+
+ if (SAStatus != SAB_STATUS_OK) {
+ CRYPTO_ERR("%s: SA not created because of errors\n", __func__);
+ goto error_exit;
+ }
+
+ // Allocate a DMA-safe buffer for the SA.
+ DMAProperties.fCached = true;
+ DMAProperties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
+ DMAProperties.Bank = MTK_EIP197_INLINE_BANK_TRANSFORM;
+ DMAProperties.Size = SAWords * sizeof(uint32_t);
+
+ DMAStatus = DMABuf_Alloc(DMAProperties, &SAHostAddress,
+ &DTLSResourceEntity_p->DTLSHandleSAInbound);
+ if (DMAStatus != DMABUF_STATUS_OK || DTLSResourceEntity_p->DTLSHandleSAInbound.p == NULL) {
+ CRYPTO_ERR("%s: Allocation of inbound SA failed\n", __func__);
+ goto error_exit;
+ }
+
+ // Now we can actually build the SA in the DMA-safe buffer.
+ SAStatus = SABuilder_BuildSA(¶ms, (uint32_t *)SAHostAddress.p, NULL, NULL);
+ if (SAStatus != SAB_STATUS_OK) {
+ CRYPTO_ERR("%s: SA not created because of errors\n", __func__);
+ goto error_exit;
+ }
+ if (fVerbose) {
+ CRYPTO_INFO("Inbound transform record created\n");
+
+ Log_HexDump("Inbound transform record",
+ 0,
+ SAHostAddress.p,
+ SAWords * sizeof(uint32_t));
+ }
+
+ // Register the SAs with the PCL API. DMA buffers for hardware transforms
+ // (SAs) are allocated and filled in external to the PCL API.
+ PCL_Status = PCL_Transform_Register(DTLSResourceEntity_p->DTLSHandleSAOutbound);
+ if (PCL_Status != PCL_STATUS_OK) {
+ CRYPTO_ERR("%s: PCL_Transform_Register failed\n", __func__);
+ goto error_exit;
+ }
+ if (fVerbose)
+ CRYPTO_INFO("%s: Outbound transform registered\n", __func__);
+
+ PCL_Status = PCL_Transform_Register(DTLSResourceEntity_p->DTLSHandleSAInbound);
+ if (PCL_Status != PCL_STATUS_OK) {
+ CRYPTO_ERR("%s: PCL_Transform_Register failed\n", __func__);
+ PCL_Transform_UnRegister(DTLSResourceEntity_p->DTLSHandleSAOutbound);
+ goto error_exit;
+ }
+ if (fVerbose)
+ CRYPTO_INFO("%s: Inbound transform registered\n", __func__);
+
+
+
+ /* Create the DTL entries. */
+ if (fPktCfy) {
+ ZEROINIT(SelectorParams);
+ ZEROINIT(DTLTransformParams);
+
+ SelectorParams.flags = PCL_SELECT_IPV4;
+ SelectorParams.SrcIp = ((unsigned char *)(&(DTLSParam_p->sip)));
+ SelectorParams.DstIp = ((unsigned char *)(&(DTLSParam_p->dip)));
+ SelectorParams.IpProto = 17; //UDP
+ SelectorParams.SrcPort = DTLSParam_p->sport;
+ SelectorParams.DstPort = DTLSParam_p->dport;
+ SelectorParams.spi = 0;
+ SelectorParams.epoch = 0; // No epoch, not present in outbound packet
+
+ /* Compute the hash for the inbound DTL */
+ PCL_Status = PCL_Flow_Hash(&SelectorParams, DTLTransformParams.HashID);
+ if (PCL_Status != PCL_STATUS_OK) {
+ CRYPTO_ERR("%s: PEC_Flow_Hash failed\n", __func__);
+ goto error_exit_unregister;
+ }
+ if (fVerbose)
+ CRYPTO_INFO("%s: Inbound flow hashed\n", __func__);
+
+ /* Add the inbound DTL entry. */
+ PCL_Status = PCL_DTL_Transform_Add(PCL_INTERFACE_ID, 0,
+ &DTLTransformParams,
+ DTLSResourceEntity_p->DTLSHandleSAOutbound,
+ &SAHashHandle);
+ if (PCL_Status != PCL_STATUS_OK) {
+ CRYPTO_ERR("%s: PEC_DTL_Transform_Add failed\n", __func__);
+ goto error_exit_unregister;
+ }
+ if (fVerbose)
+ CRYPTO_INFO("%s: Outbound DTL added\n", __func__);
+
+ ZEROINIT(SelectorParams);
+ ZEROINIT(DTLTransformParams);
+
+ SelectorParams.flags = PCL_SELECT_IPV4;
+ SelectorParams.DstIp = ((unsigned char *)(&(DTLSParam_p->sip)));
+ SelectorParams.SrcIp = ((unsigned char *)(&(DTLSParam_p->dip)));
+ SelectorParams.SrcPort = DTLSParam_p->dport;
+ SelectorParams.DstPort = DTLSParam_p->sport;
+ SelectorParams.IpProto = 17; //UDP
+ SelectorParams.epoch = DTLSParam_p->dtls_epoch;
+
+ /* Compute the hash for the inbound DTL */
+ PCL_Status = PCL_Flow_Hash(&SelectorParams, DTLTransformParams.HashID);
+ if (PCL_Status != PCL_STATUS_OK) {
+ CRYPTO_ERR("%s: PEC_Flow_Hash failed\n", __func__);
+ PCL_DTL_Transform_Remove(PCL_INTERFACE_ID, 0,
+ DTLSResourceEntity_p->DTLSHandleSAOutbound);
+ goto error_exit_unregister;
+ }
+ if (fVerbose)
+ CRYPTO_INFO("%s: Inbound lookup hashed\n", __func__);
+
+ /* Add the inbound DTL entry. */
+ PCL_Status = PCL_DTL_Transform_Add(PCL_INTERFACE_ID, 0,
+ &DTLTransformParams,
+ DTLSResourceEntity_p->DTLSHandleSAInbound,
+ &SAHashHandle);
+ if (PCL_Status != PCL_STATUS_OK) {
+ CRYPTO_ERR("%s: PEC_DTL_Transform_Add failed\n", __func__);
+ PCL_DTL_Transform_Remove(PCL_INTERFACE_ID, 0,
+ DTLSResourceEntity_p->DTLSHandleSAOutbound);
+ goto error_exit_unregister;
+ }
+ if (fVerbose)
+ CRYPTO_INFO("%s: Inbound DTL added\n", __func__);
+ }
+
+ /* At this point, both outbound and inbound transforms have been
+ * registered and both outbound and inbound DTL entries are added to the
+ * lookup table. The Packet Engine is ready to accept packets and
+ * perform classification and processing autonomously.*/
+
+ if (fVerbose)
+ CRYPTO_INFO("*** Finished update DTLS-CAPWAP SA ***\n\n");
+
+ // If we made it to here, consider this run a success. Any jump
+ // to one of the error labels below will skip "success = true"
+ success = true;
+ DTLSParam_p->SA_encrypt = DTLSResourceEntity_p->DTLSHandleSAOutbound.p;
+ DTLSParam_p->SA_decrypt = DTLSResourceEntity_p->DTLSHandleSAInbound.p;
+ DTLSResourceEntity_p->DTLSParam = DTLSParam_p;
+ *DTLSResource = DTLSResourceEntity_p;
+
+ return success;
+
+
+error_exit_unregister:
+ /* At this point, all flows have been removed, so we can start
+ * removing the transform records. Note: all flows that use the
+ * transform must be removed before removing the transform.
+ *
+ * When any flow creation error occurs, return to this point. The
+ * flow records have not been created, but the transform records
+ * are registered at this point.
+ */
+
+ /* Obtain statistics of the outbound transform. We do this at the
+ * end of the lifetime of the transform, but it can be done at any
+ * time when the transform is registered.*/
+ PCL_Status = PCL_Transform_Get_ReadOnly(DTLSResourceEntity_p->DTLSHandleSAOutbound,
+ &TransformParams);
+ if (PCL_Status != PCL_STATUS_OK)
+ CRYPTO_ERR("%s: Could not obtain statistics for outbound transform\n", __func__);
+ else
+ CRYPTO_INFO("Statistics of outbound transform: %u packets %u octets\n",
+ TransformParams.PacketsCounterLo,
+ TransformParams.OctetsCounterLo);
+
+ /* Obtain statistics of the inbound transform. */
+ PCL_Status = PCL_Transform_Get_ReadOnly(DTLSResourceEntity_p->DTLSHandleSAInbound,
+ &TransformParams);
+ if (PCL_Status != PCL_STATUS_OK)
+ CRYPTO_ERR("%s: Could not obtain statistics for inbound transform\n", __func__);
+ else
+ CRYPTO_INFO("Statistics of inbound transform: %u packets %u octets\n",
+ TransformParams.PacketsCounterLo,
+ TransformParams.OctetsCounterLo);
+
+
+ /* Unregister both transforms. Report, but do not handle the
+ * results of these calls. If they fail, there is nothing sensible
+ * that we can do to recover.
+ */
+ if (!mtk_ddk_invalidate_rec(DTLSResourceEntity_p->DTLSHandleSAOutbound, true))
+ CRYPTO_ERR("%s: transform invalidate failed\n", __func__);
+ else if (fVerbose)
+ CRYPTO_INFO("transform invalidate succeeded\n");
+
+
+ PCL_Status = PCL_Transform_UnRegister(DTLSResourceEntity_p->DTLSHandleSAOutbound);
+ if (PCL_Status != PCL_STATUS_OK)
+ CRYPTO_ERR("%s: PCL_Transform_UnRegister failed\n", __func__);
+ else if (fVerbose)
+ CRYPTO_INFO("PCL_Transform_UnRegister succeeded\n");
+
+
+ if (!mtk_ddk_invalidate_rec(DTLSResourceEntity_p->DTLSHandleSAInbound, true))
+ CRYPTO_ERR("%s: transform invalidate failed\n", __func__);
+ else if (fVerbose)
+ CRYPTO_INFO("transform invalidate succeeded\n");
+
+
+ PCL_Status = PCL_Transform_UnRegister(DTLSResourceEntity_p->DTLSHandleSAInbound);
+ if (PCL_Status != PCL_STATUS_OK)
+ CRYPTO_ERR("%s: PCL_Transform_UnRegister failed\n", __func__);
+ else if (fVerbose)
+ CRYPTO_INFO("PCL_Transform_UnRegister succeeded\n");
+
+
+error_exit:
+ /* Remove the buffers occupied by the transforms, the packets and the
+ * header processor contexts.
+ *
+ * Return here if any error occurs before the transforms are registered.
+ * When we return here with an error, not all buffers may have been
+ * allocated.
+ * Note: DMABuf_Release can be called when no buffer was allocated.
+ */
+ if (DTLSResourceEntity_p != NULL) {
+ if (DTLSResourceEntity_p->DTLSHandleSAOutbound.p != NULL) {
+ DMABuf_Release(DTLSResourceEntity_p->DTLSHandleSAOutbound);
+ DTLSResourceEntity_p->DTLSHandleSAOutbound.p = NULL;
+ DTLSResourceEntity_p->DTLSParam->SA_encrypt = (void *) NULL;
+ }
+ if (DTLSResourceEntity_p->DTLSHandleSAInbound.p != NULL) {
+ DMABuf_Release(DTLSResourceEntity_p->DTLSHandleSAInbound);
+ DTLSResourceEntity_p->DTLSHandleSAInbound.p = NULL;
+ DTLSResourceEntity_p->DTLSParam->SA_decrypt = (void *) NULL;
+ }
+ if (DTLSResourceEntity_p->HKeyOutbound != NULL) {
+ kfree(DTLSResourceEntity_p->HKeyOutbound);
+ DTLSResourceEntity_p->HKeyOutbound = NULL;
+ }
+ if (DTLSResourceEntity_p->HKeyInbound != NULL) {
+ kfree(DTLSResourceEntity_p->HKeyInbound);
+ DTLSResourceEntity_p->HKeyInbound = NULL;
+ }
+ if (DTLSResourceEntity_p->InnerDigestInbound != NULL) {
+ kfree(DTLSResourceEntity_p->InnerDigestInbound);
+ DTLSResourceEntity_p->InnerDigestInbound = NULL;
+ }
+ if (DTLSResourceEntity_p->OuterDigestInbound != NULL) {
+ kfree(DTLSResourceEntity_p->OuterDigestInbound);
+ DTLSResourceEntity_p->OuterDigestInbound = NULL;
+ }
+ if (DTLSResourceEntity_p->InnerDigestOutbound != NULL) {
+ kfree(DTLSResourceEntity_p->InnerDigestOutbound);
+ DTLSResourceEntity_p->InnerDigestOutbound = NULL;
+ }
+ if (DTLSResourceEntity_p->OuterDigestOutbound != NULL) {
+ kfree(DTLSResourceEntity_p->OuterDigestOutbound);
+ DTLSResourceEntity_p->OuterDigestOutbound = NULL;
+ }
+ if (DTLSResourceEntity_p != NULL) {
+ kfree(DTLSResourceEntity_p);
+ DTLSResourceEntity_p = NULL;
+ }
+ *DTLSResource = NULL;
+ }
+ return success;
+}
+
+void mtk_ddk_remove_dtls_param(struct DTLSResourceMgmt **DTLSResource)
+{
+ bool fVerbose = false;
+ bool fPktCfy = true;
+ PCL_Status_t PCL_Status;
+ PCL_TransformParams_t TransformParams;
+
+ if (*DTLSResource == NULL) {
+ if (fVerbose)
+ CRYPTO_ERR("%s: DTLSResource is NULL\n", __func__);
+ return;
+ }
+
+ // unregister_flows
+ if (fPktCfy) {
+ PCL_Status = PCL_DTL_Transform_Remove(PCL_INTERFACE_ID, 0,
+ (*DTLSResource)->DTLSHandleSAInbound);
+ if (PCL_Status != PCL_STATUS_OK)
+ CRYPTO_ERR("%s: PCL_DLT_Tansform_Remove Inbound failed\n", __func__);
+ else
+ if (fVerbose)
+ CRYPTO_INFO("PCL_DTL_Transform_Remove Inbound succeeded\n");
+
+ PCL_Status = PCL_DTL_Transform_Remove(PCL_INTERFACE_ID, 0,
+ (*DTLSResource)->DTLSHandleSAOutbound);
+ if (PCL_Status != PCL_STATUS_OK)
+ CRYPTO_ERR("%s: PCL_DLT_Tansform_Remove Outbound failed\n", __func__);
+ else
+ if (fVerbose)
+ CRYPTO_INFO("PCL_DTL_Transform_Remove Outbound succeeded\n");
+ }
+
+ /* At this point, all flows have been removed, so we can start
+ * removing the transform records. Note: all flows that use the
+ * transform must be removed before removing the transform.
+ *
+ * When any flow creation error occurs, return to this point. The
+ * flow records have not been created, but the transform records
+ * are registered at this point.
+ */
+
+ /* Obtain statistics of the outbound transform. We do this at the
+ * end of the lifetime of the transform, but it can be done at any
+ * time when the transform is registered.*/
+ PCL_Status = PCL_Transform_Get_ReadOnly((*DTLSResource)->DTLSHandleSAOutbound,
+ &TransformParams);
+ if (PCL_Status != PCL_STATUS_OK)
+ CRYPTO_ERR("%s: Could not obtain statistics for outbound transform\n", __func__);
+ else
+ CRYPTO_INFO("Statistics of outbound transform: %u packets %u octets\n",
+ TransformParams.PacketsCounterLo,
+ TransformParams.OctetsCounterLo);
+
+ /* Obtain statistics of the inbound transform. */
+ PCL_Status = PCL_Transform_Get_ReadOnly((*DTLSResource)->DTLSHandleSAInbound,
+ &TransformParams);
+ if (PCL_Status != PCL_STATUS_OK)
+ CRYPTO_ERR("%s: Could not obtain statistics for inbound transform\n", __func__);
+ else
+ CRYPTO_INFO("Statistics of inbound transform: %u packets %u octets\n",
+ TransformParams.PacketsCounterLo,
+ TransformParams.OctetsCounterLo);
+
+
+ /* Unregister both transforms. Report, but do not handle the
+ * results of these calls. If they fail, there is nothing sensible
+ * that we can do to recover.
+ */
+ if (!mtk_ddk_invalidate_rec((*DTLSResource)->DTLSHandleSAOutbound, true))
+ CRYPTO_ERR("%s: transform invalidate failed\n", __func__);
+ else
+ if (fVerbose)
+ CRYPTO_INFO("transform invalidate succeeded\n");
+#ifdef PEC_PCL_EIP197
+ PCL_Status = PCL_Transform_UnRegister((*DTLSResource)->DTLSHandleSAOutbound);
+ if (PCL_Status != PCL_STATUS_OK)
+ CRYPTO_ERR("%s: PCL_Transform_UnRegister failed\n", __func__);
+ else
+ if (fVerbose)
+ CRYPTO_INFO("PCL_Transform_UnRegister succeeded\n");
+#else
+ PEC_SA_UnRegister(PCL_INTERFACE_ID, (*DTLSResource)->DTLSHandleSAOutbound,
+ DMABuf_NULLHandle, DMABuf_NULLHandle);
+#endif
+
+ if (!mtk_ddk_invalidate_rec((*DTLSResource)->DTLSHandleSAInbound, true))
+ CRYPTO_ERR("%s: transform invalidate failed\n", __func__);
+ else
+ if (fVerbose)
+ CRYPTO_INFO("transform invalidate succeeded\n");
+#ifdef PEC_PCL_EIP197
+ PCL_Status = PCL_Transform_UnRegister((*DTLSResource)->DTLSHandleSAInbound);
+ if (PCL_Status != PCL_STATUS_OK)
+ CRYPTO_ERR("%s: PCL_Transform_UnRegister failed\n", __func__);
+ else
+ if (fVerbose)
+ CRYPTO_INFO("PCL_Transform_UnRegister succeeded\n");
+#else
+ PEC_SA_UnRegister(PCL_INTERFACE_ID, (*DTLSResource)->DTLSHandleSAInbound,
+ DMABuf_NULLHandle, DMABuf_NULLHandle);
+#endif
+
+ /* Remove the buffers occupied by the transforms, the packets and the
+ * header processor contexts.
+ *
+ * Return here if any error occurs before the transforms are registered.
+ * When we return here with an error, not all buffers may have been
+ * allocated.
+ * Note: DMABuf_Release can be called when no buffer was allocated.
+ */
+ if ((*DTLSResource)->DTLSHandleSAOutbound.p != NULL) {
+ DMABuf_Release((*DTLSResource)->DTLSHandleSAOutbound);
+ (*DTLSResource)->DTLSHandleSAOutbound.p = NULL;
+ (*DTLSResource)->DTLSParam->SA_encrypt = (void *) NULL;
+ }
+ if ((*DTLSResource)->DTLSHandleSAInbound.p != NULL) {
+ DMABuf_Release((*DTLSResource)->DTLSHandleSAInbound);
+ (*DTLSResource)->DTLSHandleSAInbound.p = NULL;
+ (*DTLSResource)->DTLSParam->SA_decrypt = (void *) NULL;
+ }
+ if ((*DTLSResource)->HKeyOutbound != NULL) {
+ kfree((*DTLSResource)->HKeyOutbound);
+ (*DTLSResource)->HKeyOutbound = NULL;
+ }
+ if ((*DTLSResource)->HKeyInbound != NULL) {
+ kfree((*DTLSResource)->HKeyInbound);
+ (*DTLSResource)->HKeyInbound = NULL;
+ }
+ if ((*DTLSResource)->InnerDigestInbound != NULL) {
+ kfree((*DTLSResource)->InnerDigestInbound);
+ (*DTLSResource)->InnerDigestInbound = NULL;
+ }
+ if ((*DTLSResource)->OuterDigestInbound != NULL) {
+ kfree((*DTLSResource)->OuterDigestInbound);
+ (*DTLSResource)->OuterDigestInbound = NULL;
+ }
+ if ((*DTLSResource)->InnerDigestOutbound != NULL) {
+ kfree((*DTLSResource)->InnerDigestOutbound);
+ (*DTLSResource)->InnerDigestOutbound = NULL;
+ }
+ if ((*DTLSResource)->OuterDigestOutbound != NULL) {
+ kfree((*DTLSResource)->OuterDigestOutbound);
+ (*DTLSResource)->OuterDigestOutbound = NULL;
+ }
+ if (*DTLSResource != NULL) {
+ kfree(*DTLSResource);
+ *DTLSResource = NULL;
+ }
+ *DTLSResource = NULL;
}