From mboxrd@z Thu Jan 1 00:00:00 1970 From: Sergio Gonzalez Monroy Subject: [PATCH 1/3] examples/ipsec-secgw: change CBC IV generation Date: Tue, 23 Aug 2016 17:59:32 +0100 Message-ID: <1471971574-108998-2-git-send-email-sergio.gonzalez.monroy@intel.com> References: <1471971574-108998-1-git-send-email-sergio.gonzalez.monroy@intel.com> To: dev@dpdk.org Return-path: Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by dpdk.org (Postfix) with ESMTP id CF4572B82 for ; Tue, 23 Aug 2016 18:59:36 +0200 (CEST) In-Reply-To: <1471971574-108998-1-git-send-email-sergio.gonzalez.monroy@intel.com> List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" NIST SP800-38A recommends two methods to generate unpredictable IVs (Initilisation Vector) for CBC mode: 1) Apply the forward function to a nonce (ie. counter) 2) Use a FIPS-approved random number generator This patch implements the first recommended method by using the forward function to generate the IV. Signed-off-by: Sergio Gonzalez Monroy --- examples/ipsec-secgw/esp.c | 99 +++++++++++++++++++++++++------------------- examples/ipsec-secgw/ipsec.h | 33 ++++++++++++++- 2 files changed, 88 insertions(+), 44 deletions(-) diff --git a/examples/ipsec-secgw/esp.c b/examples/ipsec-secgw/esp.c index 05caa77..d640ab2 100644 --- a/examples/ipsec-secgw/esp.c +++ b/examples/ipsec-secgw/esp.c @@ -50,21 +50,6 @@ #include "esp.h" #include "ipip.h" -static inline void -random_iv_u64(uint64_t *buf, uint16_t n) -{ - uint32_t left = n & 0x7; - uint32_t i; - - RTE_ASSERT((n & 0x3) == 0); - - for (i = 0; i < (n >> 3); i++) - buf[i] = rte_rand(); - - if (left) - *((uint32_t *)&buf[i]) = (uint32_t)lrand48(); -} - int esp_inbound(struct rte_mbuf *m, struct ipsec_sa *sa, struct rte_crypto_op *cop) @@ -98,22 +83,32 @@ esp_inbound(struct rte_mbuf *m, struct ipsec_sa *sa, return -EINVAL; } - sym_cop = (struct rte_crypto_sym_op *)(cop + 1); + sym_cop = get_sym_cop(cop); sym_cop->m_src = m; sym_cop->cipher.data.offset = ip_hdr_len + sizeof(struct esp_hdr) + sa->iv_len; sym_cop->cipher.data.length = payload_len; - sym_cop->cipher.iv.data = rte_pktmbuf_mtod_offset(m, void*, - ip_hdr_len + sizeof(struct esp_hdr)); - sym_cop->cipher.iv.phys_addr = rte_pktmbuf_mtophys_offset(m, - ip_hdr_len + sizeof(struct esp_hdr)); - sym_cop->cipher.iv.length = sa->iv_len; + uint8_t *iv = RTE_PTR_ADD(ip4, ip_hdr_len + sizeof(struct esp_hdr)); + + switch (sa->cipher_algo) { + case RTE_CRYPTO_CIPHER_NULL: + case RTE_CRYPTO_CIPHER_AES_CBC: + sym_cop->cipher.iv.data = iv; + sym_cop->cipher.iv.phys_addr = rte_pktmbuf_mtophys_offset(m, + ip_hdr_len + sizeof(struct esp_hdr)); + sym_cop->cipher.iv.length = sa->iv_len; - sym_cop->auth.data.offset = ip_hdr_len; - sym_cop->auth.data.length = sizeof(struct esp_hdr) + - sa->iv_len + payload_len; + sym_cop->auth.data.offset = ip_hdr_len; + sym_cop->auth.data.length = sizeof(struct esp_hdr) + + sa->iv_len + payload_len; + break; + default: + RTE_LOG(ERR, IPSEC_ESP, "unsupported cipher algorithm %u\n", + sa->cipher_algo); + return -EINVAL; + } sym_cop->auth.digest.data = rte_pktmbuf_mtod_offset(m, void*, rte_pktmbuf_pkt_len(m) - sa->digest_len); @@ -282,10 +277,25 @@ esp_outbound(struct rte_mbuf *m, struct ipsec_sa *sa, sa->seq++; esp->spi = rte_cpu_to_be_32(sa->spi); - esp->seq = rte_cpu_to_be_32(sa->seq); + esp->seq = rte_cpu_to_be_32((uint32_t)sa->seq); - if (sa->cipher_algo == RTE_CRYPTO_CIPHER_AES_CBC) - random_iv_u64((uint64_t *)(esp + 1), sa->iv_len); + uint64_t *iv = (uint64_t *)(esp + 1); + + sym_cop = get_sym_cop(cop); + sym_cop->m_src = m; + switch (sa->cipher_algo) { + case RTE_CRYPTO_CIPHER_NULL: + case RTE_CRYPTO_CIPHER_AES_CBC: + memset(iv, 0, sa->iv_len); + sym_cop->cipher.data.offset = ip_hdr_len + + sizeof(struct esp_hdr); + sym_cop->cipher.data.length = pad_payload_len + sa->iv_len; + break; + default: + RTE_LOG(ERR, IPSEC_ESP, "unsupported cipher algorithm %u\n", + sa->cipher_algo); + return -EINVAL; + } /* Fill pad_len using default sequential scheme */ for (i = 0; i < pad_len - 2; i++) @@ -293,22 +303,27 @@ esp_outbound(struct rte_mbuf *m, struct ipsec_sa *sa, padding[pad_len - 2] = pad_len - 2; padding[pad_len - 1] = nlp; - sym_cop = (struct rte_crypto_sym_op *)(cop + 1); - - sym_cop->m_src = m; - sym_cop->cipher.data.offset = ip_hdr_len + sizeof(struct esp_hdr) + - sa->iv_len; - sym_cop->cipher.data.length = pad_payload_len; - - sym_cop->cipher.iv.data = rte_pktmbuf_mtod_offset(m, uint8_t *, - ip_hdr_len + sizeof(struct esp_hdr)); + struct cnt_blk *nonce = get_cnt_blk(m); + nonce->salt = sa->salt; + nonce->iv = sa->seq; + sym_cop->cipher.iv.data = (uint8_t *)nonce; sym_cop->cipher.iv.phys_addr = rte_pktmbuf_mtophys_offset(m, - ip_hdr_len + sizeof(struct esp_hdr)); - sym_cop->cipher.iv.length = sa->iv_len; - - sym_cop->auth.data.offset = ip_hdr_len; - sym_cop->auth.data.length = sizeof(struct esp_hdr) + sa->iv_len + - pad_payload_len; + (uint8_t *)nonce - rte_pktmbuf_mtod(m, uint8_t *)); + /* FIXME should be 12 for GCM, but API needs 16 */ + sym_cop->cipher.iv.length = 16; + + switch (sa->cipher_algo) { + case RTE_CRYPTO_CIPHER_NULL: + case RTE_CRYPTO_CIPHER_AES_CBC: + sym_cop->auth.data.offset = ip_hdr_len; + sym_cop->auth.data.length = sizeof(struct esp_hdr) + + sa->iv_len + pad_payload_len; + break; + default: + RTE_LOG(ERR, IPSEC_ESP, "unsupported cipher algorithm %u\n", + sa->cipher_algo); + return -EINVAL; + } sym_cop->auth.digest.data = rte_pktmbuf_mtod_offset(m, uint8_t *, rte_pktmbuf_pkt_len(m) - sa->digest_len); diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h index 4cc316c..d950df3 100644 --- a/examples/ipsec-secgw/ipsec.h +++ b/examples/ipsec-secgw/ipsec.h @@ -95,8 +95,9 @@ struct ip_addr { struct ipsec_sa { uint32_t spi; uint32_t cdev_id_qp; + uint64_t seq; + uint32_t salt; struct rte_cryptodev_sym_session *crypto_session; - uint32_t seq; enum rte_crypto_cipher_algorithm cipher_algo; enum rte_crypto_auth_algorithm auth_algo; uint16_t digest_len; @@ -116,10 +117,11 @@ struct ipsec_sa { } __rte_cache_aligned; struct ipsec_mbuf_metadata { + uint8_t buf[32]; struct ipsec_sa *sa; struct rte_crypto_op cop; struct rte_crypto_sym_op sym_cop; -}; +} __rte_cache_aligned; struct cdev_qp { uint16_t id; @@ -157,6 +159,11 @@ struct socket_ctx { struct rte_mempool *mbuf_pool; }; +struct cnt_blk { + uint32_t salt; + uint64_t iv; +}; + uint16_t ipsec_inbound(struct ipsec_ctx *ctx, struct rte_mbuf *pkts[], uint16_t nb_pkts, uint16_t len); @@ -177,6 +184,28 @@ get_priv(struct rte_mbuf *m) return RTE_PTR_ADD(m, sizeof(struct rte_mbuf)); } +static inline void * +get_cnt_blk(struct rte_mbuf *m) +{ + struct ipsec_mbuf_metadata *priv = get_priv(m); + + return &priv->buf[0]; +} + +static inline void * +get_cop(struct rte_mbuf *m) +{ + struct ipsec_mbuf_metadata *priv = get_priv(m); + + return &priv->cop; +} + +static inline void * +get_sym_cop(struct rte_crypto_op *cop) +{ + return (cop + 1); +} + int inbound_sa_check(struct sa_ctx *sa_ctx, struct rte_mbuf *m, uint32_t sa_idx); -- 2.5.5