[][openwrt][mt7988][crypto][EIP197 DDK Porting]

[Description]
Add eip197 DDK(Driver Development Kit) and firmware
to eip197 package(crypto-eip)

eip197 DDK v5.6.1
eip197b-iew firmware v3.5

[Release-log]
N/A

Change-Id: I662327ecfbdac69742bf0b50362d7c28fc06372b
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/7895272
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder.c
new file mode 100644
index 0000000..84401f4
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder.c
@@ -0,0 +1,1720 @@
+/* sa_builder.c
+ *
+ * Main implementation file of the EIP-96 SA builder.
+ */
+
+/*****************************************************************************
+* Copyright (c) 2011-2022 by Rambus, Inc. and/or its subsidiaries.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+#include "sa_builder.h"
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+#include "c_sa_builder.h"
+#include "basic_defs.h"
+#include "log.h"
+#include "sa_builder_internal.h"
+
+#ifdef SAB_AUTO_TOKEN_CONTEXT_GENERATION
+#include "token_builder.h"
+#endif
+
+#if defined(SAB_ENABLE_IPSEC_EXTENDED) || defined(SAB_ENABLE_BASIC_EXTENDED)
+#include "sa_builder_extended_internal.h"
+#include "firmware_eip207_api_flow_cs.h"
+#endif
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+#if defined(SAB_ENABLE_IPSEC_EXTENDED) || defined(SAB_ENABLE_SSLTLS_EXTENDED)
+unsigned int LargeTransformOffset = SAB_LARGE_TRANSFORM_OFFSET;
+#else
+#define LargeTransformOffset 16
+#endif
+
+/*----------------------------------------------------------------------------
+ * SABuilderLib_CopyKeyMat
+ *
+ * Copy a key into the SA.
+ *
+ * Destination_p (input)
+ *   Destination (word-aligned) of the SA record.
+ *
+ * offset (input)
+ *   Word offset of the key in the SA record where it must be stored.
+ *
+ * Source_p (input)
+ *   Source (byte aligned) of the data.
+ *
+ * KeyByteCount (input)
+ *   Size of the key in bytes.
+ *
+ * Destination_p is allowed to be a null pointer, in which case no key
+ * will be written.
+ */
+void
+SABuilderLib_CopyKeyMat(
+        uint32_t * const Destination_p,
+        const unsigned int offset,
+        const uint8_t * const Source_p,
+        const unsigned int KeyByteCount)
+{
+    uint32_t *dst = Destination_p + offset;
+    const uint8_t *src = Source_p;
+    unsigned int i,j;
+    uint32_t w;
+    if (Destination_p == NULL)
+        return;
+    for(i=0; i < KeyByteCount / sizeof(uint32_t); i++)
+    {
+        w=0;
+        for(j=0; j<sizeof(uint32_t); j++)
+            w=(w>>8)|(*src++ << 24);
+        *dst++ = w;
+    }
+    if ((KeyByteCount % sizeof(uint32_t)) != 0)
+    {
+        w=0;
+        for(j=0; j<KeyByteCount % sizeof(uint32_t); j++)
+        {
+            w = w | (*src++ << (j*8));
+        }
+        *dst++ = w;
+    }
+}
+
+
+/*----------------------------------------------------------------------------
+ * SABuilderLib_CopyKeyMatSwap
+ *
+ * Copy a key into the SA with the words byte-swapped.
+ *
+ * Destination_p (input)
+ *   Destination (word-aligned) to store the data.
+ *
+ * offset (input)
+ *   Word offset of the key in the SA record where it must be stored.
+ *
+ * Source_p (input)
+ *   Source (byte aligned) of the data.
+ *
+ * KeyByteCount (input)
+ *   Size of the key in bytes.
+ *
+ * Destination_p is allowed to be a null pointer, in which case no key
+ * will be written.
+ */
+void
+SABuilderLib_CopyKeyMatSwap(
+        uint32_t * const Destination_p,
+        const unsigned int offset,
+        const uint8_t * const Source_p,
+        const unsigned int KeyByteCount)
+{
+    uint32_t *dst = Destination_p + offset;
+    const uint8_t *src = Source_p;
+    unsigned int i,j;
+    uint32_t w;
+
+    if (Destination_p == NULL)
+        return;
+
+    for(i=0; i < KeyByteCount  / sizeof(uint32_t); i++)
+    {
+        w=0;
+
+        for(j=0; j<sizeof(uint32_t); j++)
+            w=(w<<8)|(*src++);
+
+        *dst++ = w;
+    }
+    if ((KeyByteCount % sizeof(uint32_t)) != 0)
+    {
+        w=0;
+        for(j=0; j<KeyByteCount % sizeof(uint32_t); j++)
+        {
+            w = w | (*src++ << (24 - j*8));
+        }
+        *dst++ = w;
+    }
+}
+
+
+/*----------------------------------------------------------------------------
+ * SABuilderLib_ZeroFill
+ *
+ * Fill an area in the SA with zero bytes.
+ *
+ * Destination_p (input)
+ *   Destination (word-aligned) of the SA record.
+ *
+ * offset (input)
+ *   Word offset of the area in the SA that must be zero-filled.
+ *
+ * ByteCount (input)
+ *   Number of bytes to write.
+ *
+ * Destination_p is allowed to be a null pointer, in which case no zeroes
+ * will be written.
+ */
+void
+SABuilderLib_ZeroFill(
+        uint32_t * const Destination_p,
+        const unsigned int offset,
+        const unsigned int ByteCount)
+{
+    uint32_t *dst = Destination_p + offset;
+    unsigned int i;
+    if (Destination_p == NULL)
+        return;
+    for(i=0; i < (ByteCount + sizeof(uint32_t) - 1) / sizeof(uint32_t); i++)
+    {
+        *dst++ = 0;
+    }
+}
+
+#ifdef SAB_ARC4_STATE_IN_SA
+/*----------------------------------------------------------------------------
+ * SABuilder_AlignForARc4State
+ *
+ * Align CurrentOffset to the alignment as specified by
+ * SAB_ARC4_STATE_ALIGN_BYTE_COUNT
+ */
+static unsigned int
+SABuilder_AlignForARc4State(
+        unsigned int CurrentOffset)
+{
+#if SAB_ARC4_STATE_ALIGN_BYTE_COUNT <= 4
+    return CurrentOffset;
+#else
+    uint32_t AlignMask = (SAB_ARC4_STATE_ALIGN_BYTE_COUNT >> 2) - 1;
+    return (CurrentOffset + AlignMask) & ~AlignMask;
+#endif
+}
+#endif
+
+
+/*----------------------------------------------------------------------------
+ * SABuilder_SetCipherKeys
+ *
+ * Fill in cipher keys and associated command word fields in SA.
+ *
+ * SAParams_p (input)
+ *   The SA parameters structure from which the SA is derived.
+ *
+ * SAState_p (input, output)
+ *   Variables containing information about the SA being generated.
+ *
+ * SABuffer_p (input, output).
+ *   The buffer in which the SA is built. If NULL, no SA will be built, but
+ *   state variables in SAState_p will still be updated.
+ *
+ * Return:
+ * SAB_STATUS_OK on success
+ * SAB_INVALID_PARAMETER when SAParams_p is invalid, or if any of
+ *    the buffer arguments  is a null pointer while the corresponding buffer
+ *    would be required for the operation.
+ * SAB_UNSUPPORTED_FEATURE when SAParams_p describes an operations that
+ *    is not supported on the hardware for which this SA builder
+ *    is configured.
+ */
+static SABuilder_Status_t
+SABuilder_SetCipherKeys(
+        SABuilder_Params_t *const SAParams_p,
+        SABuilder_State_t * const SAState_p,
+        uint32_t * const SABuffer_p)
+{
+    /* Fill in crypto-algorithm specific parameters */
+    switch (SAParams_p->CryptoAlgo)
+    {
+    case SAB_CRYPTO_NULL: /* Null crypto, do nothing */
+        break;
+#ifdef SAB_ENABLE_CRYPTO_3DES
+    case SAB_CRYPTO_DES:
+        SAState_p->CipherKeyWords = 2;
+        SAState_p->IVWords = 2;
+        SAState_p->CW0 |= SAB_CW0_CRYPTO_DES;
+        break;
+    case SAB_CRYPTO_3DES:
+        SAState_p->CipherKeyWords = 6;
+        SAState_p->IVWords = 2;
+        SAState_p->CW0 |= SAB_CW0_CRYPTO_3DES;
+        break;
+#endif
+#ifdef SAB_ENABLE_CRYPTO_AES
+    case SAB_CRYPTO_AES:
+        switch (SAParams_p->KeyByteCount)
+        {
+        case 16:
+            SAState_p->CW0 |= SAB_CW0_CRYPTO_AES_128;
+            SAState_p->CipherKeyWords = 4;
+            break;
+        case 24:
+            SAState_p->CW0 |= SAB_CW0_CRYPTO_AES_192;
+            SAState_p->CipherKeyWords = 6;
+            break;
+        case 32:
+            SAState_p->CW0 |= SAB_CW0_CRYPTO_AES_256;
+            SAState_p->CipherKeyWords = 8;
+            break;
+        default:
+            LOG_CRIT("SABuilder: Bad key size for AES.\n");
+            return SAB_INVALID_PARAMETER;
+        }
+        SAState_p->IVWords = 4;
+        break;
+#endif
+#ifdef SAB_ENABLE_CRYPTO_ARCFOUR
+    case SAB_CRYPTO_ARCFOUR:
+        SAState_p->CW0 |= SAB_CW0_CRYPTO_ARC4;
+        if (SAParams_p->KeyByteCount < 5 ||
+            SAParams_p->KeyByteCount > 16)
+        {
+            LOG_CRIT("SABuilder: Bad key size for ARCFOUR.\n");
+            return SAB_INVALID_PARAMETER;
+        }
+        SAState_p->CW1 |= SAParams_p->KeyByteCount;
+        SAState_p->CipherKeyWords =
+            ((unsigned int)SAParams_p->KeyByteCount + sizeof(uint32_t) - 1) /
+            sizeof(uint32_t);
+
+        if (SAParams_p->CryptoMode != SAB_CRYPTO_MODE_STATELESS)
+        {
+            SAState_p->ARC4State = true;
+            SAState_p->CW1 |= SAB_CW1_ARC4_IJ_PTR | SAB_CW1_ARC4_STATE_SEL |
+                SAB_CW1_CRYPTO_STORE;
+        }
+        break;
+#endif
+#ifdef SAB_ENABLE_CRYPTO_SM4
+    case SAB_CRYPTO_SM4:
+        SAState_p->CipherKeyWords = 4;
+        SAState_p->IVWords = 4;
+        SAState_p->CW0 |= SAB_CW0_CRYPTO_SM4;
+        break;
+#endif
+#ifdef SAB_ENABLE_CRYPTO_BC0
+    case SAB_CRYPTO_BC0:
+        SAState_p->CipherKeyWords = 8;
+        SAState_p->IVWords = 4;
+        SAState_p->CW0 |= SAB_CW0_CRYPTO_BC0 +
+            ((SAParams_p->CryptoParameter & 0x3) << 17) ;
+        SAState_p->CW1 |= SAB_CW1_EXT_CIPHER_SET;
+        break;
+#endif
+#ifdef SAB_ENABLE_CRYPTO_KASUMI
+    case SAB_CRYPTO_KASUMI:
+        SAState_p->CipherKeyWords = 4;
+        SAState_p->IVWords = 0;
+        SAState_p->CW0 |= SAB_CW0_CRYPTO_KASUMI;
+        break;
+#endif
+#ifdef SAB_ENABLE_CRYPTO_SNOW
+    case SAB_CRYPTO_SNOW:
+        SAState_p->CipherKeyWords = 4;
+        SAState_p->IVWords = 4;
+        SAState_p->CW0 |= SAB_CW0_CRYPTO_SNOW;
+        break;
+#endif
+#ifdef SAB_ENABLE_CRYPTO_ZUC
+    case SAB_CRYPTO_ZUC:
+        SAState_p->CipherKeyWords = 4;
+        SAState_p->IVWords = 4;
+        SAState_p->CW0 |= SAB_CW0_CRYPTO_ZUC;
+        break;
+#endif
+#ifdef SAB_ENABLE_CRYPTO_CHACHAPOLY
+    case SAB_CRYPTO_CHACHA20:
+        SAState_p->CW0 |= SAB_CW0_CRYPTO_CHACHA20;
+        switch (SAParams_p->KeyByteCount)
+        {
+        case 16:
+            SAState_p->CW1 |= SAB_CW1_CRYPTO_MODE_CHACHA128;
+            SAState_p->CipherKeyWords = 4;
+            break;
+        case 32:
+            SAState_p->CW1 |= SAB_CW1_CRYPTO_MODE_CHACHA256;
+            SAState_p->CipherKeyWords = 8;
+            break;
+        default:
+            LOG_CRIT("SABuilder: Bad key size for Chacha20.\n");
+            return SAB_INVALID_PARAMETER;
+        }
+        break;
+#endif
+    default:
+        LOG_CRIT("SABuilder: Unsupported crypto algorithm\n");
+        return SAB_UNSUPPORTED_FEATURE;
+    }
+
+    /* Check block cipher length against provided key  */
+    if (SAParams_p->CryptoAlgo != SAB_CRYPTO_ARCFOUR &&
+        SAState_p->CipherKeyWords*sizeof(uint32_t) != SAParams_p->KeyByteCount)
+    {
+        LOG_CRIT("SABuilder: Bad cipher key size..\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+#ifdef SAB_STRICT_ARGS_CHECK
+    if ( SAState_p->CipherKeyWords > 0 && SAParams_p->Key_p == NULL)
+    {
+        LOG_CRIT("SABuilder: NULL pointer for Key_p.\n");
+        return SAB_INVALID_PARAMETER;
+    }
+#endif
+
+#ifdef SAB_ENABLE_CRYPTO_CHACHAPOLY
+    if (SAParams_p->CryptoAlgo == SAB_CRYPTO_CHACHA20 &&
+        SAParams_p->KeyByteCount == 16)
+    {
+        /* Copy the key twice for 128-bit Chacha20 */
+        SABuilderLib_CopyKeyMat(SABuffer_p, SAState_p->CurrentOffset,
+                                SAParams_p->Key_p, SAParams_p->KeyByteCount);
+        SAState_p->CurrentOffset += SAState_p->CipherKeyWords;
+    }
+#endif
+    /* Copy the cipher key */
+    SABuilderLib_CopyKeyMat(SABuffer_p, SAState_p->CurrentOffset,
+                            SAParams_p->Key_p, SAParams_p->KeyByteCount);
+
+    if (SAParams_p->CryptoAlgo == SAB_CRYPTO_ARCFOUR)
+        SAState_p->CurrentOffset += 4; /* Always use 4 words for key in ARC4*/
+    else
+        SAState_p->CurrentOffset += SAState_p->CipherKeyWords;
+
+    /* Check that wireless algorithms are not used with authentication */
+    if ((SAParams_p->CryptoAlgo == SAB_CRYPTO_KASUMI ||
+         SAParams_p->CryptoAlgo == SAB_CRYPTO_SNOW ||
+         SAParams_p->CryptoAlgo == SAB_CRYPTO_ZUC) &&
+        SAParams_p->AuthAlgo != SAB_AUTH_NULL)
+    {
+        LOG_CRIT("SABuilder: "
+                 "Crypto algorithm cannot be combined with authentication.\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    /* Handle feedback modes */
+    if (SAParams_p->CryptoAlgo == SAB_CRYPTO_DES ||
+        SAParams_p->CryptoAlgo == SAB_CRYPTO_3DES ||
+        SAParams_p->CryptoAlgo == SAB_CRYPTO_AES ||
+        SAParams_p->CryptoAlgo == SAB_CRYPTO_SM4 ||
+        SAParams_p->CryptoAlgo == SAB_CRYPTO_BC0)
+    {
+        switch (SAParams_p->CryptoMode)
+        {
+        case SAB_CRYPTO_MODE_ECB:
+            SAState_p->CW1 |= SAB_CW1_CRYPTO_MODE_ECB;
+            SAState_p->IVWords = 0;
+            break;
+        case SAB_CRYPTO_MODE_CBC:
+            SAState_p->CW1 |= SAB_CW1_CRYPTO_MODE_CBC;
+            break;
+        case SAB_CRYPTO_MODE_CFB:
+            SAState_p->CW1 |= SAB_CW1_CRYPTO_MODE_CFB;
+            break;
+        case SAB_CRYPTO_MODE_OFB:
+            SAState_p->CW1 |= SAB_CW1_CRYPTO_MODE_OFB;
+            break;
+        case SAB_CRYPTO_MODE_CTR:
+            SAState_p->CW1 |= SAB_CW1_CRYPTO_MODE_CTR;
+            break;
+        case SAB_CRYPTO_MODE_ICM:
+            SAState_p->CW1 |= SAB_CW1_CRYPTO_MODE_ICM;
+            break;
+        case SAB_CRYPTO_MODE_CCM:
+            SAState_p->CW1 |= SAB_CW1_CRYPTO_MODE_CTR_LOAD;
+            if (SAParams_p->AuthAlgo != SAB_AUTH_AES_CCM)
+            {
+                LOG_CRIT("SABuilder: crypto CCM requires auth CCM.\n");
+                return SAB_INVALID_PARAMETER;
+            }
+            break;
+        case SAB_CRYPTO_MODE_GCM:
+            SAState_p->CW1 |= SAB_CW1_CRYPTO_MODE_CTR;
+            if (SAParams_p->AuthAlgo != SAB_AUTH_AES_GCM)
+            {
+                LOG_CRIT("SABuilder: crypto GCM requires auth GCM.\n");
+                return SAB_INVALID_PARAMETER;
+            }
+            break;
+        case SAB_CRYPTO_MODE_GMAC:
+            SAState_p->CW1 |= SAB_CW1_CRYPTO_MODE_CTR;
+            if (SAParams_p->AuthAlgo != SAB_AUTH_AES_GMAC)
+            {
+                LOG_CRIT("SABuilder: crypto GMAC requires auth GMAC.\n");
+                return SAB_INVALID_PARAMETER;
+            }
+            break;
+#ifdef SAB_ENABLE_CRYPTO_XTS
+        case SAB_CRYPTO_MODE_XTS:
+            SAState_p->CW1 |= SAB_CW1_CRYPTO_MODE_XTS;
+            if (SAParams_p->AuthAlgo != SAB_AUTH_NULL)
+            {
+                LOG_CRIT("SABuilder: crypto AES-XTS requires auth NULL.\n");
+                return SAB_INVALID_PARAMETER;
+            }
+            break;
+        case SAB_CRYPTO_MODE_XTS_STATEFUL:
+            SAState_p->CW1 |= SAB_CW1_CRYPTO_MODE_XTS | SAB_CW1_XTS_STATEFUL;
+            if (SAParams_p->AuthAlgo != SAB_AUTH_NULL)
+            {
+                LOG_CRIT("SABuilder: crypto AES-XTS requires auth NULL.\n");
+                return SAB_INVALID_PARAMETER;
+            }
+            break;
+#endif
+        default:
+            LOG_CRIT("SABuilder: Invalid crypto mode.\n");
+            return SAB_INVALID_PARAMETER;
+        }
+    }
+    else if (SAParams_p->CryptoAlgo == SAB_CRYPTO_KASUMI ||
+             SAParams_p->CryptoAlgo == SAB_CRYPTO_SNOW ||
+             SAParams_p->CryptoAlgo == SAB_CRYPTO_ZUC)
+    {
+        if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_F8 ||
+            SAParams_p->CryptoMode == SAB_CRYPTO_MODE_UEA2 ||
+            SAParams_p->CryptoMode == SAB_CRYPTO_MODE_EEA3)
+
+        {
+            SAState_p->CW1 |= SAB_CW1_CRYPTO_MODE_F8_UEA;
+        }
+        else if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_BASIC ||
+                 SAParams_p->CryptoMode == SAB_CRYPTO_MODE_ECB)
+        {
+            // Do nothing.
+        }
+        else
+        {
+            LOG_CRIT("SABuilder: Invalid crypto mode for wireless .\n");
+            return SAB_INVALID_PARAMETER;
+        }
+    }
+
+#ifdef SAB_ENABLE_CRYPTO_CHACHAPOLY
+    else if (SAParams_p->CryptoAlgo == SAB_CRYPTO_CHACHA20)
+    {
+        SAState_p->IVWords = 4;
+        if (SAParams_p->AuthAlgo == SAB_AUTH_POLY1305 ||
+            SAParams_p->AuthAlgo == SAB_AUTH_KEYED_HASH_POLY1305)
+        {
+            SAState_p->CW1 |= SAB_CW1_CRYPTO_MODE_CHACHA_CTR32 |
+                SAB_CW1_CRYPTO_AEAD;
+        }
+        else if (SAParams_p->AuthAlgo == SAB_AUTH_NULL)
+        {
+            if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CHACHA_CTR64)
+            {
+                SAState_p->CW1 |= SAB_CW1_CRYPTO_MODE_CHACHA_CTR64;
+            }
+            else
+            {
+                SAState_p->CW1 |= SAB_CW1_CRYPTO_MODE_CHACHA_CTR32;
+            }
+        }
+        else
+        {
+            LOG_CRIT("SABuilder: Invalid authentication mode for Chacha20 .\n");
+            return SAB_INVALID_PARAMETER;
+        }
+    }
+#endif
+
+    /* The following crypto modes can only be used with AES */
+    if ( (SAParams_p->CryptoMode==SAB_CRYPTO_MODE_CCM ||
+          SAParams_p->CryptoMode==SAB_CRYPTO_MODE_GCM ||
+          SAParams_p->CryptoMode==SAB_CRYPTO_MODE_GMAC ||
+          SAParams_p->CryptoMode==SAB_CRYPTO_MODE_XTS ||
+          SAParams_p->CryptoMode==SAB_CRYPTO_MODE_XTS_STATEFUL) &&
+         SAParams_p->CryptoAlgo != SAB_CRYPTO_AES)
+    {
+        LOG_CRIT("SABuilder: crypto mode requires AES.\n");
+        return SAB_INVALID_PARAMETER;
+    }
+    /* The following crypto modes can only be used with AES or SM4 */
+    if ( (SAParams_p->CryptoMode==SAB_CRYPTO_MODE_CTR ||
+          SAParams_p->CryptoMode==SAB_CRYPTO_MODE_ICM) &&
+         SAParams_p->CryptoAlgo != SAB_CRYPTO_AES &&
+         SAParams_p->CryptoAlgo != SAB_CRYPTO_SM4 &&
+         SAParams_p->CryptoAlgo != SAB_CRYPTO_BC0)
+    {
+        LOG_CRIT("SABuilder: crypto mode requires AES or SM4.\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    return SAB_STATUS_OK;
+}
+
+
+/*----------------------------------------------------------------------------
+ * SABuilder_SetAuthSizeAndMode
+ *
+ * Determine the size of the authentication keys and set the required mode
+ * bits in the control words.
+ *
+ * SAParams_p (input)
+ *   The SA parameters structure from which the SA is derived.
+ *
+ * SAState_p (input, output)
+ *   Variables containing information about the SA being generated.
+ *
+ * Auth1Words_p (output)
+ *   The number of 32-bit words of the first authentication key.
+ *
+ * Auth2Words_p (output)
+ *   The number of 32-bit words of the second authentication key.
+ *
+ * Return:
+ * SAB_STATUS_OK on success
+ * SAB_INVALID_PARAMETER when SAParams_p is invalid, or if any of
+ *    the buffer arguments  is a null pointer while the corresponding buffer
+ *    would be required for the operation.
+ * SAB_UNSUPPORTED_FEATURE when SAParams_p describes an operations that
+ *    is not supported on the hardware for which this SA builder
+ *    is configured.
+ */
+static SABuilder_Status_t
+SABuilder_SetAuthSizeAndMode(
+        SABuilder_Params_t *const SAParams_p,
+        SABuilder_State_t * const SAState_p,
+        uint32_t * const Auth1Words_p,
+        uint32_t * const Auth2Words_p)
+{
+    unsigned int Auth1Words = 0;
+    unsigned int Auth2Words = 0;
+
+    switch (SAParams_p->AuthAlgo)
+    {
+    case SAB_AUTH_NULL:
+        break;
+#ifdef SAB_ENABLE_AUTH_MD5
+    case SAB_AUTH_HASH_MD5:
+        SAState_p->CW0 |= SAB_CW0_AUTH_HASH_MD5;
+        if ((SAParams_p->flags & (SAB_FLAG_HASH_LOAD|SAB_FLAG_HASH_SAVE|
+                                  SAB_FLAG_HASH_INTERMEDIATE)) != 0)
+        {
+            SAState_p->CW0 |= SAB_CW0_HASH_LOAD_DIGEST;
+            Auth1Words = 4;
+        }
+        break;
+#endif
+#ifdef SAB_ENABLE_AUTH_SHA1
+    case SAB_AUTH_HASH_SHA1:
+        SAState_p->CW0 |= SAB_CW0_AUTH_HASH_SHA1;
+        if ((SAParams_p->flags & (SAB_FLAG_HASH_LOAD|SAB_FLAG_HASH_SAVE|
+                                  SAB_FLAG_HASH_INTERMEDIATE)) != 0)
+        {
+            SAState_p->CW0 |= SAB_CW0_HASH_LOAD_DIGEST;
+            Auth1Words = 5;
+        }
+        break;
+#endif
+#ifdef SAB_ENABLE_AUTH_SHA2_256
+    case SAB_AUTH_HASH_SHA2_224:
+        SAState_p->CW0 |= SAB_CW0_AUTH_HASH_SHA2_224;
+        if ((SAParams_p->flags & (SAB_FLAG_HASH_LOAD|SAB_FLAG_HASH_SAVE|
+                                  SAB_FLAG_HASH_INTERMEDIATE)) != 0)
+        {
+            SAState_p->CW0 |= SAB_CW0_HASH_LOAD_DIGEST;
+            Auth1Words = 8;
+        }
+        break;
+    case SAB_AUTH_HASH_SHA2_256:
+        SAState_p->CW0 |= SAB_CW0_AUTH_HASH_SHA2_256;
+        if ((SAParams_p->flags & (SAB_FLAG_HASH_LOAD|SAB_FLAG_HASH_SAVE|
+                                  SAB_FLAG_HASH_INTERMEDIATE)) != 0)
+        {
+            SAState_p->CW0 |= SAB_CW0_HASH_LOAD_DIGEST;
+            Auth1Words = 8;
+        }
+        break;
+#endif
+#ifdef SAB_ENABLE_AUTH_SHA2_512
+    case SAB_AUTH_HASH_SHA2_384:
+        SAState_p->CW0 |= SAB_CW0_AUTH_HASH_SHA2_384;
+        if ((SAParams_p->flags & (SAB_FLAG_HASH_LOAD|SAB_FLAG_HASH_SAVE|
+                                  SAB_FLAG_HASH_INTERMEDIATE)) != 0)
+        {
+            SAState_p->CW0 |= SAB_CW0_HASH_LOAD_DIGEST;
+            Auth1Words = 16;
+        }
+        break;
+    case SAB_AUTH_HASH_SHA2_512:
+        SAState_p->CW0 |= SAB_CW0_AUTH_HASH_SHA2_512;
+        if ((SAParams_p->flags & (SAB_FLAG_HASH_LOAD|SAB_FLAG_HASH_SAVE|
+                                  SAB_FLAG_HASH_INTERMEDIATE)) != 0)
+        {
+            SAState_p->CW0 |= SAB_CW0_HASH_LOAD_DIGEST;
+            Auth1Words = 16;
+        }
+        break;
+#endif
+#ifdef SAB_ENABLE_AUTH_SHA3
+    case SAB_AUTH_HASH_SHA3_224:
+        SAState_p->CW0 |= SAB_CW0_AUTH_HASH_SHA3_224;
+        if ((SAParams_p->flags & SAB_FLAG_HASH_SAVE) != 0)
+        {
+            Auth1Words = 36;
+        }
+        break;
+    case SAB_AUTH_HASH_SHA3_256:
+        SAState_p->CW0 |= SAB_CW0_AUTH_HASH_SHA3_256;
+        if ((SAParams_p->flags & SAB_FLAG_HASH_SAVE) != 0)
+        {
+            Auth1Words = 34;
+        }
+        break;
+    case SAB_AUTH_HASH_SHA3_384:
+        SAState_p->CW0 |= SAB_CW0_AUTH_HASH_SHA3_384;
+        if ((SAParams_p->flags & SAB_FLAG_HASH_SAVE) != 0)
+        {
+            Auth1Words = 26;
+        }
+        break;
+    case SAB_AUTH_HASH_SHA3_512:
+        SAState_p->CW0 |= SAB_CW0_AUTH_HASH_SHA3_512;
+        if ((SAParams_p->flags & SAB_FLAG_HASH_SAVE) != 0)
+        {
+            Auth1Words = 18;
+        }
+        break;
+#endif
+#ifdef SAB_ENABLE_AUTH_SM3
+    case SAB_AUTH_HASH_SM3:
+        SAState_p->CW0 |= SAB_CW0_AUTH_HASH_SM3;
+        if ((SAParams_p->flags & (SAB_FLAG_HASH_LOAD|SAB_FLAG_HASH_SAVE|
+                                  SAB_FLAG_HASH_INTERMEDIATE)) != 0)
+        {
+            SAState_p->CW0 |= SAB_CW0_HASH_LOAD_DIGEST;
+            Auth1Words = 8;
+        }
+        break;
+#endif
+#ifdef SAB_ENABLE_AUTH_MD5
+    case SAB_AUTH_SSLMAC_MD5:
+    case SAB_AUTH_HMAC_MD5:
+        SAState_p->CW0 |= SAB_CW0_AUTH_HMAC_MD5;
+        Auth1Words = 4;
+        Auth2Words = 4;
+        break;
+#endif
+#ifdef SAB_ENABLE_AUTH_SHA1
+    case SAB_AUTH_SSLMAC_SHA1:
+        SAState_p->CW0 |= SAB_CW0_AUTH_SSLMAC_SHA1;
+        Auth1Words = 5;
+        break;
+    case SAB_AUTH_HMAC_SHA1:
+        SAState_p->CW0 |= SAB_CW0_AUTH_HMAC_SHA1;
+        Auth1Words = 5;
+        Auth2Words = 5;
+        break;
+#endif
+#ifdef SAB_ENABLE_AUTH_SHA2_256
+    case SAB_AUTH_HMAC_SHA2_224:
+        SAState_p->CW0 |= SAB_CW0_AUTH_HMAC_SHA2_224;
+        Auth1Words = 8;
+        Auth2Words = 8;
+        break;
+    case SAB_AUTH_HMAC_SHA2_256:
+        SAState_p->CW0 |= SAB_CW0_AUTH_HMAC_SHA2_256;
+        Auth1Words = 8;
+        Auth2Words = 8;
+        break;
+#endif
+#ifdef SAB_ENABLE_AUTH_SHA2_512
+    case SAB_AUTH_HMAC_SHA2_384:
+        SAState_p->CW0 |= SAB_CW0_AUTH_HMAC_SHA2_384;
+        Auth1Words = 16;
+        Auth2Words = 16;
+        break;
+    case SAB_AUTH_HMAC_SHA2_512:
+        SAState_p->CW0 |= SAB_CW0_AUTH_HMAC_SHA2_512;
+        Auth1Words = 16;
+        Auth2Words = 16;
+        break;
+#endif
+#ifdef SAB_ENABLE_AUTH_SHA3
+    case SAB_AUTH_KEYED_HASH_SHA3_224:
+        SAState_p->CW0 |= SAB_CW0_AUTH_KEYED_HASH_SHA3_224;
+        SAState_p->CW0 |= SAB_CW0_HASH_LOAD_DIGEST;
+        Auth1Words = 36;
+        break;
+    case SAB_AUTH_KEYED_HASH_SHA3_256:
+        SAState_p->CW0 |= SAB_CW0_AUTH_KEYED_HASH_SHA3_256;
+        SAState_p->CW0 |= SAB_CW0_HASH_LOAD_DIGEST;
+        Auth1Words = 34;
+        break;
+    case SAB_AUTH_KEYED_HASH_SHA3_384:
+        SAState_p->CW0 |= SAB_CW0_AUTH_KEYED_HASH_SHA3_384;
+        SAState_p->CW0 |= SAB_CW0_HASH_LOAD_DIGEST;
+        Auth1Words = 26;
+        break;
+    case SAB_AUTH_KEYED_HASH_SHA3_512:
+        SAState_p->CW0 |= SAB_CW0_AUTH_KEYED_HASH_SHA3_512;
+        SAState_p->CW0 |= SAB_CW0_HASH_LOAD_DIGEST;
+        Auth1Words = 18;
+        break;
+    case SAB_AUTH_HMAC_SHA3_224:
+        SAState_p->CW0 |= SAB_CW0_AUTH_HMAC_SHA3_224;
+        Auth1Words = 36;
+        break;
+    case SAB_AUTH_HMAC_SHA3_256:
+        SAState_p->CW0 |= SAB_CW0_AUTH_HMAC_SHA3_256;
+        Auth1Words = 34;
+        break;
+    case SAB_AUTH_HMAC_SHA3_384:
+        SAState_p->CW0 |= SAB_CW0_AUTH_HMAC_SHA3_384;
+        Auth1Words = 26;
+        break;
+    case SAB_AUTH_HMAC_SHA3_512:
+        SAState_p->CW0 |= SAB_CW0_AUTH_HMAC_SHA3_512;
+        Auth1Words = 18;
+        break;
+#endif
+#ifdef SAB_ENABLE_AUTH_SM3
+    case SAB_AUTH_HMAC_SM3:
+        SAState_p->CW0 |= SAB_CW0_AUTH_HMAC_SM3;
+        Auth1Words = 8;
+        Auth2Words = 8;
+        break;
+#endif
+    case SAB_AUTH_AES_XCBC_MAC:
+    case SAB_AUTH_AES_CMAC_128:
+        SAState_p->CW0 |= SAB_CW0_AUTH_CMAC_128;
+        Auth1Words = 4;
+        Auth2Words = 4;
+        break;
+    case SAB_AUTH_AES_CMAC_192:
+        SAState_p->CW0 |= SAB_CW0_AUTH_CMAC_192;
+        Auth1Words = 6;
+        Auth2Words = 4;
+        break;
+    case SAB_AUTH_AES_CMAC_256:
+        SAState_p->CW0 |= SAB_CW0_AUTH_CMAC_256;
+        Auth1Words = 8;
+        Auth2Words = 4;
+        break;
+    case SAB_AUTH_AES_CCM:
+        if (SAParams_p->CryptoMode != SAB_CRYPTO_MODE_CCM)
+        {
+            LOG_CRIT("SABuilder: auth CCM requires crypto CCM.\n");
+            return SAB_INVALID_PARAMETER;
+        }
+        switch (SAParams_p->KeyByteCount)
+        {
+        case 16:
+            Auth1Words = 4;
+            SAState_p->CW0 |= SAB_CW0_AUTH_CMAC_128;
+            break;
+        case 24:
+            Auth1Words = 6;
+            SAState_p->CW0 |= SAB_CW0_AUTH_CMAC_192;
+            break;
+        case 32:
+            Auth1Words = 8;
+            SAState_p->CW0 |= SAB_CW0_AUTH_CMAC_256;
+            break;
+        }
+        Auth2Words = 4;
+        SAState_p->CW1 |= SAB_CW1_ENCRYPT_HASHRES;
+        break;
+#ifdef SAB_ENABLE_CRYPTO_GCM
+    case SAB_AUTH_AES_GCM:
+        if (SAParams_p->CryptoMode != SAB_CRYPTO_MODE_GCM)
+        {
+            LOG_CRIT("SABuilder: auth GCM requires crypto GCM.\n");
+            return SAB_INVALID_PARAMETER;
+        }
+        SAState_p->CW0 |= SAB_CW0_AUTH_GHASH;
+        Auth1Words = 4;
+        SAState_p->CW1 |= SAB_CW1_ENCRYPT_HASHRES;
+        break;
+    case SAB_AUTH_AES_GMAC:
+        if (SAParams_p->CryptoMode != SAB_CRYPTO_MODE_GMAC)
+        {
+            LOG_CRIT("SABuilder: auth GMAC requires crypto GMAC.\n");
+            return SAB_INVALID_PARAMETER;
+        }
+        SAState_p->CW0 |= SAB_CW0_AUTH_GHASH;
+        Auth1Words = 4;
+        SAState_p->CW1 |= SAB_CW1_ENCRYPT_HASHRES;
+        break;
+#endif
+#ifdef SAB_ENABLE_CRYPTO_KASUMI
+    case SAB_AUTH_KASUMI_F9:
+        if (SAParams_p->CryptoAlgo != SAB_CRYPTO_NULL)
+        {
+            LOG_CRIT("SABuilder: auth KASUMI requires crypto NULL.\n");
+            return SAB_INVALID_PARAMETER;
+        }
+        Auth1Words = 4;
+        SAState_p->CW0 |= SAB_CW0_AUTH_KASUMI_F9;
+        break;
+#endif
+#ifdef SAB_ENABLE_CRYPTO_SNOW
+    case SAB_AUTH_SNOW_UIA2:
+        if (SAParams_p->CryptoAlgo != SAB_CRYPTO_NULL)
+        {
+            LOG_CRIT("SABuilder: auth SNOW requires crypto NULL.\n");
+            return SAB_INVALID_PARAMETER;
+        }
+        Auth1Words = 4;
+        SAState_p->CW0 |= SAB_CW0_AUTH_SNOW_UIA2;
+        break;
+#endif
+#ifdef SAB_ENABLE_CRYPTO_ZUC
+    case SAB_AUTH_ZUC_EIA3:
+        if (SAParams_p->CryptoAlgo != SAB_CRYPTO_NULL)
+        {
+            LOG_CRIT("SABuilder: auth ZUC requires crypto NULL.\n");
+            return SAB_INVALID_PARAMETER;
+        }
+        Auth1Words = 4;
+        SAState_p->CW0 |= SAB_CW0_AUTH_ZUC_EIA3;
+        break;
+#endif
+#ifdef SAB_ENABLE_CRYPTO_CHACHAPOLY
+    case SAB_AUTH_KEYED_HASH_POLY1305:
+        if (SAParams_p->CryptoAlgo != SAB_CRYPTO_NULL)
+        {
+            LOG_CRIT("SABuilder: auth keyed Poly1305 requires crypto NULL.\n");
+            return SAB_INVALID_PARAMETER;
+        }
+        if ((SAParams_p->flags & (SAB_FLAG_HASH_LOAD|SAB_FLAG_HASH_SAVE|
+                                  SAB_FLAG_HASH_INTERMEDIATE)) != 0)
+        {
+            SAState_p->CW0 |= SAB_CW0_HASH_LOAD_DIGEST;
+            Auth1Words = 4;
+            Auth2Words = 8;
+        }
+        else
+        {
+            Auth1Words = 8;
+        }
+        SAState_p->CW0 |= SAB_CW0_AUTH_KEYED_HASH_POLY1305;
+        break;
+    case SAB_AUTH_POLY1305:
+        if (SAParams_p->CryptoAlgo != SAB_CRYPTO_CHACHA20)
+        {
+            LOG_CRIT("SABuilder: auth Poly1305 requires crypto Chacha20.\n");
+            return SAB_INVALID_PARAMETER;
+        }
+        SAState_p->CW0 |= SAB_CW0_AUTH_POLY1305;
+        SAState_p->CW1 |= SAB_CW1_IV_CTR|SAB_CW1_CRYPTO_MODE_CHACHA_POLY_OTK;
+        SAState_p->CW1 |= SAB_CW1_ENCRYPT_HASHRES;
+        break;
+#endif
+    default:
+        LOG_CRIT("SABuilder: Unsupported authentication algorithm\n");
+        return SAB_UNSUPPORTED_FEATURE;
+    }
+
+    *Auth1Words_p = Auth1Words;
+    *Auth2Words_p = Auth2Words;
+    return SAB_STATUS_OK;
+}
+
+
+/*----------------------------------------------------------------------------
+ * SABuilder_SetAuthKeys
+ *
+ * Fill in authentication keys and associated command word fields in SA.
+ *
+ * SAParams_p (input)
+ *   The SA parameters structure from which the SA is derived.
+ *
+ * SAState_p (input, output)
+ *   Variables containing information about the SA being generated.
+ *
+ * SABuffer_p (input, output).
+ *   The buffer in which the SA is built. If NULL, no SA will be built, but
+ *   state variables in SAState_p will still be updated.
+ *
+ * Return:
+ * SAB_STATUS_OK on success
+ * SAB_INVALID_PARAMETER when SAParams_p is invalid, or if any of
+ *    the buffer arguments  is a null pointer while the corresponding buffer
+ *    would be required for the operation.
+ * SAB_UNSUPPORTED_FEATURE when SAParams_p describes an operations that
+ *    is not supported on the hardware for which this SA builder
+ *    is configured.
+ */
+static SABuilder_Status_t
+SABuilder_SetAuthKeys(
+        SABuilder_Params_t *const SAParams_p,
+        SABuilder_State_t * const SAState_p,
+        uint32_t * const SABuffer_p)
+{
+    unsigned int Auth1Words = 0;
+    unsigned int Auth2Words = 0;
+    SABuilder_Status_t Rc;
+
+    Rc = SABuilder_SetAuthSizeAndMode(SAParams_p,
+                                      SAState_p,
+                                      &Auth1Words,
+                                      &Auth2Words);
+    if (Rc != SAB_STATUS_OK)
+    {
+        return  Rc;
+    }
+
+    /* Now copy the authentication keys, if applicable */
+    if (SAParams_p->AuthAlgo == SAB_AUTH_AES_CCM)
+    {
+        SAParams_p->OffsetDigest0 = SAState_p->CurrentOffset;
+        SABuilderLib_ZeroFill(SABuffer_p, SAState_p->CurrentOffset, 32);
+        /* Fill zero blocks for the XCBC MAC subkeys */
+        SAState_p->CurrentOffset += 8;
+        SABuilderLib_CopyKeyMatSwap(SABuffer_p, SAState_p->CurrentOffset,
+                                    SAParams_p->Key_p,
+                                    SAParams_p->KeyByteCount);
+        SAState_p->CurrentOffset += SAState_p->CipherKeyWords;
+
+        if (SAState_p->CipherKeyWords == 6)
+        {
+            SABuilderLib_ZeroFill(SABuffer_p, SAState_p->CurrentOffset, 8);
+            SAState_p->CurrentOffset += 2; /* Pad key to 256 bits for CCM-192*/
+        }
+    }
+    else if (SAParams_p->AuthAlgo == SAB_AUTH_AES_XCBC_MAC ||
+             SAParams_p->AuthAlgo == SAB_AUTH_AES_CMAC_128 ||
+             SAParams_p->AuthAlgo == SAB_AUTH_AES_CMAC_192 ||
+             SAParams_p->AuthAlgo == SAB_AUTH_AES_CMAC_256)
+    {
+#ifdef SAB_STRICT_ARGS_CHECK
+        if (SAParams_p->AuthKey1_p == NULL ||
+            SAParams_p->AuthKey2_p == NULL ||
+            SAParams_p->AuthKey3_p == NULL)
+        {
+            LOG_CRIT("SABuilder: NULL pointer AuthKey supplied\n");
+            return SAB_INVALID_PARAMETER;
+        }
+#endif
+        SAParams_p->OffsetDigest0 = SAState_p->CurrentOffset;
+        SABuilderLib_CopyKeyMatSwap(SABuffer_p, SAState_p->CurrentOffset,
+                                    SAParams_p->AuthKey2_p,
+                                    4 * sizeof(uint32_t));
+        SABuilderLib_CopyKeyMatSwap(SABuffer_p, SAState_p->CurrentOffset + 4,
+                                    SAParams_p->AuthKey3_p,
+                                    4 * sizeof(uint32_t));
+        SABuilderLib_CopyKeyMatSwap(SABuffer_p, SAState_p->CurrentOffset + 8,
+                                    SAParams_p->AuthKey1_p,
+                                    Auth1Words * sizeof(uint32_t));
+        SAState_p->CurrentOffset += 8 + Auth1Words;
+        if (Auth1Words == 6)
+        {
+            SABuilderLib_ZeroFill(SABuffer_p, SAState_p->CurrentOffset, 8);
+            SAState_p->CurrentOffset += 2; /* Pad key to 256 bits for CMAC-192*/
+        }
+    }
+#ifdef SAB_ENABLE_AUTH_SHA3
+    else if (SAParams_p->AuthAlgo == SAB_AUTH_HASH_SHA3_224 ||
+             SAParams_p->AuthAlgo == SAB_AUTH_HASH_SHA3_256 ||
+             SAParams_p->AuthAlgo == SAB_AUTH_HASH_SHA3_384 ||
+             SAParams_p->AuthAlgo == SAB_AUTH_HASH_SHA3_512 ||
+             SAParams_p->AuthAlgo == SAB_AUTH_KEYED_HASH_SHA3_224 ||
+             SAParams_p->AuthAlgo == SAB_AUTH_KEYED_HASH_SHA3_256 ||
+             SAParams_p->AuthAlgo == SAB_AUTH_KEYED_HASH_SHA3_384 ||
+             SAParams_p->AuthAlgo == SAB_AUTH_KEYED_HASH_SHA3_512 ||
+             SAParams_p->AuthAlgo == SAB_AUTH_HMAC_SHA3_224 ||
+             SAParams_p->AuthAlgo == SAB_AUTH_HMAC_SHA3_256 ||
+             SAParams_p->AuthAlgo == SAB_AUTH_HMAC_SHA3_384 ||
+             SAParams_p->AuthAlgo == SAB_AUTH_HMAC_SHA3_512)
+    {
+#ifdef SAB_STRICT_ARGS_CHECK
+        if (Auth1Words > 0)
+        {
+            if (SAParams_p->AuthKey1_p == NULL &&
+                SAParams_p->AuthKeyByteCount > 0)
+            {
+                LOG_CRIT("SABuilder: NULL pointer AuthKey supplied\n");
+                return SAB_INVALID_PARAMETER;
+            }
+            if (SAParams_p->AuthKeyByteCount > Auth1Words * sizeof(uint32_t))
+            {
+                LOG_CRIT("SABuilder: Authentication key too long\n");
+                return SAB_INVALID_PARAMETER;
+            }
+#endif
+            SAParams_p->OffsetDigest0 = SAState_p->CurrentOffset;
+            SABuilderLib_ZeroFill(SABuffer_p, SAState_p->CurrentOffset,
+                                  Auth1Words * sizeof(uint32_t));
+
+            SABuilderLib_CopyKeyMat(SABuffer_p, SAState_p->CurrentOffset,
+                                    SAParams_p->AuthKey1_p,
+                                    SAParams_p->AuthKeyByteCount);
+
+            SAState_p->CurrentOffset += Auth1Words;
+
+            if (SAParams_p->AuthAlgo == SAB_AUTH_KEYED_HASH_SHA3_224 ||
+                SAParams_p->AuthAlgo == SAB_AUTH_KEYED_HASH_SHA3_256 ||
+                SAParams_p->AuthAlgo == SAB_AUTH_KEYED_HASH_SHA3_384 ||
+                SAParams_p->AuthAlgo == SAB_AUTH_KEYED_HASH_SHA3_512)
+            {
+                if (SAParams_p->AuthKeyByteCount <
+                    Auth1Words * sizeof(uint32_t))
+                {
+                    // Put the key length in last byte of key if it is smaller
+                    // than the maximum.
+                    SAState_p->CW1 |= SAB_CW1_DIGEST_CNT;
+                    if (SABuffer_p != NULL)
+                    {
+                        SABuffer_p[SAState_p->CurrentOffset - 1] |=
+                            (SAParams_p->AuthKeyByteCount << 24);
+                    }
+                }
+            }
+        }
+    }
+#endif
+    else if(Auth1Words > 0 && Auth2Words > 0 &&
+            SAParams_p->AuthKey1_p == NULL && SAParams_p->AuthKey2_p == NULL)
+    {
+        /* HMAC precomputes not given, allow later computation of
+           precomputes. */
+        SAParams_p->OffsetDigest0 = SAState_p->CurrentOffset;
+        SAParams_p->OffsetDigest1 = SAState_p->CurrentOffset + Auth1Words;
+        SABuilderLib_ZeroFill(SABuffer_p, SAState_p->CurrentOffset,
+                              (Auth1Words + Auth2Words) * sizeof(uint32_t));
+        SAState_p->CurrentOffset += Auth1Words + Auth2Words;
+    }
+    else
+    {
+        if (Auth1Words > 0)
+        {
+#ifdef SAB_STRICT_ARGS_CHECK
+            if (SAParams_p->AuthKey1_p == NULL)
+            {
+                LOG_CRIT("SABuilder: NULL pointer AuthKey supplied\n");
+                return SAB_INVALID_PARAMETER;
+            }
+#endif
+            SAParams_p->OffsetDigest0 = SAState_p->CurrentOffset;
+            SABuilderLib_CopyKeyMat(SABuffer_p, SAState_p->CurrentOffset,
+                                    SAParams_p->AuthKey1_p,
+                                    Auth1Words * sizeof(uint32_t));
+            SAState_p->CurrentOffset += Auth1Words;
+
+            if (SAParams_p->AuthAlgo == SAB_AUTH_SSLMAC_SHA1)
+            { /* both inner and outer digest fields must be set, even though
+                 only one is used. */
+                SABuilderLib_ZeroFill(SABuffer_p, SAState_p->CurrentOffset,
+                                        Auth1Words * sizeof(uint32_t));
+                SAState_p->CurrentOffset += Auth1Words;
+            }
+        }
+        if (Auth2Words > 0)
+        {
+#ifdef SAB_STRICT_ARGS_CHECK
+            if (SAParams_p->AuthKey2_p == NULL)
+            {
+                LOG_CRIT("SABuilder: NULL pointer AuthKey supplied\n");
+                return SAB_INVALID_PARAMETER;
+            }
+#endif
+            SAParams_p->OffsetDigest1 = SAState_p->CurrentOffset;
+            SABuilderLib_CopyKeyMat(SABuffer_p, SAState_p->CurrentOffset,
+                                    SAParams_p->AuthKey2_p,
+                                    Auth2Words * sizeof(uint32_t));
+            SAState_p->CurrentOffset += Auth2Words;
+        }
+    }
+
+    return SAB_STATUS_OK;
+}
+
+
+
+/*----------------------------------------------------------------------------
+ * SABuilder_GetSizes
+ *
+ * Compute the required sizes in 32-bit words of any of up to three memory
+ * areas used by the SA.
+ *
+ * SAParams_p (input)
+ *   Pointer to the SA parameters structure.
+ *
+ * SAWord32Count_p (output)
+ *   The size of the normal SA buffer.
+ *
+ * SAStateWord32Count_p (output)
+ *   The size of any SA state record.
+ *
+ * ARC4StateWord32Count_p (output) T
+ *   The size of any ARCFOUR state buffer (output).
+ *
+ * When the SA state record or ARCFOUR state buffer are not required by
+ * the packet engine for this transform, the corresponding size outputs
+ * are returned as zero. The Security-IP-96 never requires these buffers
+ *
+ * If any of the output parameters is a null pointer,
+ * the corresponding size will not be returned.
+ *
+ * The SAParams_p structure must be fully filled in: it must have the
+ * same contents as it would have when SABuilder_BuildSA is called.
+ * This function calls the same routines as SABuilder_BuildSA, but with
+ * null pointers instead of the SA pointer, so no actual SA will be built.
+ * These functions are only called to obtain the length of the SA.
+ *
+ * Return:
+ * SAB_STATUS_OK on success
+ * SAB_INVALID_PARAMETER when the record referenced by SAParams_p is invalid,
+ */
+SABuilder_Status_t
+SABuilder_GetSizes(
+        SABuilder_Params_t *const SAParams_p,
+        unsigned int *const SAWord32Count_p,
+        unsigned int *const SAStateWord32Count_p,
+        unsigned int *const ARC4StateWord32Count_p)
+{
+    SABuilder_State_t SAState;
+    int rc;
+
+#ifdef SAB_STRICT_ARGS_CHECK
+    if (SAParams_p == NULL)
+    {
+        LOG_CRIT("SABuilder_GetSizes: NULL pointer SAParams_p supplied\n");
+        return SAB_INVALID_PARAMETER;
+    }
+#endif
+
+    SAState.CurrentOffset = 2; /* Count Control words 0 and 1 */
+    SAState.CW0 = 0;
+    SAState.CW1 = 0;
+    SAState.CipherKeyWords = 0;
+    SAState.IVWords = 0;
+    SAState.ARC4State = false;
+    SAState.fLarge = false;
+    SAState.fLargeMask = false;
+
+    rc = SABuilder_SetCipherKeys(SAParams_p, &SAState, NULL);
+    if (rc != SAB_STATUS_OK)
+        return rc;
+
+    rc = SABuilder_SetAuthKeys(SAParams_p, &SAState, NULL);
+    if (rc != SAB_STATUS_OK)
+        return rc;
+
+    switch ( SAParams_p->protocol)
+    {
+#ifdef SAB_ENABLE_PROTO_BASIC
+    case SAB_PROTO_BASIC:
+    {
+        rc = SABuilder_SetBasicParams(SAParams_p, &SAState, NULL);
+    }
+    break;
+#endif
+#ifdef SAB_ENABLE_PROTO_IPSEC
+    case SAB_PROTO_IPSEC:
+    {
+        rc = SABuilder_SetIPsecParams(SAParams_p, &SAState, NULL);
+    }
+    break;
+#endif
+#ifdef SAB_ENABLE_PROTO_SSLTLS
+    case SAB_PROTO_SSLTLS:
+    {
+        rc = SABuilder_SetSSLTLSParams(SAParams_p, &SAState, NULL);
+    }
+    break;
+#endif
+#ifdef SAB_ENABLE_PROTO_SRTP
+    case SAB_PROTO_SRTP:
+    {
+        rc = SABuilder_SetSRTPParams(SAParams_p, &SAState, NULL);
+    }
+    break;
+#endif
+#ifdef SAB_ENABLE_PROTO_MACSEC
+    case SAB_PROTO_MACSEC:
+    {
+        rc = SABuilder_SetMACsecParams(SAParams_p, &SAState, NULL);
+    }
+    break;
+#endif
+    default:
+        LOG_CRIT("SABuilder_GetSizes: unsupported protocol\n");
+        return SAB_INVALID_PARAMETER;
+    }
+    if (rc != SAB_STATUS_OK)
+        return rc;
+
+    if (SAState.ARC4State)
+    {
+        SAState.CurrentOffset += 2; /* Count IJ pointer and ARC4 State */
+    }
+
+    if (SAState.CurrentOffset == 2)
+    {
+        SAState.CurrentOffset += 1;
+        /* Make sure to have at least one non-context word */
+    }
+
+#ifdef SAB_ENABLE_FIXED_RECORD_SIZE
+#ifdef SAB_ENABLE_TWO_FIXED_RECORD_SIZES
+#ifdef SAB_ENABLE_IPSEC_EXTENDED
+    /* It is possible that a record will have to be
+       large because of options used by firmware, so determine if the record
+       needs to be large. */
+    if (SAParams_p->protocol == SAB_PROTO_IPSEC)
+    {
+        SABuilder_Status_t res;
+        res = SABuilder_SetExtendedIPsecParams(SAParams_p,
+                                               &SAState,
+                                               NULL);
+        if (res != SAB_STATUS_OK)
+            return res;
+    }
+#endif
+#ifdef SAB_ENABLE_DTLS_EXTENDED
+    if (SAParams_p->protocol == SAB_PROTO_SSLTLS)
+    {
+        SABuilder_Status_t res;
+        res = SABuilder_SetExtendedDTLSParams(SAParams_p, &SAState, NULL);
+        if (res != SAB_STATUS_OK)
+            return res;
+    }
+#endif
+#ifdef SAB_ENABLE_MACSEC_EXTENDED
+    if (SAParams_p->protocol == SAB_PROTO_MACSEC)
+    {
+        SABuilder_Status_t res;
+        res = SABuilder_SetExtendedMACsecParams(SAParams_p,
+                                                &SAState,
+                                                NULL);
+        if (res != SAB_STATUS_OK)
+            return res;
+    }
+#endif
+#ifdef SAB_ENABLE_BASIC_EXTENDED
+    if (SAParams_p->protocol == SAB_PROTO_BASIC)
+    {
+        SABuilder_Status_t res;
+        res = SABuilder_SetExtendedBasicParams(SAParams_p,
+                                               &SAState,
+                                               NULL);
+        if (res != SAB_STATUS_OK)
+            return res;
+    }
+#endif
+    if (SAParams_p->OffsetSeqNum <= SAB_SEQNUM_LO_FIX_OFFSET &&
+        !SAState.fLarge)
+    {
+        SAState.CurrentOffset = SAB_RECORD_WORD_COUNT;
+    }
+    else if (SAState.CurrentOffset <= SAB_RECORD_WORD_COUNT + LargeTransformOffset)
+    {
+        SAState.CurrentOffset = SAB_RECORD_WORD_COUNT + LargeTransformOffset;
+    }
+    else
+    {
+        LOG_CRIT("SABuilder_GetSizes: SA filled beyond record size.\n");
+        return SAB_INVALID_PARAMETER;
+    }
+#else
+    if (SAState.CurrentOffset > SAB_RECORD_WORD_COUNT)
+    {
+        LOG_CRIT("SABuilder_GetSizes: SA filled beyond record size.\n");
+        return SAB_INVALID_PARAMETER;
+    }
+    SAState.CurrentOffset = SAB_RECORD_WORD_COUNT;
+    /* Make the SA record a fixed size for engines that have
+       record caches */
+#endif
+#endif
+
+    if (SAStateWord32Count_p != NULL)
+        *SAStateWord32Count_p = 0;
+
+#ifdef SAB_ARC4_STATE_IN_SA
+    if (ARC4StateWord32Count_p != NULL)
+        *ARC4StateWord32Count_p = 0;
+    if (SAState.ARC4State)
+    {
+        if (SAParams_p->OffsetARC4StateRecord > 0)
+        {
+            if (SAParams_p->OffsetARC4StateRecord  < SAState.CurrentOffset)
+            {
+                LOG_CRIT("SABuilder_GetSizes: OffsetARC4StateRecord too low\n");
+                return SAB_INVALID_PARAMETER;
+            }
+            SAState.CurrentOffset = SAParams_p->OffsetARC4StateRecord + 64;
+        }
+        else
+        {
+            SAState.CurrentOffset =
+                    SABuilder_AlignForARc4State(SAState.CurrentOffset);
+            SAState.CurrentOffset += 64;
+        }
+    }
+#else
+    if (ARC4StateWord32Count_p != NULL)
+    {
+        if (SAState.ARC4State)
+        {
+            *ARC4StateWord32Count_p = 64;
+        }
+        else
+        {
+            *ARC4StateWord32Count_p = 0;
+        }
+    }
+#endif
+#ifdef SAB_AUTO_TOKEN_CONTEXT_GENERATION
+    {
+        TokenBuilder_Status_t rc;
+        unsigned int ContextSize;
+        rc = TokenBuilder_GetContextSize(SAParams_p, &ContextSize);
+        if (rc != TKB_STATUS_OK)
+        {
+            return SAB_ERROR;
+        }
+        SAState.CurrentOffset += ContextSize;
+    }
+#endif
+    if (SAWord32Count_p != NULL)
+        *SAWord32Count_p = SAState.CurrentOffset;
+
+    return SAB_STATUS_OK;
+}
+
+/*----------------------------------------------------------------------------
+ * SABuilder_BuildSA
+ *
+ * Construct the SA record for the operation described in SAParams_p in
+ * up to three memory buffers.
+ *
+ * SAParams_p (input)
+ *    Pointer to the SA parameters structure.
+ *
+ * SABuffer_p (output)
+ *    Pointer to the the normal SA buffer.
+ *
+ * SAStateBuffer_p (output)
+ *    Pointer to the SA state record buffer.
+ *
+ * ARC4StateBuffer_p (output)
+ *    Pointer to the ARCFOUR state buffer.
+ *
+ * Each of the Buffer arguments must point to a word-aligned
+ * memory buffer whose size in words is at least equal to the
+ * corresponding size parameter returned by SABuilder_GetSizes().
+ *
+ * If any of the three buffers is not required for the SA (the
+ * corresponding size in SABuilder_GetSizes() is 0), the corresponding
+ * Buffer arguments to this function may be a null pointer.
+ * The Security-IP-96 never requires these buffers.
+ *
+ * Return:
+ * SAB_STATUS_OK on success
+ * SAB_INVALID_PARAMETER when SAParams_p is invalid, or if any of
+ *    the buffer arguments  is a null pointer while the corresponding buffer
+ *    would be required for the operation.
+ * SAB_UNSUPPORTED_FEATURE when SAParams_p describes an operations that
+ *    is not supported on the hardware for which this SA builder
+ *    is configured.
+ */
+SABuilder_Status_t
+SABuilder_BuildSA(
+        SABuilder_Params_t * const SAParams_p,
+        uint32_t *const SABuffer_p,
+        uint32_t *const SAStateBuffer_p,
+        uint32_t *const ARC4StateBuffer_p)
+{
+    SABuilder_State_t SAState;
+    int rc;
+
+    IDENTIFIER_NOT_USED(SAStateBuffer_p);
+    IDENTIFIER_NOT_USED(ARC4StateBuffer_p);
+
+#ifdef SAB_STRICT_ARGS_CHECK
+    if (SAParams_p == NULL || SABuffer_p == NULL)
+    {
+        LOG_CRIT("SABuilder: NULL pointer parameter supplied.\n");
+        return SAB_INVALID_PARAMETER;
+    }
+#endif
+
+    SAState.CurrentOffset = 2; /* Count Control words 0 and 1 */
+    SAState.CW0 = 0;
+    SAState.CW1 = 0;
+    SAState.CipherKeyWords = 0;
+    SAState.IVWords = 0;
+    SAState.ARC4State = false;
+    SAState.fLarge = false;
+    SAState.fLargeMask = false;
+
+    rc = SABuilder_SetCipherKeys(SAParams_p, &SAState, SABuffer_p);
+    if (rc != SAB_STATUS_OK)
+        return rc;
+
+    rc = SABuilder_SetAuthKeys(SAParams_p, &SAState, SABuffer_p);
+    if (rc != SAB_STATUS_OK)
+        return rc;
+
+    switch ( SAParams_p->protocol)
+    {
+#ifdef SAB_ENABLE_PROTO_BASIC
+    case SAB_PROTO_BASIC:
+    {
+        rc = SABuilder_SetBasicParams(SAParams_p, &SAState, SABuffer_p);
+    }
+    break;
+#endif
+#ifdef SAB_ENABLE_PROTO_IPSEC
+    case SAB_PROTO_IPSEC:
+    {
+        rc = SABuilder_SetIPsecParams(SAParams_p, &SAState, SABuffer_p);
+    }
+    break;
+#endif
+#ifdef SAB_ENABLE_PROTO_SSLTLS
+    case SAB_PROTO_SSLTLS:
+    {
+        rc = SABuilder_SetSSLTLSParams(SAParams_p, &SAState, SABuffer_p);
+    }
+    break;
+#endif
+#ifdef SAB_ENABLE_PROTO_SRTP
+    case SAB_PROTO_SRTP:
+    {
+        rc = SABuilder_SetSRTPParams(SAParams_p, &SAState, SABuffer_p);
+    }
+    break;
+#endif
+#ifdef SAB_ENABLE_PROTO_MACSEC
+    case SAB_PROTO_MACSEC:
+    {
+        rc = SABuilder_SetMACsecParams(SAParams_p, &SAState, SABuffer_p);
+    }
+    break;
+#endif
+    default:
+        LOG_CRIT("SABuilder_BuildSA: unsupported protocol\n");
+        return SAB_UNSUPPORTED_FEATURE;
+    }
+    if (rc != SAB_STATUS_OK)
+        return rc;
+
+#ifdef SAB_ENABLE_FIXED_RECORD_SIZE
+#ifdef SAB_ENABLE_TWO_FIXED_RECORD_SIZES
+    if (SAParams_p->OffsetSeqNum > SAB_SEQNUM_LO_FIX_OFFSET)
+        SAState.fLarge = true;
+#endif
+#endif
+
+    if (SAState.ARC4State)
+    {
+        unsigned int ARC4Offset = 0;
+#ifdef SAB_ARC4_STATE_IN_SA
+        if (SAParams_p->OffsetARC4StateRecord > 0)
+        {
+            ARC4Offset = SAParams_p->OffsetARC4StateRecord;
+        }
+        else
+        {
+#ifdef SAB_ENABLE_FIXED_RECORD_SIZE
+#ifdef SAB_ENABLE_TWO_FIXED_RECORD_SIZES
+            if (SAState.fLarge)
+            {
+                ARC4Offset = SAB_RECORD_WORD_COUNT + LargeTransformOffset;
+            }
+            else
+#else
+            {
+                ARC4Offset = SAB_RECORD_WORD_COUNT;
+            }
+#endif
+#else
+            ARC4Offset = SAState.CurrentOffset + 2;
+#endif
+            ARC4Offset = SABuilder_AlignForARc4State(ARC4Offset);
+        }
+#endif
+        SABuffer_p[SAState.CurrentOffset] = ARC4Offset * sizeof(uint32_t);
+        SABuffer_p[SAState.CurrentOffset + 1] = 0;
+
+        if ( (SAParams_p->flags & SAB_FLAG_ARC4_STATE_LOAD) != 0)
+        {
+            /* Load the ARC4 state when building the SA.
+             Nonce_p[0] is the 'i' variable and
+             Nonce_p[1] is the 'j' variable.
+             IV_p points to the 256-byte state array.
+             The SA Builder will not fill in the ARC4 state pointer. */
+            if (SAParams_p->Nonce_p != NULL)
+            {
+                SABuffer_p[SAState.CurrentOffset + 1] =
+                    ((SAParams_p->Nonce_p[0] + 1) & 0xff) |
+                    (SAParams_p->Nonce_p[1]<<8);
+            }
+            if(SAParams_p->IV_p != NULL)
+            {
+#ifdef SAB_ARC4_STATE_IN_SA
+                SABuilderLib_CopyKeyMat(SABuffer_p,
+                                        (SAParams_p->OffsetARC4StateRecord >0 ?
+                                         SAParams_p->OffsetARC4StateRecord :
+                                          ARC4Offset),
+                                        SAParams_p->IV_p,
+                                        256);
+
+#else
+                SABuilderLib_CopyKeyMat(ARC4StateBuffer_p,
+                                        0,
+                                        SAParams_p->IV_p,
+                                        256);
+#endif
+            }
+
+        }
+
+        SAParams_p->OffsetIJPtr = SAState.CurrentOffset + 1;
+        SAParams_p->OffsetARC4State = SAState.CurrentOffset;
+
+        SAState.CurrentOffset += 2; /* Count IJ pointer and ARC4 State */
+    }
+
+    if (SAState.CurrentOffset == 2)
+    {
+        SABuffer_p[SAState.CurrentOffset++] = 0;
+        /* Make sure to have at least one non-context word */
+    }
+
+    if (!SAState.fLargeMask)
+        SAState.CW0 |= (SAState.CurrentOffset - 2) << 8;
+    else
+        SAState.CW0 |= (SAState.CurrentOffset == 66)? 0x0200 : 0x0300;
+
+    SABuffer_p[0] = SAState.CW0;
+    SABuffer_p[1] = SAState.CW1;
+
+    SAParams_p->CW0 = SAState.CW0;
+    SAParams_p->CW1 = SAState.CW1;
+
+#ifdef SAB_ENABLE_IPSEC_EXTENDED
+    if (SAParams_p->protocol == SAB_PROTO_IPSEC)
+    {
+        SABuilder_Status_t res;
+        res = SABuilder_SetExtendedIPsecParams(SAParams_p,
+                                               &SAState,
+                                               SABuffer_p);
+        if (res != SAB_STATUS_OK)
+            return res;
+    }
+#endif
+#ifdef SAB_ENABLE_DTLS_EXTENDED
+    if (SAParams_p->protocol == SAB_PROTO_SSLTLS)
+    {
+        SABuilder_Status_t res;
+        res = SABuilder_SetExtendedDTLSParams(SAParams_p, &SAState, SABuffer_p);
+        if (res != SAB_STATUS_OK)
+            return res;
+    }
+#endif
+#ifdef SAB_ENABLE_MACSEC_EXTENDED
+    if (SAParams_p->protocol == SAB_PROTO_MACSEC)
+    {
+        SABuilder_Status_t res;
+        res = SABuilder_SetExtendedMACsecParams(SAParams_p,
+                                                &SAState,
+                                                SABuffer_p);
+        if (res != SAB_STATUS_OK)
+            return res;
+    }
+#endif
+#ifdef SAB_ENABLE_BASIC_EXTENDED
+    if (SAParams_p->protocol == SAB_PROTO_BASIC)
+    {
+        SABuilder_Status_t res;
+        res = SABuilder_SetExtendedBasicParams(SAParams_p,
+                                               &SAState,
+                                               SABuffer_p);
+        if (res != SAB_STATUS_OK)
+            return res;
+    }
+#endif
+
+#ifdef SAB_ENABLE_FIXED_RECORD_SIZE
+#ifdef SAB_ENABLE_TWO_FIXED_RECORD_SIZES
+    if (SAState.fLarge)
+    {
+        SABuffer_p[0] |= SAB_CW0_SW_IS_LARGE;
+#ifdef SAB_ENABLE_IPSEC_EXTENDED
+        /* Must be set independent of protocol */
+        if ((SAParams_p->flags & SAB_FLAG_REDIRECT) != 0)
+        {
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_FLAGS_WORD_OFFSET +
+                       LargeTransformOffset] |=
+                BIT_11 | ((SAParams_p->RedirectInterface & MASK_4_BITS) << 12);
+        }
+#endif
+        SAState.CurrentOffset = SAB_RECORD_WORD_COUNT + LargeTransformOffset;
+    }
+    else
+    {
+#ifdef SAB_ENABLE_IPSEC_EXTENDED
+        /* Must be set independent of protocol */
+        if ((SAParams_p->flags & SAB_FLAG_REDIRECT) != 0)
+        {
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_FLAGS_WORD_OFFSET] |=
+                BIT_11 | ((SAParams_p->RedirectInterface & MASK_4_BITS) << 12);
+        }
+#endif
+        SAState.CurrentOffset = SAB_RECORD_WORD_COUNT;
+    }
+#endif
+#endif
+
+#ifdef SAB_AUTO_TOKEN_CONTEXT_GENERATION
+    {
+        TokenBuilder_Status_t rc;
+        void *TokenContext_p = (void*)&SABuffer_p[SAState.CurrentOffset];
+        rc = TokenBuilder_BuildContext(SAParams_p, TokenContext_p);
+        if (rc != TKB_STATUS_OK)
+        {
+            return SAB_ERROR;
+        }
+    }
+#endif
+
+
+    return SAB_STATUS_OK;
+}
+
+
+/*----------------------------------------------------------------------------
+ * SABuilder_SetLargeTransformOffset();
+ */
+SABuilder_Status_t
+SABuilder_SetLargeTransformOffset(
+    unsigned int Offset)
+{
+#if defined(SAB_ENABLE_IPSEC_EXTENDED) || defined(SAB_ENABLE_SSLTLS_EXTENDED)
+    LargeTransformOffset = Offset;
+    return SAB_STATUS_OK;
+#else
+    IDENTIFIER_NOT_USED(Offset);
+    return SAB_UNSUPPORTED_FEATURE;
+#endif
+}
+
+/* end of file sa_builder.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_basic.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_basic.c
new file mode 100644
index 0000000..256e341
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_basic.c
@@ -0,0 +1,444 @@
+/* sa_builder_basic.c
+ *
+ * Basic Crypto/hash specific functions (for initialization of
+ * SABuilder_Params_t structures and for building the Basic Crypto/hash
+ * specific part of an SA).
+ */
+
+/*****************************************************************************
+* Copyright (c) 2011-2020 by Rambus, Inc. and/or its subsidiaries.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+#include "sa_builder_basic.h"
+#include "sa_builder_internal.h" /* SABuilder_SetBasicParams */
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+#include "c_sa_builder.h"
+#include "basic_defs.h"
+#include "log.h"
+
+#ifdef SAB_ENABLE_PROTO_BASIC
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+/*----------------------------------------------------------------------------
+ * SABuilder_Init_Basic
+ *
+ * This function initializes the SABuilder_Params_t data structure and
+ * its SABuilder_Params_Basic_t extension with sensible defaults for
+ * basic crypto and hash processing.
+ *
+ * SAParams_p (output)
+ *   Pointer to SA parameter structure to be filled in.
+ *
+ * SAParamsBasic_p (output)
+ *   Pointer to Basic parameter extension to be filled in
+ *
+ * direction (input)
+ *   Must be one of SAB_DIRECTION_INBOUND or SAB_DIRECTION_OUTBOUND.
+ *
+ * Both the crypto and the authentication algorithm are initialized to
+ * NULL. Either the cipher algorithm or the authentication algorithm
+ * or both can be set to one of the supported algorithms for
+ * basic crypto or basic hash or HMAC. If they are both left at NULL. the
+ * SA will be a bypass SA. The crypto mode and IV source
+ * can be specified as well.  Any required keys have to be specified
+ * as well.
+ *
+ * Both the SAParams_p and SAParamsBasic_p input parameters must point
+ * to valid storage where variables of the appropriate type can be
+ * stored. This function initializes the link from SAParams_p to
+ * SAParamsBasic_p.
+ *
+ * Return:
+ * SAB_STATUS_OK on success
+ * SAB_INVALID_PARAMETER when one of the pointer parameters is NULL
+ *   or the remaining parameters have illegal values.
+ */
+SABuilder_Status_t
+SABuilder_Init_Basic(
+        SABuilder_Params_t * const SAParams_p,
+        SABuilder_Params_Basic_t * const SAParamsBasic_p,
+        const SABuilder_Direction_t direction)
+{
+#ifdef SAB_STRICT_ARGS_CHECK
+    if (SAParams_p == NULL || SAParamsBasic_p == NULL)
+    {
+        LOG_CRIT("SABuilder_Init_Basic: NULL pointer parameter supplied.\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    if (direction != SAB_DIRECTION_OUTBOUND &&
+        direction != SAB_DIRECTION_INBOUND)
+    {
+        LOG_CRIT("SABuilder_Init_Basic: Invalid direction.\n");
+        return SAB_INVALID_PARAMETER;
+    }
+#endif
+
+    SAParams_p->protocol = SAB_PROTO_BASIC;
+    SAParams_p->direction = direction;
+    SAParams_p->ProtocolExtension_p = (void*)SAParamsBasic_p;
+    SAParams_p->flags = 0;
+    SAParams_p->RedirectInterface = 0;
+
+    SAParams_p->CryptoAlgo = SAB_CRYPTO_NULL;
+    SAParams_p->CryptoMode = SAB_CRYPTO_MODE_CBC;
+    SAParams_p->IVSrc = SAB_IV_SRC_DEFAULT;
+    SAParams_p->CryptoParameter = 0;
+    SAParams_p->KeyByteCount = 0;
+    SAParams_p->Key_p = NULL;
+    SAParams_p->IV_p = NULL;
+    SAParams_p->Nonce_p = NULL;
+
+    SAParams_p->AuthAlgo = SAB_AUTH_NULL;
+    SAParams_p->AuthKey1_p = NULL;
+    SAParams_p->AuthKey2_p = NULL;
+    SAParams_p->AuthKey3_p = NULL;
+    SAParams_p->AuthKeyByteCount = 0;
+
+    SAParams_p->OffsetARC4StateRecord = 0;
+    SAParams_p->CW0 = 0;
+    SAParams_p->CW1 = 0;
+    SAParams_p->OffsetDigest0 = 0;
+    SAParams_p->OffsetDigest1 = 0;
+    SAParams_p->OffsetSeqNum = 0;
+    SAParams_p->OffsetSeqMask = 0;
+    SAParams_p->OffsetIV = 0;
+    SAParams_p->OffsetIJPtr = 0;
+    SAParams_p->OffsetARC4State = 0;
+    SAParams_p->SeqNumWord32Count = 0;
+    SAParams_p->SeqMaskWord32Count = 0;
+    SAParams_p->IVWord32Count = 0;
+
+    SAParamsBasic_p->BasicFlags = 0;
+    SAParamsBasic_p->DigestBlockCount = 0;
+    SAParamsBasic_p->ICVByteCount = 0;
+
+    SAParamsBasic_p->fresh = 0;
+    SAParamsBasic_p->bearer = 0;
+    SAParamsBasic_p->direction = 0;
+
+    SAParamsBasic_p->ContextRef = 0;
+    return SAB_STATUS_OK;
+}
+
+
+/*----------------------------------------------------------------------------
+ * SABuilder_SetBasicParams
+ *
+ * Fill in Basic Crypto and hash-specific extensions into the SA.
+ *
+ * SAParams_p (input)
+ *   The SA parameters structure from which the SA is derived.
+ *
+ * SAState_p (input, output)
+ *   Variables containing information about the SA being generated.
+ *
+ * SABuffer_p (input, output).
+ *   The buffer in which the SA is built. If NULL, no SA will be built, but
+ *   state variables in SAState_p will still be updated.
+ *
+ * Return:
+ * SAB_STATUS_OK on success
+ * SAB_INVALID_PARAMETER when SAParams_p is invalid, or if any of
+ *    the buffer arguments  is a null pointer while the corresponding buffer
+ *    would be required for the operation.
+ * SAB_UNSUPPORTED_FEATURE when SAParams_p describes an operations that
+ *    is not supported on the hardware for which this SA builder
+ *    is configured.
+ */
+SABuilder_Status_t
+SABuilder_SetBasicParams(
+        SABuilder_Params_t *const SAParams_p,
+        SABuilder_State_t * const SAState_p,
+        uint32_t * const SABuffer_p)
+{
+    SABuilder_Params_Basic_t *SAParamsBasic_p;
+    SAParamsBasic_p = (SABuilder_Params_Basic_t *)
+        (SAParams_p->ProtocolExtension_p);
+
+    if (SAParamsBasic_p == NULL)
+    {
+        LOG_CRIT("SABuilder: Basic extension pointer is null\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    if (SAParamsBasic_p->direction > 1 ||
+        SAParamsBasic_p->bearer > 32)
+    {
+        LOG_CRIT("SABuilder: Illegal value for bearer or direction\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    /* Use one of the classic hash algorithms, possibly with
+       encryption */
+    if ((SAParams_p->AuthAlgo == SAB_AUTH_HASH_MD5 ||
+         SAParams_p->AuthAlgo == SAB_AUTH_HASH_SHA1 ||
+         SAParams_p->AuthAlgo == SAB_AUTH_HASH_SHA2_224 ||
+         SAParams_p->AuthAlgo == SAB_AUTH_HASH_SHA2_256 ||
+         SAParams_p->AuthAlgo == SAB_AUTH_HASH_SHA2_384 ||
+         SAParams_p->AuthAlgo == SAB_AUTH_HASH_SHA2_512 ||
+         SAParams_p->AuthAlgo == SAB_AUTH_HASH_SM3) &&
+        (SAParams_p->flags & (SAB_FLAG_HASH_LOAD|SAB_FLAG_HASH_SAVE|
+                              SAB_FLAG_HASH_INTERMEDIATE)) != 0)
+    {
+        /* We are doing basic hash (no HMAC) with storing the state.*/
+        SAState_p->CW1 |= SAB_CW1_HASH_STORE | SAB_CW1_DIGEST_CNT;
+        if(SABuffer_p != NULL)
+            SABuffer_p[SAState_p->CurrentOffset] =
+                SAParamsBasic_p->DigestBlockCount;
+        SAState_p->CurrentOffset += 1;
+    }
+    else if (SAParams_p->AuthAlgo != SAB_AUTH_NULL &&
+             (SAParams_p->flags & (SAB_FLAG_HASH_SAVE)) != 0)
+    {
+        SAState_p->CW1 |= SAB_CW1_HASH_STORE;
+    }
+
+    if ((SAParams_p->AuthAlgo == SAB_AUTH_KASUMI_F9 ||
+         SAParams_p->AuthAlgo == SAB_AUTH_SNOW_UIA2 ||
+         SAParams_p->AuthAlgo == SAB_AUTH_ZUC_EIA3) &&
+        SAParamsBasic_p->direction != 0)
+    {
+        SAState_p->CW1 |= SAB_CW1_WIRELESS_DIR;
+    }
+
+    if (SAParams_p->CryptoAlgo != SAB_CRYPTO_NULL)
+    {
+        /* We are now doing basic encryption/decryption,
+           possibly with hash.*/
+        if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+            if (SAParams_p->AuthAlgo == SAB_AUTH_NULL)
+                SAState_p->CW0 |= SAB_CW0_TOP_ENCRYPT;
+            else if (SAParams_p->AuthAlgo==SAB_AUTH_AES_CCM ||
+                     SAParams_p->AuthAlgo==SAB_AUTH_AES_GMAC)
+                SAState_p->CW0 |= SAB_CW0_TOP_HASH_ENCRYPT;
+            else if ( (SAParamsBasic_p->BasicFlags & SAB_BASIC_FLAG_ENCRYPT_AFTER_HASH) != 0)
+                SAState_p->CW0 |= SAB_CW0_TOP_HASH_ENCRYPT;
+            else
+                SAState_p->CW0 |= SAB_CW0_TOP_ENCRYPT_HASH;
+        else
+            if (SAParams_p->AuthAlgo == SAB_AUTH_NULL)
+                SAState_p->CW0 |= SAB_CW0_TOP_DECRYPT;
+            else if (SAParams_p->AuthAlgo==SAB_AUTH_AES_CCM)
+                SAState_p->CW0 |= SAB_CW0_TOP_DECRYPT_HASH;
+            else if ( (SAParamsBasic_p->BasicFlags & SAB_BASIC_FLAG_ENCRYPT_AFTER_HASH) != 0)
+            {
+                SAState_p->CW0 |= SAB_CW0_TOP_DECRYPT_HASH;
+                SAState_p->CW1 |= SAB_CW1_PREPKT_OP;
+                SAState_p->CW1 |= SAB_CW1_PAD_TLS;
+            }
+            else
+                SAState_p->CW0 |= SAB_CW0_TOP_HASH_DECRYPT;
+
+        /* Check for prohibited algorithms and crypto modes. */
+        if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CFB1 ||
+            SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CFB8)
+        {
+            LOG_CRIT("SABuilder: crypto algorithm/mode not supported\n");
+            return SAB_INVALID_PARAMETER;
+        }
+
+        /* Reject crypto modes other than CBC for ENCRYPT_AFTER_HASH */
+        if ( (SAParamsBasic_p->BasicFlags & SAB_BASIC_FLAG_ENCRYPT_AFTER_HASH) != 0 &&
+            SAParams_p->CryptoMode != SAB_CRYPTO_MODE_CBC)
+        {
+            LOG_CRIT("SABuilder: crypto algorithm/mode not supported for encrypt after hash\n");
+            return SAB_INVALID_PARAMETER;
+        }
+
+        if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_XTS ||
+            SAParams_p->CryptoMode == SAB_CRYPTO_MODE_XTS_STATEFUL)
+        { /* For AES-XTS, extract Key2 from Nonce_p parameter,
+           same size as the primary AES key. */
+#ifdef SAB_STRICT_ARGS_CHECK
+            if (SAParams_p->Nonce_p == NULL)
+            {
+                LOG_CRIT("SABuilder: NULL pointer Key 2.\n");
+                return SAB_INVALID_PARAMETER;
+            }
+#endif
+            SABuilderLib_CopyKeyMat(SABuffer_p,
+                                    SAState_p->CurrentOffset,
+                                    SAParams_p->Nonce_p,
+                                    SAParams_p->KeyByteCount);
+            SAState_p->CurrentOffset+=SAState_p->CipherKeyWords;
+        }
+
+        if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_F8 ||
+            SAParams_p->CryptoMode == SAB_CRYPTO_MODE_UEA2 ||
+            SAParams_p->CryptoMode == SAB_CRYPTO_MODE_EEA3)
+        {
+            SAParams_p->IVSrc = SAB_IV_SRC_TOKEN;
+        }
+        else if (SAParams_p->CryptoAlgo != SAB_CRYPTO_ARCFOUR &&
+                 SAParams_p->CryptoMode != SAB_CRYPTO_MODE_ECB &&
+                 !(SAParams_p->CryptoAlgo==SAB_CRYPTO_KASUMI &&
+                   SAParams_p->CryptoMode==SAB_CRYPTO_MODE_BASIC))
+        {
+            /* For ARCFOUR and block ciphers in ECB mode and
+               Basic Kasumi we do not have an IV */
+            if (SAParams_p->IVSrc == SAB_IV_SRC_DEFAULT)
+                SAParams_p->IVSrc = SAB_IV_SRC_INPUT;
+
+            if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CTR ||
+                SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CCM ||
+                SAParams_p->CryptoMode == SAB_CRYPTO_MODE_GMAC ||
+                SAParams_p->CryptoMode == SAB_CRYPTO_MODE_GCM)
+            {
+                if (SAParams_p->IVSrc == SAB_IV_SRC_TOKEN)
+                {
+                    SAState_p->CW1 &= ~0x7; // Clear crypto mode (CTR);
+                    SAState_p->CW1 |= SAB_CW1_CRYPTO_MODE_CTR_LOAD;
+                    /* When the CTR mode IV is loaded from token, then
+                       load all four IV words, including block counter */
+                }
+                else
+                {   /* else add nonce to SA */
+                    SAState_p->CW1 |= SAB_CW1_IV0;
+
+#ifdef SAB_STRICT_ARGS_CHECK
+                    if (SAParams_p->Nonce_p == NULL)
+                    {
+                        LOG_CRIT("SABuilder: NULL pointer nonce.\n");
+                        return SAB_INVALID_PARAMETER;
+                    }
+#endif
+                    if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CCM)
+                    {
+                        if (SABuffer_p != NULL)
+                            SABuffer_p[SAState_p->CurrentOffset] =
+                              (SAParams_p->Nonce_p[0] << 8)  |
+                              (SAParams_p->Nonce_p[1] << 16) |
+                              (SAParams_p->Nonce_p[2] << 24) | SAB_CCM_FLAG_L4;
+                    }
+                    else
+                    {
+                        SABuilderLib_CopyKeyMat(SABuffer_p,
+                                                SAState_p->CurrentOffset,
+                                                SAParams_p->Nonce_p, sizeof(uint32_t));
+                    }
+                    SAState_p->CurrentOffset +=1;
+                }
+
+                if (SAParams_p->IVSrc == SAB_IV_SRC_SA)
+                {
+                    SAState_p->CW1 |= SAB_CW1_IV_CTR |
+                                      SAB_CW1_IV1    |
+                                      SAB_CW1_IV2;
+#ifdef SAB_STRICT_ARGS_CHECK
+                    if (SAParams_p->IV_p == NULL)
+                    {
+                        LOG_CRIT("SABuilder: NULL pointer IV.\n");
+                        return SAB_INVALID_PARAMETER;
+                    }
+#endif
+                    SAParams_p->OffsetIV = SAState_p->CurrentOffset;
+                    SAParams_p->IVWord32Count = 2;
+
+                    SABuilderLib_CopyKeyMat(SABuffer_p,
+                                            SAState_p->CurrentOffset,
+                                            SAParams_p->IV_p, 8);
+                    SAState_p->CurrentOffset += 2;
+                }
+                else
+                {
+                    SAState_p->CW1 |= SAB_CW1_IV_CTR;
+                }
+
+                if (SAParams_p->IVSrc != SAB_IV_SRC_TOKEN &&
+                    SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CCM)
+                {
+                    /* Add 0 counter field (IV3) */
+                    SAState_p->CW1 |= SAB_CW1_IV3;
+                    if(SABuffer_p != NULL)
+                        SABuffer_p[SAState_p->CurrentOffset] = 0;
+                    SAState_p->CurrentOffset+=1;
+                }
+            }
+            else
+            {
+                if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_ICM)
+                {
+                    SAState_p->CW1 &= ~0x7; // Clear crypto mode (CTR or ICM);
+                    SAState_p->CW1 |= SAB_CW1_CRYPTO_MODE_CTR_LOAD;
+                    /* When the CTR mode IV is loaded from token, then
+                       load all four IV words, including block counter */
+                }
+
+                SAState_p->CW1 |= SAB_CW1_IV_FULL;
+                if (SAParams_p->IVSrc == SAB_IV_SRC_SA)
+                {
+                    SAState_p->CW1 |= SAB_CW1_IV0 | SAB_CW1_IV1;
+                    if(SAState_p->IVWords == 4)
+                        SAState_p->CW1 |= SAB_CW1_IV2 | SAB_CW1_IV3;
+
+#ifdef SAB_STRICT_ARGS_CHECK
+                    if (SAParams_p->IV_p == NULL)
+                    {
+                        LOG_CRIT("SABuilder: NULL pointer IV.\n");
+                        return SAB_INVALID_PARAMETER;
+                    }
+#endif
+                    SAParams_p->OffsetIV = SAState_p->CurrentOffset;
+                    SAParams_p->IVWord32Count = SAState_p->IVWords;
+
+                    SABuilderLib_CopyKeyMat(SABuffer_p,
+                                     SAState_p->CurrentOffset,
+                                     SAParams_p->IV_p,
+                                     SAState_p->IVWords * sizeof(uint32_t));
+                    SAState_p->CurrentOffset += SAState_p->IVWords;
+                    if (SAParams_p->CryptoAlgo == SAB_CRYPTO_DES ||
+                        SAParams_p->CryptoAlgo == SAB_CRYPTO_3DES ||
+                        SAParams_p->CryptoAlgo == SAB_CRYPTO_AES ||
+                        SAParams_p->CryptoAlgo == SAB_CRYPTO_SM4 ||
+                        SAParams_p->CryptoAlgo == SAB_CRYPTO_BC0)
+                      SAState_p->CW1 |= SAB_CW1_CRYPTO_STORE;
+                }
+            }
+        }
+    }
+    else
+    {
+        /* Bypass operation or authenticate-only,
+           use inbound direction when verifying */
+        if (SAParams_p->AuthAlgo == SAB_AUTH_NULL)
+            SAState_p->CW0 |= SAB_CW0_TOP_NULL_OUT;
+        else if ((SAParamsBasic_p->BasicFlags & SAB_BASIC_FLAG_EXTRACT_ICV) !=0)
+            SAState_p->CW0 |= SAB_CW0_TOP_HASH_IN;
+        else
+            SAState_p->CW0 |= SAB_CW0_TOP_HASH_OUT;
+    }
+
+    return SAB_STATUS_OK;
+}
+
+#endif /* SAB_ENABLE_PROTO_BASIC */
+
+/* end of file sa_builder_basic.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_extended_basic.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_extended_basic.c
new file mode 100644
index 0000000..236a8ba
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_extended_basic.c
@@ -0,0 +1,406 @@
+/* sa_builder_extended_basic.c
+ *
+ * Basic opaeration specific functions (for initialization of
+ * SABuilder_Params_t structures and for building the Basic specific
+ * part of an SA) in the Extended use case.
+ */
+
+/*****************************************************************************
+* Copyright (c) 2016-2022 by Rambus, Inc. and/or its subsidiaries.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+#include "c_sa_builder.h"
+#ifdef SAB_ENABLE_BASIC_EXTENDED
+#include "sa_builder_extended_internal.h"
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+#include "basic_defs.h"
+#include "log.h"
+#include "sa_builder_internal.h" /* SABuilder_SetBasicParams */
+#include "sa_builder_basic.h"
+
+#include "firmware_eip207_api_cs.h"
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * SABuilder_SetExtendedBasicParams
+ *
+ * Fill in Basic-specific extensions into the SA.for Extended.
+ *
+ * SAParams_p (input)
+ *   The SA parameters structure from which the SA is derived.
+ * SAState_p (input, output)
+ *   Variables containing information about the SA being generated/
+ * SABuffer_p (input, output).
+ *   The buffer in which the SA is built. If NULL, no SA will be built, but
+ *   state variables in SAState_p will still be updated.
+ *
+ * Return:
+ * SAB_STATUS_OK on success
+ * SAB_INVALID_PARAMETER when SAParams_p is invalid, or if any of
+ *    the buffer arguments  is a null pointer while the corresponding buffer
+ *    would be required for the operation.
+ * SAB_UNSUPPORTED_FEATURE when SAParams_p describes an operations that
+ *    is not supported on the hardware for which this SA builder
+ *    is configured.
+ */
+SABuilder_Status_t
+SABuilder_SetExtendedBasicParams(SABuilder_Params_t *const SAParams_p,
+                                 SABuilder_State_t * const SAState_p,
+                                 uint32_t * const SABuffer_p)
+{
+    SABuilder_Params_Basic_t *SAParamsBasic_p =
+        (SABuilder_Params_Basic_t *)(SAParams_p->ProtocolExtension_p);
+
+    IDENTIFIER_NOT_USED(SAState_p);
+
+#ifdef FIRMWARE_EIP207_CS_TR_IV_WORD_OFFSET
+    /* These operations are specific to PDCP firmware */
+    if (SAParams_p->AuthAlgo == SAB_AUTH_SNOW_UIA2 ||
+        SAParams_p->AuthAlgo == SAB_AUTH_KASUMI_F9)
+    {
+        if(SABuffer_p != NULL)
+            SABuffer_p[FIRMWARE_EIP207_CS_TR_IV_WORD_OFFSET] =
+                SAParamsBasic_p->fresh;
+    }
+#endif
+#ifdef FIRMWARE_EIP207_CS_FLOW_TR_BYTE_PARAM_WORD_OFFSET
+    /* These operations are specific to non-PDCP firmware */
+    if ((SAParams_p->CryptoAlgo != SAB_CRYPTO_NULL &&
+         SAParams_p->CryptoAlgo != SAB_CRYPTO_ARCFOUR &&
+         SAParams_p->CryptoAlgo != SAB_CRYPTO_CHACHA20 &&
+         SAParams_p->AuthAlgo != SAB_AUTH_NULL &&
+         SAParams_p->AuthAlgo != SAB_AUTH_AES_GCM &&
+         SAParams_p->AuthAlgo != SAB_AUTH_AES_GMAC &&
+         SAParams_p->AuthAlgo != SAB_AUTH_AES_CCM) ||
+        (SAParams_p->CryptoAlgo == SAB_CRYPTO_NULL &&
+         SAParams_p->AuthAlgo == SAB_AUTH_NULL))
+    {
+        /* Only combined crypto + hash and not AES-GCM/AES-GMAC/AES-CCM are
+           supported */
+        uint32_t TokenHeaderWord = SAB_HEADER_DEFAULT;
+        SABuilder_ESPProtocol_t ESPProto;
+        SABuilder_HeaderProtocol_t HeaderProto;
+        uint8_t PadBlockByteCount = 1;
+        uint8_t IVByteCount = 0;
+        uint8_t ICVByteCount = 0;
+        uint32_t flags = 0;
+        uint32_t VerifyInstructionWord, CtxInstructionWord;
+        uint32_t IVInstructionWord = 0;
+
+        if (SAParams_p->CryptoAlgo == SAB_CRYPTO_NULL)
+        {
+            ESPProto = SAB_ESP_PROTO_NONE;
+            if ((SAParamsBasic_p->BasicFlags & SAB_BASIC_FLAG_XFRM_API) != 0)
+
+                HeaderProto = SAB_HDR_BASIC_IN_NO_PAD;
+            else
+                HeaderProto = SAB_HDR_BYPASS;
+            VerifyInstructionWord = SAB_VERIFY_NONE;
+        }
+        else
+        {
+            if ((SAParamsBasic_p->BasicFlags & SAB_BASIC_FLAG_ENCRYPT_AFTER_HASH) != 0)
+            {
+                if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+                {
+                    ESPProto = SAB_BASIC_PROTO_OUT_HASHENC;
+                    HeaderProto = SAB_HDR_BASIC_OUT_TPAD;
+                }
+                else
+                {
+                    ESPProto = SAB_BASIC_PROTO_IN_DECHASH;
+                    TokenHeaderWord |= SAB_HEADER_PAD_VERIFY;
+                    HeaderProto = SAB_HDR_BASIC_IN_PAD;
+                }
+            }
+            else
+            {
+                if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+                {
+                    ESPProto = SAB_BASIC_PROTO_OUT_ENCHASH;
+                    HeaderProto = SAB_HDR_BASIC_OUT_ZPAD;
+                }
+                else
+                {
+                    ESPProto = SAB_BASIC_PROTO_IN_HASHDEC;
+                    HeaderProto = SAB_HDR_BASIC_IN_NO_PAD;
+                }
+        }
+
+            if ((SAParams_p->flags & SAB_FLAG_SUPPRESS_HEADER) == 0)
+                flags |= BIT_29;
+
+            switch(SAParams_p->CryptoAlgo)
+            {
+            case SAB_CRYPTO_DES:
+            case SAB_CRYPTO_3DES:
+                IVByteCount = 8;
+                PadBlockByteCount = 8;
+            break;
+            case SAB_CRYPTO_AES:
+            case SAB_CRYPTO_SM4:
+            case SAB_CRYPTO_BC0:
+                IVByteCount = 16;
+                PadBlockByteCount = 16;
+                break;
+            default:
+                LOG_CRIT("SABuilder_BuildSA: unsupported crypto algorithm\n");
+                return SAB_UNSUPPORTED_FEATURE;
+            }
+
+            switch(SAParams_p->CryptoMode)
+            {
+            case SAB_CRYPTO_MODE_ECB:
+                IVByteCount = 0;
+                IVInstructionWord = 0x20000004; /* NOP instruction */
+                break;
+            case SAB_CRYPTO_MODE_CBC:
+                if (SAParams_p->IVSrc == SAB_IV_SRC_DEFAULT ||
+                    SAParams_p->IVSrc == SAB_IV_SRC_INPUT)
+                {
+                    IVInstructionWord = SA_RETR_HASH_IV0 + IVByteCount;
+                }
+                else
+                {
+                    IVInstructionWord = SA_INS_NONE_IV0 + IVByteCount;
+                    IVByteCount = 0;
+                }
+                if (SAParams_p->IVSrc == SAB_IV_SRC_PRNG)
+                    TokenHeaderWord |= SAB_HEADER_IV_PRNG;
+                if ((SAParams_p->flags & SAB_FLAG_COPY_IV) != 0)
+                {
+                    IVInstructionWord |= BIT_25|BIT_24; /* IV to output & hash */
+                }
+                if ((SAParamsBasic_p->BasicFlags & SAB_BASIC_FLAG_ENCRYPT_AFTER_HASH) != 0)
+                {
+                    IVInstructionWord &= ~BIT_25; /* Do not hash IV for HASHENC */
+                }
+                break;
+            case SAB_CRYPTO_MODE_CTR:
+                IVByteCount = 8;
+                PadBlockByteCount = 1;
+                if (SAParams_p->IVSrc == SAB_IV_SRC_DEFAULT ||
+                    SAParams_p->IVSrc == SAB_IV_SRC_INPUT)
+                {
+                    IVInstructionWord = SA_RETR_HASH_IV1 + IVByteCount;
+                }
+                else
+                {
+                    IVInstructionWord = SA_INS_NONE_IV1 + IVByteCount;
+                    IVByteCount = 0;
+                }
+                if ((SAParams_p->flags & SAB_FLAG_COPY_IV) != 0)
+                {
+                    IVInstructionWord |= BIT_25|BIT_24; /* IV to output & hash */
+                }
+                break;
+            case SAB_CRYPTO_MODE_ICM:
+                IVByteCount = 16;
+                PadBlockByteCount = 1;
+                if (SAParams_p->IVSrc == SAB_IV_SRC_DEFAULT ||
+                    SAParams_p->IVSrc == SAB_IV_SRC_INPUT)
+                {
+                    IVInstructionWord = SA_RETR_HASH_IV0 + IVByteCount;
+                }
+                else
+                {
+                    IVInstructionWord = SA_INS_NONE_IV0 + IVByteCount;
+                    IVByteCount = 0;
+                }
+                if ((SAParams_p->flags & SAB_FLAG_COPY_IV) != 0)
+                {
+                    IVInstructionWord |= BIT_25|BIT_24; /* IV to output & hash */
+                }
+                break;
+            default:
+                LOG_CRIT("SABuilder_BuildSA: unsupported crypto mode\n");
+                return SAB_UNSUPPORTED_FEATURE;
+            }
+
+            switch(SAParams_p->AuthAlgo)
+            {
+            case SAB_AUTH_HASH_MD5:
+            case SAB_AUTH_SSLMAC_MD5:
+            case SAB_AUTH_HMAC_MD5:
+                ICVByteCount = 16;
+                break;
+            case SAB_AUTH_HASH_SHA1:
+            case SAB_AUTH_SSLMAC_SHA1:
+            case SAB_AUTH_HMAC_SHA1:
+                ICVByteCount = 20;
+                break;
+            case SAB_AUTH_HASH_SHA3_224:
+            case SAB_AUTH_KEYED_HASH_SHA3_224:
+            case SAB_AUTH_HMAC_SHA3_224:
+                ICVByteCount = 28;
+                break;
+            case SAB_AUTH_HASH_SHA2_224:
+            case SAB_AUTH_HMAC_SHA2_224:
+            case SAB_AUTH_HASH_SHA2_256:
+            case SAB_AUTH_HMAC_SHA2_256:
+            case SAB_AUTH_HMAC_SM3:
+            case SAB_AUTH_HASH_SM3:
+            case SAB_AUTH_HASH_SHA3_256:
+            case SAB_AUTH_KEYED_HASH_SHA3_256:
+            case SAB_AUTH_HMAC_SHA3_256:
+                ICVByteCount = 32;
+                break;
+            case SAB_AUTH_HASH_SHA3_384:
+            case SAB_AUTH_KEYED_HASH_SHA3_384:
+            case SAB_AUTH_HMAC_SHA3_384:
+                ICVByteCount = 48;
+                break;
+            case SAB_AUTH_HASH_SHA2_384:
+            case SAB_AUTH_HMAC_SHA2_384:
+                if ((SAParamsBasic_p->BasicFlags & SAB_BASIC_FLAG_ENCRYPT_AFTER_HASH) != 0)
+                    ICVByteCount = 48;
+                else
+                    ICVByteCount = 64;
+                break;
+            case SAB_AUTH_HASH_SHA3_512:
+            case SAB_AUTH_KEYED_HASH_SHA3_512:
+            case SAB_AUTH_HMAC_SHA3_512:
+            case SAB_AUTH_HASH_SHA2_512:
+            case SAB_AUTH_HMAC_SHA2_512:
+                ICVByteCount = 64;
+                break;
+            case SAB_AUTH_AES_XCBC_MAC:
+            case SAB_AUTH_AES_CMAC_128:
+            case SAB_AUTH_AES_CMAC_192:
+            case SAB_AUTH_AES_CMAC_256:
+                ICVByteCount = 16;
+                break;
+            default:
+                LOG_CRIT("SABuilder_BuildSA: unsupported authentication algorithm\n");
+                return SAB_UNSUPPORTED_FEATURE;
+            }
+            if (SAParamsBasic_p->ICVByteCount != 0 &&
+                SAParamsBasic_p->ICVByteCount < ICVByteCount)
+                ICVByteCount = SAParamsBasic_p->ICVByteCount;
+
+            /* Take care of the VERIFY and CTX token instructions */
+            if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+            {
+                VerifyInstructionWord = SAB_VERIFY_NONE;
+            }
+            else
+            {
+                if ((SAParamsBasic_p->BasicFlags & SAB_BASIC_FLAG_ENCRYPT_AFTER_HASH) != 0)
+                {
+                    VerifyInstructionWord = SAB_VERIFY_PAD;
+                }
+                else
+                {
+                    VerifyInstructionWord = SAB_VERIFY_NONE;
+                }
+                VerifyInstructionWord += SAB_VERIFY_BIT_H + ICVByteCount;
+            }
+        }
+
+#ifdef SAB_ENABLE_TWO_FIXED_RECORD_SIZES
+        if (SAState_p->fLarge)
+        {
+            CtxInstructionWord = SAB_CTX_NONE + FIRMWARE_EIP207_CS_FLOW_TRC_RECORD_WORD_COUNT + LargeTransformOffset - 1;
+        }
+        else
+#endif
+        {
+            CtxInstructionWord = SAB_CTX_NONE + FIRMWARE_EIP207_CS_FLOW_TRC_RECORD_WORD_COUNT - 1;
+        }
+
+        /* Write all parameters to their respective offsets */
+        if (SABuffer_p != NULL)
+        {
+#ifdef SAB_ENABLE_TWO_FIXED_RECORD_SIZES
+            if (SAState_p->fLarge)
+            {
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_FLAGS_WORD_OFFSET +
+                           LargeTransformOffset] = flags;
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_HDRPROC_CTX_WORD_OFFSET +
+                    LargeTransformOffset] = SAParamsBasic_p->ContextRef;
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_BYTE_PARAM_WORD_OFFSET +
+                           LargeTransformOffset] =
+                    SAB_PACKBYTES(IVByteCount,ICVByteCount,HeaderProto,ESPProto);
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_HDR_WORD_OFFSET +
+                           LargeTransformOffset] = TokenHeaderWord;
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_PAD_ALIGN_WORD_OFFSET +
+                           LargeTransformOffset] =
+                    SAB_PACKBYTES(PadBlockByteCount/2, 0, 0, 0);
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_CCM_SALT_WORD_OFFSET +
+                    LargeTransformOffset] =IVInstructionWord;
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_VFY_INST_WORD_OFFSET +
+                    LargeTransformOffset] = VerifyInstructionWord;
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_CTX_INST_WORD_OFFSET +
+                    LargeTransformOffset] = CtxInstructionWord;
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_LO_WORD_OFFSET +
+                           LargeTransformOffset] = 0;
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_HI_WORD_OFFSET +
+                    LargeTransformOffset] = 0;
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_LO_WORD_OFFSET +
+                    LargeTransformOffset] = 0;
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_HI_WORD_OFFSET +
+                    LargeTransformOffset] = 0;
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_PKT_WORD_OFFSET +
+                    LargeTransformOffset] = 0;
+            }
+            else
+#endif /* SAB_ENABLE_TWO_FIXED_RECORD_SIZES */
+            {
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_FLAGS_WORD_OFFSET] = flags;
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_HDRPROC_CTX_WORD_OFFSET] =
+                    SAParamsBasic_p->ContextRef;
+;
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_BYTE_PARAM_WORD_OFFSET] =
+                    SAB_PACKBYTES(IVByteCount,ICVByteCount,HeaderProto,ESPProto);
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_HDR_WORD_OFFSET] = TokenHeaderWord;
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_PAD_ALIGN_WORD_OFFSET] =
+                    SAB_PACKBYTES(PadBlockByteCount/2, 0, 0, 0);
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_CCM_SALT_WORD_OFFSET] = IVInstructionWord;
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_VFY_INST_WORD_OFFSET] =
+                    VerifyInstructionWord;
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_CTX_INST_WORD_OFFSET] =
+                    CtxInstructionWord;
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_LO_WORD_OFFSET] = 0;
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_HI_WORD_OFFSET] = 0;
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_LO_WORD_OFFSET] = 0;
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_HI_WORD_OFFSET] = 0;
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_PKT_WORD_OFFSET] = 0;
+            }
+        }
+    }
+#endif
+    return SAB_STATUS_OK;
+}
+
+#endif /* SAB_ENABLE_BASIC_EXTENDED */
+
+
+/* end of file sa_builder_extended_basic.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_extended_dtls.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_extended_dtls.c
new file mode 100644
index 0000000..11abdd6
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_extended_dtls.c
@@ -0,0 +1,396 @@
+/* sa_builder_extended_dtls.c
+ *
+ * DTLS specific functions (for initialization of SABuilder_Params_t
+ * structures and for building the DTLS specifc part of an SA.) in the
+ * Extended use case.
+ */
+
+/*****************************************************************************
+* Copyright (c) 2011-2022 by Rambus, Inc. and/or its subsidiaries.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+#include "c_sa_builder.h"
+#ifdef SAB_ENABLE_DTLS_EXTENDED
+#include "sa_builder_extended_internal.h"
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+#include "basic_defs.h"
+#include "log.h"
+#include "sa_builder_internal.h" /* SABuilder_SetDTLSParams */
+#include "sa_builder_ssltls.h"
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * SABuilder_SetExtendedDTLSParams
+ *
+ * Fill in DTLS-specific extensions into the SA.for Extended.
+ *
+ * SAParams_p (input)
+ *   The SA parameters structure from which the SA is derived.
+ * SAState_p (input, output)
+ *   Variables containing information about the SA being generated/
+ * SABuffer_p (input, output).
+ *   The buffer in which the SA is built. If NULL, no SA will be built, but
+ *   state variables in SAState_p will still be updated.
+ *
+ * Return:
+ * SAB_STATUS_OK on success
+ * SAB_INVALID_PARAMETER when SAParams_p is invalid, or if any of
+ *    the buffer arguments  is a null pointer while the corresponding buffer
+ *    would be required for the operation.
+ * SAB_UNSUPPORTED_FEATURE when SAParams_p describes an operations that
+ *    is not supported on the hardware for which this SA builder
+ *    is configured.
+ */
+SABuilder_Status_t
+SABuilder_SetExtendedDTLSParams(SABuilder_Params_t *const SAParams_p,
+                         SABuilder_State_t * const SAState_p,
+                         uint32_t * const SABuffer_p)
+{
+    SABuilder_Params_SSLTLS_t *SAParamsSSLTLS_p =
+        (SABuilder_Params_SSLTLS_t *)(SAParams_p->ProtocolExtension_p);
+    uint32_t TokenHeaderWord = SAB_HEADER_DEFAULT;
+    SABuilder_ESPProtocol_t ESPProto;
+    SABuilder_HeaderProtocol_t HeaderProto;
+    uint8_t PadBlockByteCount;
+    uint8_t IVByteCount;
+    uint8_t ICVByteCount;
+    uint8_t SeqOffset;
+    uint8_t AntiReplay;
+    uint32_t flags = 0;
+    uint32_t VerifyInstructionWord, CtxInstructionWord;
+
+    IDENTIFIER_NOT_USED(SAState_p);
+
+    if (SAParamsSSLTLS_p == NULL)
+    {
+        LOG_CRIT("SABuilder: SSLTLS extension pointer is null\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    if ((SAParamsSSLTLS_p->version != SAB_DTLS_VERSION_1_0 &&
+         SAParamsSSLTLS_p->version != SAB_DTLS_VERSION_1_2) ||
+        (SAParams_p->CryptoAlgo != SAB_CRYPTO_AES &&
+         SAParams_p->CryptoAlgo != SAB_CRYPTO_CHACHA20 &&
+         SAParams_p->CryptoAlgo != SAB_CRYPTO_3DES &&
+         SAParams_p->CryptoAlgo != SAB_CRYPTO_SM4 &&
+         SAParams_p->CryptoAlgo != SAB_CRYPTO_NULL))
+    {
+        if (SABuffer_p != 0)
+            LOG_CRIT("SABuilder: SSLTLS record only for look-aside\n");
+        // No extended transform record can be created, however it can
+        // still be valid for host look-aside.
+        return SAB_STATUS_OK;
+    }
+
+    if ((SAParamsSSLTLS_p->SSLTLSFlags & SAB_DTLS_NO_ANTI_REPLAY) != 0)
+        AntiReplay = 0;
+    else
+        AntiReplay = 1;
+
+    if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+    {
+        if (SAParams_p->CryptoAlgo == SAB_CRYPTO_CHACHA20)
+        {
+            ESPProto = SAB_DTLS_PROTO_OUT_CHACHAPOLY;
+            PadBlockByteCount = 0;
+            IVByteCount = 0;
+        }
+        else if (SAParams_p->AuthAlgo == SAB_AUTH_AES_GCM)
+        {
+            ESPProto = SAB_DTLS_PROTO_OUT_GCM;
+            PadBlockByteCount = 0;
+            IVByteCount = 8;
+        }
+        else if (SAParams_p->CryptoAlgo == SAB_CRYPTO_NULL)
+        {
+            ESPProto = SAB_DTLS_PROTO_OUT_CHACHAPOLY;
+            PadBlockByteCount = 0;
+            IVByteCount = 0;
+        }
+        else
+        {
+            switch (SAParams_p->IVSrc)
+            {
+            case SAB_IV_SRC_DEFAULT:
+            case SAB_IV_SRC_PRNG:
+                TokenHeaderWord |=
+                    SAB_HEADER_IV_PRNG;
+                break;
+            case SAB_IV_SRC_SA: /* No action required */
+            case SAB_IV_SRC_TOKEN:
+                break;
+            default:
+                LOG_CRIT("SABuilder_BuildSA:"
+                         "Unsupported IV source\n");
+                return SAB_INVALID_PARAMETER;
+            }
+            ESPProto = SAB_DTLS_PROTO_OUT_CBC;
+            if (SAParams_p->CryptoAlgo == SAB_CRYPTO_3DES)
+            {
+                PadBlockByteCount = 8;
+                IVByteCount = 8;
+            }
+            else
+            {
+                PadBlockByteCount = 16;
+                IVByteCount = 16;
+            }
+        }
+
+        if ((SAParamsSSLTLS_p->SSLTLSFlags & SAB_DTLS_IPV6) !=0)
+        {
+            if ((SAParamsSSLTLS_p->SSLTLSFlags & SAB_DTLS_CAPWAP) !=0)
+            {
+                HeaderProto = SAB_HDR_IPV6_OUT_DTLS_CAPWAP;
+            }
+            else
+            {
+                HeaderProto = SAB_HDR_IPV6_OUT_DTLS;
+            }
+        }
+        else
+        {
+            if ((SAParamsSSLTLS_p->SSLTLSFlags & SAB_DTLS_CAPWAP) !=0)
+            {
+                HeaderProto = SAB_HDR_IPV4_OUT_DTLS_CAPWAP;
+            }
+            else
+            {
+                HeaderProto = SAB_HDR_IPV4_OUT_DTLS;
+            }
+        }
+    }
+    else
+    {
+        if (SAParams_p->CryptoAlgo == SAB_CRYPTO_CHACHA20)
+        {
+            ESPProto = SAB_DTLS_PROTO_IN_CHACHAPOLY;
+            PadBlockByteCount = 0;
+            IVByteCount = 0;
+        }
+        else if (SAParams_p->AuthAlgo == SAB_AUTH_AES_GCM)
+        {
+            ESPProto = SAB_DTLS_PROTO_IN_GCM;
+            PadBlockByteCount = 0;
+            IVByteCount = 8;
+        }
+        else if (SAParams_p->CryptoAlgo == SAB_CRYPTO_NULL)
+        {
+            ESPProto = SAB_DTLS_PROTO_IN_CHACHAPOLY;
+            PadBlockByteCount = 0;
+            IVByteCount = 0;
+        }
+        else
+        {
+            ESPProto = SAB_DTLS_PROTO_IN_CBC;
+            TokenHeaderWord |= SAB_HEADER_PAD_VERIFY;
+            if (SAParams_p->CryptoAlgo == SAB_CRYPTO_3DES)
+            {
+                PadBlockByteCount = 8;
+                IVByteCount = 8;
+            }
+            else
+            {
+                PadBlockByteCount = 16;
+                IVByteCount = 16;
+            }
+        }
+
+        if ((SAParamsSSLTLS_p->SSLTLSFlags & SAB_DTLS_IPV6) !=0)
+        {
+            if ((SAParamsSSLTLS_p->SSLTLSFlags & SAB_DTLS_CAPWAP) !=0)
+            {
+                HeaderProto = SAB_HDR_IPV6_IN_DTLS_CAPWAP;
+            }
+            else
+            {
+                HeaderProto = SAB_HDR_IPV6_IN_DTLS;
+            }
+        }
+        else
+        {
+            if ((SAParamsSSLTLS_p->SSLTLSFlags & SAB_DTLS_CAPWAP) !=0)
+            {
+                HeaderProto = SAB_HDR_IPV4_IN_DTLS_CAPWAP;
+            }
+            else
+            {
+                HeaderProto = SAB_HDR_IPV4_IN_DTLS;
+            }
+        }
+
+        AntiReplay *= SAParamsSSLTLS_p->SequenceMaskBitCount / 32;
+    }
+    SeqOffset = SAParams_p->OffsetSeqNum;
+
+    if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND &&
+        SAParamsSSLTLS_p->PadAlignment >
+        PadBlockByteCount &&
+        SAParamsSSLTLS_p->PadAlignment <= 256)
+        PadBlockByteCount =
+            SAParamsSSLTLS_p->PadAlignment;
+
+    switch(SAParams_p->AuthAlgo)
+    {
+    case SAB_AUTH_HMAC_MD5:
+        ICVByteCount = 16;
+        break;
+    case SAB_AUTH_HMAC_SHA1:
+        ICVByteCount = 20;
+        break;
+    case SAB_AUTH_HMAC_SHA2_256:
+    case SAB_AUTH_HMAC_SM3:
+        ICVByteCount = 32;
+        break;
+    case SAB_AUTH_HMAC_SHA2_384:
+        ICVByteCount = 48;
+        break;
+    case SAB_AUTH_HMAC_SHA2_512:
+        ICVByteCount = 64;
+        break;
+    case SAB_AUTH_AES_GCM:
+        ICVByteCount = 16;
+        break;
+    case SAB_AUTH_POLY1305:
+        ICVByteCount = 16;
+        break;
+    break;
+    default:
+        LOG_CRIT("SABuilder_BuildSA: unsupported authentication algorithm\n");
+        return SAB_UNSUPPORTED_FEATURE;
+    }
+
+    /* Flags variable */
+    if ((SAParamsSSLTLS_p->SSLTLSFlags & SAB_DTLS_IPV6) !=0)
+        flags |= BIT_8;
+    if ((SAParamsSSLTLS_p->SSLTLSFlags & SAB_DTLS_PROCESS_IP_HEADERS) !=0)
+        flags |= BIT_19;
+    if ((SAParamsSSLTLS_p->SSLTLSFlags & SAB_DTLS_PLAINTEXT_HEADERS) !=0)
+        flags |= BIT_29;
+
+    /* Take care of the VERIFY and CTX token instructions */
+    if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+    {
+        VerifyInstructionWord = SAB_VERIFY_NONE;
+        CtxInstructionWord = SAB_CTX_OUT_SEQNUM +
+            ((unsigned int)(2<<24)) + SeqOffset;
+    }
+    else
+    {
+        if (PadBlockByteCount != 0)
+        {
+            VerifyInstructionWord = SAB_VERIFY_PAD;
+        }
+        else
+        {
+            VerifyInstructionWord = SAB_VERIFY_NONE;
+        }
+        if (ICVByteCount > 0)
+        {
+            VerifyInstructionWord += SAB_VERIFY_BIT_H + ICVByteCount;
+        }
+        if (AntiReplay > 0)
+        {
+            VerifyInstructionWord += SAB_VERIFY_BIT_SEQ;
+        }
+        CtxInstructionWord = SAB_CTX_SEQNUM +
+            ((unsigned int)(2+AntiReplay)<<24) + SeqOffset;
+    }
+    /* Write all parameters to their respective offsets */
+    if (SABuffer_p != NULL)
+    {
+#ifdef SAB_ENABLE_TWO_FIXED_RECORD_SIZES
+        if (SAState_p->fLarge)
+        {
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_FLAGS_WORD_OFFSET +
+                       LargeTransformOffset] = flags;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_HDRPROC_CTX_WORD_OFFSET +
+                LargeTransformOffset] = SAParamsSSLTLS_p->ContextRef;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_BYTE_PARAM_WORD_OFFSET +
+                       LargeTransformOffset] =
+                SAB_PACKBYTES(IVByteCount,ICVByteCount,HeaderProto,ESPProto);
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_HDR_WORD_OFFSET +
+                       LargeTransformOffset] = TokenHeaderWord;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_PAD_ALIGN_WORD_OFFSET +
+                       LargeTransformOffset] =
+                SAB_PACKBYTES(PadBlockByteCount/2, 0, 0, 0);
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_CCM_SALT_WORD_OFFSET +
+                       LargeTransformOffset] =0;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_VFY_INST_WORD_OFFSET +
+                       LargeTransformOffset] = VerifyInstructionWord;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_CTX_INST_WORD_OFFSET +
+                       LargeTransformOffset] = CtxInstructionWord;
+            SABuffer_p[FIMRWARE_EIP207_CS_FLOW_TR_NATT_PORTS_WORD_OFFSET +
+                       LargeTransformOffset] =
+                SAParamsSSLTLS_p->version;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_LO_WORD_OFFSET +
+                       LargeTransformOffset] = 0;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_HI_WORD_OFFSET +
+                       LargeTransformOffset] = 0;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_LO_WORD_OFFSET +
+                LargeTransformOffset] = 0;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_HI_WORD_OFFSET +
+                LargeTransformOffset] = 0;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_PKT_WORD_OFFSET +
+                LargeTransformOffset] = 0;
+        }
+        else
+#endif /* SAB_ENABLE_TWO_FIXED_RECORD_SIZES */
+        {
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_FLAGS_WORD_OFFSET] = flags;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_HDRPROC_CTX_WORD_OFFSET] =
+                SAParamsSSLTLS_p->ContextRef;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_BYTE_PARAM_WORD_OFFSET] =
+                SAB_PACKBYTES(IVByteCount,ICVByteCount,HeaderProto,ESPProto);
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_HDR_WORD_OFFSET] = TokenHeaderWord;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_PAD_ALIGN_WORD_OFFSET] =
+                SAB_PACKBYTES(PadBlockByteCount/2, 0, 0, 0);
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_CCM_SALT_WORD_OFFSET] = 0;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_VFY_INST_WORD_OFFSET] =
+                VerifyInstructionWord;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_CTX_INST_WORD_OFFSET] =
+                CtxInstructionWord;
+            SABuffer_p[FIMRWARE_EIP207_CS_FLOW_TR_NATT_PORTS_WORD_OFFSET] =
+                SAParamsSSLTLS_p->version;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_LO_WORD_OFFSET] = 0;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_HI_WORD_OFFSET] = 0;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_LO_WORD_OFFSET] = 0;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_HI_WORD_OFFSET] = 0;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_PKT_WORD_OFFSET] = 0;
+        }
+    }
+    return SAB_STATUS_OK;
+}
+
+
+#endif /* SAB_ENABLE_DTLS_EXTENDED */
+
+
+/* end of file sa_builder_extended_dtls.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_extended_ipsec.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_extended_ipsec.c
new file mode 100644
index 0000000..14a07ab
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_extended_ipsec.c
@@ -0,0 +1,832 @@
+/* sa_builder_extended_ipsec.c
+ *
+ * IPsec specific functions (for initialization of SABuilder_Params_t
+ * structures and for building the IPSec specifc part of an SA.) in the
+ * Extended use case.
+ */
+
+/*****************************************************************************
+* Copyright (c) 2011-2022 by Rambus, Inc. and/or its subsidiaries.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+#include "c_sa_builder.h"
+
+#ifdef SAB_ENABLE_IPSEC_EXTENDED
+#include "sa_builder_extended_internal.h"
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+#include "basic_defs.h"
+#include "log.h"
+#include "sa_builder_internal.h" /* SABuilder_SetIpsecParams */
+#include "sa_builder_ipsec.h"
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+#define ESP_HDR_LEN 8
+#define IPV4_HDR_LEN 20
+#define IPV6_HDR_LEN 40
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+#ifdef SAB_ENABLE_EXTENDED_TUNNEL_HEADER
+/*----------------------------------------------------------------------------
+ * get16
+ *
+ * Read 16-bit value from byte array not changing the byte order.
+ */
+static uint16_t
+get16no(
+        uint8_t *p,
+        unsigned int offs)
+{
+    return (p[offs+1]<<8) | p[offs];
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ * SABuilder_SetExtendedIPsecParams
+ *
+ * Fill in IPsec-specific extensions into the SA.for Extended.
+ *
+ * SAParams_p (input)
+ *   The SA parameters structure from which the SA is derived.
+ * SAState_p (input, output)
+ *   Variables containing information about the SA being generated/
+ * SABuffer_p (input, output).
+ *   The buffer in which the SA is built. If NULL, no SA will be built, but
+ *   state variables in SAState_p will still be updated.
+ *
+ * Return:
+ * SAB_STATUS_OK on success
+ * SAB_INVALID_PARAMETER when SAParams_p is invalid, or if any of
+ *    the buffer arguments  is a null pointer while the corresponding buffer
+ *    would be required for the operation.
+ * SAB_UNSUPPORTED_FEATURE when SAParams_p describes an operations that
+ *    is not supported on the hardware for which this SA builder
+ *    is configured.
+ */
+SABuilder_Status_t
+SABuilder_SetExtendedIPsecParams(SABuilder_Params_t *const SAParams_p,
+                         SABuilder_State_t * const SAState_p,
+                         uint32_t * const SABuffer_p)
+{
+    SABuilder_Params_IPsec_t *SAParamsIPsec_p =
+        (SABuilder_Params_IPsec_t *)(SAParams_p->ProtocolExtension_p);
+    uint32_t TokenHeaderWord = SAB_HEADER_DEFAULT;
+    SABuilder_ESPProtocol_t ESPProto;
+    SABuilder_HeaderProtocol_t HeaderProto;
+    uint8_t PadBlockByteCount;
+    uint8_t IVByteCount;
+    uint8_t ICVByteCount;
+    uint8_t SeqOffset;
+    uint8_t ExtSeq = 0;
+    uint8_t AntiReplay;
+    uint32_t CCMSalt = 0;
+    uint32_t flags = 0;
+    uint32_t VerifyInstructionWord, CtxInstructionWord;
+#ifdef SAB_ENABLE_EXTENDED_TUNNEL_HEADER
+    uint32_t MTUDiscount = 0;
+    uint32_t CheckSum = 0;
+#endif
+    IDENTIFIER_NOT_USED(SAState_p);
+
+    if (SAParamsIPsec_p == NULL)
+    {
+        LOG_CRIT("SABuilder: IPsec extension pointer is null\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_ESP) == 0)
+    {
+        LOG_CRIT("SABuilder: IPsec only supports ESP.\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_XFRM_API) != 0)
+    {
+        if(SAParams_p->CryptoMode != SAB_CRYPTO_MODE_CBC &&
+           SAParams_p->CryptoMode != SAB_CRYPTO_MODE_GCM)
+        {
+            LOG_CRIT("SABuilder: IPsec for XFRM only supports CBC and GCM modes.\n");
+            return SAB_INVALID_PARAMETER;
+        }
+        if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_NATT) != 0)
+        {
+            LOG_CRIT("SABuilder: IPsec for XFRM does not support NATT\n");
+            return SAB_INVALID_PARAMETER;
+        }
+
+    }
+    if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_NO_ANTI_REPLAY) != 0)
+        AntiReplay = 0;
+    else
+        AntiReplay = 1;
+
+    if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+    {
+        if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_XFRM_API) != 0)
+            ESPProto = SAB_ESP_PROTO_OUT_XFRM_CBC;
+        else
+            ESPProto = SAB_ESP_PROTO_OUT_CBC;
+        PadBlockByteCount = 4;
+        if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_IPV6) !=0)
+        {
+            if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_XFRM_API) != 0)
+            {
+                    HeaderProto = SAB_HDR_IPV6_OUT_XFRM;
+            }
+            else if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_PROCESS_IP_HEADERS) !=0)
+            {
+                if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) !=0)
+                {
+                    HeaderProto = SAB_HDR_IPV6_OUT_TUNNEL;
+                }
+                else
+                {
+                    HeaderProto = SAB_HDR_IPV6_OUT_TRANSP;
+                }
+            }
+            else
+            {
+                HeaderProto = SAB_HDR_IPV6_OUT_TRANSP_HDRBYPASS;
+            }
+        }
+        else
+        {
+            if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_XFRM_API) != 0)
+            {
+                    HeaderProto = SAB_HDR_IPV4_OUT_XFRM;
+            }
+            else if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_PROCESS_IP_HEADERS) !=0)
+            {
+                if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) !=0)
+                {
+                    HeaderProto = SAB_HDR_IPV4_OUT_TUNNEL;
+                }
+                else
+                {
+                    HeaderProto = SAB_HDR_IPV4_OUT_TRANSP;
+                }
+            }
+            else
+            {
+                HeaderProto = SAB_HDR_IPV4_OUT_TRANSP_HDRBYPASS;
+            }
+        }
+
+        if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_LONG_SEQ) != 0)
+            ExtSeq = 1;
+    }
+    else
+    {
+        if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_XFRM_API) != 0)
+            ESPProto = SAB_ESP_PROTO_IN_XFRM_CBC;
+        else
+            ESPProto = SAB_ESP_PROTO_IN_CBC;
+        PadBlockByteCount = 4;
+        TokenHeaderWord |= SAB_HEADER_PAD_VERIFY;
+
+        if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_IPV6) !=0)
+        {
+            if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_XFRM_API) != 0)
+            {
+                    HeaderProto = SAB_HDR_IPV6_IN_XFRM;
+            }
+            else if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_PROCESS_IP_HEADERS) !=0)
+            {
+                if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) !=0)
+                {
+                    HeaderProto = SAB_HDR_IPV6_IN_TUNNEL;
+                }
+                else
+                {
+                    HeaderProto = SAB_HDR_IPV6_IN_TRANSP;
+                    TokenHeaderWord |= SAB_HEADER_UPD_HDR;
+                }
+            }
+            else
+            {
+                HeaderProto = SAB_HDR_IPV6_IN_TRANSP_HDRBYPASS;
+            }
+        }
+        else
+        {
+            if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_XFRM_API) != 0)
+            {
+                    HeaderProto = SAB_HDR_IPV4_IN_XFRM;
+            }
+            else if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_PROCESS_IP_HEADERS) !=0)
+            {
+                if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) !=0)
+                {
+                    HeaderProto = SAB_HDR_IPV4_IN_TUNNEL;
+                }
+                else
+                {
+                    HeaderProto = SAB_HDR_IPV4_IN_TRANSP;
+                    TokenHeaderWord |= SAB_HEADER_UPD_HDR;
+                }
+            }
+            else
+            {
+                HeaderProto = SAB_HDR_IPV4_IN_TRANSP_HDRBYPASS;
+            }
+        }
+
+        if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_LONG_SEQ) != 0)
+            ExtSeq = 1;
+        AntiReplay *= SAParamsIPsec_p->SequenceMaskBitCount / 32;
+    }
+    SeqOffset = SAParams_p->OffsetSeqNum;
+
+    switch (SAParams_p->CryptoAlgo)
+    {
+    case SAB_CRYPTO_NULL:
+        IVByteCount = 0;
+                break;
+    case SAB_CRYPTO_DES:
+    case SAB_CRYPTO_3DES:
+        IVByteCount = 8;
+        PadBlockByteCount = 8;
+        break;
+    case SAB_CRYPTO_AES:
+    case SAB_CRYPTO_SM4:
+    case SAB_CRYPTO_BC0:
+        if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CBC)
+        {
+            IVByteCount = 16;
+            PadBlockByteCount = 16;
+        }
+        else
+        {
+            if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+                ESPProto = SAB_ESP_PROTO_OUT_CTR;
+            else
+                ESPProto = SAB_ESP_PROTO_IN_CTR;
+
+            if (SAParams_p->IVSrc == SAB_IV_SRC_IMPLICIT)
+                IVByteCount = 0;
+            else
+                IVByteCount = 8;
+        }
+        break;
+    case SAB_CRYPTO_CHACHA20:
+        if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+            ESPProto = SAB_ESP_PROTO_OUT_CHACHAPOLY;
+        else
+            ESPProto = SAB_ESP_PROTO_IN_CHACHAPOLY;
+
+        if (SAParams_p->IVSrc == SAB_IV_SRC_IMPLICIT)
+            IVByteCount = 0;
+        else
+            IVByteCount = 8;
+        break;
+    default:
+            LOG_CRIT("SABuilder_BuildSA:"
+                     "Unsupported Crypto algorithm\n");
+            return SAB_INVALID_PARAMETER;
+        ;
+    }
+
+    /* For all inbound and CTR mode outbound packets there is
+       only one supported way to obtain the IV, which is already
+       taken care of. Now handle outbound CBC. */
+    if(SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CBC &&
+       SAParams_p->direction == SAB_DIRECTION_OUTBOUND &&
+       SAParams_p->CryptoAlgo != SAB_CRYPTO_NULL)
+    {
+        switch (SAParams_p->IVSrc)
+        {
+        case SAB_IV_SRC_PRNG:
+            TokenHeaderWord |=
+                SAB_HEADER_IV_PRNG;
+            break;
+        case SAB_IV_SRC_DEFAULT:
+        case SAB_IV_SRC_SA: /* No action required */
+        case SAB_IV_SRC_TOKEN:
+            break;
+        default:
+            LOG_CRIT("SABuilder_BuildSA:"
+                     "Unsupported IV source\n");
+            return SAB_INVALID_PARAMETER;
+        }
+    }
+
+    if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND &&
+        SAParamsIPsec_p->PadAlignment >
+        PadBlockByteCount &&
+        SAParamsIPsec_p->PadAlignment <= 256)
+        PadBlockByteCount =
+            SAParamsIPsec_p->PadAlignment;
+
+    switch(SAParams_p->AuthAlgo)
+    {
+    case SAB_AUTH_NULL:
+        ICVByteCount = 0;
+        ExtSeq = 0;
+        if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+            ESPProto = SAB_ESP_PROTO_OUT_NULLAUTH;
+        else
+            ESPProto = SAB_ESP_PROTO_IN_NULLAUTH;
+
+        break;
+            case SAB_AUTH_HMAC_MD5:
+    case SAB_AUTH_HMAC_SHA1:
+    case SAB_AUTH_AES_XCBC_MAC:
+    case SAB_AUTH_AES_CMAC_128:
+        ICVByteCount = 12;
+        break;
+    case SAB_AUTH_HMAC_SHA2_224:
+    case SAB_AUTH_HMAC_SHA2_256:
+    case SAB_AUTH_HMAC_SM3:
+        ICVByteCount = 16;
+        break;
+    case SAB_AUTH_HMAC_SHA2_384:
+        ICVByteCount = 24;
+        break;
+    case SAB_AUTH_HMAC_SHA2_512:
+        ICVByteCount = 32;
+        break;
+    case SAB_AUTH_AES_CCM:
+    case SAB_AUTH_AES_GCM:
+    case SAB_AUTH_AES_GMAC:
+        // All these protocols have a selectable ICV length.
+        if (SAParamsIPsec_p->ICVByteCount == 8 ||
+            SAParamsIPsec_p->ICVByteCount == 12 ||
+            SAParamsIPsec_p->ICVByteCount == 16)
+        {
+            ICVByteCount =
+                        SAParamsIPsec_p->ICVByteCount;
+        }
+        else
+        {
+            ICVByteCount = 16;
+        }
+        switch (SAParams_p->AuthAlgo)
+        {
+            /* These protocols need specialized protocol codes
+               for the token generator.*/
+        case SAB_AUTH_AES_CCM:
+            if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+                ESPProto = SAB_ESP_PROTO_OUT_CCM;
+            else
+                ESPProto = SAB_ESP_PROTO_IN_CCM;
+
+            CCMSalt =
+                (SAParams_p->Nonce_p[0] << 8) |
+                (SAParams_p->Nonce_p[1] << 16) |
+                (SAParams_p->Nonce_p[2] << 24) |
+                SAB_CCM_FLAG_ADATA_L4 |
+                ((ICVByteCount-2)*4);
+            break;
+        case SAB_AUTH_AES_GCM:
+            if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+            {
+                if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_XFRM_API) != 0)
+                    ESPProto = SAB_ESP_PROTO_OUT_XFRM_GCM;
+                else
+                    ESPProto = SAB_ESP_PROTO_OUT_GCM;
+            }
+            else
+            {
+                if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_XFRM_API) != 0)
+                    ESPProto = SAB_ESP_PROTO_IN_XFRM_GCM;
+                else
+                    ESPProto = SAB_ESP_PROTO_IN_GCM;
+            }
+            break;
+        case SAB_AUTH_AES_GMAC:
+            if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+                        ESPProto = SAB_ESP_PROTO_OUT_GMAC;
+            else
+                ESPProto = SAB_ESP_PROTO_IN_GMAC;
+            break;
+        default:
+            ;
+        }
+        break;
+    case SAB_AUTH_POLY1305:
+        ICVByteCount = 16;
+        break;
+    default:
+        LOG_CRIT("SABuilder_BuildSA: unsupported authentication algorithm\n");
+        return SAB_UNSUPPORTED_FEATURE;
+    }
+
+
+    /* Flags variable */
+    if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_IPV6) !=0)
+        flags |= BIT_8;
+    if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_PROCESS_IP_HEADERS) !=0)
+        flags |= BIT_19;
+    if (ExtSeq !=0)
+        flags |= BIT_29;
+    if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_DEC_TTL) != 0)
+        flags |= BIT_27;
+    if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_CLEAR_DF) != 0)
+        flags |= BIT_20;
+    if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_SET_DF) != 0)
+        flags |= BIT_21;
+    if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_REPLACE_DSCP) != 0)
+        flags |= BIT_22;
+    if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_CLEAR_ECN) != 0)
+        flags |= BIT_23;
+    if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_APPEND_SEQNUM) != 0)
+    {
+        if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_LONG_SEQ) != 0)
+            flags |= BIT_25;
+        else
+            flags |= BIT_24;
+    }
+    if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TRANSPORT_NAT) != 0)
+    {
+        if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) != 0)
+        {
+            LOG_CRIT("NAT only for transport\n");
+            return SAB_INVALID_PARAMETER;
+        }
+        if (SAParams_p->direction==SAB_DIRECTION_INBOUND &&
+            SAParamsIPsec_p->SequenceMaskBitCount > 128)
+        {
+            if (SAState_p->fLarge && LargeTransformOffset == 16)
+            {
+                LOG_CRIT(
+                    "SABuilder_BuildSA: Inbound NAT cannot be combined with \n"
+                    " anti-replay mask > 128\n and HMAC-SHA384/512\n");
+                return SAB_UNSUPPORTED_FEATURE;
+            }
+            else if (SAParams_p->OffsetSeqNum == SAB_SEQNUM_HI_FIX_OFFSET &&
+                     SAParamsIPsec_p->SequenceMaskBitCount > 384)
+            {
+                LOG_CRIT(
+                    "SABuilder_BuildSA: Inbound NAT cannot be combined with \n"
+                    " anti-replay mask > 384\n and HMAC-SHA384/512\n");
+                return SAB_UNSUPPORTED_FEATURE;
+            }
+            else
+            {
+                SAState_p->fLarge = true;
+            }
+        }
+        flags |= BIT_28;
+    }
+
+    /* Take care of the VERIFY and CTX token instructions */
+    if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+    {
+        VerifyInstructionWord = SAB_VERIFY_NONE;
+#ifdef SAB_ENABLE_TWO_FIXED_RECORD_SIZES
+        if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_XFRM_API) != 0)
+        {
+            if (SAState_p->fLarge)
+            {
+                CtxInstructionWord = SAB_CTX_NONE + FIRMWARE_EIP207_CS_FLOW_TRC_RECORD_WORD_COUNT + LargeTransformOffset - 1;
+            }
+            else
+#endif
+            {
+                CtxInstructionWord = SAB_CTX_NONE + FIRMWARE_EIP207_CS_FLOW_TRC_RECORD_WORD_COUNT - 1;
+            }
+        }
+        else
+        {
+            CtxInstructionWord = SAB_CTX_OUT_SEQNUM +
+                ((unsigned int)(ExtSeq+1)<<24) + SeqOffset;
+        }
+    }
+    else
+    {
+        VerifyInstructionWord = SAB_VERIFY_PADSPI;
+        if (ICVByteCount > 0)
+        {
+            VerifyInstructionWord += SAB_VERIFY_BIT_H + ICVByteCount;
+        }
+        if (AntiReplay > 0 &&
+            (SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_APPEND_SEQNUM) == 0 &&
+            (SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_XFRM_API) == 0)
+        {
+            /* Skip verification of sequence number in sequence number append
+               mode. */
+            VerifyInstructionWord += SAB_VERIFY_BIT_SEQ;
+        }
+        if (ICVByteCount == 0 || AntiReplay == 0 ||
+            (SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_XFRM_API) != 0)
+        {
+#ifdef SAB_ENABLE_TWO_FIXED_RECORD_SIZES
+            if (SAState_p->fLarge)
+            {
+                CtxInstructionWord = SAB_CTX_NONE + FIRMWARE_EIP207_CS_FLOW_TRC_RECORD_WORD_COUNT + LargeTransformOffset - 1;
+            }
+            else
+#endif
+            {
+                CtxInstructionWord = SAB_CTX_NONE + FIRMWARE_EIP207_CS_FLOW_TRC_RECORD_WORD_COUNT - 1;
+            }
+        }
+        else if (ExtSeq != 0 ||
+                 (AntiReplay != 0 &&
+                  SAParams_p->OffsetSeqNum + 2 == SAParams_p->OffsetSeqMask))
+        {
+            if (AntiReplay > 12)
+                CtxInstructionWord = SAB_CTX_SEQNUM +
+                     + SeqOffset;
+            else
+                CtxInstructionWord = SAB_CTX_SEQNUM +
+                    ((unsigned int)(2+AntiReplay)<<24) + SeqOffset;
+        }
+        else
+        {
+            CtxInstructionWord = SAB_CTX_INSEQNUM +
+                ((unsigned int)(1+AntiReplay)<<24) + SeqOffset;
+        }
+    }
+
+#ifdef SAB_ENABLE_EXTENDED_TUNNEL_HEADER
+    /* Compute the maximum amount by which the packet can be enlarged,
+       so discount that from the output MTU to judge whether a packet can
+       be processed without fragmentation. */
+    if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+    {
+        MTUDiscount = ESP_HDR_LEN + 1 + PadBlockByteCount +
+            IVByteCount + ICVByteCount;
+
+        if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) !=0)
+        {
+            if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_IPV4) !=0)
+                MTUDiscount += IPV4_HDR_LEN;
+            else
+                MTUDiscount += IPV6_HDR_LEN;
+
+            // for IPv4 tunnel, pre-calculate checksum on IP addresses and store them in the transform record
+            // this checksum does not include the final inversion and is performed on data
+            // as they stored in the memory
+            if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_IPV4) !=0)
+            {
+                // protection against NULL pointers
+                if ((SAParamsIPsec_p->SrcIPAddr_p != NULL)&&
+                    (SAParamsIPsec_p->DestIPAddr_p != NULL))
+                {
+                    // add the addresses (in order they are stored in the memory)
+                    CheckSum += get16no(SAParamsIPsec_p->SrcIPAddr_p, 0);
+                    CheckSum += get16no(SAParamsIPsec_p->SrcIPAddr_p, 2);
+                    CheckSum += get16no(SAParamsIPsec_p->DestIPAddr_p, 0);
+                    CheckSum += get16no(SAParamsIPsec_p->DestIPAddr_p, 2);
+
+                    // process the carries
+                    while ((CheckSum>>16) != 0)
+                        CheckSum = (CheckSum>>16) + (CheckSum & 0xffff);
+                }
+            }
+        }
+    }
+    /* Compute the checksum delta for internal NAT operations and for inbound
+       transport NAT-T checksum fixup */
+    if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) == 0 &&
+        (SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_CHECKSUM_FIX) != 0)
+    {
+        uint8_t IPLen = SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_IPV4?4:16;
+        unsigned int i;
+        // Compute source address delta only if both original and new source
+        // addresses are provided, otherwise assume source address is unchanged.
+        if (SAParamsIPsec_p->SrcIPAddr_p != NULL &&
+            SAParamsIPsec_p->OrigSrcIPAddr_p != NULL)
+        {
+            for (i=0; i<IPLen; i+=2)
+            {
+                CheckSum += get16no(SAParamsIPsec_p->SrcIPAddr_p, i);
+                CheckSum += get16no(SAParamsIPsec_p->OrigSrcIPAddr_p, i) ^ 0xffff;
+            }
+        }
+        // Compute destination address delta only if both original and
+        // new destination addresses are provided, otherwise assume
+        // destination address is unchanged.
+        if (SAParamsIPsec_p->DestIPAddr_p != NULL &&
+            SAParamsIPsec_p->OrigDestIPAddr_p != NULL)
+        {
+            for (i=0; i<IPLen; i+=2)
+            {
+                CheckSum += get16no(SAParamsIPsec_p->DestIPAddr_p, i);
+                CheckSum += get16no(SAParamsIPsec_p->OrigDestIPAddr_p, i) ^ 0xffff;
+            }
+        }
+        // process the carries
+        while ((CheckSum>>16) != 0)
+            CheckSum = (CheckSum>>16) + (CheckSum & 0xffff);
+    }
+
+#endif
+
+    /* If NAT-T selected, select other header protocol range */
+    if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_NATT) != 0)
+        HeaderProto += (SAB_HDR_IPV4_OUT_TRANSP_HDRBYPASS_NATT -
+                        SAB_HDR_IPV4_OUT_TRANSP_HDRBYPASS);
+
+    /* Write all parameters to their respective offsets */
+    if (SABuffer_p != NULL)
+    {
+#ifdef SAB_ENABLE_TWO_FIXED_RECORD_SIZES
+        if (SAState_p->fLarge)
+        {
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_FLAGS_WORD_OFFSET +
+                       LargeTransformOffset] = flags;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_HDRPROC_CTX_WORD_OFFSET +
+                       LargeTransformOffset] =
+                SAParamsIPsec_p->ContextRef;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_BYTE_PARAM_WORD_OFFSET +
+                       LargeTransformOffset] =
+                SAB_PACKBYTES(IVByteCount,ICVByteCount,HeaderProto,ESPProto);
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_HDR_WORD_OFFSET +
+                       LargeTransformOffset] = TokenHeaderWord;
+            if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_CHECKSUM_FIX) != 0 &&
+                (SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) == 0)
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_PAD_ALIGN_WORD_OFFSET +
+                    LargeTransformOffset] =
+                    SAB_PACKBYTES(PadBlockByteCount/2,
+                                  0,
+                                  CheckSum & 0xff,
+                                  CheckSum >> 8);
+            else if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) != 0)
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_PAD_ALIGN_WORD_OFFSET +
+                           LargeTransformOffset] =
+                    SAB_PACKBYTES(PadBlockByteCount/2,
+                                  0,
+                                  SAParamsIPsec_p->TTL,
+                                  SAParamsIPsec_p->DSCP);
+            else
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_PAD_ALIGN_WORD_OFFSET
+                           + LargeTransformOffset] =
+                    SAB_PACKBYTES(PadBlockByteCount/2,
+                                  0,
+                                  0,
+                                  0);
+
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_CCM_SALT_WORD_OFFSET +
+                       LargeTransformOffset] = CCMSalt;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_VFY_INST_WORD_OFFSET +
+                       LargeTransformOffset] =
+                VerifyInstructionWord;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_CTX_INST_WORD_OFFSET +
+                       LargeTransformOffset] =
+                CtxInstructionWord;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_LO_WORD_OFFSET +
+                       LargeTransformOffset] = 0;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_HI_WORD_OFFSET +
+                       LargeTransformOffset] = 0;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_LO_WORD_OFFSET +
+                       LargeTransformOffset] = 0;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_HI_WORD_OFFSET +
+                       LargeTransformOffset] = 0;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_PKT_WORD_OFFSET +
+                       LargeTransformOffset] = 0;
+#ifdef SAB_ENABLE_EXTENDED_TUNNEL_HEADER
+            SABuffer_p[FIMRWARE_EIP207_CS_FLOW_TR_NATT_PORTS_WORD_OFFSET +
+                       LargeTransformOffset] =
+                SAB_PACKBYTES(SAParamsIPsec_p->NATTSrcPort >> 8,
+                              SAParamsIPsec_p->NATTSrcPort & 0xff,
+                              SAParamsIPsec_p->NATTDestPort >> 8,
+                              SAParamsIPsec_p->NATTDestPort & 0xff);
+
+            if (HeaderProto == SAB_HDR_IPV4_OUT_TUNNEL ||
+                HeaderProto == SAB_HDR_IPV6_OUT_TUNNEL ||
+                HeaderProto == SAB_HDR_IPV4_OUT_TUNNEL_NATT ||
+                HeaderProto == SAB_HDR_IPV6_OUT_TUNNEL_NATT ||
+                (SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TRANSPORT_NAT) != 0)
+            {
+#ifdef SAB_STRICT_ARGS_CHECK
+                if (SAParamsIPsec_p->SrcIPAddr_p == NULL ||
+                    SAParamsIPsec_p->DestIPAddr_p == NULL)
+                {
+                    LOG_CRIT("SABuilder: NULL pointer tunnel address.\n");
+                    return SAB_INVALID_PARAMETER;
+                }
+#endif
+                SABuilderLib_CopyKeyMat(SABuffer_p,
+                                        FIRMWARE_EIP207_CS_FLOW_TR_TUNNEL_SRC_WORD_OFFSET + LargeTransformOffset,
+                                        SAParamsIPsec_p->SrcIPAddr_p,
+                                        (SAParamsIPsec_p->IPsecFlags&SAB_IPSEC_IPV4)!=0?4:16);
+                SABuilderLib_CopyKeyMat(SABuffer_p,
+                                        FIRMWARE_EIP207_CS_FLOW_TR_TUNNEL_DST_WORD_OFFSET + LargeTransformOffset,
+                                        SAParamsIPsec_p->DestIPAddr_p,
+                                        (SAParamsIPsec_p->IPsecFlags&SAB_IPSEC_IPV4)!=0?4:16);
+
+#ifdef FIRMWARE_EIP207_CS_FLOW_TR_CHECKSUM_WORD_OFFSET
+                // checksum (only for IPv4)
+                if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_IPV4) !=0)
+                    SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_CHECKSUM_WORD_OFFSET +
+                        LargeTransformOffset] = CheckSum;
+#endif
+            }
+
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_PATH_MTU_WORD_OFFSET +
+                       LargeTransformOffset] =  MTUDiscount;
+#endif /* SAB_ENABLE_EXTENDED_TUNNEL_HEADER */
+        }
+        else
+#endif /* SAB_ENABLE_TWO_FIXED_RECORD_SIZES */
+        {
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_FLAGS_WORD_OFFSET] = flags;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_HDRPROC_CTX_WORD_OFFSET] =
+                SAParamsIPsec_p->ContextRef;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_BYTE_PARAM_WORD_OFFSET] =
+                SAB_PACKBYTES(IVByteCount,ICVByteCount,HeaderProto,ESPProto);
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_HDR_WORD_OFFSET] = TokenHeaderWord;
+            if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_CHECKSUM_FIX) != 0 &&
+                (SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) == 0)
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_PAD_ALIGN_WORD_OFFSET] =
+                    SAB_PACKBYTES(PadBlockByteCount/2,
+                                  0,
+                                  CheckSum & 0xff,
+                                  CheckSum >> 8);
+            else if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) != 0)
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_PAD_ALIGN_WORD_OFFSET] =
+                    SAB_PACKBYTES(PadBlockByteCount/2,
+                                  0,
+                                  SAParamsIPsec_p->TTL,
+                                  SAParamsIPsec_p->DSCP);
+            else
+                SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_PAD_ALIGN_WORD_OFFSET] =
+                    SAB_PACKBYTES(PadBlockByteCount/2,
+                                  0,
+                                  0,
+                                  0);
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_CCM_SALT_WORD_OFFSET] = CCMSalt;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_VFY_INST_WORD_OFFSET] =
+                VerifyInstructionWord;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_CTX_INST_WORD_OFFSET] =
+                CtxInstructionWord;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_LO_WORD_OFFSET] = 0;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_HI_WORD_OFFSET] = 0;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_LO_WORD_OFFSET] = 0;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_HI_WORD_OFFSET] = 0;
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_PKT_WORD_OFFSET] = 0;
+#ifdef SAB_ENABLE_EXTENDED_TUNNEL_HEADER
+            SABuffer_p[FIMRWARE_EIP207_CS_FLOW_TR_NATT_PORTS_WORD_OFFSET] =
+                SAB_PACKBYTES(SAParamsIPsec_p->NATTSrcPort >> 8,
+                              SAParamsIPsec_p->NATTSrcPort & 0xff,
+                              SAParamsIPsec_p->NATTDestPort >> 8,
+                              SAParamsIPsec_p->NATTDestPort & 0xff);
+
+            if (HeaderProto == SAB_HDR_IPV4_OUT_TUNNEL ||
+                HeaderProto == SAB_HDR_IPV6_OUT_TUNNEL ||
+                HeaderProto == SAB_HDR_IPV4_OUT_TUNNEL_NATT ||
+                HeaderProto == SAB_HDR_IPV6_OUT_TUNNEL_NATT ||
+                (SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TRANSPORT_NAT) != 0)
+            {
+#ifdef SAB_STRICT_ARGS_CHECK
+                if (SAParamsIPsec_p->SrcIPAddr_p == NULL ||
+                    SAParamsIPsec_p->DestIPAddr_p == NULL)
+                {
+                    LOG_CRIT("SABuilder: NULL pointer tunnel address.\n");
+                    return SAB_INVALID_PARAMETER;
+                }
+#endif
+                SABuilderLib_CopyKeyMat(SABuffer_p,
+                                        FIRMWARE_EIP207_CS_FLOW_TR_TUNNEL_SRC_WORD_OFFSET,
+                                        SAParamsIPsec_p->SrcIPAddr_p,
+                                        (SAParamsIPsec_p->IPsecFlags&SAB_IPSEC_IPV4)!=0?4:16);
+                SABuilderLib_CopyKeyMat(SABuffer_p,
+                                        FIRMWARE_EIP207_CS_FLOW_TR_TUNNEL_DST_WORD_OFFSET,
+                                        SAParamsIPsec_p->DestIPAddr_p,
+                                        (SAParamsIPsec_p->IPsecFlags&SAB_IPSEC_IPV4)!=0?4:16);
+
+#ifdef FIRMWARE_EIP207_CS_FLOW_TR_CHECKSUM_WORD_OFFSET
+                // checksum (only for IPv4)
+                if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_IPV4) !=0)
+                    SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_CHECKSUM_WORD_OFFSET] = CheckSum;
+#endif
+
+            }
+            SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_PATH_MTU_WORD_OFFSET] =  MTUDiscount;
+#endif /* SAB_ENABLE_EXTENDED_TUNNEL_HEADER */
+        }
+    }
+    return SAB_STATUS_OK;
+}
+
+
+#endif /* SAB_ENABLE_IPSEC_EXTENDED */
+
+
+/* end of file sa_builder_extended_ipsec.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_extended_macsec.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_extended_macsec.c
new file mode 100644
index 0000000..38b3312
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_extended_macsec.c
@@ -0,0 +1,187 @@
+/* sa_builder_extended_macsec.c
+ *
+ * MACsec specific functions (for initialization of SABuilder_Params_t
+ * structures and for building the MACsec specific part of an SA) in the
+ * Extended use case.
+ */
+
+/*****************************************************************************
+* Copyright (c) 2013-2020 by Rambus, Inc. and/or its subsidiaries.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+#include "c_sa_builder.h"
+#ifdef SAB_ENABLE_MACSEC_EXTENDED
+#include "sa_builder_extended_internal.h"
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+#include "basic_defs.h"
+#include "log.h"
+#include "sa_builder_internal.h" /* SABuilder_SetMACsecParams */
+#include "sa_builder_macsec.h"
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+#define SAB_MACSEC_ETHER_TYPE 0x88e5
+/* Various bits in the TCI byte */
+#define SAB_MACSEC_TCI_ES  BIT_6
+#define SAB_MACSEC_TCI_SC  BIT_5
+#define SAB_MACSEC_TCI_SCB BIT_4
+#define SAB_MACSEC_TCI_E   BIT_3
+#define SAB_MACSEC_TCI_C   BIT_2
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * SABuilder_SetExtendedMACsecParams
+ *
+ * Fill in MACsec-specific extensions into the SA.for Extended.
+ *
+ * SAParams_p (input)
+ *   The SA parameters structure from which the SA is derived.
+ * SAState_p (input, output)
+ *   Variables containing information about the SA being generated/
+ * SABuffer_p (input, output).
+ *   The buffer in which the SA is built. If NULL, no SA will be built, but
+ *   state variables in SAState_p will still be updated.
+ *
+ * Return:
+ * SAB_STATUS_OK on success
+ * SAB_INVALID_PARAMETER when SAParams_p is invalid, or if any of
+ *    the buffer arguments  is a null pointer while the corresponding buffer
+ *    would be required for the operation.
+ * SAB_UNSUPPORTED_FEATURE when SAParams_p describes an operations that
+ *    is not supported on the hardware for which this SA builder
+ *    is configured.
+ */
+SABuilder_Status_t
+SABuilder_SetExtendedMACsecParams(SABuilder_Params_t *const SAParams_p,
+                         SABuilder_State_t * const SAState_p,
+                         uint32_t * const SABuffer_p)
+{
+    SABuilder_Params_MACsec_t *SAParamsMACsec_p =
+        (SABuilder_Params_MACsec_t *)(SAParams_p->ProtocolExtension_p);
+    uint32_t TokenHeaderWord = SAB_HEADER_DEFAULT;
+    SABuilder_ESPProtocol_t ESPProto;
+    SABuilder_HeaderProtocol_t HeaderProto;
+    uint8_t IVByteCount;
+    uint8_t ICVByteCount;
+    uint8_t SeqOffset;
+    uint8_t TCI; /* TCI byte in SECtag */
+    uint32_t flags = 0;
+    uint32_t VerifyInstructionWord, CtxInstructionWord;
+
+    IDENTIFIER_NOT_USED(SAState_p);
+
+    if (SAParamsMACsec_p == NULL)
+    {
+        LOG_CRIT("SABuilder: MACsec extension pointer is null\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    SeqOffset = SAParams_p->OffsetSeqNum;
+    ICVByteCount = 16;
+    TCI = SAParamsMACsec_p->AN;
+    if ((SAParamsMACsec_p->MACsecFlags & SAB_MACSEC_ES) != 0)
+    {
+        TCI |= SAB_MACSEC_TCI_ES;
+    }
+    if ((SAParamsMACsec_p->MACsecFlags & SAB_MACSEC_SC) != 0)
+    {
+        IVByteCount = 8;
+        TCI |= SAB_MACSEC_TCI_SC;
+    }
+    else
+    {
+        IVByteCount = 0;
+    }
+    if ((SAParamsMACsec_p->MACsecFlags & SAB_MACSEC_SCB) != 0)
+    {
+        TCI |= SAB_MACSEC_TCI_SCB;
+    }
+
+    if (SAParams_p->AuthAlgo == SAB_AUTH_AES_GCM)
+        TCI |= SAB_MACSEC_TCI_E | SAB_MACSEC_TCI_C;
+
+    if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+    {
+        HeaderProto = SAB_HDR_MACSEC_OUT;
+        if (SAParams_p->AuthAlgo == SAB_AUTH_AES_GCM)
+            ESPProto = SAB_MACSEC_PROTO_OUT_GCM;
+        else
+            ESPProto = SAB_MACSEC_PROTO_OUT_GMAC;
+        VerifyInstructionWord = SAB_VERIFY_NONE;
+        CtxInstructionWord = SAB_CTX_OUT_SEQNUM +
+            ((unsigned int)(1<<24)) + SeqOffset;
+    }
+    else
+    {
+        HeaderProto = SAB_HDR_MACSEC_IN;
+        if (SAParams_p->AuthAlgo == SAB_AUTH_AES_GCM)
+            ESPProto = SAB_MACSEC_PROTO_IN_GCM;
+        else
+            ESPProto = SAB_MACSEC_PROTO_IN_GMAC;
+        VerifyInstructionWord = SAB_VERIFY_NONE + SAB_VERIFY_BIT_H +
+            SAB_VERIFY_BIT_SEQ + ICVByteCount;
+        CtxInstructionWord = SAB_CTX_SEQNUM +
+            ((unsigned int)(1<<24)) + SeqOffset;
+    }
+
+    /* Write all parameters to their respective offsets */
+    if (SABuffer_p != NULL)
+    {
+        /* Do not support large transform records as Macsec will never
+           use HMAC-SHA512 */
+        SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_FLAGS_WORD_OFFSET] = flags;
+        SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_HDRPROC_CTX_WORD_OFFSET] =
+            SAParamsMACsec_p->ContextRef;
+        SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_BYTE_PARAM_WORD_OFFSET] =
+            SAB_PACKBYTES(IVByteCount,ICVByteCount,HeaderProto,ESPProto);
+        SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_HDR_WORD_OFFSET] = TokenHeaderWord;
+        SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_PAD_ALIGN_WORD_OFFSET] =
+            SAB_PACKBYTES(SAB_MACSEC_ETHER_TYPE>>8,
+                          SAB_MACSEC_ETHER_TYPE &0xff, TCI, 0);
+        SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_CCM_SALT_WORD_OFFSET] =
+            SAParamsMACsec_p->ConfOffset;
+        SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_VFY_INST_WORD_OFFSET] =
+                VerifyInstructionWord;
+        SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TK_CTX_INST_WORD_OFFSET] =
+            CtxInstructionWord;
+        SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_LO_WORD_OFFSET] = 0;
+        SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_HI_WORD_OFFSET] = 0;
+        SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_LO_WORD_OFFSET] = 0;
+        SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_HI_WORD_OFFSET] = 0;
+        SABuffer_p[FIRMWARE_EIP207_CS_FLOW_TR_STAT_PKT_WORD_OFFSET] = 0;
+
+        SABuilderLib_CopyKeyMat(SABuffer_p,
+                                FIRMWARE_EIP207_CS_FLOW_TR_TUNNEL_SRC_WORD_OFFSET,
+                                SAParamsMACsec_p->SCI_p, 8);
+    }
+    return SAB_STATUS_OK;
+}
+
+#endif /* SAB_ENABLE_MACSEC_EXTENDED */
+
+
+/* end of file sa_builder_extended_dtls.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_ipsec.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_ipsec.c
new file mode 100644
index 0000000..eb5144d
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_ipsec.c
@@ -0,0 +1,722 @@
+/* sa_builder_ipsec.c
+ *
+ * IPsec specific functions (for initialization of SABuilder_Params_t
+ * structures and for building the IPSec specifc part of an SA.).
+ */
+
+/*****************************************************************************
+* Copyright (c) 2011-2021 by Rambus, Inc. and/or its subsidiaries.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+#include "sa_builder_ipsec.h"
+#include "sa_builder_internal.h" /* SABuilder_SetIpsecParams */
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+#include "c_sa_builder.h"
+#include "basic_defs.h"
+#include "log.h"
+
+#ifdef SAB_ENABLE_PROTO_IPSEC
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+#ifdef SAB_ENABLE_1024BIT_SEQMASK
+#define SAB_SEQUENCE_MAXBITS 1024
+#elif defined(SAB_ENABLE_384BIT_SEQMASK)
+#define SAB_SEQUENCE_MAXBITS 384
+#else
+#define SAB_SEQUENCE_MAXBITS 128
+#endif
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+/*----------------------------------------------------------------------------
+ * SABuilder_Init_ESP
+ *
+ * This function initializes the SABuilder_Params_t data structure and its
+ * SABuilder_Params_IPsec_t extension with sensible defaults for ESP
+ * processing.
+ *
+ * SAParams_p (output)
+ *   Pointer to SA parameter structure to be filled in.
+ * SAParamsIPsec_p (output)
+ *   Pointer to IPsec parameter extension to be filled in
+ * spi (input)
+ *   SPI of the newly created parameter structure (must not be zero).
+ * TunnelTransport (input)
+ *   Must be one of SAB_IPSEC_TUNNEL or SAB_IPSEC_TRANSPORT.
+ * IPMode (input)
+ *   Must be one of SAB_IPSEC_IPV4 or SAB_IPSEC_IPV6.
+ * direction (input)
+ *   Must be one of SAB_DIRECTION_INBOUND or SAB_DIRECTION_OUTBOUND.
+ *
+ * Both the crypto and the authentication algorithm are initialized to
+ * NULL, which is illegal according to the IPsec standards, but it is
+ * possible to use this setting for debug purposes.
+ *
+ * Both the SAParams_p and SAParamsIPsec_p input parameters must point
+ * to valid storage where variables of the appropriate type can be
+ * stored. This function initializes the link from SAParams_p to
+ * SAParamsIPsec_p.
+ *
+ * Return:
+ * SAB_STATUS_OK on success
+ * SAB_INVALID_PARAMETER when one of the pointer parameters is NULL
+ *   or the remaining parameters have illegal values.
+ */
+SABuilder_Status_t
+SABuilder_Init_ESP(
+    SABuilder_Params_t * const SAParams_p,
+    SABuilder_Params_IPsec_t * const SAParamsIPsec_p,
+    const uint32_t spi,
+    const uint32_t TunnelTransport,
+    const uint32_t IPMode,
+    const SABuilder_Direction_t direction)
+{
+    int i;
+#ifdef SAB_STRICT_ARGS_CHECK
+    if (SAParams_p == NULL || SAParamsIPsec_p == NULL)
+    {
+        LOG_CRIT("SABuilder_Init_ESP: NULL pointer parameter supplied.\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    if (spi == 0)
+    {
+        LOG_CRIT("SABuilder_Init_ESP: SPI may not be 0.\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    if (TunnelTransport != SAB_IPSEC_TUNNEL &&
+        TunnelTransport != SAB_IPSEC_TRANSPORT)
+    {
+        LOG_CRIT("SABuilder_Init_ESP: Invalid TunnelTransport.\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    if (IPMode != SAB_IPSEC_IPV4 && IPMode != SAB_IPSEC_IPV6)
+    {
+        LOG_CRIT("SABuilder_Init_ESP: Invalid IPMode.\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    if (direction != SAB_DIRECTION_OUTBOUND &&
+        direction != SAB_DIRECTION_INBOUND)
+    {
+        LOG_CRIT("SABuilder_Init_ESP: Invalid direction.\n");
+        return SAB_INVALID_PARAMETER;
+    }
+#endif
+
+    SAParams_p->protocol = SAB_PROTO_IPSEC;
+    SAParams_p->direction = direction;
+    SAParams_p->ProtocolExtension_p = (void*)SAParamsIPsec_p;
+    SAParams_p->flags = 0;
+    SAParams_p->RedirectInterface = 0;
+
+    SAParams_p->CryptoAlgo = SAB_CRYPTO_NULL;
+    SAParams_p->CryptoMode = SAB_CRYPTO_MODE_CBC;
+    SAParams_p->IVSrc = SAB_IV_SRC_DEFAULT;
+    SAParams_p->CryptoParameter = 0;
+    SAParams_p->KeyByteCount = 0;
+    SAParams_p->Key_p = NULL;
+    SAParams_p->IV_p = NULL;
+    SAParams_p->Nonce_p = NULL;
+
+    SAParams_p->AuthAlgo = SAB_AUTH_NULL;
+    SAParams_p->AuthKey1_p = NULL;
+    SAParams_p->AuthKey2_p = NULL;
+    SAParams_p->AuthKey3_p = NULL;
+    SAParams_p->AuthKeyByteCount = 0;
+
+    SAParams_p->OffsetARC4StateRecord = 0;
+    SAParams_p->CW0 = 0;
+    SAParams_p->CW1 = 0;
+    SAParams_p->OffsetDigest0 = 0;
+    SAParams_p->OffsetDigest1 = 0;
+    SAParams_p->OffsetSeqNum = 0;
+    SAParams_p->OffsetSeqMask = 0;
+    SAParams_p->OffsetIV = 0;
+    SAParams_p->OffsetIJPtr = 0;
+    SAParams_p->OffsetARC4State = 0;
+    SAParams_p->SeqNumWord32Count = 0;
+    SAParams_p->SeqMaskWord32Count = 0;
+    SAParams_p->IVWord32Count = 0;
+
+    SAParamsIPsec_p->spi = spi;
+    SAParamsIPsec_p->IPsecFlags = SAB_IPSEC_ESP | TunnelTransport | IPMode;
+    SAParamsIPsec_p->SeqNum = 0;
+    SAParamsIPsec_p->SeqNumHi = 0;
+    SAParamsIPsec_p->SeqMask[0] = 1;
+    for (i=1; i<SA_SEQ_MASK_WORD_COUNT; i++)
+        SAParamsIPsec_p->SeqMask[i] = 0;
+    SAParamsIPsec_p->PadAlignment = 0;
+    SAParamsIPsec_p->ICVByteCount = 0;
+    SAParamsIPsec_p->SrcIPAddr_p = NULL;
+    SAParamsIPsec_p->DestIPAddr_p = NULL;
+    SAParamsIPsec_p->OrigSrcIPAddr_p = NULL;
+    SAParamsIPsec_p->OrigDestIPAddr_p = NULL;
+    SAParamsIPsec_p->NATTSrcPort = 4500;
+    SAParamsIPsec_p->NATTDestPort = 4500;
+    SAParamsIPsec_p->ContextRef = 0;
+    SAParamsIPsec_p->TTL = 240;
+    SAParamsIPsec_p->DSCP = 0;
+    SAParamsIPsec_p->SequenceMaskBitCount = 0;
+    return SAB_STATUS_OK;
+}
+
+
+/*----------------------------------------------------------------------------
+ * SABuilder_SetIPsecParams
+ *
+ * Fill in IPsec-specific extensions into the SA.
+ *
+ * SAParams_p (input, updated)
+ *   The SA parameters structure from which the SA is derived.
+ * SAState_p (input, output)
+ *   Variables containing information about the SA being generated/
+ * SABuffer_p (output).
+ *   The buffer in which the SA is built. If NULL, no SA will be built, but
+ *   state variables in SAState_p will still be updated.
+ *
+ * Return:
+ * SAB_STATUS_OK on success
+ * SAB_INVALID_PARAMETER when SAParams_p is invalid, or if any of
+ *    the buffer arguments  is a null pointer while the corresponding buffer
+ *    would be required for the operation.
+ * SAB_UNSUPPORTED_FEATURE when SAParams_p describes an operations that
+ *    is not supported on the hardware for which this SA builder
+ *    is configured.
+ */
+SABuilder_Status_t
+SABuilder_SetIPsecParams(SABuilder_Params_t *const SAParams_p,
+                         SABuilder_State_t * const SAState_p,
+                         uint32_t * const SABuffer_p)
+{
+    unsigned int IVOffset = 0;
+    SABuilder_Params_IPsec_t *SAParamsIPsec_p;
+    bool fFixedSeqOffset = false;
+    SAParamsIPsec_p = (SABuilder_Params_IPsec_t *)
+        (SAParams_p->ProtocolExtension_p);
+    if (SAParamsIPsec_p == NULL)
+    {
+        LOG_CRIT("SABuilder: IPsec extension pointer is null\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    /* First check whether AH or ESP flags are correct */
+
+    if ( (SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_AH) != 0)
+    {
+#ifdef SAB_ENABLE_IPSEC_AH
+        if (SAParams_p->CryptoAlgo != SAB_CRYPTO_NULL ||
+            (SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_ESP) != 0)
+        {
+            LOG_CRIT("SABuilder: AH does not support crypto.\n");
+            return SAB_INVALID_PARAMETER;
+        }
+#else
+        LOG_CRIT("SABuilder: AH unsupported..\n");
+        return SAB_INVALID_PARAMETER;
+#endif
+    }
+
+#ifndef SAB_ENABLE_IPSEC_ESP
+    if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_ESP) != 0)
+    {
+        LOG_CRIT("SABuilder: ESP unsupported.\n");
+        return SAB_INVALID_PARAMETER;
+    }
+#endif
+
+    /* Check for supported algorithms and crypto modes in IPsec */
+    if ((SAParams_p->CryptoAlgo != SAB_CRYPTO_NULL &&
+         SAParams_p->CryptoAlgo != SAB_CRYPTO_DES &&
+         SAParams_p->CryptoAlgo != SAB_CRYPTO_3DES &&
+         SAParams_p->CryptoAlgo != SAB_CRYPTO_AES &&
+         SAParams_p->CryptoAlgo != SAB_CRYPTO_CHACHA20 &&
+         SAParams_p->CryptoAlgo != SAB_CRYPTO_SM4 &&
+         SAParams_p->CryptoAlgo != SAB_CRYPTO_BC0) ||
+        (SAParams_p->CryptoAlgo != SAB_CRYPTO_NULL && (
+            SAParams_p->CryptoMode != SAB_CRYPTO_MODE_CBC &&
+            SAParams_p->CryptoMode != SAB_CRYPTO_MODE_CTR &&
+            SAParams_p->CryptoMode != SAB_CRYPTO_MODE_GCM &&
+            SAParams_p->CryptoMode != SAB_CRYPTO_MODE_GMAC &&
+            SAParams_p->CryptoMode != SAB_CRYPTO_MODE_CCM &&
+            SAParams_p->CryptoMode != SAB_CRYPTO_MODE_CHACHA_CTR32)))
+    {
+        LOG_CRIT("SABuilder: IPsec: crypto algorithm/mode not supported\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    /* Check for supported authentication algorithms in IPsec */
+    if (SAParams_p->AuthAlgo != SAB_AUTH_NULL &&
+        SAParams_p->AuthAlgo != SAB_AUTH_HMAC_MD5 &&
+        SAParams_p->AuthAlgo != SAB_AUTH_HMAC_SHA1 &&
+        SAParams_p->AuthAlgo != SAB_AUTH_HMAC_SHA2_256 &&
+        SAParams_p->AuthAlgo != SAB_AUTH_HMAC_SHA2_384 &&
+        SAParams_p->AuthAlgo != SAB_AUTH_HMAC_SHA2_512 &&
+        SAParams_p->AuthAlgo != SAB_AUTH_AES_XCBC_MAC &&
+        SAParams_p->AuthAlgo != SAB_AUTH_AES_CMAC_128 &&
+        SAParams_p->AuthAlgo != SAB_AUTH_AES_GCM &&
+        SAParams_p->AuthAlgo != SAB_AUTH_AES_GMAC &&
+        SAParams_p->AuthAlgo != SAB_AUTH_AES_CCM &&
+        SAParams_p->AuthAlgo != SAB_AUTH_POLY1305 &&
+        SAParams_p->AuthAlgo != SAB_AUTH_HMAC_SM3)
+    {
+        LOG_CRIT("SABuilder: IPsec: auth algorithm not supported\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    /* Add SPI to SA record */
+    if (SABuffer_p != NULL)
+        SABuffer_p[SAState_p->CurrentOffset] = SAParamsIPsec_p->spi;
+    SAState_p->CurrentOffset += 1;
+
+    /* Determine whether we will have a fixed sequence number offset */
+    if (SAParams_p->direction == SAB_DIRECTION_INBOUND)
+    {
+        /* Determine size of sequence number mask in bits */
+        if (SAParamsIPsec_p->SequenceMaskBitCount == 0)
+        {
+            /* Some flags indicate specific mask sizes */
+            if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_MASK_384) != 0)
+            {
+                SAParamsIPsec_p->SequenceMaskBitCount = 384;
+            }
+            else if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_MASK_256) != 0)
+            {
+                SAParamsIPsec_p->SequenceMaskBitCount = 256;
+            }
+            else if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_MASK_128) != 0)
+            {
+                SAParamsIPsec_p->SequenceMaskBitCount = 128;
+            }
+            else if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_MASK_32) != 0)
+            {
+                SAParamsIPsec_p->SequenceMaskBitCount = 32;
+            }
+            else
+            {
+                SAParamsIPsec_p->SequenceMaskBitCount = 64;
+            }
+        }
+        if (SAParamsIPsec_p->SequenceMaskBitCount > SAB_SEQUENCE_MAXBITS ||
+            (SAParamsIPsec_p->SequenceMaskBitCount & 0x1f) != 0)
+        {
+            LOG_CRIT("SABuilder: Illegal sequence mask size.\n");
+            return SAB_INVALID_PARAMETER;
+        }
+#ifdef SAB_ENABLE_DEFAULT_FIXED_OFFSETS
+        fFixedSeqOffset = true;
+#else
+        if (SAParamsIPsec_p->SequenceMaskBitCount > 128 ||
+            (SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_FIXED_SEQ_OFFSET) != 0)
+        {
+            fFixedSeqOffset = true;
+        }
+#endif
+        if (SAParamsIPsec_p->SequenceMaskBitCount ==32)
+        {
+            fFixedSeqOffset = false; /* not supported for 32-bit mask */
+        }
+    }
+
+    if (fFixedSeqOffset)
+    {
+        /* Use a fixed sequence number offset for inbound if the hardware
+           supports it. */
+        /* Take care to insert the IV (nonce) just after the SPI. */
+        IVOffset = SAState_p->CurrentOffset;
+
+        /* Select one of two fixed offsets for the sequence number */
+        if (SAState_p->CurrentOffset < SAB_SEQNUM_LO_FIX_OFFSET)
+        {
+            SAState_p->CurrentOffset = SAB_SEQNUM_LO_FIX_OFFSET;
+        }
+        else
+        {
+            SAState_p->CurrentOffset = SAB_SEQNUM_HI_FIX_OFFSET;
+        }
+
+        /* Add sequence number */
+        SAParams_p->OffsetSeqNum = SAState_p->CurrentOffset;
+
+        if (SABuffer_p != NULL)
+            SABuffer_p[SAState_p->CurrentOffset] = SAParamsIPsec_p->SeqNum;
+
+        if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_LONG_SEQ) != 0)
+        {
+            if (SABuffer_p != NULL)
+                SABuffer_p[SAState_p->CurrentOffset+1] = SAParamsIPsec_p->SeqNumHi;
+            SAState_p->CW0 |= SAB_CW0_SPI | SAB_CW0_SEQNUM_64_FIX;
+            SAParams_p->SeqNumWord32Count = 2;
+        }
+        else
+        {
+            SAState_p->CW0 |= SAB_CW0_SPI | SAB_CW0_SEQNUM_32_FIX;
+            SAParams_p->SeqNumWord32Count = 1;
+        }
+        // Always reserve 2 words for the sequence number.
+        SAState_p->CurrentOffset += 2;
+    }
+    else
+    {
+        /* Add sequence number */
+        SAParams_p->OffsetSeqNum = SAState_p->CurrentOffset;
+
+        if (SABuffer_p != NULL)
+            SABuffer_p[SAState_p->CurrentOffset] = SAParamsIPsec_p->SeqNum;
+        SAState_p->CurrentOffset += 1;
+        if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_LONG_SEQ) != 0)
+        {
+            if (SABuffer_p != NULL)
+                SABuffer_p[SAState_p->CurrentOffset] = SAParamsIPsec_p->SeqNumHi;
+            SAState_p->CW0 |= SAB_CW0_SPI | SAB_CW0_SEQNUM_64;
+            SAState_p->CurrentOffset += 1;
+
+            SAParams_p->SeqNumWord32Count = 2;
+        }
+        else
+        {
+            SAState_p->CW0 |= SAB_CW0_SPI | SAB_CW0_SEQNUM_32;
+            SAParams_p->SeqNumWord32Count = 1;
+        }
+    }
+
+    if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+    {
+
+        if (SAParams_p->CryptoAlgo==SAB_CRYPTO_NULL &&
+            SAParams_p->AuthAlgo==SAB_AUTH_NULL)
+            SAState_p->CW0 |= SAB_CW0_TOP_NULL_OUT;
+        else if (SAParams_p->CryptoAlgo==SAB_CRYPTO_NULL)
+            SAState_p->CW0 |= SAB_CW0_TOP_HASH_OUT;
+        else if (SAParams_p->AuthAlgo==SAB_AUTH_NULL)
+            SAState_p->CW0 |= SAB_CW0_TOP_ENCRYPT;
+        else if (SAParams_p->AuthAlgo==SAB_AUTH_AES_CCM ||
+                 SAParams_p->AuthAlgo==SAB_AUTH_AES_GMAC)
+            SAState_p->CW0 |= SAB_CW0_TOP_HASH_ENCRYPT;
+        else
+            SAState_p->CW0 |= SAB_CW0_TOP_ENCRYPT_HASH;
+
+        /* Some versions of the hardware can update the sequence number
+           early, so multiple engines can operate in parallel. */
+        SAState_p->CW1 |= SAB_CW1_EARLY_SEQNUM_UPDATE;
+        SAState_p->CW1 |= SAParams_p->OffsetSeqNum << 24;
+
+        SAState_p->CW1 |= SAB_CW1_SEQNUM_STORE;
+        if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_NO_ANTI_REPLAY)!=0 &&
+            (SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_LONG_SEQ) == 0)
+        {
+            /* Disable outbound sequence number rollover checking by putting
+               an 64-sequence number in the SA. This will not be
+               used in authentication (no ESN) */
+            if (SABuffer_p != NULL)
+                SABuffer_p[SAState_p->CurrentOffset] = 0;
+            SAState_p->CW0 |= SAB_CW0_SEQNUM_64;
+            SAState_p->CurrentOffset += 1;
+        }
+
+        /* Take care of IV and nonce */
+        if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CTR ||
+            SAParams_p->CryptoMode == SAB_CRYPTO_MODE_GCM ||
+            SAParams_p->CryptoMode == SAB_CRYPTO_MODE_GMAC ||
+            SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CCM ||
+            SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CHACHA_CTR32)
+        {
+            if (SAParams_p->IVSrc == SAB_IV_SRC_DEFAULT)
+                SAParams_p->IVSrc = SAB_IV_SRC_SEQ;
+
+            /* Add nonce, always present */
+            SAState_p->CW1 |= SAB_CW1_IV0;
+            if (SABuffer_p != NULL)
+            {
+                if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CCM)
+                    SABuffer_p[SAState_p->CurrentOffset] =
+                        (SAParams_p->Nonce_p[0] << 8)  |
+                        (SAParams_p->Nonce_p[1] << 16) |
+                        (SAParams_p->Nonce_p[2] << 24) | SAB_CCM_FLAG_L4;
+                else
+                    SABuilderLib_CopyKeyMat(SABuffer_p,
+                                            SAState_p->CurrentOffset,
+                                            SAParams_p->Nonce_p,
+                                            sizeof(uint32_t));
+            }
+            SAState_p->CurrentOffset +=1;
+
+            if (SAParams_p->IVSrc == SAB_IV_SRC_SEQ)
+            {
+                SAState_p->CW1 |= SAB_CW1_IV_ORIG_SEQ;
+            }
+            else if (SAParams_p->IVSrc == SAB_IV_SRC_IMPLICIT)
+            {
+                SAState_p->CW1 |= SAB_CW1_IV_INCR_SEQ;
+            }
+            else if (SAParams_p->IVSrc == SAB_IV_SRC_XORSEQ)
+            {
+                SAState_p->CW1 |= SAB_CW1_IV_CTR|SAB_CW1_CRYPTO_NONCE_XOR;
+                SAState_p->CW1 |= SAB_CW1_IV0|SAB_CW1_IV1|SAB_CW1_IV2;
+                SABuilderLib_CopyKeyMat(SABuffer_p,
+                                        SAState_p->CurrentOffset,
+                                        SAParams_p->IV_p,
+                                        2*sizeof(uint32_t));
+                SAState_p->CurrentOffset +=2;
+            }
+            else if (SAParams_p->IVSrc == SAB_IV_SRC_SA)
+            {
+                SAState_p->CW1 |= SAB_CW1_IV_CTR | SAB_CW1_IV1 | SAB_CW1_IV2;
+#ifdef SAB_STRICT_ARGS_CHECK
+                if (SAParams_p->IV_p == NULL)
+                {
+                    LOG_CRIT("SABuilder: NULL pointer IV.\n");
+                    return SAB_INVALID_PARAMETER;
+                }
+#endif
+                SAParams_p->OffsetIV = SAState_p->CurrentOffset;
+                SAParams_p->IVWord32Count = 2;
+
+                SABuilderLib_CopyKeyMat(SABuffer_p, SAState_p->CurrentOffset,
+                                        SAParams_p->IV_p, 8);
+                SAState_p->CurrentOffset += 2;
+            }
+            else
+            {
+                SAState_p->CW1 |= SAB_CW1_IV_CTR;
+            }
+            if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CCM)
+            {
+                /* Add 0 counter field (IV3) */
+                SAState_p->CW1 |= SAB_CW1_IV3;
+                if(SABuffer_p != NULL)
+                    SABuffer_p[SAState_p->CurrentOffset] = 0;
+                SAState_p->CurrentOffset+=1;
+            }
+        }
+        else if (SAState_p->IVWords > 0)
+        { /* CBC mode, non-null */
+            if (SAParams_p->IVSrc == SAB_IV_SRC_DEFAULT)
+                SAParams_p->IVSrc = SAB_IV_SRC_PRNG;
+            SAState_p->CW1 |= SAB_CW1_IV_FULL;
+            if (SAParams_p->IVSrc == SAB_IV_SRC_SA)
+            {
+                SAState_p->CW1 |= SAB_CW1_IV0 | SAB_CW1_IV1;
+                    if(SAState_p->IVWords == 4)
+                        SAState_p->CW1 |= SAB_CW1_IV2 | SAB_CW1_IV3;
+#ifdef SAB_STRICT_ARGS_CHECK
+                    if (SAParams_p->IV_p == NULL)
+                    {
+                        LOG_CRIT("SABuilder: NULL pointer IV.\n");
+                        return SAB_INVALID_PARAMETER;
+                    }
+#endif
+                    SAParams_p->OffsetIV = SAState_p->CurrentOffset;
+                    SAParams_p->IVWord32Count = SAState_p->IVWords;
+
+                    SABuilderLib_CopyKeyMat(SABuffer_p,
+                                       SAState_p->CurrentOffset,
+                                       SAParams_p->IV_p,
+                                       SAState_p->IVWords * sizeof(uint32_t));
+                    SAState_p->CurrentOffset += SAState_p->IVWords;
+            }
+        }
+    }
+    else
+    {   /* Inbound */
+        unsigned int InputMaskWordCount =
+            SAParamsIPsec_p->SequenceMaskBitCount / 32;
+        unsigned int AllocMaskWordCount;
+
+        if (SAParams_p->CryptoAlgo==SAB_CRYPTO_NULL &&
+            SAParams_p->AuthAlgo==SAB_AUTH_NULL)
+            SAState_p->CW0 |= SAB_CW0_TOP_NULL_IN;
+        else if (SAParams_p->CryptoAlgo==SAB_CRYPTO_NULL)
+            SAState_p->CW0 |= SAB_CW0_TOP_HASH_IN;
+        else if (SAParams_p->AuthAlgo==SAB_AUTH_NULL)
+            SAState_p->CW0 |= SAB_CW0_TOP_DECRYPT;
+        else if (SAParams_p->AuthAlgo==SAB_AUTH_AES_CCM)
+            SAState_p->CW0 |= SAB_CW0_TOP_DECRYPT_HASH;
+        else
+            SAState_p->CW0 |= SAB_CW0_TOP_HASH_DECRYPT;
+
+        SAState_p->CW1 |= SAB_CW1_PAD_IPSEC;
+
+        /* Add sequence mask  Always add one even with no anti-replay*/
+        SAParams_p->OffsetSeqMask = SAState_p->CurrentOffset;
+
+        if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_APPEND_SEQNUM) != 0)
+            SAState_p->CW0 |= SAB_CW0_SEQNUM_APPEND;
+
+        /* Determine the required hardware mask size in words and set
+           control words accordingly. */
+        if (InputMaskWordCount  == 1)
+        {
+            AllocMaskWordCount = 1;
+            SAState_p->CW0 |= SAB_CW0_MASK_32;
+        }
+        else if (InputMaskWordCount  == 2)
+        {
+            AllocMaskWordCount = 2;
+            if (fFixedSeqOffset)
+            {
+                SAState_p->CW0 |= SAB_CW0_MASK_64_FIX;
+            }
+            else
+            {
+                SAState_p->CW0 |= SAB_CW0_MASK_64;
+            }
+        }
+        else if (InputMaskWordCount <= 4)
+        {
+            AllocMaskWordCount = 4;
+            if (fFixedSeqOffset)
+            {
+                SAState_p->CW0 |= SAB_CW0_MASK_128_FIX;
+            }
+            else
+            {
+                SAState_p->CW0 |= SAB_CW0_MASK_128;
+            }
+        }
+#ifdef SAB_ENABLE_256BIT_SEQMASK
+        else if (InputMaskWordCount <= 8)
+        {
+            AllocMaskWordCount = 8;
+            SAState_p->CW0 |= SAB_CW0_MASK_256_FIX;
+        }
+#endif
+        else if (InputMaskWordCount <= 12)
+        {
+            AllocMaskWordCount = 12;
+            SAState_p->CW0 |= SAB_CW0_MASK_384_FIX;
+        }
+        else
+        {
+            AllocMaskWordCount = 32;
+            SAState_p->CW0 |= SAB_CW0_MASK_1024_FIX;
+            SAState_p->fLargeMask = true;
+            SAState_p->fLarge = true;
+        }
+        if(SABuffer_p != NULL)
+        {
+            unsigned int i;
+            if (AllocMaskWordCount <= SA_SEQ_MASK_WORD_COUNT)
+            {
+                for (i = 0; i < InputMaskWordCount; i++)
+                    SABuffer_p[SAState_p->CurrentOffset+i] =
+                        SAParamsIPsec_p->SeqMask[i];
+                /* If the input mask is smaller than the one picked by the
+                   hardware, fill the remaining words with all-one, the
+                   hardware will treat these words as invalid.
+                */
+                for (i= InputMaskWordCount; i < AllocMaskWordCount; i++)
+                    SABuffer_p[SAState_p->CurrentOffset+i] = 0xffffffff;
+            }
+            else
+            {
+                /* Mask too big to store in parameter structure.
+                   Also need to shift the '1' bit to correct position */
+                uint32_t WordIdx, BitMask;
+                for (i= 0; i < AllocMaskWordCount; i++)
+                    SABuffer_p[SAState_p->CurrentOffset+i] = 0;
+                WordIdx = (SAParamsIPsec_p->SeqNum & MASK_10_BITS) >> 5;
+                BitMask = 1 << (SAParamsIPsec_p->SeqNum & MASK_5_BITS);
+                SABuffer_p[SAState_p->CurrentOffset+WordIdx] = BitMask;
+            }
+        }
+        SAState_p->CurrentOffset += AllocMaskWordCount;
+        SAParams_p->SeqMaskWord32Count = InputMaskWordCount;
+
+        /* Add nonce for CTR and related modes */
+        if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CTR ||
+            SAParams_p->CryptoMode == SAB_CRYPTO_MODE_GCM ||
+            SAParams_p->CryptoMode == SAB_CRYPTO_MODE_GMAC ||
+            SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CCM||
+            SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CHACHA_CTR32)
+        {
+            if (IVOffset == 0)
+                IVOffset = SAState_p->CurrentOffset;
+
+            SAState_p->CW1 |= SAB_CW1_IV0;
+
+            /* For Poly/Chacha, we need to run in XOR IV mode with
+              delayed OTK in order to make the OTK derivation from the
+              extracted IV work */
+            if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CHACHA_CTR32)
+            {
+                SAState_p->CW1 |= SAB_CW1_CRYPTO_NONCE_XOR|
+                    SAB_CW1_CRYPTO_MODE_CHACHA_POLY_OTK;
+                /* need all 3 IV double words - for IV=seqno these need to be
+                   zeroized */
+                SAState_p->CW1 |= SAB_CW1_IV1|SAB_CW1_IV2;
+                if (SAParams_p->IVSrc == SAB_IV_SRC_IMPLICIT)
+                    SAState_p->CW1 |= SAB_CW1_IV_CTR;
+            }
+            else if (SAParams_p->IVSrc == SAB_IV_SRC_IMPLICIT)
+                SAState_p->CW1 |= SAB_CW1_IV_ORIG_SEQ;
+
+            if (SABuffer_p != NULL)
+            {
+                if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CCM)
+                {
+                    SABuffer_p[IVOffset] =
+                        (SAParams_p->Nonce_p[0] << 8)  |
+                        (SAParams_p->Nonce_p[1] << 16) |
+                        (SAParams_p->Nonce_p[2] << 24) | SAB_CCM_FLAG_L4;
+                }
+                else
+                    SABuilderLib_CopyKeyMat(SABuffer_p,
+                                            IVOffset,
+                                            SAParams_p->Nonce_p,
+                                            sizeof(uint32_t));
+            }
+            IVOffset += 1;
+            if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CCM)
+            {
+                /* Add 0 counter field (IV3) */
+                SAState_p->CW1 |= SAB_CW1_IV3;
+                if(SABuffer_p != NULL)
+                    SABuffer_p[IVOffset] = 0;
+                IVOffset += 1;
+            }
+            else if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CHACHA_CTR32)
+            {
+                /* For ChaCha20 the IV1 and IV2 words are required to be 0 */
+                SABuilderLib_ZeroFill(SABuffer_p, IVOffset, 2*sizeof(uint32_t));
+                IVOffset +=2;
+            }
+            if (IVOffset > SAState_p->CurrentOffset)
+            {
+                SAState_p->CurrentOffset = IVOffset;
+            }
+         }
+    }
+    return SAB_STATUS_OK;
+}
+
+
+#endif /* SAB_ENABLE_PROTO_IPSEC */
+
+/* end of file sa_builder_ipsec.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_macsec.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_macsec.c
new file mode 100644
index 0000000..e6a7f99
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_macsec.c
@@ -0,0 +1,275 @@
+/* sa_builder_macsec.c
+ *
+ * MACsec specific functions (for initialization of SABuilder_Params_t
+ * structures and for building the MACsec specifc part of an SA.).
+ */
+
+/*****************************************************************************
+* Copyright (c) 2013-2020 by Rambus, Inc. and/or its subsidiaries.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+#include "sa_builder_macsec.h"
+#include "sa_builder_internal.h" /* SABuilder_SetMACsecParams */
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+#include "c_sa_builder.h"
+#include "basic_defs.h"
+#include "log.h"
+
+#ifdef SAB_ENABLE_PROTO_MACSEC
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+/*----------------------------------------------------------------------------
+ * SABuilder_Init_MACsec
+ *
+ * This function initializes the SABuilder_Params_t data structure and its
+ * SABuilder_Params_MACsec_t extension with sensible defaults for MACsec
+ * processing.
+ *
+ * SAParams_p (output)
+ *   Pointer to SA parameter structure to be filled in.
+ * SAParamsMACsec_p (output)
+ *   Pointer to MACsec parameter extension to be filled in
+ * SCI_p (input)
+ *   Pointer to Secure Channel Identifier, 8 bytes.
+ * AN (input)
+ *   Association number, a number for 0 to 3.
+ * direction (input)
+ *   Must be one of SAB_DIRECTION_INBOUND or SAB_DIRECTION_OUTBOUND.
+ *
+ * Both the crypto and the authentication algorithm are initialized to
+ * NULL. The crypto algorithm (which may remain NULL) must be set to
+ * one of the algorithms supported by the protocol. The authentication
+ * algorithm must also be set to one of the algorithms supported by
+ * the protocol..Any required keys have to be specified as well.
+ *
+ * Both the SAParams_p and SAParamsMACsec_p input parameters must point
+ * to valid storage where variables of the appropriate type can be
+ * stored. This function initializes the link from SAParams_p to
+ * SAParamsMACsec_p.
+ *
+ * Return:
+ * SAB_STATUS_OK on success
+ * SAB_INVALID_PARAMETER when one of the pointer parameters is NULL
+ *   or the remaining parameters have illegal values.
+ */
+SABuilder_Status_t
+SABuilder_Init_MACsec(
+    SABuilder_Params_t * const SAParams_p,
+    SABuilder_Params_MACsec_t * const SAParamsMACsec_p,
+    const uint8_t *SCI_p,
+    const uint8_t AN,
+    const SABuilder_Direction_t direction)
+{
+#ifdef SAB_STRICT_ARGS_CHECK
+    if (SAParams_p == NULL || SAParamsMACsec_p == NULL || SCI_p == NULL)
+    {
+        LOG_CRIT("SABuilder_Init_MACsec: NULL pointer parameter supplied.\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    if (AN > 3)
+    {
+        LOG_CRIT("SABuilder_Init_MACsec: Invalid Association Number.\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    if (direction != SAB_DIRECTION_OUTBOUND &&
+        direction != SAB_DIRECTION_INBOUND)
+    {
+        LOG_CRIT("SABuilder_Init_ESP: Invalid direction.\n");
+        return SAB_INVALID_PARAMETER;
+    }
+#endif
+
+    SAParams_p->protocol = SAB_PROTO_MACSEC;
+    SAParams_p->direction = direction;
+    SAParams_p->ProtocolExtension_p = (void*)SAParamsMACsec_p;
+    SAParams_p->flags = 0;
+    SAParams_p->RedirectInterface = 0;
+
+    SAParams_p->CryptoAlgo = SAB_CRYPTO_NULL;
+    SAParams_p->CryptoMode = SAB_CRYPTO_MODE_CBC;
+    SAParams_p->IVSrc = SAB_IV_SRC_DEFAULT;
+    SAParams_p->CryptoParameter = 0;
+    SAParams_p->KeyByteCount = 0;
+    SAParams_p->Key_p = NULL;
+    SAParams_p->IV_p = NULL;
+    SAParams_p->Nonce_p = NULL;
+
+    SAParams_p->AuthAlgo = SAB_AUTH_NULL;
+    SAParams_p->AuthKey1_p = NULL;
+    SAParams_p->AuthKey2_p = NULL;
+    SAParams_p->AuthKey3_p = NULL;
+    SAParams_p->AuthKeyByteCount = 0;
+
+    SAParams_p->OffsetARC4StateRecord = 0;
+    SAParams_p->CW0 = 0;
+    SAParams_p->CW1 = 0;
+    SAParams_p->OffsetDigest0 = 0;
+    SAParams_p->OffsetDigest1 = 0;
+    SAParams_p->OffsetSeqNum = 0;
+    SAParams_p->OffsetSeqMask = 0;
+    SAParams_p->OffsetIV = 0;
+    SAParams_p->OffsetIJPtr = 0;
+    SAParams_p->OffsetARC4State = 0;
+    SAParams_p->SeqNumWord32Count = 0;
+    SAParams_p->SeqMaskWord32Count = 0;
+    SAParams_p->IVWord32Count = 0;
+
+    SAParamsMACsec_p->MACsecFlags = 0;
+    SAParamsMACsec_p->SCI_p = SCI_p;
+    SAParamsMACsec_p->AN = AN;
+    SAParamsMACsec_p->SeqNum = 0;
+    SAParamsMACsec_p->ReplayWindow = 0;
+    SAParamsMACsec_p->ConfOffset = 0;
+    SAParamsMACsec_p->ContextRef = 0;
+
+    return SAB_STATUS_OK;
+}
+
+/*----------------------------------------------------------------------------
+ * SABuilder_SetMACsecParams
+ *
+ * Fill in MACsec-specific extensions into the SA.
+ *
+ * SAParams_p (input)
+ *   The SA parameters structure from which the SA is derived.
+ * SAState_p (input, output)
+ *   Variables containing information about the SA being generated/
+ * SABuffer_p (input, output).
+ *   The buffer in which the SA is built. If NULL, no SA will be built, but
+ *   state variables in SAState_p will still be updated.
+ *
+ * Return:
+ * SAB_STATUS_OK on success
+ * SAB_INVALID_PARAMETER when SAParams_p is invalid, or if any of
+ *    the buffer arguments  is a null pointer while the corresponding buffer
+ *    would be required for the operation.
+ * SAB_UNSUPPORTED_FEATURE when SAParams_p describes an operations that
+ *    is not supported on the hardware for which this SA builder
+ *    is configured.
+ */
+SABuilder_Status_t
+SABuilder_SetMACsecParams(SABuilder_Params_t *const SAParams_p,
+                          SABuilder_State_t * const SAState_p,
+                          uint32_t * const SABuffer_p)
+{
+    SABuilder_Params_MACsec_t *SAParamsMACsec_p;
+    SAParamsMACsec_p = (SABuilder_Params_MACsec_t *)
+        (SAParams_p->ProtocolExtension_p);
+    if (SAParamsMACsec_p == NULL)
+    {
+        LOG_CRIT("SABuilder: MACsec extension pointer is null\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    /* Allow only AES-GMAC and AES-GCM */
+    if (SAParams_p->AuthAlgo != SAB_AUTH_AES_GCM &&
+        SAParams_p->AuthAlgo != SAB_AUTH_AES_GMAC)
+    {
+        LOG_CRIT("SABuilder: Only AES-GCM and GMAC allowed wtih MACsec\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    if ( (SAParamsMACsec_p->MACsecFlags & SAB_MACSEC_ES) != 0 &&
+         (SAParamsMACsec_p->MACsecFlags & SAB_MACSEC_SC) != 0)
+    {
+        LOG_CRIT("SABuilder: MACSEC if ES is set, then SC must be zero,\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    /* Add sequence number */
+    SAState_p->CW0 |= SAB_CW0_SEQNUM_32;
+    SAParams_p->OffsetSeqNum = SAState_p->CurrentOffset;
+    SAParams_p->SeqNumWord32Count = 1;
+    SAState_p->CW1 |= SAB_CW1_SEQNUM_STORE;
+
+    if (SABuffer_p != NULL)
+        SABuffer_p[SAState_p->CurrentOffset] = SAParamsMACsec_p->SeqNum;
+    SAState_p->CurrentOffset += 1;
+
+    if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+    {
+        if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_GCM)
+            SAState_p->CW0 |= SAB_CW0_TOP_ENCRYPT_HASH;
+        else
+            SAState_p->CW0 |= SAB_CW0_TOP_HASH_ENCRYPT;
+        /* Some versions of the hardware can update the sequence number
+           early, so multiple engines can operate in parallel. */
+        SAState_p->CW1 |= SAB_CW1_EARLY_SEQNUM_UPDATE;
+        SAState_p->CW1 |= SAParams_p->OffsetSeqNum << 24;
+    }
+    else
+    {
+        SAState_p->CW0 |= SAB_CW0_TOP_HASH_DECRYPT;
+
+        /* Add 'sequence number mask' parameter, which is the replay
+           window size */
+        SAParams_p->OffsetSeqMask = SAState_p->CurrentOffset;
+        if(SABuffer_p != NULL)
+        {
+            SABuffer_p[SAState_p->CurrentOffset] =
+                SAParamsMACsec_p->ReplayWindow;
+            SABuffer_p[SAState_p->CurrentOffset+1] = 0; // Add dummy mask word.
+        }
+        SAParams_p->SeqMaskWord32Count = 1;
+        SAState_p->CurrentOffset += 2;
+        SAState_p->CW0 |= SAB_CW0_MASK_32;
+        SAState_p->CW1 |= SAB_CW1_MACSEC_SEQCHECK|SAB_CW1_NO_MASK_UPDATE;
+    }
+
+    /* Add SCI (IV0 and IV1) */
+    SAState_p->CW1 |= SAB_CW1_IV_CTR | SAB_CW1_IV0 | SAB_CW1_IV1 | SAB_CW1_IV2;
+#ifdef SAB_STRICT_ARGS_CHECK
+    if (SAParamsMACsec_p->SCI_p == NULL)
+    {
+        LOG_CRIT("SABuilder: NULL pointer SCI.\n");
+        return SAB_INVALID_PARAMETER;
+    }
+#endif
+    SAParams_p->OffsetIV = SAState_p->CurrentOffset;
+    SAParams_p->IVWord32Count = 2;
+
+    SABuilderLib_CopyKeyMat(SABuffer_p, SAState_p->CurrentOffset,
+                            SAParamsMACsec_p->SCI_p, 8);
+    SAState_p->CurrentOffset += 2;
+
+    /* Add sequence number once more (IV2) */
+    if (SABuffer_p != NULL)
+        SABuffer_p[SAState_p->CurrentOffset] = SAParamsMACsec_p->SeqNum;
+    SAState_p->CurrentOffset += 1;
+
+    return SAB_STATUS_OK;
+}
+
+
+#endif /* SAB_ENABLE_PROTO_MACSEC */
+
+/* end of file sa_builder_macsec.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_srtp.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_srtp.c
new file mode 100644
index 0000000..a43e711
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_srtp.c
@@ -0,0 +1,228 @@
+/* sa_builder_srtp.c
+ *
+ * SRTP specific functions (for initialization of
+ * SABuilder_Params_t structures and for building the SRTP
+ * specifc part of an SA.).
+ */
+
+/*****************************************************************************
+* Copyright (c) 2011-2020 by Rambus, Inc. and/or its subsidiaries.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+#include "sa_builder_srtp.h"
+#include "sa_builder_internal.h" /* SABuilder_SetSSLTLSParams */
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+#include "c_sa_builder.h"
+#include "basic_defs.h"
+#include "log.h"
+
+#ifdef SAB_ENABLE_PROTO_SRTP
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+/*----------------------------------------------------------------------------
+ * SABuilder_Init_SRTP
+ *
+ * This function initializes the SABuilder_Params_t data structure and
+ * its SABuilder_Params_SRTP_t extension with sensible defaults for
+ * SRTP processing..
+ *
+ * SAParams_p (output)
+ *   Pointer to SA parameter structure to be filled in.
+ * SAParamsSRTP_p (output)
+ *   Pointer to SRTP parameter extension to be filled in
+ * IsSRTCP (input)
+ *   true if the SA is for SRTCP.
+ * direction (input)
+ *   Must be one of SAB_DIRECTION_INBOUND or SAB_DIRECTION_OUTBOUND.
+ *
+ * Tis function initializes the authentication algorithm to HMAC_SHA1.
+ * The application has to fill in the appropriate keys. The crypto algorithm
+ * is initialized to NULL. It can be changed to AES ICM and then a crypto
+ * key has to be added as well.
+ *
+ * Both the SAParams_p and SAParamsSRTP_p input parameters must point
+ * to valid storage where variables of the appropriate type can be
+ * stored. This function initializes the link from SAParams_p to
+ * SAParamsSRTP_p.
+ *
+ * Return:
+ * SAB_STATUS_OK on success
+ * SAB_INVALID_PARAMETER when one of the pointer parameters is NULL
+ *   or the remaining parameters have illegal values.
+ */
+SABuilder_Status_t
+SABuilder_Init_SRTP(
+        SABuilder_Params_t * const SAParams_p,
+        SABuilder_Params_SRTP_t * const SAParamsSRTP_p,
+        const bool IsSRTCP,
+        const SABuilder_Direction_t direction)
+{
+#ifdef SAB_STRICT_ARGS_CHECK
+    if (SAParams_p == NULL || SAParamsSRTP_p == NULL)
+    {
+        LOG_CRIT("SABuilder_Init_SSLTLS: NULL pointer parameter supplied.\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    if (direction != SAB_DIRECTION_OUTBOUND &&
+        direction != SAB_DIRECTION_INBOUND)
+    {
+        LOG_CRIT("SABuilder_Init_ESP: Invalid direction.\n");
+        return SAB_INVALID_PARAMETER;
+    }
+#endif
+
+    SAParams_p->protocol = SAB_PROTO_SRTP;
+    SAParams_p->direction = direction;
+    SAParams_p->ProtocolExtension_p = (void*)SAParamsSRTP_p;
+    SAParams_p->flags = 0;
+    SAParams_p->RedirectInterface = 0;
+
+    SAParams_p->CryptoAlgo = SAB_CRYPTO_NULL;
+    SAParams_p->CryptoMode = SAB_CRYPTO_MODE_CBC;
+    SAParams_p->IVSrc = SAB_IV_SRC_DEFAULT;
+    SAParams_p->CryptoParameter = 0;
+    SAParams_p->KeyByteCount = 0;
+    SAParams_p->Key_p = NULL;
+    SAParams_p->IV_p = NULL;
+    SAParams_p->Nonce_p = NULL;
+
+    SAParams_p->AuthAlgo = SAB_AUTH_HMAC_SHA1;
+    SAParams_p->AuthKey1_p = NULL;
+    SAParams_p->AuthKey2_p = NULL;
+    SAParams_p->AuthKey3_p = NULL;
+    SAParams_p->AuthKeyByteCount = 0;
+
+    SAParams_p->OffsetARC4StateRecord = 0;
+    SAParams_p->CW0 = 0;
+    SAParams_p->CW1 = 0;
+    SAParams_p->OffsetDigest0 = 0;
+    SAParams_p->OffsetDigest1 = 0;
+    SAParams_p->OffsetSeqNum = 0;
+    SAParams_p->OffsetSeqMask = 0;
+    SAParams_p->OffsetIV = 0;
+    SAParams_p->OffsetIJPtr = 0;
+    SAParams_p->OffsetARC4State = 0;
+    SAParams_p->SeqNumWord32Count = 0;
+    SAParams_p->SeqMaskWord32Count = 0;
+    SAParams_p->IVWord32Count = 0;
+
+    SAParamsSRTP_p->SRTPFlags = 0;
+    if (IsSRTCP)
+        SAParamsSRTP_p->SRTPFlags |= SAB_SRTP_FLAG_SRTCP;
+    SAParamsSRTP_p->MKI = 0;
+    SAParamsSRTP_p->ICVByteCount = 10;
+
+    return SAB_STATUS_OK;
+}
+
+/*----------------------------------------------------------------------------
+ * SABuilder_SetSRTPParams
+ *
+ * Fill in SRTP-specific extensions into the SA.
+ *
+ * SAParams_p (input)
+ *   The SA parameters structure from which the SA is derived.
+ * SAState_p (input, output)
+ *   Variables containing information about the SA being generated.
+ * SABuffer_p (input, output).
+ *   The buffer in which the SA is built. If NULL, no SA will be built, but
+ *   state variables in SAState_p will still be updated.
+ *
+ * Return:
+ * SAB_STATUS_OK on success
+ * SAB_INVALID_PARAMETER when SAParams_p is invalid, or if any of
+ *    the buffer arguments  is a null pointer while the corresponding buffer
+ *    would be required for the operation.
+ * SAB_UNSUPPORTED_FEATURE when SAParams_p describes an operations that
+ *    is not supported on the hardware for which this SA builder
+ *    is configured.
+ */
+SABuilder_Status_t
+SABuilder_SetSRTPParams(SABuilder_Params_t *const SAParams_p,
+                        SABuilder_State_t * const SAState_p,
+                        uint32_t * const SABuffer_p)
+{
+    SABuilder_Params_SRTP_t *SAParamsSRTP_p;
+    SAParamsSRTP_p = (SABuilder_Params_SRTP_t *)
+        (SAParams_p->ProtocolExtension_p);
+    if (SAParamsSRTP_p == NULL)
+    {
+        LOG_CRIT("SABuilder: SRTP extension pointer is null\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    if (SAParams_p->CryptoAlgo == SAB_CRYPTO_AES)
+    {
+        SAState_p->CW1 &= ~0x7; // Clear crypto mode (CTR or ICM);
+        SAState_p->CW1 |= SAB_CW1_CRYPTO_MODE_CTR_LOAD | SAB_CW1_IV_CTR;
+    }
+    else if (SAParams_p->CryptoAlgo != SAB_CRYPTO_NULL)
+    {
+        LOG_CRIT("SABuilder: I: crypto algorithm not supported\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    if (SAParams_p->AuthAlgo != SAB_AUTH_HMAC_SHA1)
+    {
+        LOG_CRIT("SABuilder: I: authentication algorithm not supported\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    /* Add MKI (as the SPI field) */
+    if ((SAParamsSRTP_p->SRTPFlags & SAB_SRTP_FLAG_INCLUDE_MKI) != 0)
+    {
+        SAState_p->CW0 |= SAB_CW0_SPI;
+        if (SABuffer_p != NULL)
+            SABuffer_p[SAState_p->CurrentOffset] = SAParamsSRTP_p->MKI;
+        SAState_p->CurrentOffset += 1;
+    }
+
+    if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+    {
+        if (SAParams_p->CryptoAlgo==SAB_CRYPTO_NULL)
+            SAState_p->CW0 |= SAB_CW0_TOP_HASH_OUT;
+        else
+            SAState_p->CW0 |= SAB_CW0_TOP_ENCRYPT_HASH;
+    }
+    else
+    {
+        if (SAParams_p->CryptoAlgo==SAB_CRYPTO_NULL)
+            SAState_p->CW0 |= SAB_CW0_TOP_HASH_IN;
+        else
+            SAState_p->CW0 |= SAB_CW0_TOP_HASH_DECRYPT;
+    }
+
+    return SAB_STATUS_OK;
+}
+
+#endif /* SAB_ENABLE_PROTO_SRTP */
+
+
+/* end of file sa_builder_srtp.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_ssltls.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_ssltls.c
new file mode 100644
index 0000000..6a47ad0
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/sa/sa_builder_ssltls.c
@@ -0,0 +1,760 @@
+/* sa_builder_ssltls.c
+ *
+ * SSL/TLS/DTLS specific functions (for initialization of SABuilder_Params_t
+ * structures and for building the SSL/TLS/DTLS specifc part of an SA.).
+ */
+
+/*****************************************************************************
+* Copyright (c) 2011-2021 by Rambus, Inc. and/or its subsidiaries.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+#include "sa_builder_ssltls.h"
+#include "sa_builder_internal.h" /* SABuilder_SetSSLTLSParams */
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+#include "c_sa_builder.h"
+#include "basic_defs.h"
+#include "log.h"
+
+#ifdef SAB_ENABLE_PROTO_SSLTLS
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+#ifdef SAB_ENABLE_384BIT_SEQMASK
+#define SAB_SEQUENCE_MAXBITS 384
+#else
+#define SAB_SEQUENCE_MAXBITS 128
+#endif
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+/*----------------------------------------------------------------------------
+ * SABuilder_Init_SSLTLS
+ *
+ * This function initializes the SABuilder_Params_t data structure and its
+ * SABuilder_Params_SSLTLS_t extension with sensible defaults for SSL, TLS
+ * and DTLS processing.
+ *
+ * SAParams_p (output)
+ *   Pointer to SA parameter structure to be filled in.
+ * SAParamsSSLTLS_p (output)
+ *   Pointer to SSLTLS parameter extension to be filled in
+ * version (input)
+ *   Version code for the desired protcol (choose one of the SAB_*_VERSION_*
+ *   constants from sa_builder_params_ssltls.h).
+ * direction (input)
+ *   Must be one of SAB_DIRECTION_INBOUND or SAB_DIRECTION_OUTBOUND.
+ *
+ * Both the crypto and the authentication algorithm are initialized to
+ * NULL. The crypto algorithm (which may remain NULL) must be set to
+ * one of the algorithms supported by the protocol. The authentication
+ * algorithm must also be set to one of the algorithms supported by
+ * the protocol..Any required keys have to be specified as well.
+ *
+ * Both the SAParams_p and SAParamsSSLTLS_p input parameters must point
+ * to valid storage where variables of the appropriate type can be
+ * stored. This function initializes the link from SAParams_p to
+ * SAParamsSSSLTLS_p.
+ *
+ * Return:
+ * SAB_STATUS_OK on success
+ * SAB_INVALID_PARAMETER when one of the pointer parameters is NULL
+ *   or the remaining parameters have illegal values.
+ */
+SABuilder_Status_t
+SABuilder_Init_SSLTLS(
+    SABuilder_Params_t * const SAParams_p,
+    SABuilder_Params_SSLTLS_t * const SAParamsSSLTLS_p,
+    const uint16_t version,
+    const SABuilder_Direction_t direction)
+{
+    int i;
+#ifdef SAB_STRICT_ARGS_CHECK
+    if (SAParams_p == NULL || SAParamsSSLTLS_p == NULL)
+    {
+        LOG_CRIT("SABuilder_Init_SSLTLS: NULL pointer parameter supplied.\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    if (version != SAB_SSL_VERSION_3_0 &&
+        version != SAB_TLS_VERSION_1_0 &&
+        version != SAB_TLS_VERSION_1_1 &&
+        version != SAB_TLS_VERSION_1_2 &&
+        version != SAB_TLS_VERSION_1_3 &&
+        version != SAB_DTLS_VERSION_1_0 &&
+        version != SAB_DTLS_VERSION_1_2)
+    {
+        LOG_CRIT("SABuilder_Init_SSLTLS: Invalid protocol version.\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    if (direction != SAB_DIRECTION_OUTBOUND &&
+        direction != SAB_DIRECTION_INBOUND)
+    {
+        LOG_CRIT("SABuilder_Init_ESP: Invalid direction.\n");
+        return SAB_INVALID_PARAMETER;
+    }
+#endif
+
+    SAParams_p->protocol = SAB_PROTO_SSLTLS;
+    SAParams_p->direction = direction;
+    SAParams_p->ProtocolExtension_p = (void*)SAParamsSSLTLS_p;
+    SAParams_p->flags = 0;
+    SAParams_p->RedirectInterface = 0;
+
+    SAParams_p->CryptoAlgo = SAB_CRYPTO_NULL;
+    SAParams_p->CryptoMode = SAB_CRYPTO_MODE_CBC;
+    SAParams_p->IVSrc = SAB_IV_SRC_DEFAULT;
+    SAParams_p->CryptoParameter = 0;
+    SAParams_p->KeyByteCount = 0;
+    SAParams_p->Key_p = NULL;
+    SAParams_p->IV_p = NULL;
+    SAParams_p->Nonce_p = NULL;
+
+    SAParams_p->AuthAlgo = SAB_AUTH_NULL;
+    SAParams_p->AuthKey1_p = NULL;
+    SAParams_p->AuthKey2_p = NULL;
+    SAParams_p->AuthKey3_p = NULL;
+    SAParams_p->AuthKeyByteCount = 0;
+
+    SAParams_p->OffsetARC4StateRecord = 0;
+    SAParams_p->CW0 = 0;
+    SAParams_p->CW1 = 0;
+    SAParams_p->OffsetDigest0 = 0;
+    SAParams_p->OffsetDigest1 = 0;
+    SAParams_p->OffsetSeqNum = 0;
+    SAParams_p->OffsetSeqMask = 0;
+    SAParams_p->OffsetIV = 0;
+    SAParams_p->OffsetIJPtr = 0;
+    SAParams_p->OffsetARC4State = 0;
+    SAParams_p->SeqNumWord32Count = 0;
+    SAParams_p->SeqMaskWord32Count = 0;
+    SAParams_p->IVWord32Count = 0;
+
+    SAParamsSSLTLS_p->SSLTLSFlags = 0;
+    SAParamsSSLTLS_p->version = version;
+    SAParamsSSLTLS_p->epoch = 0;
+    SAParamsSSLTLS_p->SeqNum = 0;
+    SAParamsSSLTLS_p->SeqNumHi = 0;
+    for (i=0; i<12; i++)
+        SAParamsSSLTLS_p->SeqMask[i] = 0;
+    SAParamsSSLTLS_p->PadAlignment = 0;
+    SAParamsSSLTLS_p->ContextRef = 0;
+    SAParamsSSLTLS_p->SequenceMaskBitCount = 0;
+    SAParamsSSLTLS_p->ICVByteCount = 0;
+    return SAB_STATUS_OK;
+}
+
+/*----------------------------------------------------------------------------
+ * SABuilder_SetSSLTLSParams
+ *
+ * Fill in SSL/TLS/DTLS-specific extensions into the SA.
+ *
+ * SAParams_p (input)
+ *   The SA parameters structure from which the SA is derived.
+ * SAState_p (input, output)
+ *   Variables containing information about the SA being generated/
+ * SABuffer_p (input, output).
+ *   The buffer in which the SA is built. If NULL, no SA will be built, but
+ *   state variables in SAState_p will still be updated.
+ *
+ * Return:
+ * SAB_STATUS_OK on success
+ * SAB_INVALID_PARAMETER when SAParams_p is invalid, or if any of
+ *    the buffer arguments  is a null pointer while the corresponding buffer
+ *    would be required for the operation.
+ * SAB_UNSUPPORTED_FEATURE when SAParams_p describes an operations that
+ *    is not supported on the hardware for which this SA builder
+ *    is configured.
+ */
+SABuilder_Status_t
+SABuilder_SetSSLTLSParams(SABuilder_Params_t *const SAParams_p,
+                          SABuilder_State_t * const SAState_p,
+                          uint32_t * const SABuffer_p)
+{
+    unsigned int IVOffset = 0;
+    SABuilder_Params_SSLTLS_t *SAParamsSSLTLS_p;
+    bool fFixedSeqOffset = false;
+    SAParamsSSLTLS_p = (SABuilder_Params_SSLTLS_t *)
+        (SAParams_p->ProtocolExtension_p);
+    if (SAParamsSSLTLS_p == NULL)
+    {
+        LOG_CRIT("SABuilder: SSLTLS extension pointer is null\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    /* Prohibit ARC4 in DTLS and TLS1.3 */
+    if (SAParams_p->CryptoAlgo == SAB_CRYPTO_ARCFOUR &&
+        (SAParamsSSLTLS_p->version == SAB_TLS_VERSION_1_3||
+         SAParamsSSLTLS_p->version == SAB_DTLS_VERSION_1_0||
+         SAParamsSSLTLS_p->version == SAB_DTLS_VERSION_1_2))
+    {
+        LOG_CRIT("SABuilder: ARC4 not allowed with DTLS/TLS1.3\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    /* Prohibit CBC mode or NULL crypto in TLS1.3 */
+    if (SAParamsSSLTLS_p->version == SAB_TLS_VERSION_1_3 &&
+        (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CBC ||
+         SAParams_p->CryptoAlgo == SAB_CRYPTO_NULL))
+    {
+        LOG_CRIT("SABuilder: CBC or nullcrypto  not allowed with TLS1.3\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    /* AES GCM/CCM/Chacha20 is only allowed with TLS1.2/TLS1.3/DTLS1.2 */
+    if ((SAParams_p->CryptoAlgo == SAB_CRYPTO_CHACHA20 ||
+         SAParams_p->CryptoMode == SAB_CRYPTO_MODE_GCM||
+         SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CCM) &&
+        SAParamsSSLTLS_p->version != SAB_TLS_VERSION_1_2 &&
+        SAParamsSSLTLS_p->version != SAB_TLS_VERSION_1_3 &&
+        SAParamsSSLTLS_p->version != SAB_DTLS_VERSION_1_2)
+    {
+        LOG_CRIT("SABuilder: AES-GCM/CCM/ChaCha20 only allowed with TLS/DTLS 1.2 and 1.3\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    /* Prohibit stateless ARC4*/
+    if (SAParams_p->CryptoAlgo == SAB_CRYPTO_ARCFOUR &&
+        SAParams_p->CryptoMode != SAB_CRYPTO_MODE_STATEFUL)
+    {
+        LOG_CRIT("SABuilder: ARC4 must be stateful\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    /* Check for supported algorithms and crypto modes in SSL/TLS */
+    if ((SAParams_p->CryptoAlgo != SAB_CRYPTO_NULL &&
+         SAParams_p->CryptoAlgo != SAB_CRYPTO_ARCFOUR &&
+         SAParams_p->CryptoAlgo != SAB_CRYPTO_DES &&
+         SAParams_p->CryptoAlgo != SAB_CRYPTO_3DES &&
+         SAParams_p->CryptoAlgo != SAB_CRYPTO_AES &&
+         SAParams_p->CryptoAlgo != SAB_CRYPTO_CHACHA20 &&
+         SAParams_p->CryptoAlgo != SAB_CRYPTO_SM4 &&
+         SAParams_p->CryptoAlgo != SAB_CRYPTO_BC0) ||
+        (SAParams_p->CryptoAlgo != SAB_CRYPTO_NULL &&
+         SAParams_p->CryptoMode != SAB_CRYPTO_MODE_STATEFUL &&
+         SAParams_p->CryptoMode != SAB_CRYPTO_MODE_CBC &&
+         SAParams_p->CryptoMode != SAB_CRYPTO_MODE_GCM &&
+         SAParams_p->CryptoMode != SAB_CRYPTO_MODE_CCM &&
+         SAParams_p->CryptoMode != SAB_CRYPTO_MODE_CHACHA_CTR32))
+    {
+        LOG_CRIT("SABuilder: SSLTLS crypto algorithm/mode not supported\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    /* Check for supported authentication algorithms in SSL/TLS */
+    if (SAParams_p->AuthAlgo != SAB_AUTH_HMAC_MD5 &&
+        SAParams_p->AuthAlgo != SAB_AUTH_SSLMAC_MD5 &&
+        SAParams_p->AuthAlgo != SAB_AUTH_HMAC_SHA1 &&
+        SAParams_p->AuthAlgo != SAB_AUTH_SSLMAC_SHA1 &&
+        SAParams_p->AuthAlgo != SAB_AUTH_HMAC_SHA2_256 &&
+        SAParams_p->AuthAlgo != SAB_AUTH_HMAC_SHA2_384 &&
+        SAParams_p->AuthAlgo != SAB_AUTH_HMAC_SHA2_512 &&
+        SAParams_p->AuthAlgo != SAB_AUTH_AES_GCM &&
+        SAParams_p->AuthAlgo != SAB_AUTH_AES_CCM &&
+        SAParams_p->AuthAlgo != SAB_AUTH_POLY1305 &&
+        SAParams_p->AuthAlgo != SAB_AUTH_HMAC_SM3)
+    {
+        LOG_CRIT("SABuilder: SSLTLS: auth algorithm not supported\n");
+        return SAB_INVALID_PARAMETER;
+    }
+
+    /* Add version to SA record */
+    if (SABuffer_p != NULL)
+    {
+        if (SAParamsSSLTLS_p->version == SAB_TLS_VERSION_1_3)
+        {
+            SABuffer_p[SAState_p->CurrentOffset] = SAB_TLS_VERSION_1_2<<16;
+            /* fixed type & version to be put in record for TLS1.3 */
+        }
+        else
+        {
+            SABuffer_p[SAState_p->CurrentOffset] = SAParamsSSLTLS_p->version<<16;
+        }
+    }
+    SAState_p->CurrentOffset += 1;
+
+    /* Determine whether we will have a fixed sequence number offset */
+    if (SAParams_p->direction == SAB_DIRECTION_INBOUND &&
+        (SAParamsSSLTLS_p->version == SAB_DTLS_VERSION_1_0||
+         SAParamsSSLTLS_p->version == SAB_DTLS_VERSION_1_2))
+    {
+        /* Determine size of sequence number mask in bits */
+        if (SAParamsSSLTLS_p->SequenceMaskBitCount == 0)
+        {
+            if ((SAParamsSSLTLS_p->SSLTLSFlags & SAB_DTLS_MASK_128) != 0)
+            {
+                SAParamsSSLTLS_p->SequenceMaskBitCount = 128;
+            }
+            else if ((SAParamsSSLTLS_p->SSLTLSFlags & SAB_DTLS_MASK_32) != 0)
+            {
+                SAParamsSSLTLS_p->SequenceMaskBitCount = 32;
+            }
+            else
+            {
+                SAParamsSSLTLS_p->SequenceMaskBitCount = 64;
+            }
+        }
+        if (SAParamsSSLTLS_p->SequenceMaskBitCount > SAB_SEQUENCE_MAXBITS ||
+            (SAParamsSSLTLS_p->SequenceMaskBitCount & 0x1f) != 0)
+        {
+            LOG_CRIT("SABuilder: Illegal sequence mask size.\n");
+            return SAB_INVALID_PARAMETER;
+        }
+#ifdef SAB_ENABLE_DEFAULT_FIXED_OFFSETS
+        fFixedSeqOffset = true;
+#else
+        if (SAParamsSSLTLS_p->SequenceMaskBitCount > 128 ||
+            (SAParamsSSLTLS_p->SSLTLSFlags & SAB_DTLS_FIXED_SEQ_OFFSET) != 0)
+        {
+            fFixedSeqOffset = true;
+        }
+#endif
+        if (SAParamsSSLTLS_p->SequenceMaskBitCount == 32)
+        {
+            fFixedSeqOffset = false; /* not supported for 32-bit mask */
+        }
+    }
+
+
+    if (fFixedSeqOffset)
+    {
+        /* Use a fixed sequence number offset for inbound if the hardware
+           supports it. */
+        /* Take care to insert the IV (nonce) just after the SPI. */
+        IVOffset = SAState_p->CurrentOffset;
+
+        /* Select one of two fixed offsets for the sequence number */
+        if (SAState_p->CurrentOffset < SAB_SEQNUM_LO_FIX_OFFSET)
+        {
+            SAState_p->CurrentOffset = SAB_SEQNUM_LO_FIX_OFFSET;
+        }
+        else
+        {
+            SAState_p->CurrentOffset = SAB_SEQNUM_HI_FIX_OFFSET;
+        }
+
+        /* Add sequence number */
+        SAParams_p->OffsetSeqNum = SAState_p->CurrentOffset;
+        SAParams_p->SeqNumWord32Count = 2;
+        SAState_p->CW1 |= SAB_CW1_SEQNUM_STORE;
+        SAState_p->CW0 |= SAB_CW0_SPI | SAB_CW0_SEQNUM_48_FIX;
+        if (SABuffer_p != NULL)
+        {
+            SABuffer_p[SAState_p->CurrentOffset] = SAParamsSSLTLS_p->SeqNum;
+            SABuffer_p[SAState_p->CurrentOffset + 1] =
+                    (SAParamsSSLTLS_p->SeqNumHi & 0xffff) |
+                    (SAParamsSSLTLS_p->epoch << 16);
+        }
+        SAState_p->CurrentOffset += 2;
+    }
+    else
+    {
+        /* Add sequence number */
+        SAParams_p->OffsetSeqNum = SAState_p->CurrentOffset;
+        SAParams_p->SeqNumWord32Count = 2;
+        SAState_p->CW1 |= SAB_CW1_SEQNUM_STORE;
+
+        if (SABuffer_p != NULL)
+            SABuffer_p[SAState_p->CurrentOffset] = SAParamsSSLTLS_p->SeqNum;
+        SAState_p->CurrentOffset += 1;
+        if (SAParamsSSLTLS_p->version != SAB_DTLS_VERSION_1_0 &&
+            SAParamsSSLTLS_p->version != SAB_DTLS_VERSION_1_2)
+        {
+            SAState_p->CW0 |= SAB_CW0_SPI | SAB_CW0_SEQNUM_64;
+            if (SABuffer_p != NULL)
+                SABuffer_p[SAState_p->CurrentOffset] =
+                    SAParamsSSLTLS_p->SeqNumHi;
+        }
+        else
+        {
+            SAState_p->CW0 |= SAB_CW0_SPI | SAB_CW0_SEQNUM_48;
+            if (SABuffer_p != NULL)
+                SABuffer_p[SAState_p->CurrentOffset] =
+                    (SAParamsSSLTLS_p->SeqNumHi & 0xffff) |
+                    (SAParamsSSLTLS_p->epoch << 16);
+        }
+        SAState_p->CurrentOffset += 1;
+    }
+
+    if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+    {
+
+        if (SAParams_p->CryptoAlgo==SAB_CRYPTO_NULL)
+            SAState_p->CW0 |= SAB_CW0_TOP_HASH_OUT;
+        else if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_GCM||
+                 SAParams_p->CryptoAlgo == SAB_CRYPTO_CHACHA20)
+            SAState_p->CW0 |= SAB_CW0_TOP_ENCRYPT_HASH;
+        else
+            SAState_p->CW0 |= SAB_CW0_TOP_HASH_ENCRYPT;
+
+        /* Some versions of the hardware can update the sequence number
+           early, so multiple engines can operate in parallel. */
+        SAState_p->CW1 |= SAB_CW1_EARLY_SEQNUM_UPDATE;
+        SAState_p->CW1 |= SAParams_p->OffsetSeqNum << 24;
+
+        /* Take care of IV  */
+        if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CCM)
+        {
+            if (SAParamsSSLTLS_p->version == SAB_TLS_VERSION_1_3)
+            {
+                SAState_p->CW1 = (SAState_p->CW1 & ~SAB_CW1_IV_MODE_MASK) |
+                    SAB_CW1_IV_ORIG_SEQ|SAB_CW1_CRYPTO_NONCE_XOR;
+                SAState_p->CW1 |= SAB_CW1_IV0|SAB_CW1_IV1|SAB_CW1_IV2|
+                    SAB_CW1_IV3 | SAB_CW1_CCM_IV_SHIFT;
+                if (SABuffer_p != NULL)
+                {
+                    SABuilderLib_CopyKeyMat(SABuffer_p,
+                                            SAState_p->CurrentOffset,
+                                            SAParams_p->Nonce_p,
+                                            3 * sizeof(uint32_t));
+                    SABuffer_p[SAState_p->CurrentOffset + 3] =
+                        SAB_CCM_FLAG_L3 << 24;
+                }
+                SAState_p->CurrentOffset += 4;
+            }
+            else
+            {
+                SAState_p->CW1 = (SAState_p->CW1 & ~SAB_CW1_IV_MODE_MASK) |
+                    SAB_CW1_IV_ORIG_SEQ;
+                SAState_p->CW1 |= SAB_CW1_IV0|SAB_CW1_IV3 | SAB_CW1_CCM_IV_SHIFT;
+                if (SABuffer_p != NULL)
+                {
+                    SABuilderLib_CopyKeyMat(SABuffer_p,
+                                            SAState_p->CurrentOffset,
+                                            SAParams_p->Nonce_p,
+                                            sizeof(uint32_t));
+                    SABuffer_p[SAState_p->CurrentOffset + 1] =
+                        SAB_CCM_FLAG_L3 << 24;
+                }
+                SAState_p->CurrentOffset += 2;
+            }
+        }
+        else if (SAParamsSSLTLS_p->version == SAB_TLS_VERSION_1_3 ||
+                 SAParams_p->CryptoAlgo == SAB_CRYPTO_CHACHA20)
+        {
+            SAState_p->CW1 = (SAState_p->CW1 & ~SAB_CW1_IV_MODE_MASK) |
+                SAB_CW1_IV_ORIG_SEQ|SAB_CW1_CRYPTO_NONCE_XOR;
+            SAState_p->CW1 |= SAB_CW1_IV0|SAB_CW1_IV1|SAB_CW1_IV2;
+            /* Always store the nonce (implicit salt) with TLS1.3 */
+            SABuilderLib_CopyKeyMat(SABuffer_p,
+                                    SAState_p->CurrentOffset,
+                                    SAParams_p->Nonce_p, 3*sizeof(uint32_t));
+            SAState_p->CurrentOffset +=3;
+        }
+        else if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_GCM)
+        {
+            if (SAParams_p->IVSrc == SAB_IV_SRC_DEFAULT)
+                SAParams_p->IVSrc = SAB_IV_SRC_SEQ;
+
+            if (SAParams_p->IVSrc == SAB_IV_SRC_SEQ)
+            {
+                SAState_p->CW1 |= SAB_CW1_IV_ORIG_SEQ;
+            }
+            else if (SAParams_p->IVSrc == SAB_IV_SRC_XORSEQ)
+            {
+                SAState_p->CW1 |= SAB_CW1_IV_CTR|SAB_CW1_CRYPTO_NONCE_XOR;
+                SAState_p->CW1 |= SAB_CW1_IV0|SAB_CW1_IV1|SAB_CW1_IV2;
+            }
+            else if (SAParams_p->IVSrc == SAB_IV_SRC_SA)
+            {
+                SAState_p->CW1 |= SAB_CW1_IV_CTR | SAB_CW1_IV1 | SAB_CW1_IV2;
+#ifdef SAB_STRICT_ARGS_CHECK
+                if (SAParams_p->IV_p == NULL)
+                {
+                    LOG_CRIT("SABuilder: NULL pointer IV.\n");
+                    return SAB_INVALID_PARAMETER;
+                }
+#endif
+                SAParams_p->OffsetIV = SAState_p->CurrentOffset;
+                SAParams_p->IVWord32Count = 2;
+
+                SABuilderLib_CopyKeyMat(SABuffer_p, SAState_p->CurrentOffset,
+                                        SAParams_p->IV_p, 8);
+                SAState_p->CurrentOffset += 2;
+            }
+            else
+            {
+                SAState_p->CW1 |= SAB_CW1_IV_CTR;
+            }
+            SAState_p->CW1 |= SAB_CW1_IV0;
+            /* Always store the nonce (implicit salt) with AES-GCM */
+            SABuilderLib_CopyKeyMat(SABuffer_p,
+                                    SAState_p->CurrentOffset,
+                                    SAParams_p->Nonce_p,
+                                    sizeof(uint32_t));
+            SAState_p->CurrentOffset +=1;
+            if (SAParams_p->IVSrc == SAB_IV_SRC_XORSEQ)
+            {
+                /* Store a fixed 8-byte value to XOR with sequence number */
+                SABuilderLib_CopyKeyMat(SABuffer_p,
+                                    SAState_p->CurrentOffset,
+                                    SAParams_p->IV_p,
+                                        2*sizeof(uint32_t));
+                SAState_p->CurrentOffset +=2;
+            }
+        }
+        else if (SAState_p->IVWords > 0)
+        { /* CBC mode, non-null */
+            if (SAParamsSSLTLS_p->version == SAB_SSL_VERSION_3_0 ||
+                SAParamsSSLTLS_p->version == SAB_TLS_VERSION_1_0)
+            {
+                SAParams_p->IVSrc = SAB_IV_SRC_SA;
+                SAState_p->CW1 |= SAB_CW1_CRYPTO_STORE;
+            }
+            else if (SAParams_p->IVSrc == SAB_IV_SRC_DEFAULT)
+            {
+                SAParams_p->IVSrc = SAB_IV_SRC_PRNG;
+            }
+            SAState_p->CW1 |= SAB_CW1_IV_FULL;
+            if (SAParams_p->IVSrc == SAB_IV_SRC_SA)
+            {
+                SAState_p->CW1 |= SAB_CW1_IV0 | SAB_CW1_IV1;
+                if(SAState_p->IVWords == 4)
+                    SAState_p->CW1 |= SAB_CW1_IV2 | SAB_CW1_IV3;
+#ifdef SAB_STRICT_ARGS_CHECK
+                if (SAParams_p->IV_p == NULL)
+                {
+                    LOG_CRIT("SABuilder: NULL pointer IV.\n");
+                    return SAB_INVALID_PARAMETER;
+                }
+#endif
+                SAParams_p->OffsetIV = SAState_p->CurrentOffset;
+                SAParams_p->IVWord32Count = SAState_p->IVWords;
+
+                SABuilderLib_CopyKeyMat(SABuffer_p,
+                                        SAState_p->CurrentOffset,
+                                        SAParams_p->IV_p,
+                                        SAState_p->IVWords * sizeof(uint32_t));
+                SAState_p->CurrentOffset += SAState_p->IVWords;
+            }
+        }
+    }
+    else
+    {   /* Inbound */
+        if (SAParams_p->CryptoAlgo==SAB_CRYPTO_NULL)
+            SAState_p->CW0 |= SAB_CW0_TOP_HASH_IN;
+        else if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_GCM ||
+                 SAParams_p->CryptoAlgo == SAB_CRYPTO_CHACHA20)
+            SAState_p->CW0 |= SAB_CW0_TOP_HASH_DECRYPT;
+        else
+            SAState_p->CW0 |= SAB_CW0_TOP_DECRYPT_HASH;
+
+        if (SAParams_p->CryptoMode != SAB_CRYPTO_MODE_GCM &&
+            SAParams_p->CryptoMode != SAB_CRYPTO_MODE_CCM &&
+            SAParams_p->CryptoAlgo != SAB_CRYPTO_CHACHA20  &&
+            SAState_p->IVWords > 0)
+        {
+            SAState_p->CW1 |= SAB_CW1_PREPKT_OP;
+            if (SAParamsSSLTLS_p->version == SAB_SSL_VERSION_3_0)
+            {
+                SAState_p->CW1 |= SAB_CW1_PAD_SSL;
+            }
+            else
+            {
+                SAState_p->CW1 |= SAB_CW1_PAD_TLS;
+            }
+        }
+        if (SAParamsSSLTLS_p->version == SAB_TLS_VERSION_1_3)
+        {
+            SAState_p->CW1 |= SAB_CW1_PAD_TLS | SAB_CW1_CRYPTO_AEAD;
+        }
+
+        /* Add sequence mask for DTLS only. */
+        if ((SAParamsSSLTLS_p->version == SAB_DTLS_VERSION_1_0 ||
+             SAParamsSSLTLS_p->version == SAB_DTLS_VERSION_1_2))
+        {
+            unsigned int InputMaskWordCount =
+                SAParamsSSLTLS_p->SequenceMaskBitCount / 32;
+            unsigned int AllocMaskWordCount;
+            SAParams_p->OffsetSeqMask = SAState_p->CurrentOffset;
+            /* Determine the required hardware mask size in words and set
+               control words accordingly. */
+            if (InputMaskWordCount  == 1)
+            {
+                AllocMaskWordCount = 1;
+                SAState_p->CW0 |= SAB_CW0_MASK_32;
+            }
+            else if (InputMaskWordCount  == 2)
+            {
+                AllocMaskWordCount = 2;
+                if (fFixedSeqOffset)
+                {
+                    SAState_p->CW0 |= SAB_CW0_MASK_64_FIX;
+                }
+                else
+                {
+                    SAState_p->CW0 |= SAB_CW0_MASK_64;
+                }
+            }
+            else if (InputMaskWordCount <= 4)
+            {
+                AllocMaskWordCount = 4;
+                if (fFixedSeqOffset)
+                {
+                SAState_p->CW0 |= SAB_CW0_MASK_128_FIX;
+                }
+                else
+                {
+                SAState_p->CW0 |= SAB_CW0_MASK_128;
+                }
+            }
+#ifdef SAB_ENABLE_256BIT_SEQMASK
+            else if (InputMaskWordCount <= 8)
+            {
+                AllocMaskWordCount = 8;
+                SAState_p->CW0 |= SAB_CW0_MASK_256_FIX;
+            }
+#endif
+            else
+            {
+                AllocMaskWordCount = 12;
+                SAState_p->CW0 |= SAB_CW0_MASK_384_FIX;
+            }
+            if(SABuffer_p != NULL)
+            {
+                unsigned int i;
+                for (i = 0; i < InputMaskWordCount; i++)
+                    SABuffer_p[SAState_p->CurrentOffset+i] =
+                        SAParamsSSLTLS_p->SeqMask[i];
+                /* If the input mask is smaller than the one picked by the
+                   hardware, fill the remaining words with all-one, the
+                   hardware will treat these words as invalid.
+                */
+                for (i= InputMaskWordCount; i < AllocMaskWordCount; i++)
+                    SABuffer_p[SAState_p->CurrentOffset+i] = 0xffffffff;
+            }
+            SAState_p->CurrentOffset += AllocMaskWordCount;
+            SAParams_p->SeqMaskWord32Count = InputMaskWordCount;
+        }
+
+        if (IVOffset == 0)
+            IVOffset = SAState_p->CurrentOffset;
+        if (SAState_p->IVWords > 0 &&
+            (SAParamsSSLTLS_p->version == SAB_SSL_VERSION_3_0 ||
+             SAParamsSSLTLS_p->version == SAB_TLS_VERSION_1_0))
+        {
+            SAParams_p->IVSrc = SAB_IV_SRC_SA;
+            SAState_p->CW1 |= SAB_CW1_IV_FULL;
+
+            SAState_p->CW1 |= SAB_CW1_IV0 | SAB_CW1_IV1 |
+                SAB_CW1_CRYPTO_STORE;
+            if(SAState_p->IVWords == 4)
+                    SAState_p->CW1 |= SAB_CW1_IV2 | SAB_CW1_IV3;
+#ifdef SAB_STRICT_ARGS_CHECK
+            if (SAParams_p->IV_p == NULL)
+            {
+                LOG_CRIT("SABuilder: NULL pointer IV.\n");
+                    return SAB_INVALID_PARAMETER;
+            }
+#endif
+            SAParams_p->OffsetIV = IVOffset;
+            SAParams_p->IVWord32Count = SAState_p->IVWords;
+
+            SABuilderLib_CopyKeyMat(SABuffer_p,
+                                    IVOffset,
+                                    SAParams_p->IV_p,
+                                    SAState_p->IVWords * sizeof(uint32_t));
+            IVOffset += SAState_p->IVWords;
+        }
+
+        if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CCM)
+        {
+            if (SAParamsSSLTLS_p->version == SAB_TLS_VERSION_1_3)
+            {
+                SAState_p->CW1 = (SAState_p->CW1 & ~SAB_CW1_IV_MODE_MASK) |
+                    SAB_CW1_IV_ORIG_SEQ|SAB_CW1_CRYPTO_NONCE_XOR;
+                SAState_p->CW1 |= SAB_CW1_IV0|SAB_CW1_IV1|SAB_CW1_IV2|
+                    SAB_CW1_IV3 | SAB_CW1_CCM_IV_SHIFT;
+                if (SABuffer_p != NULL)
+                {
+                    SABuilderLib_CopyKeyMat(SABuffer_p,
+                                            SAState_p->CurrentOffset,
+                                            SAParams_p->Nonce_p,
+                                            3 * sizeof(uint32_t));
+                    SABuffer_p[SAState_p->CurrentOffset + 3] =
+                        SAB_CCM_FLAG_L3 << 24;
+                }
+                SAState_p->CurrentOffset += 4;
+            }
+            else
+            {
+                SAState_p->CW1 = (SAState_p->CW1 & ~SAB_CW1_IV_MODE_MASK);
+                SAState_p->CW1 |= SAB_CW1_IV0| SAB_CW1_IV3 | SAB_CW1_CCM_IV_SHIFT;
+                if (SABuffer_p != NULL)
+                {
+                    SABuilderLib_CopyKeyMat(SABuffer_p,
+                                            SAState_p->CurrentOffset,
+                                            SAParams_p->Nonce_p,
+                                            sizeof(uint32_t));
+                    SABuffer_p[SAState_p->CurrentOffset + 1] =
+                        SAB_CCM_FLAG_L3 << 24;
+                }
+                SAState_p->CurrentOffset += 2;
+            }
+        }
+        else if (SAParamsSSLTLS_p->version == SAB_TLS_VERSION_1_3 ||
+            SAParams_p->CryptoAlgo == SAB_CRYPTO_CHACHA20)
+        {
+
+            if (SAParamsSSLTLS_p->version == SAB_DTLS_VERSION_1_2)
+            {
+                /* DTLS inbound extracts the sequence number from the packet, use delayed OTK mode */
+                SAState_p->CW1 |= SAB_CW1_IV_CTR|SAB_CW1_CRYPTO_NONCE_XOR;
+            } else {
+                /* regular TLS inbound internally increments the sequence number, so can save some cycles by starting OTK calc early */
+                SAState_p->CW1 = (SAState_p->CW1 & ~SAB_CW1_IV_MODE_MASK) |
+                    SAB_CW1_IV_ORIG_SEQ|SAB_CW1_CRYPTO_NONCE_XOR;
+            }
+            SAState_p->CW1 |= SAB_CW1_IV0|SAB_CW1_IV1|SAB_CW1_IV2;
+            /* Always store the nonce (implicit salt) with TLS1.3 */
+            SABuilderLib_CopyKeyMat(SABuffer_p,
+                                    IVOffset,
+                                    SAParams_p->Nonce_p, 3*sizeof(uint32_t));
+            IVOffset +=3;
+        }
+        else if(SAParams_p->CryptoMode == SAB_CRYPTO_MODE_GCM)
+        {
+            SAState_p->CW1 |= SAB_CW1_IV_CTR|SAB_CW1_IV0;
+            /* Always store the nonce (implicit salt) with AES-GCM */
+            SABuilderLib_CopyKeyMat(SABuffer_p,
+                                    IVOffset,
+                                    SAParams_p->Nonce_p, sizeof(uint32_t));
+            IVOffset +=1;
+        }
+        if (IVOffset > SAState_p->CurrentOffset)
+        {
+            SAState_p->CurrentOffset = IVOffset;
+        }
+
+    }
+
+    return SAB_STATUS_OK;
+}
+
+
+#endif /* SAB_ENABLE_PROTO_SSLTLS */
+
+/* end of file sa_builder_ssltls.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/token/token_builder_context.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/token/token_builder_context.c
new file mode 100644
index 0000000..16b039e
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/token/token_builder_context.c
@@ -0,0 +1,1696 @@
+/* token_builder_context.c
+ *
+ * This is the main implementation module for the EIP-96 Token Builder.
+ */
+
+/*****************************************************************************
+* Copyright (c) 2011-2022 by Rambus, Inc. and/or its subsidiaries.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+#include "token_builder.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+#include "c_token_builder.h"
+#include "basic_defs.h"
+#include "clib.h"
+#include "log.h"
+#include "sa_builder_params.h"
+#include "sa_builder_params_ipsec.h"
+
+#include "token_builder_internal.h"
+#include "sa_builder_params.h"
+#ifdef TKB_ENABLE_PROTO_IPSEC
+#include "sa_builder_params_ipsec.h"
+#endif
+#ifdef TKB_ENABLE_PROTO_SSLTLS
+#include "sa_builder_params_ssltls.h"
+#endif
+#ifdef TKB_ENABLE_PROTO_BASIC
+#include "sa_builder_params_basic.h"
+#endif
+#ifdef TKB_ENABLE_PROTO_SRTP
+#include "sa_builder_params_srtp.h"
+#endif
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+
+/*----------------------------------------------------------------------------
+ * TokenBuilder_GetContextSize
+ *
+ * Determine the size of the token context record in 32-bit words, which may
+ * depend on the SA parameters.
+ *
+ * SAParams_p (input)
+ *   Points to the SA parameters data structure
+ * TokenContextWord32Count_p (output)
+ *   Required size of the Token Context Record in 32-bit words.
+ *
+ * Note: This implementation has one Token Context Record format with a fixed
+ *       size. Therefore this function does not look at the SA parameters.
+ *
+ * Return:
+ * TKB_STATUS_OK if successful.
+ * TKB_INVALID_PARAMETER if any of the pointer parameters is NULL or if
+ *                      the contents of the input data structures are invalid.
+ */
+TokenBuilder_Status_t
+TokenBuilder_GetContextSize(
+    const SABuilder_Params_t * const SAParams_p,
+    unsigned int * const TokenContextWord32Count_p
+    )
+{
+#ifdef TKB_STRICT_ARGS_CHECK
+    if (SAParams_p == NULL || TokenContextWord32Count_p == NULL)
+    {
+        LOG_CRIT("TokenBuilder_GetContextSize: NULL pointer supplied\n");
+        return TKB_INVALID_PARAMETER;
+    }
+#endif
+    *TokenContextWord32Count_p =
+        ((unsigned int)sizeof(TokenBuilder_Context_t) +  sizeof(uint32_t) - 1) /
+        sizeof(uint32_t);
+    return TKB_STATUS_OK;
+}
+
+
+#ifdef TKB_ENABLE_PROTO_IPSEC
+#ifdef TKB_ENABLE_EXTENDED_IPSEC
+/*----------------------------------------------------------------------------
+ * TokenBuilder_BuildContext_IPsec
+ *
+ * Fill in the context fields for extended IPsec operations.
+ *
+ * SAParams_p (input)
+ *   Points to the SA parameters data structure. It is important that
+ *   SABuilder_GetSIze() and SABuilder_BuildSA() have already been called
+ *   for this SA.
+ * TokenContext_Internal_p (output)
+ *   Buffer to hold the Token Context Record.
+ *
+ * Return:
+ * TKB_STATUS_OK if successful.
+ * TKB_INVALID_PARAMETER if any of the pointer parameters is NULL or if
+ *                      the contents of the SA parameters are invalid.
+ */
+static TokenBuilder_Status_t
+TokenBuilder_BuildContext_Extended(
+    const SABuilder_Params_t * const SAParams_p,
+    TokenBuilder_Context_t * const TokenContext_Internal_p)
+{
+    uint8_t HeaderProto;
+    SABuilder_Params_IPsec_t *SAParamsIPsec_p;
+    SAParamsIPsec_p = (SABuilder_Params_IPsec_t *)
+        (SAParams_p->ProtocolExtension_p);
+    if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+    {
+        if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_IPV6) !=0)
+        {
+            if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_PROCESS_IP_HEADERS) !=0)
+            {
+                if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) !=0)
+                {
+                    HeaderProto = TKB_HDR_IPV6_OUT_TUNNEL;
+                }
+                else
+                {
+                    HeaderProto = TKB_HDR_IPV6_OUT_TRANSP;
+                }
+            }
+            else
+            {
+                HeaderProto = TKB_HDR_IPV6_OUT_TRANSP_HDRBYPASS;
+            }
+        }
+        else
+        {
+            if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_PROCESS_IP_HEADERS) !=0)
+            {
+                if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) !=0)
+                {
+                    HeaderProto = TKB_HDR_IPV4_OUT_TUNNEL;
+                }
+                else
+                {
+                    HeaderProto = TKB_HDR_IPV4_OUT_TRANSP;
+                }
+            }
+            else
+            {
+                HeaderProto = TKB_HDR_IPV4_OUT_TRANSP_HDRBYPASS;
+            }
+        }
+
+    }
+    else
+    {
+        if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_IPV6) !=0)
+        {
+            if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_PROCESS_IP_HEADERS) !=0)
+            {
+                TokenContext_Internal_p->TokenHeaderWord |= TKB_HEADER_UPD_HDR;
+                if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) !=0)
+                {
+                    HeaderProto = TKB_HDR_IPV6_IN_TUNNEL;
+                }
+                else
+                {
+                    HeaderProto = TKB_HDR_IPV6_IN_TRANSP;
+                }
+            }
+            else
+            {
+                HeaderProto = TKB_HDR_IPV6_IN_TRANSP_HDRBYPASS;
+            }
+        }
+        else
+        {
+            if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_PROCESS_IP_HEADERS) !=0)
+            {
+                TokenContext_Internal_p->TokenHeaderWord |= TKB_HEADER_UPD_HDR;
+                if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TUNNEL) !=0)
+                {
+                    HeaderProto = TKB_HDR_IPV4_IN_TUNNEL;
+                }
+                else
+                {
+                    HeaderProto = TKB_HDR_IPV4_IN_TRANSP;
+                }
+            }
+            else
+            {
+                HeaderProto = TKB_HDR_IPV4_IN_TRANSP_HDRBYPASS;
+            }
+        }
+
+    }
+    /* If NAT-T selected, select other header protocol range */
+    if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_NATT) != 0)
+        HeaderProto += (TKB_HDR_IPV4_OUT_TRANSP_HDRBYPASS_NATT -
+                        TKB_HDR_IPV4_OUT_TRANSP_HDRBYPASS);
+
+    TokenContext_Internal_p->hproto = HeaderProto;
+
+    TokenContext_Internal_p->u.generic.TTL = SAParamsIPsec_p->TTL;
+    TokenContext_Internal_p->u.generic.DSCP = SAParamsIPsec_p->DSCP;
+    TokenContext_Internal_p->NATT_Ports =
+        (SAParamsIPsec_p->NATTSrcPort >> 8) |
+        ((SAParamsIPsec_p->NATTSrcPort & 0xff) << 8) |
+        ((SAParamsIPsec_p->NATTDestPort & 0xff00) << 8) |
+        ((SAParamsIPsec_p->NATTDestPort & 0xff) << 24 );
+
+    TokenContext_Internal_p->u.generic.ESPFlags = 0;
+    if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_CLEAR_DF) != 0)
+        TokenContext_Internal_p->u.generic.ESPFlags |= TKB_ESP_FLAG_CLEAR_DF;
+    if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_SET_DF) != 0)
+        TokenContext_Internal_p->u.generic.ESPFlags |= TKB_ESP_FLAG_SET_DF;
+    if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_REPLACE_DSCP) != 0)
+        TokenContext_Internal_p->u.generic.ESPFlags |= TKB_ESP_FLAG_REPLACE_DSCP;
+    if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_CLEAR_ECN) != 0)
+        TokenContext_Internal_p->u.generic.ESPFlags |= TKB_ESP_FLAG_CLEAR_ECN;
+
+    if (HeaderProto == TKB_HDR_IPV4_OUT_TUNNEL ||
+        HeaderProto == TKB_HDR_IPV6_OUT_TUNNEL ||
+        HeaderProto == TKB_HDR_IPV4_OUT_TUNNEL_NATT ||
+        HeaderProto == TKB_HDR_IPV6_OUT_TUNNEL_NATT)
+    {
+        if (SAParamsIPsec_p->SrcIPAddr_p == NULL ||
+            SAParamsIPsec_p->DestIPAddr_p == NULL)
+        {
+            LOG_CRIT("SABuilder: NULL pointer tunnel address.\n");
+            return TKB_INVALID_PARAMETER;
+        }
+        if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_IPV4) != 0)
+        {
+            memcpy(TokenContext_Internal_p->TunnelIP,
+                   SAParamsIPsec_p->SrcIPAddr_p,
+                   4);
+            memcpy(TokenContext_Internal_p->TunnelIP + 4,
+                   SAParamsIPsec_p->DestIPAddr_p,
+                   4);
+        }
+        else
+        {
+            memcpy(TokenContext_Internal_p->TunnelIP,
+                   SAParamsIPsec_p->SrcIPAddr_p,
+                   16);
+            memcpy(TokenContext_Internal_p->TunnelIP + 16,
+                   SAParamsIPsec_p->DestIPAddr_p,
+                   16);
+        }
+    }
+    else if ((HeaderProto == TKB_HDR_IPV4_OUT_TRANSP_NATT ||
+              HeaderProto == TKB_HDR_IPV4_IN_TRANSP_NATT) &&
+             (SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TRANSPORT_NAT) !=0)
+    {
+        TokenContext_Internal_p->u.generic.ESPFlags |= TKB_ESP_FLAG_NAT;
+        if (SAParamsIPsec_p->SrcIPAddr_p == NULL ||
+            SAParamsIPsec_p->DestIPAddr_p == NULL)
+        {
+            LOG_CRIT("SABuilder: NULL pointer NAT address.\n");
+            return TKB_INVALID_PARAMETER;
+        }
+        memcpy(TokenContext_Internal_p->TunnelIP,
+               SAParamsIPsec_p->SrcIPAddr_p,
+               4);
+        memcpy(TokenContext_Internal_p->TunnelIP + 4,
+               SAParamsIPsec_p->DestIPAddr_p,
+               4);
+    }
+    else if ((HeaderProto == TKB_HDR_IPV6_OUT_TRANSP_NATT ||
+              HeaderProto == TKB_HDR_IPV6_IN_TRANSP_NATT) &&
+             (SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_TRANSPORT_NAT) !=0)
+    {
+        TokenContext_Internal_p->u.generic.ESPFlags |= TKB_ESP_FLAG_NAT;
+        if (SAParamsIPsec_p->SrcIPAddr_p == NULL ||
+            SAParamsIPsec_p->DestIPAddr_p == NULL)
+        {
+            LOG_CRIT("SABuilder: NULL pointer NAT address.\n");
+            return TKB_INVALID_PARAMETER;
+        }
+        memcpy(TokenContext_Internal_p->TunnelIP,
+               SAParamsIPsec_p->SrcIPAddr_p,
+               16);
+        memcpy(TokenContext_Internal_p->TunnelIP + 16,
+               SAParamsIPsec_p->DestIPAddr_p,
+               16);
+    }
+    return TKB_STATUS_OK;
+}
+
+/*----------------------------------------------------------------------------
+ * TokenBuilder_Next_PktId
+ *
+ * Increment the PktID if the Token Context describes an IPv4 ESP Tunnel
+ * operation
+ *
+ */
+unsigned int
+TokenBuilder_Next_PktId(
+    const void * const TokenContext_p,
+    unsigned int PktId)
+{
+    const TokenBuilder_Context_t * const TokenContext_Internal_p =
+        (const TokenBuilder_Context_t * const )TokenContext_p;
+    if (TokenContext_Internal_p->hproto == TKB_HDR_IPV4_OUT_TUNNEL ||
+        TokenContext_Internal_p->hproto == TKB_HDR_IPV4_OUT_TUNNEL_NATT)
+    {
+        return (PktId + 1) & MASK_16_BITS;
+    }
+    else
+    {
+        return PktId;
+    }
+}
+
+
+#endif
+
+/*----------------------------------------------------------------------------
+ * TokenBuilder_BuildContext_IPsec
+ *
+ * Create a Token Context Record for IPsec.
+ *
+ * SAParams_p (input)
+ *   Points to the SA parameters data structure. It is important that
+ *   SABuilder_GetSIze() and SABuilder_BuildSA() have already been called
+ *   for this SA.
+ * TokenContext_Internal_p (output)
+ *   Buffer to hold the Token Context Record.
+ *
+ * Return:
+ * TKB_STATUS_OK if successful.
+ * TKB_INVALID_PARAMETER if any of the pointer parameters is NULL or if
+ *                      the contents of the SA parameters are invalid.
+ */
+static TokenBuilder_Status_t
+TokenBuilder_BuildContext_IPsec(
+    const SABuilder_Params_t * const SAParams_p,
+    TokenBuilder_Context_t * const TokenContext_Internal_p)
+{
+    SABuilder_Params_IPsec_t *SAParamsIPsec_p;
+    SAParamsIPsec_p = (SABuilder_Params_IPsec_t *)
+        (SAParams_p->ProtocolExtension_p);
+    if (SAParamsIPsec_p == NULL)
+    {
+        LOG_CRIT("TokenBuilder_BuildContext:"
+                 " IPsec extension pointer is NULL\n");
+        return TKB_INVALID_PARAMETER;
+    }
+    if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_ESP) != 0)
+    {
+#ifdef TKB_ENABLE_IPSEC_ESP
+        TokenContext_Internal_p->ExtSeq = 0;
+        if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_NO_ANTI_REPLAY) != 0)
+            TokenContext_Internal_p->AntiReplay = 0;
+        else
+            TokenContext_Internal_p->AntiReplay = 1;
+
+        if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+        {
+            TokenContext_Internal_p->protocol = TKB_PROTO_ESP_OUT;
+            TokenContext_Internal_p->PadBlockByteCount = 4;
+            TokenContext_Internal_p->IVHandling = TKB_IV_OUTBOUND_CBC;
+            if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_LONG_SEQ) != 0)
+                TokenContext_Internal_p->ExtSeq = 1;
+        }
+        else
+        {
+            TokenContext_Internal_p->protocol = TKB_PROTO_ESP_IN;
+            TokenContext_Internal_p->PadBlockByteCount = 4;
+            TokenContext_Internal_p->TokenHeaderWord |=
+                TKB_HEADER_PAD_VERIFY;
+            TokenContext_Internal_p->IVHandling = TKB_IV_INBOUND_CBC;
+            if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_LONG_SEQ) != 0)
+                TokenContext_Internal_p->ExtSeq = 1;
+            if (TokenContext_Internal_p->ExtSeq == 0 &&
+                SAParams_p->OffsetSeqNum + 2 == SAParams_p->OffsetSeqMask &&
+                TokenContext_Internal_p->AntiReplay != 0)
+            {
+                TokenContext_Internal_p->ExtSeq = 2;
+                /* Special case, ExtSeq==2 do not use extended sequence
+                   number, but update context as if we have extended
+                   sequence number. Special SA format fixed seqnum/mask
+                   offsets.
+                */
+            }
+            TokenContext_Internal_p->AntiReplay *=
+                SAParamsIPsec_p->SequenceMaskBitCount / 32;
+        }
+        TokenContext_Internal_p->SeqOffset = SAParams_p->OffsetSeqNum;
+
+        switch (SAParams_p->CryptoAlgo)
+        {
+        case SAB_CRYPTO_NULL:
+            TokenContext_Internal_p->IVByteCount = 0;
+            break;
+        case SAB_CRYPTO_DES:
+        case SAB_CRYPTO_3DES:
+            TokenContext_Internal_p->IVByteCount = 8;
+            TokenContext_Internal_p->PadBlockByteCount = 8;
+            break;
+        case SAB_CRYPTO_AES:
+        case SAB_CRYPTO_SM4:
+        case SAB_CRYPTO_BC0:
+            if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CBC)
+            {
+                TokenContext_Internal_p->IVByteCount = 16;
+                TokenContext_Internal_p->PadBlockByteCount = 16;
+            }
+            else
+            {
+                if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+                    TokenContext_Internal_p->IVHandling =
+                        TKB_IV_OUTBOUND_CTR;
+                else
+                    TokenContext_Internal_p->IVHandling =
+                        TKB_IV_INBOUND_CTR;
+                if (SAParams_p->IVSrc == SAB_IV_SRC_IMPLICIT)
+                    TokenContext_Internal_p->IVByteCount = 0;
+                else
+                    TokenContext_Internal_p->IVByteCount = 8;
+            }
+            break;
+        case SAB_CRYPTO_CHACHA20:
+            if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+                TokenContext_Internal_p->IVHandling =
+                    TKB_IV_OUTBOUND_CTR;
+            else
+                    TokenContext_Internal_p->IVHandling =
+                        TKB_IV_INBOUND_CTR;
+            if (SAParams_p->IVSrc == SAB_IV_SRC_IMPLICIT)
+                TokenContext_Internal_p->IVByteCount = 0;
+            else
+                TokenContext_Internal_p->IVByteCount = 8;
+            break;
+        default:
+            LOG_CRIT("TokenBuilder_BuildContext:"
+                     " unsupported crypto algorithm.\n");
+            return TKB_INVALID_PARAMETER;
+        }
+
+        /* For all inbound and CTR mode outbound packets there is
+           only one supported way to obtain the IV, which is already
+           taken care of. Now handle outbound CBC. */
+        if(SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CBC &&
+           SAParams_p->direction == SAB_DIRECTION_OUTBOUND &&
+           SAParams_p->CryptoAlgo != SAB_CRYPTO_NULL)
+        {
+            switch (SAParams_p->IVSrc)
+            {
+            case SAB_IV_SRC_DEFAULT:
+            case SAB_IV_SRC_PRNG:
+                TokenContext_Internal_p->TokenHeaderWord |=
+                    TKB_HEADER_IV_PRNG;
+                break;
+            case SAB_IV_SRC_SA: /* No action required */
+                break;
+            case SAB_IV_SRC_TOKEN:
+                if (TokenContext_Internal_p->IVByteCount == 8)
+                {
+                    TokenContext_Internal_p->IVHandling =
+                        TKB_IV_OUTBOUND_TOKEN_2WORDS;
+                    TokenContext_Internal_p->TokenHeaderWord |=
+                        TKB_HEADER_IV_TOKEN_2WORDS;
+                }
+                else
+                {
+                    TokenContext_Internal_p->IVHandling =
+                        TKB_IV_OUTBOUND_TOKEN_4WORDS;
+                    TokenContext_Internal_p->TokenHeaderWord |=
+                        TKB_HEADER_IV_TOKEN_4WORDS;
+                }
+                break;
+            default:
+                LOG_CRIT("TokenBuilder_BuildContext:"
+                         "Unsupported IV source\n");
+                return TKB_INVALID_PARAMETER;
+            }
+        }
+
+        if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND &&
+            SAParamsIPsec_p->PadAlignment >
+            TokenContext_Internal_p->PadBlockByteCount &&
+            SAParamsIPsec_p->PadAlignment <= 256)
+            TokenContext_Internal_p->PadBlockByteCount =
+                SAParamsIPsec_p->PadAlignment;
+
+        switch(SAParams_p->AuthAlgo)
+        {
+        case SAB_AUTH_NULL:
+            TokenContext_Internal_p->ICVByteCount = 0;
+            TokenContext_Internal_p->ExtSeq = 0;
+            break;
+        case SAB_AUTH_HMAC_MD5:
+        case SAB_AUTH_HMAC_SHA1:
+        case SAB_AUTH_AES_XCBC_MAC:
+        case SAB_AUTH_AES_CMAC_128:
+            TokenContext_Internal_p->ICVByteCount = 12;
+            break;
+        case SAB_AUTH_HMAC_SHA2_224:
+        case SAB_AUTH_HMAC_SHA2_256:
+        case SAB_AUTH_HMAC_SM3:
+            TokenContext_Internal_p->ICVByteCount = 16;
+            break;
+        case SAB_AUTH_HMAC_SHA2_384:
+            TokenContext_Internal_p->ICVByteCount = 24;
+            break;
+        case SAB_AUTH_HMAC_SHA2_512:
+            TokenContext_Internal_p->ICVByteCount = 32;
+            break;
+        case SAB_AUTH_AES_CCM:
+        case SAB_AUTH_AES_GCM:
+        case SAB_AUTH_AES_GMAC:
+            // All these protocols have a selectable ICV length.
+            if (SAParamsIPsec_p->ICVByteCount == 8 ||
+                SAParamsIPsec_p->ICVByteCount == 12 ||
+                SAParamsIPsec_p->ICVByteCount == 16)
+            {
+                TokenContext_Internal_p->ICVByteCount =
+                    SAParamsIPsec_p->ICVByteCount;
+            }
+            else
+            {
+                TokenContext_Internal_p->ICVByteCount = 16;
+            }
+            switch (SAParams_p->AuthAlgo)
+            {
+                /* These protocols need specialized protocol codes
+                   for the token generator.*/
+            case SAB_AUTH_AES_CCM:
+                if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+                {
+                    TokenContext_Internal_p->protocol = TKB_PROTO_ESP_CCM_OUT;
+                }
+                else
+                {
+                    TokenContext_Internal_p->protocol = TKB_PROTO_ESP_CCM_IN;
+                }
+                TokenContext_Internal_p->u.generic.CCMSalt =
+                    (SAParams_p->Nonce_p[0] << 8) |
+                    (SAParams_p->Nonce_p[1] << 16) |
+                    (SAParams_p->Nonce_p[2] << 24) |
+                    TKB_CCM_FLAG_ADATA_L4 |
+                    ((TokenContext_Internal_p->ICVByteCount-2)*4);
+                break;
+            case SAB_AUTH_AES_GCM:
+                if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+                {
+                    TokenContext_Internal_p->protocol = TKB_PROTO_ESP_GCM_OUT;
+                }
+                else
+                {
+                    TokenContext_Internal_p->protocol = TKB_PROTO_ESP_GCM_IN;
+                }
+                break;
+            case SAB_AUTH_AES_GMAC:
+                if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+                {
+                    TokenContext_Internal_p->protocol = TKB_PROTO_ESP_GMAC_OUT;
+                }
+                else
+                {
+                    TokenContext_Internal_p->protocol = TKB_PROTO_ESP_GMAC_IN;
+                }
+                break;
+            default:
+                ;
+            }
+            break;
+        case SAB_AUTH_POLY1305:
+            TokenContext_Internal_p->ICVByteCount = 16;
+            if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+            {
+                TokenContext_Internal_p->protocol =
+                    TKB_PROTO_ESP_CHACHAPOLY_OUT;
+            }
+            else
+            {
+                TokenContext_Internal_p->protocol =
+                    TKB_PROTO_ESP_CHACHAPOLY_IN;
+            }
+            break;
+        default:
+            LOG_CRIT("TokenBuilder_BuildContext:"
+                     " unsupported authentication algorithm.\n");
+            return TKB_INVALID_PARAMETER;
+        }
+#else /* TKB_ENABLE_IPSEC_ESP */
+        LOG_CRIT("TokenBuilder_BuildContext: ESP not supported\n");
+        return TKB_INVALID_PARAMETER;
+#endif /* TKB_ENABLE_IPSEC_ESP */
+    }
+    else if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_AH) != 0)
+    {
+#ifdef TKB_ENABLE_IPSEC_AH
+
+#else /* TKB_ENABLE_IPSEC_AH */
+        LOG_CRIT("TokenBuilder_BuildContext: AH not supported\n");
+        return TKB_INVALID_PARAMETER;
+#endif /* TKB_ENABLE_IPSEC_AH */
+    }
+    else
+    {
+        LOG_CRIT("TokenBuilder_BuildContext: Neither ESP nor AH set\n");
+        return TKB_INVALID_PARAMETER;
+    }
+#ifdef TKB_ENABLE_EXTENDED_IPSEC
+    if ((SAParamsIPsec_p->IPsecFlags & SAB_IPSEC_EXT_PROCESSING) != 0)
+    {
+        TokenBuilder_Status_t Rc;
+
+        Rc = TokenBuilder_BuildContext_Extended(SAParams_p,
+                                                TokenContext_Internal_p);
+        return Rc;
+    }
+#endif
+    return TKB_STATUS_OK;
+}
+#endif
+
+
+#ifdef TKB_ENABLE_PROTO_SSLTLS
+/*----------------------------------------------------------------------------
+ * TokenBuilder_BuildContext_SSLTLS
+ *
+ * Create a Token Context Record for SSL/TLS/DTLS
+ *
+ * SAParams_p (input)
+ *   Points to the SA parameters data structure. It is important that
+ *   SABuilder_GetSIze() and SABuilder_BuildSA() have already been called
+ *   for this SA.
+ * TokenContext_Internal_p (output)
+ *   Buffer to hold the Token Context Record.
+ *
+ * Return:
+ * TKB_STATUS_OK if successful.
+ * TKB_INVALID_PARAMETER if any of the pointer parameters is NULL or if
+ *                      the contents of the SA parameters are invalid.
+ */
+static TokenBuilder_Status_t
+TokenBuilder_BuildContext_SSLTLS(
+    const SABuilder_Params_t * const SAParams_p,
+    TokenBuilder_Context_t * const TokenContext_Internal_p)
+{
+    SABuilder_Params_SSLTLS_t *SAParamsSSLTLS_p;
+    SAParamsSSLTLS_p = (SABuilder_Params_SSLTLS_t *)
+        (SAParams_p->ProtocolExtension_p);
+    if (SAParamsSSLTLS_p == NULL)
+    {
+        LOG_CRIT("TokenBuilder_BuildContext:"
+                 " SSL/TLS extension pointer is NULL\n");
+        return TKB_INVALID_PARAMETER;
+    }
+
+    TokenContext_Internal_p->ExtSeq = 0;
+    TokenContext_Internal_p->AntiReplay = 1;
+    TokenContext_Internal_p->IVOffset = 0;
+    TokenContext_Internal_p->DigestWordCount = 0;
+    TokenContext_Internal_p->u.generic.ESPFlags = 0;
+    if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+    {
+        TokenContext_Internal_p->protocol = TKB_PROTO_SSLTLS_OUT;
+        TokenContext_Internal_p->PadBlockByteCount = 1;
+        TokenContext_Internal_p->IVHandling = TKB_IV_OUTBOUND_CBC;
+    }
+    else
+    {
+        TokenContext_Internal_p->protocol = TKB_PROTO_SSLTLS_IN;
+        TokenContext_Internal_p->PadBlockByteCount = 1;
+        if (SAParams_p->CryptoAlgo != SAB_CRYPTO_NULL &&
+            SAParams_p->CryptoAlgo != SAB_CRYPTO_ARCFOUR)
+            TokenContext_Internal_p->TokenHeaderWord |=
+                TKB_HEADER_PAD_VERIFY;
+        TokenContext_Internal_p->IVHandling = TKB_IV_INBOUND_CBC;
+    }
+    TokenContext_Internal_p->SeqOffset = SAParams_p->OffsetSeqNum;
+
+    switch (SAParams_p->CryptoAlgo)
+    {
+    case SAB_CRYPTO_NULL:
+        TokenContext_Internal_p->IVByteCount = 0;
+        TokenContext_Internal_p->u.generic.UpdateHandling = TKB_UPD_NULL;
+        break;
+    case SAB_CRYPTO_ARCFOUR:
+        TokenContext_Internal_p->IVByteCount = 0;
+        TokenContext_Internal_p->u.generic.UpdateHandling = TKB_UPD_ARC4;
+        TokenContext_Internal_p->IVOffset = SAParams_p->OffsetIJPtr;
+        break;
+    case SAB_CRYPTO_DES:
+    case SAB_CRYPTO_3DES:
+        TokenContext_Internal_p->IVByteCount = 8;
+        TokenContext_Internal_p->PadBlockByteCount = 8;
+        TokenContext_Internal_p->u.generic.UpdateHandling = TKB_UPD_IV2;
+        TokenContext_Internal_p->IVOffset = SAParams_p->OffsetIV;
+        break;
+    case SAB_CRYPTO_AES:
+    case SAB_CRYPTO_SM4:
+    case SAB_CRYPTO_BC0:
+        if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_GCM)
+        {
+            TokenContext_Internal_p->IVByteCount = 8;
+            TokenContext_Internal_p->u.generic.UpdateHandling = TKB_UPD_NULL;
+            TokenContext_Internal_p->IVOffset = SAParams_p->OffsetIV;
+            if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+            {
+                TokenContext_Internal_p->IVHandling = TKB_IV_OUTBOUND_CTR;
+                if (SAParamsSSLTLS_p->version == SAB_TLS_VERSION_1_3)
+                {
+                    TokenContext_Internal_p->protocol =
+                        TKB_PROTO_TLS13_GCM_OUT;
+                }
+                else
+                {
+                    TokenContext_Internal_p->protocol =
+                        TKB_PROTO_SSLTLS_GCM_OUT;
+                }
+            }
+            else
+            {
+                TokenContext_Internal_p->IVHandling = TKB_IV_INBOUND_CTR;
+                if (SAParamsSSLTLS_p->version == SAB_TLS_VERSION_1_3)
+                {
+                    TokenContext_Internal_p->protocol =
+                        TKB_PROTO_TLS13_GCM_IN;
+                }
+                else
+                {
+                    TokenContext_Internal_p->protocol =
+                        TKB_PROTO_SSLTLS_GCM_IN;
+                }
+            }
+        }
+        else if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CCM)
+        {
+            TokenContext_Internal_p->IVByteCount = 8;
+            TokenContext_Internal_p->u.generic.UpdateHandling = TKB_UPD_NULL;
+            TokenContext_Internal_p->IVOffset = SAParams_p->OffsetIV;
+            if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+            {
+                TokenContext_Internal_p->IVHandling = TKB_IV_OUTBOUND_CTR;
+                if (SAParamsSSLTLS_p->version == SAB_TLS_VERSION_1_3)
+                {
+                    TokenContext_Internal_p->protocol =
+                        TKB_PROTO_TLS13_CCM_OUT;
+                }
+                else
+                {
+                    TokenContext_Internal_p->protocol =
+                        TKB_PROTO_SSLTLS_CCM_OUT;
+                }
+            }
+            else
+            {
+                TokenContext_Internal_p->IVHandling = TKB_IV_INBOUND_CTR;
+                if (SAParamsSSLTLS_p->version == SAB_TLS_VERSION_1_3)
+                {
+                    TokenContext_Internal_p->protocol =
+                        TKB_PROTO_TLS13_CCM_IN;
+                }
+                else
+                {
+                    TokenContext_Internal_p->protocol =
+                        TKB_PROTO_SSLTLS_CCM_IN;
+                }
+            }
+            if (SAParamsSSLTLS_p->ICVByteCount == 0)
+                TokenContext_Internal_p->ICVByteCount = 16;
+            else if (SAParamsSSLTLS_p->ICVByteCount == 8 ||
+                     SAParamsSSLTLS_p->ICVByteCount == 16)
+            {
+                TokenContext_Internal_p->ICVByteCount = SAParamsSSLTLS_p->ICVByteCount;
+            }
+            else
+            {
+                LOG_CRIT("TokenBuilder_BuildContext:"
+                         " TLS AES-CCM rquires tag length of 8 or 16\n");
+                return TKB_INVALID_PARAMETER;
+            }
+            TokenContext_Internal_p->u.generic.CCMSalt = TKB_CCM_FLAG_ADATA_L3 |
+                ((TokenContext_Internal_p->ICVByteCount-2)*4);
+        }
+        else
+        {
+            TokenContext_Internal_p->IVByteCount = 16;
+            TokenContext_Internal_p->PadBlockByteCount = 16;
+            TokenContext_Internal_p->u.generic.UpdateHandling = TKB_UPD_IV4;
+            TokenContext_Internal_p->IVOffset = SAParams_p->OffsetIV;
+        }
+        break;
+    case SAB_CRYPTO_CHACHA20:
+        TokenContext_Internal_p->IVByteCount = 0;
+        TokenContext_Internal_p->u.generic.UpdateHandling = TKB_UPD_NULL;
+        if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+        {
+            if (SAParamsSSLTLS_p->version == SAB_TLS_VERSION_1_3)
+            {
+                TokenContext_Internal_p->protocol = TKB_PROTO_TLS13_CHACHAPOLY_OUT;
+            }
+            else
+            {
+                TokenContext_Internal_p->protocol = TKB_PROTO_SSLTLS_CHACHAPOLY_OUT;
+            }
+        }
+        else
+        {
+            if (SAParamsSSLTLS_p->version == SAB_TLS_VERSION_1_3)
+            {
+                TokenContext_Internal_p->protocol = TKB_PROTO_TLS13_CHACHAPOLY_IN;
+            }
+            else
+            {
+                TokenContext_Internal_p->protocol = TKB_PROTO_SSLTLS_CHACHAPOLY_IN;
+            }
+        }
+        break;
+    default:
+        LOG_CRIT("TokenBuilder_BuildContext:"
+                 " unsupported crypto algorithm.\n");
+        return TKB_INVALID_PARAMETER;
+    }
+
+    /* For all inbound and ARCFOUR outbound packets there is
+       only one supported way to obtain the IV, which is already
+       taken care of. Now handle outbound CBC. */
+    if(SAParams_p->CryptoMode == SAB_CRYPTO_MODE_CBC &&
+       SAParams_p->direction == SAB_DIRECTION_OUTBOUND &&
+       SAParams_p->CryptoAlgo != SAB_CRYPTO_NULL)
+    {
+        switch (SAParams_p->IVSrc)
+        {
+        case SAB_IV_SRC_DEFAULT:
+        case SAB_IV_SRC_PRNG:
+            TokenContext_Internal_p->TokenHeaderWord |=
+                TKB_HEADER_IV_PRNG;
+            break;
+        case SAB_IV_SRC_SA: /* No action required */
+            break;
+        case SAB_IV_SRC_TOKEN:
+            if (TokenContext_Internal_p->IVByteCount == 8)
+            {
+                TokenContext_Internal_p->IVHandling =
+                    TKB_IV_OUTBOUND_TOKEN_2WORDS;
+                TokenContext_Internal_p->TokenHeaderWord |=
+                    TKB_HEADER_IV_TOKEN_2WORDS;
+            }
+            else
+            {
+                TokenContext_Internal_p->IVHandling =
+                    TKB_IV_OUTBOUND_TOKEN_4WORDS;
+                TokenContext_Internal_p->TokenHeaderWord |=
+                    TKB_HEADER_IV_TOKEN_4WORDS;
+            }
+            break;
+        default:
+            LOG_CRIT("TokenBuilder_BuildContext:"
+                     "Unsupported IV source\n");
+            return TKB_INVALID_PARAMETER;
+        }
+    }
+
+    /* In SSL and TLS1.0 the IV does not appear explicitly in the packet */
+    if (SAParamsSSLTLS_p->version == SAB_SSL_VERSION_3_0 ||
+        SAParamsSSLTLS_p->version == SAB_TLS_VERSION_1_0)
+        TokenContext_Internal_p->IVByteCount = 0;
+    else if (TokenContext_Internal_p->u.generic.UpdateHandling == TKB_UPD_IV2 ||
+             TokenContext_Internal_p->u.generic.UpdateHandling == TKB_UPD_IV4)
+        TokenContext_Internal_p->u.generic.UpdateHandling = TKB_UPD_BLK;
+
+    /* Sequence numbers appear explicitly in the packet in DTLS */
+    if (SAParamsSSLTLS_p->version == SAB_DTLS_VERSION_1_0 ||
+        SAParamsSSLTLS_p->version == SAB_DTLS_VERSION_1_2)
+    {
+        if ((SAParamsSSLTLS_p->SSLTLSFlags & SAB_DTLS_CAPWAP) != 0)
+            TokenContext_Internal_p->u.generic.ESPFlags |= TKB_DTLS_FLAG_CAPWAP;
+
+        if ((SAParamsSSLTLS_p->SSLTLSFlags & SAB_DTLS_NO_ANTI_REPLAY) != 0)
+            TokenContext_Internal_p->ExtSeq = 1;
+        else
+            TokenContext_Internal_p->ExtSeq = 1 +
+                SAParamsSSLTLS_p->SequenceMaskBitCount / 32;
+#ifdef TKB_ENABLE_EXTENDED_DTLS
+        if ((SAParamsSSLTLS_p->SSLTLSFlags &  SAB_DTLS_EXT_PROCESSING) != 0)
+        {
+            if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+            {
+                if ((SAParamsSSLTLS_p->SSLTLSFlags & SAB_DTLS_IPV6) != 0)
+                    TokenContext_Internal_p->hproto = TKB_HDR_IPV6_OUT_DTLS;
+                else
+                    TokenContext_Internal_p->hproto = TKB_HDR_IPV4_OUT_DTLS;
+            }
+            else
+            {
+                TokenContext_Internal_p->hproto = TKB_HDR_DTLS_UDP_IN;
+                if ((SAParamsSSLTLS_p->SSLTLSFlags &  SAB_DTLS_PLAINTEXT_HEADERS) != 0)
+                    TokenContext_Internal_p->u.generic.ESPFlags |= TKB_DTLS_FLAG_PLAINTEXT_HDR;
+            }
+        }
+#endif
+    }
+
+    /* Version field is not hashed in SSL 3.0. */
+    if (SAParamsSSLTLS_p->version == SAB_SSL_VERSION_3_0)
+        TokenContext_Internal_p->AntiReplay = 0;
+
+
+    switch(SAParams_p->AuthAlgo)
+    {
+    case SAB_AUTH_HMAC_MD5:
+    case SAB_AUTH_SSLMAC_MD5:
+        TokenContext_Internal_p->ICVByteCount = 16;
+        break;
+    case SAB_AUTH_HMAC_SHA1:
+    case SAB_AUTH_SSLMAC_SHA1:
+        TokenContext_Internal_p->ICVByteCount = 20;
+        break;
+    case SAB_AUTH_HMAC_SHA2_224:
+        TokenContext_Internal_p->ICVByteCount = 28;
+        break;
+    case SAB_AUTH_HMAC_SHA2_256:
+    case SAB_AUTH_HMAC_SM3:
+        TokenContext_Internal_p->ICVByteCount = 32;
+        break;
+    case SAB_AUTH_HMAC_SHA2_384:
+        TokenContext_Internal_p->ICVByteCount = 48;
+        break;
+    case SAB_AUTH_HMAC_SHA2_512:
+        TokenContext_Internal_p->ICVByteCount = 64;
+        break;
+    case SAB_AUTH_AES_GCM:
+        TokenContext_Internal_p->ICVByteCount = 16;
+        break;
+    case SAB_AUTH_AES_CCM:
+        /* Was already set earlier */
+        break;
+    case SAB_AUTH_POLY1305:
+        TokenContext_Internal_p->ICVByteCount = 16;
+        break;
+    default:
+        LOG_CRIT("TokenBuilder_BuildContext:"
+                 " unsupported authentication algorithm.\n");
+        return TKB_INVALID_PARAMETER;
+    }
+    if (SAParamsSSLTLS_p->ICVByteCount != 0 &&
+        SAParamsSSLTLS_p->ICVByteCount < TokenContext_Internal_p->ICVByteCount)
+    {
+        TokenContext_Internal_p->ICVByteCount = SAParamsSSLTLS_p->ICVByteCount;
+    }
+    return TKB_STATUS_OK;
+}
+#endif
+
+
+#ifdef TKB_ENABLE_PROTO_BASIC
+/*----------------------------------------------------------------------------
+ * TokenBuilder_BuildContext_Basic
+ *
+ * Create a Token Context Record for Basic crypto
+ *
+ * SAParams_p (input)
+ *   Points to the SA parameters data structure. It is important that
+ *   SABuilder_GetSIze() and SABuilder_BuildSA() have already been called
+ *   for this SA.
+ * TokenContext_Internal_p (output)
+ *   Buffer to hold the Token Context Record.
+ *
+ * Return:
+ * TKB_STATUS_OK if successful.
+ * TKB_INVALID_PARAMETER if any of the pointer parameters is NULL or if
+ *                      the contents of the SA parameters are invalid.
+ */
+static TokenBuilder_Status_t
+TokenBuilder_BuildContext_Basic(
+    const SABuilder_Params_t * const SAParams_p,
+    TokenBuilder_Context_t * const TokenContext_Internal_p)
+{
+    SABuilder_Params_Basic_t *SAParamsBasic_p;
+    SAParamsBasic_p = (SABuilder_Params_Basic_t *)
+        (SAParams_p->ProtocolExtension_p);
+    if (SAParamsBasic_p == NULL)
+    {
+        LOG_CRIT("TokenBuilder_BuildContext:"
+                 " Basic extension pointer is NULL\n");
+        return TKB_INVALID_PARAMETER;
+    }
+
+    TokenContext_Internal_p->ExtSeq = 0;
+    TokenContext_Internal_p->AntiReplay = 0;
+    TokenContext_Internal_p->IVOffset = 0;
+    TokenContext_Internal_p->SeqOffset = 0;
+    TokenContext_Internal_p->PadBlockByteCount = 1;
+    TokenContext_Internal_p->IVByteCount = 0;
+    TokenContext_Internal_p->ICVByteCount = 0;
+    TokenContext_Internal_p->DigestWordCount = 0;
+    TokenContext_Internal_p->IVHandling = TKB_IV_OUTBOUND_CBC;
+    TokenContext_Internal_p->u.generic.UpdateHandling = TKB_UPD_NULL;
+    TokenContext_Internal_p->u.generic.CCMSalt = 0;
+
+    if (SAParams_p->CryptoAlgo != SAB_CRYPTO_NULL)
+    {   /* Basic crypto */
+        if (SAParams_p->AuthAlgo == SAB_AUTH_NULL)
+        {
+            TokenContext_Internal_p->protocol = TKB_PROTO_BASIC_CRYPTO;
+        }
+        else if ((SAParamsBasic_p->BasicFlags & SAB_BASIC_FLAG_ENCRYPT_AFTER_HASH) != 0)
+        {
+            if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+            {
+                TokenContext_Internal_p->protocol = TKB_PROTO_BASIC_HASHENC;
+            }
+            else
+            {
+                TokenContext_Internal_p->protocol = TKB_PROTO_BASIC_DECHASH;
+                TokenContext_Internal_p->TokenHeaderWord |=
+                    TKB_HEADER_PAD_VERIFY;
+            }
+        }
+#ifdef TKB_ENABLE_CRYPTO_CHACHAPOLY
+        else if (SAParams_p->CryptoAlgo == SAB_CRYPTO_CHACHA20)
+        {
+            if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+            {
+                TokenContext_Internal_p->protocol = TKB_PROTO_BASIC_CHACHAPOLY_OUT;
+            }
+            else
+            {
+                TokenContext_Internal_p->protocol = TKB_PROTO_BASIC_CHACHAPOLY_IN;
+            }
+        }
+#endif
+        else
+        {
+            TokenContext_Internal_p->protocol = TKB_PROTO_BASIC_CRYPTHASH;
+        }
+        switch (SAParams_p->CryptoAlgo)
+        {
+        case SAB_CRYPTO_ARCFOUR:
+            TokenContext_Internal_p->IVByteCount = 0;
+            if (SAParams_p->CryptoMode != SAB_CRYPTO_MODE_STATELESS)
+                TokenContext_Internal_p->u.generic.UpdateHandling = TKB_UPD_ARC4;
+            TokenContext_Internal_p->IVOffset = SAParams_p->OffsetIJPtr;
+            break;
+        case SAB_CRYPTO_DES:
+        case SAB_CRYPTO_3DES:
+            TokenContext_Internal_p->IVByteCount = 8;
+            TokenContext_Internal_p->PadBlockByteCount = 8;
+            TokenContext_Internal_p->u.generic.UpdateHandling = TKB_UPD_IV2;
+            TokenContext_Internal_p->IVOffset = SAParams_p->OffsetIV;
+            break;
+        case SAB_CRYPTO_AES:
+        case SAB_CRYPTO_SM4:
+        case SAB_CRYPTO_BC0:
+            TokenContext_Internal_p->IVByteCount = 16;
+            TokenContext_Internal_p->PadBlockByteCount = 16;
+            TokenContext_Internal_p->u.generic.UpdateHandling = TKB_UPD_IV4;
+            TokenContext_Internal_p->IVOffset = SAParams_p->OffsetIV;
+            break;
+#ifdef TKB_ENABLE_CRYPTO_WIRELESS
+        case SAB_CRYPTO_KASUMI:
+            TokenContext_Internal_p->IVByteCount = 8;
+            TokenContext_Internal_p->PadBlockByteCount = 8;
+            TokenContext_Internal_p->IVHandling = TKB_IV_KASUMI_F8;
+            TokenContext_Internal_p->u.generic.UpdateHandling = TKB_UPD_NULL;
+            TokenContext_Internal_p->IVOffset = SAParams_p->OffsetIV;
+            break;
+        case SAB_CRYPTO_SNOW:
+            TokenContext_Internal_p->IVByteCount = 16;
+            TokenContext_Internal_p->PadBlockByteCount = 1;
+            TokenContext_Internal_p->IVHandling = TKB_IV_SNOW_UEA2;
+            TokenContext_Internal_p->u.generic.UpdateHandling = TKB_UPD_NULL;
+            TokenContext_Internal_p->IVOffset = SAParams_p->OffsetIV;
+            break;
+        case SAB_CRYPTO_ZUC:
+            TokenContext_Internal_p->IVByteCount = 16;
+            TokenContext_Internal_p->PadBlockByteCount = 1;
+            TokenContext_Internal_p->IVHandling = TKB_IV_ZUC_EEA3;
+            TokenContext_Internal_p->u.generic.UpdateHandling = TKB_UPD_NULL;
+            TokenContext_Internal_p->IVOffset = SAParams_p->OffsetIV;
+            break;
+#endif
+#ifdef TKB_ENABLE_CRYPTO_CHACHAPOLY
+        case SAB_CRYPTO_CHACHA20:
+            TokenContext_Internal_p->IVByteCount = 16;
+            TokenContext_Internal_p->PadBlockByteCount = 1;
+            TokenContext_Internal_p->u.generic.UpdateHandling = TKB_UPD_NULL;
+            break;
+#endif
+        default:
+            LOG_CRIT("TokenBuilder_BuildContext:"
+                     " unsupported crypto algorithm.\n");
+            return TKB_INVALID_PARAMETER;
+        }
+
+        switch (SAParams_p->CryptoMode)
+        {
+        case SAB_CRYPTO_MODE_ECB:
+            TokenContext_Internal_p->IVByteCount = 0;
+            TokenContext_Internal_p->IVHandling = TKB_IV_OUTBOUND_CBC;
+            TokenContext_Internal_p->u.generic.UpdateHandling = TKB_UPD_NULL;
+            break;
+        case SAB_CRYPTO_MODE_BASIC:
+        case SAB_CRYPTO_MODE_CBC:
+        case SAB_CRYPTO_MODE_ICM:
+        case SAB_CRYPTO_MODE_CFB:
+        case SAB_CRYPTO_MODE_OFB:
+        case SAB_CRYPTO_MODE_XTS:
+        case SAB_CRYPTO_MODE_XTS_STATEFUL:
+        case SAB_CRYPTO_MODE_CHACHA_CTR32:
+        case SAB_CRYPTO_MODE_CHACHA_CTR64:
+            if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_BASIC)
+            {
+                TokenContext_Internal_p->IVHandling = TKB_IV_OUTBOUND_CBC;
+                if (SAParams_p->CryptoAlgo == SAB_CRYPTO_KASUMI)
+                {
+                    TokenContext_Internal_p->IVByteCount = 0;
+                    TokenContext_Internal_p->u.generic.UpdateHandling = TKB_UPD_NULL;
+                    break;
+                }
+                else
+                {
+                    TokenContext_Internal_p->PadBlockByteCount = 1;
+                }
+            }
+            else if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_ICM)
+            {
+                TokenContext_Internal_p->PadBlockByteCount = 1;
+            }
+            else if (SAParams_p->CryptoMode == SAB_CRYPTO_MODE_XTS ||
+                     SAParams_p->CryptoMode == SAB_CRYPTO_MODE_XTS_STATEFUL)
+            {
+                TokenContext_Internal_p->PadBlockByteCount = 1;
+                TokenContext_Internal_p->protocol = TKB_PROTO_BASIC_XTS_CRYPTO;
+            }
+
+            if (SAParams_p->IVSrc == SAB_IV_SRC_TOKEN)
+            {
+                TokenContext_Internal_p->u.generic.UpdateHandling = TKB_UPD_NULL;
+                if (TokenContext_Internal_p->IVByteCount == 8)
+                {
+                    TokenContext_Internal_p->IVByteCount = 0;
+                    if ((SAParams_p->flags & SAB_FLAG_COPY_IV) != 0)
+                        TokenContext_Internal_p->IVHandling =
+                            TKB_IV_COPY_TOKEN_2WORDS;
+                    else
+                        TokenContext_Internal_p->IVHandling =
+                            TKB_IV_OUTBOUND_TOKEN_2WORDS;
+                    TokenContext_Internal_p->TokenHeaderWord |=
+                        TKB_HEADER_IV_TOKEN_2WORDS;
+                }
+                else
+                {
+                    TokenContext_Internal_p->IVByteCount = 0;
+                    if ((SAParams_p->flags & SAB_FLAG_COPY_IV) != 0)
+                        TokenContext_Internal_p->IVHandling =
+                            TKB_IV_COPY_TOKEN_4WORDS;
+                    else
+                        TokenContext_Internal_p->IVHandling =
+                            TKB_IV_OUTBOUND_TOKEN_4WORDS;
+                    TokenContext_Internal_p->TokenHeaderWord |=
+                        TKB_HEADER_IV_TOKEN_4WORDS;
+                }
+            }
+            else if (SAParams_p->IVSrc == SAB_IV_SRC_INPUT)
+            {
+                TokenContext_Internal_p->u.generic.UpdateHandling = TKB_UPD_NULL;
+                if ((SAParams_p->flags & SAB_FLAG_COPY_IV) != 0)
+                    TokenContext_Internal_p->IVHandling = TKB_IV_COPY_CBC;
+                else
+                    TokenContext_Internal_p->IVHandling = TKB_IV_INBOUND_CBC;
+            }
+            else
+            {
+                if(SAParams_p->IVSrc ==  SAB_IV_SRC_PRNG)
+                {
+                    TokenContext_Internal_p->TokenHeaderWord |=
+                        TKB_HEADER_IV_PRNG;
+                    TokenContext_Internal_p->u.generic.UpdateHandling = TKB_UPD_NULL;
+                }
+                if ((SAParams_p->flags & SAB_FLAG_COPY_IV) != 0)
+                {
+                    if (TokenContext_Internal_p->IVByteCount==8)
+                        TokenContext_Internal_p->IVHandling =
+                            TKB_IV_OUTBOUND_2WORDS;
+                    else
+                        TokenContext_Internal_p->IVHandling =
+                            TKB_IV_OUTBOUND_4WORDS;
+                }
+                TokenContext_Internal_p->IVByteCount = 0;
+            }
+
+            break;
+        case SAB_CRYPTO_MODE_CTR:
+        case SAB_CRYPTO_MODE_CCM:
+        case SAB_CRYPTO_MODE_GCM:
+        case SAB_CRYPTO_MODE_GMAC:
+            TokenContext_Internal_p->PadBlockByteCount = 1;
+            TokenContext_Internal_p->u.generic.UpdateHandling = TKB_UPD_NULL;
+
+            if (SAParams_p->IVSrc == SAB_IV_SRC_TOKEN)
+            {
+                TokenContext_Internal_p->IVByteCount = 0;
+                if ((SAParams_p->flags & SAB_FLAG_COPY_IV) != 0)
+                    TokenContext_Internal_p->IVHandling =
+                        TKB_IV_COPY_TOKEN_4WORDS;
+                else
+                    TokenContext_Internal_p->IVHandling =
+                        TKB_IV_OUTBOUND_TOKEN_4WORDS;
+                TokenContext_Internal_p->TokenHeaderWord |=
+                    TKB_HEADER_IV_TOKEN_4WORDS;
+            }
+            else if (SAParams_p->IVSrc == SAB_IV_SRC_INPUT)
+            {
+                TokenContext_Internal_p->IVByteCount = 8;
+                if ((SAParams_p->flags & SAB_FLAG_COPY_IV) != 0)
+                    TokenContext_Internal_p->IVHandling = TKB_IV_COPY_CTR;
+                else
+                    TokenContext_Internal_p->IVHandling = TKB_IV_INBOUND_CTR;
+            }
+            else
+            {
+                TokenContext_Internal_p->IVByteCount = 0;
+                if ((SAParams_p->flags & SAB_FLAG_COPY_IV) != 0)
+                    TokenContext_Internal_p->IVHandling = TKB_IV_OUTBOUND_CTR;
+            }
+            break;
+#ifdef TKB_ENABLE_CRYPTO_WIRELESS
+        case SAB_CRYPTO_MODE_F8:
+        case SAB_CRYPTO_MODE_UEA2:
+        case SAB_CRYPTO_MODE_EEA3:
+            TokenContext_Internal_p->PadBlockByteCount = 1;
+            TokenContext_Internal_p->u.generic.CCMSalt =
+                (SAParamsBasic_p->bearer << 3) |
+                (SAParamsBasic_p->direction<<2);
+            if (TokenContext_Internal_p->IVByteCount == 8)
+                TokenContext_Internal_p->TokenHeaderWord |=
+                    TKB_HEADER_IV_TOKEN_2WORDS;
+            else
+                TokenContext_Internal_p->TokenHeaderWord |=
+                    TKB_HEADER_IV_TOKEN_4WORDS;
+            TokenContext_Internal_p->IVByteCount = 0;
+            break;
+#endif
+            default:
+                ;
+        }
+    }
+    else if (SAParams_p->AuthAlgo == SAB_AUTH_NULL)
+    {
+        TokenContext_Internal_p->protocol = TKB_PROTO_BASIC_BYPASS;
+    }
+    else if (SAParamsBasic_p->BasicFlags & SAB_BASIC_FLAG_HMAC_PRECOMPUTE &&
+             SAParams_p->OffsetDigest1 != 0)
+    {
+        TokenContext_Internal_p->protocol = TKB_PROTO_BASIC_HMAC_PRECOMPUTE;
+    }
+    else
+    {
+        TokenContext_Internal_p->protocol = TKB_PROTO_BASIC_HASH;
+    }
+    if (SAParams_p->AuthAlgo != SAB_AUTH_NULL)
+    {   /* Basic hash */
+        if ((SAParams_p->flags & (SAB_FLAG_HASH_SAVE|
+                                      SAB_FLAG_HASH_INTERMEDIATE)) != 0)
+        {
+            /* We intend to store the hash state.*/
+            TokenContext_Internal_p->SeqOffset = SAParams_p->OffsetDigest0;
+        }
+        if(SAParams_p->CryptoAlgo == SAB_CRYPTO_NULL)
+        {
+            /* Use ExtSeq variable to specify that payload will be copied */
+            if ((SAParams_p->flags & SAB_FLAG_SUPPRESS_PAYLOAD) == 0)
+                TokenContext_Internal_p->ExtSeq = 1;
+        }
+        else
+        {
+            /* Use ExtSeq variable to specify that header
+             * (authenticated data( will be copied */
+            if ((SAParams_p->flags & SAB_FLAG_SUPPRESS_HEADER) == 0)
+                TokenContext_Internal_p->ExtSeq = 1;
+        }
+        switch(SAParams_p->AuthAlgo)
+        {
+        case SAB_AUTH_HASH_MD5:
+            TokenContext_Internal_p->ICVByteCount = 16;
+            TokenContext_Internal_p->DigestWordCount = 16 + 4;
+            break;
+        case SAB_AUTH_HMAC_MD5:
+            TokenContext_Internal_p->ICVByteCount = 16;
+            TokenContext_Internal_p->DigestWordCount = 4;
+            break;
+        case SAB_AUTH_HASH_SHA1:
+            TokenContext_Internal_p->ICVByteCount = 20;
+            TokenContext_Internal_p->DigestWordCount = 16 + 5;
+            break;
+        case SAB_AUTH_HMAC_SHA1:
+            TokenContext_Internal_p->ICVByteCount = 20;
+            TokenContext_Internal_p->DigestWordCount = 5;
+            break;
+        case SAB_AUTH_HASH_SHA2_224:
+            TokenContext_Internal_p->ICVByteCount = 32;
+            TokenContext_Internal_p->DigestWordCount = 16 + 8;
+            break;
+        case SAB_AUTH_HMAC_SHA2_224:
+            TokenContext_Internal_p->ICVByteCount = 32;
+            TokenContext_Internal_p->DigestWordCount = 8;
+            break;
+        case SAB_AUTH_HASH_SHA2_256:
+        case SAB_AUTH_HASH_SM3:
+            TokenContext_Internal_p->ICVByteCount = 32;
+            TokenContext_Internal_p->DigestWordCount = 16 + 8;
+            break;
+        case SAB_AUTH_HMAC_SHA2_256:
+        case SAB_AUTH_HMAC_SM3:
+            TokenContext_Internal_p->ICVByteCount = 32;
+            TokenContext_Internal_p->DigestWordCount = 8;
+            break;
+        case SAB_AUTH_HASH_SHA2_384:
+            TokenContext_Internal_p->ICVByteCount = 64;
+            TokenContext_Internal_p->DigestWordCount = 16 + 16;
+            break;
+        case SAB_AUTH_HMAC_SHA2_384:
+            if ((SAParamsBasic_p->BasicFlags & SAB_BASIC_FLAG_ENCRYPT_AFTER_HASH) != 0)
+                TokenContext_Internal_p->ICVByteCount = 48;
+            else
+                TokenContext_Internal_p->ICVByteCount = 64;
+            TokenContext_Internal_p->DigestWordCount = 16;
+            break;
+        case SAB_AUTH_HASH_SHA2_512:
+            TokenContext_Internal_p->ICVByteCount = 64;
+            TokenContext_Internal_p->DigestWordCount = 16 + 16;
+            break;
+        case SAB_AUTH_HMAC_SHA2_512:
+            TokenContext_Internal_p->ICVByteCount = 64;
+            TokenContext_Internal_p->DigestWordCount = 16;
+            break;
+        case SAB_AUTH_HASH_SHA3_224:
+        case SAB_AUTH_HMAC_SHA3_224:
+        case SAB_AUTH_KEYED_HASH_SHA3_224:
+            TokenContext_Internal_p->ICVByteCount = 28;
+            TokenContext_Internal_p->DigestWordCount = 7;
+            break;
+        case SAB_AUTH_HASH_SHA3_256:
+        case SAB_AUTH_HMAC_SHA3_256:
+        case SAB_AUTH_KEYED_HASH_SHA3_256:
+            TokenContext_Internal_p->ICVByteCount = 32;
+            TokenContext_Internal_p->DigestWordCount = 8;
+            break;
+        case SAB_AUTH_HASH_SHA3_384:
+        case SAB_AUTH_HMAC_SHA3_384:
+        case SAB_AUTH_KEYED_HASH_SHA3_384:
+            TokenContext_Internal_p->ICVByteCount = 48;
+            TokenContext_Internal_p->DigestWordCount = 12;
+            break;
+        case SAB_AUTH_HASH_SHA3_512:
+        case SAB_AUTH_HMAC_SHA3_512:
+        case SAB_AUTH_KEYED_HASH_SHA3_512:
+            TokenContext_Internal_p->ICVByteCount = 64;
+            TokenContext_Internal_p->DigestWordCount = 16;
+            break;
+
+        case SAB_AUTH_AES_XCBC_MAC:
+        case SAB_AUTH_AES_CMAC_128:
+        case SAB_AUTH_AES_CMAC_192:
+        case SAB_AUTH_AES_CMAC_256:
+            TokenContext_Internal_p->ICVByteCount = 16;
+            TokenContext_Internal_p->DigestWordCount = 4;
+            break;
+        case SAB_AUTH_AES_CCM:
+            if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+                TokenContext_Internal_p->protocol = TKB_PROTO_BASIC_CCM_OUT;
+            else
+                TokenContext_Internal_p->protocol = TKB_PROTO_BASIC_CCM_IN;
+            TokenContext_Internal_p->ICVByteCount = 16;
+            TokenContext_Internal_p->DigestWordCount = 4;
+            // Adjust byte count now as it influences the SALT value.
+            if (SAParamsBasic_p->ICVByteCount != 0 &&
+                SAParamsBasic_p->ICVByteCount <
+                TokenContext_Internal_p->ICVByteCount)
+                TokenContext_Internal_p->ICVByteCount =
+                    SAParamsBasic_p->ICVByteCount;
+            TokenContext_Internal_p->u.generic.CCMSalt =
+                (SAParams_p->Nonce_p[0] << 8) |
+                (SAParams_p->Nonce_p[1] << 16) |
+                (SAParams_p->Nonce_p[2] << 24) |
+                TKB_CCM_FLAG_ADATA_L4 |
+                ((TokenContext_Internal_p->ICVByteCount-2)*4);
+            break;
+        case SAB_AUTH_AES_GCM:
+            if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+                TokenContext_Internal_p->protocol = TKB_PROTO_BASIC_GCM_OUT;
+            else
+                TokenContext_Internal_p->protocol = TKB_PROTO_BASIC_GCM_IN;
+            TokenContext_Internal_p->ICVByteCount = 16;
+            TokenContext_Internal_p->DigestWordCount = 4;
+            break;
+        case SAB_AUTH_AES_GMAC:
+            if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+                TokenContext_Internal_p->protocol = TKB_PROTO_BASIC_GMAC_OUT;
+            else
+                TokenContext_Internal_p->protocol = TKB_PROTO_BASIC_GMAC_IN;
+            TokenContext_Internal_p->ICVByteCount = 16;
+            TokenContext_Internal_p->DigestWordCount = 4;
+            break;
+#ifdef TKB_ENABLE_CRYPTO_WIRELESS
+        case SAB_AUTH_KASUMI_F9:
+            TokenContext_Internal_p->protocol = TKB_PROTO_BASIC_KASUMI_HASH;
+            TokenContext_Internal_p->ICVByteCount = 4;
+            TokenContext_Internal_p->DigestWordCount = 4;
+            TokenContext_Internal_p->u.generic.CCMSalt =
+                SAParamsBasic_p->fresh;
+            break;
+        case SAB_AUTH_SNOW_UIA2:
+            TokenContext_Internal_p->protocol = TKB_PROTO_BASIC_SNOW_HASH;
+            TokenContext_Internal_p->ICVByteCount = 4;
+            TokenContext_Internal_p->DigestWordCount = 4;
+            TokenContext_Internal_p->u.generic.CCMSalt =
+                SAParamsBasic_p->fresh;
+            break;
+        case SAB_AUTH_ZUC_EIA3:
+            TokenContext_Internal_p->protocol = TKB_PROTO_BASIC_ZUC_HASH;
+            TokenContext_Internal_p->ICVByteCount = 4;
+            TokenContext_Internal_p->DigestWordCount = 4;
+            TokenContext_Internal_p->u.generic.CCMSalt =
+                (SAParamsBasic_p->bearer << 3);
+            break;
+#endif
+#ifdef TKB_ENABLE_CRYPTO_CHACHAPOLY
+        case SAB_AUTH_KEYED_HASH_POLY1305:
+        case SAB_AUTH_POLY1305:
+            TokenContext_Internal_p->ICVByteCount = 16;
+            TokenContext_Internal_p->DigestWordCount = 4;
+            break;
+#endif
+        default:
+            LOG_CRIT("TokenBuilder_BuildContext:"
+                     " unsupported authentication algorithm.\n");
+            return TKB_INVALID_PARAMETER;
+        }
+        if (SAParamsBasic_p->ICVByteCount != 0 &&
+            SAParamsBasic_p->ICVByteCount <
+            TokenContext_Internal_p->ICVByteCount)
+            TokenContext_Internal_p->ICVByteCount =
+                SAParamsBasic_p->ICVByteCount;
+        if ((SAParamsBasic_p->BasicFlags & SAB_BASIC_FLAG_EXTRACT_ICV) != 0 ||
+            ((SAParams_p->AuthAlgo == SAB_AUTH_AES_CCM ||
+                 SAParams_p->AuthAlgo == SAB_AUTH_AES_GCM ||
+              SAParams_p->AuthAlgo == SAB_AUTH_AES_GMAC) &&
+             TokenContext_Internal_p->SeqOffset == 0))
+            TokenContext_Internal_p->AntiReplay =
+                TokenContext_Internal_p->ICVByteCount;
+    }
+    return TKB_STATUS_OK;
+}
+#endif
+
+
+#ifdef TKB_ENABLE_PROTO_SRTP
+/*----------------------------------------------------------------------------
+ * TokenBuilder_BuildContext_SRTP
+ *
+ * Create a Token Context Record for SRTP
+ *
+ * SAParams_p (input)
+ *   Points to the SA parameters data structure. It is important that
+ *   SABuilder_GetSIze() and SABuilder_BuildSA() have already been called
+ *   for this SA.
+ * TokenContext_Internal_p (output)
+ *   Buffer to hold the Token Context Record.
+ *
+ * Return:
+ * TKB_STATUS_OK if successful.
+ * TKB_INVALID_PARAMETER if any of the pointer parameters is NULL or if
+ *                      the contents of the SA parameters are invalid.
+ */
+static TokenBuilder_Status_t
+TokenBuilder_BuildContext_SRTP(
+    const SABuilder_Params_t * const SAParams_p,
+    TokenBuilder_Context_t * const TokenContext_Internal_p)
+{
+    // Note: SRTP may not make use of the Token Context fields
+    // CW0, CW1 CCMAalt and UpdateHandling as they occupy the same
+    // space as the SaltKey fields.
+    SABuilder_Params_SRTP_t *SAParamsSRTP_p;
+    SAParamsSRTP_p = (SABuilder_Params_SRTP_t *)
+        (SAParams_p->ProtocolExtension_p);
+    if (SAParamsSRTP_p == NULL)
+    {
+        LOG_CRIT("TokenBuilder_BuildContext:"
+                 " SRTP extension pointer is NULL\n");
+        return TKB_INVALID_PARAMETER;
+    }
+
+    if (SAParams_p->direction == SAB_DIRECTION_OUTBOUND)
+        TokenContext_Internal_p->protocol = TKB_PROTO_SRTP_OUT;
+    else
+        TokenContext_Internal_p->protocol = TKB_PROTO_SRTP_IN;
+
+    TokenContext_Internal_p->ICVByteCount = SAParamsSRTP_p->ICVByteCount;
+
+    if (SAParams_p->CryptoAlgo != SAB_CRYPTO_NULL)
+    {
+        TokenContext_Internal_p->IVHandling = TKB_IV_OUTBOUND_TOKEN_SRTP;
+
+        TokenContext_Internal_p->IVByteCount = 16;
+        TokenContext_Internal_p->TokenHeaderWord |=
+            TKB_HEADER_IV_TOKEN_4WORDS;
+        if (SAParams_p->Nonce_p == NULL)
+        {
+            LOG_CRIT("TokenBuilder_BuildContext: NULL nonce pointer.\n");
+            return TKB_INVALID_PARAMETER;
+        }
+
+        TokenContext_Internal_p->u.srtp.SaltKey0 =
+            (SAParams_p->Nonce_p[0]) |
+            (SAParams_p->Nonce_p[1] << 8) |
+            (SAParams_p->Nonce_p[2] << 16) |
+            (SAParams_p->Nonce_p[3] << 24);
+        TokenContext_Internal_p->u.srtp.SaltKey1 =
+            (SAParams_p->Nonce_p[4]) |
+            (SAParams_p->Nonce_p[5] << 8) |
+            (SAParams_p->Nonce_p[6] << 16) |
+            (SAParams_p->Nonce_p[7] << 24);
+        TokenContext_Internal_p->u.srtp.SaltKey2 =
+            (SAParams_p->Nonce_p[8]) |
+            (SAParams_p->Nonce_p[9] << 8) |
+            (SAParams_p->Nonce_p[10] << 16) |
+            (SAParams_p->Nonce_p[11] << 24);
+        TokenContext_Internal_p->u.srtp.SaltKey3 =
+            (SAParams_p->Nonce_p[12]) |
+            (SAParams_p->Nonce_p[13] << 8);
+    }
+    else
+    {
+        TokenContext_Internal_p->IVHandling = TKB_IV_OUTBOUND_CBC;
+        TokenContext_Internal_p->IVByteCount = 0;
+    }
+
+    if ((SAParamsSRTP_p->SRTPFlags & SAB_SRTP_FLAG_SRTCP) != 0)
+    {
+        TokenContext_Internal_p->ExtSeq = 4;
+    }
+    else
+    {
+        TokenContext_Internal_p->ExtSeq = 0;
+    }
+
+    if ((SAParamsSRTP_p->SRTPFlags & SAB_SRTP_FLAG_INCLUDE_MKI) != 0)
+    {
+        TokenContext_Internal_p->AntiReplay = 4;
+    }
+    else
+    {
+        TokenContext_Internal_p->AntiReplay = 0;
+    }
+    return TKB_STATUS_OK;
+}
+#endif
+
+
+/*----------------------------------------------------------------------------
+ * TokenBuilder_BuildContext
+ *
+ * Create a Token Context Record.
+ *
+ * SAParams_p (input)
+ *   Points to the SA parameters data structure. It is important that
+ *   SABuilder_GetSIze() and SABuilder_BuildSA() have already been called
+ *   for this SA.
+ * TokenContext_p (output)
+ *   Buffer to hold the Token Context Record. It must point to a valid
+ *   storage buffer that is large enough to hold the Token
+ *   Context. Before calling this function, the application must call
+ *   TokeBuilder_GetContextSize() with the same SA parameters and
+ *   allocate a buffer of that size.
+ *
+ * Return:
+ * TKB_STATUS_OK if successful.
+ * TKB_INVALID_PARAMETER if any of the pointer parameters is NULL or if
+ *                      the contents of the SA parameters are invalid.
+ */
+TokenBuilder_Status_t
+TokenBuilder_BuildContext(
+    const SABuilder_Params_t * const SAParams_p,
+    void * const TokenContext_p
+    )
+{
+    TokenBuilder_Context_t *TokenContext_Internal_p =
+        (TokenBuilder_Context_t *)TokenContext_p;
+    TokenBuilder_Status_t Rc;
+#ifdef TKB_STRICT_ARGS_CHECK
+    if (SAParams_p == NULL || TokenContext_p == NULL)
+    {
+        LOG_CRIT("TokenBuilder_BuildContext: NULL pointer supplied\n");
+        return TKB_INVALID_PARAMETER;
+    }
+#endif
+
+    TokenContext_Internal_p->TokenHeaderWord = TKB_HEADER_DEFAULT;
+
+    TokenContext_Internal_p->u.generic.CW0 = SAParams_p->CW0;
+    TokenContext_Internal_p->u.generic.CW1 = SAParams_p->CW1;
+    TokenContext_Internal_p->hproto = TKB_HDR_BYPASS;
+    switch (SAParams_p->protocol)
+    {
+#ifdef TKB_ENABLE_PROTO_IPSEC
+    case SAB_PROTO_IPSEC:
+        Rc = TokenBuilder_BuildContext_IPsec(SAParams_p,
+                                             TokenContext_Internal_p);
+    break;
+#endif  /* TKB_ENABLE_PROTO_IPSEC */
+#ifdef TKB_ENABLE_PROTO_SSLTLS
+    case SAB_PROTO_SSLTLS:
+        Rc = TokenBuilder_BuildContext_SSLTLS(SAParams_p,
+                                             TokenContext_Internal_p);
+    break;
+#endif
+#ifdef TKB_ENABLE_PROTO_BASIC
+    case SAB_PROTO_BASIC:
+        Rc = TokenBuilder_BuildContext_Basic(SAParams_p,
+                                             TokenContext_Internal_p);
+    break;
+#endif
+#ifdef TKB_ENABLE_PROTO_SRTP
+    case SAB_PROTO_SRTP:
+        Rc = TokenBuilder_BuildContext_SRTP(SAParams_p,
+                                             TokenContext_Internal_p);
+    break;
+#endif
+    default:
+        LOG_CRIT("TokenBuilder_BuildContext: unsupported protocol.\n");
+        return TKB_INVALID_PARAMETER;
+    }
+
+    if (Rc != TKB_STATUS_OK)
+    {
+        return Rc;
+    }
+
+    if (TokenContext_Internal_p->protocol != TKB_PROTO_BASIC_HMAC_PRECOMPUTE &&
+        SAParams_p->OffsetDigest1 != 0 &&
+        SAParams_p->AuthKey2_p == NULL)
+    {
+        /* HMAC key desired, but not supplied, convert context temporarily
+           to context prepare context. After the first token, the Token
+           Builder will switch it back */
+        TokenContext_Internal_p->protocol_next =
+            TokenContext_Internal_p->protocol;
+        TokenContext_Internal_p->hproto_next =
+            TokenContext_Internal_p->hproto;
+        TokenContext_Internal_p->IVHandling_next =
+            TokenContext_Internal_p->IVHandling;
+        TokenContext_Internal_p->HeaderWordFields_next =
+            (TokenContext_Internal_p->TokenHeaderWord >> 22) & MASK_8_BITS;
+        TokenContext_Internal_p->protocol = TKB_PROTO_BASIC_HMAC_CTXPREPARE;
+        TokenContext_Internal_p->hproto = TKB_HDR_BYPASS;
+        TokenContext_Internal_p->IVHandling = TKB_IV_INBOUND_CTR;
+        /* Clear fields in Token Header word, to prevent IV from token etc.*/
+        TokenContext_Internal_p->TokenHeaderWord &= 0xc03fffff;
+        TokenContext_Internal_p->DigestWordCount =
+            SAParams_p->OffsetDigest1 - SAParams_p->OffsetDigest0;
+        TokenContext_Internal_p->DigestOffset = SAParams_p->OffsetDigest0;
+    }
+
+    LOG_INFO("TokenBuilderBuildContext: created context, header word=%08x\n"
+             "  proto=%d hproto=%d padalign=%d ivsize=%d icvsize=%d\n"
+             "  seqoffset=%d extseq=%d antireplay=%d ivhandling=%d\n",
+             TokenContext_Internal_p->TokenHeaderWord,
+             TokenContext_Internal_p->protocol,
+             TokenContext_Internal_p->hproto,
+             TokenContext_Internal_p->PadBlockByteCount,
+             TokenContext_Internal_p->IVByteCount,
+             TokenContext_Internal_p->ICVByteCount,
+             TokenContext_Internal_p->SeqOffset,
+             TokenContext_Internal_p->ExtSeq,
+             TokenContext_Internal_p->AntiReplay,
+             TokenContext_Internal_p->IVHandling);
+
+    return TKB_STATUS_OK;
+}
+
+
+
+
+/* end of file token_builder_context.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/token/token_builder_core.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/token/token_builder_core.c
new file mode 100644
index 0000000..1cdba87
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/builder/token/token_builder_core.c
@@ -0,0 +1,5650 @@
+/* File token_builder_core.c
+   code generated by tbgen.py */
+
+/*****************************************************************************
+* Copyright (c) 2011-2022 by Rambus, Inc. and/or its subsidiaries.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+****************************************************************************/
+
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "token_builder.h"
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+#include "c_token_builder.h"
+#include "basic_defs.h"
+#include "clib.h"
+#include "token_builder_internal.h"
+#include "token_builder_macros.h"
+
+#include "log.h"
+
+TokenBuilder_Status_t
+TokenBuilder_GetSize(
+    const void * const TokenContext_p,
+    unsigned int * const TokenWord32Count_p
+    )
+{
+    TokenBuilder_Context_t ContextCopy;
+    TokenBuilder_Context_t *TokenContext_Internal_p = &ContextCopy;
+    unsigned int WordCountOld = 0;
+
+
+    uint32_t proto;
+#if (TKB_HAVE_PROTO_IPSEC == 1u && TKB_HAVE_EXTENDED_IPSEC == 1u)
+    uint32_t hproto;
+#endif
+#if TKB_HAVE_PROTO_BASIC == 1u
+    uint32_t seq_offset;
+#endif
+#if TKB_HAVE_PROTO_SSLTLS == 1u || TKB_HAVE_PROTO_BASIC == 1u
+    uint32_t ivlen;
+#endif
+#if TKB_HAVE_PROTO_IPSEC == 1u || TKB_HAVE_PROTO_SRTP == 1u
+    uint32_t icvlen;
+#endif
+    uint32_t ivhandling;
+#if TKB_HAVE_PROTO_IPSEC == 1u || TKB_HAVE_PROTO_SSLTLS == 1u || TKB_HAVE_PROTO_BASIC == 1u || TKB_HAVE_CRYPTO_WIRELESS == 1u || TKB_HAVE_PROTO_SRTP == 1u
+    uint32_t extseq;
+#endif
+#if TKB_HAVE_PROTO_SSLTLS == 1u || TKB_HAVE_PROTO_SRTP == 1u || TKB_HAVE_PROTO_IPSEC == 1u
+    uint32_t antireplay;
+#endif
+#if TKB_HAVE_PROTO_SSLTLS == 1u || TKB_HAVE_PROTO_BASIC == 1u || TKB_HAVE_CRYPTO_XTS == 1u
+    uint32_t upd_handling;
+#endif
+#if TKB_HAVE_PROTO_SSLTLS == 1u || TKB_HAVE_PROTO_BASIC == 1u
+    uint32_t cipher_is_aes;
+#endif
+#if TKB_HAVE_PROTO_BASIC == 1u
+    uint32_t hstatelen;
+#endif
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+    uint32_t capwap_out;
+#endif
+#if (TKB_HAVE_PROTO_IPSEC == 1u && TKB_HAVE_EXTENDED_IPSEC == 1u)
+    uint32_t is_nat;
+#endif
+
+#ifdef TKB_STRICT_ARGS_CHECK
+    if (TokenWord32Count_p == NULL || TokenContext_p == NULL)
+    {
+        LOG_CRIT("TokenBuilder_GetSize: NULL pointer supplied\n");
+        return TKB_INVALID_PARAMETER;
+    }
+#endif
+    memcpy(TokenContext_Internal_p, TokenContext_p, sizeof(ContextCopy));
+
+redo:
+    *TokenWord32Count_p = TKB_TOKEN_HEADER_WORD_COUNT;
+
+    *TokenWord32Count_p += 3u;
+    ivhandling = EVAL_ivhandling();
+    if (ivhandling >= 8u)
+    {
+        if (ivhandling < 10u)
+        {
+            *TokenWord32Count_p += 2u;
+        }
+        else if (ivhandling > 13u)
+        {
+            *TokenWord32Count_p += 4u;
+        }
+        else if (ivhandling == 10u)
+        {
+            *TokenWord32Count_p += 4u;
+        }
+        else if (ivhandling == 11u)
+        {
+            *TokenWord32Count_p += 2u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 4u;
+        }
+    }
+    *TokenWord32Count_p += 1u;
+#if TKB_HAVE_PROTO_IPSEC == 1u
+#if TKB_HAVE_EXTENDED_IPSEC == 1u
+    hproto = EVAL_hproto();
+    switch(hproto)
+    {
+    case 5: /* ipv4_out_transp */
+        *TokenWord32Count_p += 2u;
+        break;
+    case 1: /* ipv4_out_transp_nohdrproc */
+        *TokenWord32Count_p += 1u;
+        break;
+    case 11: /* ipv6_out_transp */
+        *TokenWord32Count_p += 5u;
+        break;
+    case 2: /* ipv4_out_tunnel */
+        *TokenWord32Count_p += 6u;
+        break;
+    case 7: /* ipv6_out_tunnel */
+        *TokenWord32Count_p += 11u;
+        break;
+    case 6: /* ipv4_in_transp */
+        *TokenWord32Count_p += 2u;
+        break;
+    case 3: /* ipv4_in_transp_nohdrproc */
+        *TokenWord32Count_p += 1u;
+        break;
+    case 12: /* ipv6_in_transp */
+        *TokenWord32Count_p += 5u;
+        break;
+    case 4: /* ipv4_in_tunnel */
+    case 8: /* ipv6_in_tunnel */
+    case 24: /* ipv4_in_tunnel_natt */
+    case 28: /* ipv6_in_tunnel_natt */
+        *TokenWord32Count_p += 2u;
+        break;
+    case 25: /* ipv4_out_transp_natt */
+        *TokenWord32Count_p += 1u;
+        is_nat = EVAL_is_nat();
+        if (is_nat != 0u)
+        {
+            *TokenWord32Count_p += 4u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        *TokenWord32Count_p += 3u;
+        break;
+    case 31: /* ipv6_out_transp_natt */
+        *TokenWord32Count_p += 17u;
+        break;
+    case 22: /* ipv4_out_tunnel_natt */
+        *TokenWord32Count_p += 8u;
+        break;
+    case 27: /* ipv6_out_tunnel_natt */
+        *TokenWord32Count_p += 13u;
+        break;
+    case 26: /* ipv4_in_transp_natt */
+        *TokenWord32Count_p += 1u;
+        is_nat = EVAL_is_nat();
+        if (is_nat != 0u)
+        {
+            *TokenWord32Count_p += 5u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        *TokenWord32Count_p += 1u;
+        break;
+    case 32: /* ipv6_in_transp_natt */
+        *TokenWord32Count_p += 15u;
+        break;
+    case 13: /* ipv4_out_dtls */
+        *TokenWord32Count_p += 5u;
+        break;
+    case 33: /* ipv6_out_dtls */
+        *TokenWord32Count_p += 5u;
+        break;
+    }
+#endif
+#endif
+    proto = EVAL_proto();
+    switch(proto)
+    {
+    case 0: /* esp_out */
+#if TKB_HAVE_PROTO_IPSEC == 1u
+        if (ivhandling == 2u)
+        {
+            *TokenWord32Count_p += 2u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        *TokenWord32Count_p += 1u;
+        icvlen = EVAL_icvlen();
+        if (icvlen > 0u)
+        {
+            extseq = EVAL_extseq();
+            if (extseq == 0u)
+            {
+                *TokenWord32Count_p += 1u;
+            }
+            else
+            {
+                *TokenWord32Count_p += 2u;
+            }
+            *TokenWord32Count_p += 1u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        *TokenWord32Count_p += 2u;
+#else
+#endif
+        break;
+    case 1: /* esp_in */
+#if TKB_HAVE_PROTO_IPSEC == 1u
+#if TKB_HAVE_ECN_FIXUP == 1u
+        *TokenWord32Count_p += 1u;
+#endif
+        if (ivhandling == 0u)
+        {
+            *TokenWord32Count_p += 2u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        icvlen = EVAL_icvlen();
+        if (icvlen > 0u)
+        {
+            extseq = EVAL_extseq();
+            if (extseq != 1u)
+            {
+                *TokenWord32Count_p += 1u;
+            }
+            else
+            {
+                *TokenWord32Count_p += 2u;
+            }
+            *TokenWord32Count_p += 1u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 1u;
+        }
+#else
+#endif
+        break;
+    case 2: /* esp_out_ccm */
+#if TKB_HAVE_PROTO_IPSEC == 1u
+        *TokenWord32Count_p += 5u;
+        extseq = EVAL_extseq();
+        if (extseq == 0u)
+        {
+            *TokenWord32Count_p += 3u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 5u;
+        }
+        *TokenWord32Count_p += 9u;
+#else
+#endif
+        break;
+    case 3: /* esp_in_ccm */
+#if TKB_HAVE_PROTO_IPSEC == 1u
+        *TokenWord32Count_p += 7u;
+        extseq = EVAL_extseq();
+        if (extseq != 1u)
+        {
+            *TokenWord32Count_p += 3u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 5u;
+        }
+        *TokenWord32Count_p += 1u;
+#if TKB_HAVE_ECN_FIXUP == 1u
+        *TokenWord32Count_p += 1u;
+#endif
+        *TokenWord32Count_p += 4u;
+#else
+#endif
+        break;
+    case 4: /* esp_out_gcm */
+#if TKB_HAVE_PROTO_IPSEC == 1u
+        extseq = EVAL_extseq();
+        if (extseq == 0u)
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 3u;
+        }
+        *TokenWord32Count_p += 8u;
+#else
+#endif
+        break;
+    case 5: /* esp_in_gcm */
+#if TKB_HAVE_PROTO_IPSEC == 1u
+        extseq = EVAL_extseq();
+        if (extseq != 1u)
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 4u;
+        }
+        *TokenWord32Count_p += 2u;
+#if TKB_HAVE_ECN_FIXUP == 1u
+        *TokenWord32Count_p += 1u;
+#endif
+        *TokenWord32Count_p += 3u;
+#else
+#endif
+        break;
+    case 6: /* esp_out_gmac */
+#if TKB_HAVE_PROTO_IPSEC == 1u
+        extseq = EVAL_extseq();
+        if (extseq == 0u)
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 3u;
+        }
+        *TokenWord32Count_p += 8u;
+#else
+#endif
+        break;
+    case 7: /* esp_in_gmac */
+#if TKB_HAVE_PROTO_IPSEC == 1u
+        extseq = EVAL_extseq();
+        if (extseq != 1u)
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 4u;
+        }
+        *TokenWord32Count_p += 2u;
+#if TKB_HAVE_ECN_FIXUP == 1u
+        *TokenWord32Count_p += 1u;
+#endif
+        *TokenWord32Count_p += 3u;
+#else
+#endif
+        break;
+    case 8: /* ssltls_out */
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+        capwap_out = EVAL_capwap_out();
+        if (capwap_out != 0u)
+        {
+            *TokenWord32Count_p += 2u;
+        }
+        *TokenWord32Count_p += 3u;
+        antireplay = EVAL_antireplay();
+        if (antireplay != 0u)
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        extseq = EVAL_extseq();
+        if (extseq != 0u)
+        {
+            *TokenWord32Count_p += 2u;
+        }
+        *TokenWord32Count_p += 6u;
+        upd_handling = EVAL_upd_handling();
+        switch(upd_handling)
+        {
+        case 0: /* upd_null */
+            *TokenWord32Count_p += 3u;
+            break;
+        case 1: /* upd_arc4 */
+            *TokenWord32Count_p += 4u;
+            break;
+        case 2: /* upd_iv2 */
+            *TokenWord32Count_p += 1u;
+            if (antireplay != 0u)
+            {
+                *TokenWord32Count_p += 1u;
+            }
+            else
+            {
+                *TokenWord32Count_p += 1u;
+            }
+            *TokenWord32Count_p += 2u;
+            break;
+        case 3: /* upd_iv4 */
+            *TokenWord32Count_p += 1u;
+            if (antireplay != 0u)
+            {
+                *TokenWord32Count_p += 1u;
+            }
+            else
+            {
+                *TokenWord32Count_p += 1u;
+            }
+            *TokenWord32Count_p += 2u;
+            break;
+        case 4: /* upd_blk */
+            *TokenWord32Count_p += 4u;
+            break;
+        }
+#else
+#endif
+        break;
+    case 9: /* ssltls_in */
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+        upd_handling = EVAL_upd_handling();
+        if (upd_handling <= 1u)
+        {
+            *TokenWord32Count_p += 3u;
+            extseq = EVAL_extseq();
+            if (extseq != 0u)
+            {
+                *TokenWord32Count_p += 7u;
+            }
+            else
+            {
+                *TokenWord32Count_p += 2u;
+                antireplay = EVAL_antireplay();
+                if (antireplay != 0u)
+                {
+                    *TokenWord32Count_p += 1u;
+                }
+                else
+                {
+                    *TokenWord32Count_p += 2u;
+                }
+                *TokenWord32Count_p += 2u;
+            }
+            *TokenWord32Count_p += 3u;
+            switch(upd_handling)
+            {
+            case 0: /* upd_null */
+                *TokenWord32Count_p += 1u;
+                if (extseq == 0u)
+                {
+                    *TokenWord32Count_p += 2u;
+                }
+                else if (extseq == 1u)
+                {
+                    *TokenWord32Count_p += 1u;
+                }
+                else
+                {
+                    *TokenWord32Count_p += 2u;
+                }
+                break;
+            case 1: /* upd_arc4 */
+                *TokenWord32Count_p += 5u;
+                break;
+            }
+        }
+        else
+        {
+            *TokenWord32Count_p += 1u;
+            cipher_is_aes = EVAL_cipher_is_aes();
+            if (cipher_is_aes == 0u)
+            {
+                *TokenWord32Count_p += 6u;
+            }
+            else
+            {
+                *TokenWord32Count_p += 10u;
+            }
+            *TokenWord32Count_p += 3u;
+            extseq = EVAL_extseq();
+            if (extseq != 0u)
+            {
+                *TokenWord32Count_p += 6u;
+            }
+            else
+            {
+                *TokenWord32Count_p += 3u;
+                antireplay = EVAL_antireplay();
+                if (antireplay != 0u)
+                {
+                    *TokenWord32Count_p += 1u;
+                }
+                else
+                {
+                    *TokenWord32Count_p += 1u;
+                }
+                *TokenWord32Count_p += 1u;
+            }
+            *TokenWord32Count_p += 1u;
+            ivlen = EVAL_ivlen();
+            if (ivlen > 0u)
+            {
+                *TokenWord32Count_p += 1u;
+            }
+            *TokenWord32Count_p += 3u;
+            switch(upd_handling)
+            {
+            case 2: /* upd_iv2 */
+                antireplay = EVAL_antireplay();
+                if (antireplay != 0u)
+                {
+                    *TokenWord32Count_p += 1u;
+                }
+                else
+                {
+                    *TokenWord32Count_p += 1u;
+                }
+                *TokenWord32Count_p += 2u;
+                break;
+            case 3: /* upd_iv4 */
+                antireplay = EVAL_antireplay();
+                if (antireplay != 0u)
+                {
+                    *TokenWord32Count_p += 1u;
+                }
+                else
+                {
+                    *TokenWord32Count_p += 1u;
+                }
+                *TokenWord32Count_p += 2u;
+                break;
+            case 4: /* upd_blk */
+                if (extseq == 0u)
+                {
+                    *TokenWord32Count_p += 2u;
+                }
+                else if (extseq == 1u)
+                {
+                    *TokenWord32Count_p += 1u;
+                }
+                else
+                {
+                    *TokenWord32Count_p += 2u;
+                }
+                break;
+            }
+        }
+#else
+#endif
+        break;
+    case 21: /* ssltls_gcm_out */
+    case 37: /* ssltls_chachapoly_out */
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+        capwap_out = EVAL_capwap_out();
+        if (capwap_out != 0u)
+        {
+            *TokenWord32Count_p += 2u;
+        }
+        *TokenWord32Count_p += 4u;
+        extseq = EVAL_extseq();
+        if (extseq != 0u)
+        {
+            *TokenWord32Count_p += 2u;
+        }
+        *TokenWord32Count_p += 5u;
+        if (proto != 37u)
+        {
+            if (extseq != 0u)
+            {
+                *TokenWord32Count_p += 1u;
+            }
+            else
+            {
+                *TokenWord32Count_p += 1u;
+            }
+            *TokenWord32Count_p += 1u;
+        }
+        *TokenWord32Count_p += 4u;
+#else
+#endif
+        break;
+    case 22: /* ssltls_gcm_in */
+    case 38: /* ssltls_chachapoly_in */
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+        *TokenWord32Count_p += 11u;
+        if (proto != 38u)
+        {
+            *TokenWord32Count_p += 2u;
+        }
+        else
+        {
+#if TKB_HAVE_CHACHAPOLY_HW30 == 1u
+            *TokenWord32Count_p += 1u;
+#else
+            *TokenWord32Count_p += 1u;
+#endif
+        }
+        *TokenWord32Count_p += 2u;
+        extseq = EVAL_extseq();
+        if (extseq == 0u)
+        {
+            *TokenWord32Count_p += 2u;
+        }
+        else if (extseq == 1u)
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 2u;
+        }
+#else
+#endif
+        break;
+    case 10: /* basic_crypto */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        switch(ivhandling)
+        {
+        case 0: /* iv_inbound_ctr */
+            *TokenWord32Count_p += 1u;
+            break;
+        case 1: /* iv_inbound_cbc */
+            *TokenWord32Count_p += 1u;
+            break;
+        case 2: /* iv_outbound_ctr */
+            *TokenWord32Count_p += 1u;
+            break;
+        case 5: /* iv_copy_ctr */
+            *TokenWord32Count_p += 1u;
+            break;
+        case 4: /* iv_copy_cbc */
+            *TokenWord32Count_p += 1u;
+            break;
+        case 6: /* iv_outbound_2words */
+        case 9: /* iv_copy_token_2words */
+            *TokenWord32Count_p += 1u;
+            break;
+        case 7: /* iv_outbound_4words */
+        case 15: /* iv_copy_token_4words */
+            *TokenWord32Count_p += 1u;
+            break;
+        }
+        *TokenWord32Count_p += 2u;
+        upd_handling = EVAL_upd_handling();
+        switch(upd_handling)
+        {
+        case 0: /* upd_null */
+            break;
+        case 1: /* upd_arc4 */
+            *TokenWord32Count_p += 2u;
+            break;
+        case 2: /* upd_iv2 */
+            *TokenWord32Count_p += 1u;
+            break;
+        case 3: /* upd_iv4 */
+            *TokenWord32Count_p += 1u;
+            break;
+        }
+#else
+#endif
+        break;
+    case 11: /* basic_hash */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        *TokenWord32Count_p += 17u;
+        extseq = EVAL_extseq();
+        if (extseq > 0u)
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        *TokenWord32Count_p += 2u;
+        seq_offset = EVAL_seq_offset();
+        if (seq_offset > 0u)
+        {
+            *TokenWord32Count_p += 1u;
+            hstatelen = EVAL_hstatelen();
+            if (hstatelen > 16u)
+            {
+                *TokenWord32Count_p += 1u;
+            }
+        }
+#else
+#endif
+        break;
+    case 14: /* basic_crypthash */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        *TokenWord32Count_p += 17u;
+        switch(ivhandling)
+        {
+        case 0: /* iv_inbound_ctr */
+            *TokenWord32Count_p += 1u;
+            break;
+        case 1: /* iv_inbound_cbc */
+            *TokenWord32Count_p += 1u;
+            break;
+        case 2: /* iv_outbound_ctr */
+            *TokenWord32Count_p += 1u;
+            break;
+        case 5: /* iv_copy_ctr */
+            *TokenWord32Count_p += 1u;
+            break;
+        case 4: /* iv_copy_cbc */
+            *TokenWord32Count_p += 1u;
+            break;
+        case 6: /* iv_outbound_2words */
+        case 9: /* iv_copy_token_2words */
+            *TokenWord32Count_p += 1u;
+            break;
+        case 7: /* iv_outbound_4words */
+        case 15: /* iv_copy_token_4words */
+            *TokenWord32Count_p += 1u;
+            break;
+        }
+        *TokenWord32Count_p += 4u;
+        seq_offset = EVAL_seq_offset();
+        if (seq_offset > 0u)
+        {
+            *TokenWord32Count_p += 1u;
+            hstatelen = EVAL_hstatelen();
+            if (hstatelen > 16u)
+            {
+                *TokenWord32Count_p += 1u;
+            }
+        }
+        upd_handling = EVAL_upd_handling();
+        switch(upd_handling)
+        {
+        case 0: /* upd_null */
+            break;
+        case 1: /* upd_arc4 */
+            *TokenWord32Count_p += 2u;
+            break;
+        case 2: /* upd_iv2 */
+            *TokenWord32Count_p += 1u;
+            break;
+        case 3: /* upd_iv4 */
+            *TokenWord32Count_p += 1u;
+            break;
+        }
+#else
+#endif
+        break;
+    case 15: /* basic_out_ccm */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        *TokenWord32Count_p += 2u;
+        if (ivhandling == 5u)
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        *TokenWord32Count_p += 25u;
+        seq_offset = EVAL_seq_offset();
+        if (seq_offset > 0u)
+        {
+            *TokenWord32Count_p += 2u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 1u;
+        }
+#else
+#endif
+        break;
+    case 16: /* basic_in_ccm */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        *TokenWord32Count_p += 2u;
+        if (ivhandling == 0u)
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        *TokenWord32Count_p += 25u;
+        seq_offset = EVAL_seq_offset();
+        if (seq_offset > 0u)
+        {
+            *TokenWord32Count_p += 2u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 2u;
+        }
+#else
+#endif
+        break;
+    case 17: /* basic_out_gcm */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        *TokenWord32Count_p += 17u;
+        switch(ivhandling)
+        {
+        case 0: /* iv_inbound_ctr */
+            *TokenWord32Count_p += 2u;
+            break;
+        case 5: /* iv_copy_ctr */
+            *TokenWord32Count_p += 2u;
+            break;
+        case 15: /* iv_copy_token_4words */
+        case 2: /* iv_outbound_ctr */
+            *TokenWord32Count_p += 2u;
+            break;
+        default:
+            *TokenWord32Count_p += 1u;
+            ;
+        }
+        *TokenWord32Count_p += 2u;
+        seq_offset = EVAL_seq_offset();
+        if (seq_offset > 0u)
+        {
+            *TokenWord32Count_p += 2u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 1u;
+        }
+#else
+#endif
+        break;
+    case 18: /* basic_in_gcm */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        *TokenWord32Count_p += 17u;
+        switch(ivhandling)
+        {
+        case 0: /* iv_inbound_ctr */
+            *TokenWord32Count_p += 2u;
+            break;
+        case 5: /* iv_copy_ctr */
+            *TokenWord32Count_p += 2u;
+            break;
+        case 15: /* iv_copy_token_4words */
+        case 2: /* iv_outbound_ctr */
+            *TokenWord32Count_p += 2u;
+            break;
+        default:
+            *TokenWord32Count_p += 1u;
+            ;
+        }
+        *TokenWord32Count_p += 2u;
+        seq_offset = EVAL_seq_offset();
+        if (seq_offset > 0u)
+        {
+            *TokenWord32Count_p += 2u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 2u;
+        }
+#else
+#endif
+        break;
+    case 19: /* basic_out_gmac */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        *TokenWord32Count_p += 17u;
+        switch(ivhandling)
+        {
+        case 0: /* iv_inbound_ctr */
+            *TokenWord32Count_p += 3u;
+            break;
+        case 5: /* iv_copy_ctr */
+            *TokenWord32Count_p += 3u;
+            break;
+        case 15: /* iv_copy_token_4words */
+        case 2: /* iv_outbound_ctr */
+            *TokenWord32Count_p += 3u;
+            break;
+        default:
+            *TokenWord32Count_p += 2u;
+            ;
+        }
+        *TokenWord32Count_p += 1u;
+        seq_offset = EVAL_seq_offset();
+        if (seq_offset > 0u)
+        {
+            *TokenWord32Count_p += 2u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 1u;
+        }
+#else
+#endif
+        break;
+    case 20: /* basic_in_gmac */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        *TokenWord32Count_p += 17u;
+        switch(ivhandling)
+        {
+        case 0: /* iv_inbound_ctr */
+            *TokenWord32Count_p += 3u;
+            break;
+        case 5: /* iv_copy_ctr */
+            *TokenWord32Count_p += 3u;
+            break;
+        case 15: /* iv_copy_token_4words */
+        case 2: /* iv_outbound_ctr */
+            *TokenWord32Count_p += 3u;
+            break;
+        default:
+            *TokenWord32Count_p += 2u;
+            ;
+        }
+        *TokenWord32Count_p += 1u;
+        seq_offset = EVAL_seq_offset();
+        if (seq_offset > 0u)
+        {
+            *TokenWord32Count_p += 2u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 2u;
+        }
+#else
+#endif
+        break;
+    case 23: /* basic_xts_crypto */
+#if TKB_HAVE_CRYPTO_XTS == 1u
+        *TokenWord32Count_p += 5u;
+        switch(ivhandling)
+        {
+        case 1: /* iv_inbound_cbc */
+            *TokenWord32Count_p += 1u;
+            break;
+        case 4: /* iv_copy_cbc */
+            *TokenWord32Count_p += 1u;
+            break;
+        case 7: /* iv_outbound_4words */
+        case 15: /* iv_copy_token_4words */
+            *TokenWord32Count_p += 1u;
+            break;
+        }
+        *TokenWord32Count_p += 2u;
+        upd_handling = EVAL_upd_handling();
+        switch(upd_handling)
+        {
+        case 0: /* upd_null */
+            break;
+        case 3: /* upd_iv4 */
+            *TokenWord32Count_p += 1u;
+            break;
+        }
+#else
+#endif
+        break;
+    case 24: /* basic_kasumi_hash */
+#if TKB_HAVE_CRYPTO_WIRELESS == 1u
+        *TokenWord32Count_p += 3u;
+        extseq = EVAL_extseq();
+        if (extseq > 0u)
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        *TokenWord32Count_p += 2u;
+#else
+#endif
+        break;
+    case 25: /* basic_snow_hash */
+    case 26: /* basic_zuc_hash */
+#if TKB_HAVE_CRYPTO_WIRELESS == 1u
+        *TokenWord32Count_p += 5u;
+        extseq = EVAL_extseq();
+        if (extseq > 0u)
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        *TokenWord32Count_p += 2u;
+#else
+#endif
+        break;
+    case 27: /* basic_hashenc */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        *TokenWord32Count_p += 17u;
+        switch(ivhandling)
+        {
+        case 4: /* iv_copy_cbc */
+            *TokenWord32Count_p += 1u;
+            break;
+        case 6: /* iv_outbound_2words */
+        case 9: /* iv_copy_token_2words */
+            *TokenWord32Count_p += 1u;
+            break;
+        case 7: /* iv_outbound_4words */
+        case 15: /* iv_copy_token_4words */
+            *TokenWord32Count_p += 1u;
+            break;
+        }
+        *TokenWord32Count_p += 3u;
+#else
+#endif
+        break;
+    case 28: /* basic_dechash */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        *TokenWord32Count_p += 1u;
+        cipher_is_aes = EVAL_cipher_is_aes();
+        if (cipher_is_aes == 0u)
+        {
+            *TokenWord32Count_p += 6u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 10u;
+        }
+        *TokenWord32Count_p += 21u;
+        ivlen = EVAL_ivlen();
+        if (ivlen > 0u)
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        *TokenWord32Count_p += 4u;
+#else
+#endif
+        break;
+    case 12: /* srtp_out */
+#if TKB_HAVE_PROTO_SRTP == 1u
+        *TokenWord32Count_p += 2u;
+        extseq = EVAL_extseq();
+        if (extseq > 0u)
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        *TokenWord32Count_p += 1u;
+        antireplay = EVAL_antireplay();
+        if (antireplay > 0u)
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        *TokenWord32Count_p += 1u;
+#else
+#endif
+        break;
+    case 13: /* srtp_in */
+#if TKB_HAVE_PROTO_SRTP == 1u
+        *TokenWord32Count_p += 2u;
+        extseq = EVAL_extseq();
+        if (extseq > 0u)
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 2u;
+        }
+        antireplay = EVAL_antireplay();
+        if (antireplay > 0u)
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        icvlen = EVAL_icvlen();
+        if (icvlen > 0u)
+        {
+            *TokenWord32Count_p += 1u;
+            if (antireplay > 0u)
+            {
+                *TokenWord32Count_p += 1u;
+            }
+            else
+            {
+                *TokenWord32Count_p += 1u;
+            }
+        }
+        else
+        {
+            *TokenWord32Count_p += 1u;
+            if (antireplay > 0u)
+            {
+                *TokenWord32Count_p += 1u;
+            }
+        }
+#else
+#endif
+        break;
+    case 29: /* basic_out_chachapoly */
+#if TKB_HAVE_PROTO_BASIC == 1u
+#if TKB_HAVE_CRYPTO_CHACHAPOLY == 1u
+        *TokenWord32Count_p += 19u;
+#else
+#endif
+#else
+#endif
+        break;
+    case 30: /* basic_in_chachapoly */
+#if TKB_HAVE_PROTO_BASIC == 1u
+#if TKB_HAVE_CRYPTO_CHACHAPOLY == 1u
+        *TokenWord32Count_p += 17u;
+#if TKB_HAVE_CHACHAPOLY_HW30 == 1u
+        *TokenWord32Count_p += 1u;
+#else
+        *TokenWord32Count_p += 1u;
+#endif
+        *TokenWord32Count_p += 3u;
+#else
+#endif
+#else
+#endif
+        break;
+    case 31: /* tls13_gcm_out */
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+        *TokenWord32Count_p += 12u;
+#else
+#endif
+        break;
+    case 32: /* tls13_gcm_in */
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+        *TokenWord32Count_p += 7u;
+#else
+#endif
+        break;
+    case 33: /* tls13_chachapoly_out */
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+        *TokenWord32Count_p += 10u;
+#else
+#endif
+        break;
+    case 34: /* tls13_chachapoly_in */
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+        *TokenWord32Count_p += 6u;
+#else
+#endif
+        break;
+    case 35: /* esp_out_chachapoly */
+#if TKB_HAVE_PROTO_IPSEC == 1u
+        extseq = EVAL_extseq();
+        if (extseq == 0u)
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 3u;
+        }
+        *TokenWord32Count_p += 6u;
+#else
+#endif
+        break;
+    case 36: /* esp_in_chachapoly */
+#if TKB_HAVE_PROTO_IPSEC == 1u
+        extseq = EVAL_extseq();
+        if (extseq != 1u)
+        {
+            *TokenWord32Count_p += 2u;
+#if TKB_HAVE_ECN_FIXUP == 1u
+            *TokenWord32Count_p += 1u;
+#endif
+            *TokenWord32Count_p += 1u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 5u;
+#if TKB_HAVE_ECN_FIXUP == 1u
+            *TokenWord32Count_p += 1u;
+#endif
+#if TKB_HAVE_CHACHAPOLY_HW30 == 1u
+            *TokenWord32Count_p += 1u;
+#else
+            *TokenWord32Count_p += 1u;
+#endif
+        }
+        *TokenWord32Count_p += 2u;
+#else
+#endif
+        break;
+    case 39: /* ssltls_ccm_out */
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+        *TokenWord32Count_p += 1u;
+        capwap_out = EVAL_capwap_out();
+        if (capwap_out != 0u)
+        {
+            *TokenWord32Count_p += 2u;
+        }
+        *TokenWord32Count_p += 11u;
+        extseq = EVAL_extseq();
+        if (extseq != 0u)
+        {
+            *TokenWord32Count_p += 2u;
+        }
+        *TokenWord32Count_p += 6u;
+        if (extseq != 0u)
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        *TokenWord32Count_p += 6u;
+#else
+#endif
+        break;
+    case 40: /* ssltls_ccm_in */
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+        *TokenWord32Count_p += 24u;
+        extseq = EVAL_extseq();
+        if (extseq == 0u)
+        {
+            *TokenWord32Count_p += 2u;
+        }
+        else if (extseq == 1u)
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        else
+        {
+            *TokenWord32Count_p += 2u;
+        }
+#else
+#endif
+        break;
+    case 41: /* tls13_ccm_out */
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+        *TokenWord32Count_p += 19u;
+#else
+#endif
+        break;
+    case 42: /* tls13_ccm_in */
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+        *TokenWord32Count_p += 14u;
+#else
+#endif
+        break;
+    case 43: /* basic_hmac_precompute */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        *TokenWord32Count_p += 4u;
+#else
+#endif
+        break;
+    case 44: /* basic_hmac_ctxprepare */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        *TokenWord32Count_p += 6u;
+#else
+#endif
+        break;
+    case 45: /* basic_bypass */
+        *TokenWord32Count_p += 1u;
+        break;
+    default:
+        ;
+    }
+#if TKB_HAVE_PROTO_IPSEC == 1u
+#if TKB_HAVE_EXTENDED_IPSEC == 1u
+    hproto = EVAL_hproto();
+    switch(hproto)
+    {
+    case 6: /* ipv4_in_transp */
+    case 26: /* ipv4_in_transp_natt */
+        *TokenWord32Count_p += 1u;
+        break;
+    case 12: /* ipv6_in_transp */
+    case 32: /* ipv6_in_transp_natt */
+        *TokenWord32Count_p += 2u;
+        break;
+    }
+#endif
+    switch(proto)
+    {
+    case 1: /* esp_in */
+    case 3: /* esp_in_ccm */
+    case 5: /* esp_in_gcm */
+    case 7: /* esp_in_gmac */
+    case 36: /* esp_in_chachapoly */
+        icvlen = EVAL_icvlen();
+        if (icvlen > 0u)
+        {
+            antireplay = EVAL_antireplay();
+            if (antireplay > 12u)
+            {
+                *TokenWord32Count_p += 1u;
+                extseq = EVAL_extseq();
+                if (extseq > 0u)
+                {
+                    *TokenWord32Count_p += 1u;
+                }
+                else
+                {
+                    *TokenWord32Count_p += 1u;
+                }
+            }
+            else if (antireplay != 0u)
+            {
+                *TokenWord32Count_p += 1u;
+                extseq = EVAL_extseq();
+                if (extseq > 0u)
+                {
+                    *TokenWord32Count_p += 1u;
+                }
+                else
+                {
+                    *TokenWord32Count_p += 1u;
+                }
+            }
+            else
+            {
+                *TokenWord32Count_p += 1u;
+            }
+        }
+        else
+        {
+            *TokenWord32Count_p += 1u;
+        }
+        break;
+    }
+#endif
+
+
+    if (Switch_Proto(TokenContext_Internal_p))
+    {
+        /* Protocol was switched (HMAC context prepare to original protocol),
+           redo size computation with original protocol.*/
+        WordCountOld = *TokenWord32Count_p;
+        goto redo;
+    }
+    *TokenWord32Count_p = MAX(*TokenWord32Count_p, WordCountOld);
+
+   return TKB_STATUS_OK;
+}
+
+
+TokenBuilder_Status_t
+TokenBuilder_BuildToken(
+    void * const TokenContext_p,
+    const uint8_t *const Packet_p,
+    const uint32_t PacketByteCount,
+    TokenBuilder_Params_t * const TKBParams_p,
+    void * const Token_p,
+    uint32_t * const TokenWord32Count_p,
+    uint32_t * const TokenHeaderWord_p)
+{
+    uint32_t *tp = (uint32_t*)Token_p;
+    uint32_t rc = TKB_STATUS_OK;
+    TokenBuilder_Context_t *TokenContext_Internal_p =
+        (TokenBuilder_Context_t*)TokenContext_p;
+    uint32_t proto;
+#if (TKB_HAVE_PROTO_IPSEC == 1u && TKB_HAVE_EXTENDED_IPSEC == 1u)
+    uint32_t hproto;
+#endif
+    uint32_t packetsize;
+    uint32_t bypass;
+#if TKB_HAVE_PROTO_IPSEC == 1u || TKB_HAVE_PROTO_SSLTLS == 1u
+    uint32_t nextheader;
+#endif
+#if TKB_HAVE_PROTO_IPSEC == 1u
+    uint32_t pad_remainder;
+#endif
+#if TKB_HAVE_PROTO_IPSEC == 1u
+    uint32_t pad_blocksize;
+#endif
+#if TKB_HAVE_PROTO_IPSEC == 1u || TKB_HAVE_PROTO_SSLTLS == 1u
+    uint32_t pad_bytes;
+#endif
+#if TKB_HAVE_PROTO_IPSEC == 1u || TKB_HAVE_PROTO_SSLTLS == 1u || TKB_HAVE_PROTO_BASIC == 1u
+    uint32_t seq_offset;
+#endif
+#if TKB_HAVE_PROTO_SSLTLS == 1u || TKB_HAVE_PROTO_BASIC == 1u || TKB_HAVE_CRYPTO_XTS == 1u
+    uint32_t iv_offset;
+#endif
+#if TKB_HAVE_PROTO_BASIC == 1u
+    uint32_t digest_offset;
+#endif
+#if TKB_HAVE_PROTO_IPSEC == 1u || TKB_HAVE_PROTO_SSLTLS == 1u || TKB_HAVE_PROTO_BASIC == 1u || TKB_HAVE_CRYPTO_XTS == 1u
+    uint32_t ivlen;
+#endif
+#if TKB_HAVE_PROTO_IPSEC == 1u || TKB_HAVE_PROTO_SSLTLS == 1u || TKB_HAVE_PROTO_BASIC == 1u || TKB_HAVE_CRYPTO_WIRELESS == 1u || TKB_HAVE_PROTO_SRTP == 1u
+    uint32_t icvlen;
+#endif
+    uint32_t ivhandling;
+#if TKB_HAVE_PROTO_IPSEC == 1u || TKB_HAVE_PROTO_SSLTLS == 1u || TKB_HAVE_PROTO_BASIC == 1u || TKB_HAVE_CRYPTO_WIRELESS == 1u || TKB_HAVE_PROTO_SRTP == 1u
+    uint32_t extseq;
+#endif
+#if TKB_HAVE_PROTO_IPSEC == 1u || TKB_HAVE_PROTO_SSLTLS == 1u
+    uint32_t salt;
+#endif
+#if TKB_HAVE_PROTO_BASIC == 1u
+    uint32_t basic_salt;
+#endif
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+    uint32_t paylen;
+#endif
+#if TKB_HAVE_PROTO_IPSEC == 1u || TKB_HAVE_PROTO_SSLTLS == 1u
+    uint32_t swaplen;
+#endif
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+    uint32_t swap_fraglen;
+#endif
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+    uint32_t swap_fraglen_tls13;
+#endif
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+    uint32_t swaplen3;
+#endif
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+    uint32_t swaplen3_tls13_out;
+#endif
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+    uint32_t swaplen3_tls13_in;
+#endif
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+    uint32_t hashpad_tls13_out;
+#endif
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+    uint32_t hashpad_tls13_in;
+#endif
+#if TKB_HAVE_PROTO_IPSEC == 1u || TKB_HAVE_PROTO_SSLTLS == 1u
+    uint32_t hashpad;
+#endif
+#if TKB_HAVE_PROTO_BASIC == 1u
+    uint32_t aadlen_pkt;
+#endif
+#if TKB_HAVE_PROTO_BASIC == 1u
+    uint32_t aadlen_tkn;
+#endif
+#if TKB_HAVE_PROTO_BASIC == 1u
+    uint32_t aadlen_out;
+#endif
+#if TKB_HAVE_CRYPTO_XTS == 1u
+    uint32_t swap_j;
+#endif
+#if TKB_HAVE_PROTO_BASIC == 1u
+    uint32_t basic_swaplen;
+#endif
+#if TKB_HAVE_PROTO_BASIC == 1u
+    uint32_t aadlen_swap;
+#endif
+#if TKB_HAVE_PROTO_BASIC == 1u
+    uint32_t aadpad;
+#endif
+#if TKB_HAVE_PROTO_BASIC == 1u
+    uint32_t basic_hashpad;
+#endif
+#if TKB_HAVE_PROTO_SSLTLS == 1u || TKB_HAVE_PROTO_BASIC == 1u || TKB_HAVE_CRYPTO_WIRELESS == 1u || TKB_HAVE_PROTO_SRTP == 1u || TKB_HAVE_PROTO_IPSEC == 1u
+    uint32_t antireplay;
+#endif
+#if TKB_HAVE_PROTO_SSLTLS == 1u || TKB_HAVE_PROTO_BASIC == 1u || TKB_HAVE_CRYPTO_XTS == 1u
+    uint32_t upd_handling;
+#endif
+#if TKB_HAVE_PROTO_SSLTLS == 1u || TKB_HAVE_PROTO_BASIC == 1u
+    uint32_t cipher_is_aes;
+#endif
+#if TKB_HAVE_PROTO_BASIC == 1u || TKB_HAVE_CRYPTO_WIRELESS == 1u
+    uint32_t appendhash;
+#endif
+#if TKB_HAVE_PROTO_BASIC == 1u || TKB_HAVE_CRYPTO_XTS == 1u
+    uint32_t pad_bytes_basic;
+#endif
+#if TKB_HAVE_PROTO_BASIC == 1u
+    uint32_t hstatelen;
+#endif
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+    uint32_t capwap_out;
+#endif
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+    uint32_t capwap_in;
+#endif
+#if TKB_HAVE_PROTO_BASIC == 1u
+    uint32_t hstatelen_bytes;
+#endif
+#if TKB_HAVE_PROTO_BASIC == 1u
+    uint32_t pad_bytes_hashenc;
+#endif
+#if TKB_HAVE_PROTO_SRTP == 1u
+    uint32_t srtp_offset;
+#endif
+#if TKB_HAVE_PROTO_SRTP == 1u
+    uint32_t srtp_swaproc;
+#endif
+    uint32_t srtp_iv0;
+    uint32_t srtp_iv1;
+    uint32_t srtp_iv2;
+    uint32_t srtp_iv3;
+    uint32_t count;
+    uint32_t bearer_dir_fresh;
+#if (TKB_HAVE_PROTO_IPSEC == 1u && TKB_HAVE_EXTENDED_IPSEC == 1u)
+    uint32_t prev_nhoffset;
+#endif
+    uint32_t hdrlen;
+#if (TKB_HAVE_PROTO_IPSEC == 1u && TKB_HAVE_EXTENDED_IPSEC == 1u) || TKB_HAVE_PROTO_IPSEC == 1u || TKB_HAVE_PROTO_SSLTLS == 1u
+    uint32_t ohdrlen;
+#endif
+#if (TKB_HAVE_PROTO_IPSEC == 1u && TKB_HAVE_EXTENDED_IPSEC == 1u)
+    uint32_t outlen;
+#endif
+#if (TKB_HAVE_PROTO_IPSEC == 1u && TKB_HAVE_EXTENDED_IPSEC == 1u)
+    uint32_t nh;
+#endif
+#if (TKB_HAVE_PROTO_IPSEC == 1u && TKB_HAVE_EXTENDED_IPSEC == 1u)
+    uint32_t is_nat;
+#endif
+#if (TKB_HAVE_PROTO_IPSEC == 1u && TKB_HAVE_EXTENDED_IPSEC == 1u)
+    uint32_t tunnel_w0_ip4;
+#endif
+#if (TKB_HAVE_PROTO_IPSEC == 1u && TKB_HAVE_EXTENDED_IPSEC == 1u)
+    uint32_t tunnel_w1_ip4;
+#endif
+#if (TKB_HAVE_PROTO_IPSEC == 1u && TKB_HAVE_EXTENDED_IPSEC == 1u)
+    uint32_t tunnel_w2_ip4;
+#endif
+#if (TKB_HAVE_PROTO_IPSEC == 1u && TKB_HAVE_EXTENDED_IPSEC == 1u)
+    uint32_t tunnel_w0_ip6;
+#endif
+#if (TKB_HAVE_PROTO_IPSEC == 1u && TKB_HAVE_EXTENDED_IPSEC == 1u)
+    uint32_t tunnel_w1_ip6;
+#endif
+#if (TKB_HAVE_PROTO_IPSEC == 1u && TKB_HAVE_EXTENDED_IPSEC == 1u)
+    const uint8_t *tunnel_ip_addr;
+#endif
+#if (TKB_HAVE_PROTO_IPSEC == 1u && TKB_HAVE_EXTENDED_IPSEC == 1u)
+    const uint8_t *dst_ip_addr;
+#endif
+#if (TKB_HAVE_PROTO_IPSEC == 1u && TKB_HAVE_EXTENDED_IPSEC == 1u)
+    uint32_t ports_natt;
+#endif
+#if (TKB_HAVE_PROTO_IPSEC == 1u && TKB_HAVE_ECN_FIXUP == 1u)
+    uint32_t ecn_fixup_instr;
+#endif
+    uint32_t per_packet_options;
+    uint32_t u_word;
+    uint32_t cw0;
+    uint32_t cw1;
+    const uint8_t *iv;
+#if TKB_HAVE_PROTO_SSLTLS == 1u || TKB_HAVE_PROTO_BASIC == 1u
+    const uint8_t *ssltls_lastblock;
+#endif
+#if TKB_HAVE_PROTO_SSLTLS == 1u || TKB_HAVE_PROTO_BASIC == 1u
+    const uint8_t *ssltls_lastword;
+#endif
+#if TKB_HAVE_PROTO_BASIC == 1u
+    const uint8_t *aad;
+#endif
+
+    IDENTIFIER_NOT_USED(Packet_p);
+#ifdef TKB_STRICT_ARGS_CHECK
+    if (Token_p == NULL ||
+        TokenWord32Count_p == NULL ||
+        (TokenHeaderWord_p == NULL && TKB_TOKEN_HEADER_WORD_COUNT == 0))
+    {
+        LOG_CRIT("TokenBuilder: NULL pointer supplied\n");
+        return TKB_INVALID_PARAMETER;
+    }
+#endif
+    if (TokenContext_p == NULL)
+    {
+        rc = TKB_ERROR;
+        TKBParams_p->CLE = 2;
+        goto error;
+    }
+
+    if (TokenHeaderWord_p != NULL)
+        *TokenHeaderWord_p = EVAL_TokenHeaderWord();
+#if TKB_TOKEN_HEADER_WORD_COUNT > 0
+    {
+        unsigned int i;
+        *tp++ = EVAL_TokenHeaderWord();
+        for (i = 0; i < TKB_TOKEN_HEADER_WORD_COUNT - 1; i++)
+        {
+            *tp++ = 0;
+        }
+    }
+#endif
+
+    per_packet_options = EVAL_per_packet_options();
+    if (per_packet_options != 0u)
+    {
+        /* DATA32 cw0 + per_packet_options */
+        cw0 = EVAL_cw0();
+        *tp++=0x00000000 | ((cw0+per_packet_options)&0xffffffffu)<<0;
+        /* DATA32 cw1 */
+        cw1 = EVAL_cw1();
+        *tp++=0x00000000 | ((cw1)&0xffffffffu)<<0;
+    }
+    bypass = EVAL_bypass();
+    hdrlen = EVAL_hdrlen();
+    if (hdrlen == 4294967295u)
+    {
+        LOG_WARN("TokenBuilder: bad packet, ip header parse error\n");
+        rc = TKB_BAD_PACKET; goto error;
+    }
+    proto = EVAL_proto();
+    u_word = EVAL_u_word();
+    if (u_word != 0u)
+    {
+        /* DATA32 u_word */
+        *tp++=0x00000000 | ((u_word)&0xffffffffu)<<0;
+    }
+    ivhandling = EVAL_ivhandling();
+    if (ivhandling >= 8u)
+    {
+        if (ivhandling < 10u)
+        {
+            iv = EVAL_iv();
+            TokenBuilder_CopyBytes(tp, iv, 8);
+            tp += 2;
+        }
+        else if (ivhandling > 13u)
+        {
+            iv = EVAL_iv();
+            TokenBuilder_CopyBytes(tp, iv, 16);
+            tp += 4;
+        }
+        else if (ivhandling == 10u)
+        {
+            /* DATA32 srtp_iv0 */
+            srtp_iv0 = EVAL_srtp_iv0();
+            *tp++=0x00000000 | ((srtp_iv0)&0xffffffffu)<<0;
+            /* DATA32 srtp_iv1 */
+            srtp_iv1 = EVAL_srtp_iv1();
+            *tp++=0x00000000 | ((srtp_iv1)&0xffffffffu)<<0;
+            /* DATA32 srtp_iv2 */
+            srtp_iv2 = EVAL_srtp_iv2();
+            *tp++=0x00000000 | ((srtp_iv2)&0xffffffffu)<<0;
+            /* DATA32 srtp_iv3 */
+            srtp_iv3 = EVAL_srtp_iv3();
+            *tp++=0x00000000 | ((srtp_iv3)&0xffffffffu)<<0;
+        }
+        else if (ivhandling == 11u)
+        {
+            /* DATA32 count */
+            count = EVAL_count();
+            *tp++=0x00000000 | ((count)&0xffffffffu)<<0;
+            /* DATA32 bearer_dir_fresh */
+            bearer_dir_fresh = EVAL_bearer_dir_fresh();
+            *tp++=0x00000000 | ((bearer_dir_fresh)&0xffffffffu)<<0;
+        }
+        else
+        {
+            /* DATA32 count */
+            count = EVAL_count();
+            *tp++=0x00000000 | ((count)&0xffffffffu)<<0;
+            /* DATA32 bearer_dir_fresh */
+            bearer_dir_fresh = EVAL_bearer_dir_fresh();
+            *tp++=0x00000000 | ((bearer_dir_fresh)&0xffffffffu)<<0;
+            /* DATA32 count */
+            *tp++=0x00000000 | ((count)&0xffffffffu)<<0;
+            /* DATA32 bearer_dir_fresh */
+            *tp++=0x00000000 | ((bearer_dir_fresh)&0xffffffffu)<<0;
+        }
+    }
+    if (bypass > 0u)
+    {
+        if (proto != 9u)
+        {
+            if (proto != 28u)
+            {
+                /* DIR OUT,bypass */
+                *tp++=0x01000000 | ((bypass)&0x1ffffu)<<0;
+            }
+        }
+    }
+    packetsize = EVAL_packetsize();
+    if (packetsize > 131071u)
+    {
+        LOG_WARN("TokenBuilder: bad packet, too long\n");
+        rc = TKB_BAD_PACKET; goto error;
+    }
+#if TKB_HAVE_PROTO_IPSEC == 1u
+#if TKB_HAVE_EXTENDED_IPSEC == 1u
+    hproto = EVAL_hproto();
+    switch(hproto)
+    {
+    case 5: /* ipv4_out_transp */
+        /* IPV4CHK OUT,50,outlen */
+        outlen = EVAL_outlen();
+        *tp++=0x61000000 | ((50u)&0xffu)<<16 | ((outlen)&0xffffu)<<0;
+        /* DIR OUT,hdrlen-12 */
+        *tp++=0x01000000 | ((-12u+hdrlen)&0x1ffffu)<<0;
+        break;
+    case 1: /* ipv4_out_transp_nohdrproc */
+        /* DIR OUT,hdrlen */
+        *tp++=0x01000000 | ((hdrlen)&0x1ffffu)<<0;
+        break;
+    case 11: /* ipv6_out_transp */
+        if (hdrlen > 40u)
+        {
+            /* IPV6 OUT,nh,outlen-40 */
+            nh = EVAL_nh();
+            outlen = EVAL_outlen();
+            *tp++=0x81000000 | ((nh)&0xffu)<<16 | ((-40u+outlen)&0xffffu)<<0;
+            /* DIR OUT,prev_nhoffset-8    ; -8 to include two 32-bit words of the IPv6 header passed via IPV6 instruction */
+            prev_nhoffset = EVAL_prev_nhoffset();
+            *tp++=0x01000000 | ((-8u+prev_nhoffset)&0x1ffffu)<<0;
+            /* REPL OUT,ORIG_TOKEN,1                ; replace NH byte of the last extension header with ESP type */
+            *tp++=0x31d80000 | ((1u)&0x1ffffu)<<0;
+            /* DATA32 50                            ; ESP proto */
+            *tp++=0x00000000 | ((50u)&0xffffffffu)<<0;
+            /* DIR OUT,hdrlen-prev_nhoffset-1    ; bypass the rest of the last extension header */
+            *tp++=0x01000000 | ((-1u+hdrlen-prev_nhoffset)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* IPV6 OUT,50,outlen-hdrlen */
+            outlen = EVAL_outlen();
+            *tp++=0x81000000 | ((50u)&0xffu)<<16 | ((outlen-hdrlen)&0xffffu)<<0;
+            /* DIR OUT,hdrlen-8 */
+            *tp++=0x01000000 | ((-8u+hdrlen)&0x1ffffu)<<0;
+        }
+        break;
+    case 2: /* ipv4_out_tunnel */
+        /* INS OUT,ORIG_TOKEN,20 */
+        *tp++=0x21d80000 | ((20u)&0x1ffffu)<<0;
+        /* DATA32 tunnel_w0_ip4 */
+        tunnel_w0_ip4 = EVAL_tunnel_w0_ip4();
+        *tp++=0x00000000 | ((tunnel_w0_ip4)&0xffffffffu)<<0;
+        /* DATA32 tunnel_w1_ip4 */
+        tunnel_w1_ip4 = EVAL_tunnel_w1_ip4();
+        *tp++=0x00000000 | ((tunnel_w1_ip4)&0xffffffffu)<<0;
+        /* DATA32 tunnel_w2_ip4 */
+        tunnel_w2_ip4 = EVAL_tunnel_w2_ip4();
+        *tp++=0x00000000 | ((tunnel_w2_ip4)&0xffffffffu)<<0;
+        tunnel_ip_addr = EVAL_tunnel_ip_addr();
+        TokenBuilder_CopyBytes(tp, tunnel_ip_addr, 8);
+        tp += 2;
+        break;
+    case 7: /* ipv6_out_tunnel */
+        /* INS OUT,ORIG_TOKEN,40 */
+        *tp++=0x21d80000 | ((40u)&0x1ffffu)<<0;
+        /* DATA32 tunnel_w0_ip6 */
+        tunnel_w0_ip6 = EVAL_tunnel_w0_ip6();
+        *tp++=0x00000000 | ((tunnel_w0_ip6)&0xffffffffu)<<0;
+        /* DATA32 tunnel_w1_ip6 */
+        tunnel_w1_ip6 = EVAL_tunnel_w1_ip6();
+        *tp++=0x00000000 | ((tunnel_w1_ip6)&0xffffffffu)<<0;
+        tunnel_ip_addr = EVAL_tunnel_ip_addr();
+        TokenBuilder_CopyBytes(tp, tunnel_ip_addr, 32);
+        tp += 8;
+        break;
+    case 6: /* ipv4_in_transp */
+        /* IPV4CHK OUT,0,0 */
+        *tp++=0x61000000 | ((0u)&0xffu)<<16 | ((0u)&0xffffu)<<0;
+        /* DIR OUT,hdrlen-12 */
+        *tp++=0x01000000 | ((-12u+hdrlen)&0x1ffffu)<<0;
+        break;
+    case 3: /* ipv4_in_transp_nohdrproc */
+        /* DIR OUT, hdrlen */
+        *tp++=0x01000000 | ((hdrlen)&0x1ffffu)<<0;
+        break;
+    case 12: /* ipv6_in_transp */
+        nh = EVAL_nh();
+        if (nh == 50u)
+        {
+            /* IPV6 OUT,00,00                      ; zeroise the NH and payload length */
+            *tp++=0x81000000 | ((0u)&0xffu)<<16 | ((0u)&0xffffu)<<0;
+            /* DIR OUT,hdrlen-8                    ; pass the remaining header words */
+            *tp++=0x01000000 | ((-8u+hdrlen)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* IPV6 OUT,nh,00                      ; bypass NH, but zeroise the payload length */
+            *tp++=0x81000000 | ((nh)&0xffu)<<16 | ((0u)&0xffffu)<<0;
+            /* DIR OUT,prev_nhoffset-8   ; pass the remaining data until the next header of the last extentnio header */
+            prev_nhoffset = EVAL_prev_nhoffset();
+            *tp++=0x01000000 | ((-8u+prev_nhoffset)&0x1ffffu)<<0;
+            /* REPL OUT,ORIG_TOKEN,1               ; zeroize the NH field */
+            *tp++=0x31d80000 | ((1u)&0x1ffffu)<<0;
+            /* DATA32 00                           ; */
+            *tp++=0x00000000 | ((0u)&0xffffffffu)<<0;
+            /* DIR OUT,hdrlen-prev_nhoffset-1      ; bypass the rest of the last extension header */
+            *tp++=0x01000000 | ((-1u+hdrlen-prev_nhoffset)&0x1ffffu)<<0;
+        }
+        break;
+    case 4: /* ipv4_in_tunnel */
+    case 8: /* ipv6_in_tunnel */
+    case 24: /* ipv4_in_tunnel_natt */
+    case 28: /* ipv6_in_tunnel_natt */
+        /* DIR OUT, ohdrlen     ; keep (optionally) outer IP heade */
+        ohdrlen = EVAL_ohdrlen();
+        *tp++=0x01000000 | ((ohdrlen)&0x1ffffu)<<0;
+        /* REM hdrlen-ohdrlen   ; remobe IP header (optionally) and NATT header. */
+        *tp++=0x40d80000 | ((hdrlen-ohdrlen)&0x1ffffu)<<0;
+        break;
+    case 25: /* ipv4_out_transp_natt */
+        /* IPV4CHK OUT,17,outlen    ; include 8 byte of NAT-T */
+        outlen = EVAL_outlen();
+        *tp++=0x61000000 | ((17u)&0xffu)<<16 | ((outlen)&0xffffu)<<0;
+        is_nat = EVAL_is_nat();
+        if (is_nat != 0u)
+        {
+            /* REPL OUT,ORIG_TOKEN,8 */
+            *tp++=0x31d80000 | ((8u)&0x1ffffu)<<0;
+            tunnel_ip_addr = EVAL_tunnel_ip_addr();
+            TokenBuilder_CopyBytes(tp, tunnel_ip_addr, 8);
+            tp += 2;
+            /* DIR OUT,hdrlen-20 */
+            *tp++=0x01000000 | ((-20u+hdrlen)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* DIR OUT,hdrlen-12 */
+            *tp++=0x01000000 | ((-12u+hdrlen)&0x1ffffu)<<0;
+        }
+        /* INS OUT,ORIG_TOKEN,8 */
+        *tp++=0x21d80000 | ((8u)&0x1ffffu)<<0;
+        /* DATA32 ports_natt */
+        ports_natt = EVAL_ports_natt();
+        *tp++=0x00000000 | ((ports_natt)&0xffffffffu)<<0;
+        /* SWAP16 outlen - hdrlen ; include 8 byte of NAT-T */
+        *tp++ = ByteSwap16(outlen-hdrlen);
+        break;
+    case 31: /* ipv6_out_transp_natt */
+        if (hdrlen > 40u)
+        {
+            /* IPV6 OUT,nh,outlen-40              ; include 8 bytes of NAT-T */
+            nh = EVAL_nh();
+            outlen = EVAL_outlen();
+            *tp++=0x81000000 | ((nh)&0xffu)<<16 | ((-40u+outlen)&0xffffu)<<0;
+            is_nat = EVAL_is_nat();
+            if (is_nat != 0u)
+            {
+                /* REPL OUT,ORIG_TOKEN,32 */
+                *tp++=0x31d80000 | ((32u)&0x1ffffu)<<0;
+                tunnel_ip_addr = EVAL_tunnel_ip_addr();
+                TokenBuilder_CopyBytes(tp, tunnel_ip_addr, 32);
+                tp += 8;
+                /* DIR OUT,prev_nhoffset-40 */
+                prev_nhoffset = EVAL_prev_nhoffset();
+                *tp++=0x01000000 | ((-40u+prev_nhoffset)&0x1ffffu)<<0;
+            }
+            else
+            {
+                /* DIR OUT,prev_nhoffset-8    ; -8 to include two 32-bit words of the IPv6 header passed via IPV6 instruction */
+                prev_nhoffset = EVAL_prev_nhoffset();
+                *tp++=0x01000000 | ((-8u+prev_nhoffset)&0x1ffffu)<<0;
+            }
+            /* REPL OUT,ORIG_TOKEN,1                ; replace NH byte of the last extension header with UDP type */
+            *tp++=0x31d80000 | ((1u)&0x1ffffu)<<0;
+            /* DATA32 17                            ; */
+            *tp++=0x00000000 | ((17u)&0xffffffffu)<<0;
+            /* DIR OUT,hdrlen-prev_nhoffset-1    ; bypass the rest data of the last extension header */
+            prev_nhoffset = EVAL_prev_nhoffset();
+            *tp++=0x01000000 | ((-1u+hdrlen-prev_nhoffset)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* IPV6 OUT,17,outlen-hdrlen         ; include 8 bytes of NAT-T */
+            outlen = EVAL_outlen();
+            *tp++=0x81000000 | ((17u)&0xffu)<<16 | ((outlen-hdrlen)&0xffffu)<<0;
+            is_nat = EVAL_is_nat();
+            if (is_nat != 0u)
+            {
+                /* REPL OUT,ORIG_TOKEN,32 */
+                *tp++=0x31d80000 | ((32u)&0x1ffffu)<<0;
+                tunnel_ip_addr = EVAL_tunnel_ip_addr();
+                TokenBuilder_CopyBytes(tp, tunnel_ip_addr, 32);
+                tp += 8;
+                /* DIR OUT,hdrlen-40 */
+                *tp++=0x01000000 | ((-40u+hdrlen)&0x1ffffu)<<0;
+            }
+            else
+            {
+                /* DIR OUT,hdrlen-8 */
+                *tp++=0x01000000 | ((-8u+hdrlen)&0x1ffffu)<<0;
+            }
+        }
+        /* INS OUT,ORIG_TOKEN,8 */
+        *tp++=0x21d80000 | ((8u)&0x1ffffu)<<0;
+        /* DATA32 ports_natt */
+        ports_natt = EVAL_ports_natt();
+        *tp++=0x00000000 | ((ports_natt)&0xffffffffu)<<0;
+        outlen = EVAL_outlen();
+        /* SWAP16 outlen-hdrlen                  ; include 8 bytes of NAT-T */
+        *tp++ = ByteSwap16(outlen-hdrlen);
+        break;
+    case 22: /* ipv4_out_tunnel_natt */
+        /* INS OUT,ORIG_TOKEN,28 */
+        *tp++=0x21d80000 | ((28u)&0x1ffffu)<<0;
+        /* DATA32 tunnel_w0_ip4 */
+        tunnel_w0_ip4 = EVAL_tunnel_w0_ip4();
+        *tp++=0x00000000 | ((tunnel_w0_ip4)&0xffffffffu)<<0;
+        /* DATA32 tunnel_w1_ip4 */
+        tunnel_w1_ip4 = EVAL_tunnel_w1_ip4();
+        *tp++=0x00000000 | ((tunnel_w1_ip4)&0xffffffffu)<<0;
+        /* DATA32 tunnel_w2_ip4 */
+        tunnel_w2_ip4 = EVAL_tunnel_w2_ip4();
+        *tp++=0x00000000 | ((tunnel_w2_ip4)&0xffffffffu)<<0;
+        tunnel_ip_addr = EVAL_tunnel_ip_addr();
+        TokenBuilder_CopyBytes(tp, tunnel_ip_addr, 8);
+        tp += 2;
+        /* DATA32 ports_natt */
+        ports_natt = EVAL_ports_natt();
+        *tp++=0x00000000 | ((ports_natt)&0xffffffffu)<<0;
+        outlen = EVAL_outlen();
+        ohdrlen = EVAL_ohdrlen();
+        /* SWAP16 outlen+8 - ohdrlen                ; include 8 byte of NAT-T */
+        *tp++ = ByteSwap16(8u+outlen-ohdrlen);
+        break;
+    case 27: /* ipv6_out_tunnel_natt */
+        /* INS OUT,ORIG_TOKEN,48 */
+        *tp++=0x21d80000 | ((48u)&0x1ffffu)<<0;
+        /* DATA32 tunnel_w0_ip6 */
+        tunnel_w0_ip6 = EVAL_tunnel_w0_ip6();
+        *tp++=0x00000000 | ((tunnel_w0_ip6)&0xffffffffu)<<0;
+        /* DATA32 tunnel_w1_ip6 */
+        tunnel_w1_ip6 = EVAL_tunnel_w1_ip6();
+        *tp++=0x00000000 | ((tunnel_w1_ip6)&0xffffffffu)<<0;
+        tunnel_ip_addr = EVAL_tunnel_ip_addr();
+        TokenBuilder_CopyBytes(tp, tunnel_ip_addr, 32);
+        tp += 8;
+        /* DATA32 ports_natt */
+        ports_natt = EVAL_ports_natt();
+        *tp++=0x00000000 | ((ports_natt)&0xffffffffu)<<0;
+        outlen = EVAL_outlen();
+        ohdrlen = EVAL_ohdrlen();
+        /* SWAP16 outlen+8 - ohdrlen                ; include 8 byte of NAT-T */
+        *tp++ = ByteSwap16(8u+outlen-ohdrlen);
+        break;
+    case 26: /* ipv4_in_transp_natt */
+        /* IPV4CHK OUT,0,0                         ; IP header update instruction */
+        *tp++=0x61000000 | ((0u)&0xffu)<<16 | ((0u)&0xffffu)<<0;
+        is_nat = EVAL_is_nat();
+        if (is_nat != 0u)
+        {
+            /* REPL OUT,ORIG_TOKEN,4 */
+            *tp++=0x31d80000 | ((4u)&0x1ffffu)<<0;
+            tunnel_ip_addr = EVAL_tunnel_ip_addr();
+            TokenBuilder_CopyBytes(tp, tunnel_ip_addr, 4);
+            tp += 1;
+            /* REPL OUT,ORIG_TOKEN,4 */
+            *tp++=0x31d80000 | ((4u)&0x1ffffu)<<0;
+            dst_ip_addr = EVAL_dst_ip_addr();
+            TokenBuilder_CopyBytes(tp, dst_ip_addr, 4);
+            tp += 1;
+            /* DIR OUT,hdrlen-20-8 */
+            *tp++=0x01000000 | ((-28u+hdrlen)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* DIR OUT,hdrlen-12-8                     ; bypass the rest of IP header words */
+            *tp++=0x01000000 | ((-20u+hdrlen)&0x1ffffu)<<0;
+        }
+        /* REM 8                                   ; remove NAT-T UDP header */
+        *tp++=0x40d80000 | ((8u)&0x1ffffu)<<0;
+        break;
+    case 32: /* ipv6_in_transp_natt */
+        nh = EVAL_nh();
+        if (nh == 17u)
+        {
+            /* IPV6 OUT,00,00                      ; bypass IPv6 header and zeroise length and protocol fields */
+            *tp++=0x81000000 | ((0u)&0xffu)<<16 | ((0u)&0xffffu)<<0;
+            is_nat = EVAL_is_nat();
+            if (is_nat != 0u)
+            {
+                /* REPL OUT,ORIG_TOKEN,32 */
+                *tp++=0x31d80000 | ((32u)&0x1ffffu)<<0;
+                tunnel_ip_addr = EVAL_tunnel_ip_addr();
+                TokenBuilder_CopyBytes(tp, tunnel_ip_addr, 32);
+                tp += 8;
+                /* DIR OUT,hdrlen-40-8 */
+                *tp++=0x01000000 | ((-48u+hdrlen)&0x1ffffu)<<0;
+            }
+            else
+            {
+                /* DIR OUT,hdrlen-8-8                  ; bypass rest of the IPv6 header (hdrlen includes the UDP length) */
+                *tp++=0x01000000 | ((-16u+hdrlen)&0x1ffffu)<<0;
+            }
+        }
+        else
+        {
+            prev_nhoffset = EVAL_prev_nhoffset();
+            /* IPV6 OUT,nh,00                      ; bypass IPv6 header and restore the next header */
+            *tp++=0x81000000 | ((nh)&0xffu)<<16 | ((0u)&0xffffu)<<0;
+            is_nat = EVAL_is_nat();
+            if (is_nat != 0u)
+            {
+                /* REPL OUT,ORIG_TOKEN,32 */
+                *tp++=0x31d80000 | ((32u)&0x1ffffu)<<0;
+                tunnel_ip_addr = EVAL_tunnel_ip_addr();
+                TokenBuilder_CopyBytes(tp, tunnel_ip_addr, 32);
+                tp += 8;
+                /* DIR OUT,prev_nhoffset-40 */
+                *tp++=0x01000000 | ((-40u+prev_nhoffset)&0x1ffffu)<<0;
+            }
+            else
+            {
+                /* DIR OUT,prev_nhoffset-8   ; bypass rest of the IPv6 header (hdrlen includes the UDP length) */
+                *tp++=0x01000000 | ((-8u+prev_nhoffset)&0x1ffffu)<<0;
+            }
+            /* REPL OUT,ORIG_TOKEN,1               ; zeroise the NH byte of the last extension header */
+            *tp++=0x31d80000 | ((1u)&0x1ffffu)<<0;
+            /* DATA32 00                           ; */
+            *tp++=0x00000000 | ((0u)&0xffffffffu)<<0;
+            /* DIR OUT,hdrlen-prev_nhoffset-1-8    ; bypass the rest data of the last extension header */
+            *tp++=0x01000000 | ((-9u+hdrlen-prev_nhoffset)&0x1ffffu)<<0;
+        }
+        /* REM 8                                   ; remove UDP NAT-T header */
+        *tp++=0x40d80000 | ((8u)&0x1ffffu)<<0;
+        break;
+    case 13: /* ipv4_out_dtls */
+        /* IPV4CHK OUT,nh,outlen+hdrlen */
+        nh = EVAL_nh();
+        outlen = EVAL_outlen();
+        *tp++=0x61000000 | ((nh)&0xffu)<<16 | ((outlen+hdrlen)&0xffffu)<<0;
+        if (nh == 136u)
+        {
+            /* DIR OUT,hdrlen-12 */
+            *tp++=0x01000000 | ((-12u+hdrlen)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* DIR OUT, hdrlen-16 */
+            *tp++=0x01000000 | ((-16u+hdrlen)&0x1ffffu)<<0;
+            /* REPL OUT,ORIG_TOKEN,2 */
+            *tp++=0x31d80000 | ((2u)&0x1ffffu)<<0;
+            /* SWAP16 outlen+8 ; include 8 bytes UDP header */
+            *tp++ = ByteSwap16(8u+outlen);
+            /* DIR OUT,2 */
+            *tp++=0x01000000 | ((2u)&0x1ffffu)<<0;
+        }
+        break;
+    case 33: /* ipv6_out_dtls */
+        /* IPV6 OUT,prev_nhoffset,outlen+hdrlen-40 */
+        prev_nhoffset = EVAL_prev_nhoffset();
+        outlen = EVAL_outlen();
+        *tp++=0x81000000 | ((prev_nhoffset)&0xffu)<<16 | ((-40u+outlen+hdrlen)&0xffffu)<<0;
+        nh = EVAL_nh();
+        if (nh == 136u)
+        {
+            /* DIR OUT,hdrlen-8 */
+            *tp++=0x01000000 | ((-8u+hdrlen)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* DIR OUT, hdrlen-12 */
+            *tp++=0x01000000 | ((-12u+hdrlen)&0x1ffffu)<<0;
+            /* REPL OUT,ORIG_TOKEN,2 */
+            *tp++=0x31d80000 | ((2u)&0x1ffffu)<<0;
+            /* SWAP16 outlen+8 ; include 8 bytes UDP header */
+            *tp++ = ByteSwap16(8u+outlen);
+            /* DIR OUT,2 */
+            *tp++=0x01000000 | ((2u)&0x1ffffu)<<0;
+        }
+        break;
+    }
+#endif
+#endif
+    switch(proto)
+    {
+    case 0: /* esp_out */
+#if TKB_HAVE_PROTO_IPSEC == 1u
+        if (packetsize <= bypass+hdrlen)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for ESP outbound\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        if (ivhandling == 2u)
+        {
+            /* INS      HASH,ORIG_SPI,8 */
+            *tp++=0x23900000 | ((8u)&0x1ffffu)<<0;
+            /* INS      HASH,ORIG_IV1,ivlen */
+            ivlen = EVAL_ivlen();
+            *tp++=0x23a80000 | ((ivlen)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* INS      HASH,ORIG_SPI,8+ivlen */
+            ivlen = EVAL_ivlen();
+            *tp++=0x23900000 | ((8u+ivlen)&0x1ffffu)<<0;
+        }
+        /* DIR      CRYPTHASH,packetsize-bypass-hdrlen */
+        *tp++=0x07000000 | ((packetsize-bypass-hdrlen)&0x1ffffu)<<0;
+        icvlen = EVAL_icvlen();
+        if (icvlen > 0u)
+        {
+            extseq = EVAL_extseq();
+            if (extseq == 0u)
+            {
+                /* INS      CRYPTHASH,PAD_IPSEC,nextheader,pad_bytes,LAST,LASTHASH */
+                nextheader = EVAL_nextheader();
+                pad_bytes = EVAL_pad_bytes();
+                *tp++=0x2f220000 | ((nextheader)&0xffu)<<9 | ((pad_bytes)&0x1ffu)<<0;
+            }
+            else
+            {
+                /* INS      CRYPTHASH,PAD_IPSEC,nextheader,pad_bytes,LAST */
+                nextheader = EVAL_nextheader();
+                pad_bytes = EVAL_pad_bytes();
+                *tp++=0x2f200000 | ((nextheader)&0xffu)<<9 | ((pad_bytes)&0x1ffu)<<0;
+                /* INS      HASHONLY,ORIG_EXTSEQNUM_RES2,4,LASTHASH */
+                *tp++=0x224a0000 | ((4u)&0x1ffffu)<<0;
+            }
+            /* INS      OUT,ORIG_HASH,icvlen,LASTHASHPKT */
+            *tp++=0x21e60000 | ((icvlen)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* INS      CRYPT,PAD_IPSEC,nextheader,pad_bytes,LAST,LASTHASHPKT */
+            nextheader = EVAL_nextheader();
+            pad_bytes = EVAL_pad_bytes();
+            *tp++=0x2d260000 | ((nextheader)&0xffu)<<9 | ((pad_bytes)&0x1ffu)<<0;
+        }
+        /* VERIFY   0  ; Causes any sequence number rollover error to fail the packet. */
+        *tp++=0xd0060000 | ((0u)&0x7fu)<<0;
+        /* CTX      ORIG_SEQNUM,seq_offset,1+extseq */
+        seq_offset = EVAL_seq_offset();
+        extseq = EVAL_extseq();
+        *tp++=0xe0560800 | ((seq_offset)&0xffu)<<0 | ((1u+extseq)&0xfu)<<24;
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 1: /* esp_in */
+#if TKB_HAVE_PROTO_IPSEC == 1u
+        ivlen = EVAL_ivlen();
+        icvlen = EVAL_icvlen();
+        pad_blocksize = EVAL_pad_blocksize();
+        if (packetsize < 8u+ivlen+icvlen+pad_blocksize+bypass+hdrlen)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for ESP inbound\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        pad_remainder = EVAL_pad_remainder();
+        if (pad_remainder != 0u)
+        {
+            LOG_WARN("TokenBuilder: bad packet, pad alignment ESP inbound\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+#if TKB_HAVE_ECN_FIXUP == 1u
+        /* DATA32 ecn_fixup_instr */
+        ecn_fixup_instr = EVAL_ecn_fixup_instr();
+        *tp++=0x00000000 | ((ecn_fixup_instr)&0xffffffffu)<<0;
+#endif
+        if (ivhandling == 0u)
+        {
+            /* RETR     HASHONLY,ORIG_SPI,8 */
+            *tp++=0x42900000 | ((8u)&0x1ffffu)<<0;
+            /* RETR     HASHONLY,ORIG_IV1,ivlen */
+            *tp++=0x42a80000 | ((ivlen)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* RETR     HASHONLY,ORIG_SPI,8+ivlen */
+            *tp++=0x42900000 | ((8u+ivlen)&0x1ffffu)<<0;
+        }
+        if (icvlen > 0u)
+        {
+            extseq = EVAL_extseq();
+            if (extseq != 1u)
+            {
+                /* DIR   CRYPTHASH,packetsize - ivlen - 8 - icvlen - bypass - hdrlen,LAST,LASTHASH */
+                *tp++=0x0f020000 | ((-8u+packetsize-ivlen-icvlen-bypass-hdrlen)&0x1ffffu)<<0;
+            }
+            else
+            {
+                /* DIR   CRYPTHASH,packetsize - ivlen - 8 - icvlen - bypass - hdrlen,LAST */
+                *tp++=0x0f000000 | ((-8u+packetsize-ivlen-icvlen-bypass-hdrlen)&0x1ffffu)<<0;
+                /* INS   HASHONLY, ORIG_EXTSEQNUM_RES2,4,LASTHASH */
+                *tp++=0x224a0000 | ((4u)&0x1ffffu)<<0;
+            }
+            /* RETR  NONE,ORIG_HASH,icvlen,LASTHASHPKT */
+            *tp++=0x40e60000 | ((icvlen)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* DIR CRYPT,packetsize - ivlen - 8 - icvlen - bypass - hdrlen,LAST,LASTHASHPKT */
+            *tp++=0x0d060000 | ((-8u+packetsize-ivlen-icvlen-bypass-hdrlen)&0x1ffffu)<<0;
+        }
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 2: /* esp_out_ccm */
+#if TKB_HAVE_PROTO_IPSEC == 1u
+        if (packetsize <= bypass+hdrlen)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for ESP outbound CCM\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        /* INS      HASHONLY,ORIG_TOKEN,4 */
+        *tp++=0x22d80000 | ((4u)&0x1ffffu)<<0;
+        /* DATA32   salt */
+        salt = EVAL_salt();
+        *tp++=0x00000000 | ((salt)&0xffffffffu)<<0;
+        /* INS      HASHONLY,ORIG_IV1,8 */
+        *tp++=0x22a80000 | ((8u)&0x1ffffu)<<0;
+        /* INS      HASHONLY,ORIG_TOKEN,6     ; Insert message length + AAD length. */
+        *tp++=0x22d80000 | ((6u)&0x1ffffu)<<0;
+        /* DATA32 swaplen                     ; Message length, byte-swapped */
+        swaplen = EVAL_swaplen();
+        *tp++=0x00000000 | ((swaplen)&0xffffffffu)<<0;
+        extseq = EVAL_extseq();
+        if (extseq == 0u)
+        {
+            /* DATA32   0x0800  ; AAD length, byte-swapped */
+            *tp++=0x00000000 | ((2048u)&0xffffffffu)<<0;
+            /* INS      HASH,ORIG_SPI,8 */
+            *tp++=0x23900000 | ((8u)&0x1ffffu)<<0;
+            /* INS      HASHONLY, PAD_ZERO, 0, 6 */
+            *tp++=0x22000000 | ((0u)&0x1u)<<16 | ((6u)&0xffffu)<<0;
+        }
+        else
+        {
+            /* DATA32   0x0c00 ; AAD length, byte-swapped */
+            *tp++=0x00000000 | ((3072u)&0xffffffffu)<<0;
+            /* INS      HASH,ORIG_SPI,4 */
+            *tp++=0x23900000 | ((4u)&0x1ffffu)<<0;
+            /* INS      HASHONLY,ORIG_EXTSEQNUM_RES2, 4 */
+            *tp++=0x22480000 | ((4u)&0x1ffffu)<<0;
+            /* INS      HASH,ORIG_SEQNUM_RES, 4 */
+            *tp++=0x23980000 | ((4u)&0x1ffffu)<<0;
+            /* INS      HASHONLY, PAD_ZERO, 0, 2 */
+            *tp++=0x22000000 | ((0u)&0x1u)<<16 | ((2u)&0xffffu)<<0;
+        }
+        /* INS      OUT,ORIG_IV1,ivlen */
+        ivlen = EVAL_ivlen();
+        *tp++=0x21a80000 | ((ivlen)&0x1ffffu)<<0;
+        /* REMRES   bypass+ohdrlen+8+ivlen, 16 */
+        ohdrlen = EVAL_ohdrlen();
+        *tp++=0xa0000000 | ((8u+bypass+ohdrlen+ivlen)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+        /* INS      CRYPT, PAD_ZERO, 0, 16 */
+        *tp++=0x25000000 | ((0u)&0x1u)<<16 | ((16u)&0xffffu)<<0;
+        /* DIR      CRYPTHASH, packetsize-bypass-hdrlen */
+        *tp++=0x07000000 | ((packetsize-bypass-hdrlen)&0x1ffffu)<<0;
+        hashpad = EVAL_hashpad();
+        if (hashpad == 0u)
+        {
+            /* INS      CRYPTHASH,PAD_IPSEC,nextheader,pad_bytes,LAST,LASTHASH */
+            nextheader = EVAL_nextheader();
+            pad_bytes = EVAL_pad_bytes();
+            *tp++=0x2f220000 | ((nextheader)&0xffu)<<9 | ((pad_bytes)&0x1ffu)<<0;
+        }
+        else
+        {
+            /* INS      CRYPTHASH,PAD_IPSEC,nextheader,pad_bytes,LAST */
+            nextheader = EVAL_nextheader();
+            pad_bytes = EVAL_pad_bytes();
+            *tp++=0x2f200000 | ((nextheader)&0xffu)<<9 | ((pad_bytes)&0x1ffu)<<0;
+            /* INS      HASHONLY,PAD_ZERO,0,hashpad,LASTHASH */
+            *tp++=0x22020000 | ((0u)&0x1u)<<16 | ((hashpad)&0xffffu)<<0;
+        }
+        /* INS      OUT,ORIG_HASH,icvlen,LASTHASHPKT */
+        icvlen = EVAL_icvlen();
+        *tp++=0x21e60000 | ((icvlen)&0x1ffffu)<<0;
+        /* VERIFY   0  ; Causes any sequence number rollover error to fail the packet. */
+        *tp++=0xd0060000 | ((0u)&0x7fu)<<0;
+        /* CTX      ORIG_SEQNUM,seq_offset,1+extseq */
+        seq_offset = EVAL_seq_offset();
+        *tp++=0xe0560800 | ((seq_offset)&0xffu)<<0 | ((1u+extseq)&0xfu)<<24;
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 3: /* esp_in_ccm */
+#if TKB_HAVE_PROTO_IPSEC == 1u
+        ivlen = EVAL_ivlen();
+        icvlen = EVAL_icvlen();
+        pad_blocksize = EVAL_pad_blocksize();
+        if (packetsize < 8u+ivlen+icvlen+pad_blocksize+bypass+hdrlen)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for ESP inbound CCM\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        pad_remainder = EVAL_pad_remainder();
+        if (pad_remainder != 0u)
+        {
+            LOG_WARN("TokenBuilder: bad packet, pad alignment ESP inbound CCM\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        /* RETR     NONE,ORIG_SPI,8 */
+        *tp++=0x40900000 | ((8u)&0x1ffffu)<<0;
+        /* RETR     NONE,ORIG_IV1,ivlen */
+        *tp++=0x40a80000 | ((ivlen)&0x1ffffu)<<0;
+        /* INS      HASHONLY,ORIG_TOKEN,4 */
+        *tp++=0x22d80000 | ((4u)&0x1ffffu)<<0;
+        /* DATA32   salt */
+        salt = EVAL_salt();
+        *tp++=0x00000000 | ((salt)&0xffffffffu)<<0;
+        /* INS      HASHONLY,ORIG_IV1,8 */
+        *tp++=0x22a80000 | ((8u)&0x1ffffu)<<0;
+        /* INS      HASHONLY,ORIG_TOKEN,6    ; Insert message length + AAD length. */
+        *tp++=0x22d80000 | ((6u)&0x1ffffu)<<0;
+        /* DATA32 swaplen                    ; Message length, byte-swapped */
+        swaplen = EVAL_swaplen();
+        *tp++=0x00000000 | ((swaplen)&0xffffffffu)<<0;
+        extseq = EVAL_extseq();
+        if (extseq != 1u)
+        {
+            /* DATA32 0x0800  ; AAD length, byte-swapped */
+            *tp++=0x00000000 | ((2048u)&0xffffffffu)<<0;
+            /* INS      HASHONLY,ORIG_SPI,8 */
+            *tp++=0x22900000 | ((8u)&0x1ffffu)<<0;
+            /* INS      HASHONLY, PAD_ZERO, 0, 6 */
+            *tp++=0x22000000 | ((0u)&0x1u)<<16 | ((6u)&0xffffu)<<0;
+        }
+        else
+        {
+            /* DATA32 0x0c00 ; AAD length, byte-swapped */
+            *tp++=0x00000000 | ((3072u)&0xffffffffu)<<0;
+            /* INS      HASHONLY,ORIG_SPI,4 */
+            *tp++=0x22900000 | ((4u)&0x1ffffu)<<0;
+            /* INS      HASHONLY,ORIG_EXTSEQNUM_RES2, 4 */
+            *tp++=0x22480000 | ((4u)&0x1ffffu)<<0;
+            /* INS      HASHONLY,ORIG_SEQNUM_RES, 4 */
+            *tp++=0x22980000 | ((4u)&0x1ffffu)<<0;
+            /* INS      HASHONLY, PAD_ZERO, 0, 2 */
+            *tp++=0x22000000 | ((0u)&0x1u)<<16 | ((2u)&0xffffu)<<0;
+        }
+        /* REMRES   bypass+ohdrlen, 16 */
+        ohdrlen = EVAL_ohdrlen();
+        *tp++=0xa0000000 | ((bypass+ohdrlen)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+#if TKB_HAVE_ECN_FIXUP == 1u
+        /* DATA32 ecn_fixup_instr */
+        ecn_fixup_instr = EVAL_ecn_fixup_instr();
+        *tp++=0x00000000 | ((ecn_fixup_instr)&0xffffffffu)<<0;
+#endif
+        /* INS      CRYPT, PAD_ZERO, 0, 16 */
+        *tp++=0x25000000 | ((0u)&0x1u)<<16 | ((16u)&0xffffu)<<0;
+        hashpad = EVAL_hashpad();
+        if (hashpad == 0u)
+        {
+            /* DIR      CRYPTHASH,packetsize - ivlen - 8 - icvlen - bypass - hdrlen,LAST,LASTHASH */
+            *tp++=0x0f020000 | ((-8u+packetsize-ivlen-icvlen-bypass-hdrlen)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* DIR      CRYPTHASH,packetsize - ivlen - 8 - icvlen - bypass - hdrlen,LAST */
+            *tp++=0x0f000000 | ((-8u+packetsize-ivlen-icvlen-bypass-hdrlen)&0x1ffffu)<<0;
+            /* INS      HASHONLY,PAD_ZERO,0,hashpad,LASTHASH */
+            *tp++=0x22020000 | ((0u)&0x1u)<<16 | ((hashpad)&0xffffu)<<0;
+        }
+        /* RETR     NONE,ORIG_HASH,icvlen,LASTHASHPKT */
+        *tp++=0x40e60000 | ((icvlen)&0x1ffffu)<<0;
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 4: /* esp_out_gcm */
+#if TKB_HAVE_PROTO_IPSEC == 1u
+        if (packetsize <= bypass+hdrlen)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for ESP outbound GCM\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        extseq = EVAL_extseq();
+        if (extseq == 0u)
+        {
+            /* INS      HASH,ORIG_SPI,8,LAST */
+            *tp++=0x2b900000 | ((8u)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* INS      HASH,ORIG_SPI,4 */
+            *tp++=0x23900000 | ((4u)&0x1ffffu)<<0;
+            /* INS      HASHONLY, ORIG_EXTSEQNUM_RES2, 4 */
+            *tp++=0x22480000 | ((4u)&0x1ffffu)<<0;
+            /* INS      HASH,ORIG_SEQNUM_RES, 4, LAST */
+            *tp++=0x2b980000 | ((4u)&0x1ffffu)<<0;
+        }
+        /* INS      OUT,ORIG_IV1,ivlen */
+        ivlen = EVAL_ivlen();
+        *tp++=0x21a80000 | ((ivlen)&0x1ffffu)<<0;
+        /* REMRES   bypass+ohdrlen+8+ivlen, 16 */
+        ohdrlen = EVAL_ohdrlen();
+        *tp++=0xa0000000 | ((8u+bypass+ohdrlen+ivlen)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+        /* INS      CRYPT, PAD_ZERO, 0, 16 */
+        *tp++=0x25000000 | ((0u)&0x1u)<<16 | ((16u)&0xffffu)<<0;
+        /* DIR      CRYPTHASH, packetsize-bypass-hdrlen */
+        *tp++=0x07000000 | ((packetsize-bypass-hdrlen)&0x1ffffu)<<0;
+        /* INS      CRYPTHASH,PAD_IPSEC,nextheader,pad_bytes,LAST,LASTHASH */
+        nextheader = EVAL_nextheader();
+        pad_bytes = EVAL_pad_bytes();
+        *tp++=0x2f220000 | ((nextheader)&0xffu)<<9 | ((pad_bytes)&0x1ffu)<<0;
+        /* INS      OUT,ORIG_HASH,icvlen,LASTHASHPKT */
+        icvlen = EVAL_icvlen();
+        *tp++=0x21e60000 | ((icvlen)&0x1ffffu)<<0;
+        /* VERIFY   0  ; Causes any sequence number rollover error to fail the packet. */
+        *tp++=0xd0060000 | ((0u)&0x7fu)<<0;
+        /* CTX      ORIG_SEQNUM,seq_offset,1+extseq */
+        seq_offset = EVAL_seq_offset();
+        *tp++=0xe0560800 | ((seq_offset)&0xffu)<<0 | ((1u+extseq)&0xfu)<<24;
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 5: /* esp_in_gcm */
+#if TKB_HAVE_PROTO_IPSEC == 1u
+        ivlen = EVAL_ivlen();
+        icvlen = EVAL_icvlen();
+        pad_blocksize = EVAL_pad_blocksize();
+        if (packetsize < 8u+ivlen+icvlen+pad_blocksize+bypass+hdrlen)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for ESP inbound GCM\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        pad_remainder = EVAL_pad_remainder();
+        if (pad_remainder != 0u)
+        {
+            LOG_WARN("TokenBuilder: bad packet, pad alignment ESP inbound GCM\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        extseq = EVAL_extseq();
+        if (extseq != 1u)
+        {
+            /* RETR     HASHONLY,ORIG_SPI,8,LAST */
+            *tp++=0x4a900000 | ((8u)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* RETR     HASHONLY,ORIG_SPI,4 */
+            *tp++=0x42900000 | ((4u)&0x1ffffu)<<0;
+            /* RETR     NONE,ORIG_SEQNUM_RES,4 */
+            *tp++=0x40980000 | ((4u)&0x1ffffu)<<0;
+            /* INS      HASHONLY,ORIG_EXTSEQNUM_RES2, 4 */
+            *tp++=0x22480000 | ((4u)&0x1ffffu)<<0;
+            /* INS      HASHONLY,ORIG_SEQNUM_RES,4,LAST */
+            *tp++=0x2a980000 | ((4u)&0x1ffffu)<<0;
+        }
+        /* RETR     NONE,ORIG_IV1,ivlen */
+        *tp++=0x40a80000 | ((ivlen)&0x1ffffu)<<0;
+        /* REMRES   bypass+ohdrlen, 16 */
+        ohdrlen = EVAL_ohdrlen();
+        *tp++=0xa0000000 | ((bypass+ohdrlen)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+#if TKB_HAVE_ECN_FIXUP == 1u
+        /* DATA32 ecn_fixup_instr */
+        ecn_fixup_instr = EVAL_ecn_fixup_instr();
+        *tp++=0x00000000 | ((ecn_fixup_instr)&0xffffffffu)<<0;
+#endif
+        /* INS      CRYPT, PAD_ZERO, 0, 16 */
+        *tp++=0x25000000 | ((0u)&0x1u)<<16 | ((16u)&0xffffu)<<0;
+        /* DIR      CRYPTHASH,packetsize - ivlen - 8 - icvlen - bypass - hdrlen,LAST,LASTHASH */
+        *tp++=0x0f020000 | ((-8u+packetsize-ivlen-icvlen-bypass-hdrlen)&0x1ffffu)<<0;
+        /* RETR     NONE,ORIG_HASH,icvlen,LASTHASHPKT */
+        *tp++=0x40e60000 | ((icvlen)&0x1ffffu)<<0;
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 6: /* esp_out_gmac */
+#if TKB_HAVE_PROTO_IPSEC == 1u
+        if (packetsize <= bypass+hdrlen)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for ESP outbound GMAC\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        extseq = EVAL_extseq();
+        if (extseq == 0u)
+        {
+            /* INS      HASH,ORIG_SPI,8 */
+            *tp++=0x23900000 | ((8u)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* INS      HASH,ORIG_SPI,4 */
+            *tp++=0x23900000 | ((4u)&0x1ffffu)<<0;
+            /* INS      HASHONLY, ORIG_EXTSEQNUM_RES2, 4 */
+            *tp++=0x22480000 | ((4u)&0x1ffffu)<<0;
+            /* INS      HASH,ORIG_SEQNUM_RES, 4 */
+            *tp++=0x23980000 | ((4u)&0x1ffffu)<<0;
+        }
+        /* INS      HASH,ORIG_IV1,ivlen */
+        ivlen = EVAL_ivlen();
+        *tp++=0x23a80000 | ((ivlen)&0x1ffffu)<<0;
+        /* REMRES   bypass+ohdrlen+8+ivlen, 16 */
+        ohdrlen = EVAL_ohdrlen();
+        *tp++=0xa0000000 | ((8u+bypass+ohdrlen+ivlen)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+        /* INS      CRYPT, PAD_ZERO, 0, 16 */
+        *tp++=0x25000000 | ((0u)&0x1u)<<16 | ((16u)&0xffffu)<<0;
+        /* DIR      HASH, packetsize-bypass-hdrlen */
+        *tp++=0x03000000 | ((packetsize-bypass-hdrlen)&0x1ffffu)<<0;
+        /* INS      HASH,PAD_IPSEC,nextheader,pad_bytes,LAST,LASTHASH */
+        nextheader = EVAL_nextheader();
+        pad_bytes = EVAL_pad_bytes();
+        *tp++=0x2b220000 | ((nextheader)&0xffu)<<9 | ((pad_bytes)&0x1ffu)<<0;
+        /* INS      OUT,ORIG_HASH,icvlen,LASTHASHPKT */
+        icvlen = EVAL_icvlen();
+        *tp++=0x21e60000 | ((icvlen)&0x1ffffu)<<0;
+        /* VERIFY   0  ; Causes any sequence number rollover error to fail the packet. */
+        *tp++=0xd0060000 | ((0u)&0x7fu)<<0;
+        /* CTX      ORIG_SEQNUM,seq_offset,1+extseq */
+        seq_offset = EVAL_seq_offset();
+        *tp++=0xe0560800 | ((seq_offset)&0xffu)<<0 | ((1u+extseq)&0xfu)<<24;
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 7: /* esp_in_gmac */
+#if TKB_HAVE_PROTO_IPSEC == 1u
+        ivlen = EVAL_ivlen();
+        icvlen = EVAL_icvlen();
+        pad_blocksize = EVAL_pad_blocksize();
+        if (packetsize < 8u+ivlen+icvlen+pad_blocksize+bypass+hdrlen)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for ESP inbound GMAC\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        pad_remainder = EVAL_pad_remainder();
+        if (pad_remainder != 0u)
+        {
+            LOG_WARN("TokenBuilder: bad packet, pad alignment ESP inbound GMAC\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        extseq = EVAL_extseq();
+        if (extseq != 1u)
+        {
+            /* RETR     HASHONLY,ORIG_SPI,8 */
+            *tp++=0x42900000 | ((8u)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* RETR     HASHONLY,ORIG_SPI,4 */
+            *tp++=0x42900000 | ((4u)&0x1ffffu)<<0;
+            /* RETR     NONE,ORIG_SEQNUM_RES,4 */
+            *tp++=0x40980000 | ((4u)&0x1ffffu)<<0;
+            /* INS      HASHONLY,ORIG_EXTSEQNUM_RES2, 4 */
+            *tp++=0x22480000 | ((4u)&0x1ffffu)<<0;
+            /* INS      HASHONLY,ORIG_SEQNUM_RES,4 */
+            *tp++=0x22980000 | ((4u)&0x1ffffu)<<0;
+        }
+        /* RETR     HASHONLY,ORIG_IV1,ivlen */
+        *tp++=0x42a80000 | ((ivlen)&0x1ffffu)<<0;
+        /* REMRES   bypass+ohdrlen, 16 */
+        ohdrlen = EVAL_ohdrlen();
+        *tp++=0xa0000000 | ((bypass+ohdrlen)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+#if TKB_HAVE_ECN_FIXUP == 1u
+        /* DATA32 ecn_fixup_instr */
+        ecn_fixup_instr = EVAL_ecn_fixup_instr();
+        *tp++=0x00000000 | ((ecn_fixup_instr)&0xffffffffu)<<0;
+#endif
+        /* INS      CRYPT, PAD_ZERO, 0, 16 */
+        *tp++=0x25000000 | ((0u)&0x1u)<<16 | ((16u)&0xffffu)<<0;
+        /* DIR      HASH,packetsize - ivlen - 8 - icvlen - bypass - hdrlen,LAST,LASTHASH */
+        *tp++=0x0b020000 | ((-8u+packetsize-ivlen-icvlen-bypass-hdrlen)&0x1ffffu)<<0;
+        /* RETR     NONE,ORIG_HASH,icvlen,LASTHASHPKT */
+        *tp++=0x40e60000 | ((icvlen)&0x1ffffu)<<0;
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 8: /* ssltls_out */
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+        if (packetsize < bypass+hdrlen)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for SSLTLS outbound\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        capwap_out = EVAL_capwap_out();
+        if (capwap_out != 0u)
+        {
+            /* INS OUT,ORIG_TOKEN,4 */
+            *tp++=0x21d80000 | ((4u)&0x1ffffu)<<0;
+            /* DATA32 0x0000001  ; Insert DTLS/CAPWAP header. */
+            *tp++=0x00000000 | ((1u)&0xffffffffu)<<0;
+        }
+        /* INS HASHONLY,ORIG_EXTSEQNUM,4 */
+        *tp++=0x22580000 | ((4u)&0x1ffffu)<<0;
+        /* INS HASHONLY,ORIG_SEQNUM,4 */
+        *tp++=0x22500000 | ((4u)&0x1ffffu)<<0;
+        /* INS HASH,PAD_CONST,nextheader,1 ; Type field */
+        nextheader = EVAL_nextheader();
+        *tp++=0x23100000 | ((nextheader)&0xffu)<<9 | ((1u)&0x1ffu)<<0;
+        antireplay = EVAL_antireplay();
+        if (antireplay != 0u)
+        {
+            /* INS HASH,ORIG_SPI,2          ; For TLS/DTLS, hash version field. */
+            *tp++=0x23900000 | ((2u)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* INS OUT,ORIG_SPI,2           ; For SSL, do not hash version field. */
+            *tp++=0x21900000 | ((2u)&0x1ffffu)<<0;
+        }
+        extseq = EVAL_extseq();
+        if (extseq != 0u)
+        {
+            /* INS OUT,ORIG_EXTSEQNUM,4 */
+            *tp++=0x21580000 | ((4u)&0x1ffffu)<<0;
+            /* INS OUT,ORIG_SEQNUM,4 */
+            *tp++=0x21500000 | ((4u)&0x1ffffu)<<0;
+        }
+        /* INS HASHONLY,ORIG_TOKEN,2 */
+        *tp++=0x22d80000 | ((2u)&0x1ffffu)<<0;
+        /* DATA32 swaplen                   ; Payload length to hash. */
+        swaplen = EVAL_swaplen();
+        *tp++=0x00000000 | ((swaplen)&0xffffffffu)<<0;
+        /* INS OUT,ORIG_TOKEN,2 */
+        *tp++=0x21d80000 | ((2u)&0x1ffffu)<<0;
+        /* DATA32 swap_fraglen              ; Fragment length to output. */
+        swap_fraglen = EVAL_swap_fraglen();
+        *tp++=0x00000000 | ((swap_fraglen)&0xffffffffu)<<0;
+        /* INS OUT,ORIG_IV0,ivlen */
+        ivlen = EVAL_ivlen();
+        *tp++=0x21a00000 | ((ivlen)&0x1ffffu)<<0;
+        if (packetsize != bypass+hdrlen)
+        {
+            /* DIR CRYPTHASH, packetsize-bypass-hdrlen,LASTHASH */
+            *tp++=0x07020000 | ((packetsize-bypass-hdrlen)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* INS CRYPTHASH, PAD_ZERO, 0, 0, LASTHASH */
+            *tp++=0x27020000 | ((0u)&0x1u)<<16 | ((0u)&0xffffu)<<0;
+        }
+        upd_handling = EVAL_upd_handling();
+        switch(upd_handling)
+        {
+        case 0: /* upd_null */
+            /* INS CRYPT,ORIG_HASH,icvlen,LAST,LASTHASHPKT */
+            icvlen = EVAL_icvlen();
+            *tp++=0x2de60000 | ((icvlen)&0x1ffffu)<<0;
+            /* VERIFY   0  ; Causes any sequence number rollover error to fail the packet. */
+            *tp++=0xd0060000 | ((0u)&0x7fu)<<0;
+            /* CTX ORIG_SEQNUM,seq_offset,2 */
+            seq_offset = EVAL_seq_offset();
+            *tp++=0xe0560800 | ((seq_offset)&0xffu)<<0 | ((2u)&0xfu)<<24;
+            break;
+        case 1: /* upd_arc4 */
+            /* INS CRYPT,ORIG_HASH,icvlen,LAST,LASTHASHPKT */
+            icvlen = EVAL_icvlen();
+            *tp++=0x2de60000 | ((icvlen)&0x1ffffu)<<0;
+            /* CTX ORIG_SEQNUM,seq_offset,2 */
+            seq_offset = EVAL_seq_offset();
+            *tp++=0xe0560800 | ((seq_offset)&0xffu)<<0 | ((2u)&0xfu)<<24;
+            /* CTX ORIG_CHKSUM,iv_offset,1,P ; Update IJ pointer */
+            iv_offset = EVAL_iv_offset();
+            *tp++=0xe0ce1800 | ((iv_offset)&0xffu)<<0 | ((1u)&0xfu)<<24;
+            /* CTX ORIG_CHKSUM_STORE,0,1,P   ; Update ARC4 state. */
+            *tp++=0xe0d61800 | ((0u)&0xffu)<<0 | ((1u)&0xfu)<<24;
+            break;
+        case 2: /* upd_iv2 */
+            /* INS CRYPT,ORIG_HASH,icvlen,LASTHASH */
+            icvlen = EVAL_icvlen();
+            *tp++=0x25e20000 | ((icvlen)&0x1ffffu)<<0;
+            if (antireplay != 0u)
+            {
+                /* INS CRYPT,PAD_TLS,0,pad_bytes,LAST,LASTHASHPKT */
+                pad_bytes = EVAL_pad_bytes();
+                *tp++=0x2d2e0000 | ((0u)&0xffu)<<9 | ((pad_bytes)&0x1ffu)<<0;
+            }
+            else
+            {
+                /* INS CRYPT,PAD_SSL,0,pad_bytes,LAST,LASTHASHPKT */
+                pad_bytes = EVAL_pad_bytes();
+                *tp++=0x2d360000 | ((0u)&0xffu)<<9 | ((pad_bytes)&0x1ffu)<<0;
+            }
+            /* CTX ORIG_SEQNUM,seq_offset,2 */
+            seq_offset = EVAL_seq_offset();
+            *tp++=0xe0560800 | ((seq_offset)&0xffu)<<0 | ((2u)&0xfu)<<24;
+            /* CTX ORIG_IV0,iv_offset,2,P */
+            iv_offset = EVAL_iv_offset();
+            *tp++=0xe0a61800 | ((iv_offset)&0xffu)<<0 | ((2u)&0xfu)<<24;
+            break;
+        case 3: /* upd_iv4 */
+            /* INS CRYPT,ORIG_HASH,icvlen,LASTHASH */
+            icvlen = EVAL_icvlen();
+            *tp++=0x25e20000 | ((icvlen)&0x1ffffu)<<0;
+            if (antireplay != 0u)
+            {
+                /* INS CRYPT,PAD_TLS,0,pad_bytes,LAST,LASTHASHPKT */
+                pad_bytes = EVAL_pad_bytes();
+                *tp++=0x2d2e0000 | ((0u)&0xffu)<<9 | ((pad_bytes)&0x1ffu)<<0;
+            }
+            else
+            {
+                /* INS CRYPT,PAD_SSL,0,pad_bytes,LAST,LASTHASHPKT */
+                pad_bytes = EVAL_pad_bytes();
+                *tp++=0x2d360000 | ((0u)&0xffu)<<9 | ((pad_bytes)&0x1ffu)<<0;
+            }
+            /* CTX ORIG_SEQNUM,seq_offset,2 */
+            seq_offset = EVAL_seq_offset();
+            *tp++=0xe0560800 | ((seq_offset)&0xffu)<<0 | ((2u)&0xfu)<<24;
+            /* CTX ORIG_IV0,iv_offset,4,P */
+            iv_offset = EVAL_iv_offset();
+            *tp++=0xe0a61800 | ((iv_offset)&0xffu)<<0 | ((4u)&0xfu)<<24;
+            break;
+        case 4: /* upd_blk */
+            /* INS CRYPT,ORIG_HASH,icvlen,LASTHASH */
+            icvlen = EVAL_icvlen();
+            *tp++=0x25e20000 | ((icvlen)&0x1ffffu)<<0;
+            /* INS CRYPT,PAD_TLS,0,pad_bytes,LAST,LASTHASHPKT */
+            pad_bytes = EVAL_pad_bytes();
+            *tp++=0x2d2e0000 | ((0u)&0xffu)<<9 | ((pad_bytes)&0x1ffu)<<0;
+            /* VERIFY   0  ; Causes any sequence number rollover error to fail the packet. */
+            *tp++=0xd0060000 | ((0u)&0x7fu)<<0;
+            /* CTX ORIG_SEQNUM,seq_offset,2 */
+            seq_offset = EVAL_seq_offset();
+            *tp++=0xe0560800 | ((seq_offset)&0xffu)<<0 | ((2u)&0xfu)<<24;
+            break;
+        }
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 9: /* ssltls_in */
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+        paylen = EVAL_paylen();
+        if (paylen == 4294967295u)
+        {
+            LOG_WARN("TokenBuilder: bad packet, payload size for SSLTLS inbound\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        upd_handling = EVAL_upd_handling();
+        if (upd_handling <= 1u)
+        {
+            if (bypass > 0u)
+            {
+                /* DIR OUT,bypass */
+                *tp++=0x01000000 | ((bypass)&0x1ffffu)<<0;
+            }
+            if (hdrlen > 0u)
+            {
+                /* DIR OUT,hdrlen */
+                *tp++=0x01000000 | ((hdrlen)&0x1ffffu)<<0;
+            }
+            capwap_in = EVAL_capwap_in();
+            if (capwap_in != 0u)
+            {
+                /* REM 4  ; Remove DTLS/CAPWAP header. */
+                *tp++=0x40d80000 | ((4u)&0x1ffffu)<<0;
+            }
+            extseq = EVAL_extseq();
+            if (extseq != 0u)
+            {
+                ohdrlen = EVAL_ohdrlen();
+                if (ohdrlen > hdrlen)
+                {
+                    /* RETR OUT,ORIG_SPI,3    ; Extract Type and Version. */
+                    *tp++=0x41900000 | ((3u)&0x1ffffu)<<0;
+                    /* RETR HASHONLY,ORIG_EXTSEQNUM_RES2,4 ; Extract seq numbers from packet. */
+                    *tp++=0x42480000 | ((4u)&0x1ffffu)<<0;
+                    /* RETR HASHONLY,ORIG_SEQNUM_RES2,4 */
+                    *tp++=0x42400000 | ((4u)&0x1ffffu)<<0;
+                    /* INS HASHONLY,ORIG_SPI_RES,3  ; Hash type and version. */
+                    *tp++=0x22c00000 | ((3u)&0x1ffffu)<<0;
+                    /* INS HASH,ORIG_TOKEN,2 */
+                    *tp++=0x23d80000 | ((2u)&0x1ffffu)<<0;
+                    /* DATA32 swaplen */
+                    swaplen = EVAL_swaplen();
+                    *tp++=0x00000000 | ((swaplen)&0xffffffffu)<<0;
+                    if (ohdrlen-hdrlen > 5u)
+                    {
+                        /* INS OUT,PAD_ZERO,0,ohdrlen-hdrlen-5 */
+                        *tp++=0x21000000 | ((0u)&0x1u)<<16 | ((-5u+ohdrlen-hdrlen)&0xffffu)<<0;
+                    }
+                }
+                else
+                {
+                    /* RETR NONE,ORIG_SPI,3    ; Extract Type and Version. */
+                    *tp++=0x40900000 | ((3u)&0x1ffffu)<<0;
+                    /* RETR HASHONLY,ORIG_EXTSEQNUM_RES2,4 ; Extract seq numbers from packet. */
+                    *tp++=0x42480000 | ((4u)&0x1ffffu)<<0;
+                    /* RETR HASHONLY,ORIG_SEQNUM_RES2,4 */
+                    *tp++=0x42400000 | ((4u)&0x1ffffu)<<0;
+                    /* INS HASHONLY,ORIG_SPI_RES,3  ; Hash type and version. */
+                    *tp++=0x22c00000 | ((3u)&0x1ffffu)<<0;
+                    /* INS HASHONLY,ORIG_TOKEN,2 */
+                    *tp++=0x22d80000 | ((2u)&0x1ffffu)<<0;
+                    /* DATA32 swaplen */
+                    swaplen = EVAL_swaplen();
+                    *tp++=0x00000000 | ((swaplen)&0xffffffffu)<<0;
+                }
+            }
+            else
+            {
+                /* INS HASHONLY,ORIG_EXTSEQNUM,4  ; Extract from SA. */
+                *tp++=0x22580000 | ((4u)&0x1ffffu)<<0;
+                /* INS HASHONLY,ORIG_SEQNUM,4 */
+                *tp++=0x22500000 | ((4u)&0x1ffffu)<<0;
+                antireplay = EVAL_antireplay();
+                if (antireplay != 0u)
+                {
+                    /* DIR HASHONLY,3       ; Hash type and version number */
+                    *tp++=0x02000000 | ((3u)&0x1ffffu)<<0;
+                }
+                else
+                {
+                    /* DIR HASHONLY,1       ; Hash type only for SSL */
+                    *tp++=0x02000000 | ((1u)&0x1ffffu)<<0;
+                    /* REM 2 */
+                    *tp++=0x40d80000 | ((2u)&0x1ffffu)<<0;
+                }
+                /* INS HASHONLY,ORIG_TOKEN,2 */
+                *tp++=0x22d80000 | ((2u)&0x1ffffu)<<0;
+                /* DATA32 swaplen */
+                swaplen = EVAL_swaplen();
+                *tp++=0x00000000 | ((swaplen)&0xffffffffu)<<0;
+            }
+            /* REM 2                              ; Remove fragment length. */
+            *tp++=0x40d80000 | ((2u)&0x1ffffu)<<0;
+            /* REMRES bypass+ohdrlen+paylen,icvlen          ; Cause the MAC to be removed */
+            ohdrlen = EVAL_ohdrlen();
+            icvlen = EVAL_icvlen();
+            *tp++=0xa0000000 | ((bypass+ohdrlen+paylen)&0xffffu)<<0 | ((icvlen)&0x3fu)<<19;
+            /* DIR CRYPTHASH,paylen,LASTHASH */
+            *tp++=0x07020000 | ((paylen)&0x1ffffu)<<0;
+            switch(upd_handling)
+            {
+            case 0: /* upd_null */
+                /* DIR CRYPT,icvlen,LAST,LASTHASHPKT */
+                *tp++=0x0d060000 | ((icvlen)&0x1ffffu)<<0;
+                if (extseq == 0u)
+                {
+                    /* VERIFY icvlen,H */
+                    *tp++=0xd0070000 | ((icvlen)&0x7fu)<<0;
+                    /* CTX ORIG_SEQNUM,seq_offset,2,P */
+                    seq_offset = EVAL_seq_offset();
+                    *tp++=0xe0561800 | ((seq_offset)&0xffu)<<0 | ((2u)&0xfu)<<24;
+                }
+                else if (extseq == 1u)
+                {
+                    /* VERIFY icvlen,H */
+                    *tp++=0xd0070000 | ((icvlen)&0x7fu)<<0;
+                }
+                else
+                {
+                    /* VERIFY icvlen,S,H */
+                    *tp++=0xd8070000 | ((icvlen)&0x7fu)<<0;
+                    /* CTX ORIG_SEQNUM,seq_offset,1+extseq,P */
+                    seq_offset = EVAL_seq_offset();
+                    *tp++=0xe0561800 | ((seq_offset)&0xffu)<<0 | ((1u+extseq)&0xfu)<<24;
+                }
+                break;
+            case 1: /* upd_arc4 */
+                /* DIR CRYPT,icvlen,LAST,LASTHASHPKT */
+                *tp++=0x0d060000 | ((icvlen)&0x1ffffu)<<0;
+                /* VERIFY icvlen,H */
+                *tp++=0xd0070000 | ((icvlen)&0x7fu)<<0;
+                /* CTX ORIG_SEQNUM,seq_offset,2,P */
+                seq_offset = EVAL_seq_offset();
+                *tp++=0xe0561800 | ((seq_offset)&0xffu)<<0 | ((2u)&0xfu)<<24;
+                /* CTX ORIG_CHKSUM,iv_offset,1,P ; Update IJ pointer */
+                iv_offset = EVAL_iv_offset();
+                *tp++=0xe0ce1800 | ((iv_offset)&0xffu)<<0 | ((1u)&0xfu)<<24;
+                /* CTX ORIG_CHKSUM_STORE,0,1,P   ; Update ARC4 state. */
+                *tp++=0xe0d61800 | ((0u)&0xffu)<<0 | ((1u)&0xfu)<<24;
+                break;
+            }
+        }
+        else
+        {
+            /* REMRES 0,4,NOUPDCHK */
+            *tp++=0xa0020000 | ((0u)&0xffffu)<<0 | ((4u)&0x3fu)<<19;
+            cipher_is_aes = EVAL_cipher_is_aes();
+            if (cipher_is_aes == 0u)
+            {
+                /* INS CRYPTONLY,ORIG_TOKEN,12 */
+                *tp++=0x24d80000 | ((12u)&0x1ffffu)<<0;
+                ssltls_lastblock = EVAL_ssltls_lastblock();
+                TokenBuilder_CopyBytes(tp, ssltls_lastblock, 12);
+                tp += 3;
+                /* INS CRYPT,ORIG_TOKEN,4 */
+                *tp++=0x25d80000 | ((4u)&0x1ffffu)<<0;
+                ssltls_lastword = EVAL_ssltls_lastword();
+                TokenBuilder_CopyBytes(tp, ssltls_lastword, 4);
+                tp += 1;
+            }
+            else
+            {
+                /* INS CRYPTONLY,ORIG_TOKEN,28 */
+                *tp++=0x24d80000 | ((28u)&0x1ffffu)<<0;
+                ssltls_lastblock = EVAL_ssltls_lastblock();
+                TokenBuilder_CopyBytes(tp, ssltls_lastblock, 28);
+                tp += 7;
+                /* INS CRYPT,ORIG_TOKEN,4 */
+                *tp++=0x25d80000 | ((4u)&0x1ffffu)<<0;
+                ssltls_lastword = EVAL_ssltls_lastword();
+                TokenBuilder_CopyBytes(tp, ssltls_lastword, 4);
+                tp += 1;
+            }
+            /* DIR NONE,0,LAST */
+            *tp++=0x08000000 | ((0u)&0x1ffffu)<<0;
+            if (bypass+hdrlen > 0u)
+            {
+                /* DIR OUT,bypass+hdrlen */
+                *tp++=0x01000000 | ((bypass+hdrlen)&0x1ffffu)<<0;
+            }
+            capwap_in = EVAL_capwap_in();
+            if (capwap_in != 0u)
+            {
+                /* REM 4  ; Remove DTLS/CAPWAP header. */
+                *tp++=0x40d80000 | ((4u)&0x1ffffu)<<0;
+            }
+            extseq = EVAL_extseq();
+            if (extseq != 0u)
+            {
+                ohdrlen = EVAL_ohdrlen();
+                if (ohdrlen > hdrlen)
+                {
+                    /* RETR OUT,ORIG_SPI,3    ; Extract Type and Version. */
+                    *tp++=0x41900000 | ((3u)&0x1ffffu)<<0;
+                    /* RETR HASHONLY,ORIG_EXTSEQNUM_RES2,4 ; Extract seq numbers from packet. */
+                    *tp++=0x42480000 | ((4u)&0x1ffffu)<<0;
+                    /* RETR HASHONLY,ORIG_SEQNUM_RES2,4 */
+                    *tp++=0x42400000 | ((4u)&0x1ffffu)<<0;
+                    /* INS HASHONLY,ORIG_SPI_RES,3  ; Hash type and version. */
+                    *tp++=0x22c00000 | ((3u)&0x1ffffu)<<0;
+                    /* INS HASH,ORIG_LENCOR,paylen-1 */
+                    *tp++=0x23780000 | ((-1u+paylen)&0x1ffffu)<<0;
+                    if (ohdrlen-hdrlen > 5u)
+                    {
+                        /* INS OUT,PAD_ZERO,0,ohdrlen-hdrlen-5 */
+                        *tp++=0x21000000 | ((0u)&0x1u)<<16 | ((-5u+ohdrlen-hdrlen)&0xffffu)<<0;
+                    }
+                }
+                else
+                {
+                    /* RETR NONE,ORIG_SPI,3    ; Extract Type and Version. */
+                    *tp++=0x40900000 | ((3u)&0x1ffffu)<<0;
+                    /* RETR HASHONLY,ORIG_EXTSEQNUM_RES2,4 ; Extract seq numbers from packet. */
+                    *tp++=0x42480000 | ((4u)&0x1ffffu)<<0;
+                    /* RETR HASHONLY,ORIG_SEQNUM_RES2,4 */
+                    *tp++=0x42400000 | ((4u)&0x1ffffu)<<0;
+                    /* INS HASHONLY,ORIG_SPI_RES,3  ; Hash type and version. */
+                    *tp++=0x22c00000 | ((3u)&0x1ffffu)<<0;
+                    /* INS HASHONLY,ORIG_LENCOR,paylen-1 */
+                    *tp++=0x22780000 | ((-1u+paylen)&0x1ffffu)<<0;
+                }
+            }
+            else
+            {
+                /* RETR NONE,ORIG_SPI,3    ; Extract Type and Version. */
+                *tp++=0x40900000 | ((3u)&0x1ffffu)<<0;
+                /* INS HASHONLY,ORIG_EXTSEQNUM,4  ; Extract from SA. */
+                *tp++=0x22580000 | ((4u)&0x1ffffu)<<0;
+                /* INS HASHONLY,ORIG_SEQNUM,4 */
+                *tp++=0x22500000 | ((4u)&0x1ffffu)<<0;
+                antireplay = EVAL_antireplay();
+                if (antireplay != 0u)
+                {
+                    /* INS HASHONLY,ORIG_SPI_RES,3       ; Hash type and version number */
+                    *tp++=0x22c00000 | ((3u)&0x1ffffu)<<0;
+                }
+                else
+                {
+                    /* INS HASHONLY,ORIG_SPI_RES,1       ; Hash type only. */
+                    *tp++=0x22c00000 | ((1u)&0x1ffffu)<<0;
+                }
+                /* INS HASHONLY,ORIG_LENCOR,paylen-1 */
+                *tp++=0x22780000 | ((-1u+paylen)&0x1ffffu)<<0;
+            }
+            /* REM 2                              ; Remove fragment length. */
+            *tp++=0x40d80000 | ((2u)&0x1ffffu)<<0;
+            ivlen = EVAL_ivlen();
+            if (ivlen > 0u)
+            {
+                /* RETR NONE,ORIG_IV0,ivlen */
+                *tp++=0x40a00000 | ((ivlen)&0x1ffffu)<<0;
+            }
+            /* REMRES bypass+ohdrlen,icvlen,NOUPDCHK          ; Cause the MAC to be removed */
+            ohdrlen = EVAL_ohdrlen();
+            icvlen = EVAL_icvlen();
+            *tp++=0xa0020000 | ((bypass+ohdrlen)&0xffffu)<<0 | ((icvlen)&0x3fu)<<19;
+            /* DIRX CRYPTHASH,ORIG_LENCOR,0,LASTHASH */
+            *tp++=0x077a0000 | ((0u)&0x1ffffu)<<0;
+            /* DIRX CRYPT,ORIG_LENCOR,icvlen+1,LAST,LASTHASHPKT */
+            *tp++=0x0d7e0000 | ((1u+icvlen)&0x1ffffu)<<0;
+            switch(upd_handling)
+            {
+            case 2: /* upd_iv2 */
+                antireplay = EVAL_antireplay();
+                if (antireplay != 0u)
+                {
+                    /* VERIFY icvlen,P,H */
+                    *tp++=0xd1070000 | ((icvlen)&0x7fu)<<0;
+                }
+                else
+                {
+                    /* VERIFY icvlen,H */
+                    *tp++=0xd0070000 | ((icvlen)&0x7fu)<<0;
+                }
+                /* CTX ORIG_SEQNUM,seq_offset,2,P */
+                seq_offset = EVAL_seq_offset();
+                *tp++=0xe0561800 | ((seq_offset)&0xffu)<<0 | ((2u)&0xfu)<<24;
+                /* CTX ORIG_IV0,iv_offset,2,P */
+                iv_offset = EVAL_iv_offset();
+                *tp++=0xe0a61800 | ((iv_offset)&0xffu)<<0 | ((2u)&0xfu)<<24;
+                break;
+            case 3: /* upd_iv4 */
+                antireplay = EVAL_antireplay();
+                if (antireplay != 0u)
+                {
+                    /* VERIFY icvlen,P,H */
+                    *tp++=0xd1070000 | ((icvlen)&0x7fu)<<0;
+                }
+                else
+                {
+                    /* VERIFY icvlen,H */
+                    *tp++=0xd0070000 | ((icvlen)&0x7fu)<<0;
+                }
+                /* CTX ORIG_SEQNUM,seq_offset,2,P */
+                seq_offset = EVAL_seq_offset();
+                *tp++=0xe0561800 | ((seq_offset)&0xffu)<<0 | ((2u)&0xfu)<<24;
+                /* CTX ORIG_IV0,iv_offset,4,P */
+                iv_offset = EVAL_iv_offset();
+                *tp++=0xe0a61800 | ((iv_offset)&0xffu)<<0 | ((4u)&0xfu)<<24;
+                break;
+            case 4: /* upd_blk */
+                if (extseq == 0u)
+                {
+                    /* VERIFY icvlen,P,H */
+                    *tp++=0xd1070000 | ((icvlen)&0x7fu)<<0;
+                    /* CTX ORIG_SEQNUM,seq_offset,2,P */
+                    seq_offset = EVAL_seq_offset();
+                    *tp++=0xe0561800 | ((seq_offset)&0xffu)<<0 | ((2u)&0xfu)<<24;
+                }
+                else if (extseq == 1u)
+                {
+                    /* VERIFY icvlen,P,H */
+                    *tp++=0xd1070000 | ((icvlen)&0x7fu)<<0;
+                }
+                else
+                {
+                    /* VERIFY icvlen,P,S,H */
+                    *tp++=0xd9070000 | ((icvlen)&0x7fu)<<0;
+                    /* CTX ORIG_SEQNUM,seq_offset,1+extseq,P */
+                    seq_offset = EVAL_seq_offset();
+                    *tp++=0xe0561800 | ((seq_offset)&0xffu)<<0 | ((1u+extseq)&0xfu)<<24;
+                }
+                break;
+            }
+        }
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 21: /* ssltls_gcm_out */
+    case 37: /* ssltls_chachapoly_out */
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+        if (packetsize < bypass+hdrlen)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for SSLTLS outbound GCM or ChaChaPoly\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        capwap_out = EVAL_capwap_out();
+        if (capwap_out != 0u)
+        {
+            /* INS OUT,ORIG_TOKEN,4 */
+            *tp++=0x21d80000 | ((4u)&0x1ffffu)<<0;
+            /* DATA32 0x0000001  ; Insert DTLS/CAPWAP header. */
+            *tp++=0x00000000 | ((1u)&0xffffffffu)<<0;
+        }
+        /* INS HASHONLY,ORIG_EXTSEQNUM,4 */
+        *tp++=0x22580000 | ((4u)&0x1ffffu)<<0;
+        /* INS HASHONLY,ORIG_SEQNUM,4 */
+        *tp++=0x22500000 | ((4u)&0x1ffffu)<<0;
+        /* INS HASH,PAD_CONST,nextheader,1 ; Type field */
+        nextheader = EVAL_nextheader();
+        *tp++=0x23100000 | ((nextheader)&0xffu)<<9 | ((1u)&0x1ffu)<<0;
+        /* INS HASH,ORIG_SPI,2          ; For TLS/DTLS, hash version field. */
+        *tp++=0x23900000 | ((2u)&0x1ffffu)<<0;
+        extseq = EVAL_extseq();
+        if (extseq != 0u)
+        {
+            /* INS OUT,ORIG_EXTSEQNUM,4 ; Output sequence number for DTLS */
+            *tp++=0x21580000 | ((4u)&0x1ffffu)<<0;
+            /* INS OUT,ORIG_SEQNUM,4 */
+            *tp++=0x21500000 | ((4u)&0x1ffffu)<<0;
+        }
+        /* INS HASHONLY,ORIG_TOKEN,2,LAST */
+        *tp++=0x2ad80000 | ((2u)&0x1ffffu)<<0;
+        /* DATA32 swaplen                   ; Payload length to hash. */
+        swaplen = EVAL_swaplen();
+        *tp++=0x00000000 | ((swaplen)&0xffffffffu)<<0;
+        /* INS OUT,ORIG_TOKEN,2 */
+        *tp++=0x21d80000 | ((2u)&0x1ffffu)<<0;
+        /* DATA32 swap_fraglen              ; Fragment length to output. */
+        swap_fraglen = EVAL_swap_fraglen();
+        *tp++=0x00000000 | ((swap_fraglen)&0xffffffffu)<<0;
+        /* INS OUT,ORIG_IV1,ivlen */
+        ivlen = EVAL_ivlen();
+        *tp++=0x21a80000 | ((ivlen)&0x1ffffu)<<0;
+        if (proto != 37u)
+        {
+            if (extseq != 0u)
+            {
+                /* REMRES bypass + hdrlen + capwap_out + 5 + 8 + 8, 16 */
+                *tp++=0xa0000000 | ((21u+bypass+hdrlen+capwap_out)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+            }
+            else
+            {
+                /* REMRES bypass + hdrlen + 5 + 8, 16 */
+                *tp++=0xa0000000 | ((13u+bypass+hdrlen)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+            }
+            /* INS CRYPT, PAD_ZERO, 0, 16 */
+            *tp++=0x25000000 | ((0u)&0x1u)<<16 | ((16u)&0xffffu)<<0;
+        }
+        if (packetsize != bypass+hdrlen)
+        {
+            /* DIR CRYPTHASH, packetsize-bypass-hdrlen,LAST,LASTHASH */
+            *tp++=0x0f020000 | ((packetsize-bypass-hdrlen)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* INS CRYPTHASH, PAD_ZERO, 0, 0, LAST, LASTHASH */
+            *tp++=0x2f020000 | ((0u)&0x1u)<<16 | ((0u)&0xffffu)<<0;
+        }
+        /* INS OUT,ORIG_HASH,icvlen,LASTHASHPKT */
+        icvlen = EVAL_icvlen();
+        *tp++=0x21e60000 | ((icvlen)&0x1ffffu)<<0;
+        /* VERIFY   0  ; Causes any sequence number rollover error to fail the packet. */
+        *tp++=0xd0060000 | ((0u)&0x7fu)<<0;
+        /* CTX ORIG_SEQNUM,seq_offset,2 */
+        seq_offset = EVAL_seq_offset();
+        *tp++=0xe0560800 | ((seq_offset)&0xffu)<<0 | ((2u)&0xfu)<<24;
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 22: /* ssltls_gcm_in */
+    case 38: /* ssltls_chachapoly_in */
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+        paylen = EVAL_paylen();
+        if (paylen == 4294967295u)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for SSLTLS inbound GCM or ChaChaPoly\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        if (hdrlen > 0u)
+        {
+            /* DIR OUT,hdrlen */
+            *tp++=0x01000000 | ((hdrlen)&0x1ffffu)<<0;
+        }
+        capwap_in = EVAL_capwap_in();
+        if (capwap_in != 0u)
+        {
+            /* REM 4  ; Remove DTLS/CAPWAP header. */
+            *tp++=0x40d80000 | ((4u)&0x1ffffu)<<0;
+        }
+        ohdrlen = EVAL_ohdrlen();
+        if (ohdrlen > hdrlen)
+        {
+            /* RETR OUT,ORIG_SPI,3    ; Extract Type and Version. */
+            *tp++=0x41900000 | ((3u)&0x1ffffu)<<0;
+            /* RETR HASHONLY,ORIG_EXTSEQNUM_RES2,4 ; Extract seq numbers from packet. */
+            *tp++=0x42480000 | ((4u)&0x1ffffu)<<0;
+            /* RETR HASHONLY,ORIG_SEQNUM_RES2,4 */
+            *tp++=0x42400000 | ((4u)&0x1ffffu)<<0;
+            /* REM 2                    ; Remove fragment length. */
+            *tp++=0x40d80000 | ((2u)&0x1ffffu)<<0;
+            /* RETR NONE,ORIG_IV1,ivlen */
+            ivlen = EVAL_ivlen();
+            *tp++=0x40a80000 | ((ivlen)&0x1ffffu)<<0;
+            /* INS HASHONLY,ORIG_SPI_RES,3  ; Hash type and version. */
+            *tp++=0x22c00000 | ((3u)&0x1ffffu)<<0;
+            /* INS HASH,ORIG_TOKEN,2,LAST */
+            *tp++=0x2bd80000 | ((2u)&0x1ffffu)<<0;
+            /* DATA32 swaplen */
+            swaplen = EVAL_swaplen();
+            *tp++=0x00000000 | ((swaplen)&0xffffffffu)<<0;
+            if (ohdrlen-hdrlen > 5u)
+            {
+                /* INS OUT,PAD_ZERO,0,ohdrlen-hdrlen-5 */
+                *tp++=0x21000000 | ((0u)&0x1u)<<16 | ((-5u+ohdrlen-hdrlen)&0xffffu)<<0;
+            }
+        }
+        else
+        {
+            /* RETR NONE,ORIG_SPI,3    ; Extract Type and Version. */
+            *tp++=0x40900000 | ((3u)&0x1ffffu)<<0;
+            extseq = EVAL_extseq();
+            if (extseq != 0u)
+            {
+                /* RETR HASHONLY,ORIG_EXTSEQNUM_RES2,4 ; Extract seq numbers from packet. */
+                *tp++=0x42480000 | ((4u)&0x1ffffu)<<0;
+                /* RETR HASHONLY,ORIG_SEQNUM_RES2,4 */
+                *tp++=0x42400000 | ((4u)&0x1ffffu)<<0;
+            }
+            else
+            {
+                /* INS HASHONLY,ORIG_EXTSEQNUM,4  ; Extract from SA. */
+                *tp++=0x22580000 | ((4u)&0x1ffffu)<<0;
+                /* INS HASHONLY,ORIG_SEQNUM,4 */
+                *tp++=0x22500000 | ((4u)&0x1ffffu)<<0;
+            }
+            /* REM 2                    ; Remove fragment length. */
+            *tp++=0x40d80000 | ((2u)&0x1ffffu)<<0;
+            /* RETR NONE,ORIG_IV1,ivlen */
+            ivlen = EVAL_ivlen();
+            *tp++=0x40a80000 | ((ivlen)&0x1ffffu)<<0;
+            /* INS HASHONLY,ORIG_SPI_RES,3  ; Hash type and version. */
+            *tp++=0x22c00000 | ((3u)&0x1ffffu)<<0;
+            /* INS HASHONLY,ORIG_TOKEN,2,LAST */
+            *tp++=0x2ad80000 | ((2u)&0x1ffffu)<<0;
+            /* DATA32 swaplen */
+            swaplen = EVAL_swaplen();
+            *tp++=0x00000000 | ((swaplen)&0xffffffffu)<<0;
+        }
+        if (proto != 38u)
+        {
+            /* REMRES bypass+ohdrlen, 16 */
+            *tp++=0xa0000000 | ((bypass+ohdrlen)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+            /* INS CRYPT, PAD_ZERO, 0, 16 */
+            *tp++=0x25000000 | ((0u)&0x1u)<<16 | ((16u)&0xffffu)<<0;
+        }
+        else
+        {
+#if TKB_HAVE_CHACHAPOLY_HW30 == 1u
+            /* INS NONE, PAD_ZERO, 0, 160 */
+            *tp++=0x20000000 | ((0u)&0x1u)<<16 | ((160u)&0xffffu)<<0;
+#else
+            /* INS NONE, PAD_ZERO, 0, 16 */
+            *tp++=0x20000000 | ((0u)&0x1u)<<16 | ((16u)&0xffffu)<<0;
+#endif
+        }
+        /* DIR CRYPTHASH, paylen,LAST,LASTHASH */
+        *tp++=0x0f020000 | ((paylen)&0x1ffffu)<<0;
+        /* RETR NONE,ORIG_HASH,icvlen,LASTHASHPKT */
+        icvlen = EVAL_icvlen();
+        *tp++=0x40e60000 | ((icvlen)&0x1ffffu)<<0;
+        extseq = EVAL_extseq();
+        if (extseq == 0u)
+        {
+            /* VERIFY icvlen,H */
+            *tp++=0xd0070000 | ((icvlen)&0x7fu)<<0;
+            /* CTX ORIG_SEQNUM,seq_offset,2,P */
+            seq_offset = EVAL_seq_offset();
+            *tp++=0xe0561800 | ((seq_offset)&0xffu)<<0 | ((2u)&0xfu)<<24;
+        }
+        else if (extseq == 1u)
+        {
+            /* VERIFY icvlen,H */
+            *tp++=0xd0070000 | ((icvlen)&0x7fu)<<0;
+        }
+        else
+        {
+            /* VERIFY icvlen,S,H */
+            *tp++=0xd8070000 | ((icvlen)&0x7fu)<<0;
+            /* CTX ORIG_SEQNUM,seq_offset,1+extseq,P */
+            seq_offset = EVAL_seq_offset();
+            *tp++=0xe0561800 | ((seq_offset)&0xffu)<<0 | ((1u+extseq)&0xfu)<<24;
+        }
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 10: /* basic_crypto */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        ivlen = EVAL_ivlen();
+        if (packetsize < ivlen+bypass)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for basic crypto\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        switch(ivhandling)
+        {
+        case 0: /* iv_inbound_ctr */
+            /* RETR NONE,ORIG_IV1,8 ; IV from input packet, CTR. */
+            *tp++=0x40a80000 | ((8u)&0x1ffffu)<<0;
+            break;
+        case 1: /* iv_inbound_cbc */
+            /* RETR NONE,ORIG_IV0,ivlen ; IV from input packet CBC */
+            *tp++=0x40a00000 | ((ivlen)&0x1ffffu)<<0;
+            break;
+        case 2: /* iv_outbound_ctr */
+            /* INS  OUT,ORIG_IV1,8 */
+            *tp++=0x21a80000 | ((8u)&0x1ffffu)<<0;
+            break;
+        case 5: /* iv_copy_ctr */
+            /* RETR OUT,ORIG_IV1,8 ; IV from input packet, CTR. */
+            *tp++=0x41a80000 | ((8u)&0x1ffffu)<<0;
+            break;
+        case 4: /* iv_copy_cbc */
+            /* RETR OUT,ORIG_IV0,ivlen ; IV from input packet CBC */
+            *tp++=0x41a00000 | ((ivlen)&0x1ffffu)<<0;
+            break;
+        case 6: /* iv_outbound_2words */
+        case 9: /* iv_copy_token_2words */
+            /* INS  OUT,ORIG_IV0,8 */
+            *tp++=0x21a00000 | ((8u)&0x1ffffu)<<0;
+            break;
+        case 7: /* iv_outbound_4words */
+        case 15: /* iv_copy_token_4words */
+            /* INS  OUT,ORIG_IV0,16 */
+            *tp++=0x21a00000 | ((16u)&0x1ffffu)<<0;
+            break;
+        }
+        /* DIR CRYPT,packetsize-ivlen-bypass */
+        *tp++=0x05000000 | ((packetsize-ivlen-bypass)&0x1ffffu)<<0;
+        /* INS CRYPT,PAD_ZERO,0,pad_bytes_basic,LAST,LASTHASHPKT */
+        pad_bytes_basic = EVAL_pad_bytes_basic();
+        *tp++=0x2d060000 | ((0u)&0x1u)<<16 | ((pad_bytes_basic)&0xffffu)<<0;
+        upd_handling = EVAL_upd_handling();
+        switch(upd_handling)
+        {
+        case 0: /* upd_null */
+            break;
+        case 1: /* upd_arc4 */
+            /* CTX ORIG_CHKSUM,iv_offset,1,P,F ; Update IJ pointer */
+            iv_offset = EVAL_iv_offset();
+            *tp++=0xe0ce3800 | ((iv_offset)&0xffu)<<0 | ((1u)&0xfu)<<24;
+            /* CTX ORIG_CHKSUM_STORE,0,1,P,F   ; Update ARC4 state. */
+            *tp++=0xe0d63800 | ((0u)&0xffu)<<0 | ((1u)&0xfu)<<24;
+            break;
+        case 2: /* upd_iv2 */
+            /* CTX ORIG_IV0,iv_offset,2,P,F */
+            iv_offset = EVAL_iv_offset();
+            *tp++=0xe0a63800 | ((iv_offset)&0xffu)<<0 | ((2u)&0xfu)<<24;
+            break;
+        case 3: /* upd_iv4 */
+            /* CTX ORIG_IV0,iv_offset,4,P,F */
+            iv_offset = EVAL_iv_offset();
+            *tp++=0xe0a63800 | ((iv_offset)&0xffu)<<0 | ((4u)&0xfu)<<24;
+            break;
+        }
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 11: /* basic_hash */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        antireplay = EVAL_antireplay();
+        if (packetsize < bypass+antireplay)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for basic hash\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        aadlen_tkn = EVAL_aadlen_tkn();
+        if (aadlen_tkn > 0u)
+        {
+            extseq = EVAL_extseq();
+            if (extseq > 0u)
+            {
+                /* INS HASH,ORIG_TOKEN,aadlen_tkn */
+                *tp++=0x23d80000 | ((aadlen_tkn)&0x1ffffu)<<0;
+            }
+            else
+            {
+                /* INS HASHONLY,ORIG_TOKEN,aadlen_tkn */
+                *tp++=0x22d80000 | ((aadlen_tkn)&0x1ffffu)<<0;
+            }
+            aad = EVAL_aad();
+            if (aadlen_tkn > 64)
+            {
+                LOG_CRIT("Field too large\n");
+                return TKB_BAD_FIELD_SIZE;
+            }
+            TokenBuilder_CopyBytes(tp, aad, aadlen_tkn);
+            tp += (aadlen_tkn + 3)/4;
+        }
+        extseq = EVAL_extseq();
+        if (extseq > 0u)
+        {
+            /* DIR HASH,packetsize-bypass-antireplay,LASTHASH */
+            *tp++=0x03020000 | ((packetsize-bypass-antireplay)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* DIR HASHONLY,packetsize-bypass-antireplay,LASTHASH */
+            *tp++=0x02020000 | ((packetsize-bypass-antireplay)&0x1ffffu)<<0;
+        }
+        appendhash = EVAL_appendhash();
+        if (antireplay > 0u)
+        {
+            /* RETR NONE,ORIG_HASH,antireplay,LASTHASHPKT */
+            *tp++=0x40e60000 | ((antireplay)&0x1ffffu)<<0;
+            /* VERIFY antireplay,H */
+            *tp++=0xd0070000 | ((antireplay)&0x7fu)<<0;
+        }
+        else if (appendhash > 0u)
+        {
+            /* INS OUT,ORIG_HASH,icvlen,LASTHASHPKT */
+            icvlen = EVAL_icvlen();
+            *tp++=0x21e60000 | ((icvlen)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* INS OUT,PAD_ZERO,0,0,LASTHASHPKT */
+            *tp++=0x21060000 | ((0u)&0x1u)<<16 | ((0u)&0xffffu)<<0;
+        }
+        seq_offset = EVAL_seq_offset();
+        if (seq_offset > 0u)
+        {
+            /* CTX ORIG_HASH,seq_offset,hstatelen,P,F */
+            hstatelen = EVAL_hstatelen();
+            *tp++=0xe0e63800 | ((seq_offset)&0xffu)<<0 | ((hstatelen)&0xfu)<<24;
+            if (hstatelen > 16u)
+            {
+                /* CTX ORIG_SPI_RES,seq_offset+hstatelen-16,1,P,F ; Update block counter */
+                *tp++=0xe0c63800 | ((-16u+seq_offset+hstatelen)&0xffu)<<0 | ((1u)&0xfu)<<24;
+            }
+        }
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 14: /* basic_crypthash */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        aadlen_pkt = EVAL_aadlen_pkt();
+        ivlen = EVAL_ivlen();
+        antireplay = EVAL_antireplay();
+        if (packetsize < bypass+aadlen_pkt+ivlen+antireplay)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for basic crypthash\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        aadlen_tkn = EVAL_aadlen_tkn();
+        if (aadlen_tkn > 0u)
+        {
+            extseq = EVAL_extseq();
+            if (extseq > 0u)
+            {
+                /* INS HASH,ORIG_TOKEN,aadlen_tkn */
+                *tp++=0x23d80000 | ((aadlen_tkn)&0x1ffffu)<<0;
+            }
+            else
+            {
+                /* INS HASHONLY,ORIG_TOKEN,aadlen_tkn */
+                *tp++=0x22d80000 | ((aadlen_tkn)&0x1ffffu)<<0;
+            }
+            aad = EVAL_aad();
+            if (aadlen_tkn > 64)
+            {
+                LOG_CRIT("Field too large\n");
+                return TKB_BAD_FIELD_SIZE;
+            }
+            TokenBuilder_CopyBytes(tp, aad, aadlen_tkn);
+            tp += (aadlen_tkn + 3)/4;
+        }
+        else if (aadlen_pkt > 0u)
+        {
+            extseq = EVAL_extseq();
+            if (extseq > 0u)
+            {
+                /* DIR HASH,aadlen_pkt */
+                *tp++=0x03000000 | ((aadlen_pkt)&0x1ffffu)<<0;
+            }
+            else
+            {
+                /* DIR HASHONLY,aadlen_pkt */
+                *tp++=0x02000000 | ((aadlen_pkt)&0x1ffffu)<<0;
+            }
+        }
+        switch(ivhandling)
+        {
+        case 0: /* iv_inbound_ctr */
+            /* RETR HASHONLY,ORIG_IV1,8 ; IV from input packet, CTR. */
+            *tp++=0x42a80000 | ((8u)&0x1ffffu)<<0;
+            break;
+        case 1: /* iv_inbound_cbc */
+            /* RETR HASHONLY,ORIG_IV0,ivlen ; IV from input packet CBC */
+            *tp++=0x42a00000 | ((ivlen)&0x1ffffu)<<0;
+            break;
+        case 2: /* iv_outbound_ctr */
+            /* INS  HASH,ORIG_IV1,8 */
+            *tp++=0x23a80000 | ((8u)&0x1ffffu)<<0;
+            break;
+        case 5: /* iv_copy_ctr */
+            /* RETR HASH,ORIG_IV1,8 ; IV from input packet, CTR. */
+            *tp++=0x43a80000 | ((8u)&0x1ffffu)<<0;
+            break;
+        case 4: /* iv_copy_cbc */
+            /* RETR HASH,ORIG_IV0,ivlen ; IV from input packet CBC */
+            *tp++=0x43a00000 | ((ivlen)&0x1ffffu)<<0;
+            break;
+        case 6: /* iv_outbound_2words */
+        case 9: /* iv_copy_token_2words */
+            /* INS  HASH,ORIG_IV0,8 */
+            *tp++=0x23a00000 | ((8u)&0x1ffffu)<<0;
+            break;
+        case 7: /* iv_outbound_4words */
+        case 15: /* iv_copy_token_4words */
+            /* INS  HASH,ORIG_IV0,16 */
+            *tp++=0x23a00000 | ((16u)&0x1ffffu)<<0;
+            break;
+        }
+        pad_bytes_basic = EVAL_pad_bytes_basic();
+        if (pad_bytes_basic > 0u)
+        {
+            /* DIR CRYPTHASH,packetsize-ivlen-bypass-aadlen_pkt-antireplay */
+            *tp++=0x07000000 | ((packetsize-ivlen-bypass-aadlen_pkt-antireplay)&0x1ffffu)<<0;
+            /* INS CRYPTHASH,PAD_ZERO,0,pad_bytes_basic,LAST,LASTHASH */
+            *tp++=0x2f020000 | ((0u)&0x1u)<<16 | ((pad_bytes_basic)&0xffffu)<<0;
+        }
+        else
+        {
+            /* DIR CRYPTHASH,packetsize-ivlen-bypass-aadlen_pkt-antireplay,LAST,LASTHASH */
+            *tp++=0x0f020000 | ((packetsize-ivlen-bypass-aadlen_pkt-antireplay)&0x1ffffu)<<0;
+        }
+        appendhash = EVAL_appendhash();
+        if (antireplay > 0u)
+        {
+            /* RETR NONE,ORIG_HASH,antireplay,LASTHASHPKT */
+            *tp++=0x40e60000 | ((antireplay)&0x1ffffu)<<0;
+            /* VERIFY antireplay,H */
+            *tp++=0xd0070000 | ((antireplay)&0x7fu)<<0;
+        }
+        else if (appendhash > 0u)
+        {
+            /* INS OUT,ORIG_HASH,icvlen,LASTHASHPKT */
+            icvlen = EVAL_icvlen();
+            *tp++=0x21e60000 | ((icvlen)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* INS OUT,PAD_ZERO,0,0,LASTHASHPKT */
+            *tp++=0x21060000 | ((0u)&0x1u)<<16 | ((0u)&0xffffu)<<0;
+        }
+        seq_offset = EVAL_seq_offset();
+        if (seq_offset > 0u)
+        {
+            /* CTX ORIG_HASH,seq_offset,hstatelen,P,F */
+            hstatelen = EVAL_hstatelen();
+            *tp++=0xe0e63800 | ((seq_offset)&0xffu)<<0 | ((hstatelen)&0xfu)<<24;
+            if (hstatelen > 16u)
+            {
+                /* CTX ORIG_SPI_RES,seq_offset+hstatelen-16,1,P,F ; Update block counter */
+                *tp++=0xe0c63800 | ((-16u+seq_offset+hstatelen)&0xffu)<<0 | ((1u)&0xfu)<<24;
+            }
+        }
+        upd_handling = EVAL_upd_handling();
+        switch(upd_handling)
+        {
+        case 0: /* upd_null */
+            break;
+        case 1: /* upd_arc4 */
+            /* CTX ORIG_CHKSUM,iv_offset,1,P,F ; Update IJ pointer */
+            iv_offset = EVAL_iv_offset();
+            *tp++=0xe0ce3800 | ((iv_offset)&0xffu)<<0 | ((1u)&0xfu)<<24;
+            /* CTX ORIG_CHKSUM_STORE,0,1,P,F   ; Update ARC4 state. */
+            *tp++=0xe0d63800 | ((0u)&0xffu)<<0 | ((1u)&0xfu)<<24;
+            break;
+        case 2: /* upd_iv2 */
+            /* CTX ORIG_IV0,iv_offset,2,P,F */
+            iv_offset = EVAL_iv_offset();
+            *tp++=0xe0a63800 | ((iv_offset)&0xffu)<<0 | ((2u)&0xfu)<<24;
+            break;
+        case 3: /* upd_iv4 */
+            /* CTX ORIG_IV0,iv_offset,4,P,F */
+            iv_offset = EVAL_iv_offset();
+            *tp++=0xe0a63800 | ((iv_offset)&0xffu)<<0 | ((4u)&0xfu)<<24;
+            break;
+        }
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 15: /* basic_out_ccm */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        aadlen_pkt = EVAL_aadlen_pkt();
+        ivlen = EVAL_ivlen();
+        if (packetsize < bypass+aadlen_pkt+ivlen)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for basic out ccm\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        /* INS HASHONLY,ORIG_TOKEN,4 */
+        *tp++=0x22d80000 | ((4u)&0x1ffffu)<<0;
+        /* DATA32 basic_salt */
+        basic_salt = EVAL_basic_salt();
+        *tp++=0x00000000 | ((basic_salt)&0xffffffffu)<<0;
+        if (ivhandling == 5u)
+        {
+            /* RETR HASH,ORIG_IV1,8 ; IV from input packet, CTR. */
+            *tp++=0x43a80000 | ((8u)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* INS HASH, ORIG_IV1,8 */
+            *tp++=0x23a80000 | ((8u)&0x1ffffu)<<0;
+        }
+        aadlen_swap = EVAL_aadlen_swap();
+        if (aadlen_swap > 0u)
+        {
+            /* INS HASHONLY,ORIG_TOKEN,6 */
+            *tp++=0x22d80000 | ((6u)&0x1ffffu)<<0;
+            /* DATA32 basic_swaplen */
+            basic_swaplen = EVAL_basic_swaplen();
+            *tp++=0x00000000 | ((basic_swaplen)&0xffffffffu)<<0;
+            /* DATA32 aadlen_swap */
+            *tp++=0x00000000 | ((aadlen_swap)&0xffffffffu)<<0;
+            aadlen_tkn = EVAL_aadlen_tkn();
+            if (aadlen_tkn > 0u)
+            {
+                extseq = EVAL_extseq();
+                if (extseq > 0u)
+                {
+                    /* INS HASH,ORIG_TOKEN,aadlen_tkn */
+                    *tp++=0x23d80000 | ((aadlen_tkn)&0x1ffffu)<<0;
+                }
+                else
+                {
+                    /* INS HASHONLY,ORIG_TOKEN,aadlen_tkn */
+                    *tp++=0x22d80000 | ((aadlen_tkn)&0x1ffffu)<<0;
+                }
+                aad = EVAL_aad();
+                if (aadlen_tkn > 64)
+                {
+                    LOG_CRIT("Field too large\n");
+                    return TKB_BAD_FIELD_SIZE;
+                }
+                TokenBuilder_CopyBytes(tp, aad, aadlen_tkn);
+                tp += (aadlen_tkn + 3)/4;
+            }
+            else if (aadlen_pkt > 0u)
+            {
+                extseq = EVAL_extseq();
+                if (extseq > 0u)
+                {
+                    /* DIR HASH,aadlen_pkt */
+                    *tp++=0x03000000 | ((aadlen_pkt)&0x1ffffu)<<0;
+                }
+                else
+                {
+                    /* DIR HASHONLY,aadlen_pkt */
+                    *tp++=0x02000000 | ((aadlen_pkt)&0x1ffffu)<<0;
+                }
+            }
+            /* INS HASHONLY,PAD_ZERO,0,aadpad */
+            aadpad = EVAL_aadpad();
+            *tp++=0x22000000 | ((0u)&0x1u)<<16 | ((aadpad)&0xffffu)<<0;
+        }
+        else
+        {
+            /* INS HASHONLY,ORIG_TOKEN,4 */
+            *tp++=0x22d80000 | ((4u)&0x1ffffu)<<0;
+            /* DATA32 basic_swaplen */
+            basic_swaplen = EVAL_basic_swaplen();
+            *tp++=0x00000000 | ((basic_swaplen)&0xffffffffu)<<0;
+        }
+        /* REMRES bypass+8+aadlen_out,16 */
+        aadlen_out = EVAL_aadlen_out();
+        *tp++=0xa0000000 | ((8u+bypass+aadlen_out)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+        /* INS CRYPT,PAD_ZERO,0,16 */
+        *tp++=0x25000000 | ((0u)&0x1u)<<16 | ((16u)&0xffffu)<<0;
+        basic_hashpad = EVAL_basic_hashpad();
+        if (basic_hashpad == 0u)
+        {
+            /* DIR CRYPTHASH,packetsize-aadlen_pkt-ivlen-bypass,LAST,LASTHASH */
+            *tp++=0x0f020000 | ((packetsize-aadlen_pkt-ivlen-bypass)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* DIR CRYPTHASH,packetsize-aadlen_pkt-ivlen-bypass,LAST */
+            *tp++=0x0f000000 | ((packetsize-aadlen_pkt-ivlen-bypass)&0x1ffffu)<<0;
+            /* INS HASHONLY,PAD_ZERO,0,basic_hashpad,LASTHASH */
+            *tp++=0x22020000 | ((0u)&0x1u)<<16 | ((basic_hashpad)&0xffffu)<<0;
+        }
+        seq_offset = EVAL_seq_offset();
+        if (seq_offset > 0u)
+        {
+            /* INS OUT,PAD_ZERO,0,0,LASTHASHPKT */
+            *tp++=0x21060000 | ((0u)&0x1u)<<16 | ((0u)&0xffffu)<<0;
+            /* CTX ORIG_HASH,seq_offset,hstatelen,P,F */
+            hstatelen = EVAL_hstatelen();
+            *tp++=0xe0e63800 | ((seq_offset)&0xffu)<<0 | ((hstatelen)&0xfu)<<24;
+        }
+        else
+        {
+            /* INS OUT, ORIG_HASH, icvlen, LASTHASHPKT */
+            icvlen = EVAL_icvlen();
+            *tp++=0x21e60000 | ((icvlen)&0x1ffffu)<<0;
+        }
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 16: /* basic_in_ccm */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        aadlen_pkt = EVAL_aadlen_pkt();
+        ivlen = EVAL_ivlen();
+        antireplay = EVAL_antireplay();
+        if (packetsize < bypass+aadlen_pkt+ivlen+antireplay)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for basic in ccm\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        /* INS HASHONLY,ORIG_TOKEN,4 */
+        *tp++=0x22d80000 | ((4u)&0x1ffffu)<<0;
+        /* DATA32 basic_salt */
+        basic_salt = EVAL_basic_salt();
+        *tp++=0x00000000 | ((basic_salt)&0xffffffffu)<<0;
+        if (ivhandling == 0u)
+        {
+            /* RETR HASHONLY,ORIG_IV1,8 ; IV from input packet, CTR. */
+            *tp++=0x42a80000 | ((8u)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* INS HASHONLY,ORIG_IV1,8 */
+            *tp++=0x22a80000 | ((8u)&0x1ffffu)<<0;
+        }
+        aadlen_swap = EVAL_aadlen_swap();
+        if (aadlen_swap > 0u)
+        {
+            /* INS HASHONLY,ORIG_TOKEN,6 */
+            *tp++=0x22d80000 | ((6u)&0x1ffffu)<<0;
+            /* DATA32 basic_swaplen */
+            basic_swaplen = EVAL_basic_swaplen();
+            *tp++=0x00000000 | ((basic_swaplen)&0xffffffffu)<<0;
+            /* DATA32 aadlen_swap */
+            *tp++=0x00000000 | ((aadlen_swap)&0xffffffffu)<<0;
+            aadlen_tkn = EVAL_aadlen_tkn();
+            if (aadlen_tkn > 0u)
+            {
+                extseq = EVAL_extseq();
+                if (extseq > 0u)
+                {
+                    /* INS HASH,ORIG_TOKEN,aadlen_tkn */
+                    *tp++=0x23d80000 | ((aadlen_tkn)&0x1ffffu)<<0;
+                }
+                else
+                {
+                    /* INS HASHONLY,ORIG_TOKEN,aadlen_tkn */
+                    *tp++=0x22d80000 | ((aadlen_tkn)&0x1ffffu)<<0;
+                }
+                aad = EVAL_aad();
+                if (aadlen_tkn > 64)
+                {
+                    LOG_CRIT("Field too large\n");
+                    return TKB_BAD_FIELD_SIZE;
+                }
+                TokenBuilder_CopyBytes(tp, aad, aadlen_tkn);
+                tp += (aadlen_tkn + 3)/4;
+            }
+            else if (aadlen_pkt > 0u)
+            {
+                extseq = EVAL_extseq();
+                if (extseq > 0u)
+                {
+                    /* DIR HASH,aadlen_pkt */
+                    *tp++=0x03000000 | ((aadlen_pkt)&0x1ffffu)<<0;
+                }
+                else
+                {
+                    /* DIR HASHONLY,aadlen_pkt */
+                    *tp++=0x02000000 | ((aadlen_pkt)&0x1ffffu)<<0;
+                }
+            }
+            /* INS HASHONLY,PAD_ZERO,0,aadpad */
+            aadpad = EVAL_aadpad();
+            *tp++=0x22000000 | ((0u)&0x1u)<<16 | ((aadpad)&0xffffu)<<0;
+        }
+        else
+        {
+            /* INS HASHONLY,ORIG_TOKEN,4 */
+            *tp++=0x22d80000 | ((4u)&0x1ffffu)<<0;
+            /* DATA32 basic_swaplen */
+            basic_swaplen = EVAL_basic_swaplen();
+            *tp++=0x00000000 | ((basic_swaplen)&0xffffffffu)<<0;
+        }
+        /* REMRES bypass+aadlen_out,16 */
+        aadlen_out = EVAL_aadlen_out();
+        *tp++=0xa0000000 | ((bypass+aadlen_out)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+        /* INS CRYPT,PAD_ZERO,0,16 */
+        *tp++=0x25000000 | ((0u)&0x1u)<<16 | ((16u)&0xffffu)<<0;
+        basic_hashpad = EVAL_basic_hashpad();
+        if (basic_hashpad == 0u)
+        {
+            /* DIR CRYPTHASH,packetsize-aadlen_pkt-ivlen-bypass-icvlen,LAST,LASTHASH */
+            icvlen = EVAL_icvlen();
+            *tp++=0x0f020000 | ((packetsize-aadlen_pkt-ivlen-bypass-icvlen)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* DIR CRYPTHASH,packetsize-aadlen_pkt-ivlen-bypass-icvlen,LAST */
+            icvlen = EVAL_icvlen();
+            *tp++=0x0f000000 | ((packetsize-aadlen_pkt-ivlen-bypass-icvlen)&0x1ffffu)<<0;
+            /* INS HASHONLY,PAD_ZERO,0,basic_hashpad,LASTHASH */
+            *tp++=0x22020000 | ((0u)&0x1u)<<16 | ((basic_hashpad)&0xffffu)<<0;
+        }
+        seq_offset = EVAL_seq_offset();
+        if (seq_offset > 0u)
+        {
+            /* INS OUT,PAD_ZERO,0,0,LASTHASHPKT */
+            *tp++=0x21060000 | ((0u)&0x1u)<<16 | ((0u)&0xffffu)<<0;
+            /* CTX ORIG_HASH,seq_offset,hstatelen,P,F */
+            hstatelen = EVAL_hstatelen();
+            *tp++=0xe0e63800 | ((seq_offset)&0xffu)<<0 | ((hstatelen)&0xfu)<<24;
+        }
+        else
+        {
+            /* RETR NONE, ORIG_HASH, antireplay, LASTHASHPKT */
+            *tp++=0x40e60000 | ((antireplay)&0x1ffffu)<<0;
+            /* VERIFY antireplay,H */
+            *tp++=0xd0070000 | ((antireplay)&0x7fu)<<0;
+        }
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 17: /* basic_out_gcm */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        aadlen_pkt = EVAL_aadlen_pkt();
+        ivlen = EVAL_ivlen();
+        if (packetsize < bypass+aadlen_pkt+ivlen)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for basic out gcm\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        aadlen_tkn = EVAL_aadlen_tkn();
+        if (aadlen_tkn > 0u)
+        {
+            extseq = EVAL_extseq();
+            if (extseq > 0u)
+            {
+                /* INS HASH,ORIG_TOKEN,aadlen_tkn,LAST */
+                *tp++=0x2bd80000 | ((aadlen_tkn)&0x1ffffu)<<0;
+            }
+            else
+            {
+                /* INS HASHONLY,ORIG_TOKEN,aadlen_tkn,LAST */
+                *tp++=0x2ad80000 | ((aadlen_tkn)&0x1ffffu)<<0;
+            }
+            aad = EVAL_aad();
+            if (aadlen_tkn > 64)
+            {
+                LOG_CRIT("Field too large\n");
+                return TKB_BAD_FIELD_SIZE;
+            }
+            TokenBuilder_CopyBytes(tp, aad, aadlen_tkn);
+            tp += (aadlen_tkn + 3)/4;
+        }
+        else
+        {
+            extseq = EVAL_extseq();
+            if (extseq > 0u)
+            {
+                /* DIR HASH,aadlen_pkt,LAST */
+                *tp++=0x0b000000 | ((aadlen_pkt)&0x1ffffu)<<0;
+            }
+            else
+            {
+                /* DIR HASHONLY,aadlen_pkt,LAST */
+                *tp++=0x0a000000 | ((aadlen_pkt)&0x1ffffu)<<0;
+            }
+        }
+        switch(ivhandling)
+        {
+        case 0: /* iv_inbound_ctr */
+            /* RETR NONE,ORIG_IV1,8 ; IV from input packet, CTR. */
+            *tp++=0x40a80000 | ((8u)&0x1ffffu)<<0;
+            /* REMRES   bypass+aadlen_out,16 */
+            aadlen_out = EVAL_aadlen_out();
+            *tp++=0xa0000000 | ((bypass+aadlen_out)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+            break;
+        case 5: /* iv_copy_ctr */
+            if (aadlen_pkt+aadlen_tkn == 0u)
+            {
+                LOG_WARN("TokenBuilder: bad packet, null aad illegal for gcm and copy iv\n");
+                rc = TKB_BAD_PACKET; goto error;
+            }
+            /* RETR OUT,ORIG_IV1,8 ; IV from input packet, copy iv */
+            *tp++=0x41a80000 | ((8u)&0x1ffffu)<<0;
+            /* REMRES   bypass+aadlen_out+8,16 */
+            aadlen_out = EVAL_aadlen_out();
+            *tp++=0xa0000000 | ((8u+bypass+aadlen_out)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+            break;
+        case 15: /* iv_copy_token_4words */
+        case 2: /* iv_outbound_ctr */
+            if (aadlen_pkt+aadlen_tkn == 0u)
+            {
+                LOG_WARN("TokenBuilder: bad packet, null aad illegal for gcm and copy iv\n");
+                rc = TKB_BAD_PACKET; goto error;
+            }
+            /* INS OUT,ORIG_IV1,8 ; IV from token, copy iv */
+            *tp++=0x21a80000 | ((8u)&0x1ffffu)<<0;
+            /* REMRES   bypass+aadlen_out+8,16 */
+            aadlen_out = EVAL_aadlen_out();
+            *tp++=0xa0000000 | ((8u+bypass+aadlen_out)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+            break;
+        default:
+            /* REMRES   bypass+aadlen_out,16 */
+            aadlen_out = EVAL_aadlen_out();
+            *tp++=0xa0000000 | ((bypass+aadlen_out)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+        }
+        /* INS      CRYPT, PAD_ZERO, 0, 16 */
+        *tp++=0x25000000 | ((0u)&0x1u)<<16 | ((16u)&0xffffu)<<0;
+        /* DIR      CRYPTHASH,packetsize - bypass - aadlen_pkt - ivlen, LAST,LASTHASH */
+        *tp++=0x0f020000 | ((packetsize-bypass-aadlen_pkt-ivlen)&0x1ffffu)<<0;
+        seq_offset = EVAL_seq_offset();
+        if (seq_offset > 0u)
+        {
+            /* INS OUT,PAD_ZERO,0,0,LASTHASHPKT */
+            *tp++=0x21060000 | ((0u)&0x1u)<<16 | ((0u)&0xffffu)<<0;
+            /* CTX ORIG_HASH,seq_offset,hstatelen,P,F */
+            hstatelen = EVAL_hstatelen();
+            *tp++=0xe0e63800 | ((seq_offset)&0xffu)<<0 | ((hstatelen)&0xfu)<<24;
+        }
+        else
+        {
+            /* INS OUT, ORIG_HASH, icvlen, LASTHASHPKT */
+            icvlen = EVAL_icvlen();
+            *tp++=0x21e60000 | ((icvlen)&0x1ffffu)<<0;
+        }
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 18: /* basic_in_gcm */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        aadlen_pkt = EVAL_aadlen_pkt();
+        ivlen = EVAL_ivlen();
+        antireplay = EVAL_antireplay();
+        if (packetsize < bypass+aadlen_pkt+ivlen+antireplay)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for basic in gcm\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        aadlen_tkn = EVAL_aadlen_tkn();
+        if (aadlen_tkn > 0u)
+        {
+            extseq = EVAL_extseq();
+            if (extseq > 0u)
+            {
+                /* INS HASH,ORIG_TOKEN,aadlen_tkn,LAST */
+                *tp++=0x2bd80000 | ((aadlen_tkn)&0x1ffffu)<<0;
+            }
+            else
+            {
+                /* INS HASHONLY,ORIG_TOKEN,aadlen_tkn,LAST */
+                *tp++=0x2ad80000 | ((aadlen_tkn)&0x1ffffu)<<0;
+            }
+            aad = EVAL_aad();
+            if (aadlen_tkn > 64)
+            {
+                LOG_CRIT("Field too large\n");
+                return TKB_BAD_FIELD_SIZE;
+            }
+            TokenBuilder_CopyBytes(tp, aad, aadlen_tkn);
+            tp += (aadlen_tkn + 3)/4;
+        }
+        else
+        {
+            extseq = EVAL_extseq();
+            if (extseq > 0u)
+            {
+                /* DIR HASH,aadlen_pkt,LAST */
+                *tp++=0x0b000000 | ((aadlen_pkt)&0x1ffffu)<<0;
+            }
+            else
+            {
+                /* DIR HASHONLY,aadlen_pkt,LAST */
+                *tp++=0x0a000000 | ((aadlen_pkt)&0x1ffffu)<<0;
+            }
+        }
+        switch(ivhandling)
+        {
+        case 0: /* iv_inbound_ctr */
+            /* RETR NONE,ORIG_IV1,8 ; IV from input packet, CTR. */
+            *tp++=0x40a80000 | ((8u)&0x1ffffu)<<0;
+            /* REMRES   bypass+aadlen_out,16 */
+            aadlen_out = EVAL_aadlen_out();
+            *tp++=0xa0000000 | ((bypass+aadlen_out)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+            break;
+        case 5: /* iv_copy_ctr */
+            if (aadlen_pkt+aadlen_tkn == 0u)
+            {
+                LOG_WARN("TokenBuilder: bad packet, null aad illegal for gcm and copy iv\n");
+                rc = TKB_BAD_PACKET; goto error;
+            }
+            /* RETR OUT,ORIG_IV1,8 ; IV from input packet, copy iv */
+            *tp++=0x41a80000 | ((8u)&0x1ffffu)<<0;
+            /* REMRES   bypass+aadlen_out+8,16 */
+            aadlen_out = EVAL_aadlen_out();
+            *tp++=0xa0000000 | ((8u+bypass+aadlen_out)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+            break;
+        case 15: /* iv_copy_token_4words */
+        case 2: /* iv_outbound_ctr */
+            if (aadlen_pkt+aadlen_tkn == 0u)
+            {
+                LOG_WARN("TokenBuilder: bad packet, null aad illegal for gcm and copy iv\n");
+                rc = TKB_BAD_PACKET; goto error;
+            }
+            /* INS OUT,ORIG_IV1,8 ; IV from token, copy iv */
+            *tp++=0x21a80000 | ((8u)&0x1ffffu)<<0;
+            /* REMRES   bypass+aadlen_out+8,16 */
+            aadlen_out = EVAL_aadlen_out();
+            *tp++=0xa0000000 | ((8u+bypass+aadlen_out)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+            break;
+        default:
+            /* REMRES   bypass+aadlen_out,16 */
+            aadlen_out = EVAL_aadlen_out();
+            *tp++=0xa0000000 | ((bypass+aadlen_out)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+        }
+        /* INS      CRYPT, PAD_ZERO, 0, 16 */
+        *tp++=0x25000000 | ((0u)&0x1u)<<16 | ((16u)&0xffffu)<<0;
+        /* DIR      CRYPTHASH,packetsize - bypass - aadlen_pkt - ivlen - icvlen, LAST,LASTHASH */
+        icvlen = EVAL_icvlen();
+        *tp++=0x0f020000 | ((packetsize-bypass-aadlen_pkt-ivlen-icvlen)&0x1ffffu)<<0;
+        seq_offset = EVAL_seq_offset();
+        if (seq_offset > 0u)
+        {
+            /* INS OUT,PAD_ZERO,0,0,LASTHASHPKT */
+            *tp++=0x21060000 | ((0u)&0x1u)<<16 | ((0u)&0xffffu)<<0;
+            /* CTX ORIG_HASH,seq_offset,hstatelen,P,F */
+            hstatelen = EVAL_hstatelen();
+            *tp++=0xe0e63800 | ((seq_offset)&0xffu)<<0 | ((hstatelen)&0xfu)<<24;
+        }
+        else
+        {
+            /* RETR NONE, ORIG_HASH, antireplay, LASTHASHPKT */
+            *tp++=0x40e60000 | ((antireplay)&0x1ffffu)<<0;
+            /* VERIFY antireplay,H */
+            *tp++=0xd0070000 | ((antireplay)&0x7fu)<<0;
+        }
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 19: /* basic_out_gmac */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        aadlen_pkt = EVAL_aadlen_pkt();
+        ivlen = EVAL_ivlen();
+        if (packetsize < bypass+aadlen_pkt+ivlen)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for basic out gmac\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        aadlen_tkn = EVAL_aadlen_tkn();
+        if (aadlen_tkn > 0u)
+        {
+            extseq = EVAL_extseq();
+            if (extseq > 0u)
+            {
+                /* INS HASH,ORIG_TOKEN,aadlen_tkn */
+                *tp++=0x23d80000 | ((aadlen_tkn)&0x1ffffu)<<0;
+            }
+            else
+            {
+                /* INS HASHONLY,ORIG_TOKEN,aadlen_tkn */
+                *tp++=0x22d80000 | ((aadlen_tkn)&0x1ffffu)<<0;
+            }
+            aad = EVAL_aad();
+            if (aadlen_tkn > 64)
+            {
+                LOG_CRIT("Field too large\n");
+                return TKB_BAD_FIELD_SIZE;
+            }
+            TokenBuilder_CopyBytes(tp, aad, aadlen_tkn);
+            tp += (aadlen_tkn + 3)/4;
+        }
+        else if (aadlen_pkt > 0u)
+        {
+            extseq = EVAL_extseq();
+            if (extseq > 0u)
+            {
+                /* DIR HASH,aadlen_pkt */
+                *tp++=0x03000000 | ((aadlen_pkt)&0x1ffffu)<<0;
+            }
+            else
+            {
+                /* DIR HASHONLY,aadlen_pkt */
+                *tp++=0x02000000 | ((aadlen_pkt)&0x1ffffu)<<0;
+            }
+        }
+        switch(ivhandling)
+        {
+        case 0: /* iv_inbound_ctr */
+            /* RETR HASHONLY,ORIG_IV1,8 ; IV from input packet, CTR. */
+            *tp++=0x42a80000 | ((8u)&0x1ffffu)<<0;
+            /* DIR      HASH,packetsize - bypass - aadlen_pkt - ivlen, LAST,LASTHASH */
+            *tp++=0x0b020000 | ((packetsize-bypass-aadlen_pkt-ivlen)&0x1ffffu)<<0;
+            /* REMRES   packetsize+aadlen_out-aadlen_pkt-ivlen,16 */
+            aadlen_out = EVAL_aadlen_out();
+            *tp++=0xa0000000 | ((packetsize+aadlen_out-aadlen_pkt-ivlen)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+            break;
+        case 5: /* iv_copy_ctr */
+            /* RETR HASH,ORIG_IV1,8 ; IV from input packet, copy iv */
+            *tp++=0x43a80000 | ((8u)&0x1ffffu)<<0;
+            /* DIR      HASH,packetsize - bypass - aadlen_pkt - ivlen, LAST,LASTHASH */
+            *tp++=0x0b020000 | ((packetsize-bypass-aadlen_pkt-ivlen)&0x1ffffu)<<0;
+            /* REMRES   packetsize+aadlen_out-aadlen_pkt-ivlen+8,16 */
+            aadlen_out = EVAL_aadlen_out();
+            *tp++=0xa0000000 | ((8u+packetsize+aadlen_out-aadlen_pkt-ivlen)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+            break;
+        case 15: /* iv_copy_token_4words */
+        case 2: /* iv_outbound_ctr */
+            /* INS OUT,ORIG_IV1,8 ; IV from token, copy iv. */
+            *tp++=0x21a80000 | ((8u)&0x1ffffu)<<0;
+            /* DIR      HASH,packetsize - bypass - aadlen_pkt - ivlen, LAST,LASTHASH */
+            *tp++=0x0b020000 | ((packetsize-bypass-aadlen_pkt-ivlen)&0x1ffffu)<<0;
+            /* REMRES   packetsize+aadlen_out-aadlen_pkt-ivlen+8,16 */
+            aadlen_out = EVAL_aadlen_out();
+            *tp++=0xa0000000 | ((8u+packetsize+aadlen_out-aadlen_pkt-ivlen)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+            break;
+        default:
+            /* DIR      HASH,packetsize - bypass - aadlen_pkt - ivlen, LAST,LASTHASH */
+            *tp++=0x0b020000 | ((packetsize-bypass-aadlen_pkt-ivlen)&0x1ffffu)<<0;
+            /* REMRES   packetsize+aadlen_out-aadlen_pkt-ivlen,16 */
+            aadlen_out = EVAL_aadlen_out();
+            *tp++=0xa0000000 | ((packetsize+aadlen_out-aadlen_pkt-ivlen)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+        }
+        /* INS      CRYPT, PAD_ZERO, 0, 16,LAST */
+        *tp++=0x2d000000 | ((0u)&0x1u)<<16 | ((16u)&0xffffu)<<0;
+        seq_offset = EVAL_seq_offset();
+        if (seq_offset > 0u)
+        {
+            /* INS OUT,PAD_ZERO,0,0,LASTHASHPKT */
+            *tp++=0x21060000 | ((0u)&0x1u)<<16 | ((0u)&0xffffu)<<0;
+            /* CTX ORIG_HASH,seq_offset,hstatelen,P,F */
+            hstatelen = EVAL_hstatelen();
+            *tp++=0xe0e63800 | ((seq_offset)&0xffu)<<0 | ((hstatelen)&0xfu)<<24;
+        }
+        else
+        {
+            /* INS OUT, ORIG_HASH, icvlen, LASTHASHPKT */
+            icvlen = EVAL_icvlen();
+            *tp++=0x21e60000 | ((icvlen)&0x1ffffu)<<0;
+        }
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 20: /* basic_in_gmac */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        aadlen_pkt = EVAL_aadlen_pkt();
+        ivlen = EVAL_ivlen();
+        antireplay = EVAL_antireplay();
+        if (packetsize < bypass+aadlen_pkt+ivlen+antireplay)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for basic in gmac\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        aadlen_tkn = EVAL_aadlen_tkn();
+        if (aadlen_tkn > 0u)
+        {
+            extseq = EVAL_extseq();
+            if (extseq > 0u)
+            {
+                /* INS HASH,ORIG_TOKEN,aadlen_tkn */
+                *tp++=0x23d80000 | ((aadlen_tkn)&0x1ffffu)<<0;
+            }
+            else
+            {
+                /* INS HASHONLY,ORIG_TOKEN,aadlen_tkn */
+                *tp++=0x22d80000 | ((aadlen_tkn)&0x1ffffu)<<0;
+            }
+            aad = EVAL_aad();
+            if (aadlen_tkn > 64)
+            {
+                LOG_CRIT("Field too large\n");
+                return TKB_BAD_FIELD_SIZE;
+            }
+            TokenBuilder_CopyBytes(tp, aad, aadlen_tkn);
+            tp += (aadlen_tkn + 3)/4;
+        }
+        else if (aadlen_pkt > 0u)
+        {
+            extseq = EVAL_extseq();
+            if (extseq > 0u)
+            {
+                /* DIR HASH,aadlen_pkt */
+                *tp++=0x03000000 | ((aadlen_pkt)&0x1ffffu)<<0;
+            }
+            else
+            {
+                /* DIR HASHONLY,aadlen_pkt */
+                *tp++=0x02000000 | ((aadlen_pkt)&0x1ffffu)<<0;
+            }
+        }
+        switch(ivhandling)
+        {
+        case 0: /* iv_inbound_ctr */
+            /* RETR HASHONLY,ORIG_IV1,8 ; IV from input packet, CTR. */
+            *tp++=0x42a80000 | ((8u)&0x1ffffu)<<0;
+            /* DIR      HASH,packetsize - bypass - aadlen_pkt - ivlen - icvlen, LAST,LASTHASH */
+            icvlen = EVAL_icvlen();
+            *tp++=0x0b020000 | ((packetsize-bypass-aadlen_pkt-ivlen-icvlen)&0x1ffffu)<<0;
+            /* REMRES   packetsize+aadlen_out-aadlen_pkt-ivlen-icvlen,16 */
+            aadlen_out = EVAL_aadlen_out();
+            *tp++=0xa0000000 | ((packetsize+aadlen_out-aadlen_pkt-ivlen-icvlen)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+            break;
+        case 5: /* iv_copy_ctr */
+            /* RETR HASH,ORIG_IV1,8 ; IV from input packet, copy iv */
+            *tp++=0x43a80000 | ((8u)&0x1ffffu)<<0;
+            /* DIR      HASH,packetsize - bypass - aadlen_pkt - ivlen - icvlen, LAST,LASTHASH */
+            icvlen = EVAL_icvlen();
+            *tp++=0x0b020000 | ((packetsize-bypass-aadlen_pkt-ivlen-icvlen)&0x1ffffu)<<0;
+            /* REMRES   packetsize+aadlen_out-aadlen_pkt-ivlen-icvlen+8,16 */
+            aadlen_out = EVAL_aadlen_out();
+            *tp++=0xa0000000 | ((8u+packetsize+aadlen_out-aadlen_pkt-ivlen-icvlen)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+            break;
+        case 15: /* iv_copy_token_4words */
+        case 2: /* iv_outbound_ctr */
+            /* INS OUT,ORIG_IV1,8 ; IV from token, copy iv Do not authenticate IV */
+            *tp++=0x21a80000 | ((8u)&0x1ffffu)<<0;
+            /* DIR      HASH,packetsize - bypass - aadlen_pkt - ivlen - icvlen, LAST,LASTHASH */
+            icvlen = EVAL_icvlen();
+            *tp++=0x0b020000 | ((packetsize-bypass-aadlen_pkt-ivlen-icvlen)&0x1ffffu)<<0;
+            /* REMRES   packetsize+aadlen_out-aadlen_pkt-ivlen-icvlen+8,16 */
+            aadlen_out = EVAL_aadlen_out();
+            *tp++=0xa0000000 | ((8u+packetsize+aadlen_out-aadlen_pkt-ivlen-icvlen)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+            break;
+        default:
+            /* DIR      HASH,packetsize - bypass - aadlen_pkt - ivlen - icvlen, LAST,LASTHASH */
+            icvlen = EVAL_icvlen();
+            *tp++=0x0b020000 | ((packetsize-bypass-aadlen_pkt-ivlen-icvlen)&0x1ffffu)<<0;
+            /* REMRES   packetsize+aadlen_out-aadlen_pkt-ivlen-icvlen,16 */
+            aadlen_out = EVAL_aadlen_out();
+            *tp++=0xa0000000 | ((packetsize+aadlen_out-aadlen_pkt-ivlen-icvlen)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+        }
+        /* INS      CRYPT, PAD_ZERO, 0, 16,LAST */
+        *tp++=0x2d000000 | ((0u)&0x1u)<<16 | ((16u)&0xffffu)<<0;
+        seq_offset = EVAL_seq_offset();
+        if (seq_offset > 0u)
+        {
+            /* INS OUT,PAD_ZERO,0,0,LASTHASHPKT */
+            *tp++=0x21060000 | ((0u)&0x1u)<<16 | ((0u)&0xffffu)<<0;
+            /* CTX ORIG_HASH,seq_offset,hstatelen,P,F */
+            hstatelen = EVAL_hstatelen();
+            *tp++=0xe0e63800 | ((seq_offset)&0xffu)<<0 | ((hstatelen)&0xfu)<<24;
+        }
+        else
+        {
+            /* RETR NONE, ORIG_HASH, antireplay, LASTHASHPKT */
+            *tp++=0x40e60000 | ((antireplay)&0x1ffffu)<<0;
+            /* VERIFY antireplay,H */
+            *tp++=0xd0070000 | ((antireplay)&0x7fu)<<0;
+        }
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 23: /* basic_xts_crypto */
+#if TKB_HAVE_CRYPTO_XTS == 1u
+        ivlen = EVAL_ivlen();
+        if (packetsize < ivlen+bypass)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for basic crypto\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        swap_j = EVAL_swap_j();
+        if (swap_j != 0u)
+        {
+            /* INSCTX NONE,ORIG_TOKEN,10,16 */
+            *tp++=0x90d80000 | ((10u)&0x1fu)<<12 | ((16u)&0x1ffu)<<0;
+            /* DATA32 0 */
+            *tp++=0x00000000 | ((0u)&0xffffffffu)<<0;
+            /* DATA32 0 */
+            *tp++=0x00000000 | ((0u)&0xffffffffu)<<0;
+            /* DATA32 0 */
+            *tp++=0x00000000 | ((0u)&0xffffffffu)<<0;
+            /* DATA32 swap_j */
+            *tp++=0x00000000 | ((swap_j)&0xffffffffu)<<0;
+        }
+        switch(ivhandling)
+        {
+        case 1: /* iv_inbound_cbc */
+            /* RETR NONE,ORIG_IV0,ivlen ; IV from input packet CBC */
+            *tp++=0x40a00000 | ((ivlen)&0x1ffffu)<<0;
+            break;
+        case 4: /* iv_copy_cbc */
+            /* RETR OUT,ORIG_IV0,ivlen ; IV from input packet CBC */
+            *tp++=0x41a00000 | ((ivlen)&0x1ffffu)<<0;
+            break;
+        case 7: /* iv_outbound_4words */
+        case 15: /* iv_copy_token_4words */
+            /* INS  OUT,ORIG_IV0,16 */
+            *tp++=0x21a00000 | ((16u)&0x1ffffu)<<0;
+            break;
+        }
+        /* DIR CRYPT,packetsize-ivlen-bypass */
+        *tp++=0x05000000 | ((packetsize-ivlen-bypass)&0x1ffffu)<<0;
+        /* INS CRYPT,PAD_ZERO,0,pad_bytes_basic,LAST,LASTHASHPKT */
+        pad_bytes_basic = EVAL_pad_bytes_basic();
+        *tp++=0x2d060000 | ((0u)&0x1u)<<16 | ((pad_bytes_basic)&0xffffu)<<0;
+        upd_handling = EVAL_upd_handling();
+        switch(upd_handling)
+        {
+        case 0: /* upd_null */
+            break;
+        case 3: /* upd_iv4 */
+            /* CTX ORIG_IV0,iv_offset,4,P,F */
+            iv_offset = EVAL_iv_offset();
+            *tp++=0xe0a63800 | ((iv_offset)&0xffu)<<0 | ((4u)&0xfu)<<24;
+            break;
+        }
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 24: /* basic_kasumi_hash */
+#if TKB_HAVE_CRYPTO_WIRELESS == 1u
+        antireplay = EVAL_antireplay();
+        if (packetsize < bypass+antireplay)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for basic hash\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        /* INS HASHONLY,ORIG_TOKEN,8 */
+        *tp++=0x22d80000 | ((8u)&0x1ffffu)<<0;
+        /* DATA32 count */
+        count = EVAL_count();
+        *tp++=0x00000000 | ((count)&0xffffffffu)<<0;
+        /* DATA32 bearer_dir_fresh */
+        bearer_dir_fresh = EVAL_bearer_dir_fresh();
+        *tp++=0x00000000 | ((bearer_dir_fresh)&0xffffffffu)<<0;
+        extseq = EVAL_extseq();
+        if (extseq > 0u)
+        {
+            /* DIR HASH,packetsize-bypass-antireplay,LASTHASH */
+            *tp++=0x03020000 | ((packetsize-bypass-antireplay)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* DIR HASHONLY,packetsize-bypass-antireplay,LASTHASH */
+            *tp++=0x02020000 | ((packetsize-bypass-antireplay)&0x1ffffu)<<0;
+        }
+        appendhash = EVAL_appendhash();
+        if (antireplay > 0u)
+        {
+            /* RETR NONE,ORIG_HASH,antireplay,LASTHASHPKT */
+            *tp++=0x40e60000 | ((antireplay)&0x1ffffu)<<0;
+            /* VERIFY antireplay,H */
+            *tp++=0xd0070000 | ((antireplay)&0x7fu)<<0;
+        }
+        else if (appendhash > 0u)
+        {
+            /* INS OUT,ORIG_HASH,icvlen,LASTHASHPKT */
+            icvlen = EVAL_icvlen();
+            *tp++=0x21e60000 | ((icvlen)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* INS OUT,PAD_ZERO,0,0,LASTHASHPKT */
+            *tp++=0x21060000 | ((0u)&0x1u)<<16 | ((0u)&0xffffu)<<0;
+        }
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 25: /* basic_snow_hash */
+    case 26: /* basic_zuc_hash */
+#if TKB_HAVE_CRYPTO_WIRELESS == 1u
+        antireplay = EVAL_antireplay();
+        if (packetsize < bypass+antireplay)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for basic hash\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        /* INSCTX NONE,ORIG_TOKEN,10,16 */
+        *tp++=0x90d80000 | ((10u)&0x1fu)<<12 | ((16u)&0x1ffu)<<0;
+        /* DATA32 count */
+        count = EVAL_count();
+        *tp++=0x00000000 | ((count)&0xffffffffu)<<0;
+        /* DATA32 bearer_dir_fresh */
+        bearer_dir_fresh = EVAL_bearer_dir_fresh();
+        *tp++=0x00000000 | ((bearer_dir_fresh)&0xffffffffu)<<0;
+        /* DATA32 count */
+        *tp++=0x00000000 | ((count)&0xffffffffu)<<0;
+        /* DATA32 bearer_dir_fresh */
+        *tp++=0x00000000 | ((bearer_dir_fresh)&0xffffffffu)<<0;
+        extseq = EVAL_extseq();
+        if (extseq > 0u)
+        {
+            /* DIR HASH,packetsize-bypass-antireplay,LASTHASH */
+            *tp++=0x03020000 | ((packetsize-bypass-antireplay)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* DIR HASHONLY,packetsize-bypass-antireplay,LASTHASH */
+            *tp++=0x02020000 | ((packetsize-bypass-antireplay)&0x1ffffu)<<0;
+        }
+        appendhash = EVAL_appendhash();
+        if (antireplay > 0u)
+        {
+            /* RETR NONE,ORIG_HASH,antireplay,LASTHASHPKT */
+            *tp++=0x40e60000 | ((antireplay)&0x1ffffu)<<0;
+            /* VERIFY antireplay,H */
+            *tp++=0xd0070000 | ((antireplay)&0x7fu)<<0;
+        }
+        else if (appendhash > 0u)
+        {
+            /* INS OUT,ORIG_HASH,icvlen,LASTHASHPKT */
+            icvlen = EVAL_icvlen();
+            *tp++=0x21e60000 | ((icvlen)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* INS OUT,PAD_ZERO,0,0,LASTHASHPKT */
+            *tp++=0x21060000 | ((0u)&0x1u)<<16 | ((0u)&0xffffu)<<0;
+        }
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 27: /* basic_hashenc */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        aadlen_pkt = EVAL_aadlen_pkt();
+        ivlen = EVAL_ivlen();
+        if (packetsize < bypass+aadlen_pkt+ivlen)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for basic crypthash\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        aadlen_tkn = EVAL_aadlen_tkn();
+        if (aadlen_tkn > 0u)
+        {
+            extseq = EVAL_extseq();
+            if (extseq > 0u)
+            {
+                /* INS HASH,ORIG_TOKEN,aadlen_tkn */
+                *tp++=0x23d80000 | ((aadlen_tkn)&0x1ffffu)<<0;
+            }
+            else
+            {
+                /* INS HASHONLY,ORIG_TOKEN,aadlen_tkn */
+                *tp++=0x22d80000 | ((aadlen_tkn)&0x1ffffu)<<0;
+            }
+            aad = EVAL_aad();
+            if (aadlen_tkn > 64)
+            {
+                LOG_CRIT("Field too large\n");
+                return TKB_BAD_FIELD_SIZE;
+            }
+            TokenBuilder_CopyBytes(tp, aad, aadlen_tkn);
+            tp += (aadlen_tkn + 3)/4;
+        }
+        else if (aadlen_pkt > 0u)
+        {
+            extseq = EVAL_extseq();
+            if (extseq > 0u)
+            {
+                /* DIR HASH,aadlen_pkt */
+                *tp++=0x03000000 | ((aadlen_pkt)&0x1ffffu)<<0;
+            }
+            else
+            {
+                /* DIR HASHONLY,aadlen_pkt */
+                *tp++=0x02000000 | ((aadlen_pkt)&0x1ffffu)<<0;
+            }
+        }
+        switch(ivhandling)
+        {
+        case 4: /* iv_copy_cbc */
+            /* RETR OUT,ORIG_IV0,ivlen ; IV from input packet CBC */
+            *tp++=0x41a00000 | ((ivlen)&0x1ffffu)<<0;
+            break;
+        case 6: /* iv_outbound_2words */
+        case 9: /* iv_copy_token_2words */
+            /* INS  OUT,ORIG_IV0,8 */
+            *tp++=0x21a00000 | ((8u)&0x1ffffu)<<0;
+            break;
+        case 7: /* iv_outbound_4words */
+        case 15: /* iv_copy_token_4words */
+            /* INS  OUT,ORIG_IV0,16 */
+            *tp++=0x21a00000 | ((16u)&0x1ffffu)<<0;
+            break;
+        }
+        /* DIR CRYPTHASH,packetsize-ivlen-bypass-aadlen_pkt,LASTHASH */
+        *tp++=0x07020000 | ((packetsize-ivlen-bypass-aadlen_pkt)&0x1ffffu)<<0;
+        /* INS CRYPT,ORIG_HASH,icvlen,LASTHASH */
+        icvlen = EVAL_icvlen();
+        *tp++=0x25e20000 | ((icvlen)&0x1ffffu)<<0;
+        /* INS CRYPT,PAD_TLS,0,pad_bytes_hashenc,LAST,LASTHASHPKT */
+        pad_bytes_hashenc = EVAL_pad_bytes_hashenc();
+        *tp++=0x2d2e0000 | ((0u)&0xffu)<<9 | ((pad_bytes_hashenc)&0x1ffu)<<0;
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 28: /* basic_dechash */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        aadlen_pkt = EVAL_aadlen_pkt();
+        aadlen_tkn = EVAL_aadlen_tkn();
+        if (aadlen_pkt+aadlen_tkn < 2u)
+        {
+            LOG_WARN("TokenBuilder: bad packet, aad too short\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        /* REMRES 0,4,NOUPDCHK */
+        *tp++=0xa0020000 | ((0u)&0xffffu)<<0 | ((4u)&0x3fu)<<19;
+        cipher_is_aes = EVAL_cipher_is_aes();
+        if (cipher_is_aes == 0u)
+        {
+            ivlen = EVAL_ivlen();
+            if (packetsize < 16u+bypass+aadlen_pkt+ivlen)
+            {
+                LOG_WARN("TokenBuilder: bad packet, too short for basic dechash\n");
+                rc = TKB_BAD_PACKET; goto error;
+            }
+            /* INS CRYPTONLY,ORIG_TOKEN,12 */
+            *tp++=0x24d80000 | ((12u)&0x1ffffu)<<0;
+            ssltls_lastblock = EVAL_ssltls_lastblock();
+            TokenBuilder_CopyBytes(tp, ssltls_lastblock, 12);
+            tp += 3;
+            /* INS CRYPT,ORIG_TOKEN,4 */
+            *tp++=0x25d80000 | ((4u)&0x1ffffu)<<0;
+            ssltls_lastword = EVAL_ssltls_lastword();
+            TokenBuilder_CopyBytes(tp, ssltls_lastword, 4);
+            tp += 1;
+        }
+        else
+        {
+            ivlen = EVAL_ivlen();
+            if (packetsize < 32u+bypass+aadlen_pkt+ivlen)
+            {
+                LOG_WARN("TokenBuilder: bad packet, too short for basic dechash\n");
+                rc = TKB_BAD_PACKET; goto error;
+            }
+            /* INS CRYPTONLY,ORIG_TOKEN,28 */
+            *tp++=0x24d80000 | ((28u)&0x1ffffu)<<0;
+            ssltls_lastblock = EVAL_ssltls_lastblock();
+            TokenBuilder_CopyBytes(tp, ssltls_lastblock, 28);
+            tp += 7;
+            /* INS CRYPT,ORIG_TOKEN,4 */
+            *tp++=0x25d80000 | ((4u)&0x1ffffu)<<0;
+            ssltls_lastword = EVAL_ssltls_lastword();
+            TokenBuilder_CopyBytes(tp, ssltls_lastword, 4);
+            tp += 1;
+        }
+        /* DIR NONE,0,LAST */
+        *tp++=0x08000000 | ((0u)&0x1ffffu)<<0;
+        if (bypass > 0u)
+        {
+            /* DIR OUT,bypass */
+            *tp++=0x01000000 | ((bypass)&0x1ffffu)<<0;
+        }
+        if (aadlen_tkn > 0u)
+        {
+            /* INS HASHONLY,ORIG_TOKEN,aadlen_tkn-2 */
+            *tp++=0x22d80000 | ((-2u+aadlen_tkn)&0x1ffffu)<<0;
+            aad = EVAL_aad();
+            if (-2u+aadlen_tkn > 64)
+            {
+                LOG_CRIT("Field too large\n");
+                return TKB_BAD_FIELD_SIZE;
+            }
+            TokenBuilder_CopyBytes(tp, aad, -2u+aadlen_tkn);
+            tp += (-2u+aadlen_tkn + 3)/4;
+        }
+        else if (aadlen_pkt > 0u)
+        {
+            /* DIR HASHONLY,aadlen_pkt-2 */
+            *tp++=0x02000000 | ((-2u+aadlen_pkt)&0x1ffffu)<<0;
+        }
+        /* INS HASHONLY,ORIG_LENCOR,packetsize-bypass-aadlen_pkt-ivlen-icvlen-1 */
+        ivlen = EVAL_ivlen();
+        icvlen = EVAL_icvlen();
+        *tp++=0x22780000 | ((-1u+packetsize-bypass-aadlen_pkt-ivlen-icvlen)&0x1ffffu)<<0;
+        /* REM 2 */
+        *tp++=0x40d80000 | ((2u)&0x1ffffu)<<0;
+        if (ivlen > 0u)
+        {
+            /* RETR NONE,ORIG_IV0,ivlen */
+            *tp++=0x40a00000 | ((ivlen)&0x1ffffu)<<0;
+        }
+        /* REMRES bypass,icvlen,NOUPDCHK          ; Cause the MAC to be removed */
+        *tp++=0xa0020000 | ((bypass)&0xffffu)<<0 | ((icvlen)&0x3fu)<<19;
+        /* DIRX CRYPTHASH,ORIG_LENCOR,0,LASTHASH */
+        *tp++=0x077a0000 | ((0u)&0x1ffffu)<<0;
+        /* DIRX CRYPT,ORIG_LENCOR,icvlen+1,LAST,LASTHASHPKT */
+        *tp++=0x0d7e0000 | ((1u+icvlen)&0x1ffffu)<<0;
+        /* VERIFY icvlen,P,H */
+        *tp++=0xd1070000 | ((icvlen)&0x7fu)<<0;
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 12: /* srtp_out */
+#if TKB_HAVE_PROTO_SRTP == 1u
+        srtp_offset = EVAL_srtp_offset();
+        if (packetsize <= bypass+srtp_offset)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for SRTP outbound\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        if (srtp_offset > 0u)
+        {
+            /* DIR  HASH, srtp_offset */
+            *tp++=0x03000000 | ((srtp_offset)&0x1ffffu)<<0;
+            /* DIR  CRYPTHASH, packetsize - bypass - srtp_offset,LAST */
+            *tp++=0x0f000000 | ((packetsize-bypass-srtp_offset)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* DIR  HASH, packetsize - bypass,LAST */
+            *tp++=0x0b000000 | ((packetsize-bypass)&0x1ffffu)<<0;
+        }
+        extseq = EVAL_extseq();
+        if (extseq > 0u)
+        {
+            /* INS  HASH, ORIG_TOKEN, 4, LASTHASH ; SCTCP, index gets appended */
+            *tp++=0x23da0000 | ((4u)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* INS  HASHONLY, ORIG_TOKEN, 4, LASTHASH ; SRTP, ROC gets hashed, not appended */
+            *tp++=0x22da0000 | ((4u)&0x1ffffu)<<0;
+        }
+        /* DATA32 srtp_swaproc */
+        srtp_swaproc = EVAL_srtp_swaproc();
+        *tp++=0x00000000 | ((srtp_swaproc)&0xffffffffu)<<0;
+        antireplay = EVAL_antireplay();
+        if (antireplay > 0u)
+        {
+            /* INS OUT,ORIG_SPI,4,LASTHASH */
+            *tp++=0x21920000 | ((4u)&0x1ffffu)<<0;
+        }
+        /* INS OUT, ORIG_HASH, icvlen,LASTHASHPKT */
+        icvlen = EVAL_icvlen();
+        *tp++=0x21e60000 | ((icvlen)&0x1ffffu)<<0;
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 13: /* srtp_in */
+#if TKB_HAVE_PROTO_SRTP == 1u
+        srtp_offset = EVAL_srtp_offset();
+        icvlen = EVAL_icvlen();
+        extseq = EVAL_extseq();
+        antireplay = EVAL_antireplay();
+        if (packetsize <= bypass+srtp_offset+icvlen+extseq+antireplay)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for SRTP inbound\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        if (srtp_offset > 0u)
+        {
+            /* DIR  HASH, srtp_offset */
+            *tp++=0x03000000 | ((srtp_offset)&0x1ffffu)<<0;
+            /* DIR CRYPTHASH, packetsize - bypass - srtp_offset - icvlen - extseq -antireplay,LAST */
+            *tp++=0x0f000000 | ((packetsize-bypass-srtp_offset-icvlen-extseq-antireplay)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* DIR HASH, packetsize - bypass - icvlen - extseq -antireplay,LAST */
+            *tp++=0x0b000000 | ((packetsize-bypass-icvlen-extseq-antireplay)&0x1ffffu)<<0;
+        }
+        if (extseq > 0u)
+        {
+            /* DIR  HASHONLY, 4, LASTHASH ; SCTCP extraxt from packet. */
+            *tp++=0x02020000 | ((4u)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* INS  HASHONLY, ORIG_TOKEN, 4, LASTHASH ; SRTP, ROC gets hashed, not appended */
+            *tp++=0x22da0000 | ((4u)&0x1ffffu)<<0;
+            /* DATA32 srtp_swaproc */
+            srtp_swaproc = EVAL_srtp_swaproc();
+            *tp++=0x00000000 | ((srtp_swaproc)&0xffffffffu)<<0;
+        }
+        if (antireplay > 0u)
+        {
+            /* RETR NONE,ORIG_SPI,4 */
+            *tp++=0x40900000 | ((4u)&0x1ffffu)<<0;
+        }
+        if (icvlen > 0u)
+        {
+            /* RETR NONE,ORIG_HASH, icvlen,LASTHASHPKT */
+            *tp++=0x40e60000 | ((icvlen)&0x1ffffu)<<0;
+            if (antireplay > 0u)
+            {
+                /* VERIFY icvlen,H,SP */
+                *tp++=0xd4070000 | ((icvlen)&0x7fu)<<0;
+            }
+            else
+            {
+                /* VERIFY icvlen,H */
+                *tp++=0xd0070000 | ((icvlen)&0x7fu)<<0;
+            }
+        }
+        else
+        {
+            /* INS NONE,PAD_ZERO,0,0,LASTHASHPKT */
+            *tp++=0x20060000 | ((0u)&0x1u)<<16 | ((0u)&0xffffu)<<0;
+            if (antireplay > 0u)
+            {
+                /* VERIFY 0,SP */
+                *tp++=0xd4060000 | ((0u)&0x7fu)<<0;
+            }
+        }
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 29: /* basic_out_chachapoly */
+#if TKB_HAVE_PROTO_BASIC == 1u
+#if TKB_HAVE_CRYPTO_CHACHAPOLY == 1u
+        aadlen_pkt = EVAL_aadlen_pkt();
+        ivlen = EVAL_ivlen();
+        if (packetsize < bypass+aadlen_pkt+ivlen)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for basic out ccm\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        aadlen_tkn = EVAL_aadlen_tkn();
+        if (aadlen_tkn > 0u)
+        {
+            extseq = EVAL_extseq();
+            if (extseq > 0u)
+            {
+                /* INS HASH,ORIG_TOKEN,aadlen_tkn,LAST */
+                *tp++=0x2bd80000 | ((aadlen_tkn)&0x1ffffu)<<0;
+            }
+            else
+            {
+                /* INS HASHONLY,ORIG_TOKEN,aadlen_tkn,LAST */
+                *tp++=0x2ad80000 | ((aadlen_tkn)&0x1ffffu)<<0;
+            }
+            aad = EVAL_aad();
+            if (aadlen_tkn > 64)
+            {
+                LOG_CRIT("Field too large\n");
+                return TKB_BAD_FIELD_SIZE;
+            }
+            TokenBuilder_CopyBytes(tp, aad, aadlen_tkn);
+            tp += (aadlen_tkn + 3)/4;
+        }
+        else if (aadlen_pkt > 0u)
+        {
+            extseq = EVAL_extseq();
+            if (extseq > 0u)
+            {
+                /* DIR HASH,aadlen_pkt,LAST */
+                *tp++=0x0b000000 | ((aadlen_pkt)&0x1ffffu)<<0;
+            }
+            else
+            {
+                /* DIR HASHONLY,aadlen_pkt,LAST */
+                *tp++=0x0a000000 | ((aadlen_pkt)&0x1ffffu)<<0;
+            }
+        }
+        else
+        {
+            /* INS HASHONLY,PAD_ZERO,0,0,LAST */
+            *tp++=0x2a000000 | ((0u)&0x1u)<<16 | ((0u)&0xffffu)<<0;
+        }
+        /* DIR CRYPTHASH,packetsize-aadlen_pkt-ivlen-bypass,LAST,LASTHASH */
+        *tp++=0x0f020000 | ((packetsize-aadlen_pkt-ivlen-bypass)&0x1ffffu)<<0;
+        /* INS OUT, ORIG_HASH, icvlen, LASTHASHPKT */
+        icvlen = EVAL_icvlen();
+        *tp++=0x21e60000 | ((icvlen)&0x1ffffu)<<0;
+#else
+        LOG_WARN("TokenBuilder: bad crypto\n");
+        rc = TKB_BAD_CRYPTO; goto error;
+#endif
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 30: /* basic_in_chachapoly */
+#if TKB_HAVE_PROTO_BASIC == 1u
+#if TKB_HAVE_CRYPTO_CHACHAPOLY == 1u
+        aadlen_pkt = EVAL_aadlen_pkt();
+        ivlen = EVAL_ivlen();
+        if (packetsize < bypass+aadlen_pkt+ivlen)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for basic out ccm\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        aadlen_tkn = EVAL_aadlen_tkn();
+        if (aadlen_tkn > 0u)
+        {
+            extseq = EVAL_extseq();
+            if (extseq > 0u)
+            {
+                /* INS HASH,ORIG_TOKEN,aadlen_tkn,LAST */
+                *tp++=0x2bd80000 | ((aadlen_tkn)&0x1ffffu)<<0;
+            }
+            else
+            {
+                /* INS HASHONLY,ORIG_TOKEN,aadlen_tkn,LAST */
+                *tp++=0x2ad80000 | ((aadlen_tkn)&0x1ffffu)<<0;
+            }
+            aad = EVAL_aad();
+            if (aadlen_tkn > 64)
+            {
+                LOG_CRIT("Field too large\n");
+                return TKB_BAD_FIELD_SIZE;
+            }
+            TokenBuilder_CopyBytes(tp, aad, aadlen_tkn);
+            tp += (aadlen_tkn + 3)/4;
+        }
+        else if (aadlen_pkt > 0u)
+        {
+            extseq = EVAL_extseq();
+            if (extseq > 0u)
+            {
+                /* DIR HASH,aadlen_pkt,LAST */
+                *tp++=0x0b000000 | ((aadlen_pkt)&0x1ffffu)<<0;
+            }
+            else
+            {
+                /* DIR HASHONLY,aadlen_pkt,LAST */
+                *tp++=0x0a000000 | ((aadlen_pkt)&0x1ffffu)<<0;
+            }
+        }
+        else
+        {
+            /* INS HASHONLY,PAD_ZERO,0,0,LAST */
+            *tp++=0x2a000000 | ((0u)&0x1u)<<16 | ((0u)&0xffffu)<<0;
+        }
+#if TKB_HAVE_CHACHAPOLY_HW30 == 1u
+        /* INS NONE,PAD_ZERO,0,176 */
+        *tp++=0x20000000 | ((0u)&0x1u)<<16 | ((176u)&0xffffu)<<0;
+#else
+        /* INS NONE,PAD_ZERO,0,16 */
+        *tp++=0x20000000 | ((0u)&0x1u)<<16 | ((16u)&0xffffu)<<0;
+#endif
+        /* DIR CRYPTHASH,packetsize-aadlen_pkt-ivlen-bypass-icvlen,LAST,LASTHASH */
+        icvlen = EVAL_icvlen();
+        *tp++=0x0f020000 | ((packetsize-aadlen_pkt-ivlen-bypass-icvlen)&0x1ffffu)<<0;
+        /* RETR NONE, ORIG_HASH, antireplay, LASTHASHPKT */
+        antireplay = EVAL_antireplay();
+        *tp++=0x40e60000 | ((antireplay)&0x1ffffu)<<0;
+        /* VERIFY antireplay,H */
+        *tp++=0xd0070000 | ((antireplay)&0x7fu)<<0;
+#else
+        LOG_WARN("TokenBuilder: bad crypto\n");
+        rc = TKB_BAD_CRYPTO; goto error;
+#endif
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 31: /* tls13_gcm_out */
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+        if (packetsize < bypass)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for SSLTLS outbound GCM\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        /* INS HASH,PAD_CONST,0x17,1    ; Type field */
+        *tp++=0x23100000 | ((23u)&0xffu)<<9 | ((1u)&0x1ffu)<<0;
+        /* INS HASH,ORIG_SPI,2          ; For TLS1.3 hash fixed type/version field. */
+        *tp++=0x23900000 | ((2u)&0x1ffffu)<<0;
+        /* INS HASH,ORIG_TOKEN,2,LAST */
+        *tp++=0x2bd80000 | ((2u)&0x1ffffu)<<0;
+        /* DATA32 swap_fraglen_tls13    ; Fragment length to output and hash. */
+        swap_fraglen_tls13 = EVAL_swap_fraglen_tls13();
+        *tp++=0x00000000 | ((swap_fraglen_tls13)&0xffffffffu)<<0;
+        /* REMRES bypass + 5, 16 */
+        *tp++=0xa0000000 | ((5u+bypass)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+        /* INS CRYPT, PAD_ZERO, 0, 16 */
+        *tp++=0x25000000 | ((0u)&0x1u)<<16 | ((16u)&0xffffu)<<0;
+        /* DIR CRYPTHASH, packetsize-bypass */
+        *tp++=0x07000000 | ((packetsize-bypass)&0x1ffffu)<<0;
+        count = EVAL_count();
+        if (count == 0u)
+        {
+            /* INS CRYPTHASH, PAD_CONST, nextheader, 1, LAST, LASTHASH */
+            nextheader = EVAL_nextheader();
+            *tp++=0x2f120000 | ((nextheader)&0xffu)<<9 | ((1u)&0x1ffu)<<0;
+        }
+        else
+        {
+            /* INS CRYPTHASH, PAD_CONST, nextheader, 1 */
+            nextheader = EVAL_nextheader();
+            *tp++=0x27100000 | ((nextheader)&0xffu)<<9 | ((1u)&0x1ffu)<<0;
+            /* INS CRYPTHASH, PAD_ZERO, 0, count, LAST, LASTHASH */
+            *tp++=0x2f020000 | ((0u)&0x1u)<<16 | ((count)&0xffffu)<<0;
+        }
+        /* INS OUT,ORIG_HASH,icvlen,LASTHASHPKT */
+        icvlen = EVAL_icvlen();
+        *tp++=0x21e60000 | ((icvlen)&0x1ffffu)<<0;
+        /* VERIFY   0  ; Causes any sequence number rollover error to fail the packet. */
+        *tp++=0xd0060000 | ((0u)&0x7fu)<<0;
+        /* CTX ORIG_SEQNUM,seq_offset,2 */
+        seq_offset = EVAL_seq_offset();
+        *tp++=0xe0560800 | ((seq_offset)&0xffu)<<0 | ((2u)&0xfu)<<24;
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 32: /* tls13_gcm_in */
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+        icvlen = EVAL_icvlen();
+        if (packetsize < 5u+bypass+icvlen)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for SSLTLS inbound GCM\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        /* DIR HASHONLY,5,LAST       ; Hash type and version number and length */
+        *tp++=0x0a000000 | ((5u)&0x1ffffu)<<0;
+        /* REMRES bypass, 16 */
+        *tp++=0xa0000000 | ((bypass)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+        /* INS CRYPT, PAD_ZERO, 0, 16 */
+        *tp++=0x25000000 | ((0u)&0x1u)<<16 | ((16u)&0xffffu)<<0;
+        /* DIR CRYPTHASH, packetsize-bypass-icvlen-5,LAST,LASTHASH */
+        *tp++=0x0f020000 | ((-5u+packetsize-bypass-icvlen)&0x1ffffu)<<0;
+        /* RETR NONE,ORIG_HASH,icvlen,LASTHASHPKT */
+        *tp++=0x40e60000 | ((icvlen)&0x1ffffu)<<0;
+        /* VERIFY icvlen,H */
+        *tp++=0xd0070000 | ((icvlen)&0x7fu)<<0;
+        /* CTX ORIG_SEQNUM,seq_offset,2,P */
+        seq_offset = EVAL_seq_offset();
+        *tp++=0xe0561800 | ((seq_offset)&0xffu)<<0 | ((2u)&0xfu)<<24;
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 33: /* tls13_chachapoly_out */
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+        if (packetsize < bypass)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for SSLTLS outbound ChaChaPoly\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        /* INS HASH,PAD_CONST,0x17,1    ; Type field */
+        *tp++=0x23100000 | ((23u)&0xffu)<<9 | ((1u)&0x1ffu)<<0;
+        /* INS HASH,ORIG_SPI,2          ; For TLS1.3 hash fixed type/version field. */
+        *tp++=0x23900000 | ((2u)&0x1ffffu)<<0;
+        /* INS HASH,ORIG_TOKEN,2,LAST */
+        *tp++=0x2bd80000 | ((2u)&0x1ffffu)<<0;
+        /* DATA32 swap_fraglen_tls13    ; Fragment length to output and hash. */
+        swap_fraglen_tls13 = EVAL_swap_fraglen_tls13();
+        *tp++=0x00000000 | ((swap_fraglen_tls13)&0xffffffffu)<<0;
+        /* DIR CRYPTHASH, packetsize-bypass */
+        *tp++=0x07000000 | ((packetsize-bypass)&0x1ffffu)<<0;
+        count = EVAL_count();
+        if (count == 0u)
+        {
+            /* INS CRYPTHASH, PAD_CONST, nextheader, 1, LAST, LASTHASH */
+            nextheader = EVAL_nextheader();
+            *tp++=0x2f120000 | ((nextheader)&0xffu)<<9 | ((1u)&0x1ffu)<<0;
+        }
+        else
+        {
+            /* INS CRYPTHASH, PAD_CONST, nextheader, 1 */
+            nextheader = EVAL_nextheader();
+            *tp++=0x27100000 | ((nextheader)&0xffu)<<9 | ((1u)&0x1ffu)<<0;
+            /* INS CRYPTHASH, PAD_ZERO, 0, count, LAST, LASTHASH */
+            *tp++=0x2f020000 | ((0u)&0x1u)<<16 | ((count)&0xffffu)<<0;
+        }
+        /* INS OUT,ORIG_HASH,icvlen,LASTHASHPKT */
+        icvlen = EVAL_icvlen();
+        *tp++=0x21e60000 | ((icvlen)&0x1ffffu)<<0;
+        /* VERIFY   0  ; Causes any sequence number rollover error to fail the packet. */
+        *tp++=0xd0060000 | ((0u)&0x7fu)<<0;
+        /* CTX ORIG_SEQNUM,seq_offset,2 */
+        seq_offset = EVAL_seq_offset();
+        *tp++=0xe0560800 | ((seq_offset)&0xffu)<<0 | ((2u)&0xfu)<<24;
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 34: /* tls13_chachapoly_in */
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+        icvlen = EVAL_icvlen();
+        if (packetsize < 5u+bypass+icvlen)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for SSLTLS inbound ChaChaPoly\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        /* DIR HASHONLY,5,LAST       ; Hash type and version number and length */
+        *tp++=0x0a000000 | ((5u)&0x1ffffu)<<0;
+        /* INS NONE, PAD_ZERO, 0, 16 */
+        *tp++=0x20000000 | ((0u)&0x1u)<<16 | ((16u)&0xffffu)<<0;
+        /* DIR CRYPTHASH, packetsize-bypass-icvlen-5,LAST,LASTHASH */
+        *tp++=0x0f020000 | ((-5u+packetsize-bypass-icvlen)&0x1ffffu)<<0;
+        /* RETR NONE,ORIG_HASH,icvlen,LASTHASHPKT */
+        *tp++=0x40e60000 | ((icvlen)&0x1ffffu)<<0;
+        /* VERIFY icvlen,H */
+        *tp++=0xd0070000 | ((icvlen)&0x7fu)<<0;
+        /* CTX ORIG_SEQNUM,seq_offset,2,P */
+        seq_offset = EVAL_seq_offset();
+        *tp++=0xe0561800 | ((seq_offset)&0xffu)<<0 | ((2u)&0xfu)<<24;
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 35: /* esp_out_chachapoly */
+#if TKB_HAVE_PROTO_IPSEC == 1u
+        if (packetsize <= bypass+hdrlen)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for ESP outbound ChaChaPoly\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        extseq = EVAL_extseq();
+        if (extseq == 0u)
+        {
+            /* INS      HASH,ORIG_SPI,8,LAST */
+            *tp++=0x2b900000 | ((8u)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* INS      HASH,ORIG_SPI,4 */
+            *tp++=0x23900000 | ((4u)&0x1ffffu)<<0;
+            /* INS      HASHONLY, ORIG_EXTSEQNUM_RES2, 4 */
+            *tp++=0x22480000 | ((4u)&0x1ffffu)<<0;
+            /* INS      HASH,ORIG_SEQNUM_RES, 4, LAST */
+            *tp++=0x2b980000 | ((4u)&0x1ffffu)<<0;
+        }
+        /* INS      OUT,ORIG_IV1,ivlen */
+        ivlen = EVAL_ivlen();
+        *tp++=0x21a80000 | ((ivlen)&0x1ffffu)<<0;
+        /* DIR      CRYPTHASH, packetsize-bypass-hdrlen */
+        *tp++=0x07000000 | ((packetsize-bypass-hdrlen)&0x1ffffu)<<0;
+        /* INS      CRYPTHASH,PAD_IPSEC,nextheader,pad_bytes,LAST,LASTHASH */
+        nextheader = EVAL_nextheader();
+        pad_bytes = EVAL_pad_bytes();
+        *tp++=0x2f220000 | ((nextheader)&0xffu)<<9 | ((pad_bytes)&0x1ffu)<<0;
+        /* INS      OUT,ORIG_HASH,icvlen,LASTHASHPKT */
+        icvlen = EVAL_icvlen();
+        *tp++=0x21e60000 | ((icvlen)&0x1ffffu)<<0;
+        /* VERIFY   0  ; Causes any sequence number rollover error to fail the packet. */
+        *tp++=0xd0060000 | ((0u)&0x7fu)<<0;
+        /* CTX      ORIG_SEQNUM,seq_offset,1+extseq */
+        seq_offset = EVAL_seq_offset();
+        *tp++=0xe0560800 | ((seq_offset)&0xffu)<<0 | ((1u+extseq)&0xfu)<<24;
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 36: /* esp_in_chachapoly */
+#if TKB_HAVE_PROTO_IPSEC == 1u
+        ivlen = EVAL_ivlen();
+        icvlen = EVAL_icvlen();
+        pad_blocksize = EVAL_pad_blocksize();
+        if (packetsize < 8u+ivlen+icvlen+pad_blocksize+bypass+hdrlen)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for ESP inbound ChaChaPoly\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        pad_remainder = EVAL_pad_remainder();
+        if (pad_remainder != 0u)
+        {
+            LOG_WARN("TokenBuilder: bad packet, pad alignment ESP inbound ChaChaPoly\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        extseq = EVAL_extseq();
+        if (extseq != 1u)
+        {
+            /* RETR     HASHONLY,ORIG_SPI,8,LAST */
+            *tp++=0x4a900000 | ((8u)&0x1ffffu)<<0;
+            /* RETR     NONE,ORIG_IV1,ivlen */
+            *tp++=0x40a80000 | ((ivlen)&0x1ffffu)<<0;
+#if TKB_HAVE_ECN_FIXUP == 1u
+            /* DATA32 ecn_fixup_instr */
+            ecn_fixup_instr = EVAL_ecn_fixup_instr();
+            *tp++=0x00000000 | ((ecn_fixup_instr)&0xffffffffu)<<0;
+#endif
+            /* INS      NONE, PAD_ZERO, 0, 16 */
+            *tp++=0x20000000 | ((0u)&0x1u)<<16 | ((16u)&0xffffu)<<0;
+        }
+        else
+        {
+            /* RETR     HASHONLY,ORIG_SPI,4 */
+            *tp++=0x42900000 | ((4u)&0x1ffffu)<<0;
+            /* RETR     NONE,ORIG_SEQNUM_RES,4 */
+            *tp++=0x40980000 | ((4u)&0x1ffffu)<<0;
+            /* RETR     NONE,ORIG_IV1,ivlen */
+            *tp++=0x40a80000 | ((ivlen)&0x1ffffu)<<0;
+            /* INS      HASHONLY,ORIG_EXTSEQNUM_RES2, 4 */
+            *tp++=0x22480000 | ((4u)&0x1ffffu)<<0;
+            /* INS      HASHONLY,ORIG_SEQNUM_RES,4,LAST */
+            *tp++=0x2a980000 | ((4u)&0x1ffffu)<<0;
+#if TKB_HAVE_ECN_FIXUP == 1u
+            /* DATA32 ecn_fixup_instr */
+            ecn_fixup_instr = EVAL_ecn_fixup_instr();
+            *tp++=0x00000000 | ((ecn_fixup_instr)&0xffffffffu)<<0;
+#endif
+#if TKB_HAVE_CHACHAPOLY_HW30 == 1u
+            /* INS      NONE, PAD_ZERO, 0, 160 */
+            *tp++=0x20000000 | ((0u)&0x1u)<<16 | ((160u)&0xffffu)<<0;
+#else
+            /* INS      NONE, PAD_ZERO, 0, 16 */
+            *tp++=0x20000000 | ((0u)&0x1u)<<16 | ((16u)&0xffffu)<<0;
+#endif
+        }
+        /* DIR      CRYPTHASH,packetsize - ivlen - 8 - icvlen - bypass - hdrlen,LAST,LASTHASH */
+        *tp++=0x0f020000 | ((-8u+packetsize-ivlen-icvlen-bypass-hdrlen)&0x1ffffu)<<0;
+        /* RETR     NONE,ORIG_HASH,icvlen,LASTHASHPKT */
+        *tp++=0x40e60000 | ((icvlen)&0x1ffffu)<<0;
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 39: /* ssltls_ccm_out */
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+        if (packetsize < bypass+hdrlen)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for SSLTLS outbound CCM\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        if (hdrlen > 0u)
+        {
+            /* DIR OUT,hdrlen */
+            *tp++=0x01000000 | ((hdrlen)&0x1ffffu)<<0;
+        }
+        capwap_out = EVAL_capwap_out();
+        if (capwap_out != 0u)
+        {
+            /* INS OUT,ORIG_TOKEN,4 */
+            *tp++=0x21d80000 | ((4u)&0x1ffffu)<<0;
+            /* DATA32 0x0000001  ; Insert DTLS/CAPWAP header. */
+            *tp++=0x00000000 | ((1u)&0xffffffffu)<<0;
+        }
+        /* INS HASHONLY,PAD_CONST,salt,1 ; Form b0 block, flag byte */
+        salt = EVAL_salt();
+        *tp++=0x22100000 | ((salt)&0xffu)<<9 | ((1u)&0x1ffu)<<0;
+        /* INS HASHONLY,ORIG_IV0,4 */
+        *tp++=0x22a00000 | ((4u)&0x1ffffu)<<0;
+        /* INS HASHONLY,ORIG_EXTSEQNUM,4 */
+        *tp++=0x22580000 | ((4u)&0x1ffffu)<<0;
+        /* INS HASHONLY,ORIG_SEQNUM,4 */
+        *tp++=0x22500000 | ((4u)&0x1ffffu)<<0;
+        /* INS HASHONLY,ORIG_TOKEN,5 */
+        *tp++=0x22d80000 | ((5u)&0x1ffffu)<<0;
+        /* DATA32 swaplen3                 ; 3-byte length in b0 block. */
+        swaplen3 = EVAL_swaplen3();
+        *tp++=0x00000000 | ((swaplen3)&0xffffffffu)<<0;
+        /* DATA32 0x0d                     ; and swapped 2-byte AAD length just after */
+        *tp++=0x00000000 | ((13u)&0xffffffffu)<<0;
+        /* INS HASHONLY,ORIG_EXTSEQNUM,4 */
+        *tp++=0x22580000 | ((4u)&0x1ffffu)<<0;
+        /* INS HASHONLY,ORIG_SEQNUM,4 */
+        *tp++=0x22500000 | ((4u)&0x1ffffu)<<0;
+        /* INS HASH,PAD_CONST,nextheader,1 ; Type field */
+        nextheader = EVAL_nextheader();
+        *tp++=0x23100000 | ((nextheader)&0xffu)<<9 | ((1u)&0x1ffu)<<0;
+        /* INS HASH,ORIG_SPI,2          ; For TLS/DTLS, hash version field. */
+        *tp++=0x23900000 | ((2u)&0x1ffffu)<<0;
+        extseq = EVAL_extseq();
+        if (extseq != 0u)
+        {
+            /* INS OUT,ORIG_EXTSEQNUM,4 ; Output sequence number for DTLS */
+            *tp++=0x21580000 | ((4u)&0x1ffffu)<<0;
+            /* INS OUT,ORIG_SEQNUM,4 */
+            *tp++=0x21500000 | ((4u)&0x1ffffu)<<0;
+        }
+        /* INS HASHONLY,ORIG_TOKEN,2 */
+        *tp++=0x22d80000 | ((2u)&0x1ffffu)<<0;
+        /* DATA32 swaplen                   ; Payload length to hash. */
+        swaplen = EVAL_swaplen();
+        *tp++=0x00000000 | ((swaplen)&0xffffffffu)<<0;
+        /* INS HASHONLY,PAD_ZERO,0,1        ; Pad AAD to 16 bytes. */
+        *tp++=0x22000000 | ((0u)&0x1u)<<16 | ((1u)&0xffffu)<<0;
+        /* INS OUT,ORIG_TOKEN,2 */
+        *tp++=0x21d80000 | ((2u)&0x1ffffu)<<0;
+        /* DATA32 swap_fraglen              ; Fragment length to output. */
+        swap_fraglen = EVAL_swap_fraglen();
+        *tp++=0x00000000 | ((swap_fraglen)&0xffffffffu)<<0;
+        /* INS OUT,ORIG_IV1,ivlen */
+        ivlen = EVAL_ivlen();
+        *tp++=0x21a80000 | ((ivlen)&0x1ffffu)<<0;
+        if (extseq != 0u)
+        {
+            /* REMRES bypass + hdrlen + capwap_out + 5 + 8 + 8, 16 */
+            *tp++=0xa0000000 | ((21u+bypass+hdrlen+capwap_out)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+        }
+        else
+        {
+            /* REMRES bypass + hdrlen + 5 + 8, 16 */
+            *tp++=0xa0000000 | ((13u+bypass+hdrlen)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+        }
+        /* INS CRYPT, PAD_ZERO, 0, 16 */
+        *tp++=0x25000000 | ((0u)&0x1u)<<16 | ((16u)&0xffffu)<<0;
+        if (packetsize != bypass+hdrlen)
+        {
+            /* DIR CRYPTHASH, packetsize-bypass-hdrlen,LAST */
+            *tp++=0x0f000000 | ((packetsize-bypass-hdrlen)&0x1ffffu)<<0;
+        }
+        else
+        {
+            /* INS CRYPTHASH, PAD_ZERO, 0, 0,LAST */
+            *tp++=0x2f000000 | ((0u)&0x1u)<<16 | ((0u)&0xffffu)<<0;
+        }
+        /* INS HASHONLY,PAD_ZERO,0,hashpad,LASTHASH */
+        hashpad = EVAL_hashpad();
+        *tp++=0x22020000 | ((0u)&0x1u)<<16 | ((hashpad)&0xffffu)<<0;
+        /* INS OUT,ORIG_HASH,icvlen,LASTHASHPKT */
+        icvlen = EVAL_icvlen();
+        *tp++=0x21e60000 | ((icvlen)&0x1ffffu)<<0;
+        /* VERIFY   0  ; Causes any sequence number rollover error to fail the packet. */
+        *tp++=0xd0060000 | ((0u)&0x7fu)<<0;
+        /* CTX ORIG_SEQNUM,seq_offset,2 */
+        seq_offset = EVAL_seq_offset();
+        *tp++=0xe0560800 | ((seq_offset)&0xffu)<<0 | ((2u)&0xfu)<<24;
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 40: /* ssltls_ccm_in */
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+        paylen = EVAL_paylen();
+        if (paylen == 4294967295u)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for SSLTLS inbound CCM\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        if (hdrlen > 0u)
+        {
+            /* DIR OUT,hdrlen */
+            *tp++=0x01000000 | ((hdrlen)&0x1ffffu)<<0;
+        }
+        capwap_in = EVAL_capwap_in();
+        if (capwap_in != 0u)
+        {
+            /* REM 4  ; Remove DTLS/CAPWAP header. */
+            *tp++=0x40d80000 | ((4u)&0x1ffffu)<<0;
+        }
+        /* INS HASHONLY,PAD_CONST,salt,1 ; Form b0 block, flag byte */
+        salt = EVAL_salt();
+        *tp++=0x22100000 | ((salt)&0xffu)<<9 | ((1u)&0x1ffu)<<0;
+        /* INS HASHONLY,ORIG_IV0,4 */
+        *tp++=0x22a00000 | ((4u)&0x1ffffu)<<0;
+        ohdrlen = EVAL_ohdrlen();
+        if (ohdrlen > hdrlen)
+        {
+            /* RETR OUT,ORIG_SPI,3    ; Extract Type and Version. */
+            *tp++=0x41900000 | ((3u)&0x1ffffu)<<0;
+            /* RETR NONE,ORIG_EXTSEQNUM_RES2,4 ; Extract seq numbers from packet. */
+            *tp++=0x40480000 | ((4u)&0x1ffffu)<<0;
+            /* RETR NONE,ORIG_SEQNUM_RES2,4 */
+            *tp++=0x40400000 | ((4u)&0x1ffffu)<<0;
+            /* REM 2                    ; Remove fragment length. */
+            *tp++=0x40d80000 | ((2u)&0x1ffffu)<<0;
+            /* RETR HASHONLY,ORIG_IV1,ivlen */
+            ivlen = EVAL_ivlen();
+            *tp++=0x42a80000 | ((ivlen)&0x1ffffu)<<0;
+            /* INS HASHONLY,ORIG_TOKEN,5 */
+            *tp++=0x22d80000 | ((5u)&0x1ffffu)<<0;
+            /* DATA32 swaplen3                 ; 3-byte length in b0 block. */
+            swaplen3 = EVAL_swaplen3();
+            *tp++=0x00000000 | ((swaplen3)&0xffffffffu)<<0;
+            /* DATA32 0x0d                     ; and swapped 2-byte AAD length just after */
+            *tp++=0x00000000 | ((13u)&0xffffffffu)<<0;
+            /* INS HASHONLY, ORIG_EXTSEQNUM_RES2,4 */
+            *tp++=0x22480000 | ((4u)&0x1ffffu)<<0;
+            /* INS HASHONLY, ORIG_SEQNUM_RES2,4 */
+            *tp++=0x22400000 | ((4u)&0x1ffffu)<<0;
+            /* INS HASHONLY,ORIG_SPI_RES,3  ; Hash type and version. */
+            *tp++=0x22c00000 | ((3u)&0x1ffffu)<<0;
+            /* INS HASH,ORIG_TOKEN,2 */
+            *tp++=0x23d80000 | ((2u)&0x1ffffu)<<0;
+            /* DATA32 swaplen */
+            swaplen = EVAL_swaplen();
+            *tp++=0x00000000 | ((swaplen)&0xffffffffu)<<0;
+            if (ohdrlen-hdrlen > 5u)
+            {
+                /* INS OUT,PAD_ZERO,0,ohdrlen-hdrlen-5 */
+                *tp++=0x21000000 | ((0u)&0x1u)<<16 | ((-5u+ohdrlen-hdrlen)&0xffffu)<<0;
+            }
+        }
+        else
+        {
+            /* RETR NONE,ORIG_SPI,3    ; Extract Type and Version. */
+            *tp++=0x40900000 | ((3u)&0x1ffffu)<<0;
+            extseq = EVAL_extseq();
+            if (extseq != 0u)
+            {
+                /* RETR NONE,ORIG_EXTSEQNUM_RES2,4 ; Extract seq numbers from packet. */
+                *tp++=0x40480000 | ((4u)&0x1ffffu)<<0;
+                /* RETR NONE,ORIG_SEQNUM_RES2,4 */
+                *tp++=0x40400000 | ((4u)&0x1ffffu)<<0;
+            }
+            /* REM 2                    ; Remove fragment length. */
+            *tp++=0x40d80000 | ((2u)&0x1ffffu)<<0;
+            /* RETR HASHONLY,ORIG_IV1,ivlen */
+            ivlen = EVAL_ivlen();
+            *tp++=0x42a80000 | ((ivlen)&0x1ffffu)<<0;
+            /* INS HASHONLY,ORIG_TOKEN,5 */
+            *tp++=0x22d80000 | ((5u)&0x1ffffu)<<0;
+            /* DATA32 swaplen3                 ; 3-byte length in b0 block. */
+            swaplen3 = EVAL_swaplen3();
+            *tp++=0x00000000 | ((swaplen3)&0xffffffffu)<<0;
+            /* DATA32 0x0d                     ; and swapped 2-byte AAD length just after */
+            *tp++=0x00000000 | ((13u)&0xffffffffu)<<0;
+            if (extseq != 0u)
+            {
+                /* INS HASHONLY,ORIG_EXTSEQNUM_RES2,4  ; Extract from SA. */
+                *tp++=0x22480000 | ((4u)&0x1ffffu)<<0;
+                /* INS HASHONLY,ORIG_SEQNUM_RES2,4 */
+                *tp++=0x22400000 | ((4u)&0x1ffffu)<<0;
+            }
+            else
+            {
+                /* INS HASHONLY,ORIG_EXTSEQNUM,4  ; Extract from SA. */
+                *tp++=0x22580000 | ((4u)&0x1ffffu)<<0;
+                /* INS HASHONLY,ORIG_SEQNUM,4 */
+                *tp++=0x22500000 | ((4u)&0x1ffffu)<<0;
+            }
+            /* INS HASHONLY,ORIG_SPI_RES,3  ; Hash type and version. */
+            *tp++=0x22c00000 | ((3u)&0x1ffffu)<<0;
+            /* INS HASHONLY,ORIG_TOKEN,2 */
+            *tp++=0x22d80000 | ((2u)&0x1ffffu)<<0;
+            /* DATA32 swaplen */
+            swaplen = EVAL_swaplen();
+            *tp++=0x00000000 | ((swaplen)&0xffffffffu)<<0;
+        }
+        /* INS HASHONLY,PAD_ZERO,0,1      ; Pad AAD to 16 bytes. */
+        *tp++=0x22000000 | ((0u)&0x1u)<<16 | ((1u)&0xffffu)<<0;
+        /* REMRES bypass+ohdrlen, 16 */
+        *tp++=0xa0000000 | ((bypass+ohdrlen)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+        /* INS CRYPT, PAD_ZERO, 0, 16 */
+        *tp++=0x25000000 | ((0u)&0x1u)<<16 | ((16u)&0xffffu)<<0;
+        /* DIR CRYPTHASH, paylen,LAST */
+        *tp++=0x0f000000 | ((paylen)&0x1ffffu)<<0;
+        /* INS HASHONLY,PAD_ZERO,0,hashpad,LASTHASH */
+        hashpad = EVAL_hashpad();
+        *tp++=0x22020000 | ((0u)&0x1u)<<16 | ((hashpad)&0xffffu)<<0;
+        /* RETR NONE,ORIG_HASH,icvlen,LASTHASHPKT */
+        icvlen = EVAL_icvlen();
+        *tp++=0x40e60000 | ((icvlen)&0x1ffffu)<<0;
+        extseq = EVAL_extseq();
+        if (extseq == 0u)
+        {
+            /* VERIFY icvlen,H */
+            *tp++=0xd0070000 | ((icvlen)&0x7fu)<<0;
+            /* CTX ORIG_SEQNUM,seq_offset,2,P */
+            seq_offset = EVAL_seq_offset();
+            *tp++=0xe0561800 | ((seq_offset)&0xffu)<<0 | ((2u)&0xfu)<<24;
+        }
+        else if (extseq == 1u)
+        {
+            /* VERIFY icvlen,H */
+            *tp++=0xd0070000 | ((icvlen)&0x7fu)<<0;
+        }
+        else
+        {
+            /* VERIFY icvlen,S,H */
+            *tp++=0xd8070000 | ((icvlen)&0x7fu)<<0;
+            /* CTX ORIG_SEQNUM,seq_offset,1+extseq,P */
+            seq_offset = EVAL_seq_offset();
+            *tp++=0xe0561800 | ((seq_offset)&0xffu)<<0 | ((1u+extseq)&0xfu)<<24;
+        }
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 41: /* tls13_ccm_out */
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+        if (packetsize < bypass)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for SSLTLS outbound GCM\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        /* INS HASHONLY,PAD_CONST,salt,1 ; Form b0 block, flag byte */
+        salt = EVAL_salt();
+        *tp++=0x22100000 | ((salt)&0xffu)<<9 | ((1u)&0x1ffu)<<0;
+        /* INS HASHONLY,ORIG_IV0,12 */
+        *tp++=0x22a00000 | ((12u)&0x1ffffu)<<0;
+        /* INS HASHONLY,ORIG_TOKEN,5 */
+        *tp++=0x22d80000 | ((5u)&0x1ffffu)<<0;
+        /* DATA32 swaplen3_tls13_out       ; 3-byte length in b0 block. */
+        swaplen3_tls13_out = EVAL_swaplen3_tls13_out();
+        *tp++=0x00000000 | ((swaplen3_tls13_out)&0xffffffffu)<<0;
+        /* DATA32 0x05                     ; and swapped 2-byte AAD length just after */
+        *tp++=0x00000000 | ((5u)&0xffffffffu)<<0;
+        /* INS HASH,PAD_CONST,0x17,1    ; Type field */
+        *tp++=0x23100000 | ((23u)&0xffu)<<9 | ((1u)&0x1ffu)<<0;
+        /* INS HASH,ORIG_SPI,2          ; For TLS1.3 hash fixed type/version field. */
+        *tp++=0x23900000 | ((2u)&0x1ffffu)<<0;
+        /* INS HASH,ORIG_TOKEN,2 */
+        *tp++=0x23d80000 | ((2u)&0x1ffffu)<<0;
+        /* DATA32 swap_fraglen_tls13     ; Fragment length to output and hash. */
+        swap_fraglen_tls13 = EVAL_swap_fraglen_tls13();
+        *tp++=0x00000000 | ((swap_fraglen_tls13)&0xffffffffu)<<0;
+        /* INS HASHONLY,PAD_ZERO,0,9     ; Pad AAD block */
+        *tp++=0x22000000 | ((0u)&0x1u)<<16 | ((9u)&0xffffu)<<0;
+        /* REMRES bypass + 5, 16 */
+        *tp++=0xa0000000 | ((5u+bypass)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+        /* INS CRYPT, PAD_ZERO, 0, 16 */
+        *tp++=0x25000000 | ((0u)&0x1u)<<16 | ((16u)&0xffffu)<<0;
+        /* DIR CRYPTHASH, packetsize-bypass */
+        *tp++=0x07000000 | ((packetsize-bypass)&0x1ffffu)<<0;
+        count = EVAL_count();
+        if (count == 0u)
+        {
+            /* INS CRYPTHASH, PAD_CONST, nextheader, 1,LAST */
+            nextheader = EVAL_nextheader();
+            *tp++=0x2f100000 | ((nextheader)&0xffu)<<9 | ((1u)&0x1ffu)<<0;
+        }
+        else
+        {
+            /* INS CRYPTHASH, PAD_CONST, nextheader, 1 */
+            nextheader = EVAL_nextheader();
+            *tp++=0x27100000 | ((nextheader)&0xffu)<<9 | ((1u)&0x1ffu)<<0;
+            /* INS CRYPTHASH, PAD_ZERO, 0, count, LAST */
+            *tp++=0x2f000000 | ((0u)&0x1u)<<16 | ((count)&0xffffu)<<0;
+        }
+        /* INS HASHONLY,PAD_ZERO, 0, hashpad_tls13_out, LASTHASH */
+        hashpad_tls13_out = EVAL_hashpad_tls13_out();
+        *tp++=0x22020000 | ((0u)&0x1u)<<16 | ((hashpad_tls13_out)&0xffffu)<<0;
+        /* INS OUT,ORIG_HASH,icvlen,LASTHASHPKT */
+        icvlen = EVAL_icvlen();
+        *tp++=0x21e60000 | ((icvlen)&0x1ffffu)<<0;
+        /* VERIFY   0  ; Causes any sequence number rollover error to fail the packet. */
+        *tp++=0xd0060000 | ((0u)&0x7fu)<<0;
+        /* CTX ORIG_SEQNUM,seq_offset,2 */
+        seq_offset = EVAL_seq_offset();
+        *tp++=0xe0560800 | ((seq_offset)&0xffu)<<0 | ((2u)&0xfu)<<24;
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 42: /* tls13_ccm_in */
+#if TKB_HAVE_PROTO_SSLTLS == 1u
+        icvlen = EVAL_icvlen();
+        if (packetsize < 5u+bypass+icvlen)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for SSLTLS inbound GCM\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        /* INS HASHONLY,PAD_CONST,salt,1 ; Form b0 block, flag byte */
+        salt = EVAL_salt();
+        *tp++=0x22100000 | ((salt)&0xffu)<<9 | ((1u)&0x1ffu)<<0;
+        /* INS HASHONLY,ORIG_IV0,12 */
+        *tp++=0x22a00000 | ((12u)&0x1ffffu)<<0;
+        /* INS HASHONLY,ORIG_TOKEN,5 */
+        *tp++=0x22d80000 | ((5u)&0x1ffffu)<<0;
+        /* DATA32 swaplen3_tls13_in        ; 3-byte length in b0 block. */
+        swaplen3_tls13_in = EVAL_swaplen3_tls13_in();
+        *tp++=0x00000000 | ((swaplen3_tls13_in)&0xffffffffu)<<0;
+        /* DATA32 0x05                     ; and swapped 2-byte AAD length just after */
+        *tp++=0x00000000 | ((5u)&0xffffffffu)<<0;
+        /* DIR HASHONLY,5                  ; Hash type and version number and length */
+        *tp++=0x02000000 | ((5u)&0x1ffffu)<<0;
+        /* INS HASHONLY,PAD_ZERO,0,9       ; Pad AAD block */
+        *tp++=0x22000000 | ((0u)&0x1u)<<16 | ((9u)&0xffffu)<<0;
+        /* REMRES bypass, 16 */
+        *tp++=0xa0000000 | ((bypass)&0xffffu)<<0 | ((16u)&0x3fu)<<19;
+        /* INS CRYPT, PAD_ZERO, 0, 16 */
+        *tp++=0x25000000 | ((0u)&0x1u)<<16 | ((16u)&0xffffu)<<0;
+        /* DIR CRYPTHASH, packetsize-bypass-icvlen-5,LAST */
+        *tp++=0x0f000000 | ((-5u+packetsize-bypass-icvlen)&0x1ffffu)<<0;
+        /* INS HASHONLY,PAD_ZERO, 0, hashpad_tls13_in, LASTHASH */
+        hashpad_tls13_in = EVAL_hashpad_tls13_in();
+        *tp++=0x22020000 | ((0u)&0x1u)<<16 | ((hashpad_tls13_in)&0xffffu)<<0;
+        /* RETR NONE,ORIG_HASH,icvlen,LASTHASHPKT */
+        *tp++=0x40e60000 | ((icvlen)&0x1ffffu)<<0;
+        /* VERIFY icvlen,H */
+        *tp++=0xd0070000 | ((icvlen)&0x7fu)<<0;
+        /* CTX ORIG_SEQNUM,seq_offset,2,P */
+        seq_offset = EVAL_seq_offset();
+        *tp++=0xe0561800 | ((seq_offset)&0xffu)<<0 | ((2u)&0xfu)<<24;
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 43: /* basic_hmac_precompute */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        if (packetsize < bypass)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for basic hash precompute\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        /* DIR HASHONLY,packetsize-bypass,LASTHASH */
+        *tp++=0x02020000 | ((packetsize-bypass)&0x1ffffu)<<0;
+        /* INS OUT, ORIG_HASH,hstatelen_bytes */
+        hstatelen_bytes = EVAL_hstatelen_bytes();
+        *tp++=0x21e00000 | ((hstatelen_bytes)&0x1ffffu)<<0;
+        /* INS NONE,PAD_ZERO, 0, 0 */
+        *tp++=0x20000000 | ((0u)&0x1u)<<16 | ((0u)&0xffffu)<<0;
+        /* INS OUT,ORIG_HASH,hstatelen_bytes,LASTHASHPKT */
+        *tp++=0x21e60000 | ((hstatelen_bytes)&0x1ffffu)<<0;
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 44: /* basic_hmac_ctxprepare */
+#if TKB_HAVE_PROTO_BASIC == 1u
+        if (packetsize < bypass)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for basic hash precompute\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        /* DIR HASHONLY,packetsize-bypass,LASTHASH */
+        *tp++=0x02020000 | ((packetsize-bypass)&0x1ffffu)<<0;
+        /* INS NONE, ORIG_HASH,hstatelen_bytes */
+        hstatelen_bytes = EVAL_hstatelen_bytes();
+        *tp++=0x20e00000 | ((hstatelen_bytes)&0x1ffffu)<<0;
+        /* INS NONE,PAD_ZERO, 0, 0 */
+        *tp++=0x20000000 | ((0u)&0x1u)<<16 | ((0u)&0xffffu)<<0;
+        /* INS NONE,ORIG_HASH,hstatelen_bytes,LASTHASHPKT */
+        *tp++=0x20e60000 | ((hstatelen_bytes)&0x1ffffu)<<0;
+        /* CTX ORIG_HASH_INNER,digest_offset,hstatelen,P,F */
+        digest_offset = EVAL_digest_offset();
+        hstatelen = EVAL_hstatelen();
+        *tp++=0xe0ee3800 | ((digest_offset)&0xffu)<<0 | ((hstatelen)&0xfu)<<24;
+        /* CTX ORIG_HASH,digest_offset+hstatelen,hstatelen,P,F */
+        *tp++=0xe0e63800 | ((digest_offset+hstatelen)&0xffu)<<0 | ((hstatelen)&0xfu)<<24;
+#else
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+#endif
+        break;
+    case 45: /* basic_bypass */
+        if (packetsize < bypass)
+        {
+            LOG_WARN("TokenBuilder: bad packet, too short for basic bypass\n");
+            rc = TKB_BAD_PACKET; goto error;
+        }
+        /* DIR OUT,packetsize-bypass,LASTHASHPKT */
+        *tp++=0x01060000 | ((packetsize-bypass)&0x1ffffu)<<0;
+        break;
+    default:
+        LOG_WARN("TokenBuilder: bad protocol\n");
+        rc = TKB_BAD_PROTOCOL; goto error;
+    }
+#if TKB_HAVE_PROTO_IPSEC == 1u
+#if TKB_HAVE_EXTENDED_IPSEC == 1u
+    hproto = EVAL_hproto();
+    switch(hproto)
+    {
+    case 6: /* ipv4_in_transp */
+    case 26: /* ipv4_in_transp_natt */
+        /* INSRES 2+bypass,7,L,NH,CS,LASTINS */
+        *tp++=0xae050000 | ((2u+bypass)&0xffffu)<<0 | ((7u)&0x3fu)<<19;
+        break;
+    case 12: /* ipv6_in_transp */
+    case 32: /* ipv6_in_transp_natt */
+        /* INSRES 4+bypass,40,L,NOUPDCHK */
+        *tp++=0xa8030000 | ((4u+bypass)&0xffffu)<<0 | ((40u)&0x3fu)<<19;
+        /* INSRES bypass+prev_nhoffset,0,NH,NOUPDCHK,LASTINS */
+        prev_nhoffset = EVAL_prev_nhoffset();
+        *tp++=0xa4070000 | ((bypass+prev_nhoffset)&0xffffu)<<0 | ((0u)&0x3fu)<<19;
+        break;
+    }
+#endif
+    switch(proto)
+    {
+    case 1: /* esp_in */
+    case 3: /* esp_in_ccm */
+    case 5: /* esp_in_gcm */
+    case 7: /* esp_in_gmac */
+    case 36: /* esp_in_chachapoly */
+        icvlen = EVAL_icvlen();
+        if (icvlen > 0u)
+        {
+            antireplay = EVAL_antireplay();
+            if (antireplay > 12u)
+            {
+                /* VERIFY   icvlen,S,SP,P,H */
+                *tp++=0xdd070000 | ((icvlen)&0x7fu)<<0;
+                extseq = EVAL_extseq();
+                if (extseq > 0u)
+                {
+                    /* CTX     ORIG_SEQNUM,seq_offset,0,P */
+                    seq_offset = EVAL_seq_offset();
+                    *tp++=0xe0561800 | ((seq_offset)&0xffu)<<0 | ((0u)&0xfu)<<24;
+                }
+                else
+                {
+                    /* CTX     ORIG_SEQNUM_INBOUND,seq_offset,0,P */
+                    seq_offset = EVAL_seq_offset();
+                    *tp++=0xe02e1800 | ((seq_offset)&0xffu)<<0 | ((0u)&0xfu)<<24;
+                }
+            }
+            else if (antireplay != 0u)
+            {
+                /* VERIFY   icvlen,S,SP,P,H */
+                *tp++=0xdd070000 | ((icvlen)&0x7fu)<<0;
+                extseq = EVAL_extseq();
+                if (extseq > 0u)
+                {
+                    /* CTX     ORIG_SEQNUM,seq_offset,2+antireplay,P */
+                    seq_offset = EVAL_seq_offset();
+                    *tp++=0xe0561800 | ((seq_offset)&0xffu)<<0 | ((2u+antireplay)&0xfu)<<24;
+                }
+                else
+                {
+                    /* CTX     ORIG_SEQNUM_INBOUND,seq_offset,1+antireplay,P */
+                    seq_offset = EVAL_seq_offset();
+                    *tp++=0xe02e1800 | ((seq_offset)&0xffu)<<0 | ((1u+antireplay)&0xfu)<<24;
+                }
+            }
+            else
+            {
+                /* VERIFY   icvlen,SP,P,H */
+                *tp++=0xd5070000 | ((icvlen)&0x7fu)<<0;
+            }
+        }
+        else
+        {
+            /* VERIFY   0,SP,P */
+            *tp++=0xd5060000 | ((0u)&0x7fu)<<0;
+        }
+        break;
+    }
+#endif
+
+
+    Switch_Proto(TokenContext_Internal_p);
+
+error:
+    if (rc != TKB_STATUS_OK)
+    {
+        tp = (uint32_t *)Token_p + TKB_TOKEN_HEADER_WORD_COUNT;
+        /* Include CCW0 and CCW1 in token. */
+        *tp++ = 0;
+        *tp++ = 0;
+        /* DIR OUT,PacketByteCount,LASTHASHPKT pass packet unchanged */
+        *tp++ = 0x01060000 | (PacketByteCount & 0x1ffff);
+        *TokenHeaderWord_p = TKB_HEADER_DEFAULT | TKB_HEADER_C | (PacketByteCount & 0x1ffff);
+    }
+    *TokenWord32Count_p = tp - (uint32_t*)Token_p;
+    return rc;
+}
+
+/* end of file token_builder_core.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip201.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip201.c
new file mode 100644
index 0000000..753a1cb
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip201.c
@@ -0,0 +1,567 @@
+/* eip201_sl.c
+ *
+ * Driver Library for the Security-IP-201 Advanced Interrupt Controller.
+ */
+
+/*****************************************************************************
+* Copyright (c) 2007-2020 by Rambus, Inc. and/or its subsidiaries.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+// Top-level Interrupt controller configuration
+#include "c_eip201.h"           // configuration
+
+// Driver Framework Basic Defs API
+#include "basic_defs.h"         // uint32_t, inline, etc.
+
+// Interrupt controller API
+#include "eip201.h"             // the API we will implement
+
+// Driver Framework Device API
+#include "device_rw.h"          // Device_Read32/Write32
+
+// create a constant where all unused interrupts are '1'
+#if (EIP201_STRICT_ARGS_MAX_NUM_OF_INTERRUPTS < 32)
+#define EIP201_NOTUSEDIRQ_MASK (uint32_t) \
+                    (~((1 << EIP201_STRICT_ARGS_MAX_NUM_OF_INTERRUPTS)-1))
+#else
+#define EIP201_NOTUSEDIRQ_MASK 0
+#endif
+
+#ifdef EIP201_STRICT_ARGS
+#define EIP201_CHECK_IF_IRQ_SUPPORTED(_irqs) \
+        if (_irqs & EIP201_NOTUSEDIRQ_MASK) \
+            return EIP201_STATUS_UNSUPPORTED_IRQ;
+#else
+#define EIP201_CHECK_IF_IRQ_SUPPORTED(_irqs)
+#endif /* EIP201_STRICT_ARGS */
+
+
+/*----------------------------------------------------------------------------
+ *  EIP201 registers
+ */
+enum
+{
+    EIP201_REGISTER_OFFSET_POL_CTRL     = EIP201_LO_REG_BASE+0,
+    EIP201_REGISTER_OFFSET_TYPE_CTRL    = EIP201_LO_REG_BASE+4,
+    EIP201_REGISTER_OFFSET_ENABLE_CTRL  = EIP201_LO_REG_BASE+8,
+    EIP201_REGISTER_OFFSET_RAW_STAT     = EIP201_HI_REG_BASE+12,
+    EIP201_REGISTER_OFFSET_ENABLE_SET   = EIP201_LO_REG_BASE+12,
+    EIP201_REGISTER_OFFSET_ENABLED_STAT = EIP201_HI_REG_BASE+16,
+    EIP201_REGISTER_OFFSET_ACK          = EIP201_LO_REG_BASE+16,
+    EIP201_REGISTER_OFFSET_ENABLE_CLR   = EIP201_LO_REG_BASE+20,
+    EIP201_REGISTER_OFFSET_OPTIONS      = EIP201_HI_REG_BASE+24,
+    EIP201_REGISTER_OFFSET_VERSION      = EIP201_HI_REG_BASE+28
+};
+
+// this implementation supports only the EIP-201 HW1.1 and HW1.2
+// 0xC9  = 201
+// 0x39  = binary inverse of 0xC9
+#define EIP201_SIGNATURE      0x36C9
+#define EIP201_SIGNATURE_MASK 0xffff
+
+/*----------------------------------------------------------------------------
+ * EIP201_Read32
+ *
+ * This routine reads from a Register location in the EIP201, applying
+ * endianness swapping when required (depending on configuration).
+ */
+static inline int
+EIP201_Read32(
+        Device_Handle_t Device,
+        const unsigned int Offset,
+        uint32_t * const Value_p)
+{
+    return Device_Read32Check(Device, Offset, Value_p);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_Write32
+ *
+ * This routine writes to a Register location in the EIP201, applying
+ * endianness swapping when required (depending on configuration).
+ */
+static inline int
+EIP201_Write32(
+        Device_Handle_t Device,
+        const unsigned int Offset,
+        const uint32_t Value)
+{
+    return Device_Write32(Device, Offset, Value);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_Config_Change
+ */
+#ifndef EIP201_REMOVE_CONFIG_CHANGE
+EIP201_Status_t
+EIP201_Config_Change(
+        Device_Handle_t Device,
+        const EIP201_SourceBitmap_t Sources,
+        const EIP201_Config_t Config)
+{
+    uint32_t Value;
+    uint32_t NewPol = 0;
+    uint32_t NewType = 0;
+    int rc;
+    EIP201_CHECK_IF_IRQ_SUPPORTED(Sources);
+
+    /*
+        EIP201_CONFIG_ACTIVE_LOW,       // Type=0, Pol=0
+        EIP201_CONFIG_ACTIVE_HIGH,      // Type=0, Pol=1
+        EIP201_CONFIG_FALLING_EDGE,     // Type=1, Pol=0
+        EIP201_CONFIG_RISING_EDGE       // Type=1, Pol=1
+    */
+
+    // do we want Type=1?
+    if (Config == EIP201_CONFIG_FALLING_EDGE ||
+        Config == EIP201_CONFIG_RISING_EDGE)
+    {
+        NewType = Sources;
+    }
+
+    // do we want Pol=1?
+    if (Config == EIP201_CONFIG_ACTIVE_HIGH ||
+        Config == EIP201_CONFIG_RISING_EDGE)
+    {
+        NewPol = Sources;
+    }
+
+    if (Sources)
+    {
+        // modify polarity register
+        rc = EIP201_Read32(Device, EIP201_REGISTER_OFFSET_POL_CTRL, &Value);
+        if (rc) return rc;
+        Value &= ~Sources;
+        Value |= NewPol;
+        rc = EIP201_Write32(Device, EIP201_REGISTER_OFFSET_POL_CTRL, Value);
+        if (rc) return rc;
+
+        // modify type register
+        rc = EIP201_Read32(Device, EIP201_REGISTER_OFFSET_TYPE_CTRL, &Value);
+        if (rc) return rc;
+        Value &= ~Sources;
+        Value |= NewType;
+        rc = EIP201_Write32(Device, EIP201_REGISTER_OFFSET_TYPE_CTRL, Value);
+        if (rc) return rc;
+    }
+
+    return EIP201_STATUS_SUCCESS;
+}
+#endif /* EIP201_REMOVE_CONFIG_CHANGE */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_Config_Read
+ */
+#ifndef EIP201_REMOVE_CONFIG_READ
+
+static const EIP201_Config_t EIP201_Setting2Config[4] =
+{
+    EIP201_CONFIG_ACTIVE_LOW,       // Type=0, Pol=0
+    EIP201_CONFIG_ACTIVE_HIGH,      // Type=0, Pol=1
+    EIP201_CONFIG_FALLING_EDGE,     // Type=1, Pol=0
+    EIP201_CONFIG_RISING_EDGE       // Type=1, Pol=1
+};
+
+EIP201_Config_t
+EIP201_Config_Read(
+        Device_Handle_t Device,
+        const EIP201_Source_t Source)
+{
+    uint32_t Value;
+    unsigned char Setting = 0;
+    int rc = 0;
+
+    rc = EIP201_Read32(Device, EIP201_REGISTER_OFFSET_TYPE_CTRL, &Value);
+    if (rc) return rc;
+    if (Value & Source)
+    {
+        // Type=1, thus edge
+        Setting += 2;
+    }
+
+    EIP201_Read32(Device, EIP201_REGISTER_OFFSET_POL_CTRL, &Value);
+    if (Value & Source)
+    {
+        // Pol=1, this rising edge or active high
+        Setting++;
+    }
+
+    return EIP201_Setting2Config[Setting];
+}
+#endif /* EIP201_REMOVE_CONFIG_READ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_SourceMask_EnableSource
+ *
+ * See header file for function specifications.
+ */
+#ifndef EIP201_REMOVE_SOURCEMASK_ENABLESOURCE
+EIP201_Status_t
+EIP201_SourceMask_EnableSource(
+        Device_Handle_t Device,
+        const EIP201_SourceBitmap_t Sources)
+{
+    int rc;
+    EIP201_CHECK_IF_IRQ_SUPPORTED(Sources);
+
+    rc = EIP201_Write32(
+            Device,
+            EIP201_REGISTER_OFFSET_ENABLE_SET,
+            Sources);
+
+    return rc;
+}
+#endif /* EIP201_REMOVE_SOURCEMASK_ENABLESOURCE */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_SourceMask_DisableSource
+ */
+#ifndef EIP201_REMOVE_SOURCEMASK_DISABLESOURCE
+EIP201_Status_t
+EIP201_SourceMask_DisableSource(
+        Device_Handle_t Device,
+        const EIP201_SourceBitmap_t Sources)
+{
+    int rc;
+    rc = EIP201_Write32(
+            Device,
+            EIP201_REGISTER_OFFSET_ENABLE_CLR,
+            Sources);
+
+    return rc;
+}
+#endif /* EIP201_REMOVE_SOURCEMASK_DISABLESOURCE */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_SourceMask_SourceIsEnabled
+ */
+#ifndef EIP201_REMOVE_SOURCEMASK_SOURCEISENABLED
+bool
+EIP201_SourceMask_SourceIsEnabled(
+        Device_Handle_t Device,
+        const EIP201_Source_t Source)
+{
+    int rc;
+    uint32_t SourceMasks;
+
+    rc =  EIP201_Read32(
+                        Device,
+        EIP201_REGISTER_OFFSET_ENABLE_CTRL, &SourceMasks);
+
+    if (rc) return false;
+    if (SourceMasks & Source)
+        return true;
+
+    return false;
+}
+#endif /* EIP201_REMOVE_SOURCEMASK_SOURCEISENABLED */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_SourceMask_ReadAll
+ */
+#ifndef EIP201_REMOVE_SOURCEMASK_READALL
+EIP201_SourceBitmap_t
+EIP201_SourceMask_ReadAll(
+        Device_Handle_t Device)
+{
+    uint32_t Value;
+    EIP201_Read32(Device, EIP201_REGISTER_OFFSET_ENABLE_CTRL, &Value);
+    return Value;
+}
+#endif /* EIP201_REMOVE_SOURCEMASK_READALL */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_SourceStatus_IsEnabledSourcePending
+ */
+#ifndef EIP201_REMOVE_SOURCESTATUS_ISENABLEDSOURCEPENDING
+bool
+EIP201_SourceStatus_IsEnabledSourcePending(
+        Device_Handle_t Device,
+        const EIP201_Source_t Source)
+{
+    uint32_t Statuses;
+    int rc;
+
+    rc = EIP201_Read32(Device, EIP201_REGISTER_OFFSET_ENABLED_STAT, &Statuses);
+    if (rc) return false;
+
+    if (Statuses & Source)
+        return true;
+
+    return false;
+}
+#endif /* EIP201_REMOVE_SOURCESTATUS_ISENABLEDSOURCEPENDING */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_SourceStatus_IsRawSourcePending
+ */
+#ifndef EIP201_REMOVE_SOURCESTATUS_ISRAWSOURCEPENDING
+bool
+EIP201_SourceStatus_IsRawSourcePending(
+        Device_Handle_t Device,
+        const EIP201_Source_t Source)
+{
+    uint32_t Statuses;
+    int rc;
+
+    rc = EIP201_Read32(Device, EIP201_REGISTER_OFFSET_RAW_STAT, &Statuses);
+    if (rc) return false;
+
+    if (Statuses & Source)
+        return true;
+
+    return false;
+}
+#endif /* EIP201_REMOVE_SOURCESTATUS_ISRAWSOURCEPENDING */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_SourceStatus_ReadAllEnabled
+ */
+#ifndef EIP201_REMOVE_SOURCESTATUS_READALLENABLED
+EIP201_SourceBitmap_t
+EIP201_SourceStatus_ReadAllEnabled(
+        Device_Handle_t Device)
+{
+    uint32_t Value;
+    EIP201_Read32(Device, EIP201_REGISTER_OFFSET_ENABLED_STAT, &Value);
+    return Value;
+}
+#endif /* EIP201_REMOVE_SOURCESTATUS_READALLENABLED */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_SourceStatus_ReadAllRaw
+ */
+#ifndef EIP201_REMOVE_SOURCESTATUS_READALLRAW
+EIP201_SourceBitmap_t
+EIP201_SourceStatus_ReadAllRaw(
+        Device_Handle_t Device)
+{
+    uint32_t Value;
+    EIP201_Read32(Device, EIP201_REGISTER_OFFSET_RAW_STAT, &Value);
+    return Value;
+}
+#endif /* EIP201_REMOVE_SOURCESTATUS_READALLRAW */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_SourceStatus_ReadAllEnabledCheck
+ */
+#ifndef EIP201_REMOVE_SOURCESTATUS_READALLENABLED
+EIP201_Status_t
+EIP201_SourceStatus_ReadAllEnabledCheck(
+        Device_Handle_t Device,
+        EIP201_SourceBitmap_t * const Statuses_p)
+{
+    return EIP201_Read32(Device, EIP201_REGISTER_OFFSET_ENABLED_STAT, Statuses_p);
+}
+#endif /* EIP201_REMOVE_SOURCESTATUS_READALLENABLED */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_SourceStatus_ReadAllRawCheck
+ */
+#ifndef EIP201_REMOVE_SOURCESTATUS_READALLRAW
+EIP201_Status_t
+EIP201_SourceStatus_ReadAllRawCheck(
+        Device_Handle_t Device,
+        EIP201_SourceBitmap_t * const Statuses_p)
+{
+    return EIP201_Read32(Device, EIP201_REGISTER_OFFSET_RAW_STAT, Statuses_p);
+}
+#endif /* EIP201_REMOVE_SOURCESTATUS_READALLRAW */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201Lib_Detect
+ *
+ *  Detect the presence of EIP201 hardware.
+ */
+#ifndef EIP201_REMOVE_INITIALIZE
+static EIP201_Status_t
+EIP201Lib_Detect(
+        Device_Handle_t Device)
+{
+    uint32_t Value;
+    int rc;
+
+    rc = EIP201_Read32(Device, EIP201_REGISTER_OFFSET_VERSION, &Value);
+    if (rc) return rc;
+    Value &= EIP201_SIGNATURE_MASK;
+    if ( Value != EIP201_SIGNATURE)
+        return EIP201_STATUS_UNSUPPORTED_HARDWARE_VERSION;
+
+    // Prevent interrupts going of by disabling them
+    rc = EIP201_Write32(Device, EIP201_REGISTER_OFFSET_ENABLE_CTRL, 0);
+    if (rc) return rc;
+
+    // Get the number of interrupt sources
+    rc = EIP201_Read32(Device, EIP201_REGISTER_OFFSET_OPTIONS, &Value);
+    if (rc) return rc;
+    // lowest 6 bits contain the number of inputs, which should be between 1-32
+    Value &= MASK_6_BITS;
+    if (Value == 0 || Value > 32)
+        return EIP201_STATUS_UNSUPPORTED_HARDWARE_VERSION;
+
+    return EIP201_STATUS_SUCCESS;
+}
+#endif /* EIP201_REMOVE_INITIALIZE */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_Initialize API
+ *
+ *  See header file for function specification.
+ */
+#ifndef EIP201_REMOVE_INITIALIZE
+EIP201_Status_t
+EIP201_Initialize(
+        Device_Handle_t Device,
+        const EIP201_SourceSettings_t * SettingsArray_p,
+        const unsigned int SettingsCount)
+{
+    EIP201_SourceBitmap_t ActiveLowSources = 0;
+    EIP201_SourceBitmap_t ActiveHighSources = 0;
+    EIP201_SourceBitmap_t FallingEdgeSources = 0;
+    EIP201_SourceBitmap_t RisingEdgeSources = 0;
+    EIP201_SourceBitmap_t EnabledSources = 0;
+    int rc;
+
+    // check presence of EIP201 hardware
+    rc = EIP201Lib_Detect(Device);
+    if (rc) return rc;
+
+    // disable all interrupts and set initial configuration
+    rc = EIP201_Write32(Device, EIP201_REGISTER_OFFSET_ENABLE_CTRL, 0);
+    if (rc) return rc;
+    rc = EIP201_Write32(Device, EIP201_REGISTER_OFFSET_POL_CTRL, 0);
+    if (rc) return rc;
+    rc = EIP201_Write32(Device, EIP201_REGISTER_OFFSET_TYPE_CTRL, 0);
+    if (rc) return rc;
+
+    // process the setting, if provided
+    if (SettingsArray_p != NULL)
+    {
+        unsigned int i;
+
+        for (i = 0; i < SettingsCount; i++)
+        {
+            // check
+            const EIP201_Source_t Source = SettingsArray_p[i].Source;
+            EIP201_CHECK_IF_IRQ_SUPPORTED(Source);
+
+            // determine polarity
+            switch(SettingsArray_p[i].Config)
+            {
+                case EIP201_CONFIG_ACTIVE_LOW:
+                    ActiveLowSources |= Source;
+                    break;
+
+                case EIP201_CONFIG_ACTIVE_HIGH:
+                    ActiveHighSources |= Source;
+                    break;
+
+                case EIP201_CONFIG_FALLING_EDGE:
+                    FallingEdgeSources |= Source;
+                    break;
+
+                case EIP201_CONFIG_RISING_EDGE:
+                    RisingEdgeSources |= Source;
+                    break;
+
+                default:
+                    // invalid parameter
+                    break;
+            } // switch
+
+            // determine enabled mask
+            if (SettingsArray_p[i].fEnable)
+                EnabledSources |= Source;
+        } // for
+    }
+
+    // program source configuration
+    rc = EIP201_Config_Change(
+            Device,
+            ActiveLowSources,
+            EIP201_CONFIG_ACTIVE_LOW);
+    if (rc) return rc;
+
+    rc = EIP201_Config_Change(
+            Device,
+            ActiveHighSources,
+            EIP201_CONFIG_ACTIVE_HIGH);
+    if (rc) return rc;
+
+    rc = EIP201_Config_Change(
+            Device,
+            FallingEdgeSources,
+            EIP201_CONFIG_FALLING_EDGE);
+    if (rc) return rc;
+
+    rc = EIP201_Config_Change(
+            Device,
+            RisingEdgeSources,
+            EIP201_CONFIG_RISING_EDGE);
+    if (rc) return rc;
+
+    // the configuration change could have triggered the edge-detection logic
+    // so acknowledge all edge-based interrupts immediately
+    {
+        const uint32_t Value = FallingEdgeSources | RisingEdgeSources;
+        rc = EIP201_Write32(Device, EIP201_REGISTER_OFFSET_ACK, Value);
+        if (rc) return rc;
+    }
+
+    // set mask (enable required interrupts)
+    rc = EIP201_SourceMask_EnableSource(Device, EnabledSources);
+
+    return rc;
+}
+#endif /* EIP201_REMOVE_INITIALIZE */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_Acknowledge
+ *
+ * See header file for function specification.
+ */
+#ifndef EIP201_REMOVE_ACKNOWLEDGE
+EIP201_Status_t
+EIP201_Acknowledge(
+        Device_Handle_t Device,
+        const EIP201_SourceBitmap_t Sources)
+{
+    int rc;
+    EIP201_CHECK_IF_IRQ_SUPPORTED(Sources);
+
+    rc = EIP201_Write32(Device, EIP201_REGISTER_OFFSET_ACK, Sources);
+
+    return rc;
+}
+#endif /* EIP201_REMOVE_ACKNOWLEDGE */
+
+/* end of file eip201_sl.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cd_format.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cd_format.c
new file mode 100644
index 0000000..1190450
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cd_format.c
@@ -0,0 +1,185 @@
+/* eip202_cd_format.c
+ *
+ * EIP-202 Ring Control Driver Library
+ * Command Descriptor Internal interface
+ *
+ * This module contains the EIP-202 Command Descriptor specific functionality
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip202_cd_format.h"
+
+// Descriptor I/O Driver Library API implementation
+#include "eip202_cdr.h"                 // EIP202_ARM_CommandDescriptor_t
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip202_ring.h"
+
+// EIP-202 Ring Control Driver Library Internal interfaces
+#include "eip202_ring_internal.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                // bool, uint32_t, uint8_t
+
+// Driver Framework DMA Resource API
+#include "dmares_types.h"              // DMAResource_Handle_t
+#include "dmares_rw.h"                 // DMAResource_Write/Read
+
+// Standard IOToken API
+#include "iotoken.h"
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CD_Make_ControlWord
+ */
+uint32_t
+EIP202_CD_Make_ControlWord(
+        const uint8_t TokenWordCount,
+        const uint32_t SegmentByteCount,
+        const bool fFirstSegment,
+        const bool fLastSegment,
+        const bool fForceEngine,
+        const uint8_t EngineId)
+{
+    uint32_t Value = 0;
+
+    if(fFirstSegment)
+        Value |= BIT_23;
+
+    if(fLastSegment)
+        Value |= BIT_22;
+
+    Value |= ((((uint32_t)TokenWordCount) & MASK_8_BITS) << 24);
+    Value |= ((((uint32_t)SegmentByteCount) & MASK_16_BITS));
+    if (fForceEngine)
+        Value |= BIT_21 | (((uint32_t)EngineId & MASK_5_BITS) << 16);
+
+    return Value;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CD_Write
+ */
+void
+EIP202_CD_Write(
+        DMAResource_Handle_t Handle,
+        const unsigned int WordOffset,
+        const EIP202_ARM_CommandDescriptor_t * const Descr_p,
+        const bool fATP)
+
+{
+    unsigned int InTokenWordOffset;
+
+#ifdef EIP202_RING_ANTI_DMA_RACE_CONDITION_CDS
+    IOToken_Mark_Set(Descr_p->Token_p);
+#endif
+
+#ifdef EIP202_64BIT_DEVICE
+    // Write Control Word
+    DMAResource_Write32(Handle, WordOffset, Descr_p->ControlWord);
+
+    // Lengths greater than 20 bits not supported yet.
+#ifndef EIP202_CDR_OPT1
+    DMAResource_Write32(Handle, WordOffset + 1, 0);
+#endif
+
+    // Write Source Packet Data address
+    DMAResource_Write32(Handle, WordOffset + 2, Descr_p->SrcPacketAddr.Addr);
+    DMAResource_Write32(Handle, WordOffset + 3, Descr_p->SrcPacketAddr.UpperAddr);
+
+    if (fATP)
+    {
+#ifndef EIP202_CDR_OPT2
+        // Write Token Data address
+        DMAResource_Write32(Handle,
+                            WordOffset + 4,
+                            Descr_p->TokenDataAddr.Addr);
+        DMAResource_Write32(Handle,
+                            WordOffset + 5,
+                            Descr_p->TokenDataAddr.UpperAddr);
+#endif
+        InTokenWordOffset = WordOffset + 6;
+    }
+    else
+        InTokenWordOffset = WordOffset + 4;
+#else // EIP202_64BIT_DEVICE
+    // Write Control Word
+    DMAResource_Write32(Handle, WordOffset, Descr_p->ControlWord);
+
+    // Write Source Packet Data address
+    DMAResource_Write32(Handle, WordOffset + 1, Descr_p->SrcPacketAddr.Addr);
+
+    if (fATP)
+    {
+#ifndef EIP202_CDR_OPT2
+        // Write Token Data address
+        DMAResource_Write32(Handle, WordOffset + 2, Descr_p->TokenDataAddr.Addr);
+#endif
+        InTokenWordOffset = WordOffset + 3;
+    }
+    else
+        InTokenWordOffset = WordOffset + 2;
+#endif // !EIP202_64BIT_DEVICE
+
+    // Write Input Token (only for the first segment and if token is available)
+    if (Descr_p->ControlWord & BIT_23 && Descr_p->Token_p)
+    {
+        unsigned int i, offset = InTokenWordOffset;
+
+        // Write Application ID
+#ifdef EIP202_RING_ANTI_DMA_RACE_CONDITION_CDS
+        IOToken_Mark_Set(Descr_p->Token_p);
+#endif
+
+        for (i = 0; i < IOToken_InWordCount_Get(); i++)
+            DMAResource_Write32(Handle, offset + i, Descr_p->Token_p[i]);
+    }
+
+    return;
+}
+
+
+/* end of file eip202_cd_format.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cdr_dscr.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cdr_dscr.c
new file mode 100644
index 0000000..f7d1527
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cdr_dscr.c
@@ -0,0 +1,363 @@
+/* eip202_cdr_dscr.c
+ *
+ * EIP-202 Ring Control Driver Library
+ * 1) Descriptor I/O Driver Library API implementation
+ * 2) Internal Command Descriptor interface implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// Descriptor I/O Driver Library API implementation
+#include "eip202_cdr.h"
+
+// Internal Command Descriptor interface
+#include "eip202_cdr_dscr.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip202_ring.h"
+
+// EIP-202 Ring Control Driver Library Internal interfaces
+#include "eip202_ring_internal.h"
+#include "eip202_cdr_level0.h"         // EIP-202 Level 0 macros
+#include "eip202_cdr_fsm.h"             // CDR State machine
+#include "eip202_cd_format.h"           // CD Format API
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                // IDENTIFIER_NOT_USED, bool, uint32_t
+
+// Driver Framework DMA Resource API
+#include "dmares_types.h"         // types of the DMA resource API
+#include "dmares_rw.h"            // read/write of the DMA resource API.
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP202Lib_CDR_FillLevel_Finalize
+ *
+ */
+static EIP202_Ring_Error_t
+EIP202Lib_CDR_FillLevel_Finalize(
+        const unsigned int CDWordCount,
+        volatile EIP202_CDR_True_IOArea_t * const TrueIOArea_p,
+        unsigned int * const FillLevelDscrCount_p)
+{
+#ifdef EIP202_RING_DEBUG_FSM
+    EIP202_Ring_Error_t rv;
+
+    if(CDWordCount == 0)
+        // CD Ring is empty
+        rv = EIP202_CDR_State_Set((volatile EIP202_CDR_State_t*)&TrueIOArea_p->State,
+                                EIP202_CDR_STATE_INITIALIZED);
+    else if(CDWordCount > 0 &&
+            CDWordCount < (unsigned int)TrueIOArea_p->RingSizeWordCount)
+        // CD Ring is free
+        rv = EIP202_CDR_State_Set((volatile EIP202_CDR_State_t*)&TrueIOArea_p->State,
+                                 EIP202_CDR_STATE_FREE);
+    else if(CDWordCount == (unsigned int)TrueIOArea_p->RingSizeWordCount)
+        // CD Ring is full
+        rv = EIP202_CDR_State_Set((volatile EIP202_CDR_State_t*)&TrueIOArea_p->State,
+                                 EIP202_CDR_STATE_FULL);
+    else
+        rv = EIP202_RING_ILLEGAL_IN_STATE;
+
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+#endif
+
+    // Store actual fill level
+    *FillLevelDscrCount_p = CDWordCount /
+                            (unsigned int)TrueIOArea_p->DescOffsWordCount;
+
+    // Return actual fill level plus one descriptor to distinguish
+    // ring full from ring empty
+    if(CDWordCount < (unsigned int)TrueIOArea_p->RingSizeWordCount)
+        (*FillLevelDscrCount_p)++;
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+  Internal Command Descriptor interface
+  ---------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_WriteCB
+ */
+int
+EIP202_CDR_WriteCB(
+        void * const CallbackParam1_p,
+        const int CallbackParam2,
+        const unsigned int WriteIndex,
+        const unsigned int WriteCount,
+        const unsigned int TotalWriteLimit,
+        const void * Descriptors_p,
+        const int DescriptorCount,
+        const unsigned int DescriptorSkipCount)
+{
+    Device_Handle_t Device;
+    unsigned int i, DescOffsetWordCount;
+    unsigned int nWritten = 0;
+    volatile EIP202_CDR_True_IOArea_t * const TrueIOArea_p =
+                                            CDRIOAREA(CallbackParam1_p);
+    if(CallbackParam1_p == NULL || Descriptors_p == NULL)
+        return -1;
+
+    IDENTIFIER_NOT_USED(CallbackParam2);
+    IDENTIFIER_NOT_USED(DescriptorCount);
+    IDENTIFIER_NOT_USED(TotalWriteLimit);
+
+    Device = TrueIOArea_p->Device;
+
+    DescOffsetWordCount = (unsigned int)TrueIOArea_p->DescOffsWordCount;
+
+    // Write descriptors to CDR
+    for(i = WriteIndex; i < WriteIndex + WriteCount; i++)
+    {
+        EIP202_CD_Write(
+            TrueIOArea_p->RingHandle,
+            i * DescOffsetWordCount,
+            ((const EIP202_ARM_CommandDescriptor_t *)Descriptors_p) +
+                                            DescriptorSkipCount + nWritten,
+            TrueIOArea_p->fATP);
+
+        nWritten++;
+    }
+
+    if (nWritten > 0)
+    {
+        // Call PreDMA to prepared descriptors in Ring DMA buffer for handover
+        // to the Device (the EIP-202 DMA Master)
+        DMAResource_PreDMA(TrueIOArea_p->RingHandle,
+                           WriteIndex * DescOffsetWordCount *
+                             (unsigned int)sizeof(uint32_t),
+                           nWritten * DescOffsetWordCount *
+                             (unsigned int)sizeof(uint32_t));
+
+        // CDS point: hand over written Command Descriptors to the Device
+        EIP202_CDR_COUNT_WR(Device,
+                            (uint16_t)(nWritten * DescOffsetWordCount),
+                            false);
+    }
+
+    return (int) nWritten;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_ReadCB
+ */
+int
+EIP202_CDR_ReadCB(
+        void * const CallbackParam1_p,
+        const int CallbackParam2,
+        const unsigned int ReadIndex,
+        const unsigned int ReadLimit,
+        void * Descriptors_p,
+        const unsigned int DescriptorSkipCount)
+{
+    IDENTIFIER_NOT_USED(CallbackParam1_p);
+    IDENTIFIER_NOT_USED(CallbackParam2);
+    IDENTIFIER_NOT_USED(ReadIndex);
+    IDENTIFIER_NOT_USED(ReadLimit);
+    IDENTIFIER_NOT_USED(Descriptors_p);
+    IDENTIFIER_NOT_USED(DescriptorSkipCount);
+
+    // Not used for CDR
+
+    return -1;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_StatusCB
+ */
+int
+EIP202_CDR_StatusCB(
+        void * const CallbackParam1_p,
+        const int CallbackParam2,
+        int * const DeviceReadPos_p)
+{
+    IDENTIFIER_NOT_USED(CallbackParam1_p);
+    IDENTIFIER_NOT_USED(CallbackParam2);
+
+    *DeviceReadPos_p = -1;  // not used
+
+    return 0;
+}
+
+
+/*----------------------------------------------------------------------------
+  Descriptor I/O Driver Library API implementation
+  ---------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_FillLevel_Get
+ */
+EIP202_Ring_Error_t
+EIP202_CDR_FillLevel_Get(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        unsigned int * FillLevelDscrCount_p)
+{
+    Device_Handle_t Device;
+    unsigned int CDWordCount;
+    volatile EIP202_CDR_True_IOArea_t * const TrueIOArea_p = CDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+    EIP202_RING_CHECK_POINTER(FillLevelDscrCount_p);
+
+    Device = TrueIOArea_p->Device;
+
+    {
+        uint32_t Value32;
+
+        EIP202_CDR_COUNT_RD(Device, &Value32);
+
+        TrueIOArea_p->CountRD       = Value32;
+        TrueIOArea_p->fValidCountRD = true;
+
+        CDWordCount = (unsigned int)Value32;
+    }
+
+    return EIP202Lib_CDR_FillLevel_Finalize(CDWordCount,
+                                            TrueIOArea_p,
+                                            FillLevelDscrCount_p);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_Write_ControlWord
+ */
+uint32_t
+EIP202_CDR_Write_ControlWord(
+        const EIP202_CDR_Control_t * const  CommandCtrl_p)
+{
+    return EIP202_CD_Make_ControlWord(CommandCtrl_p->TokenWordCount,
+                                     CommandCtrl_p->SegmentByteCount,
+                                     CommandCtrl_p->fFirstSegment,
+                                     CommandCtrl_p->fLastSegment,
+                                     CommandCtrl_p->fForceEngine,
+                                     CommandCtrl_p->EngineId);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_Descriptor_Put
+ *
+ */
+EIP202_Ring_Error_t
+EIP202_CDR_Descriptor_Put(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        const EIP202_ARM_CommandDescriptor_t * CommandDscr_p,
+        const unsigned int DscrRequestedCount,
+        unsigned int * const DscrDoneCount_p,
+        unsigned int * FillLevelDscrCount_p)
+{
+    Device_Handle_t Device;
+    int res;
+    unsigned int CDWordCount, CDFreeCount, CDNewRequestedCount;
+    volatile EIP202_CDR_True_IOArea_t * const TrueIOArea_p = CDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+    EIP202_RING_CHECK_POINTER(CommandDscr_p);
+    EIP202_RING_CHECK_POINTER(DscrDoneCount_p);
+    EIP202_RING_CHECK_POINTER(FillLevelDscrCount_p);
+
+    Device = TrueIOArea_p->Device;
+
+    // Check how many descriptors can be put
+    {
+        uint32_t Value32;
+
+        if (TrueIOArea_p->fValidCountRD)
+        {
+            Value32 = TrueIOArea_p->CountRD;
+            TrueIOArea_p->fValidCountRD = false;
+        }
+        else
+        {
+            EIP202_CDR_COUNT_RD(Device, &Value32);
+            TrueIOArea_p->CountRD = Value32;
+        }
+
+        CDWordCount = (unsigned int)Value32;
+    }
+
+    // Check if CDR is full
+    if(CDWordCount == (unsigned int)TrueIOArea_p->RingSizeWordCount)
+    {
+        // CD Ring is full
+        *FillLevelDscrCount_p = CDWordCount /
+                            (unsigned int)TrueIOArea_p->DescOffsWordCount;
+        *DscrDoneCount_p = 0;
+
+        return EIP202_CDR_State_Set((volatile EIP202_CDR_State_t*)&TrueIOArea_p->State,
+                                 EIP202_CDR_STATE_FULL);
+    }
+
+    CDFreeCount =
+            ((unsigned int)TrueIOArea_p->RingSizeWordCount - CDWordCount) /
+                    (unsigned int)TrueIOArea_p->DescOffsWordCount;
+
+    CDNewRequestedCount = MIN(CDFreeCount, DscrRequestedCount);
+
+    // Put command descriptors to CDR
+    res = RingHelper_Put((volatile RingHelper_t*)&TrueIOArea_p->RingHelper,
+                         CommandDscr_p,
+                         (int)CDNewRequestedCount);
+    if(res >= 0)
+        *DscrDoneCount_p = (unsigned int)res;
+    else
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    // Increase the fill level by the number of successfully put descriptors
+    CDWordCount += ((unsigned int)res *
+                         (unsigned int)TrueIOArea_p->DescOffsWordCount);
+
+    return EIP202Lib_CDR_FillLevel_Finalize(CDWordCount,
+                                           TrueIOArea_p,
+                                           FillLevelDscrCount_p);
+}
+
+
+/* end of file eip202_cdr_dscr.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cdr_event.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cdr_event.c
new file mode 100644
index 0000000..07e8481
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cdr_event.c
@@ -0,0 +1,172 @@
+/* eip202_cdr_event.c
+ *
+ * EIP-202 Ring Control Driver Library
+ * CDR Event Management API implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip202_cdr.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip202_ring.h"
+
+// EIP-202 Ring Control Driver Library Internal interfaces
+#include "eip202_ring_internal.h"
+#include "eip202_cdr_level0.h"         // EIP-202 Level 0 macros
+#include "eip202_cdr_fsm.h"             // CDR State machine
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                // IDENTIFIER_NOT_USED, bool, uint32_t
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_Status_Get
+ */
+EIP202_Ring_Error_t
+EIP202_CDR_Status_Get(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        EIP202_CDR_Status_t * const Status_p)
+{
+    Device_Handle_t Device;
+    EIP202_Ring_Error_t rv;
+    volatile EIP202_CDR_True_IOArea_t * const TrueIOArea_p = CDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+    EIP202_RING_CHECK_POINTER(Status_p);
+
+    Device = TrueIOArea_p->Device;
+
+    EIP202_CDR_STAT_RD(Device,
+                       &Status_p->fDMAError,
+                       &Status_p->fTresholdInt,
+                       &Status_p->fError,
+                       &Status_p->fOUFlowError,
+                       &Status_p->fTimeoutInt,
+                       &Status_p->CDFIFOWordCount);
+
+    EIP202_CDR_COUNT_RD(Device, &Status_p->CDPrepWordCount);
+    EIP202_CDR_PROC_COUNT_RD(Device,
+                             &Status_p->CDProcWordCount,
+                             &Status_p->CDProcPktWordCount);
+
+    // Transit to a new state
+    if(Status_p->fDMAError)
+        rv = EIP202_CDR_State_Set((volatile EIP202_CDR_State_t*)&TrueIOArea_p->State,
+                                 EIP202_CDR_STATE_FATAL_ERROR);
+    else
+        // Remain in the current state
+        rv = EIP202_CDR_State_Set((volatile EIP202_CDR_State_t*)&TrueIOArea_p->State,
+                                 (EIP202_CDR_State_t)TrueIOArea_p->State);
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_FillLevel_Low_INT_Enable
+ */
+EIP202_Ring_Error_t
+EIP202_CDR_FillLevel_Low_INT_Enable(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        const unsigned int ThresholdDscrCount,
+        const unsigned int Timeout)
+{
+    Device_Handle_t Device;
+    EIP202_Ring_Error_t rv;
+    volatile EIP202_CDR_True_IOArea_t * const TrueIOArea_p = CDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+
+    Device = TrueIOArea_p->Device;
+
+    EIP202_CDR_THRESH_WR(Device,
+                         (uint32_t)ThresholdDscrCount *
+                               TrueIOArea_p->DescOffsWordCount,
+                         (uint8_t)Timeout);
+
+    // Remain in the current state
+    rv = EIP202_CDR_State_Set((volatile EIP202_CDR_State_t*)&TrueIOArea_p->State,
+                             (EIP202_CDR_State_t)TrueIOArea_p->State);
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_FillLevel_Low_INT_ClearAndDisable
+ */
+EIP202_Ring_Error_t
+EIP202_CDR_FillLevel_Low_INT_ClearAndDisable(
+        EIP202_Ring_IOArea_t * const IOArea_p)
+{
+    Device_Handle_t Device;
+    EIP202_Ring_Error_t rv;
+    volatile EIP202_CDR_True_IOArea_t * const TrueIOArea_p = CDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+
+    Device = TrueIOArea_p->Device;
+
+    // Disable timeout interrupt and stop timeout counter for
+    // reducing power consumption
+    EIP202_CDR_THRESH_DEFAULT_WR(Device);
+
+    // Clear all CDR interrupts
+    EIP202_CDR_STAT_CLEAR_ALL_IRQ_WR(Device);
+
+    // Remain in the current state
+    rv = EIP202_CDR_State_Set((volatile EIP202_CDR_State_t*)&TrueIOArea_p->State,
+                             (EIP202_CDR_State_t)TrueIOArea_p->State);
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/* end of file eip202_cdr_event.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cdr_fsm.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cdr_fsm.c
new file mode 100644
index 0000000..dda97e8
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cdr_fsm.c
@@ -0,0 +1,174 @@
+/* eip202_cdr_fsm.c
+ *
+ * EIP-202 Ring Control Driver Library API
+ * State Machine Internal Interface implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip202_cdr_fsm.h"
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip202_ring.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"              // IDENTIFIER_NOT_USED
+
+// EIP-202 Ring Control Driver Library Types API
+#include "eip202_ring_types.h"        // EIP202_Ring_* types
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_State_Set
+ *
+ */
+EIP202_Ring_Error_t
+EIP202_CDR_State_Set(
+        volatile EIP202_CDR_State_t * const CurrentState,
+        const EIP202_CDR_State_t NewState)
+{
+#ifdef EIP202_RING_DEBUG_FSM
+    switch(*CurrentState)
+    {
+        case EIP202_CDR_STATE_UNKNOWN:
+            switch(NewState)
+            {
+                case EIP202_CDR_STATE_UNINITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP202_RING_ILLEGAL_IN_STATE;
+            }
+            break;
+
+         case EIP202_CDR_STATE_UNINITIALIZED:
+            switch(NewState)
+            {
+                case EIP202_CDR_STATE_INITIALIZED:
+                   *CurrentState = NewState;
+                   break;
+                default:
+                    return EIP202_RING_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP202_CDR_STATE_INITIALIZED:
+            switch(NewState)
+            {
+                case EIP202_CDR_STATE_UNINITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_CDR_STATE_FREE:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_CDR_STATE_FULL:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_CDR_STATE_INITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP202_RING_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP202_CDR_STATE_FREE:
+            switch(NewState)
+            {
+                case EIP202_CDR_STATE_UNINITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_CDR_STATE_INITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_CDR_STATE_FULL:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_CDR_STATE_FATAL_ERROR:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_CDR_STATE_FREE:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP202_RING_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP202_CDR_STATE_FULL:
+            switch(NewState)
+            {
+                case EIP202_CDR_STATE_UNINITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_CDR_STATE_INITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_CDR_STATE_FREE:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_CDR_STATE_FATAL_ERROR:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_CDR_STATE_FULL:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP202_RING_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP202_CDR_STATE_FATAL_ERROR:
+            switch(NewState)
+            {
+                case EIP202_CDR_STATE_UNINITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP202_RING_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        default:
+            return EIP202_RING_ILLEGAL_IN_STATE;
+    }
+#else
+    IDENTIFIER_NOT_USED(CurrentState);
+    IDENTIFIER_NOT_USED(NewState);
+#endif // EIP202_RING_DEBUG_FSM
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/* end of file eip202_cdr_fsm.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cdr_init.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cdr_init.c
new file mode 100644
index 0000000..4b010f9
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cdr_init.c
@@ -0,0 +1,403 @@
+/* eip202_cdr_init.c
+ *
+ * EIP-202 Ring Control Driver Library
+ * CDR Init/Reset API implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip202_cdr.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip202_ring.h"
+
+// EIP-202 Ring Control Driver Library Types API
+#include "eip202_ring_types.h"          // EIP202_Ring_* types
+
+// EIP-202 Ring Control Driver Library Internal interfaces
+#include "eip202_ring_internal.h"
+#include "eip202_cdr_level0.h"          // EIP-202 Level 0 macros
+#include "eip202_cdr_fsm.h"             // CDR State machine
+#include "eip202_cdr_dscr.h"            // RingHelper callbacks
+#include "eip202_cd_format.h"           // EIP-202 Command Descriptor
+
+// RingHelper API
+#include "ringhelper.h"                // RingHelper_Init
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                // IDENTIFIER_NOT_USED, bool, uint32_t
+
+// Driver Framework Device API
+#include "device_types.h"              // Device_Handle_t
+
+// Driver Framework DMA Resource API
+#include "dmares_types.h"         // types of the DMA resource API
+#include "dmares_rw.h"            // read/write of the DMA resource API.
+
+// Driver Framework C Run-Time Library API
+#include "clib.h"
+
+// Standard IOToken API
+#include "iotoken.h"                   // IOToken_InWordCount_Get()
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP202Lib_Detect
+ *
+ * Checks the presence of EIP-202 HIA hardware. Returns true when found.
+ */
+static bool
+EIP202Lib_CDR_Detect(
+        const Device_Handle_t Device)
+{
+    uint32_t Value;
+
+    // read-write test one of the registers
+
+    // Set MASK_31_BITS bits of the EIP202_CDR_RING_BASE_ADDR_LO register
+    EIP202_CDR_Write32(Device,
+                       EIP202_CDR_RING_BASE_ADDR_LO,
+                       MASK_31_BITS );
+
+    Value = EIP202_CDR_Read32(Device, EIP202_CDR_RING_BASE_ADDR_LO);
+    if ((Value & MASK_31_BITS) != MASK_31_BITS)
+        return false;
+
+    // Clear MASK_31_BITS bits of the EIP202_CDR_RING_BASE_ADDR_LO register
+    EIP202_CDR_Write32(Device, EIP202_CDR_RING_BASE_ADDR_LO, 0);
+    Value = EIP202_CDR_Read32(Device, EIP202_CDR_RING_BASE_ADDR_LO);
+    if ((Value & MASK_31_BITS) != 0)
+       return false;
+
+    return true;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202Lib_CDR_ClearAllDescriptors
+ *
+ * Clear all descriptors
+ */
+static inline void
+EIP202Lib_CDR_ClearAllDescriptors(
+        DMAResource_Handle_t Handle,
+        const uint32_t DescriptorSpacingWordCount,
+        const uint32_t DescriptorSizeWordCount,
+        const uint32_t NumberOfDescriptors)
+{
+    unsigned int i, j;
+
+    for(i = 0; i < NumberOfDescriptors; i++)
+        for(j = 0; j < DescriptorSizeWordCount; j++)
+            DMAResource_Write32(Handle, i * DescriptorSpacingWordCount + j, 0);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_Init
+ *
+ */
+EIP202_Ring_Error_t
+EIP202_CDR_Init(
+        EIP202_Ring_IOArea_t * IOArea_p,
+        const Device_Handle_t Device,
+        const EIP202_CDR_Settings_t * const CDRSettings_p)
+{
+    uint16_t CDFIFOWordCount;
+    EIP202_Ring_Error_t rv;
+    volatile EIP202_CDR_True_IOArea_t * const TrueIOArea_p = CDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+
+    // Initialize the IO Area
+    TrueIOArea_p->fValidCountRD = false;
+    TrueIOArea_p->Device = Device;
+    TrueIOArea_p->State = (unsigned int)EIP202_CDR_STATE_UNINITIALIZED;
+
+    // Check if the CPU integer size is enough to store 32-bit value
+    if(sizeof(unsigned int) < sizeof(uint32_t))
+        return EIP202_RING_UNSUPPORTED_FEATURE_ERROR;
+
+    // Detect presence of EIP-202 CDR hardware
+    if(!EIP202Lib_CDR_Detect(Device))
+        return EIP202_RING_UNSUPPORTED_FEATURE_ERROR;
+
+    if(CDRSettings_p->fATPtoToken)
+        return EIP202_RING_UNSUPPORTED_FEATURE_ERROR;
+
+    // Extension of 32-bit pointers to 64-bit addresses not supported.
+    if(CDRSettings_p->Params.DMA_AddressMode == EIP202_RING_64BIT_DMA_EXT_ADDR)
+        return EIP202_RING_UNSUPPORTED_FEATURE_ERROR;
+
+    if(CDRSettings_p->Params.DscrOffsWordCount == 0 ||
+       CDRSettings_p->Params.DscrOffsWordCount <
+       CDRSettings_p->Params.DscrSizeWordCount)
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    // Ring size cannot be smaller than one descriptor size or
+    // larger than 4194303 (16MB / 4 - 1), in 32-bit words
+    if(CDRSettings_p->Params.RingSizeWordCount <
+       CDRSettings_p->Params.DscrOffsWordCount ||
+       CDRSettings_p->Params.RingSizeWordCount > 4194303)
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    // Read Command Descriptor FIFO size (in 32-bit words)
+    EIP202_CDR_STAT_FIFO_SIZE_RD(Device, &CDFIFOWordCount);
+
+    if(CDRSettings_p->Params.DscrSizeWordCount >
+             EIP202_CD_CTRL_DATA_MAX_WORD_COUNT + IOToken_InWordCount_Get() ||
+       CDRSettings_p->Params.DscrSizeWordCount > CDFIFOWordCount)
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    if(CDRSettings_p->Params.DscrFetchSizeWordCount > CDFIFOWordCount ||
+       CDRSettings_p->Params.DscrThresholdWordCount > CDFIFOWordCount)
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    if(CDRSettings_p->Params.DscrFetchSizeWordCount %
+                            CDRSettings_p->Params.DscrOffsWordCount)
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    if( CDRSettings_p->Params.IntThresholdDscrCount >
+        CDRSettings_p->Params.RingSizeWordCount )
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    // Configure the Ring Helper
+    TrueIOArea_p->RingHelperCallbacks.WriteFunc_p = &EIP202_CDR_WriteCB;
+    TrueIOArea_p->RingHelperCallbacks.ReadFunc_p = &EIP202_CDR_ReadCB;
+    TrueIOArea_p->RingHelperCallbacks.StatusFunc_p = &EIP202_CDR_StatusCB;
+    TrueIOArea_p->RingHelperCallbacks.CallbackParam1_p = IOArea_p;
+    TrueIOArea_p->RingHelperCallbacks.CallbackParam2 = 0;
+    TrueIOArea_p->RingHandle = CDRSettings_p->Params.RingDMA_Handle;
+    TrueIOArea_p->DescOffsWordCount = CDRSettings_p->Params.DscrOffsWordCount;
+    TrueIOArea_p->RingSizeWordCount = CDRSettings_p->Params.RingSizeWordCount;
+    TrueIOArea_p->fATP = CDRSettings_p->fATP;
+
+    // Initialize one RingHelper instance for one CDR instance
+    if( RingHelper_Init(
+         (volatile RingHelper_t*)&TrueIOArea_p->RingHelper,
+         (volatile RingHelper_CallbackInterface_t*)&TrueIOArea_p->RingHelperCallbacks,
+         true, // Separate CDR ring
+         (unsigned int)(CDRSettings_p->Params.RingSizeWordCount /
+             CDRSettings_p->Params.DscrOffsWordCount),
+         (unsigned int)(CDRSettings_p->Params.RingSizeWordCount /
+                        CDRSettings_p->Params.DscrOffsWordCount)) < 0)
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    // Transit to a new state
+    rv = EIP202_CDR_State_Set((volatile EIP202_CDR_State_t*)&TrueIOArea_p->State,
+                             EIP202_CDR_STATE_INITIALIZED);
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+
+    // Prepare the CDR DMA buffer
+    // Initialize all descriptors with zero for CDR
+    EIP202Lib_CDR_ClearAllDescriptors(
+            TrueIOArea_p->RingHandle,
+            CDRSettings_p->Params.DscrOffsWordCount,
+            CDRSettings_p->Params.DscrSizeWordCount,
+            CDRSettings_p->Params.RingSizeWordCount /
+                 CDRSettings_p->Params.DscrOffsWordCount);
+
+    // Call PreDMA to make sure engine sees it
+    DMAResource_PreDMA(TrueIOArea_p->RingHandle,
+                       0,
+                       (unsigned int)(TrueIOArea_p->RingSizeWordCount*4));
+
+    EIP202_CDR_RING_BASE_ADDR_LO_WR(
+                       Device,
+                       CDRSettings_p->Params.RingDMA_Address.Addr);
+
+    EIP202_CDR_RING_BASE_ADDR_HI_WR(
+                       Device,
+                       CDRSettings_p->Params.RingDMA_Address.UpperAddr);
+
+    EIP202_CDR_RING_SIZE_WR(
+                       Device,
+                       CDRSettings_p->Params.RingSizeWordCount);
+
+    EIP202_CDR_DESC_SIZE_WR(
+                       Device,
+                       CDRSettings_p->Params.DscrSizeWordCount,
+                       CDRSettings_p->Params.DscrOffsWordCount,
+                       CDRSettings_p->fATPtoToken,
+                       CDRSettings_p->fATP,
+                       CDRSettings_p->Params.DMA_AddressMode == EIP202_RING_64BIT_DMA_DSCR_PTR);
+
+    EIP202_CDR_CFG_WR(
+                       Device,
+                       CDRSettings_p->Params.DscrFetchSizeWordCount,
+                       CDRSettings_p->Params.DscrThresholdWordCount);
+
+    EIP202_CDR_DMA_CFG_WR(
+                       Device,
+                       (uint8_t)CDRSettings_p->Params.ByteSwap_Descriptor_Mask,
+                       (uint8_t)CDRSettings_p->Params.ByteSwap_Packet_Mask,
+                       (uint8_t)CDRSettings_p->Params.ByteSwap_Token_Mask,
+                       // Bufferability control
+                       true,  // Buffer Ownership Word DMA writes
+                       EIP202_RING_CD_WR_CACHE_CTRL, // Write cache type control
+                       EIP202_RING_CD_RD_CACHE_CTRL, // Read cache type control
+                       EIP202_RING_CD_PROT_VALUE,
+                       EIP202_RING_DATA_PROT_VALUE,
+                       EIP202_RING_ACD_PROT_VALUE);
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_Reset
+ *
+ */
+EIP202_Ring_Error_t
+EIP202_CDR_Reset(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        const Device_Handle_t Device)
+{
+    EIP202_Ring_Error_t rv;
+    volatile EIP202_CDR_True_IOArea_t * const TrueIOArea_p = CDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+
+    // Initialize the IO Area
+    memset((void*)IOArea_p, 0, sizeof(*TrueIOArea_p));
+    TrueIOArea_p->Device = Device;
+    TrueIOArea_p->State = (unsigned int)EIP202_CDR_STATE_UNKNOWN;
+
+    // Transit to a new state
+    rv = EIP202_CDR_State_Set((volatile EIP202_CDR_State_t*)&TrueIOArea_p->State,
+                             EIP202_CDR_STATE_UNINITIALIZED);
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+
+    // Clear CDR count
+    EIP202_CDR_COUNT_WR(Device, 0, true);
+
+    // Re-init CDR
+    EIP202_CDR_POINTER_DEFAULT_WR(Device);
+
+    // Restore default register values
+    EIP202_CDR_RING_BASE_ADDR_LO_DEFAULT_WR(Device);
+    EIP202_CDR_RING_BASE_ADDR_HI_DEFAULT_WR(Device);
+    EIP202_CDR_RING_SIZE_DEFAULT_WR(Device);
+    EIP202_CDR_DESC_SIZE_DEFAULT_WR(Device);
+    EIP202_CDR_CFG_DEFAULT_WR(Device);
+    EIP202_CDR_DMA_CFG_DEFAULT_WR(Device);
+
+    // Clear and disable all CDR interrupts
+    EIP202_CDR_STAT_CLEAR_ALL_IRQ_WR(Device);
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_Options_Get
+ *
+ */
+EIP202_Ring_Error_t
+EIP202_CDR_Options_Get(
+        const Device_Handle_t Device,
+        EIP202_Ring_Options_t * const Options_p)
+{
+    uint32_t Rev;
+
+    EIP202_RING_CHECK_POINTER(Options_p);
+
+    // Note: thie register does not exist in all versions of the device.
+    //       If it exists, the options register is also available.
+    Rev = EIP202_CDR_Read32(Device, EIP202_CDR_VERSION);
+    if ( !EIP202_CDR_REV_SIGNATURE_MATCH((uint16_t)Rev))
+    {
+        // No local CDR version and options registers available,
+        // function not supported
+        return EIP202_RING_UNSUPPORTED_FEATURE_ERROR;
+    }
+
+    EIP202_CDR_OPTIONS_RD(Device,
+                          &Options_p->NofRings,
+                          &Options_p->NofPes,
+                          &Options_p->fExpPlf,
+                          &Options_p->CF_Size,
+                          &Options_p->RF_Size,
+                          &Options_p->HostIfc,
+                          &Options_p->DMA_Len,
+                          &Options_p->HDW,
+                          &Options_p->TgtAlign,
+                          &Options_p->fAddr64);
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_Dump
+ *
+ */
+void
+EIP202_CDR_Dump(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        EIP202_RingAdmin_t * const RingAdmin_p)
+{
+    EIP202_RDR_True_IOArea_t * const TrueIOArea_p =
+                            (EIP202_RDR_True_IOArea_t * const)IOArea_p;
+
+    if(!TrueIOArea_p)
+        return;
+
+    if(!RingAdmin_p)
+        return;
+
+    RingAdmin_p->IN_Size           = TrueIOArea_p->RingHelper.IN_Size;
+    RingAdmin_p->IN_Tail           = TrueIOArea_p->RingHelper.IN_Tail;
+    RingAdmin_p->OUT_Size          = TrueIOArea_p->RingHelper.OUT_Size;
+    RingAdmin_p->OUT_Head          = TrueIOArea_p->RingHelper.OUT_Head;
+
+    RingAdmin_p->fSeparate         = TrueIOArea_p->RingHelper.fSeparate;
+
+    RingAdmin_p->DescOffsWordCount = TrueIOArea_p->DescOffsWordCount;
+    RingAdmin_p->RingSizeWordCount = TrueIOArea_p->RingSizeWordCount;
+}
+
+
+/* end of file eip202_cdr_init.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_global_init.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_global_init.c
new file mode 100644
index 0000000..7a0006d
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_global_init.c
@@ -0,0 +1,457 @@
+/* eip202_global_init.c
+ *
+ * EIP-202 Global Control Driver Library
+ * Initialization Module
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip202_global_init.h"
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip97_global.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"             // uint32_t
+
+// Driver Framework C Run-time Library API
+#include "clib.h"                   // ZEROINIT
+
+// Driver Framework Device API
+#include "device_types.h"           // Device_Handle_t
+
+#include "eip202_global_level0.h"   // EIP-202 Level 0 macros
+
+// EIP97_Interfaces_Get
+#include "eip97_global_internal.h"
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_Global_Detect
+ */
+bool
+EIP202_Global_Detect(
+        const Device_Handle_t Device)
+{
+    uint32_t Value;
+
+    Value = EIP202_Read32(Device, EIP202_G_REG_VERSION);
+    if (!EIP202_REV_SIGNATURE_MATCH( Value ))
+        return false;
+
+    return true;
+}
+
+
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_Global_HWRevision_Get
+ */
+void
+EIP202_Global_HWRevision_Get(
+        const Device_Handle_t Device,
+        EIP202_Capabilities_t * const Capabilities_p)
+{
+    EIP202_EIP_REV_RD(Device,
+                      &Capabilities_p->EipNumber,
+                      &Capabilities_p->ComplmtEipNumber,
+                      &Capabilities_p->HWPatchLevel,
+                      &Capabilities_p->MinHWRevision,
+                      &Capabilities_p->MajHWRevision);
+
+    EIP202_OPTIONS_RD(Device,
+                      &Capabilities_p->NofRings,
+                      &Capabilities_p->NofPes,
+                      &Capabilities_p->fExpPlf,
+                      &Capabilities_p->CF_Size,
+                      &Capabilities_p->RF_Size,
+                      &Capabilities_p->HostIfc,
+                      &Capabilities_p->DMA_Len,
+                      &Capabilities_p->HDW,
+                      &Capabilities_p->TgtAlign,
+                      &Capabilities_p->fAddr64);
+
+    EIP202_OPTIONS2_RD(Device,
+                       &Capabilities_p->NofLA_Ifs,
+                       &Capabilities_p->NofIN_Ifs,
+                       &Capabilities_p->NofAXI_WrChs,
+                       &Capabilities_p->NofAXI_RdClusters,
+                       &Capabilities_p->NofAXI_RdCPC);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_Global_Endianness_Slave_Configure
+ *
+ * Configure Endianness Conversion method
+ * for the EIP-202 slave (MMIO) interface
+ *
+ */
+bool
+EIP202_Global_Endianness_Slave_Configure(
+        const Device_Handle_t Device)
+{
+#ifdef EIP97_GLOBAL_ENABLE_SWAP_REG_DATA
+    uint32_t Value;
+
+    // Read and check the revision register
+    Value = EIP202_Read32(Device, EIP202_G_REG_VERSION);
+    if (!EIP202_REV_SIGNATURE_MATCH( Value ))
+    {
+        // No match, try to enable the Slave interface byte swap
+        // Must be done via EIP-202 HIA GLobal
+        EIP202_MST_CTRL_BYTE_SWAP_UPDATE(Device, true);
+
+        // Read and check the revision register again
+        Value = EIP202_Read32(Device, EIP202_G_REG_VERSION);
+        if (!EIP202_REV_SIGNATURE_MATCH( Value ))
+            // Bail out if still not OK
+            return false;
+    }
+
+    return true;
+#else
+    IDENTIFIER_NOT_USED(Device);
+    return true;
+#endif // EIP97_GLOBAL_ENABLE_SWAP_REG_DATA
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_Global_Init
+ */
+void
+EIP202_Global_Init(
+        const Device_Handle_t Device,
+        unsigned int NofPE,
+        unsigned int NofLA,
+        uint8_t ipbuf_min,
+        uint8_t ipbuf_max,
+        uint8_t itbuf_min,
+        uint8_t itbuf_max,
+        uint8_t opbuf_min,
+        uint8_t opbuf_max)
+{
+    unsigned int i;
+    uint8_t BufferCtrl;
+    unsigned int NofPEs,NofRings,NofLAs,NofIN,DFEDSEOffset;
+    EIP97_Interfaces_Get(&NofPEs,&NofRings,&NofLAs,&NofIN);
+    DFEDSEOffset = EIP97_DFEDSE_Offset_Get();
+
+    // Configure EIP-202 HIA Global
+    EIP202_MST_CTRL_BUS_BURST_SIZE_UPDATE(Device,
+                                          EIP97_GLOBAL_BUS_BURST_SIZE,
+                                          EIP97_GLOBAL_RX_BUS_BURST_SIZE);
+    EIP202_MST_CTRL_BUS_TIMEOUT_UPDATE(Device,
+                                       EIP97_GLOBAL_TIMEOUT_VALUE);
+    if (NofLA)
+        // User-configured value
+        BufferCtrl = EIP97_GLOBAL_DSE_BUFFER_CTRL;
+    else
+        // Default register reset value
+        BufferCtrl = (uint8_t)EIP202_DSE_BUFFER_CTRL;
+
+    for (i = 0; i < NofPE; i++)
+    {
+        // Configure EIP-202 HIA DFE Global
+        EIP202_DFE_CFG_WR(Device,
+                          DFEDSEOffset,
+                          i,
+                          ipbuf_min,
+                          EIP97_GLOBAL_DFE_DATA_CACHE_CTRL,
+                          ipbuf_max,
+                          itbuf_min,
+                          EIP97_GLOBAL_DFE_CTRL_CACHE_CTRL,
+                          itbuf_max,
+                          (EIP97_GLOBAL_DFE_ADV_THRESH_MODE_FLAG == 1),
+                          (EIP97_GLOBAL_DFE_AGGRESSIVE_DMA_FLAG == 1));
+
+        // Configure EIP-202 HIA DSE Global
+        EIP202_DSE_CFG_WR(Device,
+                          DFEDSEOffset,
+                          i,
+                          opbuf_min,
+                          EIP97_GLOBAL_DSE_DATA_CACHE_CTRL,
+                          opbuf_max,
+                          BufferCtrl,
+                          (EIP97_GLOBAL_DSE_ENABLE_SINGLE_WR_FLAG == 1),
+                          (EIP97_GLOBAL_DSE_AGGRESSIVE_DMA_FLAG == 1));
+
+    }
+
+    // Configure HIA Look-aside FIFO
+    EIP202_LASIDE_BASE_ADDR_LO_WR(Device,
+                                  EIP202_LASIDE_DSCR_BYTE_SWAP_METHOD);
+
+    for (i = EIP97_GLOBAL_LAFIFO_RING_ID;
+         i < NofLAs +
+             EIP97_GLOBAL_LAFIFO_RING_ID;
+         i++)
+    {
+        EIP202_LASIDE_SLAVE_CTRL_WR(Device,
+                                    i,
+                                    EIP202_LASIDE_IN_PKT_BYTE_SWAP_METHOD,
+                                    EIP202_LASIDE_IN_PKT_PROTO,
+                                    EIP202_LASIDE_TOKEN_BYTE_SWAP_METHOD,
+                                    EIP202_LASIDE_TOKEN_PROTO,
+                                    true); // Clear cmd descriptor error
+
+        EIP202_LASIDE_MASTER_CTRL_WR(Device,
+                                     i,
+                                     EIP202_LASIDE_OUT_PKT_BYTE_SWAP_METHOD,
+                                     EIP202_LASIDE_OUT_PKT_PROTO,
+                                     true); // Clear res descriptor error
+    }
+    // Configure HIA Inline FIFO
+    for (i = 0; i < NofIN; i++)
+        EIP202_INLINE_CTRL_WR(Device,
+                              i,
+                              EIP202_INLINE_IN_PKT_BYTE_SWAP_METHOD,
+                              false, // Clear protocol error
+                              EIP202_INLINE_OUT_PKT_BYTE_SWAP_METHOD,
+                              opbuf_min,
+                              opbuf_max,
+                              EIP202_INLINE_BURST_SIZE,
+                              EIP202_INLINE_FORCE_INORDER);
+
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_Global_Reset
+ */
+bool
+EIP202_Global_Reset(
+        const Device_Handle_t Device,
+        const unsigned int NofPE)
+{
+    unsigned int i;
+    unsigned int DFEDSEOffset;
+    DFEDSEOffset = EIP97_DFEDSE_Offset_Get();
+
+    // Restore the EIP-202 default configuration
+    // Resets DFE thread and clears ring assignment
+    for (i = 0; i < NofPE; i++)
+        EIP202_DFE_TRD_CTRL_WR(Device, DFEDSEOffset, i, 0, false, true);
+
+    // HIA DFE defaults
+    for (i = 0; i < NofPE; i++)
+        EIP202_DFE_CFG_DEFAULT_WR(Device, DFEDSEOffset, i);
+
+#ifndef EIP202_RA_DISABLE
+    EIP202_RA_PRIO_0_DEFAULT_WR(Device);
+    EIP202_RA_PRIO_1_DEFAULT_WR(Device);
+    EIP202_RA_PRIO_2_DEFAULT_WR(Device);
+    EIP202_RA_PRIO_3_DEFAULT_WR(Device);
+
+    // Resets ring assignment
+    for (i = 0; i < NofPE; i++)
+        EIP202_RA_PE_CTRL_WR(Device, i, 0, false, true);
+#endif // #ifndef EIP202_RA_DISABLE
+
+    // Resets DSE thread and clears ring assignment
+    for (i = 0; i < NofPE; i++)
+        EIP202_DSE_TRD_CTRL_WR(Device, DFEDSEOffset, i, 0, false, true);
+
+    // HIA DSE defaults
+    for (i = 0; i < NofPE; i++)
+        EIP202_DSE_CFG_DEFAULT_WR(Device, DFEDSEOffset, i);
+
+
+    // HIA LASIDE defaults
+    EIP202_LASIDE_BASE_ADDR_LO_DEFAULT_WR(Device);
+    EIP202_LASIDE_BASE_ADDR_HI_DEFAULT_WR(Device);
+    for (i = EIP97_GLOBAL_LAFIFO_RING_ID;
+         i < EIP97_GLOBAL_MAX_NOF_LAFIFO_TO_USE + EIP97_GLOBAL_LAFIFO_RING_ID;
+         i++)
+    {
+        EIP202_LASIDE_MASTER_CTRL_DEFAULT_WR(Device, i);
+        EIP202_LASIDE_SLAVE_CTRL_DEFAULT_WR(Device, i);
+    }
+
+    // HIA INLINE defaults
+    for (i = 0; i < NofPE; i++)
+        EIP202_INLINE_CTRL_DEFAULT_WR(Device, i);
+    return true;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_Global_Reset_IsDone
+ */
+bool
+EIP202_Global_Reset_IsDone(
+        const Device_Handle_t Device,
+        const unsigned int PEnr)
+{
+    uint8_t RingId;
+    unsigned int DFEDSEOffset;
+    DFEDSEOffset = EIP97_DFEDSE_Offset_Get();
+
+    // Check for completion of all DMA transfers
+    EIP202_DFE_TRD_STAT_RINGID_RD(Device, DFEDSEOffset, PEnr, &RingId);
+    if(RingId == EIP202_DFE_TRD_REG_STAT_IDLE)
+    {
+        EIP202_DSE_TRD_STAT_RINGID_RD(Device, DFEDSEOffset, PEnr, &RingId);
+        if(RingId == EIP202_DFE_TRD_REG_STAT_IDLE)
+        {
+            // Take DFE thread out of reset
+            EIP202_DFE_TRD_CTRL_DEFAULT_WR(Device, DFEDSEOffset, PEnr);
+
+            // Take DSE thread out of reset
+            EIP202_DSE_TRD_CTRL_DEFAULT_WR(Device, DFEDSEOffset, PEnr);
+
+            // Do not restore the EIP-202 Master Control default configuration
+            // so this will not change the endianness conversion configuration
+            // for the Slave interface
+        }
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_Global_Configure
+ */
+void
+EIP202_Global_Configure(
+        const Device_Handle_t Device,
+        const unsigned int PE_Number,
+        const EIP202_Global_Ring_PE_Map_t * const RingPEMap_p)
+{
+    unsigned int DFEDSEOffset;
+    DFEDSEOffset = EIP97_DFEDSE_Offset_Get();
+    // Disable EIP-202 HIA DFE thread(s)
+    EIP202_DFE_TRD_CTRL_WR(Device,
+                           DFEDSEOffset,
+                           PE_Number,   // Thread Nr
+                           0,
+                           false,       // Disable thread
+                           false);      // Do not reset thread
+
+    // Disable EIP-202 HIA DSE thread(s)
+    EIP202_DSE_TRD_CTRL_WR(Device,
+                           DFEDSEOffset,
+                           PE_Number,   // Thread Nr
+                           0,
+                           false,       // Disable thread
+                           false);      // Do not reset thread
+
+#ifndef EIP202_RA_DISABLE
+    // Configure the HIA Ring Arbiter
+    EIP202_RA_PRIO_0_WR(
+            Device,
+            (RingPEMap_p->RingPrio_Mask & BIT_0) == 0 ? false : true,
+            (uint8_t)(RingPEMap_p->RingSlots0 & MASK_4_BITS),
+            (RingPEMap_p->RingPrio_Mask & BIT_1) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots0 >> 4) & MASK_4_BITS),
+            (RingPEMap_p->RingPrio_Mask & BIT_2) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots0 >> 8) & MASK_4_BITS),
+            (RingPEMap_p->RingPrio_Mask & BIT_3) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots0 >> 12) & MASK_4_BITS));
+
+    EIP202_RA_PRIO_1_WR(
+            Device,
+            (RingPEMap_p->RingPrio_Mask & BIT_4) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots0 >> 16) & MASK_4_BITS),
+            (RingPEMap_p->RingPrio_Mask & BIT_5) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots0 >> 20) & MASK_4_BITS),
+            (RingPEMap_p->RingPrio_Mask & BIT_6) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots0 >> 24) & MASK_4_BITS),
+            (RingPEMap_p->RingPrio_Mask & BIT_7) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots0 >> 28) & MASK_4_BITS));
+
+    EIP202_RA_PRIO_2_WR(
+            Device,
+            (RingPEMap_p->RingPrio_Mask & BIT_8) == 0 ? false : true,
+            (uint8_t)(RingPEMap_p->RingSlots1 & MASK_4_BITS),
+            (RingPEMap_p->RingPrio_Mask & BIT_9) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots1 >> 4) & MASK_4_BITS),
+            (RingPEMap_p->RingPrio_Mask & BIT_10) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots1 >> 8) & MASK_4_BITS),
+            (RingPEMap_p->RingPrio_Mask & BIT_11) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots1 >> 12) & MASK_4_BITS));
+
+    EIP202_RA_PRIO_3_WR(
+            Device,
+            (RingPEMap_p->RingPrio_Mask & BIT_12) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots1 >> 16) & MASK_4_BITS),
+            (RingPEMap_p->RingPrio_Mask & BIT_13) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots1 >> 20) & MASK_4_BITS),
+            (RingPEMap_p->RingPrio_Mask & BIT_14) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots1 >> 24) & MASK_4_BITS));
+
+    // Ring assignment in the Ring Arbiter
+    EIP202_RA_PE_CTRL_WR(Device,
+                         PE_Number,
+                         RingPEMap_p->RingPE_Mask,
+                         true,
+                         false);
+#endif // #ifndef EIP202_RA_DISABLE
+
+    {
+        // Assign Rings to this DFE thread
+        // Enable EIP-202 HIA DFE thread(s)
+        EIP202_DFE_TRD_CTRL_WR(Device,
+                               DFEDSEOffset,
+                               PE_Number,   // Thread Nr
+                               RingPEMap_p->RingPE_Mask,  // Rings to assign
+                               true,        // Enable thread
+                               false);      // Do not reset thread
+
+        // Assign Rings to this DSE thread
+        // Enable EIP-202 HIA DSE thread(s)
+        EIP202_DSE_TRD_CTRL_WR(Device,
+                               DFEDSEOffset,
+                               PE_Number,   // Thread Nr
+                               RingPEMap_p->RingPE_Mask,   // Rings to assign
+                               true,        // Enable thread
+                               false);      // Do not reset thread
+    }
+}
+
+/* end of file eip202_global_init.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rd_format.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rd_format.c
new file mode 100644
index 0000000..d3ce3c6
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rd_format.c
@@ -0,0 +1,313 @@
+/* eip202_rd_format.c
+ *
+ * EIP-202 Ring Control Driver Library
+ * Result Descriptor Internal interface
+ *
+ * This module contains the EIP-202 Result Descriptor specific functionality
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip202_rd_format.h"
+
+// Descriptor I/O Driver Library API implementation
+#include "eip202_rdr.h"                 // EIP202_ARM_CommandDescriptor_t
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip202_ring.h"
+
+// EIP-202 Ring Control Driver Library Internal interfaces
+#include "eip202_ring_internal.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                // bool, uint32_t, uint8_t
+
+// Driver Framework DMA Resource API
+#include "dmares_types.h"              // DMAResource_Handle_t
+#include "dmares_rw.h"                 // DMAResource_Write/Read
+
+// Standard IOToken API
+#include "iotoken.h"
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RD_Make_ControlWord
+ */
+uint32_t
+EIP202_RD_Make_ControlWord(
+        const uint8_t ExpectedResultWordCount,
+        const uint32_t PrepSegmentByteCount,
+        const bool fFirstSegment,
+        const bool fLastSegment)
+{
+    uint32_t Value = 0;
+
+    if(fFirstSegment)
+        Value |= BIT_23;
+
+    if(fLastSegment)
+        Value |= BIT_22;
+
+    Value |= ((((uint32_t)ExpectedResultWordCount) & MASK_8_BITS) << 24);
+    Value |= ((((uint32_t)PrepSegmentByteCount)    & MASK_20_BITS));
+
+    return Value;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_Prepared_Write
+ */
+void
+EIP202_Prepared_Write(
+        DMAResource_Handle_t Handle,
+        const unsigned int WordOffset,
+        const EIP202_ARM_PreparedDescriptor_t * const Descr_p)
+{
+#ifdef EIP202_64BIT_DEVICE
+    // Write Control Word
+    DMAResource_Write32(Handle, WordOffset, Descr_p->PrepControlWord);
+
+    // Do not support lengths greater than 20 bit.
+    DMAResource_Write32(Handle, WordOffset + 1, 0);
+
+    // Write Destination Packet Data address
+    DMAResource_Write32(Handle, WordOffset + 2, Descr_p->DstPacketAddr.Addr);
+    DMAResource_Write32(Handle, WordOffset + 3, Descr_p->DstPacketAddr.UpperAddr);
+
+#else
+    // Write Control Word
+    DMAResource_Write32(Handle, WordOffset, Descr_p->PrepControlWord);
+
+    // Write Destination Packet Data address
+    DMAResource_Write32(Handle, WordOffset + 1, Descr_p->DstPacketAddr.Addr);
+#endif
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_ReadDescriptor
+ */
+void
+EIP202_ReadDescriptor(
+        EIP202_ARM_ResultDescriptor_t * const Descr_p,
+        const DMAResource_Handle_t Handle,
+        const unsigned int WordOffset,
+        const unsigned int DscrOffsWordCount,
+        const unsigned int TokenOffsWordCount,
+        bool * const fLastSegment,
+        bool * const fFirstSegment)
+{
+    unsigned int OutTokenWordOffset;
+
+#ifdef EIP202_64BIT_DEVICE
+    // Word 0 - Control Word
+    Descr_p->ProcControlWord = DMAResource_Read32(Handle, WordOffset);
+
+    // Word 1 - extended length, not read.
+
+    // Word 2 & 3 - Destination Packet Data Buffer Address
+    Descr_p->DstPacketAddr.Addr = DMAResource_Read32(Handle, WordOffset + 2);
+    Descr_p->DstPacketAddr.UpperAddr = DMAResource_Read32(Handle, WordOffset + 3);
+
+    OutTokenWordOffset = WordOffset + TokenOffsWordCount;
+#else // EIP202_64BIT_DEVICE
+    // Word 0 - Control Word
+    Descr_p->ProcControlWord = DMAResource_Read32(Handle, WordOffset);
+
+    // Word 1 - Destination Packet Data Buffer Address
+    Descr_p->DstPacketAddr.Addr = DMAResource_Read32(Handle, WordOffset + 1);
+
+    OutTokenWordOffset = WordOffset + 2;
+#endif // !EIP202_64BIT_DEVICE
+
+    if (Descr_p->Token_p == NULL)
+    {
+        *fLastSegment   = false;
+        *fFirstSegment  = false;
+        return; // Fatal error
+    }
+
+    // Read token data
+    {
+        unsigned int i;
+
+#ifdef EIP202_RING_ANTI_DMA_RACE_CONDITION_CDS
+        for (i = 0; i < IOToken_OutWordCount_Get(); i++)
+            if (i != (unsigned int)IOToken_OutMarkOffset_Get())
+                Descr_p->Token_p[i] = DMAResource_Read32(
+                                          Handle,
+                                          OutTokenWordOffset + i);
+#else
+        for (i = 0; i < IOToken_OutWordCount_Get(); i++)
+            Descr_p->Token_p[i] = DMAResource_Read32(
+                                    Handle,
+                                    OutTokenWordOffset + i);
+#endif
+    }
+
+    // Check if this descriptor is for the last segment
+    if((Descr_p->ProcControlWord & BIT_22) != 0)
+        *fLastSegment = true; // Processed packet
+    else
+        *fLastSegment = false;
+
+    // Check if this descriptor is for the first segment
+    if((Descr_p->ProcControlWord & BIT_23) != 0)
+        *fFirstSegment = true; // New packet descriptor chain detected
+    else
+        *fFirstSegment = false;
+
+    IDENTIFIER_NOT_USED(DscrOffsWordCount);
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_ClearDescriptor
+ */
+void
+EIP202_ClearDescriptor(
+        EIP202_ARM_ResultDescriptor_t * const Descr_p,
+        const DMAResource_Handle_t Handle,
+        const unsigned int WordOffset,
+        const unsigned int TokenOffsWordCount,
+        const unsigned int DscrWordCount)
+{
+    IDENTIFIER_NOT_USED(Descr_p);
+
+#if defined(EIP202_RDR_OWNERSHIP_WORD_ENABLE)
+
+    DMAResource_Write32(Handle, WordOffset + DscrWordCount - 1, 0);
+    IDENTIFIER_NOT_USED(TokenOffsWordCount);
+
+#elif defined(EIP202_RING_ANTI_DMA_RACE_CONDITION_CDS)
+
+    IDENTIFIER_NOT_USED(DscrWordCount);
+
+    DMAResource_Write32(Handle,
+                        WordOffset + TokenOffsWordCount +
+                                  IOToken_OutMarkOffset_Get(),
+                        0);
+#else
+    IDENTIFIER_NOT_USED(Handle);
+    IDENTIFIER_NOT_USED(WordOffset);
+    IDENTIFIER_NOT_USED(DscrWordCount);
+    IDENTIFIER_NOT_USED(TokenOffsWordCount);
+#endif // !EIP202_RDR_OWNERSHIP_WORD_ENABLE
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RD_Read_ControlWord
+ */
+void
+EIP202_RD_Read_ControlWord(
+        const uint32_t ControlWord,
+        uint32_t * TokenData_p,
+        EIP202_RDR_Result_Control_t * const RDControl_p,
+        EIP202_RDR_Result_Token_t * const ResToken_p)
+{
+    RDControl_p->ProcSegmentByteCount =  (ControlWord        & MASK_20_BITS);
+    RDControl_p->ProcResultWordCount  = ((ControlWord >> 24) & MASK_8_BITS);
+
+    // Fill in EIP202_RDR_Result_Control_t
+    if((ControlWord & BIT_20) != 0)
+        RDControl_p->fDscrOverflow = true;
+    else
+        RDControl_p->fDscrOverflow = false;
+
+    if((ControlWord & BIT_21) != 0)
+        RDControl_p->fBufferOverflow = true;
+    else
+        RDControl_p->fBufferOverflow = false;
+
+    if((ControlWord & BIT_22) != 0)
+        RDControl_p->fLastSegment = true;
+    else
+        RDControl_p->fLastSegment = false;
+
+    if((ControlWord & BIT_23) != 0)
+        RDControl_p->fFirstSegment = true;
+    else
+        RDControl_p->fFirstSegment = false;
+
+    IDENTIFIER_NOT_USED(TokenData_p);
+    IDENTIFIER_NOT_USED(ResToken_p);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RD_Read_BypassData
+ */
+void
+EIP202_RD_Read_BypassData(
+        const uint32_t * BypassData_p,
+        const uint8_t BypassWordCount,
+        EIP202_RDR_BypassData_t * const BD_p)
+{
+    if (BypassWordCount == 1)
+    {
+        BD_p->Fail.ErrorFlags = BypassData_p[0] & MASK_2_BITS;
+    }
+    else if (BypassWordCount == 2)
+    {
+        BD_p->Pass.TOS_TC           = BypassData_p[0] & MASK_8_BITS;
+        BD_p->Pass.fDF              = ((BypassData_p[0] & BIT_8) != 0);
+        BD_p->Pass.NextHeaderOffset = (BypassData_p[0] >> 8) & MASK_16_BITS;
+        BD_p->Pass.HdrProcCtxRef    = BypassData_p[1];
+    }
+    else
+    {
+        IDENTIFIER_NOT_USED(BypassData_p);
+        IDENTIFIER_NOT_USED(BypassWordCount);
+        IDENTIFIER_NOT_USED(BD_p);
+    }
+}
+
+
+/* end of file eip202_rd_format.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rdr_dscr.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rdr_dscr.c
new file mode 100644
index 0000000..831a486
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rdr_dscr.c
@@ -0,0 +1,735 @@
+/* eip202_rdr_dscr.c
+ *
+ * EIP-202 Ring Control Driver Library
+ * 1) Descriptor I/O Driver Library API implementation
+ * 2) Internal Result Descriptor interface implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// Descriptor I/O Driver Library API implementation
+#include "eip202_rdr.h"
+
+// Internal Result Descriptor interface
+#include "eip202_rdr_dscr.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip202_ring.h"
+
+// EIP-202 Ring Control Driver Library Internal interfaces
+#include "eip202_ring_internal.h"
+#include "eip202_rdr_level0.h"         // EIP-202 Level 0 macros
+#include "eip202_rdr_fsm.h"             // RDR State machine
+#include "eip202_rd_format.h"           // RD Format API
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                // IDENTIFIER_NOT_USED, bool, uint32_t
+
+// Driver Framework DMA Resource API
+#include "dmares_types.h"         // types of the DMA resource API
+#include "dmares_rw.h"            // read/write of the DMA resource API.
+
+// Standard IOToken API
+#include "iotoken.h"
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+// EIP-202 HW limit for the number of packets to acknowledge at once
+#define EIP202_RING_MAX_RD_PACKET_COUNT      127
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP202Lib_RDR_Prepared_FillLevel_Get
+ */
+static EIP202_Ring_Error_t
+EIP202Lib_RDR_Prepared_FillLevel_Get(
+        const Device_Handle_t Device,
+        volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p,
+        unsigned int * const FillLevelDscrCount_p)
+{
+    unsigned int RDWordCount;
+    EIP202_Ring_Error_t rv;
+
+    EIP202_RDR_PREP_COUNT_RD(Device, (uint32_t*)&RDWordCount);
+
+    // Remain in the current state
+    rv = EIP202_RDR_State_Set((volatile EIP202_RDR_State_t*)&TrueIOArea_p->State,
+                             (EIP202_RDR_State_t)TrueIOArea_p->State);
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+
+    *FillLevelDscrCount_p = RDWordCount /
+                            (unsigned int)TrueIOArea_p->DescOffsWordCount;
+
+    if(RDWordCount < (unsigned int)TrueIOArea_p->RingSizeWordCount)
+        (*FillLevelDscrCount_p)++;
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202Lib_RDR_Processed_FillLevel_Finalize
+ */
+static EIP202_Ring_Error_t
+EIP202Lib_RDR_Processed_FillLevel_Finalize(
+        const unsigned int RDWordCount,
+        const unsigned int PktCount,
+        volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p,
+        unsigned int * const FillLevelDscrCount_p,
+        unsigned int * const FillLevelPktCount_p)
+{
+#ifdef EIP202_RING_DEBUG_FSM
+    EIP202_Ring_Error_t rv;
+
+    if(RDWordCount == 0)
+        // CD Ring is empty
+        rv = EIP202_RDR_State_Set((volatile EIP202_RDR_State_t*)&TrueIOArea_p->State,
+                                EIP202_RDR_STATE_INITIALIZED);
+    else if(RDWordCount > 0 &&
+            RDWordCount < (unsigned int)TrueIOArea_p->RingSizeWordCount)
+        // CD Ring is free
+        rv = EIP202_RDR_State_Set((volatile EIP202_RDR_State_t*)&TrueIOArea_p->State,
+                                 EIP202_RDR_STATE_FREE);
+    else if(RDWordCount == (unsigned int)TrueIOArea_p->RingSizeWordCount)
+        // CD Ring is full
+        rv = EIP202_RDR_State_Set((volatile EIP202_RDR_State_t*)&TrueIOArea_p->State,
+                                 EIP202_RDR_STATE_FULL);
+    else
+        rv = EIP202_RING_ILLEGAL_IN_STATE;
+
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+#endif
+
+    *FillLevelDscrCount_p = RDWordCount /
+                            (unsigned int)TrueIOArea_p->DescOffsWordCount;
+
+    *FillLevelPktCount_p = PktCount;
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+  Internal Result Descriptor interface
+  ---------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_WriteCB
+ */
+int
+EIP202_RDR_WriteCB(
+        void * const CallbackParam1_p,
+        const int CallbackParam2,
+        const unsigned int WriteIndex,
+        const unsigned int WriteCount,
+        const unsigned int TotalWriteLimit,
+        const void * Descriptors_p,
+        const int DescriptorCount,
+        const unsigned int DescriptorSkipCount)
+{
+    Device_Handle_t Device;
+    unsigned int i, DescOffsetWordCount;
+    unsigned int nWritten = 0;
+    volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p =
+                                            RDRIOAREA(CallbackParam1_p);
+    if(CallbackParam1_p == NULL || Descriptors_p == NULL)
+        return -1;
+
+    IDENTIFIER_NOT_USED(CallbackParam2);
+    IDENTIFIER_NOT_USED(DescriptorCount);
+    IDENTIFIER_NOT_USED(TotalWriteLimit);
+
+    Device = TrueIOArea_p->Device;
+
+    DescOffsetWordCount = (unsigned int)TrueIOArea_p->DescOffsWordCount;
+
+    // Write descriptors to RDR
+    for(i = WriteIndex; i < WriteIndex + WriteCount; i++)
+    {
+        EIP202_Prepared_Write(
+            TrueIOArea_p->RingHandle,
+            i * DescOffsetWordCount,
+            ((const EIP202_ARM_PreparedDescriptor_t *)Descriptors_p) +
+                    DescriptorSkipCount + nWritten);
+
+        nWritten++;
+    }
+
+    if (nWritten > 0)
+    {
+        // Call PreDMA to prepared descriptors in Ring DMA buffer for handover
+        // to the Device (the EIP-202 DMA Master)
+        DMAResource_PreDMA(TrueIOArea_p->RingHandle,
+                           WriteIndex *
+                              DescOffsetWordCount *
+                               (unsigned int)sizeof(uint32_t),
+                           nWritten *
+                             DescOffsetWordCount *
+                               (unsigned int)sizeof(uint32_t));
+
+        // CDS point: hand over written Prepared Descriptors to the Device
+        EIP202_RDR_PREP_COUNT_WR(Device,
+                                 (uint16_t)(nWritten * DescOffsetWordCount),
+                                 false);
+    }
+
+    return (int)nWritten;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_ReadCB
+ */
+int
+EIP202_RDR_ReadCB(
+        void * const CallbackParam1_p,
+        const int CallbackParam2,
+        const unsigned int ReadIndex,
+        const unsigned int ReadLimit,
+        void * Descriptors_p,
+        const unsigned int DescriptorSkipCount)
+{
+    Device_Handle_t Device;
+    unsigned int i, DescOffsetWordCount;
+    bool fGotDescriptor, fLastSegment = false, fFirstSegment = false;
+    unsigned int GotDscrCount = 0, GotPktCount = 0;
+    volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p =
+                                       RDRIOAREA(CallbackParam1_p);
+
+    if(CallbackParam1_p == NULL || Descriptors_p == NULL)
+        return -1;
+
+    IDENTIFIER_NOT_USED(CallbackParam2);
+
+    Device = TrueIOArea_p->Device;
+
+    DescOffsetWordCount = (unsigned int )TrueIOArea_p->DescOffsWordCount;
+
+    // Read descriptors from RDR
+    for(i = ReadIndex; i < ReadIndex + ReadLimit; i++)
+    {
+        EIP202_ARM_ResultDescriptor_t * CurrentResultDesc_p =
+            ((EIP202_ARM_ResultDescriptor_t *)Descriptors_p) +
+                    DescriptorSkipCount + GotDscrCount;
+
+#define EIP202_RING_RDR_ALL_DESCRIPTORS_TO_GET_DONE             \
+         (TrueIOArea_p->AcknowledgedRDCount + GotDscrCount >=  \
+              TrueIOArea_p->RDToGetCount)
+
+// This can be true only if the PktRequestedCount parameter in
+// the EIP202_RDR_Descriptor_Get() function is set to a non-zero value
+#define EIP202_RING_RDR_ALL_PACKETS_TO_GET_DONE                 \
+         (TrueIOArea_p->PktToGetCount > 0 &&                   \
+          TrueIOArea_p->AcknowledgedPktCount + GotPktCount >=  \
+              TrueIOArea_p->PktToGetCount)
+
+        // Stop reading the descriptors if all the requested
+        // descriptors and packet chains have been read
+        if(EIP202_RING_RDR_ALL_PACKETS_TO_GET_DONE)
+        {
+            if(EIP202_RING_RDR_ALL_DESCRIPTORS_TO_GET_DONE)
+                break; // for
+        }
+
+        // Call PostDMA before reading descriptors from
+        // the EIP-202 DMA Master
+        DMAResource_PostDMA(TrueIOArea_p->RingHandle,
+                            i * DescOffsetWordCount *
+                              (unsigned int)sizeof(uint32_t),
+                            DescOffsetWordCount *
+                              (unsigned int)sizeof(uint32_t));
+
+        // Check if a processed result descriptor is received
+#if defined(EIP202_RDR_OWNERSHIP_WORD_ENABLE)
+        {
+            uint32_t OwnershipWord =
+                        DMAResource_Read32(TrueIOArea_p->RingHandle,
+                                           i * DescOffsetWordCount +
+                                                 DescOffsetWordCount - 1);
+            fGotDescriptor =
+                    (OwnershipWord == EIP202_RDR_OWNERSHIP_WORD_PATTERN);
+#ifdef EIP202_RING_BUS_KEEPALIVE_WORKAROUND
+            // Read from the device to solve a keep-alive problem in some
+            // bus environments.
+            Device_Read32(Device,0);
+#endif
+        }
+#elif defined(EIP202_RING_ANTI_DMA_RACE_CONDITION_CDS)
+        CurrentResultDesc_p->Token_p[IOToken_OutMarkOffset_Get()] =
+                DMAResource_Read32(TrueIOArea_p->RingHandle,
+                                   i * DescOffsetWordCount +
+                                   TrueIOArea_p->TokenOffsetWordCount +
+                                   IOToken_OutMarkOffset_Get());
+        fGotDescriptor = (IOToken_Mark_Check(CurrentResultDesc_p->Token_p) == 0);
+#else
+        fGotDescriptor = true; // according to EIP202_RDR_PROC_COUNT_RD()
+#endif
+
+        if (fGotDescriptor)
+        {
+            // Read Result Descriptor
+            EIP202_ReadDescriptor(CurrentResultDesc_p,
+                                  TrueIOArea_p->RingHandle,
+                                  i * DescOffsetWordCount,
+                                  DescOffsetWordCount,
+                                  TrueIOArea_p->TokenOffsetWordCount,
+                                  &fLastSegment,
+                                  &fFirstSegment);
+
+            // Stop reading the descriptors if all the requested
+            // packet chains have been read and a new processed packet descriptor
+            // chain is detected
+            if(fFirstSegment && EIP202_RING_RDR_ALL_PACKETS_TO_GET_DONE)
+                break; // for
+
+            if (fFirstSegment)
+                TrueIOArea_p->PacketFound = true;
+
+            GotDscrCount++;
+
+            if(TrueIOArea_p->PacketFound && fLastSegment)
+            {
+                GotPktCount++;
+                TrueIOArea_p->PacketFound = false;
+            }
+
+#if defined(EIP202_RING_ANTI_DMA_RACE_CONDITION_CDS) || \
+    defined(EIP202_RDR_OWNERSHIP_WORD_ENABLE)
+            // Clear this descriptor
+            EIP202_ClearDescriptor(CurrentResultDesc_p,
+                                   TrueIOArea_p->RingHandle,
+                                   i * DescOffsetWordCount,
+                                   TrueIOArea_p->TokenOffsetWordCount,
+                                   DescOffsetWordCount);
+
+            // Ensure next PostDMA does not undo the clear operation above
+            DMAResource_PreDMA(
+                TrueIOArea_p->RingHandle,
+                i * DescOffsetWordCount * (unsigned int)sizeof(uint32_t),
+                DescOffsetWordCount * (unsigned int)sizeof(uint32_t));
+#endif
+        }
+        else
+        {
+            // The fGotDescriptor is set in EIP202_ReadDescriptor() and
+            // depends on the Application ID field in the result descriptor
+            // when EIP202_RING_ANTI_DMA_RACE_CONDITION_CDS is defined.
+            // In case of a packet descriptor chain the Engine writes the
+            // Application ID field for the last segment descriptor only
+            // but we need to acknowledge all the descriptors of the chain
+            break; // for
+        }
+    } // for
+
+    // Check if there are processed result descriptors and packets
+    // that must be acknowledged
+    if (GotDscrCount > 0)
+    {
+        unsigned int NewGotPktCount;
+
+#if EIP202_RING_RD_INTERRUPTS_PER_PACKET_FLAG != 1
+        GotPktCount = 0;
+#endif
+
+        // EIP-202 HW limits the number of packets to acknowledge at once to
+        // EIP202_RING_MAX_RD_PACKET_COUNT packets
+        NewGotPktCount = MIN(GotPktCount, EIP202_RING_MAX_RD_PACKET_COUNT);
+
+        // CDS point: hand over read Result Descriptors to the Device
+        EIP202_RDR_PROC_COUNT_WR(
+                Device,
+                (uint16_t)(GotDscrCount * DescOffsetWordCount),
+                (uint8_t)NewGotPktCount,
+                false);
+    }
+
+    // Update acknowledged packets counter
+    TrueIOArea_p->AcknowledgedPktCount += GotPktCount;
+
+    // Update acknowledged descriptors counter
+    TrueIOArea_p->AcknowledgedRDCount += GotDscrCount;
+
+    return (int)GotDscrCount;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_StatusCB
+ */
+int
+EIP202_RDR_StatusCB(
+        void * const CallbackParam1_p,
+        const int CallbackParam2,
+        int * const DeviceReadPos_p)
+{
+    IDENTIFIER_NOT_USED(CallbackParam1_p);
+    IDENTIFIER_NOT_USED(CallbackParam2);
+
+    *DeviceReadPos_p = -1;  // not used
+
+    return 0;
+}
+
+
+/*----------------------------------------------------------------------------
+  Descriptor I/O Driver Library API implementation
+  ---------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_FillLevel_Get
+ */
+EIP202_Ring_Error_t
+EIP202_RDR_FillLevel_Get(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        unsigned int * FillLevelDscrCount_p)
+{
+    int FillLevel;
+    volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p = RDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+    EIP202_RING_CHECK_POINTER(FillLevelDscrCount_p);
+
+    FillLevel = RingHelper_FillLevel_Get(
+            (volatile RingHelper_t*)&TrueIOArea_p->RingHelper);
+
+    if(FillLevel < 0)
+        return EIP202_RING_UNSUPPORTED_FEATURE_ERROR;
+    else
+    {
+        *FillLevelDscrCount_p = (unsigned int)FillLevel;
+        return EIP202_RING_NO_ERROR;
+    }
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Prepared_FillLevel_Get
+ */
+EIP202_Ring_Error_t
+EIP202_RDR_Prepared_FillLevel_Get(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        unsigned int * FillLevelDscrCount_p)
+{
+    Device_Handle_t Device;
+    volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p = RDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+    EIP202_RING_CHECK_POINTER(FillLevelDscrCount_p);
+
+    Device = TrueIOArea_p->Device;
+
+    return EIP202Lib_RDR_Prepared_FillLevel_Get(Device,
+                                               TrueIOArea_p,
+                                               FillLevelDscrCount_p);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Write_Prepared_ControlWord
+ *
+ * This helper function returns the control word that can be written to
+ * the logical prepared descriptor.
+ *
+ * This function is re-entrant.
+ *
+ */
+uint32_t
+EIP202_RDR_Write_Prepared_ControlWord(
+        const EIP202_RDR_Prepared_Control_t * const  PreparedCtrl_p)
+{
+    return EIP202_RD_Make_ControlWord(PreparedCtrl_p->ExpectedResultWordCount,
+                                     PreparedCtrl_p->PrepSegmentByteCount,
+                                     PreparedCtrl_p->fFirstSegment,
+                                     PreparedCtrl_p->fLastSegment);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Descriptor_Prepare
+ */
+EIP202_Ring_Error_t
+EIP202_RDR_Descriptor_Prepare(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        const EIP202_ARM_PreparedDescriptor_t * PreparedDscr_p,
+        const unsigned int DscrRequestedCount,
+        unsigned int * const DscrPreparedCount_p,
+        unsigned int * FillLevelDscrCount_p)
+{
+    int res, FillLevel;
+    unsigned int RDWordCount, RDFreeCount, DscrNewRequestedCount;
+    volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p = RDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+    EIP202_RING_CHECK_POINTER(PreparedDscr_p);
+    EIP202_RING_CHECK_POINTER(DscrPreparedCount_p);
+    EIP202_RING_CHECK_POINTER(FillLevelDscrCount_p);
+
+    // Check how many more descriptors can be added (prepared) to RDR
+    FillLevel = RingHelper_FillLevel_Get(
+            (volatile RingHelper_t*)&TrueIOArea_p->RingHelper);
+    if(FillLevel < 0)
+        return EIP202_RING_ARGUMENT_ERROR; // Error, RDR admin corrupted
+
+    // Check if RDR is full
+    RDWordCount = ((unsigned int)FillLevel *
+            (unsigned int)TrueIOArea_p->DescOffsWordCount);
+    if(RDWordCount == (unsigned int)TrueIOArea_p->RingSizeWordCount)
+    {
+        // RD Ring is full
+        *FillLevelDscrCount_p = (unsigned int)FillLevel;
+        *DscrPreparedCount_p = 0;
+
+        // Remain in the current state
+        return EIP202_RDR_State_Set((volatile EIP202_RDR_State_t*)&TrueIOArea_p->State,
+                                   (EIP202_RDR_State_t)TrueIOArea_p->State);
+    }
+
+    // Calculate the maximum number of descriptors that can be added to RDR
+    RDFreeCount =
+            ((unsigned int)TrueIOArea_p->RingSizeWordCount - RDWordCount) /
+                    (unsigned int)TrueIOArea_p->DescOffsWordCount;
+
+    DscrNewRequestedCount = MIN(RDFreeCount, DscrRequestedCount);
+
+    res = RingHelper_Put((volatile RingHelper_t*)&TrueIOArea_p->RingHelper,
+                         PreparedDscr_p,
+                         (int)DscrNewRequestedCount);
+    if(res >= 0)
+        *DscrPreparedCount_p = (unsigned int)res;
+    else
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    // Get the current RDR fill level
+    FillLevel = RingHelper_FillLevel_Get(
+            (volatile RingHelper_t*)&TrueIOArea_p->RingHelper);
+    if(FillLevel < 0)
+        return EIP202_RING_ARGUMENT_ERROR; // Error, RDR admin corrupted
+    else
+    {
+        *FillLevelDscrCount_p = (unsigned int)FillLevel;
+        return EIP202_RING_NO_ERROR;
+    }
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Processed_FillLevel_Get
+ */
+EIP202_Ring_Error_t
+EIP202_RDR_Processed_FillLevel_Get(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        unsigned int * FillLevelDscrCount_p,
+        unsigned int * FillLevelPktCount_p)
+{
+// If configured then the driver cannot rely on the register counter
+#if defined(EIP202_RING_ANTI_DMA_RACE_CONDITION_CDS) || \
+    defined(EIP202_RDR_OWNERSHIP_WORD_ENABLE)
+    IDENTIFIER_NOT_USED(FillLevelDscrCount_p);
+    IDENTIFIER_NOT_USED(FillLevelPktCount_p);
+    IDENTIFIER_NOT_USED(IOArea_p);
+
+    return EIP202_RING_UNSUPPORTED_FEATURE_ERROR;
+#else
+    Device_Handle_t Device;
+    unsigned int RDWordCount, PktCount;
+    volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p = RDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+    EIP202_RING_CHECK_POINTER(FillLevelDscrCount_p);
+    EIP202_RING_CHECK_POINTER(FillLevelPktCount_p);
+
+    Device = TrueIOArea_p->Device;
+
+    {
+        uint8_t Value8;
+        uint32_t Value32;
+
+        EIP202_RDR_PROC_COUNT_RD(Device, &Value32, &Value8);
+
+        RDWordCount = (unsigned int)Value32;
+        PktCount = (unsigned int)Value8;
+    }
+
+    return EIP202Lib_RDR_Processed_FillLevel_Finalize(RDWordCount,
+                                                     PktCount,
+                                                     TrueIOArea_p,
+                                                     FillLevelDscrCount_p,
+                                                     FillLevelPktCount_p);
+#endif // EIP202_RING_ANTI_DMA_RACE_CONDITION_CDS
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Read_Processed_ControlWord
+ */
+void
+EIP202_RDR_Read_Processed_ControlWord(
+        EIP202_ARM_ResultDescriptor_t * const  ResDscr_p,
+        EIP202_RDR_Result_Control_t * const RDControl_p,
+        EIP202_RDR_Result_Token_t * const ResToken_p)
+{
+    IDENTIFIER_NOT_USED(ResToken_p);
+
+    EIP202_RD_Read_ControlWord(ResDscr_p->ProcControlWord,
+                               NULL,
+                               RDControl_p,
+                               NULL);
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Read_Processed_BypassData
+ */
+void
+EIP202_RDR_Read_Processed_BypassData(
+        const EIP202_RDR_Result_Token_t * const  ResToken_p,
+        EIP202_RDR_BypassData_t * const BD_p)
+{
+    EIP202_RD_Read_BypassData(ResToken_p->BypassData_p,
+                              ResToken_p->BypassWordCount,
+                              BD_p);
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Descriptor_Get
+ */
+EIP202_Ring_Error_t
+EIP202_RDR_Descriptor_Get(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        EIP202_ARM_ResultDescriptor_t * ResultDscr_p,
+        const unsigned int PktRequestedCount,
+        const unsigned int DscrRequestedCount,
+        unsigned int * const DscrDoneCount_p,
+        unsigned int * FillLevelDscrCount_p)
+{
+    Device_Handle_t Device;
+    int res;
+    unsigned int RDWordCount, ProcDsrcCount, ProcPktCount;
+    volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p = RDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+    EIP202_RING_CHECK_POINTER(ResultDscr_p);
+    EIP202_RING_CHECK_POINTER(DscrDoneCount_p);
+    EIP202_RING_CHECK_POINTER(FillLevelDscrCount_p);
+
+    if(DscrRequestedCount == 0)
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+    // Check how many descriptors can be obtained
+    {
+        uint8_t Value8;
+        uint32_t Value32;
+
+#ifdef EIP202_RDR_OWNERSHIP_WORD_ENABLE
+        Value32 = MIN(PktRequestedCount, DscrRequestedCount);
+        Value8  = MIN(EIP202_RING_MAX_RD_PACKET_COUNT, Value32);
+        Value32 = Value8 * TrueIOArea_p->DescOffsWordCount;
+        IDENTIFIER_NOT_USED(Device);
+#else
+        EIP202_RDR_PROC_COUNT_RD(Device, &Value32, &Value8);
+#endif
+        RDWordCount = (unsigned int)Value32;
+        ProcPktCount = (unsigned int)Value8;
+    }
+
+    // Check if RDR is empty or
+    // if RDR has no fully processed packet descriptor chain
+    if(RDWordCount == 0 ||
+       (PktRequestedCount != 0 && ProcPktCount == 0))
+    {
+        // Nothing to do
+        *FillLevelDscrCount_p = 0;
+        *DscrDoneCount_p = 0;
+
+        return EIP202_RDR_State_Set((volatile EIP202_RDR_State_t*)&TrueIOArea_p->State,
+                                   EIP202_RDR_STATE_INITIALIZED);
+    }
+
+    ProcDsrcCount = RDWordCount /
+                    (unsigned int)TrueIOArea_p->DescOffsWordCount;
+
+    TrueIOArea_p->AcknowledgedRDCount = 0;
+    TrueIOArea_p->AcknowledgedPktCount = 0;
+    TrueIOArea_p->RDToGetCount = MIN(ProcDsrcCount, DscrRequestedCount);
+    TrueIOArea_p->PktToGetCount = MIN(ProcPktCount, PktRequestedCount);
+
+    // Get processed (result) descriptors
+    res = RingHelper_Get((volatile RingHelper_t*)&TrueIOArea_p->RingHelper,
+// If configured then the driver cannot rely on the register counter
+#if defined(EIP202_RING_ANTI_DMA_RACE_CONDITION_CDS) || \
+    defined(EIP202_RDR_OWNERSHIP_WORD_ENABLE)
+                         -1, // Certainly available RD count unknown
+#else
+                         (int)TrueIOArea_p->RDToGetCount,
+#endif // EIP202_RING_ANTI_DMA_RACE_CONDITION_CDS
+                         ResultDscr_p,
+                         (int)DscrRequestedCount);
+    if(res >= 0)
+        *DscrDoneCount_p = (unsigned int)res;
+    else
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    // Increase the fill level by the number of successfully got descriptors
+    RDWordCount -= ((unsigned int)res *
+                         (unsigned int)TrueIOArea_p->DescOffsWordCount);
+
+    // Increase the fill level by the number of acknowledged packets
+    ProcPktCount -= TrueIOArea_p->AcknowledgedPktCount;
+
+    return EIP202Lib_RDR_Processed_FillLevel_Finalize(RDWordCount,
+                                                     ProcPktCount,
+                                                     TrueIOArea_p,
+                                                     FillLevelDscrCount_p,
+                                                     &ProcPktCount);
+}
+
+
+/* end of file eip202_rdr_dscr.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rdr_event.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rdr_event.c
new file mode 100644
index 0000000..6f6efc8
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rdr_event.c
@@ -0,0 +1,230 @@
+/* eip202_rdr_event.c
+ *
+ * EIP-202 Ring Control Driver Library
+ * CDR Event Management API implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip202_rdr.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip202_ring.h"
+
+// EIP-202 Ring Control Driver Library Internal interfaces
+#include "eip202_ring_internal.h"
+#include "eip202_rdr_level0.h"         // EIP-202 Level 0 macros
+#include "eip202_rdr_fsm.h"             // RDR State machine
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                // IDENTIFIER_NOT_USED, bool, uint32_t
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Status_Get
+ */
+EIP202_Ring_Error_t
+EIP202_RDR_Status_Get(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        EIP202_RDR_Status_t * const Status_p)
+{
+    Device_Handle_t Device;
+    EIP202_Ring_Error_t rv;
+    volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p = RDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+    EIP202_RING_CHECK_POINTER(Status_p);
+
+    Device = TrueIOArea_p->Device;
+
+    EIP202_RDR_PREP_COUNT_RD(Device, &Status_p->RDPrepWordCount);
+    EIP202_RDR_PROC_COUNT_RD(Device,
+                             &Status_p->RDProcWordCount,
+                             &Status_p->RDProcPktWordCount);
+
+    EIP202_RDR_STAT_RD(Device,
+                       &Status_p->fDMAError,
+                       &Status_p->fTresholdInt,
+                       &Status_p->fError,
+                       &Status_p->fOUFlowError,
+                       &Status_p->fTimeoutInt,
+                       &Status_p->fRDBufOverflowInt,
+                       &Status_p->fRDOverflowInt,
+                       &Status_p->RDFIFOWordCount);
+
+    // Transit to a new state
+    if(Status_p->fDMAError)
+        rv = EIP202_RDR_State_Set((volatile EIP202_RDR_State_t*)&TrueIOArea_p->State,
+                                 EIP202_RDR_STATE_FATAL_ERROR);
+    else
+        // Remain in the current state
+        rv = EIP202_RDR_State_Set((volatile EIP202_RDR_State_t*)&TrueIOArea_p->State,
+                                 (EIP202_RDR_State_t)TrueIOArea_p->State);
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Processed_FillLevel_High_INT_Enable
+ */
+EIP202_Ring_Error_t
+EIP202_RDR_Processed_FillLevel_High_INT_Enable(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        const unsigned int ThresholdDscrCount,
+        const unsigned int Timeout,
+        const bool fIntPerPacket)
+{
+    Device_Handle_t Device;
+    EIP202_Ring_Error_t rv;
+    volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p = RDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+
+    if(EIP202_RING_RD_INTERRUPTS_PER_PACKET_FLAG == 0 && fIntPerPacket)
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+    if (fIntPerPacket)
+    {
+        EIP202_RDR_THRESH_WR(Device,
+                             (uint32_t)ThresholdDscrCount,
+                             // Set packet processing mode,
+                             // e.g. interrupts per packet i.s.o. descriptor
+                             true,
+                             (uint8_t)Timeout);
+    }
+    else
+    {
+        EIP202_RDR_THRESH_WR(Device,
+                             (uint32_t)ThresholdDscrCount *
+                             TrueIOArea_p->DescOffsWordCount,
+                             // Set packet processing mode,
+                             // e.g. interrupts per packet i.s.o. descriptor
+                             false,
+                             (uint8_t)Timeout);
+    }
+
+#ifdef EIP202_CLUSTERED_WRITES_DISABLE
+    // Prevent clustered write operations, break them with a read operation
+    // Note: Reading the EIP202_RDR_RING_BASE_ADDR_LO register
+    //       has no side effects!
+    EIP202_RDR_Read32(Device, EIP202_RDR_RING_BASE_ADDR_LO);
+#endif
+
+    // Remain in the current state
+    rv = EIP202_RDR_State_Set((volatile EIP202_RDR_State_t*)&TrueIOArea_p->State,
+                             (EIP202_RDR_State_t)TrueIOArea_p->State);
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Processed_FillLevel_High_INT_ClearAndDisable
+ *
+ */
+EIP202_Ring_Error_t
+EIP202_RDR_Processed_FillLevel_High_INT_ClearAndDisable(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        const bool fOvflIntOnly)
+{
+    Device_Handle_t Device;
+    EIP202_Ring_Error_t rv;
+    volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p = RDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+
+    Device = TrueIOArea_p->Device;
+
+    if(fOvflIntOnly)
+    {
+        // Clear Descriptor and Buffer overflow interrupts
+        EIP202_RDR_STAT_CLEAR_DSCR_BUF_OFLO_IRQ_WR(Device);
+    }
+    else
+    {
+        // Disable Processed Descriptor threshold interrupt,
+        // Disable Timeout interrupt and stop timeout counter for
+        // reducing power consumption
+        EIP202_RDR_THRESH_WR(
+                           Device,
+                           TrueIOArea_p->RingSizeWordCount,
+                           0,  // Set descriptor processing mode
+                           0); // Disable timeout
+
+#ifdef EIP202_CLUSTERED_WRITES_DISABLE
+        // Prevent clustered write operations, break them with a read operation
+        // Note: Reading the EIP202_RDR_RING_BASE_ADDR_LO register
+        //       has no side effects!
+        EIP202_RDR_Read32(Device, EIP202_RDR_RING_BASE_ADDR_LO);
+#endif
+
+        // Clear all RDR interrupts
+        EIP202_RDR_STAT_CLEAR_ALL_IRQ_WR(Device);
+
+#ifdef EIP202_CLUSTERED_WRITES_DISABLE
+        // Prevent clustered write operations, break them with a read operation
+        // Note: Reading the EIP202_RDR_RING_BASE_ADDR_LO register
+        //       has no side effects!
+        EIP202_RDR_Read32(Device, EIP202_RDR_RING_BASE_ADDR_LO);
+#endif
+    }
+
+    // Remain in the current state
+    rv = EIP202_RDR_State_Set((volatile EIP202_RDR_State_t*)&TrueIOArea_p->State,
+                             (EIP202_RDR_State_t)TrueIOArea_p->State);
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/* end of file eip202_rdr_event.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rdr_fsm.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rdr_fsm.c
new file mode 100644
index 0000000..a3fa0e5
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rdr_fsm.c
@@ -0,0 +1,174 @@
+/* eip202_rdr_fsm.c
+ *
+ * EIP-202 Ring Control Driver Library API
+ * State Machine Internal Interface implementation for RDR
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip202_rdr_fsm.h"
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip202_ring.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"              // IDENTIFIER_NOT_USED
+
+// EIP-202 Ring Control Driver Library Types API
+#include "eip202_ring_types.h"        // EIP202_Ring_* types
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_State_Set
+ *
+ */
+EIP202_Ring_Error_t
+EIP202_RDR_State_Set(
+        volatile EIP202_RDR_State_t * const CurrentState,
+        const EIP202_RDR_State_t NewState)
+{
+#ifdef EIP202_RING_DEBUG_FSM
+    switch(*CurrentState)
+    {
+        case EIP202_RDR_STATE_UNKNOWN:
+            switch(NewState)
+            {
+                case EIP202_RDR_STATE_UNINITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP202_RING_ILLEGAL_IN_STATE;
+            }
+            break;
+
+         case EIP202_RDR_STATE_UNINITIALIZED:
+            switch(NewState)
+            {
+                case EIP202_RDR_STATE_INITIALIZED:
+                   *CurrentState = NewState;
+                   break;
+                default:
+                    return EIP202_RING_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP202_RDR_STATE_INITIALIZED:
+            switch(NewState)
+            {
+                case EIP202_RDR_STATE_UNINITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_RDR_STATE_FREE:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_RDR_STATE_FULL:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_RDR_STATE_INITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP202_RING_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP202_RDR_STATE_FREE:
+            switch(NewState)
+            {
+                case EIP202_RDR_STATE_UNINITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_RDR_STATE_INITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_RDR_STATE_FULL:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_RDR_STATE_FATAL_ERROR:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_RDR_STATE_FREE:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP202_RING_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP202_RDR_STATE_FULL:
+            switch(NewState)
+            {
+                case EIP202_RDR_STATE_UNINITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_RDR_STATE_INITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_RDR_STATE_FREE:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_RDR_STATE_FATAL_ERROR:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_RDR_STATE_FULL:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP202_RING_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP202_RDR_STATE_FATAL_ERROR:
+            switch(NewState)
+            {
+                case EIP202_RDR_STATE_UNINITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP202_RING_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        default:
+            return EIP202_RING_ILLEGAL_IN_STATE;
+    }
+#else
+    IDENTIFIER_NOT_USED(CurrentState);
+    IDENTIFIER_NOT_USED(NewState);
+#endif // EIP202_RING_DEBUG_FSM
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/* end of file eip202_rdr_fsm.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rdr_init.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rdr_init.c
new file mode 100644
index 0000000..6fd658c
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rdr_init.c
@@ -0,0 +1,372 @@
+/* eip202_rdr_init.c
+ *
+ * EIP-202 Ring Control Driver Library
+ * RDR Init/Reset API implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip202_rdr.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip202_ring.h"
+
+// EIP-202 Ring Control Driver Library Types API
+#include "eip202_ring_types.h"          // EIP202_Ring_* types
+
+// EIP-202 Ring Control Driver Library Internal interfaces
+#include "eip202_ring_internal.h"
+#include "eip202_rdr_level0.h"          // EIP-202 Level 0 macros
+#include "eip202_rdr_fsm.h"             // RDR State machine
+#include "eip202_rdr_dscr.h"            // RingHelper callbacks
+#include "eip202_rd_format.h"           // EIP-202 Result Descriptor
+
+// RingHelper API
+#include "ringhelper.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                // IDENTIFIER_NOT_USED, bool, uint32_t
+
+// Driver Framework Device API
+#include "device_types.h"              // Device_Handle_t
+
+// Driver Framework DMA Resource API
+#include "dmares_types.h"         // types of the DMA resource API
+#include "dmares_rw.h"            // read/write of the DMA resource API.
+
+// Driver Framework C Run-Time Library API
+#include "clib.h"
+
+// Standard IOToken API
+#include "iotoken.h"                   // IOToken_InWordCount_Get()
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP202Lib_Detect
+ *
+ * Checks the presence of EIP-202 HIA hardware. Returns true when found.
+ */
+static bool
+EIP202Lib_RDR_Detect(
+        const Device_Handle_t Device)
+{
+    uint32_t Value;
+
+    // read-write test one of the registers
+
+    // Set MASK_31_BITS bits of the EIP202_RDR_RING_BASE_ADDR_LO register
+    EIP202_RDR_Write32(Device,
+                       EIP202_RDR_RING_BASE_ADDR_LO,
+                       MASK_31_BITS );
+
+    Value = EIP202_RDR_Read32(Device, EIP202_RDR_RING_BASE_ADDR_LO);
+    if ((Value & MASK_31_BITS) != MASK_31_BITS)
+        return false;
+
+    // Clear MASK_31_BITS bits of the EIP202_RDR_RING_BASE_ADDR_LO register
+    EIP202_RDR_Write32(Device, EIP202_RDR_RING_BASE_ADDR_LO, 0);
+    Value = EIP202_RDR_Read32(Device, EIP202_RDR_RING_BASE_ADDR_LO);
+    if ((Value & MASK_31_BITS) != 0)
+       return false;
+
+    return true;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202Lib_RDR_ClearAllDescriptors
+ *
+ * Clear all descriptors
+ */
+static inline void
+EIP202Lib_RDR_ClearAllDescriptors(
+        DMAResource_Handle_t Handle,
+        const uint32_t DescriptorSpacingWordCount,
+        const uint32_t DescriptorSizeWordCount,
+        const uint32_t NumberOfDescriptors)
+{
+    unsigned int i, j;
+
+    for(i = 0; i < NumberOfDescriptors; i++)
+        for(j = 0; j < DescriptorSizeWordCount; j++)
+            DMAResource_Write32(Handle, i * DescriptorSpacingWordCount + j, 0);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Init
+ *
+ */
+EIP202_Ring_Error_t
+EIP202_RDR_Init(
+        EIP202_Ring_IOArea_t * IOArea_p,
+        const Device_Handle_t Device,
+        const EIP202_RDR_Settings_t * const RDRSettings_p)
+{
+    EIP202_Ring_Error_t rv;
+    volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p = RDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+
+    // Initialize the IO Area
+    TrueIOArea_p->Device = Device;
+    TrueIOArea_p->State = (unsigned int)EIP202_RDR_STATE_UNINITIALIZED;
+
+    // Check if the CPU integer size is enough to store 32-bit value
+    if(sizeof(unsigned int) < sizeof(uint32_t))
+        return EIP202_RING_UNSUPPORTED_FEATURE_ERROR;
+
+    // Detect presence of EIP-202 CDR hardware
+    if(!EIP202Lib_RDR_Detect(Device))
+        return EIP202_RING_UNSUPPORTED_FEATURE_ERROR;
+
+    // Extension of 32-bit pointers to 64-bit addresses not supported.
+    if(RDRSettings_p->Params.DMA_AddressMode == EIP202_RING_64BIT_DMA_EXT_ADDR)
+        return EIP202_RING_UNSUPPORTED_FEATURE_ERROR;
+
+    if(RDRSettings_p->Params.DscrOffsWordCount == 0 ||
+       RDRSettings_p->Params.DscrOffsWordCount <
+       RDRSettings_p->Params.DscrSizeWordCount)
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    // Ring size cannot be smaller than one descriptor size or
+    // larger than 4194303 (16MB / 4 - 1), in 32-bit words
+    if(RDRSettings_p->Params.RingSizeWordCount <
+       RDRSettings_p->Params.DscrOffsWordCount ||
+       RDRSettings_p->Params.RingSizeWordCount > 4194303)
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    if(RDRSettings_p->Params.DscrSizeWordCount >
+             RDRSettings_p->Params.TokenOffsetWordCount + IOToken_OutWordCount_Get())
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    if(RDRSettings_p->Params.DscrFetchSizeWordCount %
+                            RDRSettings_p->Params.DscrOffsWordCount)
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    if( RDRSettings_p->Params.IntThresholdDscrCount *
+            RDRSettings_p->Params.DscrOffsWordCount >
+                      RDRSettings_p->Params.RingSizeWordCount )
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    // Configure the Ring Helper
+    TrueIOArea_p->RingHelperCallbacks.WriteFunc_p = &EIP202_RDR_WriteCB;
+    TrueIOArea_p->RingHelperCallbacks.ReadFunc_p = &EIP202_RDR_ReadCB;
+    TrueIOArea_p->RingHelperCallbacks.StatusFunc_p = &EIP202_RDR_StatusCB;
+    TrueIOArea_p->RingHelperCallbacks.CallbackParam1_p = IOArea_p;
+    TrueIOArea_p->RingHelperCallbacks.CallbackParam2 = 0;
+    TrueIOArea_p->RingHandle = RDRSettings_p->Params.RingDMA_Handle;
+    TrueIOArea_p->DescOffsWordCount = RDRSettings_p->Params.DscrOffsWordCount;
+    TrueIOArea_p->RingSizeWordCount = RDRSettings_p->Params.RingSizeWordCount;
+    TrueIOArea_p->TokenOffsetWordCount = RDRSettings_p->Params.TokenOffsetWordCount;
+    TrueIOArea_p->PacketFound = false;
+
+    // Initialize one RingHelper instance for one RDR instance
+    if( RingHelper_Init(
+         (volatile RingHelper_t*)&TrueIOArea_p->RingHelper,
+         (volatile RingHelper_CallbackInterface_t*)&TrueIOArea_p->RingHelperCallbacks,
+         false, // One RDR as combined rings
+         (unsigned int)(RDRSettings_p->Params.RingSizeWordCount /
+             RDRSettings_p->Params.DscrOffsWordCount),
+         (unsigned int)(RDRSettings_p->Params.RingSizeWordCount /
+             RDRSettings_p->Params.DscrOffsWordCount)) < 0)
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    // Transit to a new state
+    rv = EIP202_RDR_State_Set((volatile EIP202_RDR_State_t*)&TrueIOArea_p->State,
+                             EIP202_RDR_STATE_INITIALIZED);
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+
+    // Prepare the RDR DMA buffer
+    // Initialize all descriptors with zero for RDR
+    EIP202Lib_RDR_ClearAllDescriptors(
+            TrueIOArea_p->RingHandle,
+            RDRSettings_p->Params.DscrOffsWordCount,
+            RDRSettings_p->Params.DscrSizeWordCount,
+            RDRSettings_p->Params.RingSizeWordCount /
+                 RDRSettings_p->Params.DscrOffsWordCount);
+
+    // Call PreDMA to make sure engine sees it
+    DMAResource_PreDMA(TrueIOArea_p->RingHandle,
+                       0,
+                       (unsigned int)(TrueIOArea_p->RingSizeWordCount*4));
+
+    EIP202_RDR_RING_BASE_ADDR_LO_WR(
+                       Device,
+                       RDRSettings_p->Params.RingDMA_Address.Addr);
+
+    EIP202_RDR_RING_BASE_ADDR_HI_WR(
+                       Device,
+                       RDRSettings_p->Params.RingDMA_Address.UpperAddr);
+
+    EIP202_RDR_RING_SIZE_WR(
+                       Device,
+                       RDRSettings_p->Params.RingSizeWordCount);
+
+    EIP202_RDR_DESC_SIZE_WR(
+                       Device,
+                       RDRSettings_p->Params.DscrSizeWordCount,
+                       RDRSettings_p->Params.DscrOffsWordCount,
+                       RDRSettings_p->Params.DMA_AddressMode == EIP202_RING_64BIT_DMA_DSCR_PTR);
+
+    EIP202_RDR_CFG_WR(Device,
+                      RDRSettings_p->Params.DscrFetchSizeWordCount,
+                      RDRSettings_p->Params.DscrThresholdWordCount,
+#ifdef EIP202_RDR_OWNERSHIP_WORD_ENABLE
+                      true);  // Ownership write mode
+#else
+                      RDRSettings_p->fContinuousScatter); // Normal mode, no ownership words are used.
+/* Always enable ownership words for continuous scatter */
+#endif
+
+    // Disable Processed Descriptor threshold interrupt,
+    // Disable Timeout interrupt and stop timeout counter for
+    // reducing power consumption
+    EIP202_RDR_THRESH_WR(
+                       Device,
+                       TrueIOArea_p->RingSizeWordCount,
+                       0,  // Set descriptor processing mode
+                       0); // Disable timeout
+
+    EIP202_RDR_DMA_CFG_WR(
+                       Device,
+                       (uint8_t)RDRSettings_p->Params.ByteSwap_Descriptor_Mask,
+                       (uint8_t)RDRSettings_p->Params.ByteSwap_Packet_Mask,
+
+                       // Bufferability control for DMA writes of
+                       EIP202_RING_RD_RES_BUF,  // result token
+                       EIP202_RING_RD_CTRL_BUF, // descriptor control words
+                       EIP202_RING_RD_OWN_BUF,  // ownership words
+
+                       EIP202_RING_RD_WR_CACHE_CTRL, // Write cache type control
+                       EIP202_RING_RD_RD_CACHE_CTRL, // Read cache type control
+                       EIP202_RING_RD_PROT_VALUE,
+                       EIP202_RING_DATA_PROT_VALUE,
+                       RDRSettings_p->fContinuousScatter|EIP202_RDR_PAD_TO_OFFSET); // Result descriptor padding
+/* Note: for continuous scatter: always set RDR_PAD_TO_OFFSET. */
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Reset
+ *
+ */
+EIP202_Ring_Error_t
+EIP202_RDR_Reset(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        const Device_Handle_t Device)
+{
+    EIP202_Ring_Error_t rv;
+    volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p = RDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+
+    // Initialize the IO Area
+    memset((void*)IOArea_p, 0, sizeof(*TrueIOArea_p));
+    TrueIOArea_p->Device = Device;
+    TrueIOArea_p->State = (unsigned int)EIP202_RDR_STATE_UNKNOWN;
+
+    // Transit to a new state
+    rv = EIP202_RDR_State_Set((volatile EIP202_RDR_State_t*)&TrueIOArea_p->State,
+                             EIP202_RDR_STATE_UNINITIALIZED);
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+
+    // Clear RDR count
+    EIP202_RDR_PREP_COUNT_WR(Device, 0, true);
+    EIP202_RDR_PROC_COUNT_WR(Device, 0, 0, true);
+
+    // Re-init RDR
+    EIP202_RDR_PREP_PNTR_DEFAULT_WR(Device);
+    EIP202_RDR_PROC_PNTR_DEFAULT_WR(Device);
+
+    // Restore default register values
+    EIP202_RDR_RING_BASE_ADDR_LO_DEFAULT_WR(Device);
+    EIP202_RDR_RING_BASE_ADDR_HI_DEFAULT_WR(Device);
+    EIP202_RDR_RING_SIZE_DEFAULT_WR(Device);
+    EIP202_RDR_DESC_SIZE_DEFAULT_WR(Device);
+    EIP202_RDR_CFG_DEFAULT_WR(Device);
+    EIP202_RDR_DMA_CFG_DEFAULT_WR(Device);
+    EIP202_RDR_THRESH_DEFAULT_WR(Device);
+
+    // Clear and disable all RDR interrupts
+    EIP202_RDR_STAT_CLEAR_ALL_IRQ_WR(Device);
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Dump
+ *
+ */
+void
+EIP202_RDR_Dump(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        EIP202_RingAdmin_t * const RingAdmin_p)
+{
+    EIP202_RDR_True_IOArea_t * const TrueIOArea_p =
+                            (EIP202_RDR_True_IOArea_t * const)IOArea_p;
+
+    if(!TrueIOArea_p)
+        return;
+
+    if(!RingAdmin_p)
+        return;
+
+    RingAdmin_p->IN_Size           = TrueIOArea_p->RingHelper.IN_Size;
+    RingAdmin_p->IN_Tail           = TrueIOArea_p->RingHelper.IN_Tail;
+    RingAdmin_p->OUT_Size          = TrueIOArea_p->RingHelper.OUT_Size;
+    RingAdmin_p->OUT_Head          = TrueIOArea_p->RingHelper.OUT_Head;
+
+    RingAdmin_p->fSeparate         = TrueIOArea_p->RingHelper.fSeparate;
+
+    RingAdmin_p->DescOffsWordCount = TrueIOArea_p->DescOffsWordCount;
+    RingAdmin_p->RingSizeWordCount = TrueIOArea_p->RingSizeWordCount;
+}
+
+
+/* end of file eip202_rdr_init.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_flow_dtl.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_flow_dtl.c
new file mode 100644
index 0000000..6cbdba3
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_flow_dtl.c
@@ -0,0 +1,1837 @@
+/* eip207_flow_dtl.c
+ *
+ * Partial EIP-207 Flow Control Generic API implementation and
+ * full EIP-207 Flow Control DTL API implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// EIP-207 Driver Library Flow Control Generic API
+#include "eip207_flow_dtl.h"
+
+// EIP-207 Driver Library Flow Control Generic API
+#include "eip207_flow_generic.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip207_flow.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                 // uint32_t
+
+// Driver Framework C Run-time Library API
+#include "clib.h"                       // ZEROINIT, memset, memcpy
+
+// Driver Framework Device API
+#include "device_types.h"               // Device_Handle_t
+
+// Driver Framework DMA Resource API
+#include "dmares_types.h"
+#include "dmares_rw.h"
+
+// EIP-207 Flow Control Driver Library Internal interfaces
+#include "eip207_flow_level0.h"         // EIP-207 Level 0 macros
+#include "eip207_flow_hte_dscr_dtl.h"   // HTE descriptor DTL
+#include "eip207_flow_internal.h"
+
+#ifndef EIP207_FLUE_RC_HP
+// EIP-207 (Global Control) Record Cache (RC) interface
+#include "eip207_rc.h"
+
+// EIP-207s (Global Control) Flow Look-Up Engine Cache (FLUEC) interface
+#include "eip207_fluec.h"
+#endif // !EIP207_FLUE_RC_HP
+
+// EIP-207 Firmware API
+#include "firmware_eip207_api_flow_cs.h" // Classification API: Flow Control
+#include "firmware_eip207_api_cs.h"      // Classification API: General
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+#define EIP207_FLOW_MAX_RECORDS_PER_BUCKET              3
+
+
+// Flow record input data required for the flow record creation
+typedef struct
+{
+    // Bitwise of zero or more EIP207_FLOW_FLAG_* flags, see above
+    uint32_t Flags;
+
+    // Physical (DMA/bus) address of the transform record
+    EIP207_Flow_Address_t Xform_DMA_Addr;
+
+    // Software flow record reference
+    uint32_t SW_FR_Reference;
+
+    // Transform record type, true - large, false - small
+    bool fLarge;
+} EIP207_Flow_FR_Data_t;
+
+// Transform record input data required for the transform record creation
+typedef struct
+{
+    // Transform record type, true - large, false - small
+    bool fLarge;
+
+} EIP207_Flow_TR_Data_t;
+
+// Transform record input data required for the Transform record creation
+typedef struct
+{
+    // Record hash ID
+    const EIP207_Flow_ID_t * HashID_p;
+
+    // Flow record input data, fill with NULL if not used
+    const EIP207_Flow_FR_Data_t * FR_Data_p;
+
+    // Transform record input data, fill with NULL if not used
+    const EIP207_Flow_TR_Data_t * TR_Data_p;
+
+    // Note: FR_Data_p and TR_Data_p cannot be both NULL!
+
+} EIP207_Flow_Record_InputData_t;
+
+// Full record descriptor
+typedef struct
+{
+    EIP207_Flow_Dscr_t                  RecDscr;
+
+    EIP207_Flow_HTE_Dscr_RecData_t      RecData;
+
+    void *                              Reserved_p;
+} EIP207_Flow_Rec_Dscr_t;
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_Entry_Lookup
+ */
+static void
+EIP207Lib_Flow_Entry_Lookup(
+        const uint32_t HashID_Word0,
+        const uint32_t TableSize,
+        unsigned int * const HT_Entry_ByteOffset,
+        unsigned int * const DT_Entry_Index)
+{
+    uint32_t HashID_W0, Mask;
+
+    // From the EIP-197 Programmer Manual:
+    // The hash engine completes the hash ID calculation and
+    // adds bits [(table_size+10):6] (with table_size coming from
+    // the FLUE_SIZE(_VM)_f register) of the hash ID, multiplied by 64,
+    // to the table base address given in the FLUE_HASHBASE(_VM)_f_* registers.
+
+    // Calculate the entry byte offset in the HT for this record
+    HashID_W0 = (HashID_Word0 & (~MASK_6_BITS));
+
+    Mask = (1 << (TableSize + 10 + 1)) - 1;
+
+    // Calculate the HT entry byte offset
+    *HT_Entry_ByteOffset = (unsigned int)(HashID_W0 & Mask);
+
+    // Translate the HT entry byte offset to the index in the HT
+    // HT entry size is one hash bucket (16 words = 64 bytes)
+    *DT_Entry_Index = (*HT_Entry_ByteOffset) >> 6; // divide by 64
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_TableSize_To_EntryCount
+ *
+ * Convert EIP207_Flow_HashTable_Entry_Count_t to a number
+ */
+static inline unsigned int
+EIP207Lib_Flow_TableSize_To_EntryCount(
+        const unsigned int TableSize)
+{
+    return (1 << (TableSize + 5));
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_HTE_Dscr_ByteCount_Get
+ */
+static inline unsigned int
+EIP207Lib_Flow_HTE_Dscr_ByteCount_Get(void)
+{
+    return sizeof(EIP207_Flow_HTE_Dscr_t);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_HB_Record_Add
+ *
+ * Updates Hash ID and record offset in the hash bucket,
+ * first Hash ID then record byte offset
+ */
+static inline void
+EIP207Lib_Flow_HB_Record_Add(
+        const DMAResource_Handle_t HT_DMA_Handle,
+        const unsigned int HB_ByteOffset,
+        const unsigned int slot,
+        const uint32_t Rec_ByteOffset,
+        const uint32_t RecType,
+        const EIP207_Flow_ID_t * const HashID_p)
+{
+    unsigned int i;
+    unsigned int HB_WordOffset = HB_ByteOffset >> 2;
+
+    // Write record Hash ID words
+    for (i = 0; i < EIP207_FLOW_HASH_ID_WORD_COUNT; i++)
+        DMAResource_Write32(HT_DMA_Handle,
+                            HB_WordOffset +
+                             EIP207_FLOW_HB_HASH_ID_1_WORD_OFFSET + i +
+                             EIP207_FLOW_HASH_ID_WORD_COUNT * (slot - 1),
+                            HashID_p->Word32[i]);
+
+    // Write record offset
+    DMAResource_Write32(HT_DMA_Handle,
+                        HB_WordOffset +
+                        EIP207_FLOW_HB_REC_1_WORD_OFFSET + (slot - 1),
+                        Rec_ByteOffset | RecType);
+
+    // Perform pre-DMA for this hash bucket
+    DMAResource_PreDMA(HT_DMA_Handle,
+                       HB_ByteOffset,
+                       EIP207_FLOW_HT_ENTRY_WORD_COUNT *
+                         sizeof(uint32_t));
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_HB_Record_Remove
+ *
+ * Updates Hash ID and record offset in the hash bucket,
+ * first record byte offset then Hash ID
+ */
+static inline void
+EIP207Lib_Flow_HB_Record_Remove(
+        const DMAResource_Handle_t HT_DMA_Handle,
+        const unsigned int HB_ByteOffset,
+        const unsigned int slot,
+        EIP207_Flow_ID_t * HashID_p)
+{
+    unsigned int i;
+    unsigned int HB_WordOffset = HB_ByteOffset >> 2;
+    EIP207_Flow_ID_t HashID;
+
+    // Write record offset
+    DMAResource_Write32(HT_DMA_Handle,
+                        HB_WordOffset +
+                        EIP207_FLOW_HB_REC_1_WORD_OFFSET + (slot - 1),
+                        EIP207_FLOW_RECORD_DUMMY_ADDRESS);
+
+    // Read old record Hash ID words
+    for (i = 0; i < EIP207_FLOW_HASH_ID_WORD_COUNT; i++)
+        HashID.Word32[i] = DMAResource_Read32(
+                             HT_DMA_Handle,
+                             HB_WordOffset +
+                             EIP207_FLOW_HB_HASH_ID_1_WORD_OFFSET + i +
+                             EIP207_FLOW_HASH_ID_WORD_COUNT * (slot - 1));
+
+    // Write new record Hash ID words
+    for (i = 0; i < EIP207_FLOW_HASH_ID_WORD_COUNT; i++)
+    {
+        DMAResource_Write32(HT_DMA_Handle,
+                            HB_WordOffset +
+                             EIP207_FLOW_HB_HASH_ID_1_WORD_OFFSET + i +
+                             EIP207_FLOW_HASH_ID_WORD_COUNT * (slot - 1),
+                            HashID_p->Word32[i]);
+
+        // Store old record Hash ID words
+        HashID_p->Word32[i] = HashID.Word32[i];
+    }
+
+    // Perform pre-DMA for this hash bucket
+    DMAResource_PreDMA(HT_DMA_Handle,
+                       HB_ByteOffset,
+                       EIP207_FLOW_HT_ENTRY_WORD_COUNT *
+                         sizeof(uint32_t));
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_HB_BuckOffs_Update
+ *
+ * Update bucket offset in the hash bucket (identified by HB_ByteOffset)
+ * by writing the Update_Value in there
+ */
+static inline void
+EIP207Lib_Flow_HB_BuckOffs_Update(
+        const DMAResource_Handle_t HT_DMA_Handle,
+        const unsigned int HB_ByteOffset,
+        const uint32_t Update_Value)
+{
+    unsigned int HB_WordOffset = HB_ByteOffset >> 2;
+
+    // Write record offset
+    DMAResource_Write32(HT_DMA_Handle,
+                        HB_WordOffset +
+                        EIP207_FLOW_HB_OVFL_BUCKET_WORD_OFFSET,
+                        Update_Value);
+
+    // Perform pre-DMA for this hash bucket
+    DMAResource_PreDMA(HT_DMA_Handle,
+                       HB_ByteOffset,
+                       EIP207_FLOW_HT_ENTRY_WORD_COUNT *
+                         sizeof(uint32_t));
+}
+
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_HB_HashID_Match
+ *
+ * Checks if the hash bucket already contains this Hash ID
+ */
+static bool
+EIP207Lib_Flow_HB_HashID_Match(
+        const DMAResource_Handle_t HT_DMA_Handle,
+        const unsigned int HB_ByteOffset,
+        const uint32_t RecType,
+        const EIP207_Flow_ID_t * const HashID_p)
+{
+    uint32_t Word32;
+    bool fMatch;
+    unsigned int i, j;
+    unsigned int HB_WordOffset = HB_ByteOffset >> 2;
+
+    // Read Hash ID's from the bucket
+    // (this DMA resource is read-only for the FLUE device)
+    for (i = 0; i < EIP207_FLOW_HTE_BKT_NOF_REC_MAX; i++)
+    {
+        for (j = 0; j < EIP207_FLOW_HASH_ID_WORD_COUNT; j++)
+        {
+            fMatch = true;
+
+            Word32 = DMAResource_Read32(
+                                 HT_DMA_Handle,
+                                 HB_WordOffset +
+                                  EIP207_FLOW_HB_HASH_ID_1_WORD_OFFSET +
+                                    i * EIP207_FLOW_HASH_ID_WORD_COUNT + j);
+
+            if (Word32 != HashID_p->Word32[j])
+            {
+                fMatch = false;
+                break; // No match, skip this hash ID
+            }
+        } // for
+
+        if (fMatch)
+            break; // Matching Hash ID found, stop searching
+    } // for
+
+    if (fMatch)
+    {
+        uint32_t Match_RecType;
+
+        // Check the record type in the record offset for Hash ID with index i
+        // to confirm the match
+        Word32 = DMAResource_Read32(
+                             HT_DMA_Handle,
+                             HB_WordOffset +
+                              EIP207_FLOW_HB_REC_1_WORD_OFFSET + i);
+
+        // Note: small transform record and large transform record
+        //       fall under the same record type for this check!
+        Match_RecType = Word32 & RecType;
+
+        if ((Match_RecType == EIP207_FLOW_RECORD_FR_ADDRESS  &&
+             (RecType == EIP207_FLOW_RECORD_TR_ADDRESS         ||
+              RecType == EIP207_FLOW_RECORD_TR_LARGE_ADDRESS))    ||
+
+            (RecType == EIP207_FLOW_RECORD_FR_ADDRESS        &&
+             (Match_RecType == EIP207_FLOW_RECORD_TR_ADDRESS   ||
+              Match_RecType == EIP207_FLOW_RECORD_TR_LARGE_ADDRESS)))
+        {
+            // Match not confirmed, a different record type is used
+            fMatch = false;
+        }
+    }
+
+    return fMatch;
+}
+#endif // EIP207_FLOW_CONSISTENCY_CHECK
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_HB_Slot_Get
+ *
+ * Determine the free offset slot number (1,2 or 3) and claim it
+ */
+static inline EIP207_Flow_Error_t
+EIP207Lib_Flow_HB_Slot_Get(
+        uint32_t * const RecOffsMask_p,
+        unsigned int * FreeSlot_p)
+{
+    if ((*RecOffsMask_p & EIP207_FLOW_HTE_REC_OFFSET_1) == 0)
+    {
+        *FreeSlot_p = 1;
+        *RecOffsMask_p |= EIP207_FLOW_HTE_REC_OFFSET_1;
+    }
+    else if((*RecOffsMask_p & EIP207_FLOW_HTE_REC_OFFSET_2) == 0)
+    {
+        *FreeSlot_p = 2;
+        *RecOffsMask_p |= EIP207_FLOW_HTE_REC_OFFSET_2;
+    }
+    else if((*RecOffsMask_p & EIP207_FLOW_HTE_REC_OFFSET_3) == 0)
+    {
+        *FreeSlot_p = 3;
+        *RecOffsMask_p |= EIP207_FLOW_HTE_REC_OFFSET_3;
+    }
+    else
+        // Consistency checks for the found HTE descriptor
+        return EIP207_FLOW_INTERNAL_ERROR;
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_HB_Slot_Put
+ *
+ * Determine the used offset slot number (1,2 or 3) and release it
+ */
+static inline EIP207_Flow_Error_t
+EIP207Lib_Flow_HB_Slot_Put(
+        uint32_t * const RecOffsMask_p,
+        const unsigned int Slot)
+{
+    switch (Slot)
+    {
+        case 1:
+            *RecOffsMask_p &= ~EIP207_FLOW_HTE_REC_OFFSET_1;
+            break;
+
+        case 2:
+            *RecOffsMask_p &= ~EIP207_FLOW_HTE_REC_OFFSET_2;
+            break;
+
+        case 3:
+            *RecOffsMask_p &= ~EIP207_FLOW_HTE_REC_OFFSET_3;
+            break;
+
+        default:
+            // Consistency checks for the slot to release
+            return EIP207_FLOW_INTERNAL_ERROR;
+    }
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_Dscr_InternalData_Set
+ */
+static inline void
+EIP207Lib_Flow_Dscr_InternalData_Set(
+        EIP207_Flow_Dscr_t * const Dscr_p)
+{
+    EIP207_Flow_Rec_Dscr_t * p = (EIP207_Flow_Rec_Dscr_t*)Dscr_p;
+
+    Dscr_p->InternalData_p = &p->RecData;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_FR_Write
+ */
+static void
+EIP207Lib_Flow_FR_Write(
+        const DMAResource_Handle_t DMA_Handle,
+        const EIP207_Flow_FR_Data_t * const FR_Data_p,
+        const uint32_t Xform_ByteOffset,
+        const uint32_t Xform_Addr,
+        const uint32_t Xform_UpperAddr)
+{
+    unsigned int i;
+    uint32_t Record_Type;
+
+    // Write flow record with 0's
+    for (i = 0; i < FIRMWARE_EIP207_CS_FRC_RECORD_WORD_COUNT; i++)
+        DMAResource_Write32(DMA_Handle, i, 0);
+
+#ifdef EIP207_FLOW_NO_TYPE_BITS_IN_FLOW_RECORD
+    Record_Type = 0;
+#else
+    Record_Type = FR_Data_p->fLarge ?
+        EIP207_FLOW_RECORD_TR_LARGE_ADDRESS :
+        EIP207_FLOW_RECORD_TR_ADDRESS;
+#endif
+
+    // Write Transform Record 32-bit offset
+    DMAResource_Write32(DMA_Handle,
+                        FIRMWARE_EIP207_CS_FLOW_FR_XFORM_OFFS_WORD_OFFSET,
+                        Xform_ByteOffset + Record_Type);
+
+    // Write Transform Record low half of 64-bit address
+    DMAResource_Write32(DMA_Handle,
+                        FIRMWARE_EIP207_CS_FLOW_FR_XFORM_ADDR_WORD_OFFSET,
+                        Xform_Addr + Record_Type);
+
+    // Write Transform Record high half of 64-bit address
+    DMAResource_Write32(DMA_Handle,
+                        FIRMWARE_EIP207_CS_FLOW_FR_XFORM_ADDR_HI_WORD_OFFSET,
+                        Xform_UpperAddr);
+
+    // Not supported yet
+    // Write ARC4 State Record physical address
+    //DMAResource_Write32(FR_Dscr_p->Data.DMA_Handle,
+    //                    FIRMWARE_EIP207_CS_FLOW_FR_ARC4_ADDR_WORD_OFFSET,
+    //                    EIP207_FLOW_RECORD_DUMMY_ADDRESS);
+
+    // Write Software Flow Record Reference
+    // NOTE: this is a 32-bit value!
+    DMAResource_Write32(DMA_Handle,
+                        FIRMWARE_EIP207_CS_FLOW_FR_SW_ADDR_WORD_OFFSET,
+                        FR_Data_p->SW_FR_Reference);
+
+    // Write the Flags field
+    DMAResource_Write32(DMA_Handle,
+                        FIRMWARE_EIP207_CS_FLOW_FR_FLAGS_WORD_OFFSET,
+                        FR_Data_p->Flags);
+
+    // Perform pre-DMA for the entire flow record
+    DMAResource_PreDMA(DMA_Handle, 0, 0);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_DTL_Record_Add
+ */
+static EIP207_Flow_Error_t
+EIP207Lib_Flow_DTL_Record_Add(
+        volatile EIP207_Flow_HT_Params_t * const HT_Params_p,
+        EIP207_Flow_Dscr_t * const Rec_Dscr_p,
+        const EIP207_Flow_Record_InputData_t * const RecData_p)
+{
+    uint32_t Rec_ByteOffset;
+    unsigned int slot = 0;
+    EIP207_Flow_HTE_Dscr_t * HTE_Dscr_Updated_p = NULL;
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+    // Consistency check for the provided record descriptor
+    if (Rec_Dscr_p->DMA_Addr.Addr == EIP207_FLOW_RECORD_DUMMY_ADDRESS)
+        return EIP207_FLOW_INTERNAL_ERROR;
+#endif // EIP207_FLOW_CONSISTENCY_CHECK
+
+    // Add the record to the Hash Table
+    {
+        EIP207_Flow_HTE_Dscr_t * HTE_Dscr_p;
+        unsigned int Entry_Index, HTE_ByteOffset, HT_TableSize;
+        uint32_t Record_Type = EIP207_FLOW_RECORD_DUMMY_ADDRESS;
+        DMAResource_Handle_t HT_DMA_Handle = HT_Params_p->HT_DMA_Handle;
+
+        // Transform record
+        if (RecData_p->TR_Data_p != NULL)
+            Record_Type = RecData_p->TR_Data_p->fLarge ?
+                            EIP207_FLOW_RECORD_TR_LARGE_ADDRESS :
+                                       EIP207_FLOW_RECORD_TR_ADDRESS;
+        // Flow record
+        else if (RecData_p->FR_Data_p != NULL)
+            Record_Type = EIP207_FLOW_RECORD_FR_ADDRESS;
+        else
+            return EIP207_FLOW_INTERNAL_ERROR; // Unknown record, error
+
+        HT_TableSize = HT_Params_p->HT_TableSize;
+
+        HTE_ByteOffset  = 0;
+        Entry_Index     = 0;
+
+        EIP207Lib_Flow_Entry_Lookup(
+                RecData_p->HashID_p->Word32[0], // Word 0 is used for lookup
+                HT_TableSize,
+                &HTE_ByteOffset,
+                &Entry_Index);
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+        {
+            unsigned int HT_EntryCount =
+                    EIP207Lib_Flow_TableSize_To_EntryCount(HT_TableSize);
+
+            if (Entry_Index >= HT_EntryCount)
+                return EIP207_FLOW_INTERNAL_ERROR;
+        }
+#endif
+
+        // Calculate the record byte offset,
+        // HT_Params_p->BaseAddr.Addr is the base
+        // address of the DMA bank where the record
+        // must have been allocated
+        Rec_ByteOffset = Rec_Dscr_p->DMA_Addr.Addr - HT_Params_p->BaseAddr.Addr;
+
+        // Convert the DT entry index to the HTE descriptor pointer
+        {
+            void * p;
+            unsigned char * DT_p = (unsigned char*)HT_Params_p->DT_p;
+
+            // Read the entry value at the calculated offset from the DT
+            p = DT_p + Entry_Index * EIP207Lib_Flow_HTE_Dscr_ByteCount_Get();
+
+            HTE_Dscr_p = (EIP207_Flow_HTE_Dscr_t*)p;
+        }
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+        // Consistency checks for the found HTE descriptor
+        if (HTE_Dscr_p->Bucket_ByteOffset != (uint32_t)HTE_ByteOffset)
+            return EIP207_FLOW_INTERNAL_ERROR;
+
+        // Check that this HTE is not an overflow one
+        if (HTE_Dscr_p->fOverflowBucket)
+            return EIP207_FLOW_INTERNAL_ERROR;
+#endif // EIP207_FLOW_CONSISTENCY_CHECK
+
+        do // Walk the bucket chain, look for bucket where record can be added
+        {
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+            if (HTE_Dscr_p->RecordCount > EIP207_FLOW_MAX_RECORDS_PER_BUCKET)
+                return EIP207_FLOW_INTERNAL_ERROR;
+
+            // Check if the hash bucket does not contain this Hash ID already
+            if (HTE_Dscr_Updated_p == NULL && EIP207Lib_Flow_HB_HashID_Match(
+                     HT_DMA_Handle,
+                     HTE_Dscr_p->Bucket_ByteOffset,
+                     Record_Type,
+                     RecData_p->HashID_p))
+                return EIP207_FLOW_INTERNAL_ERROR;
+#endif // EIP207_FLOW_CONSISTENCY_CHECK
+
+            // Check if the found hash bucket can be used to add
+            // the record or a next bucket in the chain must be used
+            if (HTE_Dscr_p->RecordCount < EIP207_FLOW_MAX_RECORDS_PER_BUCKET)
+            {
+                uint32_t TempMask = HTE_Dscr_p->UsedRecOffsMask;
+                uint32_t TempSlot = slot;
+
+                // Use the found bucket to add the record
+
+                // Determine the offset slot (1,2 or 3) where the record offset
+                // and Hash ID can be stored
+                {
+                    EIP207_Flow_Error_t Flow_Rc =
+                            EIP207Lib_Flow_HB_Slot_Get(
+                                    &TempMask,
+                                    &TempSlot);
+
+                    if(Flow_Rc != EIP207_FLOW_NO_ERROR)
+                        return Flow_Rc;
+                }
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+                // Check if the record offset in the HTE slot is a dummy pointer
+                {
+                    // Read record offset
+                    // (this DMA resource is read-only for the FLUE device)
+                    uint32_t Record_ByteOffset =
+                                DMAResource_Read32(
+                                         HT_DMA_Handle,
+                                         (HTE_Dscr_p->Bucket_ByteOffset >> 2) +
+                                           EIP207_FLOW_HB_REC_1_WORD_OFFSET +
+                                            (TempSlot - 1));
+
+                    if ((Record_ByteOffset &
+                         EIP207_FLOW_RECORD_ADDRESS_TYPE_BITS) !=
+                            EIP207_FLOW_RECORD_DUMMY_ADDRESS)
+                        return EIP207_FLOW_INTERNAL_ERROR;
+                }
+#endif // EIP207_FLOW_CONSISTENCY_CHECK
+
+                // Add the record only if it has not been done already
+                if (HTE_Dscr_Updated_p == NULL)
+                {
+                    HTE_Dscr_p->UsedRecOffsMask = TempMask;
+                    slot = TempSlot;
+
+                    // If flow record is added then write it
+                    if (RecData_p->FR_Data_p != NULL)
+                        EIP207Lib_Flow_FR_Write(
+                                 Rec_Dscr_p->DMA_Handle,
+                                 RecData_p->FR_Data_p,
+                                 RecData_p->FR_Data_p->Xform_DMA_Addr.Addr -
+                                 HT_Params_p->BaseAddr.Addr,
+                                 RecData_p->FR_Data_p->Xform_DMA_Addr.Addr,
+                                 RecData_p->FR_Data_p->Xform_DMA_Addr.UpperAddr);
+
+                    // Update the found hash bucket with the
+                    // record Hash ID and offset
+
+                    // CDS point: after this operation is done the FLUE
+                    //            hardware can find the transform record!
+                    EIP207Lib_Flow_HB_Record_Add(HT_DMA_Handle,
+                                             HTE_Dscr_p->Bucket_ByteOffset,
+                                             slot,
+                                             Rec_ByteOffset,
+                                             Record_Type,
+                                             RecData_p->HashID_p);
+
+                    // Increase the HTE descriptor record count
+                    // for the added record
+                    HTE_Dscr_p->RecordCount++;
+                }
+
+                // The found HTE is updated, record is added
+                if (HTE_Dscr_Updated_p == NULL)
+                    HTE_Dscr_Updated_p = HTE_Dscr_p;
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+                // Get the next HTE descriptor in the chain
+                HTE_Dscr_p = EIP207_Flow_HTE_Dscr_List_Next_Get(HTE_Dscr_p);
+                continue; // Validate the entire chain
+#else
+                break;
+#endif
+            }
+            else // Found bucket record count is max possible
+            {
+                EIP207_Flow_HTE_Dscr_t * HTE_Dscr_Next_p;
+
+                // Use a next overflow bucket to add the record, find a bucket
+                // in the chain with a free slot for the new record
+
+                // Get the next HTE descriptor in the chain
+                HTE_Dscr_Next_p =
+                           EIP207_Flow_HTE_Dscr_List_Next_Get(HTE_Dscr_p);
+
+                // Check if we have one and
+                // that the record has not been added already
+                if (HTE_Dscr_Next_p == NULL && HTE_Dscr_Updated_p == NULL)
+                {
+                    // No chain is present for HTE_Dscr_p.
+                    // Link a new HTE descriptor from the free list to
+                    // the found HTE descriptor
+
+                    EIP207_Flow_HTE_Dscr_t * FreeList_Head_p;
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+                    // Check if the overflow bucket offset is a dummy pointer
+                    {
+                        // Read the overflow bucket offset
+                        // (this DMA resource is read-only for the FLUE device)
+                        uint32_t Bucket_ByteOffset =
+                                DMAResource_Read32(
+                                    HT_DMA_Handle,
+                                    (HTE_Dscr_p->Bucket_ByteOffset >> 2) +
+                                      EIP207_FLOW_HB_OVFL_BUCKET_WORD_OFFSET);
+
+                        if (Bucket_ByteOffset !=
+                                EIP207_FLOW_RECORD_DUMMY_ADDRESS)
+                            return EIP207_FLOW_INTERNAL_ERROR;
+                    }
+#endif // EIP207_FLOW_CONSISTENCY_CHECK
+
+                    FreeList_Head_p =
+                        (EIP207_Flow_HTE_Dscr_t*)HT_Params_p->FreeList_Head_p;
+
+                    // Check if the record can be added
+                    if (FreeList_Head_p == NULL)
+                        // Out of descriptors for overflow buckets
+                        return EIP207_FLOW_OUT_OF_MEMORY_ERROR;
+
+                    slot = 1; // start with slot 1 in the new bucket
+
+                    // Get a free HTE descriptor from the free list head
+                    HTE_Dscr_Next_p =
+                          EIP207_Flow_HTE_Dscr_List_Next_Get(FreeList_Head_p);
+
+                    // Check if the last descriptor is present in the free list
+                    if (HTE_Dscr_Next_p == NULL)
+                    {
+                        HTE_Dscr_Next_p = FreeList_Head_p;
+                        HT_Params_p->FreeList_Head_p = NULL; // List is empty
+                    }
+                    else
+                    {
+                        // Remove the got HTE descriptor from the free list
+                        EIP207_Flow_HTE_Dscr_List_Remove(HTE_Dscr_Next_p);
+                    }
+
+                    // Add the got HTE descriptor to the overflow chain,
+                    // we know that HTE_Dscr_p is the last descriptor
+                    // in the chain
+                    EIP207_Flow_HTE_Dscr_List_Next_Set(HTE_Dscr_p,
+                                                       HTE_Dscr_Next_p);
+                    EIP207_Flow_HTE_Dscr_List_Prev_Set(HTE_Dscr_Next_p,
+                                                       HTE_Dscr_p);
+
+                    // We add first record to the bucket which HTE descriptor
+                    // just fresh-taken from the free list
+                    HTE_Dscr_Next_p->UsedRecOffsMask =
+                                       EIP207_FLOW_HTE_REC_OFFSET_1;
+
+                    // If flow record is added then write it
+                    if (RecData_p->FR_Data_p != NULL)
+                        EIP207Lib_Flow_FR_Write(
+                                 Rec_Dscr_p->DMA_Handle,
+                                 RecData_p->FR_Data_p,
+                                 RecData_p->FR_Data_p->Xform_DMA_Addr.Addr -
+                                 HT_Params_p->BaseAddr.Addr,
+                                 RecData_p->FR_Data_p->Xform_DMA_Addr.Addr,
+                                 RecData_p->FR_Data_p->Xform_DMA_Addr.UpperAddr);
+
+                    // Update the overflow bucket with hash ID and record offset
+                    EIP207Lib_Flow_HB_Record_Add(HT_DMA_Handle,
+                                             HTE_Dscr_Next_p->Bucket_ByteOffset,
+                                             slot,
+                                             Rec_ByteOffset,
+                                             Record_Type,
+                                             RecData_p->HashID_p);
+
+                    // CDS point: after the next write32() operation is done
+                    //            the FLUE HW can find the overflow bucket!
+
+                    // Update bucket offset to the found bucket
+                    // Note: bucket offset can use any address (pointer) type
+                    //       but not NULL!
+                    EIP207Lib_Flow_HB_BuckOffs_Update(
+                                           HT_DMA_Handle,
+                                           HTE_Dscr_p->Bucket_ByteOffset,
+                                           HTE_Dscr_Next_p->Bucket_ByteOffset |
+                                             EIP207_FLOW_RECORD_TR_ADDRESS);
+
+                    // Increment record count for the added record
+                    HTE_Dscr_Next_p->RecordCount++;
+
+                    // Bucket is updated, record is added
+                    if (HTE_Dscr_Updated_p == NULL)
+                        HTE_Dscr_Updated_p = HTE_Dscr_Next_p;
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+                    HTE_Dscr_p = HTE_Dscr_Next_p;
+                    continue; // Validate the entire chain
+#else
+                    break;
+#endif
+                }
+                else // Overflow chain is present for the found HTE_Dscr_p
+                {
+                    // HTE_Dscr_p - last found HTE descriptor in the chain
+                    // HTE_Dscr_Next_p - next HTE descriptor for HTE_Dscr_p
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+                    if (HTE_Dscr_Next_p != NULL)
+                    {
+                        // Consistency checks: next HTE descriptor must be on
+                        //                     the overflow chain
+                        if (!HTE_Dscr_Next_p->fOverflowBucket)
+                            return EIP207_FLOW_INTERNAL_ERROR;
+
+                        // Check if the overflow bucket offset is
+                        // a dummy pointer
+                        {
+                            // Read the overflow bucket offset
+                            // from the previous bucket
+                            uint32_t Bucket_ByteOffset =
+                                DMAResource_Read32(
+                                       HT_DMA_Handle,
+                                       (HTE_Dscr_p->Bucket_ByteOffset >> 2) +
+                                       EIP207_FLOW_HB_OVFL_BUCKET_WORD_OFFSET);
+
+                            if (Bucket_ByteOffset !=
+                                (HTE_Dscr_Next_p->Bucket_ByteOffset|
+                                EIP207_FLOW_RECORD_TR_ADDRESS))
+                                return EIP207_FLOW_INTERNAL_ERROR;
+                        }
+                    }
+#endif // EIP207_FLOW_CONSISTENCY_CHECK
+
+                    HTE_Dscr_p = HTE_Dscr_Next_p;
+                    continue;
+
+                } // overflow bucket is found
+
+            } // "bucket full" handling is done
+
+        } while(HTE_Dscr_p != NULL);
+
+    } // Record is added to the Hash Table
+
+    // Fill in record descriptor internal data
+    {
+        EIP207_Flow_HTE_Dscr_RecData_t * Rec_DscrData_p;
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+        // Check if the free slot number was found and
+        // the HTE descriptor to update was found
+        if (slot == 0 || HTE_Dscr_Updated_p == NULL)
+            return EIP207_FLOW_INTERNAL_ERROR;
+#endif
+
+        EIP207Lib_Flow_Dscr_InternalData_Set(Rec_Dscr_p);
+        Rec_DscrData_p =
+              (EIP207_Flow_HTE_Dscr_RecData_t*)Rec_Dscr_p->InternalData_p;
+
+        Rec_DscrData_p->Slot         = slot;
+        Rec_DscrData_p->HTE_Dscr_p   = HTE_Dscr_Updated_p;
+
+        if (RecData_p->TR_Data_p != NULL)
+        {
+            if (RecData_p->TR_Data_p->fLarge)
+                Rec_DscrData_p->Type = EIP207_FLOW_REC_TRANSFORM_LARGE;
+            else
+                Rec_DscrData_p->Type = EIP207_FLOW_REC_TRANSFORM_SMALL;
+        }
+        else if (RecData_p->FR_Data_p != NULL)
+            Rec_DscrData_p->Type = EIP207_FLOW_REC_FLOW;
+        else
+            return EIP207_FLOW_INTERNAL_ERROR;
+    }
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_DTL_Record_Remove
+ */
+static EIP207_Flow_Error_t
+EIP207Lib_Flow_DTL_Record_Remove(
+        const Device_Handle_t Device,
+        const unsigned int HashTableId,
+        volatile EIP207_Flow_HT_Params_t * const HT_Params_p,
+        EIP207_Flow_Dscr_t * const Rec_Dscr_p)
+{
+    EIP207_Flow_ID_t HashID;
+    DMAResource_Handle_t HT_DMA_Handle;
+    EIP207_Flow_HTE_Dscr_t * HTE_Dscr_p;
+    EIP207_Flow_HTE_Dscr_RecData_t * Rec_DscrData_p =
+               (EIP207_Flow_HTE_Dscr_RecData_t*)Rec_Dscr_p->InternalData_p;
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+    // Consistency check for the provided TR descriptor
+    if (Rec_Dscr_p->DMA_Addr.Addr == EIP207_FLOW_RECORD_DUMMY_ADDRESS)
+        return EIP207_FLOW_INTERNAL_ERROR;
+
+    if (Rec_DscrData_p == NULL)
+        return EIP207_FLOW_INTERNAL_ERROR;
+#endif // EIP207_FLOW_CONSISTENCY_CHECK
+
+    // get the HTE descriptor for the record to remove
+    HTE_Dscr_p = Rec_DscrData_p->HTE_Dscr_p;
+
+    HT_DMA_Handle = HT_Params_p->HT_DMA_Handle;
+
+    ZEROINIT(HashID);
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+    // Check record count is sane
+    if (HTE_Dscr_p->RecordCount > EIP207_FLOW_MAX_RECORDS_PER_BUCKET ||
+        HTE_Dscr_p->RecordCount == 0)
+        return EIP207_FLOW_INTERNAL_ERROR;
+
+    // Check the record descriptor slot number
+    if (Rec_DscrData_p->Slot < 1 || Rec_DscrData_p->Slot > 3)
+        return EIP207_FLOW_INTERNAL_ERROR; // Incorrect record slot number
+
+    // Check the record offset calculated from the record descriptor
+    // matches the one on the bucket
+    {
+        uint32_t Rec_ByteOffset2;
+        uint32_t Rec_ByteOffset1 =
+                DMAResource_Read32(HT_DMA_Handle,
+                                   (HTE_Dscr_p->Bucket_ByteOffset >> 2) +
+                                     EIP207_FLOW_HB_REC_1_WORD_OFFSET +
+                                       (Rec_DscrData_p->Slot - 1));
+
+        // Clear the bits that specify the record type
+        Rec_ByteOffset1 &= (~EIP207_FLOW_RECORD_ADDRESS_TYPE_BITS);
+
+        // Calculate the record byte offset,
+        // HT_Params_p->BaseAddr.Addr is the base
+        // address of the DMA bank where the record
+        // must have been allocated
+        Rec_ByteOffset2 = Rec_Dscr_p->DMA_Addr.Addr -
+                                            HT_Params_p->BaseAddr.Addr;
+
+        if (Rec_ByteOffset1 != Rec_ByteOffset2)
+            return EIP207_FLOW_INTERNAL_ERROR; // Incorrect record offset
+    }
+#endif // EIP207_FLOW_CONSISTENCY_CHECK
+
+    if (HTE_Dscr_p->RecordCount > 1)
+    {
+        // Remove the non-last record from the bucket
+
+        EIP207_Flow_Error_t Flow_Rc;
+
+        // CDS point: record is removed when the next function returns!
+
+        // Update the record offset in the bucket.
+        // Update the Hash ID (optional)
+        EIP207Lib_Flow_HB_Record_Remove(HT_DMA_Handle,
+                                        HTE_Dscr_p->Bucket_ByteOffset,
+                                        Rec_DscrData_p->Slot,
+                                        &HashID);
+
+        // Mark this record slot as free in the HTE descriptor
+        Flow_Rc = EIP207Lib_Flow_HB_Slot_Put(&HTE_Dscr_p->UsedRecOffsMask,
+                                             Rec_DscrData_p->Slot);
+        if (Flow_Rc != EIP207_FLOW_NO_ERROR)
+            return Flow_Rc;
+
+        // Decrease record count in the HTE descriptor
+        HTE_Dscr_p->RecordCount--;
+    }
+    else // record count = 1, so when removing the record also remove the bucket
+    {
+        // Remove the last record from the removed bucket.
+        // Also remove the bucket from the chain first.
+
+        if (HTE_Dscr_p->fOverflowBucket)
+        {
+            // Remove the last record from the overflow bucket
+
+            EIP207_Flow_HTE_Dscr_t * FreeList_Head_p;
+
+            // Get the neighboring HTE descriptors in the chain
+            EIP207_Flow_HTE_Dscr_t * HTE_Dscr_Prev_p =
+                           EIP207_Flow_HTE_Dscr_List_Prev_Get(HTE_Dscr_p);
+            EIP207_Flow_HTE_Dscr_t * HTE_Dscr_Next_p =
+                           EIP207_Flow_HTE_Dscr_List_Next_Get(HTE_Dscr_p);
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+            // Check if the previous HTE descriptor is not NULL,
+            // it may not be NULL for the overflow bucket
+            if (HTE_Dscr_Prev_p == NULL)
+                return EIP207_FLOW_INTERNAL_ERROR;
+#endif
+
+            // CDS point: bucket (and record) is removed when
+            //            the next function returns and the wait loop is done!
+
+            // Remove HTE_Dscr_p bucket from the chain,
+            // make the HTE_Dscr_Prev_p bucket refer to HTE_Dscr_Next_p bucket
+            // Note: bucket offset can use any address (pointer) type
+            //       but not NULL!
+            EIP207Lib_Flow_HB_BuckOffs_Update(
+                                     HT_DMA_Handle,
+                                     HTE_Dscr_Prev_p->Bucket_ByteOffset,
+                                     HTE_Dscr_Next_p ? // the last in chain?
+                                         (HTE_Dscr_Next_p->Bucket_ByteOffset |
+                                             EIP207_FLOW_RECORD_TR_ADDRESS) :
+                                          EIP207_FLOW_RECORD_DUMMY_ADDRESS);
+
+            // Wait loop: this is to wait for the EIP-207 packet classification
+            //            engine to complete processing using this bucket
+            //            before it can be re-used for another record lookup
+            {
+                unsigned int LoopCount, Value = 1;
+
+                for (LoopCount = 0;
+                     LoopCount < EIP207_FLOW_RECORD_REMOVE_WAIT_COUNT;
+                     LoopCount++)
+                {
+                    // Do some work in the loop
+                    if (LoopCount & BIT_0)
+                        Value <<= 1;
+                    else
+                        Value >>= 1;
+                }
+            } // HB remove wait loop is done!
+
+            // Remove record from the HTE_Dscr_p bucket
+            // which is not in the chain anymore
+            EIP207Lib_Flow_HB_Record_Remove(HT_DMA_Handle,
+                                            HTE_Dscr_p->Bucket_ByteOffset,
+                                            Rec_DscrData_p->Slot,
+                                            &HashID);
+
+            // Update the bucket offset in the removed from the chain
+            // HTE_Dscr_p bucket
+            EIP207Lib_Flow_HB_BuckOffs_Update(
+                                     HT_DMA_Handle,
+                                     HTE_Dscr_p->Bucket_ByteOffset,
+                                     EIP207_FLOW_RECORD_DUMMY_ADDRESS);
+
+            // Remove HTE descriptor from the chain
+            EIP207_Flow_HTE_Dscr_List_Remove(HTE_Dscr_p);
+
+            // Add the HTE descriptor to the free list
+            FreeList_Head_p =
+                    (EIP207_Flow_HTE_Dscr_t*)HT_Params_p->FreeList_Head_p;
+
+            // Insert the HTE descriptor at the free list head
+            if (FreeList_Head_p != NULL)
+                EIP207_Flow_HTE_Dscr_List_Insert(FreeList_Head_p, HTE_Dscr_p);
+        }
+        else
+        {
+            // Remove the last record from the HT bucket
+            // Note: the chain may still be present for this HTE_Dscr_p bucket
+
+            // CDS point: record is removed when the next function returns!
+
+            // Update the record offset in the bucket.
+            // Update the Hash ID (optional)
+            EIP207Lib_Flow_HB_Record_Remove(HT_DMA_Handle,
+                                            HTE_Dscr_p->Bucket_ByteOffset,
+                                            Rec_DscrData_p->Slot,
+                                            &HashID);
+
+            // Wait loop: this is to wait for the EIP-207 packet classification
+            //            engine to complete processing using this bucket
+            //            before it can be re-used for another record lookup
+            {
+                unsigned int LoopCount, Value = 1;
+
+                for (LoopCount = 0;
+                     LoopCount < EIP207_FLOW_RECORD_REMOVE_WAIT_COUNT;
+                     LoopCount++)
+                {
+                    // Do some work in the loop
+                    if (LoopCount & BIT_0)
+                        Value <<= 1;
+                    else
+                        Value >>= 1;
+                }
+            } // HB remove wait loop is done!
+
+            // Mark this record slot as free in the HTE descriptor
+            EIP207Lib_Flow_HB_Slot_Put(&HTE_Dscr_p->UsedRecOffsMask,
+                                       Rec_DscrData_p->Slot);
+        }
+
+        // Update the HTE_Dscr_p record offset mask and record count
+        HTE_Dscr_p->UsedRecOffsMask = 0;
+        HTE_Dscr_p->RecordCount = 0;
+    }
+
+#ifndef EIP207_FLUE_RC_HP
+    // Invalidate lookup result in the FLUEC
+    EIP207_FLUEC_Invalidate(Device,
+                            (uint8_t)HashTableId,
+                            HashID.Word32[0],
+                            HashID.Word32[1],
+                            HashID.Word32[2],
+                            HashID.Word32[3]);
+#else
+    IDENTIFIER_NOT_USED(Device);
+    IDENTIFIER_NOT_USED(HashTableId);
+#endif
+
+    // Invalidate the internal data of the DTL transform record descriptor
+    Rec_DscrData_p->Slot         = 0;
+    Rec_DscrData_p->HTE_Dscr_p   = NULL;
+    Rec_DscrData_p->Type         = EIP207_FLOW_REC_INVALID;
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+#ifdef EIP207_FLOW_STRICT_ARGS
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_Is32bitAddressable
+ */
+static bool
+EIP207Lib_Flow_Is32bitAddressable(
+        const uint32_t BaseAddrLo,
+        const uint32_t BaseAddrHi,
+        const uint32_t AddrLo,
+        const uint32_t AddrHi)
+{
+    if(BaseAddrHi == AddrHi)
+    {
+        if(BaseAddrLo > AddrLo)
+            return false;
+    }
+    else if (BaseAddrHi < AddrHi && (BaseAddrHi == AddrHi + 1))
+    {
+        if(BaseAddrLo <= AddrLo)
+            return false;
+    }
+    else
+        return false;
+
+    return true;
+}
+#endif // EIP207_FLOW_STRICT_ARGS
+
+
+/*****************************************************************************
+ * Generic API functions implemented in DTL-specific way
+ */
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_HTE_Dscr_ByteCount_Get
+ */
+unsigned int
+EIP207_Flow_HTE_Dscr_ByteCount_Get(void)
+{
+    return EIP207Lib_Flow_HTE_Dscr_ByteCount_Get();
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_FR_Dscr_ByteCount_Get
+ */
+unsigned int
+EIP207_Flow_FR_Dscr_ByteCount_Get(void)
+{
+    return sizeof(EIP207_Flow_Rec_Dscr_t);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_TR_Dscr_ByteCount_Get
+ */
+unsigned int
+EIP207_Flow_TR_Dscr_ByteCount_Get(void)
+{
+    return sizeof(EIP207_Flow_Rec_Dscr_t);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_Record_Dummy_Addr_Get
+ */
+unsigned int
+EIP207_Flow_Record_Dummy_Addr_Get(void)
+{
+    return EIP207_FLOW_RECORD_DUMMY_ADDRESS;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_HashTable_Install
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_HashTable_Install(
+        EIP207_Flow_IOArea_t * const IOArea_p,
+        const unsigned int HashTableId,
+        const EIP207_Flow_HT_t * HT_p,
+        bool fLookupCached,
+        bool fReset)
+{
+    unsigned int i, EntryCount;
+    Device_Handle_t Device;
+    volatile EIP207_Flow_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP207_FLOW_CHECK_POINTER(IOArea_p);
+    EIP207_FLOW_CHECK_POINTER(HT_p->HT_DMA_Address_p);
+    EIP207_FLOW_CHECK_POINTER(HT_p->DT_p);
+    EIP207_FLOW_CHECK_INT_ATMOST(HashTableId + 1,
+                                 EIP207_FLOW_MAX_NOF_FLOW_HASH_TABLES_TO_USE);
+
+    EntryCount = (unsigned int)HT_p->HT_TableSize;
+    EIP207_FLOW_CHECK_INT_ATMOST(EntryCount,
+                                 EIP207_FLOW_HASH_TABLE_ENTRIES_MAX);
+
+    // Convert EIP207_Flow_HashTable_Entry_Count_t to a number
+    EntryCount = EIP207Lib_Flow_TableSize_To_EntryCount(EntryCount);
+    EIP207_FLOW_CHECK_INT_ATMOST(EntryCount, HT_p->DT_EntryCount);
+
+    // Check Flow Hash Table address alignment
+    if (HT_p->HT_DMA_Address_p->Addr == EIP207_FLOW_RECORD_DUMMY_ADDRESS)
+        return EIP207_FLOW_ARGUMENT_ERROR;
+
+    // Save the flag that indicates whether the FLUEC must be used
+    // Note: FLUEC is enabled and configured via the Global Control interface
+    TrueIOArea_p->HT_Params[HashTableId].fLookupCached = fLookupCached;
+
+    // Save the host address of the Flow Descriptor Table and its size
+    TrueIOArea_p->HT_Params[HashTableId].DT_p          = HT_p->DT_p;
+    TrueIOArea_p->HT_Params[HashTableId].HT_TableSize  =
+                                            (unsigned int)HT_p->HT_TableSize;
+
+    // Save the DMA resource handle of the Flow Hash Table
+    TrueIOArea_p->HT_Params[HashTableId].HT_DMA_Handle =
+                                                    HT_p->HT_DMA_Handle;
+
+    Device = TrueIOArea_p->Device;
+
+    // Initialize the HT and the DT free list with initial values
+    if (fReset)
+    {
+        EIP207_Flow_HTE_Dscr_t * HTE_Dscr_p =
+                                        (EIP207_Flow_HTE_Dscr_t*)HT_p->DT_p;
+
+        // Initialize the Descriptor Table with initial values
+        memset(HT_p->DT_p,
+               0,
+               HT_p->DT_EntryCount * sizeof(EIP207_Flow_HTE_Dscr_t));
+
+        // Number of HTE descriptors is equal to the number of hash buckets
+        // in the HT plus the number of overflow hash buckets.
+
+        for (i = 0; i < HT_p->DT_EntryCount; i++)
+        {
+            unsigned int j;
+
+            // Initialize with dummy address all the words (j)
+            // in HTE descriptor i
+            for (j = 0; j < EIP207_FLOW_HT_ENTRY_WORD_COUNT; j++)
+                DMAResource_Write32(HT_p->HT_DMA_Handle,
+                                    i * EIP207_FLOW_HT_ENTRY_WORD_COUNT + j,
+                                    EIP207_FLOW_RECORD_DUMMY_ADDRESS);
+
+            // Add only the HTE descriptors for the overflow hash buckets
+            // to the free list.
+            if (i >= EntryCount)
+            {
+                // Descriptor Table free list initialization,
+                // all the HTE descriptors are added to the free list
+
+                // First overflow HTE descriptor in DT?
+                if (i == EntryCount)
+                {
+                    EIP207_Flow_HTE_Dscr_List_Prev_Set(HTE_Dscr_p, NULL);
+                    EIP207_Flow_HTE_Dscr_List_Next_Set(HTE_Dscr_p,
+                                                       HTE_Dscr_p + 1);
+
+                    // Set the free list head
+                    TrueIOArea_p->HT_Params[HashTableId].FreeList_Head_p =
+                                                                    HTE_Dscr_p;
+                }
+
+                // Last overflow HTE descriptor in DT?
+                if (i == HT_p->DT_EntryCount - 1)
+                {
+                    // First and last overflow HTE descriptor in DT?
+                    if (i != EntryCount)
+                        EIP207_Flow_HTE_Dscr_List_Prev_Set(HTE_Dscr_p,
+                                                           HTE_Dscr_p - 1);
+                    EIP207_Flow_HTE_Dscr_List_Next_Set(HTE_Dscr_p, NULL);
+                }
+
+                // Non-first and non-last overflow HTE descriptor in DT?
+                if (i != EntryCount && i != (HT_p->DT_EntryCount - 1))
+                {
+                    EIP207_Flow_HTE_Dscr_List_Prev_Set(HTE_Dscr_p,
+                                                       HTE_Dscr_p - 1);
+                    EIP207_Flow_HTE_Dscr_List_Next_Set(HTE_Dscr_p,
+                                                       HTE_Dscr_p + 1);
+                }
+
+                // Mark overflow hash buckets
+                HTE_Dscr_p->fOverflowBucket = true;
+            }
+            else
+                // Mark non-overflow hash buckets
+                HTE_Dscr_p->fOverflowBucket = false;
+
+            // Set hash bucket byte offset
+            HTE_Dscr_p->Bucket_ByteOffset = i *
+                                        EIP207_FLOW_HT_ENTRY_WORD_COUNT *
+                                            sizeof(uint32_t);
+
+            HTE_Dscr_p++; // Next HTE descriptor in the DT
+        } // for
+
+        // Perform pre-DMA for the entire HT including the overflow buckets,
+        // both are expected to be in one linear contiguous DMA-safe buffer
+        DMAResource_PreDMA(HT_p->HT_DMA_Handle, 0, 0);
+    }
+
+    // Install the FHT
+    EIP207_FLUE_HASHBASE_LO_WR(Device,
+                               HashTableId,
+                               HT_p->HT_DMA_Address_p->Addr);
+    EIP207_FLUE_HASHBASE_HI_WR(Device,
+                               HashTableId,
+                               HT_p->HT_DMA_Address_p->UpperAddr);
+    EIP207_FLUE_SIZE_UPDATE(Device,
+                            HashTableId,
+                            (uint8_t)HT_p->HT_TableSize);
+
+#ifdef EIP207_FLOW_DEBUG_FSM
+    if (fReset)
+    {
+        EIP207_Flow_Error_t rv;
+        uint32_t State = TrueIOArea_p->State;
+
+        // Transit to a new state
+        rv = EIP207_Flow_State_Set(
+                (EIP207_Flow_State_t* const)&State,
+                EIP207_FLOW_STATE_ENABLED);
+
+        TrueIOArea_p->State = State;
+
+        if (rv != EIP207_FLOW_NO_ERROR)
+            return EIP207_FLOW_ILLEGAL_IN_STATE;
+    }
+#endif // EIP207_FLOW_DEBUG_FSM
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_FR_Add
+
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_FR_Add(
+        EIP207_Flow_IOArea_t * const IOArea_p,
+        const unsigned int HashTableId,
+        EIP207_Flow_FR_Dscr_t * const FR_Dscr_p,
+        const EIP207_Flow_FR_InputData_t * const FlowInData_p)
+{
+    volatile EIP207_Flow_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+    EIP207_Flow_Record_InputData_t Rec_Data;
+    EIP207_Flow_FR_Data_t FR_Data;
+    EIP207_Flow_Error_t Flow_Rc;
+
+    EIP207_FLOW_CHECK_POINTER(IOArea_p);
+    EIP207_FLOW_CHECK_INT_ATMOST(HashTableId + 1,
+                                 EIP207_FLOW_MAX_NOF_FLOW_HASH_TABLES_TO_USE);
+    EIP207_FLOW_CHECK_POINTER(FR_Dscr_p);
+    EIP207_FLOW_CHECK_POINTER(FlowInData_p);
+
+#ifdef EIP207_FLOW_STRICT_ARGS
+    // Provided flow record physical DMA address must be addressable by
+    // a 32-bit offset to the Base Address installed via
+    // the EIP207_Flow_RC_BaseAddr_Set() function
+    if(!EIP207Lib_Flow_Is32bitAddressable(
+            TrueIOArea_p->HT_Params[HashTableId].BaseAddr.Addr,
+            TrueIOArea_p->HT_Params[HashTableId].BaseAddr.UpperAddr,
+            FR_Dscr_p->DMA_Addr.Addr,
+            FR_Dscr_p->DMA_Addr.UpperAddr))
+        return EIP207_FLOW_ARGUMENT_ERROR;
+
+    // Provided transform record physical DMA address must be addressable by
+    // a 32-bit offset to the Base Address installed via
+    // the EIP207_Flow_RC_BaseAddr_Set() function
+    if(FlowInData_p->Xform_DMA_Addr.Addr != EIP207_FLOW_RECORD_DUMMY_ADDRESS &&
+       !EIP207Lib_Flow_Is32bitAddressable(
+                TrueIOArea_p->HT_Params[HashTableId].BaseAddr.Addr,
+                TrueIOArea_p->HT_Params[HashTableId].BaseAddr.UpperAddr,
+                FlowInData_p->Xform_DMA_Addr.Addr,
+                FlowInData_p->Xform_DMA_Addr.UpperAddr))
+        return EIP207_FLOW_ARGUMENT_ERROR;
+#endif // EIP207_FLOW_STRICT_ARGS
+
+    ZEROINIT(Rec_Data);
+    ZEROINIT(FR_Data);
+
+    FR_Data.Flags           = FlowInData_p->Flags;
+    FR_Data.SW_FR_Reference = FlowInData_p->SW_FR_Reference;
+    FR_Data.Xform_DMA_Addr  = FlowInData_p->Xform_DMA_Addr;
+    FR_Data.fLarge          = FlowInData_p->fLarge;
+
+    Rec_Data.HashID_p       = &FlowInData_p->HashID;
+    Rec_Data.FR_Data_p      = &FR_Data;
+
+    Flow_Rc = EIP207Lib_Flow_DTL_Record_Add(
+                            &TrueIOArea_p->HT_Params[HashTableId],
+                            (EIP207_Flow_Dscr_t*)FR_Dscr_p,
+                            &Rec_Data);
+    if (Flow_Rc != EIP207_FLOW_NO_ERROR)
+        return Flow_Rc;
+
+#ifdef EIP207_FLOW_DEBUG_FSM
+    {
+        EIP207_Flow_Error_t rv;
+        uint32_t State = TrueIOArea_p->State;
+
+        TrueIOArea_p->Rec_InstalledCounter++;
+
+        // Transit to a new state
+        rv = EIP207_Flow_State_Set((EIP207_Flow_State_t* const)&State,
+                                   EIP207_FLOW_STATE_INSTALLED);
+
+        TrueIOArea_p->State = State;
+
+        if (rv != EIP207_FLOW_NO_ERROR)
+            return EIP207_FLOW_ILLEGAL_IN_STATE;
+    }
+#endif // EIP207_FLOW_DEBUG_FSM
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_RC_BaseAddr_Set
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_RC_BaseAddr_Set(
+        EIP207_Flow_IOArea_t * const IOArea_p,
+        const unsigned int HashTableId,
+        const EIP207_Flow_Address_t * const FlowBaseAddr_p,
+        const EIP207_Flow_Address_t * const TransformBaseAddr_p)
+{
+    Device_Handle_t Device;
+    volatile EIP207_Flow_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP207_FLOW_CHECK_POINTER(IOArea_p);
+    EIP207_FLOW_CHECK_INT_ATMOST(HashTableId + 1,
+                                 EIP207_FLOW_MAX_NOF_FLOW_HASH_TABLES_TO_USE);
+
+    IDENTIFIER_NOT_USED(TransformBaseAddr_p);
+
+    Device = TrueIOArea_p->Device;
+
+    // Set the common base address for all the records which can be looked up
+    // Note: Standard (legacy) record cache should have
+    //       EIP207_RC_SET_NR_DEFAULT set (which is 0, just one Hash Table);
+    //       High-performance (HP) record cache should have
+    //       HashTableId set
+#ifndef EIP207_FLUE_RC_HP
+    EIP207_RC_BaseAddr_Set(Device,
+                           EIP207_FRC_REG_BASE,
+                           HashTableId, // EIP207_RC_SET_NR_DEFAULT
+                           FlowBaseAddr_p->Addr,
+                           FlowBaseAddr_p->UpperAddr);
+#else
+    EIP207_FLUE_CACHEBASE_LO_WR(Device, HashTableId, FlowBaseAddr_p->Addr);
+    EIP207_FLUE_CACHEBASE_HI_WR(Device, HashTableId, FlowBaseAddr_p->UpperAddr);
+#endif
+
+    TrueIOArea_p->HT_Params[HashTableId].BaseAddr.Addr = FlowBaseAddr_p->Addr;
+    TrueIOArea_p->HT_Params[HashTableId].BaseAddr.UpperAddr =
+                                                    FlowBaseAddr_p->UpperAddr;
+
+    return  EIP207_FLOW_NO_ERROR;
+}
+
+
+/*****************************************************************************
+ * DTL-specific API functions
+ */
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_DTL_FR_Remove
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_DTL_FR_Remove(
+        EIP207_Flow_IOArea_t * const IOArea_p,
+        const unsigned int HashTableId,
+        EIP207_Flow_FR_Dscr_t * const FR_Dscr_p)
+{
+    volatile EIP207_Flow_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+    EIP207_Flow_HTE_Dscr_RecData_t * FR_Data_p;
+    EIP207_Flow_Error_t Flow_Rc;
+
+    EIP207_FLOW_CHECK_POINTER(IOArea_p);
+    EIP207_FLOW_CHECK_INT_ATMOST(HashTableId + 1,
+                                 EIP207_FLOW_MAX_NOF_FLOW_HASH_TABLES_TO_USE);
+    EIP207_FLOW_CHECK_POINTER(FR_Dscr_p);
+
+    FR_Data_p = (EIP207_Flow_HTE_Dscr_RecData_t*)FR_Dscr_p->InternalData_p;
+
+    EIP207_FLOW_CHECK_POINTER(FR_Data_p);
+    EIP207_FLOW_CHECK_POINTER(FR_Data_p->HTE_Dscr_p);
+
+#ifdef EIP207_FLOW_STRICT_ARGS
+    // Provided flow record physical DMA address must be addressable by
+    // a 32-bit offset to the Based Address installed via
+    // the EIP207_Flow_RC_BaseAddr_Set() function
+    if(!EIP207Lib_Flow_Is32bitAddressable(
+                TrueIOArea_p->HT_Params[HashTableId].BaseAddr.Addr,
+                TrueIOArea_p->HT_Params[HashTableId].BaseAddr.UpperAddr,
+                FR_Dscr_p->DMA_Addr.Addr,
+                FR_Dscr_p->DMA_Addr.UpperAddr))
+        return EIP207_FLOW_ARGUMENT_ERROR;
+
+    if (FR_Data_p->Type != EIP207_FLOW_REC_FLOW)
+        return EIP207_FLOW_INTERNAL_ERROR;
+#endif // EIP207_FLOW_STRICT_ARGS
+
+    Flow_Rc = EIP207Lib_Flow_DTL_Record_Remove(
+                          TrueIOArea_p->Device,
+                          HashTableId,
+                          &TrueIOArea_p->HT_Params[HashTableId],
+                          (EIP207_Flow_Dscr_t*)FR_Dscr_p);
+    if (Flow_Rc != EIP207_FLOW_NO_ERROR)
+        return Flow_Rc;
+
+    IDENTIFIER_NOT_USED(FR_Data_p);
+
+#ifdef EIP207_FLOW_DEBUG_FSM
+    {
+        EIP207_Flow_Error_t rv;
+        uint32_t State = TrueIOArea_p->State;
+
+        TrueIOArea_p->Rec_InstalledCounter--;
+
+        // Transit to a new state
+        if (TrueIOArea_p->Rec_InstalledCounter == 0)
+            // Last record is removed
+            rv = EIP207_Flow_State_Set(
+                    (EIP207_Flow_State_t* const)&State,
+                    EIP207_FLOW_STATE_ENABLED);
+        else
+            // Non-last record is removed
+            rv = EIP207_Flow_State_Set(
+                    (EIP207_Flow_State_t* const)&State,
+                    EIP207_FLOW_STATE_INSTALLED);
+
+        TrueIOArea_p->State = State;
+
+        if (rv != EIP207_FLOW_NO_ERROR)
+            return EIP207_FLOW_ILLEGAL_IN_STATE;
+    }
+#endif // EIP207_FLOW_DEBUG_FSM
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+
+#ifndef EIP207_FLOW_REMOVE_TR_LARGE_SUPPORT
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_DTL_TR_Large_WordCount_Get
+ */
+unsigned int
+EIP207_Flow_DTL_TR_Large_WordCount_Get(void)
+{
+    return FIRMWARE_EIP207_CS_FLOW_TRC_RECORD_WORD_COUNT_LARGE;
+}
+#endif // !EIP207_FLOW_REMOVE_TR_LARGE_SUPPORT
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_DTL_TR_Add
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_DTL_TR_Add(
+        EIP207_Flow_IOArea_t * const IOArea_p,
+        const unsigned int HashTableId,
+        EIP207_Flow_TR_Dscr_t * const TR_Dscr_p,
+        const EIP207_Flow_TR_InputData_t * const XformInData_p)
+{
+    volatile EIP207_Flow_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+    EIP207_Flow_Record_InputData_t Rec_Data;
+    EIP207_Flow_TR_Data_t TR_Data;
+    EIP207_Flow_Error_t Flow_Rc;
+
+    EIP207_FLOW_CHECK_POINTER(IOArea_p);
+    EIP207_FLOW_CHECK_INT_ATMOST(HashTableId + 1,
+                                 EIP207_FLOW_MAX_NOF_FLOW_HASH_TABLES_TO_USE);
+    EIP207_FLOW_CHECK_POINTER(TR_Dscr_p);
+    EIP207_FLOW_CHECK_POINTER(XformInData_p);
+
+#ifdef EIP207_FLOW_STRICT_ARGS
+    // Provided transform record physical DMA address must be addressable by
+    // a 32-bit offset to the Transform Based Address installed via
+    // the EIP207_Flow_RC_BaseAddr_Set() function
+    if(!EIP207Lib_Flow_Is32bitAddressable(
+                    TrueIOArea_p->HT_Params[HashTableId].BaseAddr.Addr,
+                    TrueIOArea_p->HT_Params[HashTableId].BaseAddr.UpperAddr,
+                    TR_Dscr_p->DMA_Addr.Addr,
+                    TR_Dscr_p->DMA_Addr.UpperAddr))
+        return EIP207_FLOW_ARGUMENT_ERROR;
+#endif // EIP207_FLOW_STRICT_ARGS
+
+    ZEROINIT(Rec_Data);
+    ZEROINIT(TR_Data);
+
+    TR_Data.fLarge     = XformInData_p->fLarge;
+
+    Rec_Data.HashID_p  = &XformInData_p->HashID;
+    Rec_Data.TR_Data_p = &TR_Data;
+
+    Flow_Rc = EIP207Lib_Flow_DTL_Record_Add(
+                            &TrueIOArea_p->HT_Params[HashTableId],
+                            (EIP207_Flow_Dscr_t*)TR_Dscr_p,
+                            &Rec_Data);
+    if (Flow_Rc != EIP207_FLOW_NO_ERROR)
+        return Flow_Rc;
+
+#ifdef EIP207_FLOW_DEBUG_FSM
+    {
+        EIP207_Flow_Error_t rv;
+        uint32_t State = TrueIOArea_p->State;
+
+        TrueIOArea_p->Rec_InstalledCounter++;
+
+        // Transit to a new state
+        rv = EIP207_Flow_State_Set((EIP207_Flow_State_t* const)&State,
+                                   EIP207_FLOW_STATE_INSTALLED);
+
+        TrueIOArea_p->State = State;
+
+        if (rv != EIP207_FLOW_NO_ERROR)
+            return EIP207_FLOW_ILLEGAL_IN_STATE;
+    }
+#endif // EIP207_FLOW_DEBUG_FSM
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+
+#ifndef EIP207_FLOW_REMOVE_TR_LARGE_SUPPORT
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_DTL_TR_Large_Read
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_DTL_TR_Large_Read(
+        EIP207_Flow_IOArea_t * const IOArea_p,
+        const unsigned int HashTableId,
+        const EIP207_Flow_TR_Dscr_t * const TR_Dscr_p,
+        EIP207_Flow_TR_OutputData_t * const XformData_p)
+{
+    EIP207_Flow_Error_t rv;
+    uint32_t Value32, SeqNrWordOffset;
+
+    EIP207_FLOW_CHECK_POINTER(IOArea_p);
+    EIP207_FLOW_CHECK_POINTER(TR_Dscr_p);
+    EIP207_FLOW_CHECK_POINTER(XformData_p);
+    EIP207_FLOW_CHECK_INT_ATMOST(HashTableId + 1,
+                                 EIP207_FLOW_MAX_NOF_FLOW_HASH_TABLES_TO_USE);
+
+    IDENTIFIER_NOT_USED(IOArea_p);
+    IDENTIFIER_NOT_USED(HashTableId);
+
+    // Prepare the transform record for reading
+    DMAResource_PostDMA(TR_Dscr_p->DMA_Handle, 0, 0);
+
+    // Read the transform record data
+
+    // Recent record Packets Counter
+    XformData_p->PacketsCounter =
+            DMAResource_Read32(
+                    TR_Dscr_p->DMA_Handle,
+                    FIRMWARE_EIP207_CS_FLOW_TR_STAT_PKT_WORD_OFFSET_LARGE);
+
+    // Read Token Context Instruction word
+    Value32 =
+        DMAResource_Read32(TR_Dscr_p->DMA_Handle,
+                FIRMWARE_EIP207_CS_FLOW_TR_TK_CTX_INST_WORD_OFFSET_LARGE);
+
+    // Extract the Sequence Number word offset from the read value
+    FIRMWARE_EIP207_CS_Flow_SeqNum_Offset_Read(Value32, &SeqNrWordOffset);
+
+    // Read the sequence number
+    XformData_p->SequenceNumber =
+            DMAResource_Read32(TR_Dscr_p->DMA_Handle, SeqNrWordOffset);
+
+    // Recent record time stamp
+    rv = EIP207_Flow_Internal_Read64(
+                   TR_Dscr_p->DMA_Handle,
+                   FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_LO_WORD_OFFSET_LARGE,
+                   FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_HI_WORD_OFFSET_LARGE,
+                   &XformData_p->LastTimeLo,
+                   &XformData_p->LastTimeHi);
+    if (rv != EIP207_FLOW_NO_ERROR)
+        return rv;
+
+    // Recent record Octets Counter
+    rv = EIP207_Flow_Internal_Read64(
+                   TR_Dscr_p->DMA_Handle,
+                   FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_LO_WORD_OFFSET_LARGE,
+                   FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_HI_WORD_OFFSET_LARGE,
+                   &XformData_p->OctetsCounterLo,
+                   &XformData_p->OctetsCounterHi);
+    if (rv != EIP207_FLOW_NO_ERROR)
+        return rv;
+
+    return EIP207_FLOW_NO_ERROR;
+}
+#endif // !EIP207_FLOW_REMOVE_TR_LARGE_SUPPORT
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_DTL_TR_Remove
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_DTL_TR_Remove(
+        EIP207_Flow_IOArea_t * const IOArea_p,
+        const unsigned int HashTableId,
+        EIP207_Flow_TR_Dscr_t * const TR_Dscr_p)
+{
+    volatile EIP207_Flow_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+    EIP207_Flow_HTE_Dscr_RecData_t * TR_Data_p;
+    EIP207_Flow_Error_t Flow_Rc;
+
+    EIP207_FLOW_CHECK_POINTER(IOArea_p);
+    EIP207_FLOW_CHECK_INT_ATMOST(HashTableId + 1,
+                                 EIP207_FLOW_MAX_NOF_FLOW_HASH_TABLES_TO_USE);
+    EIP207_FLOW_CHECK_POINTER(TR_Dscr_p);
+
+    TR_Data_p = (EIP207_Flow_HTE_Dscr_RecData_t*)TR_Dscr_p->InternalData_p;
+
+    EIP207_FLOW_CHECK_POINTER(TR_Data_p);
+    EIP207_FLOW_CHECK_POINTER(TR_Data_p->HTE_Dscr_p);
+
+#ifdef EIP207_FLOW_STRICT_ARGS
+    // Provided transform record physical DMA address must be addressable by
+    // a 32-bit offset to the Transform Based Address installed via
+    // the EIP207_Flow_RC_BaseAddr_Set() function
+    if(!EIP207Lib_Flow_Is32bitAddressable(
+                    TrueIOArea_p->HT_Params[HashTableId].BaseAddr.Addr,
+                    TrueIOArea_p->HT_Params[HashTableId].BaseAddr.UpperAddr,
+                    TR_Dscr_p->DMA_Addr.Addr,
+                    TR_Dscr_p->DMA_Addr.UpperAddr))
+        return EIP207_FLOW_ARGUMENT_ERROR;
+
+    if (TR_Data_p->Type != EIP207_FLOW_REC_TRANSFORM_SMALL &&
+        TR_Data_p->Type != EIP207_FLOW_REC_TRANSFORM_LARGE)
+        return EIP207_FLOW_INTERNAL_ERROR;
+#endif // EIP207_FLOW_STRICT_ARGS
+
+    Flow_Rc = EIP207Lib_Flow_DTL_Record_Remove(
+                          TrueIOArea_p->Device,
+                          HashTableId,
+                          &TrueIOArea_p->HT_Params[HashTableId],
+                          (EIP207_Flow_Dscr_t*)TR_Dscr_p);
+    if (Flow_Rc != EIP207_FLOW_NO_ERROR)
+        return Flow_Rc;
+
+    IDENTIFIER_NOT_USED(TR_Data_p);
+
+#ifdef EIP207_FLOW_DEBUG_FSM
+    {
+        EIP207_Flow_Error_t rv;
+        uint32_t State = TrueIOArea_p->State;
+
+        TrueIOArea_p->Rec_InstalledCounter--;
+
+        // Transit to a new state
+        if (TrueIOArea_p->Rec_InstalledCounter == 0)
+            // Last record is removed
+            rv = EIP207_Flow_State_Set(
+                    (EIP207_Flow_State_t* const)&State,
+                    EIP207_FLOW_STATE_ENABLED);
+        else
+            // Non-last record is removed
+            rv = EIP207_Flow_State_Set(
+                    (EIP207_Flow_State_t* const)&State,
+                    EIP207_FLOW_STATE_INSTALLED);
+
+        TrueIOArea_p->State = State;
+
+        if (rv != EIP207_FLOW_NO_ERROR)
+            return EIP207_FLOW_ILLEGAL_IN_STATE;
+    }
+#endif // EIP207_FLOW_DEBUG_FSM
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+
+/* end of file eip207_flow_dtl.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_flow_generic.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_flow_generic.c
new file mode 100644
index 0000000..cd3ecbd
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_flow_generic.c
@@ -0,0 +1,512 @@
+/* eip207_flow_generic.c
+ *
+ * Partial EIP-207 Flow Control Generic API implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// EIP-207 Driver Library Flow Control Generic API
+#include "eip207_flow_generic.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip207_flow.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                 // uint32_t
+
+// Driver Framework C Run-time Library API
+#include "clib.h"                       // ZEROINIT, memset, memcpy
+
+// Driver Framework Device API
+#include "device_types.h"               // Device_Handle_t
+
+// Driver Framework DMA Resource API
+#include "dmares_types.h"
+#include "dmares_rw.h"
+
+// EIP-207 Flow Control Driver Library Internal interfaces
+#include "eip207_flow_level0.h"         // EIP-207 Level 0 macros
+#include "eip207_flow_internal.h"
+
+// EIP-207 Firmware API
+#include "firmware_eip207_api_flow_cs.h" // Classification API: Flow Control
+#include "firmware_eip207_api_cs.h"      // Classification API: General
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_Detect
+ *
+ * Checks the presence of EIP-207c hardware. Returns true when found.
+ */
+static bool
+EIP207Lib_Flow_Detect(
+        const Device_Handle_t Device)
+{
+    uint32_t Value;
+
+    Value = EIP207_Flow_Read32(Device, EIP207_FLUE_FHT_REG_VERSION);
+    if (!EIP207_FLUE_SIGNATURE_MATCH( Value ))
+        return false;
+
+    // read-write test one of the registers
+
+    // Set MASK_31_BITS bits of the EIP207_FLUE_REG_HASHBASE_LO register
+    EIP207_Flow_Write32( Device,
+                         EIP207_FLUE_FHT_REG_HASHBASE_LO(0),
+                         ~MASK_2_BITS);
+    Value = EIP207_Flow_Read32(Device, EIP207_FLUE_FHT_REG_HASHBASE_LO(0));
+    if ((Value) != ~MASK_2_BITS)
+        return false;
+
+    // Clear MASK_31_BITS bits of the EIP207_FLUE_REG_HASHBASE_LO register
+    EIP207_Flow_Write32(Device, EIP207_FLUE_FHT_REG_HASHBASE_LO(0), 0);
+    Value = EIP207_Flow_Read32(Device, EIP207_FLUE_FHT_REG_HASHBASE_LO(0));
+    if (Value != 0)
+       return false;
+
+    return true;
+}
+
+
+#ifdef EIP207_FLOW_DEBUG_FSM
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_State_Set
+ *
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_State_Set(
+        EIP207_Flow_State_t * const CurrentState,
+        const EIP207_Flow_State_t NewState)
+{
+    switch(*CurrentState)
+    {
+        case EIP207_FLOW_STATE_INITIALIZED:
+            switch(NewState)
+            {
+                case EIP207_FLOW_STATE_ENABLED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP207_FLOW_STATE_FATAL_ERROR:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP207_FLOW_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP207_FLOW_STATE_ENABLED:
+            switch(NewState)
+            {
+                case EIP207_FLOW_STATE_INSTALLED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP207_FLOW_STATE_FATAL_ERROR:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP207_FLOW_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP207_FLOW_STATE_INSTALLED:
+            switch(NewState)
+            {
+                case EIP207_FLOW_STATE_INSTALLED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP207_FLOW_STATE_ENABLED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP207_FLOW_STATE_FATAL_ERROR:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP207_FLOW_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        default:
+            return EIP207_FLOW_ILLEGAL_IN_STATE;
+    }
+
+    return EIP207_FLOW_NO_ERROR;
+}
+#endif // EIP207_FLOW_DEBUG_FSM
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_IOArea_ByteCount_Get
+ */
+unsigned int
+EIP207_Flow_IOArea_ByteCount_Get(void)
+{
+    return sizeof(EIP207_Flow_True_IOArea_t);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_HT_Entry_WordCount_Get
+ */
+unsigned int
+EIP207_Flow_HT_Entry_WordCount_Get(void)
+{
+    return EIP207_FLOW_HT_ENTRY_WORD_COUNT;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_Init
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_Init(
+        EIP207_Flow_IOArea_t * const IOArea_p,
+        const Device_Handle_t Device)
+{
+    volatile EIP207_Flow_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP207_FLOW_CHECK_POINTER(IOArea_p);
+
+    // Detect presence of EIP-207c HW hardware
+    if (!EIP207Lib_Flow_Detect(Device))
+        return EIP207_FLOW_UNSUPPORTED_FEATURE_ERROR;
+
+    // Initialize the IO Area
+    TrueIOArea_p->Device = Device;
+
+#ifdef EIP207_FLOW_DEBUG_FSM
+    {
+        TrueIOArea_p->Rec_InstalledCounter = 0;
+
+        TrueIOArea_p->State = (uint32_t)EIP207_FLOW_STATE_INITIALIZED;
+    }
+#endif // EIP207_FLOW_DEBUG_FSM
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_ID_Compute
+ *
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_ID_Compute(
+        EIP207_Flow_IOArea_t * const IOArea_p,
+        const unsigned int HashTableId,
+        const EIP207_Flow_SelectorParams_t * const SelectorParams_p,
+        EIP207_Flow_ID_t * const FlowID)
+{
+    uint32_t h1, h2, h3, h4;
+    uint32_t w;
+    const uint32_t * p;
+    uint32_t count, data [FIRMWARE_EIP207_CS_FLOW_HASH_ID_INPUT_WORD_COUNT];
+    Device_Handle_t Device;
+    FIRMWARE_EIP207_CS_Flow_SelectorParams_t Selectors;
+    volatile EIP207_Flow_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP207_FLOW_CHECK_POINTER(IOArea_p);
+    EIP207_FLOW_CHECK_POINTER(SelectorParams_p);
+    EIP207_FLOW_CHECK_POINTER(FlowID);
+
+    Device = TrueIOArea_p->Device;
+
+    // Read the IV from the flow hash engine in the classification engine
+    // The IV must have been already installed in the flow hash engine
+    // via the Global Classification Control API
+    EIP207_FHASH_IV_RD(Device, HashTableId, &h1, &h2, &h3, &h4);
+
+    // Install the selectors for the flow hash ID calculation
+    ZEROINIT(Selectors);
+    Selectors.Flags   = SelectorParams_p->Flags;
+    Selectors.DstIp_p = SelectorParams_p->DstIp_p;
+    Selectors.DstPort = SelectorParams_p->DstPort;
+    Selectors.IpProto = SelectorParams_p->IpProto;
+    Selectors.SPI     = SelectorParams_p->SPI;
+#ifdef FIRMWARE_EIP207_CS_FLOW_DTLS_SUPPORTED
+    Selectors.Epoch     = SelectorParams_p->Epoch;
+#endif
+    Selectors.SrcIp_p = SelectorParams_p->SrcIp_p;
+    Selectors.SrcPort = SelectorParams_p->SrcPort;
+    FIRMWARE_EIP207_CS_Flow_Selectors_Reorder(&Selectors, data, &count);
+
+    p = data;
+
+    while (p < &data[count - 3])
+    {
+        w = *p++;
+        h2 ^= w;
+        h1 += w;
+        h1 += h1 << 10;
+        h1 ^= h1 >> 6;
+
+        w = *p++;
+        h3 ^= w;
+        h1 += w;
+        h1 += h1 << 10;
+        h1 ^= h1 >> 6;
+
+        w = *p++;
+        h4 ^= w;
+        h1 += w;
+        h1 += h1 << 10;
+        h1 ^= h1 >> 6;
+
+        /* Mixing step for the 96 bits in h2-h4.  The code comes from a
+           hash table lookup function by Robert J. Jenkins, and has been
+           presented on numerous web pages and in a Dr. Dobbs Journal
+           sometimes in late 90's.
+
+           h1 is computed according to the one-at-a-time hash function,
+           presented in the same article. */
+        h2 -= h3;  h2 -= h4;  h2 ^= h4 >> 13;
+        h3 -= h4;  h3 -= h2;  h3 ^= h2 << 8;
+        h4 -= h2;  h4 -= h3;  h4 ^= h3 >> 13;
+        h2 -= h3;  h2 -= h4;  h2 ^= h4 >> 12;
+        h3 -= h4;  h3 -= h2;  h3 ^= h2 << 16;
+        h4 -= h2;  h4 -= h3;  h4 ^= h3 >> 5;
+        h2 -= h3;  h2 -= h4;  h2 ^= h4 >> 3;
+        h3 -= h4;  h3 -= h2;  h3 ^= h2 << 10;
+        h4 -= h2;  h4 -= h3;  h4 ^= h3 >> 15;
+    } // while
+
+    w = *p++;
+    h1 += w;
+    h1 += h1 << 10;
+    h1 ^= h1 >> 6;
+    h2 ^= w;
+
+    if (p < data + count)
+    {
+        w = *p++;
+        h1 += w;
+        h1 += h1 << 10;
+        h1 ^= h1 >> 6;
+        h3 ^= w;
+
+        if (p < data + count)
+        {
+            w = *p++;
+            h1 += w;
+            h1 += h1 << 10;
+            h1 ^= h1 >> 6;
+            h4 ^= w;
+        }
+    }
+
+    FlowID->Word32[0] = h1;
+    FlowID->Word32[1] = h2;
+    FlowID->Word32[2] = h3;
+    FlowID->Word32[3] = h4;
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_FR_WordCount_Get
+ */
+unsigned int
+EIP207_Flow_FR_WordCount_Get(void)
+{
+    return FIRMWARE_EIP207_CS_FRC_RECORD_WORD_COUNT;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_FR_Read
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_FR_Read(
+        EIP207_Flow_IOArea_t * const IOArea_p,
+        const unsigned int HashTableId,
+        EIP207_Flow_FR_Dscr_t * const FR_Dscr_p,
+        EIP207_Flow_FR_OutputData_t * const FlowData_p)
+{
+    EIP207_Flow_Error_t rv;
+
+    EIP207_FLOW_CHECK_POINTER(IOArea_p);
+    EIP207_FLOW_CHECK_POINTER(FR_Dscr_p);
+    EIP207_FLOW_CHECK_POINTER(FlowData_p);
+    EIP207_FLOW_CHECK_INT_ATMOST(HashTableId + 1,
+                                 EIP207_FLOW_MAX_NOF_FLOW_HASH_TABLES_TO_USE);
+
+    IDENTIFIER_NOT_USED(HashTableId);
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+    // Consistency check for the provided flow descriptor
+    if (FR_Dscr_p->DMA_Addr.Addr == EIP207_FLOW_RECORD_DUMMY_ADDRESS)
+        return EIP207_FLOW_INTERNAL_ERROR;
+#endif // EIP207_FLOW_CONSISTENCY_CHECK
+
+    // Prepare the flow record for reading
+    DMAResource_PostDMA(FR_Dscr_p->DMA_Handle, 0, 0);
+
+    // Read the flow record data
+
+    // Recent record Packets Counter
+    FlowData_p->PacketsCounter =
+            DMAResource_Read32(FR_Dscr_p->DMA_Handle,
+                               FIRMWARE_EIP207_CS_FLOW_FR_STAT_PKT_WORD_OFFSET);
+
+    // Recent record time stamp
+    rv = EIP207_Flow_Internal_Read64(
+                       FR_Dscr_p->DMA_Handle,
+                       FIRMWARE_EIP207_CS_FLOW_FR_TIME_STAMP_LO_WORD_OFFSET,
+                       FIRMWARE_EIP207_CS_FLOW_FR_TIME_STAMP_HI_WORD_OFFSET,
+                       &FlowData_p->LastTimeLo,
+                       &FlowData_p->LastTimeHi);
+    if (rv != EIP207_FLOW_NO_ERROR)
+        return rv;
+
+    // Recent record Octets Counter
+    rv = EIP207_Flow_Internal_Read64(
+                       FR_Dscr_p->DMA_Handle,
+                       FIRMWARE_EIP207_CS_FLOW_FR_STAT_OCT_LO_WORD_OFFSET,
+                       FIRMWARE_EIP207_CS_FLOW_FR_STAT_OCT_HI_WORD_OFFSET,
+                       &FlowData_p->OctetsCounterLo,
+                       &FlowData_p->OctetsCounterHi);
+    if (rv != EIP207_FLOW_NO_ERROR)
+        return rv;
+
+#ifdef EIP207_FLOW_DEBUG_FSM
+    {
+        volatile EIP207_Flow_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+        uint32_t State = TrueIOArea_p->State;
+
+        // Remain in the current state
+        rv = EIP207_Flow_State_Set(
+                (EIP207_Flow_State_t* const)&State,
+                (EIP207_Flow_State_t)TrueIOArea_p->State);
+
+        TrueIOArea_p->State = State;
+
+        if (rv != EIP207_FLOW_NO_ERROR)
+            return EIP207_FLOW_ILLEGAL_IN_STATE;
+    }
+#else
+    IDENTIFIER_NOT_USED(IOArea_p);
+#endif // EIP207_FLOW_DEBUG_FSM
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_TR_WordCount_Get
+ */
+unsigned int
+EIP207_Flow_TR_WordCount_Get(void)
+{
+    return FIRMWARE_EIP207_CS_TRC_RECORD_WORD_COUNT;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_TR_Read
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_TR_Read(
+        EIP207_Flow_IOArea_t * const IOArea_p,
+        const unsigned int HashTableId,
+        const EIP207_Flow_TR_Dscr_t * const TR_Dscr_p,
+        EIP207_Flow_TR_OutputData_t * const XformData_p)
+{
+    EIP207_Flow_Error_t rv;
+    uint32_t Value32, SeqNrWordOffset;
+
+    EIP207_FLOW_CHECK_POINTER(IOArea_p);
+    EIP207_FLOW_CHECK_POINTER(TR_Dscr_p);
+    EIP207_FLOW_CHECK_POINTER(XformData_p);
+    EIP207_FLOW_CHECK_INT_ATMOST(HashTableId + 1,
+                                 EIP207_FLOW_MAX_NOF_FLOW_HASH_TABLES_TO_USE);
+
+    IDENTIFIER_NOT_USED(IOArea_p);
+    IDENTIFIER_NOT_USED(HashTableId);
+
+    // Prepare the transform record for reading
+    DMAResource_PostDMA(TR_Dscr_p->DMA_Handle, 0, 0);
+
+    // Read the transform record data
+
+    // Recent record Packets Counter
+    XformData_p->PacketsCounter =
+            DMAResource_Read32(TR_Dscr_p->DMA_Handle,
+                               FIRMWARE_EIP207_CS_FLOW_TR_STAT_PKT_WORD_OFFSET);
+
+    // Read Token Context Instruction word
+    Value32 =
+        DMAResource_Read32(TR_Dscr_p->DMA_Handle,
+                           FIRMWARE_EIP207_CS_FLOW_TR_TK_CTX_INST_WORD_OFFSET);
+
+    // Extract the Sequence Number word offset from the read value
+    FIRMWARE_EIP207_CS_Flow_SeqNum_Offset_Read(Value32, &SeqNrWordOffset);
+
+    // Read the sequence number
+    XformData_p->SequenceNumber =
+            DMAResource_Read32(TR_Dscr_p->DMA_Handle, SeqNrWordOffset);
+
+    // Recent record time stamp
+    rv = EIP207_Flow_Internal_Read64(
+                   TR_Dscr_p->DMA_Handle,
+                   FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_LO_WORD_OFFSET,
+                   FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_HI_WORD_OFFSET,
+                   &XformData_p->LastTimeLo,
+                   &XformData_p->LastTimeHi);
+    if (rv != EIP207_FLOW_NO_ERROR)
+        return rv;
+
+    // Recent record Octets Counter
+    rv = EIP207_Flow_Internal_Read64(
+                   TR_Dscr_p->DMA_Handle,
+                   FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_LO_WORD_OFFSET,
+                   FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_HI_WORD_OFFSET,
+                   &XformData_p->OctetsCounterLo,
+                   &XformData_p->OctetsCounterHi);
+    if (rv != EIP207_FLOW_NO_ERROR)
+        return rv;
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+
+/* end of file eip207_flow_generic.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_flow_internal.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_flow_internal.c
new file mode 100644
index 0000000..1b61461
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_flow_internal.c
@@ -0,0 +1,95 @@
+/* eip207_flow_internal.c
+ *
+ *  EIP-207 Flow Control Internal interface implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// EIP-207 Flow Control Driver Library Internal interfaces
+#include "eip207_flow_internal.h"
+#include "eip207_flow_generic.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+#include "eip207_flow_level0.h"         // EIP-207 Level 0 macros
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"         // BIT definitions, bool, uint32_t
+
+// Driver Framework DMA Resource API
+#include "dmares_types.h"       // DMAResource_Handle_t
+#include "dmares_rw.h"          // DMAResource_Write32()/_Read32()/_PreDMA()
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_Internal_Read64
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_Internal_Read64(
+        const DMAResource_Handle_t Handle,
+        const unsigned int Value64_WordOffsetLo,
+        const unsigned int Value64_WordOffsetHi,
+        uint32_t * const Value64_Lo,
+        uint32_t * const Value64_Hi)
+{
+    uint32_t Value32;
+    unsigned int i;
+
+    for (i = 0; i < EIP207_FLOW_VALUE_64BIT_MAX_NOF_READ_ATTEMPTS; i++)
+    {
+        Value32     = DMAResource_Read32(Handle, Value64_WordOffsetHi);
+        *Value64_Lo = DMAResource_Read32(Handle, Value64_WordOffsetLo);
+
+        // Prepare the flow record for reading
+        DMAResource_PostDMA(Handle, 0, 0);
+
+        *Value64_Hi = DMAResource_Read32(Handle, Value64_WordOffsetHi);
+
+        if (Value32 == (*Value64_Hi))
+            return EIP207_FLOW_NO_ERROR;
+    }
+
+    return EIP207_FLOW_INTERNAL_ERROR;
+}
+
+
+/* end of file eip207_flow_hte_dscr_dtl.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_flue.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_flue.c
new file mode 100644
index 0000000..1074b7a
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_flue.c
@@ -0,0 +1,177 @@
+/* eip207_ice.c
+ *
+ * EIP-207s Flow Look-Up Engine (FLUE) interface implementation
+ *
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// EIP-207s Flow Look-Up Engine (FLUE) interface
+#include "eip207_flue.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip207_global.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                 // uint32_t, bool
+
+// EIP-207 Global Control Driver Library Internal interfaces
+#include "eip207_level0.h"              // EIP-207 Level 0 macros
+
+// EIP-207 HW interface
+#include "eip207_hw_interface.h"
+
+// Driver Framework Device API
+#include "device_types.h"               // Device_Handle_t
+
+// EIP-207 Firmware Classification API
+#include "firmware_eip207_api_cs.h"     // Classification API: General
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+#define EIP207_FLUE_3ENTRY_LOOKUP_MODE          1
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_FLUE_Init
+ */
+void
+EIP207_FLUE_Init(
+        const Device_Handle_t Device,
+        const unsigned int HashTableId,
+        const EIP207_Global_FLUEConfig_t * const FLUEConf_p,
+        const bool fARC4Present,
+        const bool fLookupCachePresent)
+{
+    // Configure hash tables
+    EIP207_FLUE_CONFIG_WR(Device,
+                          HashTableId, // Hash Table ID
+                          HashTableId, // Function,
+                                       // set it equal to hash table id
+                          0,           // Generation
+                          true,        // Table enable
+                          true);       // Access enable
+
+    // Use Hash table 0 parameters, they must be the same for all the tables!
+    // Initialize FLUE with EIP-207 Firmware Classification API parameters
+    EIP207_FLUE_OFFSET_WR(Device,
+                          FLUEConf_p->HashTable[HashTableId].fPrefetchXform,
+                          fLookupCachePresent ?
+                              FLUEConf_p->HashTable[HashTableId].fLookupCached :
+                              false,
+                          FIRMWARE_EIP207_CS_XFORM_RECORD_WORD_OFFSET);
+
+    // Use Hash table 0 parameters, they must be the same for all the tables!
+    // Check if ARC4 Record Cache is available
+    if ( fARC4Present )
+    {
+        EIP207_FLUE_ARC4_OFFSET_WR(
+                          Device,
+                          FLUEConf_p->HashTable[HashTableId].fPrefetchARC4State,
+                          EIP207_GLOBAL_FLUE_LOOKUP_MODE,
+                          FIRMWARE_EIP207_CS_ARC4_RECORD_WORD_OFFSET);
+    }
+#if EIP207_GLOBAL_FLUE_LOOKUP_MODE == EIP207_FLUE_3ENTRY_LOOKUP_MODE
+    else
+    {
+        EIP207_FLUE_ARC4_OFFSET_WR(Device,
+                                   HashTableId,
+                                   EIP207_GLOBAL_FLUE_LOOKUP_MODE,
+                                   0);
+    }
+#endif // EIP207_GLOBAL_FLUE_LOOKUP_MODE == EIP207_FLUE_1ENTRY_LOOKUP_MODE
+
+#ifdef EIP207_FLUE_HAVE_VIRTUALIZATION
+    // Virtualisation support present, initialize the lookup table.
+    // All interfaces refer to Table # 0.
+    {
+        unsigned int i;
+        unsigned int c;
+        unsigned int idx0,idx1,idx2,idx3;
+
+        c = FLUEConf_p->InterfacesCount;
+        if (c > EIP207_FLUE_MAX_NOF_INTERFACES_TO_USE)
+            c = EIP207_FLUE_MAX_NOF_INTERFACES_TO_USE;
+
+        for (i = 0; i < c; i += 4)
+        {
+            idx0 = FLUEConf_p->InterfaceIndex[i];
+
+            if (i + 1 < c)
+                idx1 = FLUEConf_p->InterfaceIndex[i + 1];
+            else
+                idx1 = 0;
+
+            if (i + 2 < c)
+                idx2 = FLUEConf_p->InterfaceIndex[i + 2];
+            else
+                idx2 = 0;
+
+            if (i + 3 < c)
+                idx3 = FLUEConf_p->InterfaceIndex[i + 3];
+            else
+                idx3 = 0;
+
+            EIP207_FLUE_IFC_LUT_WR(Device,
+                                   i / 4,
+                                   idx0, idx1, idx2, idx3);
+        }
+    }
+#endif
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_FLUE_Status_Get
+ */
+void
+EIP207_FLUE_Status_Get(
+        const Device_Handle_t Device,
+        EIP207_Global_FLUE_Status_t * const FLUE_Status_p)
+{
+    IDENTIFIER_NOT_USED(Device);
+
+    FLUE_Status_p->Error1 = 0;
+    FLUE_Status_p->Error2 = 0;
+
+    return;
+}
+
+
+/* end of file eip207_flue.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_fluec.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_fluec.c
new file mode 100644
index 0000000..82f04ac
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_fluec.c
@@ -0,0 +1,77 @@
+/* eip207_fluec.c
+ *
+ * EIP-207 Flow Look-Up Engine Cache (FLUEC) interface implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// EIP-207s Flow Look-Up Engine Cache (FLUEC) interface
+#include "eip207_fluec.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                 // uint8_t, uint32_t,
+                                        // IDENTIFIER_NOT_USED
+
+// Driver Framework Device API
+#include "device_types.h"               // Device_Handle_t
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_FLUEC_Invalidate
+ */
+void
+EIP207_FLUEC_Invalidate(
+        const Device_Handle_t Device,
+        const uint8_t InvTable,
+        const uint32_t FlowID_W0,
+        const uint32_t FlowID_W1,
+        const uint32_t FlowID_W2,
+        const uint32_t FlowID_W3)
+{
+    // Not implemented
+    IDENTIFIER_NOT_USED(Device);
+    IDENTIFIER_NOT_USED(InvTable);
+    IDENTIFIER_NOT_USED(FlowID_W0);
+    IDENTIFIER_NOT_USED(FlowID_W1);
+    IDENTIFIER_NOT_USED(FlowID_W2);
+    IDENTIFIER_NOT_USED(FlowID_W3);
+}
+
+
+/* end of file eip207_fluec.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_global_init.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_global_init.c
new file mode 100644
index 0000000..41586a8
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_global_init.c
@@ -0,0 +1,690 @@
+/* eip207_global_init.c
+ *
+ * EIP-207 Global Control Driver Library
+ * Initialization and status retrieval Module
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// EIP-207 Global Control API
+#include "eip207_global_init.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip207_global.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                 // uint32_t
+
+// Driver Framework C Run-time Library API
+#include "clib.h"                       // ZEROINIT
+
+// Driver Framework Device API
+#include "device_types.h"               // Device_Handle_t
+
+// EIP-207s Record Cache (RC) internal interface
+#include "eip207_rc_internal.h"
+
+// EIP-207c Input Classification Engine (ICE) interface
+#include "eip207_ice.h"
+
+// EIP-207c Output Classification Engine (OCE) interface
+#include "eip207_oce.h"
+
+// EIP-207s Flow Look-Up Engine (FLUE) interface
+#include "eip207_flue.h"
+
+// EIP-207 Global Control Driver Library Internal interfaces
+#include "eip207_level0.h"              // EIP-207 Level 0 macros
+
+// EIP-207s Flow Look-Up Engine Cache (FLUEC) Level0 interface
+#include "eip207_fluec_level0.h"
+
+// EIP-207c Firmware Classification API
+#include "firmware_eip207_api_cs.h"     // Classification API: General
+
+// EIP-207c Firmware Download API
+#include "firmware_eip207_api_dwld.h"   // Classification API: FW download
+
+// EIP97 Global init API
+#include "eip97_global_init.h"
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+// Maximum number of EIP-207c Classification Engines that should be used
+// Should not exceed the number of engines physically available
+#ifndef EIP207_GLOBAL_MAX_NOF_CE_TO_USE
+#error "EIP207_GLOBAL_MAX_NOF_CE_TO_USE is not defined"
+#endif
+
+// Maximum number of flow hash tables that should be used
+#ifndef EIP207_MAX_NOF_FLOW_HASH_TABLES_TO_USE
+#error "EIP207_MAX_NOF_FLOW_HASH_TABLES_TO_USE is not defined"
+#endif
+
+// Default Classification Engine number
+#define CE_DEFAULT_NR                                   0
+
+#if (CE_DEFAULT_NR >= EIP207_GLOBAL_MAX_NOF_CE_TO_USE)
+#error "Error: CE_DEFAULT_NR must be less than EIP207_GLOBAL_MAX_NOF_CE_TO_USE"
+#endif
+
+// Size of the ARC4 State Record in 32-bit words
+#define EIP207_CS_ARC4RC_RECORD_WORD_COUNT              64
+
+#ifndef FIRMWARE_EIP207_CS_ARC4RC_RECORD_WORD_COUNT
+#define FIRMWARE_EIP207_CS_ARC4RC_RECORD_WORD_COUNT     64
+#endif
+
+// I/O Area, used internally
+typedef struct
+{
+    Device_Handle_t Device;
+    uint32_t State;
+} EIP207_True_IOArea_t;
+
+#define IOAREA(_p) ((volatile EIP207_True_IOArea_t *)_p)
+
+#ifdef EIP207_GLOBAL_STRICT_ARGS
+#define EIP207_GLOBAL_CHECK_POINTER(_p) \
+    if (NULL == (_p)) \
+        return EIP207_GLOBAL_ARGUMENT_ERROR;
+#define EIP207_GLOBAL_CHECK_INT_INRANGE(_i, _min, _max) \
+    if ((_i) < (_min) || (_i) > (_max)) \
+        return EIP207_GLOBAL_ARGUMENT_ERROR;
+#define EIP207_GLOBAL_CHECK_INT_ATLEAST(_i, _min) \
+    if ((_i) < (_min)) \
+        return EIP207_GLOBAL_ARGUMENT_ERROR;
+#define EIP207_GLOBAL_CHECK_INT_ATMOST(_i, _max) \
+    if ((_i) > (_max)) \
+        return EIP207_GLOBAL_ARGUMENT_ERROR;
+#else
+/* EIP207_GLOBAL_STRICT_ARGS undefined */
+#define EIP207_GLOBAL_CHECK_POINTER(_p)
+#define EIP207_GLOBAL_CHECK_INT_INRANGE(_i, _min, _max)
+#define EIP207_GLOBAL_CHECK_INT_ATLEAST(_i, _min)
+#define EIP207_GLOBAL_CHECK_INT_ATMOST(_i, _max)
+#endif /*end of EIP207_GLOBAL_STRICT_ARGS */
+
+#define TEST_SIZEOF(type, size) \
+    extern int size##_must_bigger[1 - 2*((int)(sizeof(type) > size))]
+
+// validate the size of the fake and real IOArea structures
+TEST_SIZEOF(EIP207_True_IOArea_t, EIP207_GLOBAL_IOAREA_REQUIRED_SIZE);
+
+#ifdef EIP207_GLOBAL_DEBUG_FSM
+// EIP-207 Global Control API States
+typedef enum
+{
+    EIP207_GLOBAL_STATE_INITIALIZED  = 5,
+    EIP207_GLOBAL_STATE_FATAL_ERROR  = 7,
+    EIP207_GLOBAL_STATE_RC_ENABLED   = 8,
+    EIP207_GLOBAL_STATE_FW_LOADED    = 9
+} EIP207_Global_State_t;
+#endif // EIP207_GLOBAL_DEBUG_FSM
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Detect
+ *
+ * Checks the presence of EIP-207 hardware. Returns true when found.
+ */
+static bool
+EIP207Lib_Detect(
+        const Device_Handle_t Device,
+        const unsigned int CEnr)
+{
+    uint32_t Value;
+
+    IDENTIFIER_NOT_USED(CEnr);
+
+    Value = EIP207_Read32(Device, EIP207_CS_REG_VERSION);
+    if (!EIP207_CS_SIGNATURE_MATCH( Value ))
+        return false;
+
+    return true;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_HWRevision_Get
+ */
+static void
+EIP207Lib_HWRevision_Get(
+        const Device_Handle_t Device,
+        EIP207_Options_t * const Options_p,
+        EIP207_Version_t * const Version_p)
+{
+    EIP207_CS_VERSION_RD(
+                      Device,
+                      &Version_p->EipNumber,
+                      &Version_p->ComplmtEipNumber,
+                      &Version_p->HWPatchLevel,
+                      &Version_p->MinHWRevision,
+                      &Version_p->MajHWRevision);
+
+    EIP207_CS_OPTIONS_RD(Device,
+                         &Options_p->NofLookupTables,
+                         &Options_p->fLookupCached,
+                         &Options_p->NofLookupClients,
+                         &Options_p->fCombinedTRC_ARC4,
+                         &Options_p->fCombinedFRC_ARC4,
+                         &Options_p->fARC4Present,
+                         &Options_p->NofARC4_Clients,
+                         &Options_p->fCombinedFRC_TRC,
+                         &Options_p->NofTRC_Clients,
+                         &Options_p->NofFRC_Clients,
+                         &Options_p->NofCacheSets);
+}
+
+
+#ifdef EIP207_GLOBAL_DEBUG_FSM
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Global_State_Set
+ *
+ */
+static EIP207_Global_Error_t
+EIP207Lib_Global_State_Set(
+        EIP207_Global_State_t * const CurrentState,
+        const EIP207_Global_State_t NewState)
+{
+    switch(*CurrentState)
+    {
+        case EIP207_GLOBAL_STATE_INITIALIZED:
+            switch(NewState)
+            {
+                case EIP207_GLOBAL_STATE_RC_ENABLED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP207_GLOBAL_STATE_FATAL_ERROR:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP207_GLOBAL_ILLEGAL_IN_STATE;
+            }
+            break;
+
+         case EIP207_GLOBAL_STATE_RC_ENABLED:
+            switch(NewState)
+            {
+                case EIP207_GLOBAL_STATE_FW_LOADED:
+                   *CurrentState = NewState;
+                   break;
+                case EIP207_GLOBAL_STATE_FATAL_ERROR:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP207_GLOBAL_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        default:
+            return EIP207_GLOBAL_ILLEGAL_IN_STATE;
+    }
+
+    return EIP207_GLOBAL_NO_ERROR;
+}
+#endif // EIP207_GLOBAL_DEBUG_FSM
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Global_Init
+ */
+EIP207_Global_Error_t
+EIP207_Global_Init(
+        EIP207_Global_IOArea_t * const IOArea_p,
+        const Device_Handle_t Device,
+        EIP207_Global_CacheConfig_t * const CacheConf_p,
+        const EIP207_Global_FLUEConfig_t * const FLUEConf_p)
+{
+    unsigned int FLUE_NofLookupTables;
+    EIP207_Global_Capabilities_t Capabilities;
+    volatile EIP207_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+    unsigned int i;
+
+    EIP207_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP207_GLOBAL_CHECK_POINTER(CacheConf_p);
+    EIP207_GLOBAL_CHECK_POINTER(FLUEConf_p);
+
+    // Detect presence of EIP-207 HW hardware
+    if (!EIP207Lib_Detect(Device, CE_DEFAULT_NR))
+        return EIP207_GLOBAL_UNSUPPORTED_FEATURE_ERROR;
+
+    // Initialize the IO Area
+    TrueIOArea_p->Device = Device;
+
+#ifdef EIP207_GLOBAL_DEBUG_FSM
+    TrueIOArea_p->State = (uint32_t)EIP207_GLOBAL_STATE_INITIALIZED;
+#endif // EIP207_GLOBAL_DEBUG_FSM
+
+    ZEROINIT(Capabilities);
+
+    EIP207Lib_HWRevision_Get(Device,
+                             &Capabilities.EIP207_Options,
+                             &Capabilities.EIP207_Version);
+
+    FLUE_NofLookupTables = Capabilities.EIP207_Options.NofLookupTables;
+
+    // 0 hash tables has a special meaning for the EIP-207 FLUE HW
+    if (FLUE_NofLookupTables == 0)
+        FLUE_NofLookupTables = EIP207_GLOBAL_MAX_HW_NOF_FLOW_HASH_TABLES;
+
+    // Check actual configuration HW against capabilities
+    // Number of configured cache sets and hash tables
+    if ((Capabilities.EIP207_Options.NofCacheSets <
+            EIP207_GLOBAL_MAX_NOF_CACHE_SETS_TO_USE) ||
+        (FLUE_NofLookupTables <
+            EIP207_MAX_NOF_FLOW_HASH_TABLES_TO_USE)  ||
+        (FLUEConf_p->HashTablesCount >
+            EIP207_MAX_NOF_FLOW_HASH_TABLES_TO_USE))
+        return EIP207_GLOBAL_UNSUPPORTED_FEATURE_ERROR;
+
+    // Configure EIP-207 Classification Engine
+
+    // Initialize Record Caches
+    {
+        EIP207_Global_Error_t rv;
+
+        // Initialize Flow Record Cache
+#ifndef EIP207_GLOBAL_FRC_DISABLE
+        if ((EIP97_SupportedFuncs_Get() & BIT_3) != 0)
+        {
+            for (i=0; i < EIP207_GLOBAL_MAX_NOF_CACHE_SETS_TO_USE; i++)
+            {
+                CacheConf_p->FRC[i].DataWordCount = EIP207_FRC_RAM_WORD_COUNT;
+                CacheConf_p->FRC[i].AdminWordCount =
+                    EIP207_FRC_ADMIN_RAM_WORD_COUNT;
+            }
+
+            rv = EIP207_RC_Internal_Init(
+                Device,
+                EIP207_RC_INTERNAL_NOT_COMBINED,
+                EIP207_FRC_REG_BASE,
+                CacheConf_p->FRC,
+                FIRMWARE_EIP207_CS_FRC_RECORD_WORD_COUNT);
+            if (rv != EIP207_GLOBAL_NO_ERROR)
+                return rv;
+        }
+#endif // EIP207_GLOBAL_FRC_DISABLE
+        for (i=0; i < EIP207_GLOBAL_MAX_NOF_CACHE_SETS_TO_USE; i++)
+        {
+            CacheConf_p->TRC[i].DataWordCount = EIP207_TRC_RAM_WORD_COUNT;
+            CacheConf_p->TRC[i].AdminWordCount =
+                EIP207_TRC_ADMIN_RAM_WORD_COUNT;
+        }
+
+        // Initialize Transform Record Cache
+        rv = EIP207_RC_Internal_Init(
+                 Device,
+                 Capabilities.EIP207_Options.fCombinedFRC_TRC ?
+                         EIP207_RC_INTERNAL_FRC_TRC_COMBINED :
+                                EIP207_RC_INTERNAL_NOT_COMBINED,
+                 EIP207_TRC_REG_BASE,
+                 CacheConf_p->TRC,
+                 FIRMWARE_EIP207_CS_TRC_RECORD_WORD_COUNT);
+        if (rv != EIP207_GLOBAL_NO_ERROR)
+            return rv;
+
+        // Check if ARC4 Record Cache is available
+        if ( Capabilities.EIP207_Options.fARC4Present )
+        {
+            for (i=0; i < EIP207_GLOBAL_MAX_NOF_CACHE_SETS_TO_USE; i++)
+            {
+                CacheConf_p->ARC4[i].DataWordCount =
+                    EIP207_ARC4RC_RAM_WORD_COUNT;
+                CacheConf_p->ARC4[i].AdminWordCount =
+                    EIP207_ARC4RC_ADMIN_RAM_WORD_COUNT;
+            }
+            // Initialize ARC4 Record Cache
+            rv = EIP207_RC_Internal_Init(
+                    Device,
+                    Capabilities.EIP207_Options.fCombinedFRC_ARC4 ?
+                        EIP207_RC_INTERNAL_FRC_ARC4_COMBINED :
+                    (Capabilities.EIP207_Options.fCombinedTRC_ARC4 ?
+                          EIP207_RC_INTERNAL_TRC_ARC4_COMBINED :
+                                    EIP207_RC_INTERNAL_NOT_COMBINED),
+                    EIP207_ARC4RC_REG_BASE,
+                    CacheConf_p->ARC4,
+                    FIRMWARE_EIP207_CS_ARC4RC_RECORD_WORD_COUNT);
+            if (rv != EIP207_GLOBAL_NO_ERROR)
+                return rv;
+        }
+    }
+
+    // Initialize Flow Hash Engine, set IV values
+    EIP207_FHASH_IV_WR(Device,
+                       FLUEConf_p->IV.IV_Word32[0],
+                       FLUEConf_p->IV.IV_Word32[1],
+                       FLUEConf_p->IV.IV_Word32[2],
+                       FLUEConf_p->IV.IV_Word32[3]);
+
+    // Initialize FLUE Hash Tables
+    {
+        unsigned int i;
+
+        for (i = 0; i < FLUEConf_p->HashTablesCount; i++)
+            EIP207_FLUE_Init(Device,
+                             i,
+                             FLUEConf_p,
+                             Capabilities.EIP207_Options.fARC4Present,
+                             Capabilities.EIP207_Options.fLookupCached);
+    }
+
+    // Initialize optional FLUE Cache
+    if (Capabilities.EIP207_Options.fLookupCached)
+    {
+        EIP207_FLUEC_CTRL_WR(Device,
+                             false,        // Disable cache RAM access
+                             FLUEConf_p->fDelayMemXS,
+                             EIP207_FLUEC_TABLE_SIZE,
+                             EIP207_FLUEC_GROUP_SIZE,
+                             FLUEConf_p->CacheChain);  // Cache chain
+    }
+
+#ifdef EIP207_GLOBAL_DEBUG_FSM
+        {
+            EIP207_Global_Error_t rv;
+            uint32_t State = TrueIOArea_p->State;
+
+            // Transit to a new state
+            rv = EIP207Lib_Global_State_Set(
+                    (EIP207_Global_State_t* const)&State,
+                    EIP207_GLOBAL_STATE_RC_ENABLED);
+
+            TrueIOArea_p->State = State;
+
+            if (rv != EIP207_GLOBAL_NO_ERROR)
+                return EIP207_GLOBAL_ILLEGAL_IN_STATE;
+        }
+#endif // EIP207_GLOBAL_DEBUG_FSM
+
+    return EIP207_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Global_Firmware_Load
+ */
+EIP207_Global_Error_t
+EIP207_Global_Firmware_Load(
+        EIP207_Global_IOArea_t * const IOArea_p,
+        const unsigned int TimerPrescaler,
+        EIP207_Firmware_t * const IPUE_Firmware_p,
+        EIP207_Firmware_t * const IFPP_Firmware_p,
+        EIP207_Firmware_t * const OPUE_Firmware_p,
+        EIP207_Firmware_t * const OFPP_Firmware_p)
+{
+    EIP207_Global_Error_t EIP207_Rc;
+    Device_Handle_t Device;
+    volatile EIP207_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP207_GLOBAL_CHECK_POINTER(IOArea_p);
+
+    Device = TrueIOArea_p->Device;
+
+    // Download EIP-207c Input Classification Engine (ICE) firmware,
+    // use the same images for all the instances of the engine
+    EIP207_Rc = EIP207_ICE_Firmware_Load(Device,
+                                         TimerPrescaler,
+                                         IPUE_Firmware_p,
+                                         IFPP_Firmware_p);
+    if (EIP207_Rc != EIP207_GLOBAL_NO_ERROR)
+        return EIP207_Rc;
+
+    // Download EIP-207c Output Classification Engine (OCE) firmware,
+    // use the same images for all the instances of the engine
+    // Download Input Classification Engine (OCE) firmware
+    EIP207_Rc = EIP207_OCE_Firmware_Load(Device,
+                                             TimerPrescaler,
+                                             OPUE_Firmware_p,
+                                             OFPP_Firmware_p);
+        // OCE is not supported by this EIP-207 HW version
+    if (EIP207_Rc != EIP207_GLOBAL_UNSUPPORTED_FEATURE_ERROR &&
+        EIP207_Rc != EIP207_GLOBAL_NO_ERROR) // OCE is supported
+        return EIP207_Rc; // OCE FW download error, abort!
+
+#ifdef EIP207_GLOBAL_DEBUG_FSM
+        {
+            EIP207_Global_Error_t rv;
+            uint32_t State = TrueIOArea_p->State;
+
+            // Transit to a new state
+            rv = EIP207Lib_Global_State_Set(
+                    (EIP207_Global_State_t* const)&State,
+                    EIP207_GLOBAL_STATE_FW_LOADED);
+
+            TrueIOArea_p->State = State;
+
+            if (rv != EIP207_GLOBAL_NO_ERROR)
+                return EIP207_GLOBAL_ILLEGAL_IN_STATE;
+        }
+#endif // EIP207_GLOBAL_DEBUG_FSM
+
+    return EIP207_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Global_HWRevision_Get
+ */
+EIP207_Global_Error_t
+EIP207_Global_HWRevision_Get(
+        EIP207_Global_IOArea_t * const IOArea_p,
+        EIP207_Global_Capabilities_t * const Capabilities_p)
+{
+    Device_Handle_t Device;
+    volatile EIP207_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP207_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP207_GLOBAL_CHECK_POINTER(Capabilities_p);
+
+    Device = TrueIOArea_p->Device;
+
+    EIP207Lib_HWRevision_Get(Device,
+                             &Capabilities_p->EIP207_Options,
+                             &Capabilities_p->EIP207_Version);
+
+    return EIP207_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Global_GlobalStats_Get
+ */
+EIP207_Global_Error_t
+EIP207_Global_GlobalStats_Get(
+        EIP207_Global_IOArea_t * const IOArea_p,
+        const unsigned int CE_Number,
+        EIP207_Global_GlobalStats_t * const GlobalStats_p)
+{
+    Device_Handle_t Device;
+    EIP207_Global_Error_t rv;
+    volatile EIP207_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP207_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP207_GLOBAL_CHECK_POINTER(GlobalStats_p);
+
+    if(CE_Number >= EIP207_GLOBAL_MAX_NOF_CE_TO_USE)
+        return EIP207_GLOBAL_ARGUMENT_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+    rv = EIP207_ICE_GlobalStats_Get(Device, CE_Number, &GlobalStats_p->ICE);
+    if (rv != EIP207_GLOBAL_NO_ERROR)
+        return rv;
+
+    rv = EIP207_OCE_GlobalStats_Get(Device, CE_Number, &GlobalStats_p->OCE);
+    if (rv == EIP207_GLOBAL_UNSUPPORTED_FEATURE_ERROR)
+        return EIP207_GLOBAL_NO_ERROR; // OCE is not supported
+    else                               // by this EIP-207 HW version
+        return rv;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Global_ClockCount_Get
+ */
+EIP207_Global_Error_t
+EIP207_Global_ClockCount_Get(
+        EIP207_Global_IOArea_t * const IOArea_p,
+        const unsigned int CE_Number,
+        EIP207_Global_Clock_t * const Clock_p)
+{
+    Device_Handle_t Device;
+    EIP207_Global_Error_t rv;
+    volatile EIP207_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP207_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP207_GLOBAL_CHECK_POINTER(Clock_p);
+
+    if(CE_Number >= EIP207_GLOBAL_MAX_NOF_CE_TO_USE)
+        return EIP207_GLOBAL_ARGUMENT_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+    rv = EIP207_ICE_ClockCount_Get(Device, CE_Number, &Clock_p->ICE);
+    if (rv != EIP207_GLOBAL_NO_ERROR)
+        return rv;
+
+    rv = EIP207_OCE_ClockCount_Get(Device, CE_Number, &Clock_p->OCE);
+    if (rv == EIP207_GLOBAL_UNSUPPORTED_FEATURE_ERROR)
+        return EIP207_GLOBAL_NO_ERROR; // OCE is not supported
+    else                               // by this EIP-207 HW version
+        return rv;
+}
+
+
+/*-----------------------------------------------------------------------------
+ * EIP207_Global_Status_Get
+ */
+EIP207_Global_Error_t
+EIP207_Global_Status_Get(
+        EIP207_Global_IOArea_t * const IOArea_p,
+        const unsigned int CE_Number,
+        EIP207_Global_Status_t * const Status_p,
+        bool * const fFatalError_p)
+{
+    unsigned int i;
+    Device_Handle_t Device;
+    EIP207_Global_Error_t rv;
+    bool fFatalError = false;
+    volatile EIP207_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP207_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP207_GLOBAL_CHECK_POINTER(Status_p);
+    EIP207_GLOBAL_CHECK_POINTER(fFatalError_p);
+
+    if(CE_Number >= EIP207_GLOBAL_MAX_NOF_CE_TO_USE)
+        return EIP207_GLOBAL_ARGUMENT_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+    rv = EIP207_ICE_Status_Get(Device, CE_Number, &Status_p->ICE);
+    if (rv != EIP207_GLOBAL_NO_ERROR)
+        return rv;
+
+    rv = EIP207_OCE_Status_Get(Device, CE_Number, &Status_p->OCE);
+    if (rv != EIP207_GLOBAL_NO_ERROR &&
+        rv != EIP207_GLOBAL_UNSUPPORTED_FEATURE_ERROR)
+        return rv;
+
+    EIP207_FLUE_Status_Get(Device, &Status_p->FLUE);
+
+    if (Status_p->ICE.fPUE_EccDerr   ||
+        Status_p->ICE.fFPP_EccDerr   ||
+        Status_p->OCE.fPUE_EccDerr ||
+        Status_p->OCE.fFPP_EccDerr ||
+        Status_p->ICE.fTimerOverflow ||
+        Status_p->OCE.fTimerOverflow ||
+        Status_p->FLUE.Error1 != 0   ||
+        Status_p->FLUE.Error2 != 0)
+        fFatalError = true;
+
+    for (i = 0; i < EIP207_GLOBAL_MAX_NOF_CACHE_SETS_TO_USE; i++)
+    {
+        EIP207_RC_Internal_Status_Get(Device,
+                                      i,
+                                      &Status_p->FRC[i],
+                                      &Status_p->TRC[i],
+                                      &Status_p->ARC4RC[i]);
+        if (Status_p->FRC[i].fDMAReadError ||
+            Status_p->FRC[i].fDMAWriteError ||
+            Status_p->FRC[i].fAdminEccErr ||
+            Status_p->FRC[i].fDataEccOflo ||
+            Status_p->TRC[i].fDMAReadError ||
+            Status_p->TRC[i].fDMAWriteError ||
+            Status_p->TRC[i].fAdminEccErr ||
+            Status_p->TRC[i].fDataEccOflo ||
+            Status_p->ARC4RC[i].fDMAReadError ||
+            Status_p->ARC4RC[i].fDMAWriteError ||
+            Status_p->ARC4RC[i].fAdminEccErr ||
+            Status_p->ARC4RC[i].fDataEccOflo)
+            fFatalError = true;
+
+        EIP207_RC_Internal_DebugStatistics_Get(Device,
+                                               i,
+                                               &Status_p->FRCStats[i],
+                                               &Status_p->TRCStats[i]);
+    }
+
+    *fFatalError_p = fFatalError;
+
+#ifdef EIP207_GLOBAL_DEBUG_FSM
+    if (fFatalError)
+    {
+        uint32_t State = TrueIOArea_p->State;
+
+        // Transit to a new state
+        rv = EIP207Lib_Global_State_Set(
+                (EIP207_Global_State_t* const)&State,
+                EIP207_GLOBAL_STATE_FATAL_ERROR);
+
+        TrueIOArea_p->State = State;
+
+        if (rv != EIP207_GLOBAL_NO_ERROR)
+            return EIP207_GLOBAL_ILLEGAL_IN_STATE;
+    }
+#endif // EIP207_GLOBAL_DEBUG_FSM
+
+    return EIP207_GLOBAL_NO_ERROR;
+}
+
+
+/* end of file eip207_global_init.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_ice.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_ice.c
new file mode 100644
index 0000000..9f2e019
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_ice.c
@@ -0,0 +1,572 @@
+/* eip207_ice.c
+ *
+ * EIP-207c Input Classification Engine (ICE) interface implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// EIP-207c Input Classification Engine (ICE) interface
+#include "eip207_ice.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip207_global.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                 // uint32_t, bool
+
+// EIP-207 Global Control Driver Library Internal interfaces
+#include "eip207_level0.h"              // EIP-207 Level 0 macros
+
+// EIP-207 HW interface
+#include "eip207_hw_interface.h"
+
+// Driver Framework Device API
+#include "device_types.h"               // Device_Handle_t
+#include "device_rw.h"                  // Read32, Write32
+
+// EIP-207 Firmware Classification API
+#include "firmware_eip207_api_cs.h"     // Classification API: General
+
+// EIP-207 Firmware Download API
+#include "firmware_eip207_api_dwld.h"   // Classification API: FW download
+
+// EIP-207 Support API
+#include "eip207_support.h"
+
+// EIP97_Interfaces_Get()
+#include "eip97_global_internal.h"
+
+#include "clib.h"                       // memcmp
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+// Allow legacy firmware to be used, which does not have these constants.
+#ifndef FIRMWARE_EIP207_DWLD_ADMIN_RAM_INPUT_LAST_BYTE_COUNT
+#define FIRMWARE_EIP207_DWLD_ADMIN_RAM_INPUT_LAST_BYTE_COUNT FIRMWARE_EIP207_DWLD_ADMIN_RAM_LAST_BYTE_COUNT
+#endif
+#ifndef FIRMWARE_EIP207_CS_ADMIN_RAM_INPUT_LAST_BYTE_COUNT
+#define FIRMWARE_EIP207_CS_ADMIN_RAM_INPUT_LAST_BYTE_COUNT FIRMWARE_EIP207_DWLD_ADMIN_RAM_INPUT_LAST_BYTE_COUNT
+#endif
+
+// Number fo words to check when reading firmware back.
+#define EIP207_FW_CHECK_WORD_COUNT 16
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_ICE_Firmware_Load
+ */
+EIP207_Global_Error_t
+EIP207_ICE_Firmware_Load(
+        const Device_Handle_t Device,
+        const unsigned int TimerPrescaler,
+        EIP207_Firmware_t * const PUE_Firmware_p,
+        EIP207_Firmware_t * const FPP_Firmware_p)
+{
+    unsigned int NofCEs;
+    EIP97_Interfaces_Get(&NofCEs,NULL,NULL,NULL);
+    // Check if the Adapter provides the IPUE firmware image with correct size.
+    if (!PUE_Firmware_p->Image_p ||
+        PUE_Firmware_p->ImageWordCount > EIP207_IPUE_PROG_RAM_WORD_COUNT)
+            return EIP207_GLOBAL_ARGUMENT_ERROR;
+
+    // Check if the Adapter provides the IFPP firmware image with correct size.
+    if (!FPP_Firmware_p->Image_p ||
+        FPP_Firmware_p->ImageWordCount > EIP207_IPUE_PROG_RAM_WORD_COUNT)
+            return EIP207_GLOBAL_ARGUMENT_ERROR;
+
+
+    // Clear EIP-207c ICE Scratchpad RAM where the the firmware
+    // administration data will be located
+    {
+        unsigned int i, CECount, BlockCount, RequiredRAMByteCount;
+
+        RequiredRAMByteCount =
+                MAX(FIRMWARE_EIP207_CS_ADMIN_RAM_INPUT_LAST_BYTE_COUNT,
+                    FIRMWARE_EIP207_DWLD_ADMIN_RAM_INPUT_LAST_BYTE_COUNT);
+
+        // Check if the administration RAM required by the EIP-207 firmware
+        // fits into physically available scratchpad RAM
+        if ((EIP207_ICE_SCRATCH_RAM_128B_BLOCK_COUNT * 128) <
+            RequiredRAMByteCount)
+            return EIP207_GLOBAL_ARGUMENT_ERROR;
+
+        // Calculate how many 128-byte blocks are required for the firmware
+        // administration data
+        BlockCount = (RequiredRAMByteCount + 127) / 128;
+
+        for (CECount = 0; CECount < NofCEs; CECount++)
+        {
+            // Make ICE Scratchpad RAM accessible and set the timer
+            EIP207_ICE_SCRATCH_CTRL_WR(
+                    Device,
+                    CECount,
+                    true, // Change timer
+                    true, // Enable timer
+                    (uint16_t)TimerPrescaler,
+                    EIP207_ICE_SCRATCH_TIMER_OFLO_BIT, // Timer overflow bit
+                    true, // Change access
+                    (uint8_t)BlockCount);
+
+#ifdef DEBUG
+            // Check if the timer runs
+            {
+                uint32_t Value32;
+                unsigned int i;
+
+                for (i = 0; i < 10; i++)
+                {
+                    Value32 = Device_Read32(Device,
+                                            EIP207_ICE_REG_TIMER_LO(CECount));
+
+                    if (Value32 == 0)
+                        return EIP207_GLOBAL_INTERNAL_ERROR;
+                }
+            }
+#endif
+
+            // Write the ICE Scratchpad RAM with 0
+            for(i = 0; i < (BlockCount * 32); i++)
+            {
+                Device_Write32(Device,
+                               EIP207_ICE_REG_SCRATCH_RAM(CECount) +
+                                                           i * sizeof(uint32_t),
+                               0);
+#ifdef DEBUG
+                // Perform read-back check
+                {
+                    uint32_t Value32 =
+                        Device_Read32(
+                               Device,
+                               EIP207_ICE_REG_SCRATCH_RAM(CECount) +
+                                                           i * sizeof(uint32_t));
+
+                    if (Value32 != 0)
+                        return EIP207_GLOBAL_INTERNAL_ERROR;
+                }
+#endif
+            }
+        }
+
+        // Leave the scratchpad RAM accessible for the Host
+    }
+
+    // Download the firmware
+    {
+        unsigned int CECount;
+#ifdef DEBUG
+        unsigned int i;
+#endif
+        for (CECount = 0; CECount < NofCEs; CECount++)
+        {
+            // Reset the Input Flow Post-Processor micro-engine (IFPP) to make its
+            // Program RAM accessible
+            EIP207_ICE_FPP_CTRL_WR(Device,
+                                   CECount,
+                                   0,     // No start address for debug mode
+                                   1,       // Clear ECC correctable error
+                                   1,       // Clear ECC non-correctable error
+                                   false, // Debug mode OFF
+                                   true); // SW Reset ON
+
+            // Enable access to IFPP Program RAM
+            EIP207_ICE_RAM_CTRL_WR(Device, CECount, false, true);
+        }
+
+#ifdef DEBUG
+        // Write the Input Flow post-Processor micro-Engine firmware
+        for(i = 0; i < FPP_Firmware_p->ImageWordCount; i++)
+        {
+            Device_Write32(Device,
+                           EIP207_CS_RAM_XS_SPACE_BASE + i * sizeof(uint32_t),
+                           FPP_Firmware_p->Image_p[i]);
+            // Perform read-back check
+            {
+                uint32_t Value32 =
+                    Device_Read32(
+                           Device,
+                           EIP207_CS_RAM_XS_SPACE_BASE + i * sizeof(uint32_t));
+
+                if (Value32 != FPP_Firmware_p->Image_p[i])
+                    return EIP207_GLOBAL_INTERNAL_ERROR;
+            }
+        }
+#else
+        Device_Write32Array(Device,
+                            EIP207_CS_RAM_XS_SPACE_BASE,
+                            FPP_Firmware_p->Image_p,
+                            FPP_Firmware_p->ImageWordCount);
+        // Perform read-back check of small subset
+        {
+            static uint32_t ReadBuf[EIP207_FW_CHECK_WORD_COUNT];
+            Device_Read32Array(Device,
+                               EIP207_CS_RAM_XS_SPACE_BASE,
+                               ReadBuf,
+                               EIP207_FW_CHECK_WORD_COUNT);
+            if (memcmp(ReadBuf,
+                       FPP_Firmware_p->Image_p,
+                       EIP207_FW_CHECK_WORD_COUNT * sizeof(uint32_t)) != 0)
+                return EIP207_GLOBAL_INTERNAL_ERROR;
+
+        }
+#endif
+
+        for (CECount = 0; CECount < NofCEs; CECount++)
+        {
+            // Disable access to IFPP Program RAM
+            // Enable access to IPUE Program RAM
+            EIP207_ICE_RAM_CTRL_WR(Device, CECount, true, false);
+
+            // Reset the Input Pull-Up micro-Engine (IPUE) to make its
+            // Program RAM accessible
+            EIP207_ICE_PUE_CTRL_WR(Device,
+                                   CECount,
+                                   0,     // No start address for debug mode
+                                   1,       // Clear ECC correctable error
+                                   1,       // Clear ECC non-correctable error
+                                   false, // Debug mode OFF
+                                   true); // SW Reset ON
+        }
+
+#ifdef DEBUG
+        // Write the Input Pull-Up micro-Engine firmware
+        for(i = 0; i < PUE_Firmware_p->ImageWordCount; i++)
+        {
+            Device_Write32(Device,
+                           EIP207_CS_RAM_XS_SPACE_BASE + i * sizeof(uint32_t),
+                           PUE_Firmware_p->Image_p[i]);
+            // Perform read-back check
+            {
+                uint32_t Value32 =
+                    Device_Read32(
+                           Device,
+                           EIP207_CS_RAM_XS_SPACE_BASE + i * sizeof(uint32_t));
+
+                if (Value32 != PUE_Firmware_p->Image_p[i])
+                    return EIP207_GLOBAL_INTERNAL_ERROR;
+            }
+        }
+#else
+        Device_Write32Array(Device,
+                            EIP207_CS_RAM_XS_SPACE_BASE,
+                            PUE_Firmware_p->Image_p,
+                            PUE_Firmware_p->ImageWordCount);
+        // Perform read-back check of small subset
+        {
+            static uint32_t ReadBuf[EIP207_FW_CHECK_WORD_COUNT];
+            Device_Read32Array(Device,
+                               EIP207_CS_RAM_XS_SPACE_BASE,
+                               ReadBuf,
+                               EIP207_FW_CHECK_WORD_COUNT);
+            if (memcmp(ReadBuf,
+                       PUE_Firmware_p->Image_p,
+                       EIP207_FW_CHECK_WORD_COUNT * sizeof(uint32_t)) != 0)
+                return EIP207_GLOBAL_INTERNAL_ERROR;
+
+        }
+#endif
+
+        // Disable access to IPUE Program RAM
+        for (CECount = 0; CECount < NofCEs; CECount++)
+            EIP207_ICE_RAM_CTRL_WR(Device, CECount, false, false);
+
+#ifdef EIP207_GLOBAL_FIRMWARE_DOWNLOAD_VERSION_CHECK
+        // Check the firmware version and start all the engines
+        for (CECount = 0; CECount < NofCEs; CECount++)
+        {
+            uint32_t Value32;
+            unsigned int Ma, Mi, Pl, i;
+            bool fUpdated;
+
+            // Start the IFPP in Debug mode for the firmware version check
+            EIP207_ICE_FPP_CTRL_WR(
+                        Device,
+                        CECount,
+                        FIRMWARE_EIP207_DWLD_IFPP_VERSION_CHECK_DBG_PROG_CNTR,
+                        1,       // Clear ECC correctable error
+                        1,       // Clear ECC non-correctable error
+                        true,    // Debug mode ON
+                        false);  // SW Reset OFF
+
+            // Wait for the IFPP version update
+            for (i = 0; i < EIP207_FW_VER_CHECK_MAX_NOF_READ_ATTEMPTS; i++)
+            {
+                Value32 = Device_Read32(
+                        Device,
+                        EIP207_ICE_REG_SCRATCH_RAM(CECount) +
+                        FIRMWARE_EIP207_DWLD_ADMIN_RAM_IFPP_CTRL_BYTE_OFFSET);
+
+                FIRMWARE_EIP207_DWLD_IFPP_VersionUpdated_Read(Value32,
+                                                              &fUpdated);
+
+                if (fUpdated)
+                    break;
+            }
+
+            if (!fUpdated)
+                return EIP207_GLOBAL_INTERNAL_ERROR;
+
+            Value32 = Device_Read32(
+                      Device,
+                      EIP207_ICE_REG_SCRATCH_RAM(CECount) +
+                      FIRMWARE_EIP207_DWLD_ADMIN_RAM_IFPP_VERSION_BYTE_OFFSET);
+
+            FIRMWARE_EIP207_DWLD_Version_Read(Value32, &Ma, &Mi, &Pl);
+
+            if (FPP_Firmware_p->Major == 0 &&
+                FPP_Firmware_p->Minor == 0 &&
+                FPP_Firmware_p->PatchLevel == 0)
+            {  // Adapter did not provide expected version, return it.
+                FPP_Firmware_p->Major = Ma;
+                FPP_Firmware_p->Minor = Mi;
+                FPP_Firmware_p->PatchLevel = Pl;
+            }
+            else
+            {
+                // Adapter provided expected version, check it.
+                if (FPP_Firmware_p->Major != Ma ||
+                    FPP_Firmware_p->Minor != Mi ||
+                    FPP_Firmware_p->PatchLevel != Pl)
+                    return EIP207_GLOBAL_INTERNAL_ERROR;
+            }
+
+            // Start the IPUE in Debug mode for the firmware version check
+            EIP207_ICE_PUE_CTRL_WR(
+                        Device,
+                        CECount,
+                        FIRMWARE_EIP207_DWLD_IPUE_VERSION_CHECK_DBG_PROG_CNTR,
+                        1,       // Clear ECC correctable error
+                        1,       // Clear ECC non-correctable error
+                        true,    // Debug mode ON
+                        false);  // SW Reset OFF
+
+            // Wait for the IPUE version update
+            for (i = 0; i < EIP207_FW_VER_CHECK_MAX_NOF_READ_ATTEMPTS; i++)
+            {
+                Value32 = Device_Read32(
+                        Device,
+                        EIP207_ICE_REG_SCRATCH_RAM(CECount) +
+                        FIRMWARE_EIP207_DWLD_ADMIN_RAM_IPUE_CTRL_BYTE_OFFSET);
+
+                FIRMWARE_EIP207_DWLD_IPUE_VersionUpdated_Read(Value32,
+                                                              &fUpdated);
+
+                if (fUpdated)
+                    break;
+            }
+
+            if (!fUpdated)
+                return EIP207_GLOBAL_INTERNAL_ERROR;
+
+            Value32 = Device_Read32(
+                     Device,
+                     EIP207_ICE_REG_SCRATCH_RAM(CECount) +
+                     FIRMWARE_EIP207_DWLD_ADMIN_RAM_IPUE_VERSION_BYTE_OFFSET);
+
+            FIRMWARE_EIP207_DWLD_Version_Read(Value32, &Ma, &Mi, &Pl);
+
+            if (PUE_Firmware_p->Major == 0 &&
+                PUE_Firmware_p->Minor == 0 &&
+                PUE_Firmware_p->PatchLevel == 0)
+            {  // Adapter did not provide expected version, return it.
+                PUE_Firmware_p->Major = Ma;
+                PUE_Firmware_p->Minor = Mi;
+                PUE_Firmware_p->PatchLevel = Pl;
+            }
+            else
+            {
+                // Adapter provided expected version, check it.
+                if (PUE_Firmware_p->Major != Ma ||
+                    PUE_Firmware_p->Minor != Mi ||
+                    PUE_Firmware_p->PatchLevel != Pl)
+                    return EIP207_GLOBAL_INTERNAL_ERROR;
+            }
+        } // for
+#else
+        for (CECount = 0; CECount < NofCEs; CECount++)
+        {
+            // Start the IFPP in Debug mode
+            EIP207_ICE_FPP_CTRL_WR(
+                            Device,
+                            CECount,
+                            FIRMWARE_EIP207_DWLD_IFPP_VERSION_CHECK_DBG_PROG_CNTR,
+                            1,       // Clear ECC correctable error
+                            1,       // Clear ECC non-correctable error
+                            true,    // Debug mode ON
+                            false);  // SW Reset OFF
+
+            // Start the IPUE in Debug mode
+            EIP207_ICE_PUE_CTRL_WR(
+                            Device,
+                            CECount,
+                            FIRMWARE_EIP207_DWLD_IPUE_VERSION_CHECK_DBG_PROG_CNTR,
+                            1,       // Clear ECC correctable error
+                            1,       // Clear ECC non-correctable error
+                            true,    // Debug mode ON
+                            false);  // SW Reset OFF
+        } // for
+#endif // EIP207_GLOBAL_FIRMWARE_DOWNLOAD_VERSION_CHECK
+        for (CECount = 0; CECount < NofCEs; CECount++)
+        {
+            uint32_t InputBufferSize = Device_Read32(
+                Device,
+                EIP207_ICE_REG_SCRATCH_RAM(CECount) +
+                4*33) & MASK_16_BITS;
+            if (InputBufferSize != 0)
+            {
+                if (PUE_Firmware_p->Major > 3 ||
+                    (PUE_Firmware_p->Major ==3 &&
+                     PUE_Firmware_p->Minor >=1))
+                {
+                    InputBufferSize -= 2048;
+                }
+                else
+                {
+                    InputBufferSize = (InputBufferSize * 3) / 4;
+                }
+                EIP207_ICE_ADAPT_CTRL_WR(Device, CECount, InputBufferSize);
+            }
+            EIP207_ICE_PUTF_CTRL_WR(Device, CECount, 3, false);
+            EIP207_ICE_PPTF_CTRL_WR(Device, CECount, 0, false);
+        }
+    }
+
+
+    return EIP207_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_ICE_GlobalStats_Get
+ */
+EIP207_Global_Error_t
+EIP207_ICE_GlobalStats_Get(
+        const Device_Handle_t Device,
+        const unsigned int CE_Number,
+        EIP207_Global_ICE_GlobalStats_t * const ICE_GlobalStats_p)
+{
+    EIP207_Global_Error_t rv;
+
+    rv = EIP207_Global_Read64(
+                       Device,
+                       EIP207_ICE_REG_SCRATCH_RAM(CE_Number) +
+                         FIRMWARE_EIP207_CS_ADMIN_RAM_STAT_DROP_LO_BYTE_OFFSET,
+                       EIP207_ICE_REG_SCRATCH_RAM(CE_Number) +
+                         FIRMWARE_EIP207_CS_ADMIN_RAM_STAT_DROP_HI_BYTE_OFFSET,
+                       &ICE_GlobalStats_p->DroppedPacketsCounter);
+    if (rv != EIP207_GLOBAL_NO_ERROR)
+        return rv;
+
+    rv = EIP207_Global_Read64(
+                     Device,
+                     EIP207_ICE_REG_SCRATCH_RAM(CE_Number) +
+                       FIRMWARE_EIP207_CS_ADMIN_RAM_STAT_IN_OCT_LO_BYTE_OFFSET,
+                     EIP207_ICE_REG_SCRATCH_RAM(CE_Number) +
+                       FIRMWARE_EIP207_CS_ADMIN_RAM_STAT_IN_OCT_HI_BYTE_OFFSET,
+                     &ICE_GlobalStats_p->InboundOctetsCounter);
+    if (rv != EIP207_GLOBAL_NO_ERROR)
+        return rv;
+
+    rv = EIP207_Global_Read64(
+                    Device,
+                    EIP207_ICE_REG_SCRATCH_RAM(CE_Number) +
+                      FIRMWARE_EIP207_CS_ADMIN_RAM_STAT_OUT_OCT_LO_BYTE_OFFSET,
+                    EIP207_ICE_REG_SCRATCH_RAM(CE_Number) +
+                      FIRMWARE_EIP207_CS_ADMIN_RAM_STAT_OUT_OCT_HI_BYTE_OFFSET,
+                    &ICE_GlobalStats_p->OutboundOctetsCounter);
+    if (rv != EIP207_GLOBAL_NO_ERROR)
+        return rv;
+
+    ICE_GlobalStats_p->InboundPacketsCounter =
+    Device_Read32(Device,
+                  EIP207_ICE_REG_SCRATCH_RAM(CE_Number) +
+                  FIRMWARE_EIP207_CS_ADMIN_RAM_STAT_IN_PKT_BYTE_OFFSET);
+
+    ICE_GlobalStats_p->OutboundPacketCounter =
+    Device_Read32(Device,
+                  EIP207_ICE_REG_SCRATCH_RAM(CE_Number) +
+                  FIRMWARE_EIP207_CS_ADMIN_RAM_STAT_OUT_PKT_BYTE_OFFSET);
+
+    return EIP207_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_ICE_ClockCount_Get
+ */
+EIP207_Global_Error_t
+EIP207_ICE_ClockCount_Get(
+        const Device_Handle_t Device,
+        const unsigned int CE_Number,
+        EIP207_Global_Value64_t * const ICE_Clock_p)
+{
+    return EIP207_Global_Read64(
+                            Device,
+                            EIP207_ICE_REG_SCRATCH_RAM(CE_Number) +
+                              FIRMWARE_EIP207_CS_ADMIN_RAM_TIME_LO_BYTE_OFFSET,
+                            EIP207_ICE_REG_SCRATCH_RAM(CE_Number) +
+                              FIRMWARE_EIP207_CS_ADMIN_RAM_TIME_HI_BYTE_OFFSET,
+                            ICE_Clock_p);
+}
+
+
+/*-----------------------------------------------------------------------------
+ * EIP207_ICE_Status_Get
+ */
+EIP207_Global_Error_t
+EIP207_ICE_Status_Get(
+        const Device_Handle_t Device,
+        const unsigned int CE_Number,
+        EIP207_Global_CE_Status_t * const ICE_Status_p)
+{
+    EIP207_ICE_PUE_CTRL_RD_CLEAR(Device,
+                           CE_Number,
+                           &ICE_Status_p->fPUE_EccCorr,
+                           &ICE_Status_p->fPUE_EccDerr);
+
+    EIP207_ICE_FPP_CTRL_RD_CLEAR(Device,
+                           CE_Number,
+                           &ICE_Status_p->fFPP_EccCorr,
+                           &ICE_Status_p->fFPP_EccDerr);
+
+    EIP207_ICE_SCRATCH_CTRL_RD(Device,
+                               CE_Number,
+                               &ICE_Status_p->fTimerOverflow);
+
+    return EIP207_GLOBAL_NO_ERROR;
+}
+
+
+/* end of file eip207_ice.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_oce.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_oce.c
new file mode 100644
index 0000000..7d29ed2
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_oce.c
@@ -0,0 +1,514 @@
+/* eip207_oce.c
+ *
+ * EIP-207c Output Classification Engine (OCE) interface implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// EIP-207c Output Classification Engine (OCE) interface
+#include "eip207_oce.h"
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip207_global.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                 // uint32_t, bool
+
+// Driver Framework C Run-Time Library Abstraction API
+#include "clib.h"                 // ZEROINIT
+
+// EIP-207 Global Control Driver Library Internal interfaces
+#include "eip207_level0.h"              // EIP-207 Level 0 macros
+
+// Driver Framework Device API
+#include "device_types.h"               // Device_Handle_t
+#include "device_rw.h"                  // Read32, Write32
+
+// EIP-207 Firmware Classification API
+#include "firmware_eip207_api_cs.h"     // Classification API: General
+
+// EIP-207 Firmware Download API
+#include "firmware_eip207_api_dwld.h"   // Classification API: FW download
+
+// EIP97_Interfaces_Get()
+#include "eip97_global_internal.h"
+
+// EIP97 Global init API
+#include "eip97_global_init.h"
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+// Allow legacy firmware to be used, which does not have these constants.
+#ifndef FIRMWARE_EIP207_DWLD_ADMIN_RAM_INPUT_LAST_BYTE_COUNT
+#define FIRMWARE_EIP207_DWLD_ADMIN_RAM_INPUT_LAST_BYTE_COUNT FIRMWARE_EIP207_DWLD_ADMIN_RAM_LAST_BYTE_COUNT
+#endif
+#ifndef FIRMWARE_EIP207_CS_ADMIN_RAM_INPUT_LAST_BYTE_COUNT
+#define FIRMWARE_EIP207_CS_ADMIN_RAM_INPUT_LAST_BYTE_COUNT FIRMWARE_EIP207_DWLD_ADMIN_RAM_INPUT_LAST_BYTE_COUNT
+#endif
+
+// Number fo words to check when reading firmware back.
+#define EIP207_FW_CHECK_WORD_COUNT 16
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_OCE_Firmware_Load
+ */
+EIP207_Global_Error_t
+EIP207_OCE_Firmware_Load(
+        const Device_Handle_t Device,
+        const unsigned int TimerPrescaler,
+        EIP207_Firmware_t * const PUE_Firmware_p,
+        EIP207_Firmware_t * const FPP_Firmware_p)
+{
+    unsigned int NofCEs;
+
+    if ((EIP97_SupportedFuncs_Get() & BIT_1) != 0)
+    {
+        EIP97_Interfaces_Get(&NofCEs,NULL,NULL,NULL);
+        // Check if the Adapter provides the OPUE firmware image with correct size.
+        if (!PUE_Firmware_p->Image_p ||
+            PUE_Firmware_p->ImageWordCount > EIP207_OPUE_PROG_RAM_WORD_COUNT)
+            return EIP207_GLOBAL_ARGUMENT_ERROR;
+
+        // Check if the Adapter provides the OFPP firmware image with correct size.
+        if (!FPP_Firmware_p->Image_p ||
+            FPP_Firmware_p->ImageWordCount > EIP207_OPUE_PROG_RAM_WORD_COUNT)
+            return EIP207_GLOBAL_ARGUMENT_ERROR;
+
+
+        // Clear EIP-207c OCE Scratchpad RAM where the the firmware
+        // administration data will be located
+        {
+            unsigned int i, CECount, BlockCount, RequiredRAMByteCount;
+
+            RequiredRAMByteCount =
+                MAX(FIRMWARE_EIP207_CS_ADMIN_RAM_INPUT_LAST_BYTE_COUNT,
+                    FIRMWARE_EIP207_DWLD_ADMIN_RAM_INPUT_LAST_BYTE_COUNT);
+
+            // Check if the administration RAM required by the EIP-207 firmware
+            // fits into physically available scratchpad RAM
+            if ((EIP207_OCE_SCRATCH_RAM_128B_BLOCK_COUNT * 128) <
+                RequiredRAMByteCount)
+                return EIP207_GLOBAL_ARGUMENT_ERROR;
+
+            // Calculate how many 128-byte blocks are required for the firmware
+            // administration data
+            BlockCount = (RequiredRAMByteCount + 127) / 128;
+
+            for (CECount = 0; CECount < NofCEs; CECount++)
+            {
+                // Make OCE Scratchpad RAM accessible and set the timer
+                EIP207_OCE_SCRATCH_CTRL_WR(
+                    Device,
+                    CECount,
+                    true, // Change timer
+                    true, // Enable timer
+                    (uint16_t)TimerPrescaler,
+                    EIP207_OCE_SCRATCH_TIMER_OFLO_BIT, // Timer overflow bit
+                    true, // Change access
+                    (uint8_t)BlockCount);
+
+#ifdef DEBUG
+                // Check if the timer runs
+                {
+                    uint32_t Value32;
+                    unsigned int i;
+
+                    for (i = 0; i < 10; i++)
+                    {
+                        Value32 = Device_Read32(Device,
+                                                EIP207_OCE_REG_TIMER_LO(CECount));
+
+                        if (Value32 == 0)
+                            return EIP207_GLOBAL_INTERNAL_ERROR;
+                    }
+                }
+#endif
+
+                // Write the OCE Scratchpad RAM with 0
+                for(i = 0; i < (BlockCount * 32); i++)
+                {
+                    Device_Write32(Device,
+                                   EIP207_OCE_REG_SCRATCH_RAM(CECount) +
+                                   i * sizeof(uint32_t),
+                                   0);
+#ifdef DEBUG
+                    // Perform read-back check
+                    {
+                        uint32_t Value32 =
+                            Device_Read32(
+                                Device,
+                                EIP207_OCE_REG_SCRATCH_RAM(CECount) +
+                                i * sizeof(uint32_t));
+
+                        if (Value32 != 0)
+                            return EIP207_GLOBAL_INTERNAL_ERROR;
+                    }
+#endif
+                }
+            }
+
+            // Leave the scratchpad RAM accessible for the Host
+        }
+
+        // Download the firmware
+        {
+            unsigned int CECount;
+#ifdef DEBUG
+            unsigned int i;
+#endif
+            for (CECount = 0; CECount < NofCEs; CECount++)
+            {
+                // Reset the Input Flow Post-Processor micro-engine (OFPP) to make its
+                // Program RAM accessible
+                EIP207_OCE_FPP_CTRL_WR(Device,
+                                       CECount,
+                                       0,     // No start address for debug mode
+                                       1,       // Clear ECC correctable error
+                                       1,       // Clear ECC non-correctable error
+                                       false, // Debug mode OFF
+                                       true); // SW Reset ON
+
+                // Enable access to OFPP Program RAM
+                EIP207_OCE_RAM_CTRL_WR(Device, CECount, false, true);
+            }
+
+#ifdef DEBUG
+            // Write the Input Flow post-Processor micro-Engine firmware
+            for(i = 0; i < FPP_Firmware_p->ImageWordCount; i++)
+            {
+                Device_Write32(Device,
+                               EIP207_CS_RAM_XS_SPACE_BASE + i * sizeof(uint32_t),
+                               FPP_Firmware_p->Image_p[i]);
+                // Perform read-back check
+                {
+                    uint32_t Value32 =
+                        Device_Read32(
+                            Device,
+                           EIP207_CS_RAM_XS_SPACE_BASE + i * sizeof(uint32_t));
+
+                    if (Value32 != FPP_Firmware_p->Image_p[i])
+                        return EIP207_GLOBAL_INTERNAL_ERROR;
+                }
+            }
+#else
+            Device_Write32Array(Device,
+                                EIP207_CS_RAM_XS_SPACE_BASE,
+                                FPP_Firmware_p->Image_p,
+                                FPP_Firmware_p->ImageWordCount);
+            // Perform read-back check of small subset
+            {
+                static uint32_t ReadBuf[EIP207_FW_CHECK_WORD_COUNT];
+                Device_Read32Array(Device,
+                                   EIP207_CS_RAM_XS_SPACE_BASE,
+                                   ReadBuf,
+                                   EIP207_FW_CHECK_WORD_COUNT);
+                if (memcmp(ReadBuf,
+                           FPP_Firmware_p->Image_p,
+                           EIP207_FW_CHECK_WORD_COUNT * sizeof(uint32_t)) != 0)
+                    return EIP207_GLOBAL_INTERNAL_ERROR;
+
+            }
+#endif
+
+            for (CECount = 0; CECount < NofCEs; CECount++)
+            {
+                // Disable access to OFPP Program RAM
+                // Enable access to OPUE Program RAM
+                EIP207_OCE_RAM_CTRL_WR(Device, CECount, true, false);
+
+                // Reset the Input Pull-Up micro-Engine (OPUE) to make its
+                // Program RAM accessible
+                EIP207_OCE_PUE_CTRL_WR(Device,
+                                       CECount,
+                                       0,     // No start address for debug mode
+                                       1,       // Clear ECC correctable error
+                                       1,       // Clear ECC non-correctable error
+                                   false, // Debug mode OFF
+                                       true); // SW Reset ON
+            }
+
+#ifdef DEBUG
+            // Write the Input Pull-Up micro-Engine firmware
+            for(i = 0; i < PUE_Firmware_p->ImageWordCount; i++)
+            {
+                Device_Write32(Device,
+                               EIP207_CS_RAM_XS_SPACE_BASE + i * sizeof(uint32_t),
+                               PUE_Firmware_p->Image_p[i]);
+                // Perform read-back check
+                {
+                    uint32_t Value32 =
+                        Device_Read32(
+                            Device,
+                            EIP207_CS_RAM_XS_SPACE_BASE + i * sizeof(uint32_t));
+
+                    if (Value32 != PUE_Firmware_p->Image_p[i])
+                        return EIP207_GLOBAL_INTERNAL_ERROR;
+                }
+            }
+#else
+            Device_Write32Array(Device,
+                                EIP207_CS_RAM_XS_SPACE_BASE,
+                                PUE_Firmware_p->Image_p,
+                                PUE_Firmware_p->ImageWordCount);
+            // Perform read-back check of small subset
+            {
+                static uint32_t ReadBuf[EIP207_FW_CHECK_WORD_COUNT];
+                Device_Read32Array(Device,
+                                   EIP207_CS_RAM_XS_SPACE_BASE,
+                                   ReadBuf,
+                               EIP207_FW_CHECK_WORD_COUNT);
+                if (memcmp(ReadBuf,
+                           PUE_Firmware_p->Image_p,
+                           EIP207_FW_CHECK_WORD_COUNT * sizeof(uint32_t)) != 0)
+                    return EIP207_GLOBAL_INTERNAL_ERROR;
+
+            }
+#endif
+
+            // Disable access to OPUE Program RAM
+            for (CECount = 0; CECount < EIP207_GLOBAL_MAX_NOF_CE_TO_USE; CECount++)
+                EIP207_OCE_RAM_CTRL_WR(Device, CECount, false, false);
+
+#ifdef EIP207_GLOBAL_FIRMWARE_DOWNLOAD_VERSION_CHECK
+            // Check the firmware version and start all the engines
+            for (CECount = 0; CECount < NofCEs; CECount++)
+            {
+                uint32_t Value32;
+                unsigned int Ma, Mi, Pl, i;
+                bool fUpdated;
+
+                // Start the OFPP in Debug mode for the firmware version check
+                EIP207_OCE_FPP_CTRL_WR(
+                    Device,
+                    CECount,
+                    FIRMWARE_EIP207_DWLD_OFPP_VERSION_CHECK_DBG_PROG_CNTR,
+                    1,       // Clear ECC correctable error
+                    1,       // Clear ECC non-correctable error
+                    true,    // Debug mode ON
+                    false);  // SW Reset OFF
+
+                // Wait for the OFPP version update
+                for (i = 0; i < EIP207_FW_VER_CHECK_MAX_NOF_READ_ATTEMPTS; i++)
+                {
+                    Value32 = Device_Read32(
+                        Device,
+                        EIP207_OCE_REG_SCRATCH_RAM(CECount) +
+                        FIRMWARE_EIP207_DWLD_ADMIN_RAM_OFPP_CTRL_BYTE_OFFSET);
+
+                    FIRMWARE_EIP207_DWLD_OFPP_VersionUpdated_Read(Value32,
+                                                                  &fUpdated);
+
+                    if (fUpdated)
+                        break;
+                }
+
+                if (!fUpdated)
+                    return EIP207_GLOBAL_INTERNAL_ERROR;
+
+                Value32 = Device_Read32(
+                    Device,
+                    EIP207_OCE_REG_SCRATCH_RAM(CECount) +
+                    FIRMWARE_EIP207_DWLD_ADMIN_RAM_OFPP_VERSION_BYTE_OFFSET);
+
+                FIRMWARE_EIP207_DWLD_Version_Read(Value32, &Ma, &Mi, &Pl);
+
+                if (FPP_Firmware_p->Major == 0 &&
+                    FPP_Firmware_p->Minor == 0 &&
+                    FPP_Firmware_p->PatchLevel == 0)
+                {  // Adapter did not provide expected version, return it.
+                    FPP_Firmware_p->Major = Ma;
+                    FPP_Firmware_p->Minor = Mi;
+                    FPP_Firmware_p->PatchLevel = Pl;
+                }
+                else
+                {
+                    // Adapter provided expected version, check it.
+                    if (FPP_Firmware_p->Major != Ma ||
+                        FPP_Firmware_p->Minor != Mi ||
+                        FPP_Firmware_p->PatchLevel != Pl)
+                        return EIP207_GLOBAL_INTERNAL_ERROR;
+                }
+
+                // Start the OPUE in Debug mode for the firmware version check
+                EIP207_OCE_PUE_CTRL_WR(
+                    Device,
+                    CECount,
+                    FIRMWARE_EIP207_DWLD_OPUE_VERSION_CHECK_DBG_PROG_CNTR,
+                    1,       // Clear ECC correctable error
+                    1,       // Clear ECC non-correctable error
+                    true,    // Debug mode ON
+                    false);  // SW Reset OFF
+
+                // Wait for the OPUE version update
+                for (i = 0; i < EIP207_FW_VER_CHECK_MAX_NOF_READ_ATTEMPTS; i++)
+                {
+                    Value32 = Device_Read32(
+                        Device,
+                        EIP207_OCE_REG_SCRATCH_RAM(CECount) +
+                        FIRMWARE_EIP207_DWLD_ADMIN_RAM_OPUE_CTRL_BYTE_OFFSET);
+
+                    FIRMWARE_EIP207_DWLD_OPUE_VersionUpdated_Read(Value32,
+                                                                  &fUpdated);
+
+                    if (fUpdated)
+                        break;
+                }
+
+                if (!fUpdated)
+                    return EIP207_GLOBAL_INTERNAL_ERROR;
+
+                Value32 = Device_Read32(
+                    Device,
+                     EIP207_OCE_REG_SCRATCH_RAM(CECount) +
+                    FIRMWARE_EIP207_DWLD_ADMIN_RAM_OPUE_VERSION_BYTE_OFFSET);
+
+                FIRMWARE_EIP207_DWLD_Version_Read(Value32, &Ma, &Mi, &Pl);
+
+                if (PUE_Firmware_p->Major == 0 &&
+                    PUE_Firmware_p->Minor == 0 &&
+                PUE_Firmware_p->PatchLevel == 0)
+                {  // Adapter did not provide expected version, return it.
+                    PUE_Firmware_p->Major = Ma;
+                    PUE_Firmware_p->Minor = Mi;
+                    PUE_Firmware_p->PatchLevel = Pl;
+                }
+                else
+                {
+                    // Adapter provided expected version, check it.
+                    if (PUE_Firmware_p->Major != Ma ||
+                    PUE_Firmware_p->Minor != Mi ||
+                        PUE_Firmware_p->PatchLevel != Pl)
+                        return EIP207_GLOBAL_INTERNAL_ERROR;
+                }
+            } // for
+#else
+            for (CECount = 0; CECount < EIP207_GLOBAL_MAX_NOF_CE_TO_USE; CECount++)
+            {
+            // Start the OFPP in Debug mode
+                EIP207_OCE_FPP_CTRL_WR(
+                    Device,
+                    CECount,
+                    FIRMWARE_EIP207_DWLD_OFPP_VERSION_CHECK_DBG_PROG_CNTR,
+                    1,       // Clear ECC correctable error
+                    1,       // Clear ECC non-correctable error
+                    true,    // Debug mode ON
+                    false);  // SW Reset OFF
+
+                // Start the OPUE in Debug mode
+                EIP207_OCE_PUE_CTRL_WR(
+                    Device,
+                    CECount,
+                    FIRMWARE_EIP207_DWLD_OPUE_VERSION_CHECK_DBG_PROG_CNTR,
+                    1,       // Clear ECC correctable error
+                    1,       // Clear ECC non-correctable error
+                            true,    // Debug mode ON
+                    false);  // SW Reset OFF
+            } // for
+#endif // EIP207_GLOBAL_FIRMWARE_DOWNLOAD_VERSION_CHECK
+        }
+    }
+    return EIP207_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_OCE_GlobalStats_Get
+ */
+EIP207_Global_Error_t
+EIP207_OCE_GlobalStats_Get(
+        const Device_Handle_t Device,
+        const unsigned int CE_Number,
+        EIP207_Global_OCE_GlobalStats_t * const OCE_GlobalStats_p)
+{
+    IDENTIFIER_NOT_USED(Device);
+    IDENTIFIER_NOT_USED(CE_Number);
+
+    // Not used / implemented yet
+    ZEROINIT(*OCE_GlobalStats_p);
+
+    return EIP207_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_OCE_ClockCount_Get
+ */
+EIP207_Global_Error_t
+EIP207_OCE_ClockCount_Get(
+        const Device_Handle_t Device,
+        const unsigned int CE_Number,
+        EIP207_Global_Value64_t * const OCE_Clock_p)
+{
+    IDENTIFIER_NOT_USED(Device);
+    IDENTIFIER_NOT_USED(CE_Number);
+
+    // Not used / implemented yet
+    ZEROINIT(*OCE_Clock_p);
+
+    return EIP207_GLOBAL_NO_ERROR;
+}
+
+
+/*-----------------------------------------------------------------------------
+ * EIP207_OCE_Status_Get
+ */
+EIP207_Global_Error_t
+EIP207_OCE_Status_Get(
+        const Device_Handle_t Device,
+        const unsigned int CE_Number,
+        EIP207_Global_CE_Status_t * const OCE_Status_p)
+{
+    if ((EIP97_SupportedFuncs_Get() & BIT_1) != 0)
+    {
+        EIP207_OCE_PUE_CTRL_RD_CLEAR(Device,
+                                     CE_Number,
+                                     &OCE_Status_p->fPUE_EccCorr,
+                                     &OCE_Status_p->fPUE_EccDerr);
+
+        EIP207_OCE_FPP_CTRL_RD_CLEAR(Device,
+                                     CE_Number,
+                                     &OCE_Status_p->fFPP_EccCorr,
+                                     &OCE_Status_p->fFPP_EccDerr);
+
+        EIP207_OCE_SCRATCH_CTRL_RD(Device,
+                                   CE_Number,
+                                   &OCE_Status_p->fTimerOverflow);
+    }
+    return EIP207_GLOBAL_NO_ERROR;
+}
+
+
+/* end of file eip207_oce.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_rc.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_rc.c
new file mode 100644
index 0000000..42ea46c
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_rc.c
@@ -0,0 +1,107 @@
+/* eip207_rc.c
+ *
+ * EIP-207 Record Cache (RC) interface High-Performance (HP) implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// EIP-207 Record Cache (RC) interface
+#include "eip207_rc.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                 // uint32_t
+
+// EIP-207 Global Control Driver Library Internal interfaces
+#include "eip207_level0.h"              // EIP-207 Level 0 macros
+
+// Driver Framework Device API
+#include "device_types.h"               // Device_Handle_t
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_RC_BaseAddr_Set
+ */
+void
+EIP207_RC_BaseAddr_Set(
+            const Device_Handle_t Device,
+            const uint32_t CacheBase,
+            const unsigned int CacheNr,
+            const uint32_t Address,
+            const uint32_t UpperAddress)
+{
+    // Not implemented
+    IDENTIFIER_NOT_USED(Device);
+    IDENTIFIER_NOT_USED(CacheBase);
+    IDENTIFIER_NOT_USED(CacheNr);
+    IDENTIFIER_NOT_USED(Address);
+    IDENTIFIER_NOT_USED(UpperAddress);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_RC_Record_Update
+ */
+void
+EIP207_RC_Record_Update(
+        const Device_Handle_t Device,
+        const uint32_t CacheBase,
+        const unsigned int CacheNr,
+        const uint32_t Rec_DMA_Addr,
+        const uint8_t Command,
+        const unsigned int ByteOffset,
+        const uint32_t Value32)
+{
+    // Not implemented
+    IDENTIFIER_NOT_USED(Command);
+    IDENTIFIER_NOT_USED(Device);
+    IDENTIFIER_NOT_USED(CacheBase);
+    IDENTIFIER_NOT_USED(Device);
+    IDENTIFIER_NOT_USED(CacheNr);
+    IDENTIFIER_NOT_USED(Rec_DMA_Addr);
+    IDENTIFIER_NOT_USED(ByteOffset);
+    IDENTIFIER_NOT_USED(Value32);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_RC_Record_Dummy_Addr_Get
+ */
+unsigned int
+EIP207_RC_Record_Dummy_Addr_Get(void)
+{
+    return EIP207_RC_RECORD_DUMMY_ADDRESS;
+}
+
+
+/* end of file eip207_rc.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_rc_internal.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_rc_internal.c
new file mode 100644
index 0000000..4ca5d25
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_rc_internal.c
@@ -0,0 +1,808 @@
+/* eip207_rc_internal.c
+ *
+ * EIP-207 Record Cache (RC) interface implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip207_global.h"
+
+// EIP-207 Record Cache (RC) internal interface
+#include "eip207_rc_internal.h"
+
+// EIP97_Interfaces_Get()
+#include "eip97_global_internal.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                 // uint32_t, bool
+
+// EIP-207 Global Control Driver Library Internal interfaces
+#include "eip207_level0.h"              // EIP-207 Level 0 macros
+
+// EIP-206 Global Control Driver Library Internal interfaces
+#include "eip206_level0.h"              // EIP-206 Level 0 macros
+
+// Driver Framework Device API
+#include "device_types.h"               // Device_Handle_t
+
+// EIP-207 Firmware Classification API
+#include "firmware_eip207_api_cs.h"     // Classification API: General
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+#if FIRMWARE_EIP207_CS_ARC4RC_RECORD_WORD_COUNT <= \
+                FIRMWARE_EIP207_CS_TRC_RECORD_WORD_COUNT
+#define EIP207_RC_ARC4_SIZE                             0
+#elif FIRMWARE_EIP207_CS_ARC4RC_RECORD_WORD_COUNT <= \
+                FIRMWARE_EIP207_CS_TRC_RECORD_WORD_COUNT_LARGE
+#define EIP207_RC_ARC4_SIZE                             1
+#else
+#error "Error: ARC4 State Record size too big"
+#endif
+
+// Minimum number of entries in the Record Cache
+#define EIP207_RC_MIN_ENTRY_COUNT                       32
+
+// Maximum number of entries in the Record Cache
+#define EIP207_RC_MAX_ENTRY_COUNT                       4096
+
+// Maximum number of records in cachs
+#define EIP207_RC_MAX_RECORD_COUNT                      1023
+
+// Number of header words (32-bits) in a cache record
+#define EIP207_RC_HEADER_WORD_COUNT                     4
+
+// Number of 32-bit words in one administration memory word
+#define EIP207_RC_ADMIN_MEMWORD_WORD_COUNT              4
+
+// Number of hash table entries in one administration memory word
+#define EIP207_RC_ADMIN_MEMWORD_ENTRY_COUNT             8
+
+// Null value used in Record Caches
+#define EIP207_RC_NULL_VALUE                            0x3FF
+
+// Checks for the required configuration parameters
+#ifndef EIP207_FRC_ADMIN_RAM_WORD_COUNT
+#error "EIP207_FRC_ADMIN_RAM_WORD_COUNT not defined"
+#endif // EIP207_FRC_ADMIN_RAM_WORD_COUNT
+
+#ifndef EIP207_TRC_ADMIN_RAM_WORD_COUNT
+#error "EIP207_TRC_ADMIN_RAM_WORD_COUNT not defined"
+#endif // EIP207_TRC_ADMIN_RAM_WORD_COUNT
+
+#ifndef EIP207_ARC4RC_ADMIN_RAM_WORD_COUNT
+#error "EIP207_ARC4RC_ADMIN_RAM_WORD_COUNT not defined"
+#endif // EIP207_ARC4RC_ADMIN_RAM_WORD_COUNT
+
+// Minimum required Record Cache Admin RAM size
+#define EIP207_RC_MIN_ADMIN_RAM_WORD_COUNT \
+      (((EIP207_RC_MIN_ENTRY_COUNT / EIP207_RC_ADMIN_MEMWORD_ENTRY_COUNT) * \
+          EIP207_RC_ADMIN_MEMWORD_WORD_COUNT) + \
+             EIP207_RC_HEADER_WORD_COUNT * EIP207_RC_MIN_ENTRY_COUNT)
+
+// Check if the configured FRC Admin RAM size is large enough to contain
+// the minimum required number of record headers with their hash table
+#if EIP207_FRC_ADMIN_RAM_WORD_COUNT > 0 && \
+    EIP207_FRC_ADMIN_RAM_WORD_COUNT < EIP207_RC_MIN_ADMIN_RAM_WORD_COUNT
+#error "Configured FRC Admin RAM size is too small"
+#endif
+
+// Check if the configured TRC Admin RAM size is large enough to contain
+// the minimum required number of record headers with their hash table
+#if EIP207_TRC_ADMIN_RAM_WORD_COUNT > 0 && \
+    EIP207_TRC_ADMIN_RAM_WORD_COUNT < EIP207_RC_MIN_ADMIN_RAM_WORD_COUNT
+#error "Configured TRC Admin RAM size is too small"
+#endif
+
+// Check if the (optional) configured ARC4RC Admin RAM size is large enough
+// to contain the minimum required number of record headers
+// with their hash table
+#if EIP207_ARC4RC_ADMIN_RAM_WORD_COUNT > 0 && \
+    EIP207_ARC4RC_ADMIN_RAM_WORD_COUNT < EIP207_RC_MIN_ADMIN_RAM_WORD_COUNT
+#error "Configured ARC4RC Admin RAM size is too small"
+#endif
+
+// Hash Table Size calculation for *RC_p_PARAMS registers
+// Hash Table entry count =
+//      2 ^ (Hash Table Size + EIP207_RC_HASH_TABLE_SIZE_POWER_FACTOR)
+#define EIP207_RC_HASH_TABLE_SIZE_POWER_FACTOR      5
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_RC_Internal_LowerPowerOfTwo
+ *
+ * Rounds down a value to the lower or equal power of two value.
+ */
+static unsigned int
+EIP207Lib_RC_Internal_LowerPowerOfTwo(const unsigned int Value,
+                                      unsigned int * const Power)
+{
+    unsigned int v = Value;
+    unsigned int i = 0;
+
+    if (v == 0)
+        return v;
+
+    while (v)
+    {
+        v = v >> 1;
+        i++;
+    }
+
+    v = 1 << (i - 1);
+
+    *Power = i - 1;
+
+    return v;
+}
+
+
+#define EIP207_RC_DATA_WORDCOUNT_MAX 131072
+#define EIP207_RC_DATA_WORDCOUNT_MIN 256
+#define EIP207_RC_ADMIN_WORDCOUNT_MAX 16384
+#define EIP207_RC_ADMIN_WORDCOUNT_MIN 64
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Bank_Set
+ *
+ * Set the bank for the CS RAM to the given address.
+ *
+ * Device (input)
+ *     Device to use.
+ *
+ * BankNr (input)
+ *     Bank number from 0 to 7.
+ *
+ */
+static void
+EIP207Lib_Bank_Set(
+    const Device_Handle_t Device,
+    uint32_t BankNr)
+{
+    uint32_t OldValue = Device_Read32(Device, EIP207_CS_REG_RAM_CTRL);
+
+    uint32_t NewValue = (OldValue & 0xffff8fff) | ((BankNr&0x7) << 12);
+
+    Device_Write32(Device, EIP207_CS_REG_RAM_CTRL, NewValue);
+}
+
+
+static void
+EIP207Lib_RAM_Write32(
+        const Device_Handle_t Device,
+        uint32_t Address,
+        uint32_t Value)
+{
+    Device_Write32(Device,
+                   EIP207_CS_RAM_XS_SPACE_BASE + Address,
+                   Value);
+}
+
+static uint32_t
+EIP207Lib_RAM_Read32(
+        const Device_Handle_t Device,
+        uint32_t Address)
+{
+    return Device_Read32(Device,
+                         EIP207_CS_RAM_XS_SPACE_BASE + Address);
+}
+
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_RAMSize_Probe
+ *
+ * Probe the size of the accessible RAM, do not access more memory than
+ * indicated by MaxSize.
+ *
+ * Device (input)
+ *     Device to use.
+ *
+ * MaxSize (input)
+ *     Maximum size of RAM
+ */
+static unsigned int
+EIP207Lib_RAMSize_Probe(
+    const Device_Handle_t Device,
+    const unsigned int MaxSize)
+{
+    unsigned int MaxBank, MaxPage, MaxOffs, i, RAMSize;
+
+    if (MaxSize <= 16384)
+    {
+        // All RAM is in a single bank.
+        MaxBank = 0;
+    }
+    else
+    {
+        // Probe the maximum bank number that has (distinct) RAM.
+        for (i=0; i<8; i++)
+        {
+            EIP207Lib_Bank_Set(Device, 7 - i);
+            EIP207Lib_RAM_Write32(Device, 0, 7 - i);
+            EIP207Lib_RAM_Write32(Device, 4, 0);
+            EIP207Lib_RAM_Write32(Device, 8, 0);
+            EIP207Lib_RAM_Write32(Device, 12, 0);
+        }
+        MaxBank=0;
+        for (i=0; i<7; i++)
+        {
+            EIP207Lib_Bank_Set(Device, i);
+            if (EIP207Lib_RAM_Read32(Device, 0) != i)
+            {
+                break;
+            }
+            MaxBank = i;
+        }
+    }
+
+    EIP207Lib_Bank_Set(Device, MaxBank);
+
+    for (i=0; i<0x10000; i+=0x100)
+    {
+        EIP207Lib_RAM_Write32(Device, 0xff00-i, 0xff00-i);
+        EIP207Lib_RAM_Write32(Device, 0xff00-i+4, 0);
+        EIP207Lib_RAM_Write32(Device, 0xff00-i+8, 0);
+        EIP207Lib_RAM_Write32(Device, 0xff00-i+12, 0);
+    }
+
+    MaxPage = 0;
+    for (i=0; i<0x10000; i+=0x100)
+    {
+        if (EIP207Lib_RAM_Read32(Device, i) != i)
+        {
+            break;
+        }
+        MaxPage = i;
+    }
+
+    for (i=0; i<0x100; i+= 4)
+    {
+        EIP207Lib_RAM_Write32(Device, MaxPage + 0xfc - i, MaxPage + 0xfc - i);
+    }
+
+    MaxOffs = 0;
+
+    for (i=0; i<0x100; i+=4)
+    {
+        if (EIP207Lib_RAM_Read32(Device, MaxPage + i) != MaxPage + i)
+        {
+            break;
+        }
+        MaxOffs = i;
+    }
+
+    EIP207Lib_Bank_Set(Device, 0);
+    RAMSize = ((MaxBank<<16) + MaxPage + MaxOffs + 4) >> 2;
+
+    if (RAMSize > MaxSize)
+        RAMSize = MaxSize;
+
+    return RAMSize;
+}
+
+/*----------------------------------------------------------------------------
+ * EIP207_RC_Internal_Init
+ */
+EIP207_Global_Error_t
+EIP207_RC_Internal_Init(
+        const Device_Handle_t Device,
+        const EIP207_RC_Internal_Combination_Type_t CombinationType,
+        const uint32_t CacheBase,
+        EIP207_Global_CacheParams_t * RC_Params_p,
+        const unsigned int RecordWordCount)
+{
+    unsigned int i;
+    uint16_t RC_Record2_WordCount = 0;
+    uint8_t ClocksPerTick;
+    bool fFrc = false, fTrc = false, fArc4 = false;
+    EIP207_Global_CacheParams_t * RC_p = RC_Params_p;
+    unsigned int NullVal = EIP207_RC_NULL_VALUE;
+
+    switch (CacheBase)
+    {
+        case EIP207_FRC_REG_BASE:
+            fFrc = true;
+            RC_Record2_WordCount = 0;
+            break;
+
+        case EIP207_TRC_REG_BASE:
+            fTrc = true;
+            RC_Record2_WordCount =
+                    FIRMWARE_EIP207_CS_TRC_RECORD_WORD_COUNT_LARGE;
+            break;
+
+        case EIP207_ARC4RC_REG_BASE:
+            fArc4 = true;
+            RC_Record2_WordCount =
+                    FIRMWARE_EIP207_CS_ARC4RC_RECORD_WORD_COUNT_LARGE;
+            break;
+
+        default:
+            return EIP207_GLOBAL_ARGUMENT_ERROR;
+    }
+
+    if (CombinationType != EIP207_RC_INTERNAL_NOT_COMBINED)
+    {
+        if( fFrc ) // FRC cannot be combined
+            return EIP207_GLOBAL_ARGUMENT_ERROR;
+
+        // Initialize all the configured for use Record Cache sets
+        for (i = 0; i < EIP207_GLOBAL_MAX_NOF_CACHE_SETS_TO_USE; i++)
+            EIP207_RC_PARAMS_WR(Device,
+                                CacheBase,
+                                i,     // Cache Set number
+                                false, // Disable cache RAM access
+                                false, // Block Next Command is reserved
+                                false, // Enable access cache administration RAM
+                                0,
+                                0,     // Block Time Base is reserved
+                                false, // Not used for this HW
+                                RC_Record2_WordCount); // Large record size
+
+        return EIP207_GLOBAL_NO_ERROR;
+    }
+    // Indicate if ARC4 state records are considered 'large' transform records.
+    // Only relevent inin case the TRC is used to store ARC4 state records, but
+    // without a combined cache.
+    if (fTrc)
+    {
+        unsigned int NofCEs;
+        EIP97_Interfaces_Get(&NofCEs,NULL,NULL,NULL);
+        for (i = 0; i < NofCEs; i++)
+            EIP206_ARC4_SIZE_WR(Device, i, EIP207_RC_ARC4_SIZE);
+    }
+
+    // Initialize all the configured for use Record Cache sets
+    for (i = 0; i < EIP207_GLOBAL_MAX_NOF_CACHE_SETS_TO_USE; i++)
+    {
+        unsigned int RC_RAM_WordCount = RC_p->DataWordCount;
+        uint8_t RC_HashTableSize;
+        unsigned int j, Power,
+                     RC_RecordCount,
+                     RC_Record_WordCount,
+                     RC_HashTable_EntryCount,
+                     RC_HashTable_WordCount,
+                     RC_AdminRAM_WordCount,
+                     RC_AdminRAM_EntryCount,
+                     RC_HashTable_ByteOffset;
+
+        if (RC_p->fEnable == false)
+            continue; // Cache is not enabled
+
+        // Enable Record Cache RAM access
+        EIP207_CS_RAM_CTRL_WR(
+            Device,
+            fFrc && i==0,
+            fFrc && i==1,
+            fFrc && i==2,
+            fTrc && i==0,
+            fTrc && i==1,
+            fTrc && i==2,
+            fArc4 && i==0,
+            fArc4 && i==1,
+            fArc4 && i==2,
+            false);               // No FLUEC cache RAM access
+
+        // Take Record Cache into reset
+        // Make cache data RAM accessible
+        EIP207_RC_PARAMS_WR(Device,
+                            CacheBase,
+                            i,     // Cache Set number
+                            true,  // Enable cache RAM access
+                            false,
+                            true, // Enable access cache data RAM
+                            0,
+                            0,
+                            false, // Not used here for this HW
+                            0);
+
+        if (RC_RAM_WordCount == 0 ||
+            RC_RAM_WordCount > EIP207_RC_DATA_WORDCOUNT_MAX)
+            RC_RAM_WordCount = EIP207_RC_DATA_WORDCOUNT_MAX;
+        // Check the size of the data RAM.
+        RC_RAM_WordCount = EIP207Lib_RAMSize_Probe(
+            Device,
+            RC_RAM_WordCount);
+
+        // Data RAM may be inaccessible on some hardware configurations,
+        // so RAM size probing may not work. Assume that provided word count
+        // input actually reflects RAM size.
+        if (RC_RAM_WordCount < EIP207_RC_DATA_WORDCOUNT_MIN)
+            RC_RAM_WordCount = MIN(RC_p->DataWordCount, EIP207_RC_DATA_WORDCOUNT_MAX);
+        if (RC_RAM_WordCount < EIP207_RC_DATA_WORDCOUNT_MIN)
+            return EIP207_GLOBAL_INTERNAL_ERROR;
+
+        RC_p->DataWordCount = RC_RAM_WordCount;
+
+        // Take Record Cache into reset
+        // Make cache administration RAM accessible
+        EIP207_RC_PARAMS_WR(Device,
+                            CacheBase,
+                            i,     // Cache Set number
+                            true,  // Enable cache RAM access
+                            false,
+                            false, // Enable access cache administration RAM
+                            0,
+                            0,
+                            false, // Not used here for this HW
+                            0);
+
+        // Get the configured RC Admin RAM size
+        RC_AdminRAM_WordCount = RC_p->AdminWordCount;
+        if (RC_AdminRAM_WordCount == 0 ||
+            RC_AdminRAM_WordCount > EIP207_RC_ADMIN_WORDCOUNT_MAX)
+            RC_AdminRAM_WordCount = EIP207_RC_ADMIN_WORDCOUNT_MAX;
+
+        RC_AdminRAM_WordCount = EIP207Lib_RAMSize_Probe(
+            Device,
+            RC_AdminRAM_WordCount);
+
+        RC_p->AdminWordCount = RC_AdminRAM_WordCount;
+
+        if (RC_AdminRAM_WordCount < EIP207_RC_ADMIN_WORDCOUNT_MIN)
+            return EIP207_GLOBAL_INTERNAL_ERROR;
+
+       // Check the size of the Admin RAM
+
+        // Determine the RC record size to use
+        if (RC_Record2_WordCount > RecordWordCount)
+            RC_Record_WordCount = RC_Record2_WordCount;
+        else
+            RC_Record_WordCount = RecordWordCount;
+
+        // Calculate the maximum possible record count that
+        // the Record Cache Data RAM can contain
+        RC_RecordCount = RC_RAM_WordCount / RC_Record_WordCount;
+        if (RC_RecordCount > EIP207_RC_MAX_RECORD_COUNT)
+            RC_RecordCount = EIP207_RC_MAX_RECORD_COUNT;
+
+        // RC_RecordCount is calculated using the configured RC Data RAM size.
+
+        // RC_AdminRAM_EntryCount is calculated using
+        // the configured RC Admin RAM size.
+
+        // Calculate the maximum possible record count that
+        // the RC Hash Table (in Record Cache Administration RAM) can contain
+        RC_AdminRAM_EntryCount = EIP207_RC_ADMIN_MEMWORD_ENTRY_COUNT *
+                                    RC_AdminRAM_WordCount /
+                                (EIP207_RC_ADMIN_MEMWORD_WORD_COUNT +
+                                        EIP207_RC_ADMIN_MEMWORD_ENTRY_COUNT *
+                                           EIP207_RC_HEADER_WORD_COUNT);
+
+        // Try to extend the Hash Table in the RC Admin RAM
+        if (RC_RecordCount < RC_AdminRAM_EntryCount)
+        {
+            unsigned int HTSpace_WordCount;
+
+            // Calculate the size of space available for the Hash Table
+            HTSpace_WordCount = RC_AdminRAM_WordCount -
+                                  RC_RecordCount * EIP207_RC_HEADER_WORD_COUNT;
+
+            // Calculate maximum possible Hash Table entry count
+            RC_HashTable_EntryCount = (HTSpace_WordCount /
+                                        EIP207_RC_ADMIN_MEMWORD_WORD_COUNT) *
+                                           EIP207_RC_ADMIN_MEMWORD_ENTRY_COUNT;
+        }
+        else // Extension impossible
+            RC_HashTable_EntryCount = RC_AdminRAM_EntryCount;
+
+        // Check minimum number of entries in the record cache
+        RC_HashTable_EntryCount = MAX(EIP207_RC_MIN_ENTRY_COUNT,
+                                      RC_HashTable_EntryCount);
+
+        // Check maximum number of entries in the record cache
+        RC_HashTable_EntryCount = MIN(EIP207_RC_MAX_ENTRY_COUNT,
+                                      RC_HashTable_EntryCount);
+
+        // Round down to power of two
+        Power = 0;
+        RC_HashTable_EntryCount =
+             EIP207Lib_RC_Internal_LowerPowerOfTwo(RC_HashTable_EntryCount,
+                                                   &Power);
+
+        // Hash Table Mask that determines the hash table size
+        if (Power >= EIP207_RC_HASH_TABLE_SIZE_POWER_FACTOR)
+            RC_HashTableSize =
+                    (uint8_t)(Power - EIP207_RC_HASH_TABLE_SIZE_POWER_FACTOR);
+        else
+            // Insufficient memory for Hash Table in the RC Admin RAM
+            return EIP207_GLOBAL_INTERNAL_ERROR;
+
+        // Calculate the Hash Table size in 32-bit words
+        RC_HashTable_WordCount = RC_HashTable_EntryCount /
+                                  EIP207_RC_ADMIN_MEMWORD_ENTRY_COUNT *
+                                       EIP207_RC_ADMIN_MEMWORD_WORD_COUNT;
+
+        // Recalculate the record count that fits the RC Admin RAM space
+        // without the Hash Table, restricting for the maximum records
+        // which fit the RC Data RAM
+        {
+            // Adjusted record count which fits the RC Admin RAM
+            unsigned int RC_AdminRAM_AdjustedEntryCount =
+                             (RC_AdminRAM_WordCount -
+                                RC_HashTable_WordCount) /
+                                   EIP207_RC_HEADER_WORD_COUNT;
+
+            // Maximum record count which fits the RC Data RAM - RC_RecordCount
+            // use the minimum of the two
+            RC_RecordCount = MIN(RC_RecordCount,
+                                 RC_AdminRAM_AdjustedEntryCount);
+        }
+
+        // Clear all ECC errors
+        EIP207_RC_ECCCTRL_WR(Device, CacheBase, i, false, false, false);
+
+        // Clear all record administration words
+        // in Record Cache administration RAM
+        for (j = 0; j < RC_RecordCount; j++)
+        {
+            // Calculate byte offset for the current record
+            unsigned int ByteOffset = EIP207_CS_RAM_XS_SPACE_BASE +
+                                      j *
+                                        EIP207_RC_HEADER_WORD_COUNT *
+                                          sizeof(uint32_t);
+
+            // Write word 0
+            Device_Write32(Device,
+                           ByteOffset,
+                           (NullVal << 20) | // Hash_Collision_Prev
+                           (NullVal << 10)); // Hash_Collision_Next
+
+            // Write word 1
+            ByteOffset += sizeof(uint32_t);
+
+            if (j == RC_RecordCount - 1)
+            {
+                // Last record
+                Device_Write32(Device,
+                               ByteOffset,
+                               ((j - 1) << 10) |   // Free_List_Prev
+                               NullVal);           // Free_List_Next
+            }
+            else if (j == 0)
+            {
+                // First record
+                Device_Write32(Device,
+                               ByteOffset,
+                               (NullVal << 10) | // Free_List_Prev
+                               (j + 1));         // Free_List_Next
+            }
+            else
+            {
+                // All other records
+                Device_Write32(Device,
+                               ByteOffset,
+                               ((j - 1) << 10) | // Free_List_Prev
+                               (j + 1));         // Free_List_Next
+            }
+
+            // Write word 2
+            ByteOffset += sizeof(uint32_t);
+
+            Device_Write32(Device,
+                           ByteOffset,
+                           0); // Address_Key, low bits
+
+            // Write word 3
+            ByteOffset += sizeof(uint32_t);
+
+            Device_Write32(Device,
+                           ByteOffset,
+                           0); // Address_Key, high bits
+        } // for (records)
+
+        // Calculate byte offset for the Hash Table
+        RC_HashTable_ByteOffset = EIP207_CS_RAM_XS_SPACE_BASE +
+                            RC_RecordCount *
+                                EIP207_RC_HEADER_WORD_COUNT *
+                                    sizeof(uint32_t);
+
+        // Clear all hash table words
+        for (j = 0; j < RC_HashTable_WordCount; j++)
+            Device_Write32(Device,
+                           RC_HashTable_ByteOffset + j * sizeof(uint32_t),
+                           0x3FFFFFFF);
+
+        // Disable Record Cache RAM access
+        EIP207_CS_RAM_CTRL_DEFAULT_WR(Device);
+
+        // Write head and tail pointers to the RC Free Chain
+        EIP207_RC_FREECHAIN_WR(
+                  Device,
+                  CacheBase,
+                  i,                               // Cache Set number
+                  0,                               // head pointer
+                  (uint16_t)(RC_RecordCount - 1)); // tail pointer
+
+        // Set Hash Table start
+        // This is an offset from EIP207_CS_RAM_XS_SPACE_BASE
+        // in record administration memory words
+        EIP207_RC_PARAMS2_WR(Device,
+                             CacheBase,
+                             i,
+                             (uint16_t)RC_RecordCount,
+    /* Small Record size */  fArc4 ? 0 : (uint16_t)RecordWordCount,
+                             FIRMWARE_EIP207_RC_DMA_WR_COMB_DLY);
+
+        // Select the highest clock count as specified by
+        // the Host and the Firmware for the FRC
+#ifdef FIRMWARE_EIP207_CS_BLOCK_NEXT_COMMAND_LOGIC_DISABLE
+        ClocksPerTick = RC_p->BlockClockCount;
+#else
+        {
+            uint8_t tmp;
+
+            tmp = (uint8_t)FIRMWARE_EIP207_CS_FRC_BLOCK_TIMEBASE;
+            ClocksPerTick = RC_p->BlockClockCount >= tmp ?
+                                       CacheConf_p->FRC.BlockClockCount : tmp;
+        }
+#endif
+
+        // Take Record Cache out of reset
+        EIP207_RC_PARAMS_WR(Device,
+                            CacheBase,
+                            i,     // Cache Set number
+                            false, // Disable cache RAM access
+                            RC_p->fNonBlock,
+                            false, // Disable access cache administration RAM
+                            RC_HashTableSize,
+                            ClocksPerTick,
+                            false, // Not used here for this HW
+                            RC_Record2_WordCount); // Large record size
+
+        RC_p++;
+    } // for, i cache sets
+
+    return EIP207_GLOBAL_NO_ERROR;
+}
+
+static void
+EIP207_RC_Internal_DebugStatistics_Single_Get(
+        const Device_Handle_t Device,
+        const unsigned int CacheSetId,
+        uint32_t RegBase,
+        EIP207_Global_CacheDebugStatistics_t * const Stats_p)
+{
+    EIP207_RC_LONGCTR_RD(Device, EIP207_RC_REG_PREFEXEC(RegBase, CacheSetId),
+                         &Stats_p->PrefetchExec);
+    EIP207_RC_LONGCTR_RD(Device, EIP207_RC_REG_PREFBLCK(RegBase, CacheSetId),
+                         &Stats_p->PrefetchBlock);
+    EIP207_RC_LONGCTR_RD(Device, EIP207_RC_REG_PREFDMA(RegBase, CacheSetId),
+                         &Stats_p->PrefetchDMA);
+    EIP207_RC_LONGCTR_RD(Device, EIP207_RC_REG_SELOPS(RegBase, CacheSetId),
+                         &Stats_p->SelectOps);
+    EIP207_RC_LONGCTR_RD(Device, EIP207_RC_REG_SELDMA(RegBase, CacheSetId),
+                         &Stats_p->SelectDMA);
+    EIP207_RC_LONGCTR_RD(Device, EIP207_RC_REG_IDMAWR(RegBase, CacheSetId),
+                         &Stats_p->IntDMAWrite);
+    EIP207_RC_LONGCTR_RD(Device, EIP207_RC_REG_XDMAWR(RegBase, CacheSetId),
+                         &Stats_p->ExtDMAWrite);
+    EIP207_RC_LONGCTR_RD(Device, EIP207_RC_REG_INVCMD(RegBase, CacheSetId),
+                         &Stats_p->InvalidateOps);
+    EIP207_RC_RDMAERRFLGS_RD(Device, RegBase, CacheSetId,
+                             &Stats_p->ReadDMAErrFlags);
+    EIP207_RC_SHORTCTR_RD(Device, EIP207_RC_REG_RDMAERR(RegBase, CacheSetId),
+                          &Stats_p->ReadDMAErrors);
+    EIP207_RC_SHORTCTR_RD(Device, EIP207_RC_REG_WDMAERR(RegBase, CacheSetId),
+                          &Stats_p->WriteDMAErrors);
+    EIP207_RC_SHORTCTR_RD(Device, EIP207_RC_REG_INVECC(RegBase, CacheSetId),
+                          &Stats_p->InvalidateECC);
+    EIP207_RC_SHORTCTR_RD(Device, EIP207_RC_REG_DATECC_CORR(RegBase, CacheSetId),
+                          &Stats_p->DataECCCorr);
+    EIP207_RC_SHORTCTR_RD(Device, EIP207_RC_REG_ADMECC_CORR(RegBase, CacheSetId),
+                          &Stats_p->AdminECCCorr);
+
+}
+
+
+void
+EIP207_RC_Internal_DebugStatistics_Get(
+        const Device_Handle_t Device,
+        const unsigned int CacheSetId,
+        EIP207_Global_CacheDebugStatistics_t * const FRC_Stats_p,
+        EIP207_Global_CacheDebugStatistics_t * const TRC_Stats_p)
+{
+    EIP207_RC_Internal_DebugStatistics_Single_Get(
+        Device,
+        CacheSetId,
+        EIP207_FRC_REG_BASE,
+        FRC_Stats_p);
+    EIP207_RC_Internal_DebugStatistics_Single_Get(
+        Device,
+        CacheSetId,
+        EIP207_TRC_REG_BASE,
+        TRC_Stats_p);
+}
+
+/*----------------------------------------------------------------------------
+ * EIP207_RC_Internal_Status_Get
+ */
+void
+EIP207_RC_Internal_Status_Get(
+        const Device_Handle_t Device,
+        const unsigned int CacheSetId,
+        EIP207_Global_CacheStatus_t * const FRC_Status_p,
+        EIP207_Global_CacheStatus_t * const TRC_Status_p,
+        EIP207_Global_CacheStatus_t * const ARC4RC_Status_p)
+{
+    // Read FRC status
+    EIP207_RC_PARAMS_RD(Device,
+                        EIP207_FRC_REG_BASE,
+                        CacheSetId,
+                        &FRC_Status_p->fDMAReadError,
+                        &FRC_Status_p->fDMAWriteError);
+
+    EIP207_RC_ECCCTRL_RD_CLEAR(Device,
+                               EIP207_FRC_REG_BASE,
+                               CacheSetId,
+                               &FRC_Status_p->fDataEccOflo,
+                               &FRC_Status_p->fDataEccErr,
+                               &FRC_Status_p->fAdminEccErr);
+
+    // Read TRC status
+    EIP207_RC_PARAMS_RD(Device,
+                        EIP207_TRC_REG_BASE,
+                        CacheSetId,
+                        &TRC_Status_p->fDMAReadError,
+                        &TRC_Status_p->fDMAWriteError);
+
+    EIP207_RC_ECCCTRL_RD_CLEAR(Device,
+                               EIP207_TRC_REG_BASE,
+                               CacheSetId,
+                               &TRC_Status_p->fDataEccOflo,
+                               &TRC_Status_p->fDataEccErr,
+                               &TRC_Status_p->fAdminEccErr);
+
+    // Read ARC4RC status
+    EIP207_RC_PARAMS_RD(Device,
+                        EIP207_ARC4RC_REG_BASE,
+                        CacheSetId,
+                        &ARC4RC_Status_p->fDMAReadError,
+                        &ARC4RC_Status_p->fDMAWriteError);
+
+    EIP207_RC_ECCCTRL_RD_CLEAR(Device,
+                               EIP207_ARC4RC_REG_BASE,
+                               CacheSetId,
+                               &ARC4RC_Status_p->fDataEccOflo,
+                               &ARC4RC_Status_p->fDataEccErr,
+                               &ARC4RC_Status_p->fAdminEccErr);
+}
+
+
+/* end of file eip207_rc_internal.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_support.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_support.c
new file mode 100644
index 0000000..b5982c6
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_support.c
@@ -0,0 +1,86 @@
+/* eip207_support.c
+ *
+ * EIP-207 Support interface implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// EIP-207 Support interface
+#include "eip207_support.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip207_global.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                 // uint32_t, bool
+
+// Driver Framework Device API
+#include "device_types.h"               // Device_Handle_t
+#include "device_rw.h"                  // Read32, Write32
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Global_Read64
+ */
+EIP207_Global_Error_t
+EIP207_Global_Read64(
+        const Device_Handle_t Device,
+        const unsigned int Value64_OffsetLo,
+        const unsigned int Value64_OffsetHi,
+        EIP207_Global_Value64_t * const Value64_p)
+{
+    uint32_t Value32;
+    unsigned int i;
+
+    for (i = 0; i < EIP207_VALUE_64BIT_MAX_NOF_READ_ATTEMPTS; i++)
+    {
+        Value32 = Device_Read32(Device, Value64_OffsetHi);
+
+        Value64_p->Value64_Lo = Device_Read32(Device, Value64_OffsetLo);
+        Value64_p->Value64_Hi = Device_Read32(Device, Value64_OffsetHi);
+
+        if (Value32 == Value64_p->Value64_Hi)
+            return EIP207_GLOBAL_NO_ERROR;
+    }
+
+    return EIP207_GLOBAL_INTERNAL_ERROR;
+}
+
+
+/* end of file eip207_support.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip74.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip74.c
new file mode 100644
index 0000000..a9ef9ff
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip74.c
@@ -0,0 +1,388 @@
+/* eip74.c
+ *
+ * Implementation of the EIP-74 Driver Library.
+ */
+
+/*****************************************************************************
+* Copyright (c) 2017-2020 by Rambus, Inc. and/or its subsidiaries.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// EIP76 initialization API
+#include "eip74.h"
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip74.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"         // uint32_t
+
+// Driver Framework Device API
+#include "device_types.h"       // Device_Handle_t
+
+// EIP-76 Driver Library Internal interfaces
+#include "eip74_level0.h"       // Level 0 macros
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+// I/O Area, used internally
+typedef struct
+{
+    Device_Handle_t Device;
+} EIP74_True_IOArea_t;
+
+#define TEST_SIZEOF(type, size) \
+    extern int size##_must_bigger[1 - 2*((int)(sizeof(type) > size))]
+
+
+#ifdef EIP74_STRICT_ARGS
+#define EIP74_CHECK_POINTER(_p) \
+    if (NULL == (_p)) \
+        return EIP74_ARGUMENT_ERROR;
+#define EIP74_CHECK_INT_INRANGE(_i, _min, _max) \
+    if ((_i) < (_min) || (_i) > (_max)) \
+        return EIP74_ARGUMENT_ERROR;
+#define EIP74_CHECK_INT_ATLEAST(_i, _min) \
+    if ((_i) < (_min)) \
+        return EIP74_ARGUMENT_ERROR;
+#define EIP74_CHECK_INT_ATMOST(_i, _max) \
+    if ((_i) > (_max)) \
+        return EIP74_ARGUMENT_ERROR;
+#else
+/* EIP74_STRICT_ARGS undefined */
+#define EIP74_CHECK_POINTER(_p)
+#define EIP74_CHECK_INT_INRANGE(_i, _min, _max)
+#define EIP74_CHECK_INT_ATLEAST(_i, _min)
+#define EIP74_CHECK_INT_ATMOST(_i, _max)
+#endif /*end of EIP74_STRICT_ARGS */
+
+
+// validate the size of the fake and real IOArea structures
+TEST_SIZEOF(EIP74_True_IOArea_t, EIP74_IOAREA_REQUIRED_SIZE);
+
+
+/*----------------------------------------------------------------------------
+ * EIP74Lib_Detect
+ *
+ * Checks the presence of EIP-74 device. Returns true when found.
+ */
+static bool
+EIP74Lib_Detect(
+        const Device_Handle_t Device)
+{
+    uint32_t Value;
+
+    Value = EIP74_Read32(Device, EIP74_REG_VERSION);
+    if (!EIP74_REV_SIGNATURE_MATCH( Value ))
+        return false;
+
+    return true;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP74Lib_Reset_IsDone
+ */
+static bool
+EIP74Lib_Reset_IsDone(
+        const Device_Handle_t Device)
+{
+    bool fReady, fPSAIWriteOK, fStuckOut, fEarlyReseed;
+    bool fTestReady,fGenPktError, fInstantiated, fTestStuckOut, fNeedClock;
+    uint8_t BlocksAvailable;
+
+    EIP74_STATUS_RD(Device,
+                    &fReady,
+                    &fPSAIWriteOK,
+                    &fStuckOut,
+                    &fEarlyReseed,
+                    &fTestReady,
+                    &fGenPktError,
+                    &fInstantiated,
+                    &fTestStuckOut,
+                    &BlocksAvailable,
+                    &fNeedClock);
+
+    return fPSAIWriteOK;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP74_Init
+ */
+EIP74_Error_t
+EIP74_Init(
+        EIP74_IOArea_t * const IOArea_p,
+        const Device_Handle_t Device)
+{
+    volatile EIP74_True_IOArea_t * const TrueIOArea_p =
+        (EIP74_True_IOArea_t *)IOArea_p;
+    EIP74_CHECK_POINTER(IOArea_p);
+
+    TrueIOArea_p->Device = Device;
+
+    if (!EIP74Lib_Detect(Device))
+    {
+        return EIP74_UNSUPPORTED_FEATURE_ERROR;
+    }
+
+    return EIP74_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP74_Reset
+ */
+EIP74_Error_t
+EIP74_Reset(
+        EIP74_IOArea_t * const IOArea_p)
+{
+    Device_Handle_t Device;
+    volatile EIP74_True_IOArea_t * const TrueIOArea_p =
+        (EIP74_True_IOArea_t *)IOArea_p;
+    EIP74_CHECK_POINTER(IOArea_p);
+
+    Device = TrueIOArea_p->Device;
+
+    EIP74_CONTROL_WR(Device,
+                     false, /* fReadyMask */
+                     false, /* fStuckOut */
+                     false, /* fTestMode */
+                     false, /* fHostMode */
+                     false, /* fEnableDRBG */
+                     false, /* fForceStuckOut */
+                     false, /* fRequestdata */
+                     0); /* DataBlocks */
+
+    if (EIP74Lib_Reset_IsDone(Device))
+    {
+        return EIP74_NO_ERROR;
+    }
+    else
+    {
+        return EIP74_BUSY_RETRY_LATER;
+    }
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP74_Reset_IsDone
+ */
+EIP74_Error_t
+EIP74_Reset_IsDone(
+        EIP74_IOArea_t * const IOArea_p)
+{
+    Device_Handle_t Device;
+    volatile EIP74_True_IOArea_t * const TrueIOArea_p =
+        (EIP74_True_IOArea_t *)IOArea_p;
+    EIP74_CHECK_POINTER(IOArea_p);
+
+    Device = TrueIOArea_p->Device;
+
+    if (EIP74Lib_Reset_IsDone(Device))
+    {
+        return EIP74_NO_ERROR;
+    }
+    else
+    {
+        return EIP74_BUSY_RETRY_LATER;
+    }
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP74_HWRevision_Get
+  */
+EIP74_Error_t
+EIP74_HWRevision_Get(
+        const Device_Handle_t Device,
+        EIP74_Capabilities_t * const Capabilities_p)
+{
+    EIP74_CHECK_POINTER(Capabilities_p);
+
+    EIP74_VERSION_RD(Device,
+                     &Capabilities_p->HW_Revision.EipNumber,
+                     &Capabilities_p->HW_Revision.ComplmtEipNumber,
+                     &Capabilities_p->HW_Revision.HWPatchLevel,
+                     &Capabilities_p->HW_Revision.MinHWRevision,
+                     &Capabilities_p->HW_Revision.MajHWRevision);
+    EIP74_OPTIONS_RD(Device,
+                     &Capabilities_p->HW_Options.ClientCount,
+                     &Capabilities_p->HW_Options.AESCoreCount,
+                     &Capabilities_p->HW_Options.AESSpeed,
+                     &Capabilities_p->HW_Options.FIFODepth);
+
+    return EIP74_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP74_Configure
+ */
+EIP74_Error_t
+EIP74_Configure(
+        EIP74_IOArea_t * const IOArea_p,
+        const EIP74_Configuration_t * const Configuration_p)
+{
+    Device_Handle_t Device;
+    volatile EIP74_True_IOArea_t * const TrueIOArea_p =
+        (EIP74_True_IOArea_t *)IOArea_p;
+    EIP74_CHECK_POINTER(IOArea_p);
+    EIP74_CHECK_POINTER(Configuration_p);
+    EIP74_CHECK_INT_INRANGE(Configuration_p->GenerateBlockSize, 1, 4095);
+
+    Device = TrueIOArea_p->Device;
+
+    EIP74_GEN_BLK_SIZE_WR(Device, Configuration_p->GenerateBlockSize);
+    EIP74_RESEED_THR_WR(Device, Configuration_p->ReseedThr);
+    EIP74_RESEED_THR_EARLY_WR(Device, Configuration_p->ReseedThrEarly);
+
+    return EIP74_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP74_Instantiate
+ */
+EIP74_Error_t
+EIP74_Instantiate(
+        EIP74_IOArea_t * const IOArea_p,
+        const uint32_t * const Entropy_p,
+        bool fStuckOut)
+{
+    Device_Handle_t Device;
+    volatile EIP74_True_IOArea_t * const TrueIOArea_p =
+        (EIP74_True_IOArea_t *)IOArea_p;
+    EIP74_CHECK_POINTER(IOArea_p);
+    EIP74_CHECK_POINTER(Entropy_p);
+
+    Device = TrueIOArea_p->Device;
+
+    EIP74_PS_AI_WR(Device, Entropy_p, 12);
+
+    EIP74_CONTROL_WR(Device,
+                     false, /* fReadyMask */
+                     fStuckOut,
+                     false, /* fTestMode */
+                     false, /* fHostMode */
+                     true, /* fEnableDRBG */
+                     false, /* fForceStuckOut */
+                     false, /* fRequestdata */
+                     0); /* DataBlocks */
+
+    return EIP74_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP74_Reseed
+ */
+EIP74_Error_t
+EIP74_Reseed(
+        EIP74_IOArea_t * const IOArea_p,
+        const uint32_t * const Entropy_p)
+{
+    Device_Handle_t Device;
+    volatile EIP74_True_IOArea_t * const TrueIOArea_p =
+        (EIP74_True_IOArea_t *)IOArea_p;
+    EIP74_CHECK_POINTER(IOArea_p);
+    EIP74_CHECK_POINTER(Entropy_p);
+
+    Device = TrueIOArea_p->Device;
+
+    EIP74_PS_AI_WR(Device, Entropy_p, 12);
+
+    return EIP74_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP74_Status_Get
+ */
+EIP74_Error_t
+EIP74_Status_Get(
+        EIP74_IOArea_t * const IOArea_p,
+        EIP74_Status_t * const Status_p)
+{
+    Device_Handle_t Device;
+    volatile EIP74_True_IOArea_t * const TrueIOArea_p =
+        (EIP74_True_IOArea_t *)IOArea_p;
+    bool fReady, fPSAIWriteOK, fStuckOut, fEarlyReseed;
+    bool fTestReady,fGenPktError, fInstantiated, fTestStuckOut, fNeedClock;
+    uint8_t BlocksAvailable;
+    uint32_t GenBlockCount, ReseedThr;
+    EIP74_CHECK_POINTER(IOArea_p);
+    EIP74_CHECK_POINTER(Status_p);
+
+    Device = TrueIOArea_p->Device;
+
+    EIP74_STATUS_RD(Device,
+                    &fReady,
+                    &fPSAIWriteOK,
+                    &fStuckOut,
+                    &fEarlyReseed,
+                    &fTestReady,
+                    &fGenPktError,
+                    &fInstantiated,
+                    &fTestStuckOut,
+                    &BlocksAvailable,
+                    &fNeedClock);
+
+    EIP74_GENERATE_CNT_RD(Device, &GenBlockCount);
+    EIP74_RESEED_THR_RD(Device, &ReseedThr);
+
+    Status_p->GenerateBlockCount = GenBlockCount;
+    Status_p->fStuckOut = fStuckOut;
+    Status_p->fNotInitialized = fGenPktError;
+    Status_p->fReseedError = GenBlockCount == ReseedThr;
+    Status_p->fReseedWarning = fEarlyReseed;
+    Status_p->fInstantiated = fInstantiated;
+    Status_p->AvailableCount = BlocksAvailable;
+
+    return EIP74_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP74_Clear
+ */
+EIP74_Error_t
+EIP74_Clear(
+        EIP74_IOArea_t * const IOArea_p)
+{
+    Device_Handle_t Device;
+    volatile EIP74_True_IOArea_t * const TrueIOArea_p =
+        (EIP74_True_IOArea_t *)IOArea_p;
+    EIP74_CHECK_POINTER(IOArea_p);
+
+    Device = TrueIOArea_p->Device;
+
+    EIP74_INTACK_WR(Device, false, true, false);
+
+    return EIP74_NO_ERROR;
+}
+
+
+/* end of file eip74.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_event.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_event.c
new file mode 100644
index 0000000..cf47963
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_event.c
@@ -0,0 +1,409 @@
+/* eip97_global_event.c
+ *
+ * EIP-97 Global Control Driver Library
+ * Event Management Module
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip97_global_event.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip97_global.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                // uint32_t
+
+// Driver Framework Device API
+#include "device_types.h"              // Device_Handle_t
+
+// EIP-97 Global Control Driver Library Internal interfaces
+#include "eip97_global_internal.h"
+#include "eip202_global_level0.h"      // EIP-202 Level 0 macros
+#include "eip96_level0.h"              // EIP-96 Level 0 macros
+#include "eip97_global_fsm.h"          // State machine
+#include "eip97_global_level0.h"
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+#ifdef EIP97_REG_DBG_BASE
+/*----------------------------------------------------------------------------
+ * EIP97_Global_Debug_Statistics_Get
+ */
+EIP97_Global_Error_t
+EIP97_Global_Debug_Statistics_Get(
+        EIP97_Global_IOArea_t * const IOArea_p,
+        EIP97_Global_Debug_Statistics_t * const Debug_Statistics_p)
+{
+    Device_Handle_t Device;
+    unsigned int i;
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP97_GLOBAL_CHECK_POINTER(Debug_Statistics_p);
+
+    Device = TrueIOArea_p->Device;
+
+    for (i = 0; i < 16; i++)
+    {
+        EIP97_DBG_RING_IN_COUNT_RD(Device,
+                                   i,
+                                   &Debug_Statistics_p->Ifc_Packets_In[i]);
+        EIP97_DBG_RING_OUT_COUNT_RD(Device,
+                                    i,
+                                    &Debug_Statistics_p->Ifc_Packets_Out[i]);
+
+    }
+    for (i = 0; i < EIP97_GLOBAL_MAX_NOF_PE_TO_USE; i++)
+    {
+        EIP97_DBG_PIPE_COUNT_RD(Device,
+                                i,
+                                &Debug_Statistics_p->Pipe_Total_Packets[i],
+                                &Debug_Statistics_p->Pipe_Current_Packets[i],
+                                &Debug_Statistics_p->Pipe_Max_Packets[i]);
+        EIP97_DBG_PIPE_DCOUNT_RD(Device,
+                                 i,
+                                 &Debug_Statistics_p->Pipe_Data_Count[i]);
+    }
+    for (i = EIP97_GLOBAL_MAX_NOF_PE_TO_USE; i < 16; i++)
+    {
+        Debug_Statistics_p->Pipe_Total_Packets[i] = 0;
+        Debug_Statistics_p->Pipe_Current_Packets[i] = 0;
+        Debug_Statistics_p->Pipe_Max_Packets[i] = 0;
+        Debug_Statistics_p->Pipe_Data_Count[i] = 0;
+    }
+    return 0;
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_DFE_Status_Get
+ */
+EIP97_Global_Error_t
+EIP97_Global_DFE_Status_Get(
+        EIP97_Global_IOArea_t * const IOArea_p,
+        const unsigned int PE_Number,
+        EIP97_Global_DFE_Status_t * const DFE_Status_p)
+{
+    Device_Handle_t Device;
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+    unsigned int DFEDSEOffset;
+    DFEDSEOffset = EIP97_DFEDSE_Offset_Get();
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP97_GLOBAL_CHECK_POINTER(DFE_Status_p);
+
+    if(PE_Number >= EIP97_GLOBAL_MAX_NOF_PE_TO_USE)
+        return EIP97_GLOBAL_ARGUMENT_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+    EIP202_DFE_TRD_STAT_RD(Device,
+                           DFEDSEOffset,
+                           PE_Number,
+                           &DFE_Status_p->CDFifoWord32Count,
+                           &DFE_Status_p->CDR_ID,
+                           &DFE_Status_p->DMASize,
+                           &DFE_Status_p->fAtDMABusy,
+                           &DFE_Status_p->fDataDMABusy,
+                           &DFE_Status_p->fDMAError);
+
+#ifdef EIP97_GLOBAL_DEBUG_FSM
+    {
+        EIP97_Global_Error_t rv;
+
+        if(DFE_Status_p->fDMAError)
+            rv = EIP97_Global_State_Set(
+                    (volatile EIP97_Global_State_t*)&TrueIOArea_p->State,
+                    EIP97_GLOBAL_STATE_FATAL_ERROR);
+        else
+            // Remain in the current state
+            rv = EIP97_Global_State_Set(
+                    (volatile EIP97_Global_State_t*)&TrueIOArea_p->State,
+                    (EIP97_Global_State_t)TrueIOArea_p->State);
+        if(rv != EIP97_GLOBAL_NO_ERROR)
+            return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+    }
+#endif // EIP97_GLOBAL_DEBUG_FSM
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_DSE_Status_Get
+ */
+EIP97_Global_Error_t
+EIP97_Global_DSE_Status_Get(
+        EIP97_Global_IOArea_t * const IOArea_p,
+        const unsigned int PE_Number,
+        EIP97_Global_DSE_Status_t * const DSE_Status_p)
+{
+    Device_Handle_t Device;
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+    unsigned int DFEDSEOffset;
+    DFEDSEOffset = EIP97_DFEDSE_Offset_Get();
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP97_GLOBAL_CHECK_POINTER(DSE_Status_p);
+
+    if(PE_Number >= EIP97_GLOBAL_MAX_NOF_PE_TO_USE)
+        return EIP97_GLOBAL_ARGUMENT_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+    EIP202_DSE_TRD_STAT_RD(Device,
+                           DFEDSEOffset,
+                           PE_Number,
+                           &DSE_Status_p->RDFifoWord32Count,
+                           &DSE_Status_p->RDR_ID,
+                           &DSE_Status_p->DMASize,
+                           &DSE_Status_p->fDataFlushBusy,
+                           &DSE_Status_p->fDataDMABusy,
+                           &DSE_Status_p->fDMAError);
+
+#ifdef EIP97_GLOBAL_DEBUG_FSM
+    {
+        EIP97_Global_Error_t rv;
+
+        if(DSE_Status_p->fDMAError)
+            rv = EIP97_Global_State_Set(
+                    (volatile EIP97_Global_State_t*)&TrueIOArea_p->State,
+                    EIP97_GLOBAL_STATE_FATAL_ERROR);
+        else
+            // Remain in the current state
+            rv = EIP97_Global_State_Set(
+                    (volatile EIP97_Global_State_t*)&TrueIOArea_p->State,
+                    (EIP97_Global_State_t)TrueIOArea_p->State);
+        if(rv != EIP97_GLOBAL_NO_ERROR)
+            return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+    }
+#endif // EIP97_GLOBAL_DEBUG_FSM
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_EIP96_Token_Status_Get
+ */
+EIP97_Global_Error_t
+EIP97_Global_EIP96_Token_Status_Get(
+        EIP97_Global_IOArea_t * const IOArea_p,
+        const unsigned int PE_Number,
+        EIP96_Token_Status_t * const Token_Status_p)
+{
+    Device_Handle_t Device;
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP97_GLOBAL_CHECK_POINTER(Token_Status_p);
+
+    if(PE_Number >= EIP97_GLOBAL_MAX_NOF_PE_TO_USE)
+        return EIP97_GLOBAL_UNSUPPORTED_FEATURE_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+#ifdef EIP97_GLOBAL_DEBUG_FSM
+    {
+        EIP97_Global_Error_t rv;
+
+        // Remain in the current state
+        rv = EIP97_Global_State_Set(
+                (volatile EIP97_Global_State_t*)&TrueIOArea_p->State,
+                (EIP97_Global_State_t)TrueIOArea_p->State);
+        if(rv != EIP97_GLOBAL_NO_ERROR)
+            return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+    }
+#endif // EIP97_GLOBAL_DEBUG_FSM
+
+    EIP96_TOKEN_CTRL_STAT_RD(Device,
+                             PE_Number,
+                             &Token_Status_p->ActiveTokenCount,
+                             &Token_Status_p->fTokenLocationAvailable,
+                             &Token_Status_p->fResultTokenAvailable,
+                             &Token_Status_p->fTokenReadActive,
+                             &Token_Status_p->fContextCacheActive,
+                             &Token_Status_p->fContextFetch,
+                             &Token_Status_p->fResultContext,
+                             &Token_Status_p->fProcessingHeld,
+                             &Token_Status_p->fBusy);
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_EIP96_Context_Status_Get
+ */
+EIP97_Global_Error_t
+EIP97_Global_EIP96_Context_Status_Get(
+        EIP97_Global_IOArea_t * const IOArea_p,
+        const unsigned int PE_Number,
+        EIP96_Context_Status_t * const Context_Status_p)
+{
+    Device_Handle_t Device;
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP97_GLOBAL_CHECK_POINTER(Context_Status_p);
+
+    if(PE_Number >= EIP97_GLOBAL_MAX_NOF_PE_TO_USE)
+        return EIP97_GLOBAL_ARGUMENT_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+    EIP96_CONTEXT_STAT_RD(Device,
+                          PE_Number,
+                          &Context_Status_p->Error,
+                          &Context_Status_p->AvailableTokenCount,
+                          &Context_Status_p->fActiveContext,
+                          &Context_Status_p->fNextContext,
+                          &Context_Status_p->fResultContext,
+                          &Context_Status_p->fErrorRecovery);
+
+#ifdef EIP97_GLOBAL_DEBUG_FSM
+    {
+        EIP97_Global_Error_t rv;
+
+        if((Context_Status_p->Error & EIP96_TIMEOUT_FATAL_ERROR_MASK) != 0)
+            rv = EIP97_Global_State_Set(
+                    (volatile EIP97_Global_State_t*)&TrueIOArea_p->State,
+                    EIP97_GLOBAL_STATE_FATAL_ERROR);
+        else
+            // Remain in the current state
+            rv = EIP97_Global_State_Set(
+                    (volatile EIP97_Global_State_t*)&TrueIOArea_p->State,
+                    (EIP97_Global_State_t)TrueIOArea_p->State);
+        if(rv != EIP97_GLOBAL_NO_ERROR)
+            return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+    }
+#endif // EIP97_GLOBAL_DEBUG_FSM
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_EIP96_OutXfer_Status_Get
+ */
+EIP97_Global_Error_t
+EIP97_Global_EIP96_OutXfer_Status_Get(
+        EIP97_Global_IOArea_t * const IOArea_p,
+        const unsigned int PE_Number,
+        EIP96_Output_Transfer_Status_t * const OutXfer_Status_p)
+{
+    Device_Handle_t Device;
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP97_GLOBAL_CHECK_POINTER(OutXfer_Status_p);
+
+    if(PE_Number >= EIP97_GLOBAL_MAX_NOF_PE_TO_USE)
+        return EIP97_GLOBAL_ARGUMENT_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+#ifdef EIP97_GLOBAL_DEBUG_FSM
+    {
+        EIP97_Global_Error_t rv;
+
+        // Remain in the current state
+        rv = EIP97_Global_State_Set((volatile EIP97_Global_State_t*)&TrueIOArea_p->State,
+                                    (EIP97_Global_State_t)TrueIOArea_p->State);
+        if(rv != EIP97_GLOBAL_NO_ERROR)
+            return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+    }
+#endif // EIP97_GLOBAL_DEBUG_FSM
+
+    EIP96_OUT_TRANS_CTRL_STAT_RD(Device,
+                                 PE_Number,
+                                 &OutXfer_Status_p->AvailableWord32Count,
+                                 &OutXfer_Status_p->MinTransferWordCount,
+                                 &OutXfer_Status_p->MaxTransferWordCount,
+                                 &OutXfer_Status_p->TransferSizeMask);
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_EIP96_PRNG_Status_Get
+ */
+EIP97_Global_Error_t
+EIP97_Global_EIP96_PRNG_Status_Get(
+        EIP97_Global_IOArea_t * const IOArea_p,
+        const unsigned int PE_Number,
+        EIP96_PRNG_Status_t * const PRNG_Status_p)
+{
+    Device_Handle_t Device;
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP97_GLOBAL_CHECK_POINTER(PRNG_Status_p);
+
+    if(PE_Number >= EIP97_GLOBAL_MAX_NOF_PE_TO_USE)
+        return EIP97_GLOBAL_ARGUMENT_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+#ifdef EIP97_GLOBAL_DEBUG_FSM
+    {
+        EIP97_Global_Error_t rv;
+
+        // Remain in the current state
+        rv = EIP97_Global_State_Set((volatile EIP97_Global_State_t*)&TrueIOArea_p->State,
+                                    (EIP97_Global_State_t)TrueIOArea_p->State);
+        if(rv != EIP97_GLOBAL_NO_ERROR)
+            return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+    }
+#endif // EIP97_GLOBAL_DEBUG_FSM
+
+    EIP96_PRNG_STAT_RD(Device,
+                       PE_Number,
+                       &PRNG_Status_p->fBusy,
+                       &PRNG_Status_p->fResultReady);
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/* end of file eip97_global_event.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_fsm.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_fsm.c
new file mode 100644
index 0000000..e3f5ffb
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_fsm.c
@@ -0,0 +1,164 @@
+/* eip97_global_fsm.c
+ *
+ * EIP-97 Global Control Driver Library API State Machine Internal Interface
+ * implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip97_global_fsm.h"
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// EIP-97 Driver Library Types API
+#include "eip97_global_types.h"        // EIP97_Global_* types
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_State_Set
+ *
+ */
+EIP97_Global_Error_t
+EIP97_Global_State_Set(
+        volatile EIP97_Global_State_t * const CurrentState,
+        const EIP97_Global_State_t NewState)
+{
+    switch(*CurrentState)
+    {
+        case EIP97_GLOBAL_STATE_UNKNOWN:
+            switch(NewState)
+            {
+                case EIP97_GLOBAL_STATE_SW_RESET_START:
+                    *CurrentState = NewState;
+                    break;
+                case EIP97_GLOBAL_STATE_SW_RESET_DONE:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+            }
+            break;
+
+         case EIP97_GLOBAL_STATE_HW_RESET_DONE:
+            switch(NewState)
+            {
+                case EIP97_GLOBAL_STATE_INITIALIZED:
+                   *CurrentState = NewState;
+                   break;
+                default:
+                    return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP97_GLOBAL_STATE_SW_RESET_START:
+            switch(NewState)
+            {
+                case EIP97_GLOBAL_STATE_SW_RESET_DONE:
+                    *CurrentState = NewState;
+                    break;
+                case EIP97_GLOBAL_STATE_SW_RESET_START:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP97_GLOBAL_STATE_SW_RESET_DONE:
+            switch(NewState)
+            {
+                case EIP97_GLOBAL_STATE_SW_RESET_DONE:
+                case EIP97_GLOBAL_STATE_INITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP97_GLOBAL_STATE_INITIALIZED:
+            switch(NewState)
+            {
+                case EIP97_GLOBAL_STATE_ENABLED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP97_GLOBAL_STATE_SW_RESET_DONE:
+                    *CurrentState = NewState;
+                    break;
+                case EIP97_GLOBAL_STATE_INITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP97_GLOBAL_STATE_ENABLED:
+            switch(NewState)
+            {
+                case EIP97_GLOBAL_STATE_SW_RESET_START:
+                    *CurrentState = NewState;
+                    break;
+                case EIP97_GLOBAL_STATE_SW_RESET_DONE:
+                    *CurrentState = NewState;
+                    break;
+                case EIP97_GLOBAL_STATE_FATAL_ERROR:
+                    break;
+                case EIP97_GLOBAL_STATE_ENABLED:
+                    break;
+                default:
+                    return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP97_GLOBAL_STATE_FATAL_ERROR:
+            switch(NewState)
+            {
+                case EIP97_GLOBAL_STATE_SW_RESET_START:
+                    *CurrentState = NewState;
+                    break;
+                case EIP97_GLOBAL_STATE_SW_RESET_DONE:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        default:
+            return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+    }
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/* end of file eip97_global_fsm.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_fsm_stub.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_fsm_stub.c
new file mode 100644
index 0000000..4289875
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_fsm_stub.c
@@ -0,0 +1,68 @@
+/* eip97_global_fsm_stub.c
+ *
+ * EIP-97 Global Control Driver Library API State Machine Internal Interface
+ * stub implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip97_global_fsm.h"
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                // IDENTIFIER_NOT_USED
+
+// EIP-97 Driver Library Types API
+#include "eip97_global_types.h"        // EIP97_Global_* types
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_State_Set
+ *
+ */
+EIP97_Global_Error_t
+EIP97_Global_State_Set(
+        EIP97_Global_State_t * const CurrentState,
+        const EIP97_Global_State_t NewState)
+{
+    IDENTIFIER_NOT_USED(CurrentState);
+    IDENTIFIER_NOT_USED((bool)NewState);
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/* end of file eip97_global_fsm_stub.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_init.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_init.c
new file mode 100644
index 0000000..5f060cb
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_init.c
@@ -0,0 +1,827 @@
+/* eip97_global_init.c
+ *
+ * EIP-97 Global Control Driver Library
+ * Initialization Module
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip97_global_init.h"
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+
+// Default configuration
+#include "c_eip97_global.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"             // uint32_t
+
+// Driver Framework C Run-time Library API
+#include "clib.h"                       // ZEROINIT
+
+// Driver Framework Device API
+#include "device_types.h"           // Device_Handle_t
+
+// EIP-97 Global Control Driver Library Internal interfaces
+#include "eip97_global_internal.h"
+#include "eip97_global_level0.h"       // EIP-97 Level 0 macros
+#include "eip202_global_init.h"        // EIP-202 Initialization code
+#include "eip206_level0.h"             // EIP-206 Level 0 macros
+#include "eip96_level0.h"              // EIP-96 Level 0 macros
+#include "eip97_global_fsm.h"          // State machine
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+// Maximum number of Packet Engines that should be used
+// Driver Library will check the maximum number supported run-time
+#ifndef EIP97_GLOBAL_MAX_NOF_PE_TO_USE
+#error "EIP97_GLOBAL_MAX_NOF_PE_TO_USE is not defined"
+#endif
+
+// Number of Ring interfaces
+// Maximum number of Ring interfaces that should be used
+// Driver Library will check the maximum number supported run-time
+#ifndef EIP97_GLOBAL_MAX_NOF_RING_TO_USE
+#error "EIP97_GLOBAL_MAX_NOF_RING_TO_USE is not defined"
+#endif
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+static unsigned int Global97_NofPEs;
+static unsigned int Global97_NofRings;
+static unsigned int Global97_NofLA;
+static unsigned int Global97_NofIN;
+static unsigned int Global97_DFEDSEOffset;
+static unsigned int Global97_SupportedFuncs;
+
+/*----------------------------------------------------------------------------
+ * EIP206Lib_Detect
+ *
+ * Checks the presence of EIP-206 PE hardware. Returns true when found.
+ */
+static bool
+EIP206Lib_Detect(
+        const Device_Handle_t Device,
+        const unsigned int PEnr)
+{
+    uint32_t Value;
+
+    // No revision register for this HW version
+
+    // read-write test one of the registers
+
+    // Set MASK_8_BITS bits of the EIP206_OUT_REG_DBUF_TRESH register
+    EIP206_Write32(Device,
+                   EIP206_OUT_REG_DBUF_TRESH(PEnr),
+                   MASK_8_BITS);
+    Value = EIP206_Read32(Device,
+                          EIP206_OUT_REG_DBUF_TRESH(PEnr));
+    if ((Value & MASK_8_BITS) != MASK_8_BITS)
+        return false;
+
+    // Clear MASK_8_BITS bits of the EIP206_OUT_REG_DBUF_TRESH(PEnr) register
+    EIP206_Write32(Device, EIP206_OUT_REG_DBUF_TRESH(PEnr), 0);
+    Value = EIP206_Read32(Device, EIP206_OUT_REG_DBUF_TRESH(PEnr));
+    if ((Value & MASK_8_BITS) != 0)
+       return false;
+
+    return true;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP96Lib_Detect
+ *
+ * Checks the presence of EIP-96 Engine hardware. Returns true when found.
+ */
+static bool
+EIP96Lib_Detect(
+        const Device_Handle_t Device,
+        const unsigned int PEnr)
+{
+    uint32_t Value, DefaultValue;
+    bool fSuccess = true;
+
+    // No revision register for this HW version
+
+    // Save the default register value
+    DefaultValue = EIP96_Read32(Device,
+                                EIP96_REG_CONTEXT_CTRL(PEnr));
+
+    // read-write test one of the registers
+
+    // Set MASK_6_BITS bits of the EIP96_REG_CONTEXT_CTRL register
+    EIP96_Write32(Device,
+                  EIP96_REG_CONTEXT_CTRL(PEnr),
+                  MASK_6_BITS );
+    Value = EIP96_Read32(Device, EIP96_REG_CONTEXT_CTRL(PEnr));
+    if ((Value & MASK_6_BITS) != MASK_6_BITS)
+        fSuccess = false;
+
+    if( fSuccess )
+    {
+        // Clear MASK_6_BITS bits of the EIP96_REG_CONTEXT_CTRL register
+        EIP96_Write32(Device, EIP96_REG_CONTEXT_CTRL(PEnr), 0);
+        Value = EIP96_Read32(Device, EIP96_REG_CONTEXT_CTRL(PEnr));
+        if ((Value & MASK_6_BITS) != 0)
+            fSuccess = false;
+    }
+
+    // Restore the default register value
+    EIP96_Write32(Device,
+            EIP96_REG_CONTEXT_CTRL(PEnr),
+                  DefaultValue );
+    return fSuccess;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97Lib_Detect
+ *
+ * Checks the presence of EIP-97 Engine hardware. Returns true when found.
+ */
+static bool
+EIP97Lib_Detect(
+        const Device_Handle_t Device)
+{
+#ifdef EIP97_GLOBAL_VERSION_CHECK_ENABLE
+    uint32_t Value;
+
+    // read and check the revision register
+    Value = EIP97_Read32(Device, EIP97_REG_VERSION);
+    if (!EIP97_REV_SIGNATURE_MATCH( Value ))
+        return false;
+#else
+    IDENTIFIER_NOT_USED(Device);
+#endif // EIP97_GLOBAL_VERSION_CHECK_ENABLE
+
+    return true;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202Lib_HWRevision_Get
+ */
+static void
+EIP202Lib_HWRevision_Get(
+        const Device_Handle_t Device,
+        EIP202_Options_t * const Options_p,
+        EIP202_Options2_t * const Options2_p,
+        EIP_Version_t * const Version_p)
+{
+    EIP202_Capabilities_t EIP202_Capabilities;
+    EIP202_Global_HWRevision_Get(Device, &EIP202_Capabilities);
+
+    Version_p->EipNumber = EIP202_Capabilities.EipNumber;
+    Version_p->ComplmtEipNumber = EIP202_Capabilities.ComplmtEipNumber;
+    Version_p->HWPatchLevel = EIP202_Capabilities.HWPatchLevel;
+    Version_p->MinHWRevision = EIP202_Capabilities.MinHWRevision;
+    Version_p->MajHWRevision = EIP202_Capabilities.MajHWRevision;
+
+    Options_p->NofRings = EIP202_Capabilities.NofRings;
+    Options_p->NofPes = EIP202_Capabilities.NofPes;
+    Options_p->fExpPlf = EIP202_Capabilities.fExpPlf;
+    Options_p->CF_Size = EIP202_Capabilities.CF_Size;
+    Options_p->RF_Size = EIP202_Capabilities.RF_Size;
+    Options_p->HostIfc = EIP202_Capabilities.HostIfc;
+    Options_p->DMA_Len = EIP202_Capabilities.DMA_Len;
+    Options_p->HDW = EIP202_Capabilities.HDW;
+    Options_p->TgtAlign = EIP202_Capabilities.TgtAlign;
+    Options_p->fAddr64 = EIP202_Capabilities.fAddr64;
+
+    Options2_p->NofLA_Ifs = EIP202_Capabilities.NofLA_Ifs;
+    Options2_p->NofIN_Ifs = EIP202_Capabilities.NofIN_Ifs;
+    Options2_p->NofAXI_WrChs = EIP202_Capabilities.NofAXI_WrChs;
+    Options2_p->NofAXI_RdClusters = EIP202_Capabilities.NofAXI_RdClusters;
+    Options2_p->NofAXI_RdCPC = EIP202_Capabilities.NofAXI_RdCPC;
+
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP96Lib_HWRevision_Get
+ */
+static void
+EIP96Lib_HWRevision_Get(
+        const Device_Handle_t Device,
+        const unsigned int PEnr,
+        EIP96_Options_t * const Options_p,
+        EIP_Version_t * const Version_p)
+{
+    uint32_t OptionsVal;
+    EIP96_EIP_REV_RD(Device,
+                     PEnr,
+                     &Version_p->EipNumber,
+                     &Version_p->ComplmtEipNumber,
+                     &Version_p->HWPatchLevel,
+                     &Version_p->MinHWRevision,
+                     &Version_p->MajHWRevision);
+
+    EIP96_OPTIONS_RD(Device,
+                     PEnr,
+                     &Options_p->fAES,
+                     &Options_p->fAESfb,
+                     &Options_p->fAESspeed,
+                     &Options_p->fDES,
+                     &Options_p->fDESfb,
+                     &Options_p->fDESspeed,
+                     &Options_p->ARC4,
+                     &Options_p->fAES_XTS,
+                     &Options_p->fWireless,
+                     &Options_p->fMD5,
+                     &Options_p->fSHA1,
+                     &Options_p->fSHA1speed,
+                     &Options_p->fSHA224_256,
+                     &Options_p->fSHA384_512,
+                     &Options_p->fXCBC_MAC,
+                     &Options_p->fCBC_MACspeed,
+                     &Options_p->fCBC_MACkeylens,
+                     &Options_p->fGHASH);
+    Global97_SupportedFuncs = Device_Read32(Device, EIP96_REG_OPTIONS(0)) & 0xfffffff0;
+    OptionsVal = Device_Read32(Device, EIP97_REG_OPTIONS);
+    if ((OptionsVal & BIT_30) != 0)
+    {
+        Global97_SupportedFuncs |= BIT_3;
+    }
+    if ((OptionsVal & BIT_25) != 0)
+    {
+        Global97_SupportedFuncs |= BIT_2;
+    }
+    if ((OptionsVal & BIT_24) != 0)
+    {
+        Global97_SupportedFuncs |= BIT_1;
+    }
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97Lib_HWRevision_Get
+ */
+static void
+EIP97Lib_HWRevision_Get(
+        const Device_Handle_t Device,
+        EIP97_Options_t * const Options_p,
+        EIP_Version_t * const Version_p)
+{
+    EIP97_EIP_REV_RD(Device,
+                     &Version_p->EipNumber,
+                     &Version_p->ComplmtEipNumber,
+                     &Version_p->HWPatchLevel,
+                     &Version_p->MinHWRevision,
+                     &Version_p->MajHWRevision);
+
+    EIP97_OPTIONS_RD(Device,
+                     &Options_p->NofPes,
+                     &Options_p->in_tbuf_size,
+                     &Options_p->in_dbuf_size,
+                     &Options_p->out_tbuf_size,
+                     &Options_p->out_dbuf_size,
+                     &Options_p->central_prng,
+                     &Options_p->tg,
+                     &Options_p->trc);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97Lib_Reset_IsDone
+ */
+static EIP97_Global_Error_t
+EIP97Lib_Reset_IsDone(
+        const Device_Handle_t Device,
+        volatile uint32_t * State_p,
+        const unsigned int PEnr)
+{
+    bool fResetDone = EIP202_Global_Reset_IsDone(Device, PEnr);
+
+    if(fResetDone)
+    {
+        // Transit to a new state
+#ifdef EIP97_GLOBAL_DEBUG_FSM
+        {
+            EIP97_Global_Error_t rv;
+
+            rv = EIP97_Global_State_Set((volatile EIP97_Global_State_t*)State_p,
+                                        EIP97_GLOBAL_STATE_SW_RESET_DONE);
+            if(rv != EIP97_GLOBAL_NO_ERROR)
+                return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+        }
+#endif // EIP97_GLOBAL_DEBUG_FSM
+    }
+    else
+    {
+#ifdef EIP97_GLOBAL_DEBUG_FSM
+        {
+            EIP97_Global_Error_t rv;
+
+            // SW Reset is ongoing, retry later
+            rv = EIP97_Global_State_Set((volatile EIP97_Global_State_t*)State_p,
+                                        EIP97_GLOBAL_STATE_SW_RESET_START);
+            if(rv != EIP97_GLOBAL_NO_ERROR)
+                return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+        }
+#endif // EIP97_GLOBAL_DEBUG_FSM
+
+        return EIP97_GLOBAL_BUSY_RETRY_LATER;
+    }
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_Init
+ */
+EIP97_Global_Error_t
+EIP97_Global_Init(
+        EIP97_Global_IOArea_t * const IOArea_p,
+        const Device_Handle_t Device)
+{
+    unsigned int i;
+    EIP97_Global_Capabilities_t Capabilities;
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    ZEROINIT(Capabilities);
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+
+    // Attempt to initialize slave byte swapping.
+    if (!EIP202_Global_Endianness_Slave_Configure(Device))
+        return EIP97_GLOBAL_UNSUPPORTED_FEATURE_ERROR;
+
+    // Detect presence of the EIP-97 HW hardware
+    if (!EIP202_Global_Detect(Device) ||
+        !EIP206Lib_Detect(Device, PE_DEFAULT_NR) ||
+        !EIP96Lib_Detect(Device, PE_DEFAULT_NR) ||
+        !EIP97Lib_Detect(Device))
+        return EIP97_GLOBAL_UNSUPPORTED_FEATURE_ERROR;
+
+    // Initialize the IO Area
+    TrueIOArea_p->Device = Device;
+    // Can also be EIP97_GLOBAL_STATE_HW_RESET_DONE
+    TrueIOArea_p->State = (uint32_t)EIP97_GLOBAL_STATE_SW_RESET_DONE;
+
+    EIP97Lib_HWRevision_Get(Device,
+                            &Capabilities.EIP97_Options,
+                            &Capabilities.EIP97_Version);
+
+    EIP202Lib_HWRevision_Get(Device,
+                             &Capabilities.EIP202_Options,
+                             &Capabilities.EIP202_Options2,
+                             &Capabilities.EIP202_Version);
+
+    EIP96Lib_HWRevision_Get(Device,
+                            PE_DEFAULT_NR,
+                            &Capabilities.EIP96_Options,
+                            &Capabilities.EIP96_Version);
+
+    // Check actual configuration HW against capabilities
+    // Number of configured PE's
+    Global97_NofPEs = MIN(Capabilities.EIP202_Options.NofPes,
+                          EIP97_GLOBAL_MAX_NOF_PE_TO_USE);
+
+    // Number of configure ring interfaces
+    Global97_NofRings = MIN(Capabilities.EIP202_Options.NofRings,
+                            EIP97_GLOBAL_MAX_NOF_RING_TO_USE);
+
+    // Number of configured Look-aside FIFO interfaces
+#if EIP97_GLOBAL_MAX_NOF_LAFIFO_TO_USE==0
+    Global97_NofLA = 0;
+#else
+    Global97_NofLA = MIN(Capabilities.EIP202_Options2.NofLA_Ifs,
+                         EIP97_GLOBAL_MAX_NOF_LAFIFO_TO_USE);
+#endif
+#if EIP97_GLOBAL_MAX_NOF_INFIFO_TO_USE==0
+    Global97_NofIN = 0;
+#else
+    // Number of configured Inline FIFO interfaces
+    Global97_NofIN = MIN(Capabilities.EIP202_Options2.NofIN_Ifs,
+                         EIP97_GLOBAL_MAX_NOF_INFIFO_TO_USE);
+#endif
+
+    // EIP197 devices with more than 12 rings move the
+    // DFE and DSE register addresses up by 2*4kB to make room for 2 extra
+    // sets of ring control registers.
+    if (Capabilities.EIP202_Options.NofRings > 12)
+    {
+        Global97_DFEDSEOffset = 0x2000;
+    }
+
+#ifdef EIP97_GLOBAL_DEBUG_FSM
+        {
+            EIP97_Global_Error_t rv;
+
+            // Transit to a new state
+            rv = EIP97_Global_State_Set(
+                    (volatile EIP97_Global_State_t*)&TrueIOArea_p->State,
+                    EIP97_GLOBAL_STATE_INITIALIZED);
+            if(rv != EIP97_GLOBAL_NO_ERROR)
+                return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+        }
+#endif // EIP97_GLOBAL_DEBUG_FSM
+
+    // Configure Endianness Conversion method for master (DMA) interface
+    for (i = 0; i < Global97_NofPEs; i++)
+        EIP97_MST_CTRL_WR(Device,
+                          i,
+                          EIP97_GLOBAL_RD_CACHE_VALUE,
+                          EIP97_GLOBAL_WR_CACHE_VALUE,
+                          EIP97_GLOBAL_BYTE_SWAP_METHOD,
+                          EIP97_GLOBAL_SUPPORT_PROTECT_VALUE,
+                          0,  // Disable cache-aligned context writes.
+                          false);
+    {
+        uint8_t ipbuf_max, ipbuf_min,
+                itbuf_max, itbuf_min,
+                opbuf_max, opbuf_min;
+
+#ifdef EIP97_GLOBAL_THRESH_CONFIG_AUTO
+        // Calculate the EIP-202 and EIP-206 Global Control thresholds
+        uint8_t dmalen;
+
+        // Convert to powers of byte counts from powers of 32-bit word counts
+        ipbuf_max = Capabilities.EIP97_Options.in_dbuf_size + 2;
+        itbuf_max = Capabilities.EIP97_Options.in_tbuf_size + 2;
+        opbuf_max = Capabilities.EIP97_Options.out_dbuf_size + 2;
+
+        // EIP-96 token cannot be larger than 2^7 bytes
+        if( itbuf_max > EIP97_GLOBAL_MAX_TOKEN_SIZE )
+            itbuf_max = EIP97_GLOBAL_MAX_TOKEN_SIZE;
+
+        // DMA_Len is power of byte count
+        if (Capabilities.EIP202_Options.DMA_Len >= 1)
+            dmalen = Capabilities.EIP202_Options.DMA_Len - 1;
+        else
+            dmalen = Capabilities.EIP202_Options.DMA_Len;
+
+        ipbuf_max = MIN(ipbuf_max, dmalen);
+        itbuf_max = MIN(itbuf_max, dmalen);
+        opbuf_max = MIN(opbuf_max, dmalen);
+
+        ipbuf_min = ipbuf_max - 1;
+        itbuf_min = itbuf_max - 1;
+        opbuf_min = opbuf_max - 1;
+#else
+        // Use configured statically
+        // the EIP-202 and EIP-206 Global Control thresholds
+        ipbuf_min = EIP97_GLOBAL_DFE_MIN_DATA_XFER_SIZE;
+        ipbuf_max = EIP97_GLOBAL_DFE_MAX_DATA_XFER_SIZE;
+
+        itbuf_min = EIP97_GLOBAL_DFE_MIN_TOKEN_XFER_SIZE;
+        itbuf_max = EIP97_GLOBAL_DFE_MAX_TOKEN_XFER_SIZE;
+
+        opbuf_min = EIP97_GLOBAL_DSE_MIN_DATA_XFER_SIZE;
+        opbuf_max = EIP97_GLOBAL_DSE_MAX_DATA_XFER_SIZE;
+#endif
+
+        EIP202_Global_Init(Device,
+                           Global97_NofPEs,
+                           Capabilities.EIP202_Options2.NofLA_Ifs,
+                           ipbuf_min,
+                           ipbuf_max,
+                           itbuf_min,
+                           itbuf_max,
+                           opbuf_min,
+                           opbuf_max);
+        for (i = 0; i < Global97_NofPEs; i++)
+        {
+
+            // Configure EIP-206 Processing Engine
+            EIP206_IN_DBUF_THRESH_WR(
+                            Device,
+                            i,
+                            0,
+                            ipbuf_min,
+                            ipbuf_max); // ... or use 0xF for maximum, autoconf
+
+            EIP206_IN_TBUF_THRESH_WR(
+                            Device,
+                            i,
+                            EIP97_GLOBAL_IN_TBUF_PKT_THR,
+                            itbuf_min,
+                            itbuf_max); // ... or use 0xF for maximum, autoconf
+
+            EIP206_OUT_DBUF_THRESH_WR(
+                            Device,
+                            i,
+                            opbuf_min,
+                            opbuf_max); // ... or use 0xF for maximum, autoconf
+
+            // Configure EIP-96 Packet Engine
+            EIP96_TOKEN_CTRL_STAT_WR(
+                    Device,
+                    i,
+                    true, /* optimal context update */
+                    EIP97_GLOBAL_EIP96_NO_TOKEN_WAIT, /* CT No token wait */
+                    false, /* Absulute ARC4 pointer */
+                    false, /* Allow reuse cached context */
+                    false, /* Allow postponed reuse */
+                    false, /* Zero length result */
+                    (EIP97_GLOBAL_EIP96_TIMEOUT_CNTR_FLAG == 0) ? false : true,
+                    (EIP97_GLOBAL_EIP96_EXTENDED_ERRORS_ENABLE == 0) ? false : true
+                    );
+            EIP96_TOKEN_CTRL2_WR(
+                    Device,
+                    i,
+                    true,
+                    true,
+                    false,
+                    EIP97_GLOBAL_EIP96_CTX_DONE_PULSE);
+            EIP96_OUT_BUF_CTRL_WR(
+                    Device,
+                    i,
+                    EIP97_GLOBAL_EIP96_PE_HOLD_OUTPUT_DATA,
+                    (EIP97_GLOBAL_EIP96_BLOCK_UPDATE_APPEND == 0) ? false : true,
+                    (EIP97_GLOBAL_EIP96_LEN_DELTA_ENABLE == 0) ? false : true);
+            EIP96_CONTEXT_CTRL_WR(
+                Device,
+                i,
+                EIP97_EIP96_CTX_SIZE,
+                false,
+                true);
+            EIP96_CTX_NUM32_THR_WR(
+                Device,
+                i,
+                EIP97_GLOBAL_EIP96_NUM32_THR);
+            EIP96_CTX_NUM64_THR_L_WR(
+                Device,
+                i,
+                EIP97_GLOBAL_EIP96_NUM64_THR_L);
+            EIP96_CTX_NUM64_THR_H_WR(
+                Device,
+                i,
+                EIP97_GLOBAL_EIP96_NUM64_THR_H);
+#ifdef EIP97_GLOBAL_HAVE_ECN_FIXUP
+            EIP96_ECN_TABLE_WR(Device, i, 0,
+                               0, 0,
+                               1, 0,
+                               2, 0,
+                               3, 0);
+            EIP96_ECN_TABLE_WR(Device, i, 1,
+                               0, EIP96_ECN_CLE0,
+                               1, 0,
+                               1, 0,
+                               3, EIP96_ECN_CLE1);
+            EIP96_ECN_TABLE_WR(Device, i, 2,
+                               0, EIP96_ECN_CLE2,
+                               1, EIP96_ECN_CLE3,
+                               2, 0,
+                               3, 0);
+            EIP96_ECN_TABLE_WR(Device, i, 3,
+                               0, EIP96_ECN_CLE4,
+                               3, 0,
+                               3, 0,
+                               3, 0);
+#endif
+        } // for
+
+    } // EIP-202 HIA Global is configured
+
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_Reset
+ */
+EIP97_Global_Error_t
+EIP97_Global_Reset(
+        EIP97_Global_IOArea_t * const IOArea_p,
+        const Device_Handle_t Device)
+{
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+    unsigned int i;
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+
+    // Attempt to initialize slave byte swapping.
+    if (!EIP202_Global_Endianness_Slave_Configure(Device))
+        return EIP97_GLOBAL_UNSUPPORTED_FEATURE_ERROR;
+
+    // Initialize the IO Area
+    TrueIOArea_p->Device = Device;
+    // Assume this function is called in the Unknown state but
+    // this may not always be true
+    TrueIOArea_p->State = (uint32_t)EIP97_GLOBAL_STATE_UNKNOWN;
+
+    if (!EIP202_Global_Reset(Device, Global97_NofPEs))
+        return EIP97_GLOBAL_UNSUPPORTED_FEATURE_ERROR;
+
+    for (i = 0; i < Global97_NofPEs; i++)
+    {
+        // Restore the EIP-206 default configuration
+        EIP206_IN_DBUF_THRESH_DEFAULT_WR(Device, i);
+        EIP206_IN_TBUF_THRESH_DEFAULT_WR(Device, i);
+        EIP206_OUT_DBUF_THRESH_DEFAULT_WR(Device, i);
+        EIP206_OUT_TBUF_THRESH_DEFAULT_WR(Device, i);
+
+        // Restore the EIP-96 default configuration
+        EIP96_TOKEN_CTRL_STAT_DEFAULT_WR(Device, i);
+    }
+
+    // Check if Global SW Reset is done
+    for (i = 0; i < Global97_NofPEs; i++)
+    {
+        EIP97_Global_Error_t EIP97_Rc;
+
+        EIP97_Rc =
+            EIP97Lib_Reset_IsDone(Device, &TrueIOArea_p->State, i);
+
+        if (EIP97_Rc != EIP97_GLOBAL_NO_ERROR)
+            return EIP97_Rc;
+    }
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_Reset_IsDone
+ */
+EIP97_Global_Error_t
+EIP97_Global_Reset_IsDone(
+        EIP97_Global_IOArea_t * const IOArea_p)
+{
+    Device_Handle_t Device;
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+    unsigned int i;
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+
+    Device = TrueIOArea_p->Device;
+
+    // Check if Global SW Reset is done
+    for (i = 0; i < Global97_NofPEs; i++)
+    {
+        EIP97_Global_Error_t EIP97_Rc;
+
+        EIP97_Rc =
+            EIP97Lib_Reset_IsDone(Device, &TrueIOArea_p->State, i);
+
+        if (EIP97_Rc != EIP97_GLOBAL_NO_ERROR)
+            return EIP97_Rc;
+    }
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_HWRevision_Get
+ */
+EIP97_Global_Error_t
+EIP97_Global_HWRevision_Get(
+        EIP97_Global_IOArea_t * const IOArea_p,
+        EIP97_Global_Capabilities_t * const Capabilities_p)
+{
+    Device_Handle_t Device;
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP97_GLOBAL_CHECK_POINTER(Capabilities_p);
+
+    Device = TrueIOArea_p->Device;
+
+    EIP202Lib_HWRevision_Get(Device,
+                             &Capabilities_p->EIP202_Options,
+                             &Capabilities_p->EIP202_Options2,
+                             &Capabilities_p->EIP202_Version);
+
+    EIP96Lib_HWRevision_Get(Device,
+                            PE_DEFAULT_NR,
+                            &Capabilities_p->EIP96_Options,
+                            &Capabilities_p->EIP96_Version);
+
+    EIP97Lib_HWRevision_Get(Device,
+                            &Capabilities_p->EIP97_Options,
+                            &Capabilities_p->EIP97_Version);
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_Configure
+ */
+EIP97_Global_Error_t
+EIP97_Global_Configure(
+        EIP97_Global_IOArea_t * const IOArea_p,
+        const unsigned int PE_Number,
+        const EIP97_Global_Ring_PE_Map_t * const RingPEMap_p)
+{
+    Device_Handle_t Device;
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+    EIP202_Global_Ring_PE_Map_t EIP202RingPEMap;
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP97_GLOBAL_CHECK_POINTER(RingPEMap_p);
+
+    if(PE_Number >= Global97_NofPEs)
+        return EIP97_GLOBAL_ARGUMENT_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+    // Figure out which rings must be assigned to
+    // DFE and DSE threads for PE_Number
+    EIP202RingPEMap.RingPE_Mask = (uint16_t)(RingPEMap_p->RingPE_Mask &
+                                             ((1 << (Global97_NofRings + Global97_NofLA + Global97_NofIN))-1));
+    EIP202RingPEMap.RingPrio_Mask = RingPEMap_p->RingPrio_Mask;
+    EIP202RingPEMap.RingSlots0 = RingPEMap_p->RingSlots0;
+    EIP202RingPEMap.RingSlots1 = RingPEMap_p->RingSlots1;
+
+#ifdef EIP97_GLOBAL_DEBUG_FSM
+    {
+        EIP97_Global_Error_t rv;
+        EIP97_Global_State_t NewState;
+
+        // Transit to a new state
+        if(EIP202RingPEMap.RingPE_Mask != 0)
+            NewState = EIP97_GLOBAL_STATE_ENABLED;
+        else
+            // Engines without rings not allowed!
+            NewState = EIP97_GLOBAL_STATE_INITIALIZED;
+
+        rv = EIP97_Global_State_Set(
+                (volatile EIP97_Global_State_t*)&TrueIOArea_p->State, NewState);
+        if(rv != EIP97_GLOBAL_NO_ERROR)
+            return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+    }
+#endif // EIP97_GLOBAL_DEBUG_FSM
+
+    EIP202_Global_Configure(Device, PE_Number, &EIP202RingPEMap);
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Interfaces_Get
+ */
+void
+EIP97_Interfaces_Get(
+    unsigned int * const NofPEs_p,
+    unsigned int * const NofRings_p,
+    unsigned int * const NofLA_p,
+    unsigned int * const NofIN_p)
+{
+    if (NofPEs_p)
+        *NofPEs_p = Global97_NofPEs;
+    if (NofRings_p)
+        *NofRings_p = Global97_NofRings;
+    if (NofLA_p)
+        *NofLA_p = Global97_NofLA;
+    if (NofIN_p)
+        *NofIN_p = Global97_NofIN;
+}
+
+/*----------------------------------------------------------------------------
+ * EIP97_DFEDSE_Offset_Get
+ */
+unsigned int
+EIP97_DFEDSE_Offset_Get(void)
+{
+    return Global97_DFEDSEOffset;
+}
+
+
+unsigned int
+EIP97_SupportedFuncs_Get(void)
+{
+    return Global97_SupportedFuncs;
+}
+
+
+/* end of file eip97_global_init.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_prng.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_prng.c
new file mode 100644
index 0000000..eb41088
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_prng.c
@@ -0,0 +1,120 @@
+/* eip97_global_prng.c
+ *
+ * EIP-97 GLobal Control Driver Library
+ * PRNG Module
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip97_global_prng.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Driver Framework Device API
+#include "device_types.h"              // Device_Handle_t
+
+// EIP-97 Global Control Driver Library Internal interfaces
+#include "eip97_global_internal.h"
+#include "eip96_level0.h"              // EIP-96 Level 0 macros
+#include "eip97_global_fsm.h"          // State machine
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_PRNG_Reseed
+ */
+EIP97_Global_Error_t
+EIP97_Global_PRNG_Reseed(
+        EIP97_Global_IOArea_t * const IOArea_p,
+        const unsigned int PE_Number,
+        const EIP96_PRNG_Reseed_t * const ReseedData_p)
+{
+    Device_Handle_t Device;
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+
+    if(PE_Number >= EIP97_GLOBAL_MAX_NOF_PE_TO_USE)
+        return EIP97_GLOBAL_ARGUMENT_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+#ifdef EIP97_GLOBAL_DEBUG_FSM
+    {
+        EIP97_Global_Error_t rv;
+
+        // Remain in the current state
+        rv = EIP97_Global_State_Set((volatile EIP97_Global_State_t*)&TrueIOArea_p->State,
+                                    (EIP97_Global_State_t)TrueIOArea_p->State);
+        if(rv != EIP97_GLOBAL_NO_ERROR)
+            return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+    }
+#endif // EIP97_GLOBAL_DEBUG_FSM
+
+    EIP96_PRNG_CTRL_WR(Device,
+                       PE_Number, // EIP-96 PE number
+                       false,     // Disable PRNG
+                       false);    // Set PRNG Manual mode
+
+    // Write new seed data
+    EIP96_PRNG_SEED_L_WR(Device, PE_Number, ReseedData_p->SeedLo);
+    EIP96_PRNG_SEED_H_WR(Device, PE_Number, ReseedData_p->SeedHi);
+
+    // Write new key data
+    EIP96_PRNG_KEY_0_L_WR(Device, PE_Number, ReseedData_p->Key0Lo);
+    EIP96_PRNG_KEY_0_H_WR(Device, PE_Number, ReseedData_p->Key0Hi);
+    EIP96_PRNG_KEY_1_L_WR(Device, PE_Number, ReseedData_p->Key1Lo);
+    EIP96_PRNG_KEY_1_H_WR(Device, PE_Number, ReseedData_p->Key1Hi);
+
+    // Write new LFSR data
+    EIP96_PRNG_LFSR_L_WR(Device, PE_Number, ReseedData_p->LFSRLo);
+    EIP96_PRNG_LFSR_H_WR(Device, PE_Number, ReseedData_p->LFSRHi);
+
+    EIP96_PRNG_CTRL_WR(Device,
+                       PE_Number, // EIP-96 PE number
+                       true,      // Enable PRNG
+                       true);     // Set PRNG Auto mode
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/* end of file eip97_global_prng.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/iotoken/iotoken.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/iotoken/iotoken.c
new file mode 100644
index 0000000..a9a3498
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/iotoken/iotoken.c
@@ -0,0 +1,633 @@
+/* iotoken.c
+ *
+ * IOToken API implementation for the EIP-197 Server with ICE only
+ *
+ */
+
+/*****************************************************************************
+* Copyright (c) 2016-2022 by Rambus, Inc. and/or its subsidiaries.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// Extended IOToken API
+#include "iotoken_ext.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_iotoken.h"              // IOTOKEN_STRICT_ARGS
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"             // IDENTIFIER_NOT_USED, bool, uint32_t
+
+// Firmware packet flow codes
+#include "firmware_eip207_api_cmd.h"
+
+// ZEROINIT
+#include "clib.h"
+
+#include "log.h"
+
+// Packet buffer access
+#include "adapter_pec_pktbuf.h"
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+#define IOTOKEN_ARGUMENT_ERROR      -1
+#define IOTOKEN_INTERNAL_ERROR      -2
+
+#ifdef IOTOKEN_STRICT_ARGS
+#define IOTOKEN_CHECK_POINTER(_p) \
+    if (NULL == (_p)) \
+        return IOTOKEN_ARGUMENT_ERROR;
+#define IOTOKEN_CHECK_INT_INRANGE(_i, _min, _max) \
+    if ((_i) < (_min) || (_i) > (_max)) \
+        return IOTOKEN_ARGUMENT_ERROR;
+#define IOTOKEN_CHECK_INT_ATLEAST(_i, _min) \
+    if ((_i) < (_min)) \
+        return IOTOKEN_ARGUMENT_ERROR;
+#define IOTOKEN_CHECK_INT_ATMOST(_i, _max) \
+    if ((_i) > (_max)) \
+        return IOTOKEN_ARGUMENT_ERROR;
+#else
+/* IOTOKEN_STRICT_ARGS undefined */
+#define IOTOKEN_CHECK_POINTER(_p)
+#define IOTOKEN_CHECK_INT_INRANGE(_i, _min, _max)
+#define IOTOKEN_CHECK_INT_ATLEAST(_i, _min)
+#define IOTOKEN_CHECK_INT_ATMOST(_i, _max)
+#endif /*end of IOTOKEN_STRICT_ARGS */
+
+// Input Token words offsets
+#define IOTOKEN_HDR_IN_WORD_OFFS           0
+#define IOTOKEN_APP_ID_IN_WORD_OFFS        1
+#define IOTOKEN_SA_ADDR_LO_IN_WORD_OFFS    2
+#define IOTOKEN_SA_ADDR_HI_IN_WORD_OFFS    3
+#define IOTOKEN_HW_SERVICES_IN_WORD_OFFS   4
+#define IOTOKEN_NH_OFFSET_IN_WORD_OFFS     5
+#define IOTOKEN_BP_DATA_IN_WORD_OFFS       6
+
+// Output Token words offsets
+#define IOTOKEN_HDR_OUT_WORD_OFFS          0
+#define IOTOKEN_BP_LEN_OUT_WORD_OFFS       1
+#define IOTOKEN_APP_ID_OUT_WORD_OFFS       2
+#define IOTOKEN_PAD_NH_OUT_WORD_OFFS       3
+#define IOTOKEN_SA_ADDR_LO_OUT_WORD_OFFS   4
+#define IOTOKEN_SA_ADDR_HI_OUT_WORD_OFFS   5
+#define IOTOKEN_NPH_CTX_OUT_WORD_OFFS      6
+#define IOTOKEN_PREV_NH_OFFS_OUT_WORD_OFFS 7
+#define IOTOKEN_BP_DATA_OUT_WORD_OFFS      8
+
+#define IOTOKEN_MARK                       0xEC00
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * IOToken_InWordCount_Get
+ */
+unsigned int
+IOToken_InWordCount_Get(void)
+{
+    return IOTOKEN_IN_WORD_COUNT - 4 + IOTOKEN_BYPASS_WORD_COUNT;
+}
+
+
+/*----------------------------------------------------------------------------
+ * IOToken_OutWordCount_Get
+ */
+unsigned int
+IOToken_OutWordCount_Get(void)
+{
+    return IOTOKEN_OUT_WORD_COUNT - 4 + IOTOKEN_BYPASS_WORD_COUNT;
+}
+
+
+/*----------------------------------------------------------------------------
+ * IOToken_Create
+ */
+int
+IOToken_Create(
+        const IOToken_Input_Dscr_t * const Dscr_p,
+        uint32_t * Data_p)
+{
+    IOToken_Input_Dscr_Ext_t * DscrExt_p;
+#if IOTOKEN_BYPASS_WORD_COUNT > 0
+    unsigned int bypass_gap = 0;
+#endif
+    unsigned int i;
+
+    IOTOKEN_CHECK_POINTER(Dscr_p);
+    IOTOKEN_CHECK_POINTER(Dscr_p->Ext_p);
+    IOTOKEN_CHECK_POINTER(Data_p);
+
+    DscrExt_p = (IOToken_Input_Dscr_Ext_t *)Dscr_p->Ext_p;
+
+    // Input Token word: EIP-96 Token Header Word
+    {
+        i = IOTOKEN_HDR_IN_WORD_OFFS;
+
+        // Set initialization value in the Token Header Word excluding packet
+        // size field
+        Data_p[i] = Dscr_p->TknHdrWordInit & ~MASK_16_BITS;
+
+        // Input packet size
+        Data_p[i] |= Dscr_p->InPacket_ByteCount & MASK_16_BITS;
+
+        if (DscrExt_p->HW_Services == IOTOKEN_CMD_PKT_LAC)
+        {
+            // Options, ARC4 pre-fetch
+            if (DscrExt_p->fARC4Prefetch)
+                Data_p[i] |= BIT_16;
+
+            Data_p[i] |= BIT_17; // Set token header format to EIP-(1)97
+
+            Data_p[i] |= BIT_18; // Only 64-bit Context (SA) pointer is supported
+
+            // Enable Context Reuse auto detect if no new SA
+            if (Dscr_p->Options.fReuseSA)
+                Data_p[i] |= BIT_21;
+        }
+        // Mask size for inbound ESP
+        if (DscrExt_p->SequenceMaskBitCount != 0)
+        {
+            switch(DscrExt_p->SequenceMaskBitCount)
+            {
+            case 64:
+                Data_p[i] |= 0x00200000;
+                break;
+            case 128:
+                Data_p[i] |= 0x00400000;
+                break;
+            case 256:
+                Data_p[i] |= 0x00600000;
+                break;
+            case 512:
+                Data_p[i] |= 0x00800000;
+                break;
+            }
+        }
+        // Extended options for LIP
+        if (DscrExt_p->fEncLastDest)
+            Data_p[i] |= BIT_25;
+        // Extended options for in-line DTLS packet flow
+        {
+            if (DscrExt_p->Options.fCAPWAP)
+                Data_p[i] |= BIT_26;
+
+            if (DscrExt_p->Options.fInbound)
+                Data_p[i] |= BIT_27;
+
+            Data_p[i] |= DscrExt_p->Options.ContentType << 28;
+        }
+
+        Data_p[i] |= IOTOKEN_FLOW_TYPE << 30; // Implemented flow type
+    }
+
+    // Input Token word: Application ID
+    {
+        i = IOTOKEN_APP_ID_IN_WORD_OFFS;
+        Data_p[i] = (Dscr_p->AppID & MASK_7_BITS) << 9;
+        Data_p[i] |= (DscrExt_p->AAD_ByteCount & MASK_8_BITS);
+        if (DscrExt_p->fInline)
+            Data_p[i] |= (32 + IOTOKEN_BYPASS_WORD_COUNT*4) << 16;
+    }
+
+    // Input Token word: Context (SA) low 32 bits physical address
+    {
+        i = IOTOKEN_SA_ADDR_LO_IN_WORD_OFFS;
+        Data_p[i] = Dscr_p->SA_PhysAddr.Lo;
+    }
+
+    // Input Token word: Context (SA) high 32 bits physical address
+    {
+        i = IOTOKEN_SA_ADDR_HI_IN_WORD_OFFS;
+        //if (DscrExt_p->Options.f64bitSA) // Only 64-bit SA address supported
+            Data_p[i] = Dscr_p->SA_PhysAddr.Hi;
+    }
+
+    // Input Token word: HW services, e,g, packet flow selection
+    {
+        i = IOTOKEN_HW_SERVICES_IN_WORD_OFFS;
+        Data_p[i] = ((DscrExt_p->HW_Services & MASK_8_BITS) << 24) |
+            (DscrExt_p->UserDef & MASK_16_BITS);
+        if (DscrExt_p->fStripPadding != IOTOKEN_PADDING_DEFAULT_ON)
+            Data_p[i] |= BIT_22;
+        if (DscrExt_p->fAllowPadding != IOTOKEN_PADDING_DEFAULT_ON)
+            Data_p[i] |= BIT_23;
+    }
+
+    // Input Token word: Offset and Next Header
+    {
+        i = IOTOKEN_NH_OFFSET_IN_WORD_OFFS;
+        Data_p[i] = (DscrExt_p->Offset_ByteCount & MASK_8_BITS) << 8;
+        Data_p[i] |= (DscrExt_p->NextHeader & MASK_8_BITS) << 16;
+        if (DscrExt_p->fFL)
+            Data_p[i] |= BIT_24;
+        if (DscrExt_p->fIPv4Chksum)
+            Data_p[i] |= BIT_25;
+        if (DscrExt_p->fL4Chksum)
+            Data_p[i] |= BIT_26;
+        if (DscrExt_p->fParseEther)
+            Data_p[i] |= BIT_27;
+        if (DscrExt_p->fKeepOuter)
+            Data_p[i] |= BIT_28;
+
+    }
+
+    if (DscrExt_p->fInline)
+    {
+        Data_p[IOTOKEN_BP_DATA_IN_WORD_OFFS]=0;
+        Data_p[IOTOKEN_BP_DATA_IN_WORD_OFFS+1]=0;
+#if IOTOKEN_BYPASS_WORD_COUNT > 0
+        bypass_gap = 2;
+#endif
+    }
+
+#if IOTOKEN_BYPASS_WORD_COUNT > 0
+    // Input Token word: Bypass Data
+    {
+        unsigned int j;
+
+        if (DscrExt_p->BypassData_p)
+        {
+            for (j = 0; j < IOTOKEN_BYPASS_WORD_COUNT; j++)
+                Data_p[j+IOTOKEN_BP_DATA_IN_WORD_OFFS + bypass_gap] = DscrExt_p->BypassData_p[j];
+        }
+        else
+        {
+            for (j = 0; j < IOTOKEN_BYPASS_WORD_COUNT; j++)
+                Data_p[j+IOTOKEN_BP_DATA_IN_WORD_OFFS + bypass_gap] = 0xf0f0f0f0;
+        }
+        i += bypass_gap + j;
+    }
+#endif
+
+    if (i  >= IOTOKEN_IN_WORD_COUNT_IL)
+        return IOTOKEN_INTERNAL_ERROR;
+    else
+        return i+1;
+}
+
+
+/*----------------------------------------------------------------------------
+ * IOToken_Fixup
+ */
+int
+IOToken_Fixup(
+        uint32_t * const Data_p,
+        const DMABuf_Handle_t PacketHandle)
+{
+    uint32_t AppendFlags;
+    if (Data_p == NULL)
+        return 0;
+
+    AppendFlags = Data_p[IOTOKEN_BP_LEN_OUT_WORD_OFFS] & (BIT_31|BIT_30|BIT_29);
+    if (AppendFlags != 0)
+    {
+        uint8_t AppendData[12];
+        uint8_t *Append_p;
+        unsigned int Offset;
+        unsigned int PrevNH_Offset;
+        unsigned int UpdateOffset;
+        unsigned int AppendLen = 0;
+        if ((AppendFlags & BIT_31) != 0)
+            AppendLen+=4;
+        if ((AppendFlags & BIT_30) != 0)
+            AppendLen+=4;
+        if ((AppendFlags & BIT_29) != 0)
+            AppendLen+=4;
+        UpdateOffset = Data_p[IOTOKEN_HDR_OUT_WORD_OFFS] & MASK_17_BITS;
+        UpdateOffset = 4*((UpdateOffset + 3)/4); // Align to word boundary.
+        Offset = Data_p[IOTOKEN_PAD_NH_OUT_WORD_OFFS] >> 16 & MASK_8_BITS;
+        // Get first byte of header
+        Append_p = Adapter_PEC_PktData_Get(PacketHandle, AppendData, UpdateOffset, AppendLen);
+        if (AppendFlags == (BIT_31|BIT_30))
+        { // IPv6 header update, NH plus length
+            PrevNH_Offset = Data_p[IOTOKEN_PREV_NH_OFFS_OUT_WORD_OFFS] & MASK_16_BITS;
+            Adapter_PEC_PktByte_Put(PacketHandle, PrevNH_Offset, Append_p[4]);
+            Adapter_PEC_PktByte_Put(PacketHandle, Offset + 4, Append_p[0]);
+            Adapter_PEC_PktByte_Put(PacketHandle, Offset + 5, Append_p[1]);
+            LOG_INFO("IOToken_Fixup: IPv6 inbound transport\n");
+        }
+        else if (AppendFlags == BIT_29)
+        { // IPv4 checksum only update
+            Adapter_PEC_PktByte_Put(PacketHandle, Offset + 10, Append_p[0]);
+            Adapter_PEC_PktByte_Put(PacketHandle, Offset + 11, Append_p[1]);
+            LOG_INFO("IOToken_Fixup: IPv4 inbound tunnel\n");
+        }
+        else if (AppendFlags == (BIT_31|BIT_30|BIT_29))
+        { // IPv4 header update, proto + length + checksum.
+            Adapter_PEC_PktByte_Put(PacketHandle, Offset + 2, Append_p[0]);
+            Adapter_PEC_PktByte_Put(PacketHandle, Offset + 3, Append_p[1]);
+            Adapter_PEC_PktByte_Put(PacketHandle, Offset + 9, Append_p[5]);
+            Adapter_PEC_PktByte_Put(PacketHandle, Offset + 10, Append_p[8]);
+            Adapter_PEC_PktByte_Put(PacketHandle, Offset + 11, Append_p[9]);
+            LOG_INFO("IOToken_Fixup: IPv4 inbound transport\n");
+        }
+        else
+        {
+            LOG_CRIT("IOToken_Fixup: Unexpected flags combination 0x%08x\n",
+                     AppendFlags);
+            return -1;
+        }
+    }
+    return 0;
+}
+
+/*----------------------------------------------------------------------------
+ * IOToken_SAAddr_Update
+ */
+int
+IOToken_SAAddr_Update(
+        const IOToken_PhysAddr_t * const SA_PhysAddr_p,
+        uint32_t * InTokenData_p)
+{
+    IOTOKEN_CHECK_POINTER(SA_PhysAddr_p);
+    IOTOKEN_CHECK_POINTER(InTokenData_p);
+
+    // Input Token word: Context (SA) low 32 bits physical address
+    InTokenData_p[IOTOKEN_SA_ADDR_LO_IN_WORD_OFFS] = SA_PhysAddr_p->Lo;
+
+    // Input Token word: Context (SA) high 32 bits physical address
+    InTokenData_p[IOTOKEN_SA_ADDR_HI_IN_WORD_OFFS] = SA_PhysAddr_p->Hi;
+
+    return 2; // updated 32-bit token words
+}
+
+
+/*----------------------------------------------------------------------------
+ * IOToken_SAReuse_Update
+ */
+int
+IOToken_SAReuse_Update(
+        const bool fReuseSA,
+        uint32_t * InTokenData_p)
+{
+    IOTOKEN_CHECK_POINTER(InTokenData_p);
+
+    // Enable Context Reuse auto detect if no new SA
+    if (fReuseSA)
+        InTokenData_p[IOTOKEN_HDR_IN_WORD_OFFS] |= BIT_21;
+    else
+        InTokenData_p[IOTOKEN_HDR_IN_WORD_OFFS] &= ~BIT_21;
+
+    return 1;
+}
+
+
+/*----------------------------------------------------------------------------
+ * IOToken_Mark_Set
+ */
+int
+IOToken_Mark_Set(
+        uint32_t * InTokenData_p)
+{
+    IOTOKEN_CHECK_POINTER(InTokenData_p);
+
+    InTokenData_p[IOTOKEN_APP_ID_IN_WORD_OFFS] &= ~(MASK_7_BITS << 9);
+    InTokenData_p[IOTOKEN_APP_ID_IN_WORD_OFFS] |= IOTOKEN_MARK;
+
+    return 1;
+}
+
+
+/*----------------------------------------------------------------------------
+ * IOToken_Mark_Offset_Get
+ */
+int
+IOToken_OutMarkOffset_Get(void)
+{
+    return IOTOKEN_APP_ID_OUT_WORD_OFFS;
+}
+
+
+/*----------------------------------------------------------------------------
+ * IOToken_Mark_Check
+ */
+int
+IOToken_Mark_Check(
+        uint32_t * OutTokenData_p)
+{
+    uint32_t Mark;
+
+    IOTOKEN_CHECK_POINTER(OutTokenData_p);
+
+    Mark = OutTokenData_p[IOTOKEN_APP_ID_OUT_WORD_OFFS] & IOTOKEN_MARK;
+
+    if (Mark == IOTOKEN_MARK)
+        return 0;
+    else
+        return 1;
+}
+
+
+/*----------------------------------------------------------------------------
+ * IOToken_Parse
+ */
+int
+IOToken_Parse(
+        const uint32_t * Data_p,
+        IOToken_Output_Dscr_t * const Dscr_p)
+{
+    unsigned int i, j = 0;
+    IOToken_Output_Dscr_Ext_t * Ext_p;
+
+    IOTOKEN_CHECK_POINTER(Data_p);
+    IOTOKEN_CHECK_POINTER(Dscr_p);
+
+    Ext_p = (IOToken_Output_Dscr_Ext_t *)Dscr_p->Ext_p;
+
+    // Output Token word: EIP-96 Output Token Header Word
+    {
+        i = IOTOKEN_HDR_OUT_WORD_OFFS;
+        Dscr_p->OutPacket_ByteCount = Data_p[i]       & MASK_17_BITS;
+        Dscr_p->ErrorCode           = Data_p[i] >> 17 & MASK_15_BITS;
+    }
+
+    // Output Token word: EIP-96 Output Token Bypass Data Length Word
+    {
+        i = IOTOKEN_BP_LEN_OUT_WORD_OFFS;
+        Dscr_p->BypassData_ByteCount =  Data_p[i] & MASK_4_BITS;
+        Dscr_p->fHashAppended        = (Data_p[i] & BIT_21) != 0;
+
+        Dscr_p->Hash_ByteCount       = Data_p[i] >> 22 & MASK_6_BITS;
+
+        Dscr_p->fBytesAppended       = (Data_p[i] & BIT_28) != 0;
+        Dscr_p->fChecksumAppended    = (Data_p[i] & BIT_29) != 0;
+        Dscr_p->fNextHeaderAppended  = (Data_p[i] & BIT_30) != 0;
+        Dscr_p->fLengthAppended      = (Data_p[i] & BIT_31) != 0;
+    }
+
+    // Output Token word: EIP-96 Output Token Application ID Word
+    {
+        i = IOTOKEN_APP_ID_OUT_WORD_OFFS;
+        Dscr_p->AppID = Data_p[i] >> 9 & MASK_7_BITS;
+    }
+
+    // Output Token word: Pad Length and Next Header
+    {
+        i = IOTOKEN_PAD_NH_OUT_WORD_OFFS;
+        Dscr_p->NextHeader    = Data_p[i]      & MASK_8_BITS;
+        Dscr_p->Pad_ByteCount = Data_p[i] >> 8 & MASK_8_BITS;
+    }
+
+    // Parse Output Token descriptor extension if requested
+    if (Ext_p)
+    {
+        // Output Token word: ToS/TC, DF, Firmware errors
+        {
+            j = IOTOKEN_BP_LEN_OUT_WORD_OFFS;
+            Ext_p->TOS_TC    = Data_p[j] >> 5  & MASK_8_BITS;
+
+            Ext_p->fDF       = (Data_p[j] & BIT_13) != 0;
+
+            Ext_p->CfyErrors = Data_p[j] >> 16 & MASK_5_BITS;
+        }
+
+#ifdef IOTOKEN_EXTENDED_ERRORS_ENABLE
+        if ((Data_p[IOTOKEN_HDR_OUT_WORD_OFFS] & BIT_31) != 0)
+        {
+            Ext_p->ExtErrors = (Data_p[IOTOKEN_HDR_OUT_WORD_OFFS] >> 17) & MASK_8_BITS;
+        }
+        else
+#endif
+        {
+            Ext_p->ExtErrors = 0;
+        }
+
+        // Output Token word: IP Length Delta and Offset
+        {
+            j = IOTOKEN_PAD_NH_OUT_WORD_OFFS;
+            Ext_p->Offset_ByteCount  = Data_p[j] >> 16 & MASK_8_BITS;
+            Ext_p->IPDelta_ByteCount = Data_p[j] >> 24 & MASK_8_BITS;
+        }
+
+        // Output Token word: SA physical address low/high words
+        {
+            j = IOTOKEN_SA_ADDR_LO_OUT_WORD_OFFS;
+            Ext_p->SA_PhysAddr.Lo = Data_p[j];
+
+            j = IOTOKEN_SA_ADDR_HI_OUT_WORD_OFFS;
+            Ext_p->SA_PhysAddr.Hi = Data_p[j];
+        }
+
+        // Output Token word: Application header processing context
+        {
+            j = IOTOKEN_NPH_CTX_OUT_WORD_OFFS;
+            Ext_p->NPH_Context = Data_p[j];
+        }
+
+        // Output Token word: Previous Next Header Offset
+        {
+            j = IOTOKEN_PREV_NH_OFFS_OUT_WORD_OFFS;
+            Ext_p->NextHeaderOffset = Data_p[j] & MASK_16_BITS;
+            Ext_p->fInIPv6 = ((Data_p[j] & BIT_16) != 0);
+            Ext_p->fFromEther = ((Data_p[j] & BIT_17) != 0);
+            Ext_p->fOutIPv6 = ((Data_p[j] & BIT_22) != 0);
+            Ext_p->fInbTunnel = ((Data_p[j] & BIT_23) != 0);
+        }
+
+#if IOTOKEN_BYPASS_WORD_COUNT > 0
+        // Output Token word: Bypass Data
+        {
+            unsigned int k = 0;
+            if (Ext_p->BypassData_p)
+            {
+                for (k = 0; k < IOTOKEN_BYPASS_WORD_COUNT; k++)
+                    Ext_p->BypassData_p[k] =
+                        Data_p[k+IOTOKEN_BP_DATA_OUT_WORD_OFFS];
+            }
+            j += k;
+        }
+#endif
+    }
+
+    // Output Token word: Reserved word not used
+    // i = IOTOKEN_RSVD_OUT_WORD_OFFS;
+
+    return MAX(i, j);
+}
+
+
+/*----------------------------------------------------------------------------
+ * IOToken_PacketLegth_Get
+ */
+int
+IOToken_PacketLegth_Get(
+        const uint32_t * Data_p,
+        unsigned int * Pkt_ByteCount_p)
+{
+    IOTOKEN_CHECK_POINTER(Data_p);
+    IOTOKEN_CHECK_POINTER(Pkt_ByteCount_p);
+
+    *Pkt_ByteCount_p = Data_p[IOTOKEN_HDR_OUT_WORD_OFFS] & MASK_17_BITS;
+
+    return 1;
+}
+
+
+/*----------------------------------------------------------------------------
+ * IOToken_BypassLegth_Get
+ */
+int
+IOToken_BypassLegth_Get(
+        const uint32_t * Data_p,
+        unsigned int * BD_ByteCount_p)
+{
+    IOTOKEN_CHECK_POINTER(Data_p);
+    IOTOKEN_CHECK_POINTER(BD_ByteCount_p);
+
+    *BD_ByteCount_p = Data_p[IOTOKEN_BP_LEN_OUT_WORD_OFFS] & MASK_4_BITS;
+
+    return 1;
+}
+
+
+/*----------------------------------------------------------------------------
+ * IOToken_ErrorCode_Get
+ */
+int
+IOToken_ErrorCode_Get(
+        const uint32_t * Data_p,
+        unsigned int * ErrorCode_p)
+{
+    IOTOKEN_CHECK_POINTER(Data_p);
+    IOTOKEN_CHECK_POINTER(ErrorCode_p);
+
+    *ErrorCode_p = (Data_p[IOTOKEN_HDR_OUT_WORD_OFFS] >> 17) & MASK_15_BITS;
+#ifdef IOTOKEN_EXTENDED_ERRORS_ENABLE
+    if ((Data_p[IOTOKEN_HDR_OUT_WORD_OFFS] & BIT_31) != 0)
+    {
+        *ErrorCode_p &= ~0x40ff; // Remove the detailed error code and related bits.
+    }
+#endif
+
+    return 1;
+}
+
+
+/* end of file iotoken.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/list/list.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/list/list.c
new file mode 100644
index 0000000..86b0727
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/list/list.c
@@ -0,0 +1,459 @@
+/* list.c
+ *
+ * This Module implements the List API
+ */
+
+/*****************************************************************************
+* Copyright (c) 2012-2020 by Rambus, Inc. and/or its subsidiaries.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// List API
+#include "list.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_list.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+typedef struct
+{
+    // List head
+    List_Element_t * Head_p;
+
+    // List tail
+    List_Element_t * Tail_p;
+
+    // Number of elements in the list
+    unsigned int ElementCount;
+
+} List_t;
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+// Statically allocated list instances. This will be deprecated in future.
+static List_t List [LIST_MAX_NOF_INSTANCES];
+
+
+/*----------------------------------------------------------------------------
+ * List_Init
+ *
+ */
+List_Status_t
+List_Init(
+        const unsigned int ListID,
+        void * const ListInstance_p)
+{
+#ifdef LIST_STRICT_ARGS
+    if (ListID >= LIST_MAX_NOF_INSTANCES)
+        return LIST_ERROR_BAD_ARGUMENT;
+#endif // LIST_STRICT_ARGS
+
+    // Initialize the list instance
+    {
+        List_t * List_p;
+
+        if (ListInstance_p)
+            List_p = (List_t*)ListInstance_p;
+        else
+            List_p = &List[ListID];
+
+        List_p->ElementCount    = 0;
+        List_p->Head_p          = NULL;
+        List_p->Tail_p          = NULL;
+    }
+
+    return LIST_STATUS_OK;
+}
+
+
+/*----------------------------------------------------------------------------
+ * List_Uninit
+ *
+ */
+List_Status_t
+List_Uninit(
+        const unsigned int ListID,
+        void * const ListInstance_p)
+{
+#ifdef LIST_STRICT_ARGS
+    if (ListID >= LIST_MAX_NOF_INSTANCES)
+        return LIST_ERROR_BAD_ARGUMENT;
+#endif // LIST_STRICT_ARGS
+
+    // Un-initialize the list instance
+    {
+        List_t * List_p;
+
+        if (ListInstance_p)
+            List_p = (List_t*)ListInstance_p;
+        else
+            List_p = &List[ListID];
+
+        List_p->ElementCount    = 0;
+        List_p->Head_p          = NULL;
+        List_p->Tail_p          = NULL;
+    }
+
+    return LIST_STATUS_OK;
+}
+
+
+/*----------------------------------------------------------------------------
+ * List_AddToHead
+ *
+ */
+List_Status_t
+List_AddToHead(
+        const unsigned int ListID,
+        void * const ListInstance_p,
+        List_Element_t * const Element_p)
+{
+#ifdef LIST_STRICT_ARGS
+    if (ListID >= LIST_MAX_NOF_INSTANCES)
+        return LIST_ERROR_BAD_ARGUMENT;
+
+    if (Element_p == NULL)
+        return LIST_ERROR_BAD_ARGUMENT;
+#endif // LIST_STRICT_ARGS
+
+    // Add the element at the list head
+    {
+        List_Element_t * TempElement_p;
+        List_t * List_p;
+
+        if (ListInstance_p)
+            List_p = (List_t*)ListInstance_p;
+        else
+            List_p = &List[ListID];
+
+        TempElement_p           = List_p->Head_p;
+        List_p->Head_p          = Element_p;
+
+        // Previous element in the list, this is a head
+        Element_p->Internal[0]  = NULL;
+
+        // Next element in the list
+        Element_p->Internal[1]  = TempElement_p;
+
+        // Check if this is the first element
+        if (List_p->ElementCount == 0)
+            List_p->Tail_p = List_p->Head_p;
+        else
+            // Link the old head to the new head
+            TempElement_p->Internal[0] = Element_p;
+
+        List_p->ElementCount++;
+    }
+
+    return LIST_STATUS_OK;
+}
+
+
+/*----------------------------------------------------------------------------
+ * List_RemoveFromTail
+ *
+ */
+List_Status_t
+List_RemoveFromTail(
+        const unsigned int ListID,
+        void * const ListInstance_p,
+        List_Element_t ** const Element_pp)
+{
+#ifdef LIST_STRICT_ARGS
+    if (ListID >= LIST_MAX_NOF_INSTANCES)
+        return LIST_ERROR_BAD_ARGUMENT;
+
+    if (Element_pp == NULL)
+        return LIST_ERROR_BAD_ARGUMENT;
+
+#endif // LIST_STRICT_ARGS
+
+    // Remove the element from the list tail
+    {
+        List_Element_t * TempElement_p;
+        List_t * List_p;
+
+        if (ListInstance_p)
+            List_p = (List_t*)ListInstance_p;
+        else
+            List_p = &List[ListID];
+
+#ifdef LIST_STRICT_ARGS
+        if (List_p->ElementCount == 0)
+            return LIST_ERROR_BAD_ARGUMENT;
+#endif // LIST_STRICT_ARGS
+
+        // Get the previous for the tail element in the list
+        TempElement_p = (List_Element_t*)List_p->Tail_p->Internal[0];
+
+        List_p->Tail_p->Internal[0] = NULL;
+        List_p->Tail_p->Internal[1] = NULL;
+        *Element_pp                 = List_p->Tail_p;
+
+        // Set the new tail
+        List_p->Tail_p              = TempElement_p;
+
+        // Check if this is the last element
+        if (List_p->ElementCount == 1)
+            List_p->Head_p = NULL;
+        else
+            // New tail must have no next element
+            List_p->Tail_p->Internal[1] = NULL;
+
+        List_p->ElementCount--;
+    }
+
+    return LIST_STATUS_OK;
+}
+
+
+/*----------------------------------------------------------------------------
+ * List_RemoveAnywhere
+ */
+List_Status_t
+List_RemoveAnywhere(
+        const unsigned int ListID,
+        void * const ListInstance_p,
+        List_Element_t * const Element_p)
+{
+#ifdef LIST_STRICT_ARGS
+    if (ListID >= LIST_MAX_NOF_INSTANCES)
+        return LIST_ERROR_BAD_ARGUMENT;
+
+    if (Element_p == NULL)
+        return LIST_ERROR_BAD_ARGUMENT;
+#endif // LIST_STRICT_ARGS
+
+    // Remove the element from the list tail
+    {
+        List_Element_t * PrevElement_p, * NextElement_p;
+        List_t * List_p;
+
+        if (ListInstance_p)
+            List_p = (List_t*)ListInstance_p;
+        else
+            List_p = &List[ListID];
+
+#ifdef LIST_STRICT_ARGS
+        if (List_p->ElementCount == 0)
+            return LIST_ERROR_BAD_ARGUMENT;
+
+        // Check element belongs to this list
+        {
+            unsigned int i;
+            List_Element_t * TempElement_p = List_p->Head_p;
+
+            for (i = 0; i < List_p->ElementCount; i++)
+            {
+                List_Element_t * p;
+
+                if (TempElement_p == Element_p)
+                    break; // Found
+
+                p = TempElement_p->Internal[1];
+                if (p)
+                    TempElement_p = p; // not end of list yet
+                else
+                    return LIST_ERROR_BAD_ARGUMENT; // Not found
+            }
+
+            if (TempElement_p != Element_p)
+                return LIST_ERROR_BAD_ARGUMENT; // Not found
+        }
+#endif // LIST_STRICT_ARGS
+
+        PrevElement_p = Element_p->Internal[0];
+        NextElement_p = Element_p->Internal[1];
+
+        Element_p->Internal[0] = NULL;
+        Element_p->Internal[1] = NULL;
+
+        if (PrevElement_p)
+            PrevElement_p->Internal[1] = NextElement_p;
+        else
+            List_p->Head_p = NextElement_p;
+
+        if (NextElement_p)
+            NextElement_p->Internal[0] = PrevElement_p;
+        else
+            List_p->Tail_p = PrevElement_p;
+
+        List_p->ElementCount--;
+    }
+
+    return LIST_STATUS_OK;
+}
+
+
+/*----------------------------------------------------------------------------
+ * List_GetListElementCount
+ *
+ */
+List_Status_t
+List_GetListElementCount(
+        const unsigned int ListID,
+        void * const ListInstance_p,
+        unsigned int * const Count_p)
+{
+#ifdef LIST_STRICT_ARGS
+    if (ListID >= LIST_MAX_NOF_INSTANCES)
+        return LIST_ERROR_BAD_ARGUMENT;
+
+    if (Count_p == NULL)
+        return LIST_ERROR_BAD_ARGUMENT;
+#endif // LIST_STRICT_ARGS
+
+    {
+        List_t * List_p;
+
+        if (ListInstance_p)
+            List_p = (List_t*)ListInstance_p;
+        else
+            List_p = &List[ListID];
+
+        *Count_p = List_p->ElementCount;
+    }
+
+    return LIST_STATUS_OK;
+}
+
+
+#ifdef LIST_FULL_API
+/*----------------------------------------------------------------------------
+ * List_RemoveFromHead
+ *
+ */
+List_Status_t
+List_RemoveFromHead(
+        const unsigned int ListID,
+        void * const ListInstance_p,
+        List_Element_t ** const Element_pp)
+{
+    List_t * List_p;
+
+    if (ListInstance_p)
+        List_p = (List_t*)ListInstance_p;
+    else
+        List_p = &List[ListID];
+
+#ifdef LIST_STRICT_ARGS
+    if (ListID >= LIST_MAX_NOF_INSTANCES)
+        return LIST_ERROR_BAD_ARGUMENT;
+
+    if (Element_pp == NULL)
+        return LIST_ERROR_BAD_ARGUMENT;
+
+    if (List_p->ElementCount == 0)
+        return LIST_ERROR_BAD_ARGUMENT;
+#endif // LIST_STRICT_ARGS
+
+    // Remove the element from the list head
+    {
+        List_Element_t * TempElement_p;
+
+        // Get the next for the head element in the list
+        TempElement_p = (List_Element_t*)List_p->Head_p->Internal[1];
+
+        List_p->Head_p->Internal[0] = NULL;
+        List_p->Head_p->Internal[1] = NULL;
+        *Element_pp                 = List_p->Head_p;
+
+        List_p->Head_p              = TempElement_p;
+
+        // Check if this is the last element
+        if (List_p->ElementCount == 1)
+            List_p->Tail_p = NULL;
+        else
+            List_p->Head_p->Internal[0] = NULL;
+
+        List_p->ElementCount--;
+    }
+
+    return LIST_STATUS_OK;
+}
+
+
+/*----------------------------------------------------------------------------
+ * List_GetHead
+ */
+List_Status_t
+List_GetHead(
+        const unsigned int ListID,
+        void * const ListInstance_p,
+        const List_Element_t ** const Element_pp)
+{
+#ifdef LIST_STRICT_ARGS
+    if (ListID >= LIST_MAX_NOF_INSTANCES)
+        return LIST_ERROR_BAD_ARGUMENT;
+
+    if (Element_pp == NULL)
+        return LIST_ERROR_BAD_ARGUMENT;
+#endif // LIST_STRICT_ARGS
+
+    // Get the list head
+    {
+        List_t * List_p;
+
+        if (ListInstance_p)
+            List_p = (List_t*)ListInstance_p;
+        else
+            List_p = &List[ListID];
+
+        *Element_pp = List_p->Head_p;
+    }
+
+    return LIST_STATUS_OK;
+}
+#endif // LIST_FULL_API
+
+
+/*----------------------------------------------------------------------------
+ * List_GetInstanceByteCount
+ *
+ * Gets the memory size of the list instance (in bytes) excluding the list
+ * elements memory size. This list memory size can be used to allocate a list
+ * instance and pass a pointer to it subsequently to the List_*() functions.
+ *
+ * This function is re-entrant and can be called any time.
+ *
+ * Return Values
+ *     Size of the list administration memory in bytes.
+ */
+unsigned int
+List_GetInstanceByteCount(void)
+{
+    return sizeof(List_t);
+}
+
+
+/* end of file list.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/log/log.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/log/log.c
new file mode 100644
index 0000000..84473f9
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/log/log.c
@@ -0,0 +1,128 @@
+/* log.c
+ *
+ * Log implementation for specific environment
+ */
+
+/*****************************************************************************
+* Copyright (c) 2008-2020 by Rambus, Inc. and/or its subsidiaries.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+#define LOG_SEVERITY_MAX  LOG_SEVERITY_NO_OUTPUT
+
+// Logging API
+#include "log.h"            // the API to implement
+
+
+/*----------------------------------------------------------------------------
+ * Log_HexDump
+ *
+ * This function logs Hex Dump of a Buffer
+ *
+ * szPrefix
+ *     Prefix to be printed on every row.
+ *
+ * PrintOffset
+ *     Offset value that is printed at the start of every row. Can be used
+ *     when the byte printed are located at some offset in another buffer.
+ *
+ * Buffer_p
+ *     Pointer to the start of the array of bytes to hex dump.
+ *
+ * ByteCount
+ *     Number of bytes to include in the hex dump from Buffer_p.
+ *
+ * Return Value
+ *     None.
+ */
+void
+Log_HexDump(
+        const char * szPrefix_p,
+        const unsigned int PrintOffset,
+        const uint8_t * Buffer_p,
+        const unsigned int ByteCount)
+{
+    unsigned int i;
+
+    for(i = 0; i < ByteCount; i += 16)
+    {
+        unsigned int j, Limit;
+
+        // if we do not have enough data for a full line
+        if (i + 16 > ByteCount)
+            Limit = ByteCount - i;
+        else
+            Limit = 16;
+
+        Log_FormattedMessage("%s %08d:", szPrefix_p, PrintOffset + i);
+
+        for (j = 0; j < Limit; j++)
+            Log_FormattedMessage(" %02X", Buffer_p[i+j]);
+
+        Log_FormattedMessage("\n");
+    } // for
+}
+
+
+/*----------------------------------------------------------------------------
+ * Log_HexDump32
+ *
+ * This function logs Hex Dump of an array of 32-bit words
+ *
+ * szPrefix
+ *     Prefix to be printed on every row.
+ *
+ * PrintOffset
+ *     Offset value that is printed at the start of every row. Can be used
+ *     when the byte printed are located at some offset in another buffer.
+ *
+ * Buffer_p
+ *     Pointer to the start of the array of 32-bit words to hex dump.
+ *
+ * Word32Count
+ *     Number of 32-bit words to include in the hex dump from Buffer_p.
+ *
+ * Return Value
+ *     None.
+ */
+void
+Log_HexDump32(
+        const char * szPrefix_p,
+        const unsigned int PrintOffset,
+        const uint32_t * Buffer_p,
+        const unsigned int Word32Count)
+{
+    unsigned int i;
+
+    for(i = 0; i < Word32Count; i += 4)
+    {
+        unsigned int j, Limit;
+
+        // if we do not have enough data for a full line
+        if (i + 4 > Word32Count)
+            Limit = Word32Count - i;
+        else
+            Limit = 4;
+
+        Log_FormattedMessage("%s %08d:", szPrefix_p, PrintOffset + i*4);
+
+        for (j = 0; j < Limit; j++)
+            Log_FormattedMessage(" %08X", Buffer_p[i+j]);
+
+        Log_FormattedMessage("\n");
+    } // for
+}
+
+/* end of file log.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/ring/ringhelper.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/ring/ringhelper.c
new file mode 100644
index 0000000..fd04cd3
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/ring/ringhelper.c
@@ -0,0 +1,484 @@
+/* ringhelper.c
+ *
+ * Ring Helper Library implementation.
+ */
+
+/*****************************************************************************
+* Copyright (c) 2008-2020 by Rambus, Inc. and/or its subsidiaries.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+#include "c_ringhelper.h"  // configuration options
+
+#include "basic_defs.h"     // bool, MIN
+#include "ringhelper.h"     // API to implement
+#include "clib.h"           // memset
+
+
+/*----------------------------------------------------------------------------
+ * RingHelper_Init
+ *
+ * This routine must be called once to initialize the administration block
+ * related to a ring.
+ *
+ * See header file for function specification.
+ */
+int
+RingHelper_Init(
+        volatile RingHelper_t * const Ring_p,
+        volatile const RingHelper_CallbackInterface_t * const CallbackIF_p,
+        const bool fSeparateRings,
+        const unsigned int CommandRing_MaxDescriptors,
+        const unsigned int ResultRing_MaxDescriptors)
+{
+#ifdef RINGHELPER_STRICT_ARGS
+    if (Ring_p == NULL ||
+        CallbackIF_p == NULL ||
+        CommandRing_MaxDescriptors < 1)
+    {
+        // invalid argument
+        return -1;
+    }
+
+    if (fSeparateRings)
+    {
+#ifdef RINGHELPER_REMOVE_SEPARATE_RING_SUPPORT
+        // not supported
+        return -1;
+#else
+        if (ResultRing_MaxDescriptors < 1)
+        {
+            // invalid arguments
+            return -1;
+        }
+#endif
+    }
+
+    if (CallbackIF_p->ReadFunc_p == NULL ||
+        CallbackIF_p->WriteFunc_p == NULL)
+    {
+        return -1;
+    }
+
+#ifndef RINGHELPER_REMOVE_STATUSFUNC
+    if (CallbackIF_p->StatusFunc_p == NULL)
+    {
+        return -1;
+    }
+#endif
+
+#endif /* RINGHELPER_STRICT_ARGS */
+
+    Ring_p->CB = *CallbackIF_p;
+    Ring_p->fSupportsDeviceReadPos = true;      // initial assumption
+    Ring_p->IN_Size = CommandRing_MaxDescriptors;
+    Ring_p->IN_Tail = 0;
+    Ring_p->OUT_Head = 0;
+
+#ifndef RINGHELPER_REMOVE_SEPARATE_RING_SUPPORT
+    if (fSeparateRings)
+    {
+        // separate rings
+        Ring_p->fSeparate = true;
+        Ring_p->OUT_Size = ResultRing_MaxDescriptors;
+    }
+    else
+#endif /* !RINGHELPER_REMOVE_SEPARATE_RING_SUPPORT */
+    {
+        // combined rings
+        Ring_p->fSeparate = false;
+        Ring_p->OUT_Size = CommandRing_MaxDescriptors;
+    }
+
+    return 0;   // success
+}
+
+
+/*----------------------------------------------------------------------------
+ * RingHelper_Put
+ *
+ * This function tries to add a number of descriptors to the command ring
+ * specified.
+ *
+ * See header file for function specification.
+ */
+int
+RingHelper_Put(
+        volatile RingHelper_t * const Ring_p,
+        const void * Descriptors_p,
+        const int DescriptorCount)
+{
+    int A, N, W1, W2;
+
+#ifdef RINGHELPER_STRICT_ARGS
+    if (Ring_p == NULL ||
+        Descriptors_p == NULL ||
+        DescriptorCount < 0)
+    {
+        return -1;
+    }
+#endif /* RINGHELPER_STRICT_ARGS */
+
+    if (DescriptorCount == 0)
+        return 0;
+
+    W2 = 0;
+
+#ifndef RINGHELPER_REMOVE_SEPARATE_RING_SUPPORT
+    // out of the descriptors provided, calculate the maximum number of
+    // descriptors that can be written sequentially before the ring is full.
+    if (Ring_p->fSeparate)
+    {
+        // separate rings
+
+        // ask how far the device has processed the ring
+        // we do this on every call and do not cache the result
+        int DeviceReadHead = -1;    // not supported
+
+#ifndef RINGHELPER_REMOVE_STATUSFUNC
+        if (Ring_p->fSupportsDeviceReadPos)
+        {
+            int res;
+
+            res = Ring_p->CB.StatusFunc_p(
+                                 Ring_p->CB.CallbackParam1_p,
+                                 Ring_p->CB.CallbackParam2,
+                                 &DeviceReadHead);
+
+            if (res < 0)
+                return res;     // ## RETURN ##
+
+            // suppress these calls if the device does not support it
+            if (DeviceReadHead < 0)
+                Ring_p->fSupportsDeviceReadPos = false;
+        }
+#endif /* !RINGHELPER_REMOVE_STATUSFUNC */
+
+        if (DeviceReadHead < 0)
+        {
+            // device does not expose its read position
+            // this means we cannot calculate how much space is available
+            // the WriteFunc will have to check, descriptor by descriptor
+            A = Ring_p->IN_Size;
+
+            // note: under this condition we rely on the implementation of
+            // the callback interface to handle ring-full condition and not
+            // overwrite existing descriptors. Because of this, we can
+            // fill the ring to the limit and do not have to keep 1 free
+            // position as done below.
+        }
+        else
+        {
+            unsigned int Device_IN_Head = (unsigned int)DeviceReadHead;
+
+            // based on the device read position we can calculate
+            // how many positions in the ring are free
+            if (Ring_p->IN_Tail < Device_IN_Head)
+            {
+                // we have wrapped around
+                // available space is between the two
+                A = Device_IN_Head - Ring_p->IN_Tail;
+            }
+            else
+            {
+                // used positions are between the two pointers
+                // rest is free
+                A = Ring_p->IN_Size - (Ring_p->IN_Tail - Device_IN_Head);
+            }
+
+            // avoid filling the entire ring
+            // so we can differentiate full from empty
+            if (A != 0)
+                A--;
+        }
+    }
+    else
+#endif /* !RINGHELPER_REMOVE_SEPARATE_RING_SUPPORT */
+    {
+        // combined rings
+
+        // Critical: we have to be careful not to read the OUT_Head more
+        //           than one, since it might change in between!
+        unsigned int OUT_Head_copy = Ring_p->OUT_Head;
+
+        // we can write descriptors up to the point where we expect the
+        // result descriptors
+        if (Ring_p->IN_Tail < OUT_Head_copy)
+        {
+            // used positions are around the wrap point
+            // free positions are between the pointers
+            A = OUT_Head_copy - Ring_p->IN_Tail;
+        }
+        else
+        {
+            // used positions are between the two pointers
+            // rest is free
+            A = Ring_p->IN_Size - (Ring_p->IN_Tail - OUT_Head_copy);
+        }
+
+        // avoid filling the entire ring
+        // so we can differentiate full from empty
+        // (when it contains all commands or all results)
+        if (A != 0)
+            A--;
+    }
+
+    // limit based on provided descriptors
+    A = MIN(A, DescriptorCount);
+
+    // limit for sequential writing
+    N = MIN(A, (int)(Ring_p->IN_Size - Ring_p->IN_Tail));
+
+    // bail out early if there is no space
+    if (N == 0)
+    {
+        return 0;       // ## RETURN ##
+    }
+
+    W1 = Ring_p->CB.WriteFunc_p(
+                        Ring_p->CB.CallbackParam1_p,
+                        Ring_p->CB.CallbackParam2,
+                        /*WriteIndex:*/Ring_p->IN_Tail,
+                        /*WriteCount:*/N,
+                        /*AvailableSpace*/A,
+                        Descriptors_p,
+                        DescriptorCount,
+                        /*SkipCount:*/0);
+
+    if (W1 <= 0)
+    {
+        //  0: no descriptors could be added
+        // <0: failure
+        return W1;      // ## RETURN ##
+    }
+
+    if (W1 == N &&
+        W1 < DescriptorCount &&
+        A > N)
+    {
+        // we have written all possible positions up to the end of the ring
+        // now write the rest
+        N = A - N;
+
+        W2 = Ring_p->CB.WriteFunc_p(
+                            Ring_p->CB.CallbackParam1_p,
+                            Ring_p->CB.CallbackParam2,
+                            /*WriteIndex:*/0,
+                            /*WriteCount:*/N,
+                            /*AvailableSpace*/N,
+                            Descriptors_p,
+                            DescriptorCount,
+                            /*SkipCount:*/W1);
+
+        if (W2 < 0)
+        {
+            // failure
+            return W2;      // ## RETURN ##
+        }
+    }
+
+    // now update the position for the next write
+    {
+        unsigned int i = Ring_p->IN_Tail + W1 + W2;
+
+        // do not use % operator to avoid costly divisions
+        if (i >= Ring_p->IN_Size)
+            i -= Ring_p->IN_Size;
+
+        Ring_p->IN_Tail = i;
+    }
+
+    // return how many descriptors were added
+    return W1 + W2;
+}
+
+
+/*----------------------------------------------------------------------------
+ * RingHelper_Get
+ *
+ * This routine retrieves a number of descriptors from the result ring
+ * specified.
+ *
+ * See header file for function specification.
+ */
+int
+RingHelper_Get(
+        volatile RingHelper_t * const Ring_p,
+        const int ReadyCount,
+        void * Descriptors_p,
+        const int DescriptorsLimit)
+{
+    int A, N;
+    int R1, R2;
+
+    R2 = 0;
+
+#ifdef RINGHELPER_STRICT_ARGS
+    if (Ring_p == NULL ||
+        Descriptors_p == NULL ||
+        DescriptorsLimit < 0)
+    {
+        return -1;
+    }
+#endif /* RINGHELPER_STRICT_ARGS */
+
+    if (DescriptorsLimit == 0 ||
+        ReadyCount == 0)
+    {
+        // no space in output buffer
+        // or no descriptors ready
+        return 0;
+    }
+
+    // calculate the maximum number of descriptors that can be retrieved
+    // sequentially from this read position, taking into account the
+    // DescriptorsLimit and the ReadyCount (if available)
+
+    // A = entries in result ring from read position till end
+    A = Ring_p->OUT_Size - Ring_p->OUT_Head;
+
+    N = MIN(A, DescriptorsLimit);
+
+    if (ReadyCount > 0)
+        N = MIN(N, ReadyCount);
+
+    // now retrieve this number of descriptors
+    R1 = Ring_p->CB.ReadFunc_p(
+                        Ring_p->CB.CallbackParam1_p,
+                        Ring_p->CB.CallbackParam2,
+                        /*ReadIndex:*/Ring_p->OUT_Head,
+                        /*ReadLimit:*/N,
+                        Descriptors_p,
+                        /*SkipCount:*/0);
+
+    if (R1 <= 0)
+    {
+        //  0: if we got nothing on the first call, we can stop here
+        // <0: error while reading
+        //     this means we cannot maintain read synchronization
+
+        return R1;      // ## RETURN ##
+    }
+
+    // if we got the maximum, we can try to read more
+    // after wrapping to the start of the buffer
+    if (R1 == N &&
+        R1 < DescriptorsLimit &&
+        R1 != ReadyCount)
+    {
+        // A = number of entries in ring up to previous read-start position
+        A = Ring_p->OUT_Head;
+
+        N = MIN(A, DescriptorsLimit - R1);
+
+        if (ReadyCount > 0)
+            N = MIN(N, ReadyCount - R1);
+
+        R2 = Ring_p->CB.ReadFunc_p(
+                            Ring_p->CB.CallbackParam1_p,
+                            Ring_p->CB.CallbackParam2,
+                            /*ReadIndex:*/0,        // start of buffer
+                            /*ReadLimit:*/N,
+                            Descriptors_p,
+                            /*SkipCount:*/R1);
+
+        if (R2 < 0)
+        {
+            // failure
+            return R2;      // ## RETURN ##
+        }
+    }
+
+    // now update the position for the next read
+    {
+        unsigned int i = Ring_p->OUT_Head + R1 + R2;
+
+        // do not use % operator to avoid costly divisions
+        if (i >= Ring_p->OUT_Size)
+            i -= Ring_p->OUT_Size;
+
+        Ring_p->OUT_Head = i;
+    }
+
+    // return the number of descriptors read
+    return R1 + R2;
+}
+
+
+/*----------------------------------------------------------------------------
+ * RingHelper_FillLevel_Get
+ *
+ * This function return a number of filled (used) descriptors in the ring
+ * specified.
+ *
+ * See header file for function specification.
+ */
+int
+RingHelper_FillLevel_Get(
+        volatile RingHelper_t * const Ring_p)
+{
+#ifdef RINGHELPER_STRICT_ARGS
+    if (Ring_p == NULL)
+    {
+        return -1;
+    }
+#endif /* RINGHELPER_STRICT_ARGS */
+
+#ifndef RINGHELPER_REMOVE_SEPARATE_RING_SUPPORT
+    // out of the descriptors provided, calculate the maximum number of
+    // descriptors that can be written sequentially before the ring is full.
+    if (Ring_p->fSeparate)
+    {
+        // separate rings
+
+        return -1; // not implemented
+    }
+    else
+#endif  /* !RINGHELPER_REMOVE_SEPARATE_RING_SUPPORT */
+    {
+        // combined rings
+
+        unsigned int FillLevel;
+        unsigned int OUT_Head_copy;
+
+        // Critical: we have to be careful not to read the OUT_Head more
+        //           than one, since it might change in between!
+        OUT_Head_copy = Ring_p->OUT_Head;
+
+        if (Ring_p->IN_Tail < OUT_Head_copy)
+        {
+            // used positions are around the wrap point
+            // free positions are between the pointers
+            FillLevel = Ring_p->IN_Size - (OUT_Head_copy - Ring_p->IN_Tail);
+        }
+        else
+        {
+            // used positions are between the two pointers
+            // rest is free
+            FillLevel = Ring_p->IN_Tail - OUT_Head_copy;
+        }
+
+        // avoid filling the entire ring
+        // so we can differentiate full from empty
+        // (when it contains all commands or all results)
+        if (FillLevel < Ring_p->IN_Size)
+            FillLevel++;
+
+        return (int)FillLevel;
+    }
+}
+
+
+/* end of file ringhelper.c */