X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fcrypto%2Fdpaa_sec%2Fdpaa_sec.h;h=2cd50cc8dda7272368d0b04bce8b9e9a4b9951af;hb=135ccbc6a753c8306d3807abc9de3ed8989e8db2;hp=af3f2550b20419bcb23c704072d4e07f2726f943;hpb=c3e85bdcc6e68323fd908bfa4304052c03ba4eb7;p=dpdk.git diff --git a/drivers/crypto/dpaa_sec/dpaa_sec.h b/drivers/crypto/dpaa_sec/dpaa_sec.h index af3f2550b2..2cd50cc8dd 100644 --- a/drivers/crypto/dpaa_sec/dpaa_sec.h +++ b/drivers/crypto/dpaa_sec/dpaa_sec.h @@ -1,46 +1,26 @@ -/*- - * BSD LICENSE +/* SPDX-License-Identifier: BSD-3-Clause * - * Copyright 2016 NXP. + * Copyright 2016-2020 NXP * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of NXP nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _DPAA_SEC_H_ #define _DPAA_SEC_H_ +#define CRYPTODEV_NAME_DPAA_SEC_PMD crypto_dpaa_sec +/**< NXP DPAA - SEC PMD device name */ + +#define MAX_DPAA_CORES 4 #define NUM_POOL_CHANNELS 4 -#define DPAA_SEC_BURST 32 +#define DPAA_SEC_BURST 7 #define DPAA_SEC_ALG_UNSUPPORT (-1) #define TDES_CBC_IV_LEN 8 #define AES_CBC_IV_LEN 16 #define AES_CTR_IV_LEN 16 #define AES_GCM_IV_LEN 12 +#define DPAA_IPv6_DEFAULT_VTC_FLOW 0x60000000 + /* Minimum job descriptor consists of a oneword job descriptor HEADER and * a pointer to the shared descriptor. */ @@ -49,6 +29,7 @@ #define CTX_POOL_NUM_BUFS 32000 #define CTX_POOL_BUF_SIZE sizeof(struct dpaa_sec_op_ctx) #define CTX_POOL_CACHE_SIZE 512 +#define RTE_DPAA_SEC_PMD_MAX_NB_SESSIONS 1024 #define DIR_ENC 1 #define DIR_DEC 0 @@ -57,44 +38,19 @@ enum dpaa_sec_op_type { DPAA_SEC_NONE, /*!< No Cipher operations*/ DPAA_SEC_CIPHER,/*!< CIPHER operations */ DPAA_SEC_AUTH, /*!< Authentication Operations */ - DPAA_SEC_AEAD, /*!< Authenticated Encryption with associated data */ + DPAA_SEC_AEAD, /*!< AEAD (AES-GCM/CCM) type operations */ + DPAA_SEC_CIPHER_HASH, /*!< Authenticated Encryption with + * associated data + */ + DPAA_SEC_HASH_CIPHER, /*!< Encryption with Authenticated + * associated data + */ DPAA_SEC_IPSEC, /*!< IPSEC protocol operations*/ DPAA_SEC_PDCP, /*!< PDCP protocol operations*/ DPAA_SEC_PKC, /*!< Public Key Cryptographic Operations */ DPAA_SEC_MAX }; -typedef struct dpaa_sec_session_entry { - uint8_t dir; /*!< Operation Direction */ - enum rte_crypto_cipher_algorithm cipher_alg; /*!< Cipher Algorithm*/ - enum rte_crypto_auth_algorithm auth_alg; /*!< Authentication Algorithm*/ - enum rte_crypto_aead_algorithm aead_alg; /*!< Authentication Algorithm*/ - union { - struct { - uint8_t *data; /**< pointer to key data */ - size_t length; /**< key length in bytes */ - } aead_key; - struct { - struct { - uint8_t *data; /**< pointer to key data */ - size_t length; /**< key length in bytes */ - } cipher_key; - struct { - uint8_t *data; /**< pointer to key data */ - size_t length; /**< key length in bytes */ - } auth_key; - }; - }; - struct { - uint16_t length; - uint16_t offset; - } iv; /**< Initialisation vector parameters */ - uint16_t auth_only_len; /*!< Length of data for Auth only */ - uint32_t digest_length; - struct dpaa_sec_qp *qp; - struct rte_mempool *ctx_pool; /* session mempool for dpaa_sec_op_ctx */ -} dpaa_sec_session; - #define DPAA_SEC_MAX_DESC_SIZE 64 /* code or cmd block to caam */ struct sec_cdb { @@ -142,12 +98,85 @@ struct sec_cdb { uint32_t sh_desc[DPAA_SEC_MAX_DESC_SIZE]; }; +#ifdef RTE_LIBRTE_SECURITY +/*! + * The structure is to be filled by user as a part of + * dpaa_sec_proto_ctxt for PDCP Protocol + */ +struct sec_pdcp_ctxt { + enum rte_security_pdcp_domain domain; /*!< Data/Control mode*/ + int8_t bearer; /*!< PDCP bearer ID */ + int8_t pkt_dir;/*!< PDCP Frame Direction 0:UL 1:DL*/ + int8_t hfn_ovd;/*!< Overwrite HFN per packet*/ + uint8_t sn_size; /*!< Sequence number size, 5/7/12/15/18 */ + uint32_t hfn_ovd_offset;/*!< offset from rte_crypto_op at which + * per packet hfn is stored + */ + uint32_t hfn; /*!< Hyper Frame Number */ + uint32_t hfn_threshold; /*!< HFN Threashold for key renegotiation */ +}; +#endif +typedef struct dpaa_sec_session_entry { + struct sec_cdb cdb; /**< cmd block associated with qp */ + struct dpaa_sec_qp *qp[MAX_DPAA_CORES]; + struct qman_fq *inq[MAX_DPAA_CORES]; + uint8_t dir; /*!< Operation Direction */ + uint8_t ctxt; /*!< Session Context Type */ + enum rte_crypto_cipher_algorithm cipher_alg; /*!< Cipher Algorithm*/ + enum rte_crypto_auth_algorithm auth_alg; /*!< Authentication Algorithm*/ + enum rte_crypto_aead_algorithm aead_alg; /*!< AEAD Algorithm*/ +#ifdef RTE_LIBRTE_SECURITY + enum rte_security_session_protocol proto_alg; /*!< Security Algorithm*/ +#endif + union { + struct { + uint8_t *data; /**< pointer to key data */ + size_t length; /**< key length in bytes */ + uint32_t alg; + uint32_t algmode; + } aead_key; + struct { + struct { + uint8_t *data; /**< pointer to key data */ + size_t length; /**< key length in bytes */ + uint32_t alg; + uint32_t algmode; + } cipher_key; + struct { + uint8_t *data; /**< pointer to key data */ + size_t length; /**< key length in bytes */ + uint32_t alg; + uint32_t algmode; + } auth_key; + }; + }; + union { + struct { + struct { + uint16_t length; + uint16_t offset; + } iv; /**< Initialisation vector parameters */ + uint16_t auth_only_len; + /*!< Length of data for Auth only */ + uint32_t digest_length; + struct ipsec_decap_pdb decap_pdb; + struct ipsec_encap_pdb encap_pdb; + union { + struct ip ip4_hdr; + struct rte_ipv6_hdr ip6_hdr; + }; + uint8_t auth_cipher_text; + /**< Authenticate/cipher ordering */ + }; +#ifdef RTE_LIBRTE_SECURITY + struct sec_pdcp_ctxt pdcp; +#endif + }; +} dpaa_sec_session; struct dpaa_sec_qp { struct dpaa_sec_dev_private *internals; - struct sec_cdb cdb; /* cmd block associated with qp */ - dpaa_sec_session *ses; /* session associated with qp */ - struct qman_fq inq; + struct rte_mempool *ctx_pool; /* mempool for dpaa_sec_op_ctx */ struct qman_fq outq; int rx_pkts; int rx_errs; @@ -155,24 +184,27 @@ struct dpaa_sec_qp { int tx_errs; }; -#define RTE_MAX_NB_SEC_QPS RTE_DPAA_SEC_PMD_MAX_NB_SESSIONS +#define RTE_DPAA_MAX_NB_SEC_QPS 2 +#define RTE_DPAA_MAX_RX_QUEUE (MAX_DPAA_CORES * RTE_DPAA_SEC_PMD_MAX_NB_SESSIONS) +#define DPAA_MAX_DEQUEUE_NUM_FRAMES 63 + /* internal sec queue interface */ struct dpaa_sec_dev_private { void *sec_hw; - struct rte_mempool *ctx_pool; /* per dev mempool for dpaa_sec_op_ctx */ - struct dpaa_sec_qp qps[RTE_MAX_NB_SEC_QPS]; /* i/o queue for sec */ + struct dpaa_sec_qp qps[RTE_DPAA_MAX_NB_SEC_QPS]; /* i/o queue for sec */ + struct qman_fq inq[RTE_DPAA_MAX_RX_QUEUE]; + unsigned char inq_attach[RTE_DPAA_MAX_RX_QUEUE]; unsigned int max_nb_queue_pairs; unsigned int max_nb_sessions; + rte_spinlock_t lock; }; #define MAX_SG_ENTRIES 16 -#define SG_CACHELINE_0 0 -#define SG_CACHELINE_1 4 -#define SG_CACHELINE_2 8 -#define SG_CACHELINE_3 12 +#define MAX_JOB_SG_ENTRIES 36 + struct dpaa_sec_job { /* sg[0] output, sg[1] input, others are possible sub frames */ - struct qm_sg_entry sg[MAX_SG_ENTRIES]; + struct qm_sg_entry sg[MAX_JOB_SG_ENTRIES]; }; #define DPAA_MAX_NB_MAX_DIGEST 32 @@ -181,10 +213,32 @@ struct dpaa_sec_op_ctx { struct rte_crypto_op *op; struct rte_mempool *ctx_pool; /* mempool pointer for dpaa_sec_op_ctx */ uint32_t fd_status; + int64_t vtop_offset; uint8_t digest[DPAA_MAX_NB_MAX_DIGEST]; }; static const struct rte_cryptodev_capabilities dpaa_sec_capabilities[] = { + { /* NULL (AUTH) */ + .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC, + {.sym = { + .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH, + {.auth = { + .algo = RTE_CRYPTO_AUTH_NULL, + .block_size = 1, + .key_size = { + .min = 0, + .max = 0, + .increment = 0 + }, + .digest_size = { + .min = 0, + .max = 0, + .increment = 0 + }, + .iv_size = { 0 } + }, }, + }, }, + }, { /* MD5 HMAC */ .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC, {.sym = { @@ -198,10 +252,11 @@ static const struct rte_cryptodev_capabilities dpaa_sec_capabilities[] = { .increment = 1 }, .digest_size = { - .min = 16, + .min = 1, .max = 16, - .increment = 0 + .increment = 1 }, + .iv_size = { 0 } }, } }, } }, @@ -218,10 +273,11 @@ static const struct rte_cryptodev_capabilities dpaa_sec_capabilities[] = { .increment = 1 }, .digest_size = { - .min = 20, + .min = 1, .max = 20, - .increment = 0 + .increment = 1 }, + .iv_size = { 0 } }, } }, } }, @@ -238,10 +294,11 @@ static const struct rte_cryptodev_capabilities dpaa_sec_capabilities[] = { .increment = 1 }, .digest_size = { - .min = 28, + .min = 1, .max = 28, - .increment = 0 + .increment = 1 }, + .iv_size = { 0 } }, } }, } }, @@ -258,10 +315,11 @@ static const struct rte_cryptodev_capabilities dpaa_sec_capabilities[] = { .increment = 1 }, .digest_size = { - .min = 32, + .min = 1, .max = 32, - .increment = 0 + .increment = 1 }, + .iv_size = { 0 } }, } }, } }, @@ -278,10 +336,11 @@ static const struct rte_cryptodev_capabilities dpaa_sec_capabilities[] = { .increment = 1 }, .digest_size = { - .min = 48, + .min = 1, .max = 48, - .increment = 0 + .increment = 1 }, + .iv_size = { 0 } }, } }, } }, @@ -298,10 +357,11 @@ static const struct rte_cryptodev_capabilities dpaa_sec_capabilities[] = { .increment = 1 }, .digest_size = { - .min = 64, + .min = 1, .max = 64, - .increment = 0 + .increment = 1 }, + .iv_size = { 0 } }, } }, } }, @@ -309,7 +369,7 @@ static const struct rte_cryptodev_capabilities dpaa_sec_capabilities[] = { .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC, {.sym = { .xform_type = RTE_CRYPTO_SYM_XFORM_AEAD, - {.auth = { + {.aead = { .algo = RTE_CRYPTO_AEAD_AES_GCM, .block_size = 16, .key_size = { @@ -335,6 +395,26 @@ static const struct rte_cryptodev_capabilities dpaa_sec_capabilities[] = { }, } }, } }, + { /* NULL (CIPHER) */ + .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC, + {.sym = { + .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER, + {.cipher = { + .algo = RTE_CRYPTO_CIPHER_NULL, + .block_size = 1, + .key_size = { + .min = 0, + .max = 0, + .increment = 0 + }, + .iv_size = { + .min = 0, + .max = 0, + .increment = 0 + } + }, }, + }, } + }, { /* AES CBC */ .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC, {.sym = { @@ -371,7 +451,7 @@ static const struct rte_cryptodev_capabilities dpaa_sec_capabilities[] = { .min = 16, .max = 16, .increment = 0 - } + }, }, } }, } }, @@ -395,8 +475,331 @@ static const struct rte_cryptodev_capabilities dpaa_sec_capabilities[] = { }, } }, } }, + { /* SNOW 3G (UIA2) */ + .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC, + {.sym = { + .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH, + {.auth = { + .algo = RTE_CRYPTO_AUTH_SNOW3G_UIA2, + .block_size = 16, + .key_size = { + .min = 16, + .max = 16, + .increment = 0 + }, + .digest_size = { + .min = 4, + .max = 4, + .increment = 0 + }, + .iv_size = { + .min = 16, + .max = 16, + .increment = 0 + } + }, } + }, } + }, + { /* SNOW 3G (UEA2) */ + .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC, + {.sym = { + .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER, + {.cipher = { + .algo = RTE_CRYPTO_CIPHER_SNOW3G_UEA2, + .block_size = 16, + .key_size = { + .min = 16, + .max = 16, + .increment = 0 + }, + .iv_size = { + .min = 16, + .max = 16, + .increment = 0 + } + }, } + }, } + }, + { /* ZUC (EEA3) */ + .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC, + {.sym = { + .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER, + {.cipher = { + .algo = RTE_CRYPTO_CIPHER_ZUC_EEA3, + .block_size = 16, + .key_size = { + .min = 16, + .max = 16, + .increment = 0 + }, + .iv_size = { + .min = 16, + .max = 16, + .increment = 0 + } + }, } + }, } + }, + { /* ZUC (EIA3) */ + .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC, + {.sym = { + .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH, + {.auth = { + .algo = RTE_CRYPTO_AUTH_ZUC_EIA3, + .block_size = 16, + .key_size = { + .min = 16, + .max = 16, + .increment = 0 + }, + .digest_size = { + .min = 4, + .max = 4, + .increment = 0 + }, + .iv_size = { + .min = 16, + .max = 16, + .increment = 0 + } + }, } + }, } + }, + RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST() +}; + +#ifdef RTE_LIBRTE_SECURITY +static const struct rte_cryptodev_capabilities dpaa_pdcp_capabilities[] = { + { /* SNOW 3G (UIA2) */ + .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC, + {.sym = { + .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH, + {.auth = { + .algo = RTE_CRYPTO_AUTH_SNOW3G_UIA2, + .block_size = 16, + .key_size = { + .min = 16, + .max = 16, + .increment = 0 + }, + .digest_size = { + .min = 4, + .max = 4, + .increment = 0 + }, + .iv_size = { + .min = 16, + .max = 16, + .increment = 0 + } + }, } + }, } + }, + { /* SNOW 3G (UEA2) */ + .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC, + {.sym = { + .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER, + {.cipher = { + .algo = RTE_CRYPTO_CIPHER_SNOW3G_UEA2, + .block_size = 16, + .key_size = { + .min = 16, + .max = 16, + .increment = 0 + }, + .iv_size = { + .min = 16, + .max = 16, + .increment = 0 + } + }, } + }, } + }, + { /* AES CTR */ + .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC, + {.sym = { + .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER, + {.cipher = { + .algo = RTE_CRYPTO_CIPHER_AES_CTR, + .block_size = 16, + .key_size = { + .min = 16, + .max = 32, + .increment = 8 + }, + .iv_size = { + .min = 16, + .max = 16, + .increment = 0 + } + }, } + }, } + }, + { /* NULL (AUTH) */ + .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC, + {.sym = { + .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH, + {.auth = { + .algo = RTE_CRYPTO_AUTH_NULL, + .block_size = 1, + .key_size = { + .min = 0, + .max = 0, + .increment = 0 + }, + .digest_size = { + .min = 0, + .max = 0, + .increment = 0 + }, + .iv_size = { 0 } + }, }, + }, }, + }, + { /* NULL (CIPHER) */ + .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC, + {.sym = { + .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER, + {.cipher = { + .algo = RTE_CRYPTO_CIPHER_NULL, + .block_size = 1, + .key_size = { + .min = 0, + .max = 0, + .increment = 0 + }, + .iv_size = { + .min = 0, + .max = 0, + .increment = 0 + } + }, }, + }, } + }, + { /* ZUC (EEA3) */ + .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC, + {.sym = { + .xform_type = RTE_CRYPTO_SYM_XFORM_CIPHER, + {.cipher = { + .algo = RTE_CRYPTO_CIPHER_ZUC_EEA3, + .block_size = 16, + .key_size = { + .min = 16, + .max = 16, + .increment = 0 + }, + .iv_size = { + .min = 16, + .max = 16, + .increment = 0 + } + }, } + }, } + }, + { /* ZUC (EIA3) */ + .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC, + {.sym = { + .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH, + {.auth = { + .algo = RTE_CRYPTO_AUTH_ZUC_EIA3, + .block_size = 16, + .key_size = { + .min = 16, + .max = 16, + .increment = 0 + }, + .digest_size = { + .min = 4, + .max = 4, + .increment = 0 + }, + .iv_size = { + .min = 16, + .max = 16, + .increment = 0 + } + }, } + }, } + }, RTE_CRYPTODEV_END_OF_CAPABILITIES_LIST() }; +static const struct rte_security_capability dpaa_sec_security_cap[] = { + { /* IPsec Lookaside Protocol offload ESP Transport Egress */ + .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL, + .protocol = RTE_SECURITY_PROTOCOL_IPSEC, + .ipsec = { + .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP, + .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL, + .direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS, + .options = { 0 }, + .replay_win_sz_max = 128 + }, + .crypto_capabilities = dpaa_sec_capabilities + }, + { /* IPsec Lookaside Protocol offload ESP Tunnel Ingress */ + .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL, + .protocol = RTE_SECURITY_PROTOCOL_IPSEC, + .ipsec = { + .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP, + .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL, + .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS, + .options = { 0 }, + .replay_win_sz_max = 128 + }, + .crypto_capabilities = dpaa_sec_capabilities + }, + { /* PDCP Lookaside Protocol offload Data */ + .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL, + .protocol = RTE_SECURITY_PROTOCOL_PDCP, + .pdcp = { + .domain = RTE_SECURITY_PDCP_MODE_DATA, + .capa_flags = 0 + }, + .crypto_capabilities = dpaa_pdcp_capabilities + }, + { /* PDCP Lookaside Protocol offload Control */ + .action = RTE_SECURITY_ACTION_TYPE_LOOKASIDE_PROTOCOL, + .protocol = RTE_SECURITY_PROTOCOL_PDCP, + .pdcp = { + .domain = RTE_SECURITY_PDCP_MODE_CONTROL, + .capa_flags = 0 + }, + .crypto_capabilities = dpaa_pdcp_capabilities + }, + { + .action = RTE_SECURITY_ACTION_TYPE_NONE + } +}; +#endif + +/** + * Checksum + * + * @param buffer calculate chksum for buffer + * @param len buffer length + * + * @return checksum value in host cpu order + */ +static inline uint16_t +calc_chksum(void *buffer, int len) +{ + uint16_t *buf = (uint16_t *)buffer; + uint32_t sum = 0; + uint16_t result; + + for (sum = 0; len > 1; len -= 2) + sum += *buf++; + + if (len == 1) + sum += *(unsigned char *)buf; + + sum = (sum >> 16) + (sum & 0xFFFF); + sum += (sum >> 16); + result = ~sum; + + return result; +} + #endif /* _DPAA_SEC_H_ */