From: yhe <y...@sonicwall.com>

---
/** Email created from pull request 470 (SonicwallYhe:api-next-seperate)
 ** https://github.com/Linaro/odp/pull/470
 ** Patch: https://github.com/Linaro/odp/pull/470.patch
 ** Base sha: af7be638ef9ac98bdb1f2e4917f152889eb1850f
 ** Merge commit sha: f30e7ae4157bae994d5734b8917d2dd31dbf201e
 **/
 platform/linux-generic/odp_crypto.c | 164 ++++++++++++++++++++++++++++++++++++
 1 file changed, 164 insertions(+)

diff --git a/platform/linux-generic/odp_crypto.c 
b/platform/linux-generic/odp_crypto.c
index 5579ade5b..16ec25d67 100644
--- a/platform/linux-generic/odp_crypto.c
+++ b/platform/linux-generic/odp_crypto.c
@@ -36,6 +36,9 @@
 
 #define MAX_SESSIONS 32
 
+#define AES_BLOCK_SIZE 16
+typedef uint32_t aes_block[4];
+
 /*
  * Cipher algorithm capabilities
  *
@@ -95,10 +98,18 @@ static const odp_crypto_auth_capability_t 
auth_capa_sha256_hmac[] = {
 {.digest_len = 16, .key_len = 32, .aad_len = {.min = 0, .max = 0, .inc = 0} },
 {.digest_len = 32, .key_len = 32, .aad_len = {.min = 0, .max = 0, .inc = 0} } 
};
 
+static const odp_crypto_auth_capability_t auth_capa_sha384_hmac[] = {
+{.digest_len = 24, .key_len = 48, .aad_len = {.min = 0, .max = 0, .inc = 0} },
+{.digest_len = 48, .key_len = 48, .aad_len = {.min = 0, .max = 0, .inc = 0} } 
};
+
 static const odp_crypto_auth_capability_t auth_capa_sha512_hmac[] = {
 {.digest_len = 32, .key_len = 64, .aad_len = {.min = 0, .max = 0, .inc = 0} },
 {.digest_len = 64, .key_len = 64, .aad_len = {.min = 0, .max = 0, .inc = 0} } 
};
 
+static const odp_crypto_auth_capability_t auth_capa_aes_xcbc[] = {
+{.digest_len = 12, .key_len = 16, .aad_len = {.min = 0, .max = 0, .inc = 0} },
+{.digest_len = 16, .key_len = 16, .aad_len = {.min = 0, .max = 0, .inc = 0} } 
};
+
 static const odp_crypto_auth_capability_t auth_capa_aes_gcm[] = {
 {.digest_len = 16, .key_len = 0, .aad_len = {.min = 8, .max = 12, .inc = 4} } 
};
 
@@ -308,6 +319,142 @@ void packet_hmac(odp_packet_t pkt,
        HMAC_Final(ctx, hash, NULL);
 }
 
+static void do_pad_xor(uint8_t *out, const uint8_t *in, int len) {
+       int pos=0;
+       for (pos=1; pos <= 16; pos++, in++, out++) {
+               if (pos <= len)
+                       *out ^= *in;
+               if (pos > len) {
+                       *out ^= 0x80;
+                       break;
+               }
+       }
+}
+static void xor_block(aes_block res, const aes_block op) {
+       res[0] ^= op[0];
+       res[1] ^= op[1];
+       res[2] ^= op[2];
+       res[3] ^= op[3];
+}
+
+static
+odp_crypto_alg_err_t aesxcbc_gen(odp_packet_t pkt,
+                             const odp_crypto_packet_op_param_t *param,
+                             odp_crypto_generic_session_t *session)
+{
+       aes_block e = {0, 0, 0, 0};
+       uint8_t *data  = odp_packet_data(pkt);
+       uint8_t *icv   = data;
+       uint32_t len = param->auth_range.length;
+       uint8_t  hash_out[16];
+       EVP_CIPHER_CTX *ctx;
+       int dummy_len = 0;
+       /* Adjust pointer for beginning of area to auth */
+       data += param->auth_range.offset;
+       icv  += param->hash_result_offset;
+
+       ctx = EVP_CIPHER_CTX_new();
+       EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, session->auth.key, 
NULL);
+       for (; len > AES_BLOCK_SIZE ; len -= AES_BLOCK_SIZE) {
+               xor_block(e, (const uint32_t*) data);
+               EVP_EncryptUpdate(ctx, (uint8_t *)e, &dummy_len, (uint8_t *)e, 
sizeof(e));
+               data += AES_BLOCK_SIZE;
+       }
+       do_pad_xor((uint8_t *)e, data, len);
+       if (len == AES_BLOCK_SIZE) {
+               xor_block(e, (const uint32_t*) (session->auth.key + 16));
+       }
+       else
+       {
+               xor_block(e, (const uint32_t*) (session->auth.key + 16*2));
+       }
+       EVP_EncryptUpdate(ctx, hash_out, &dummy_len, (uint8_t *)e, sizeof(e));
+       EVP_CIPHER_CTX_free(ctx);       
+       memcpy (icv, hash_out, 12);
+       
+       return ODP_CRYPTO_ALG_ERR_NONE;
+}
+
+static
+odp_crypto_alg_err_t aesxcbc_check(odp_packet_t pkt,
+                             const odp_crypto_packet_op_param_t *param,
+                             odp_crypto_generic_session_t *session)
+{
+       aes_block e = {0, 0, 0, 0};
+       uint8_t *data  = odp_packet_data(pkt);
+       uint8_t *icv   = data;
+       uint32_t len = param->auth_range.length;
+       uint8_t  hash_in[12];
+       uint8_t  hash_out[12];
+       EVP_CIPHER_CTX *ctx;
+       int dummy_len = 0;
+       
+       /* Adjust pointer for beginning of area to auth */
+       data += param->auth_range.offset;
+       icv  += param->hash_result_offset;
+       
+       /* Copy current value out and clear it before authentication */
+       memset(hash_in, 0, sizeof(hash_in));
+       memcpy(hash_in, icv, 12);
+       memset(hash_out, 0, sizeof(hash_out));
+
+       ctx = EVP_CIPHER_CTX_new();
+       EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, session->auth.key, 
NULL);
+
+       for (; len > AES_BLOCK_SIZE ; len -= AES_BLOCK_SIZE) {
+               xor_block(e, (const uint32_t*) data);
+               EVP_EncryptUpdate(ctx, (uint8_t *)e, &dummy_len, (uint8_t *)e, 
sizeof(e));
+               data += AES_BLOCK_SIZE;
+       }
+       do_pad_xor((uint8_t *)e, data, len);
+       if (len == AES_BLOCK_SIZE) {
+               xor_block(e, (const uint32_t*) (session->auth.key + 16));
+       }
+       else
+       {
+               xor_block(e, (const uint32_t*) (session->auth.key + 16*2));
+       }
+       EVP_EncryptUpdate(ctx, hash_out, &dummy_len, (uint8_t *)e, sizeof(e));
+       EVP_CIPHER_CTX_free(ctx);       
+       /* Verify match */
+       if (0 != memcmp(hash_in, hash_out, 12))
+               return ODP_CRYPTO_ALG_ERR_ICV_CHECK;
+
+       /* Matched */
+       return ODP_CRYPTO_ALG_ERR_NONE;
+}      
+
+static int process_aesxcbc_param(odp_crypto_generic_session_t *session)
+{
+       aes_block kn[3] = {
+               { 0x01010101, 0x01010101, 0x01010101, 0x01010101 },
+               { 0x02020202, 0x02020202, 0x02020202, 0x02020202 },
+               { 0x03030303, 0x03030303, 0x03030303, 0x03030303 },
+       };
+       EVP_CIPHER_CTX *ctx;
+       int dummy_len = 0;
+       
+       /* Set function */
+       if (ODP_CRYPTO_OP_ENCODE == session->p.op)
+               session->auth.func = aesxcbc_gen;
+       else
+               session->auth.func = aesxcbc_check;
+
+       ctx = EVP_CIPHER_CTX_new();
+       EVP_EncryptInit_ex(ctx, EVP_aes_128_ecb(), NULL, 
session->p.auth_key.data, NULL);
+       /*  K1 = 0x01010101010101010101010101010101 encrypted with Key K */
+       EVP_EncryptUpdate(ctx, session->auth.key, &dummy_len, (uint8_t *)kn[0], 
16);
+
+       /*  K2 = 0x02020202020202020202020202020202 encrypted with Key K */
+       EVP_EncryptUpdate(ctx, session->auth.key+16, &dummy_len, (uint8_t 
*)kn[1], 16);
+       
+       /*  K3 = 0x03030303030303030303030303030303 encrypted with Key K */
+       EVP_EncryptUpdate(ctx, session->auth.key+16*2, &dummy_len, (uint8_t 
*)kn[2], 16);       
+
+       EVP_CIPHER_CTX_free(ctx);       
+       return 0;
+}
+
 static
 odp_crypto_alg_err_t auth_hmac_gen(odp_packet_t pkt,
                                   const odp_crypto_packet_op_param_t *param,
@@ -1152,7 +1299,9 @@ int odp_crypto_capability(odp_crypto_capability_t *capa)
        capa->auths.bit.md5_hmac     = 1;
        capa->auths.bit.sha1_hmac    = 1;
        capa->auths.bit.sha256_hmac  = 1;
+       capa->auths.bit.sha384_hmac  = 1;
        capa->auths.bit.sha512_hmac  = 1;
+       capa->auths.bit.aes_xcbc_mac = 1;
        capa->auths.bit.aes_gcm      = 1;
        capa->auths.bit.aes_ccm      = 1;
        capa->auths.bit.aes_gmac     = 1;
@@ -1249,10 +1398,18 @@ int odp_crypto_auth_capability(odp_auth_alg_t auth,
                src = auth_capa_sha256_hmac;
                num = sizeof(auth_capa_sha256_hmac) / size;
                break;
+       case ODP_AUTH_ALG_SHA384_HMAC:
+               src = auth_capa_sha384_hmac;
+               num = sizeof(auth_capa_sha384_hmac) / size;
+               break;
        case ODP_AUTH_ALG_SHA512_HMAC:
                src = auth_capa_sha512_hmac;
                num = sizeof(auth_capa_sha512_hmac) / size;
                break;
+       case ODP_AUTH_ALG_AES_XCBC_MAC:
+               src = auth_capa_aes_xcbc;
+               num = sizeof(auth_capa_aes_xcbc) / size;
+               break;
        case ODP_AUTH_ALG_AES_GCM:
                src = auth_capa_aes_gcm;
                num = sizeof(auth_capa_aes_gcm) / size;
@@ -1462,9 +1619,16 @@ odp_crypto_session_create(odp_crypto_session_param_t 
*param,
        case ODP_AUTH_ALG_SHA256_HMAC:
                rc = process_auth_hmac_param(session, EVP_sha256());
                break;
+       case ODP_AUTH_ALG_SHA384_HMAC:
+               rc = process_auth_hmac_param(session, EVP_sha384());
+               break;
        case ODP_AUTH_ALG_SHA512_HMAC:
                rc = process_auth_hmac_param(session, EVP_sha512());
                break;
+
+       case ODP_AUTH_ALG_AES_XCBC_MAC:
+               rc = process_aesxcbc_param(session);
+               break;
 #if ODP_DEPRECATED_API
        case ODP_AUTH_ALG_AES128_GCM:
                if (param->cipher_alg == ODP_CIPHER_ALG_AES128_GCM)

Reply via email to