summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRadu Nicolau <radu.nicolau@intel.com>2016-11-29 11:00:30 +0000
committerDamjan Marion <dmarion.lists@gmail.com>2016-11-30 20:37:45 +0000
commit6929ea9225cf229ed59a480ceefb972b85971e50 (patch)
tree9366bec3e281de9cfe20fd3c58cb357c26ab6e43
parent2fee4c8fadd31979bd3e72c51d276773d17798d1 (diff)
Enabling AES-GCM-128 with 16B ICV support
Change-Id: Ib57b6f6b71ba14952ad77477a4df3ab33b36fef4 Signed-off-by: Radu Nicolau <radu.nicolau@intel.com>
-rw-r--r--build-data/packages/vpp-api-test.mk4
-rw-r--r--vnet/vnet/devices/dpdk/ipsec/esp.h31
-rw-r--r--vnet/vnet/devices/dpdk/ipsec/esp_decrypt.c142
-rw-r--r--vnet/vnet/devices/dpdk/ipsec/esp_encrypt.c104
-rw-r--r--vnet/vnet/devices/dpdk/ipsec/ipsec.h15
-rw-r--r--vnet/vnet/ipsec/ipsec.h23
-rw-r--r--vnet/vnet/ipsec/ipsec_cli.c25
-rw-r--r--vpp-api-test/Makefile.am2
-rw-r--r--vpp-api-test/configure.ac8
-rw-r--r--vpp-api-test/vat/api_format.c35
-rw-r--r--vpp/vpp-api/api.c38
11 files changed, 332 insertions, 95 deletions
diff --git a/build-data/packages/vpp-api-test.mk b/build-data/packages/vpp-api-test.mk
index 38edb5bc50a..c9eae367a12 100644
--- a/build-data/packages/vpp-api-test.mk
+++ b/build-data/packages/vpp-api-test.mk
@@ -33,3 +33,7 @@ vpp-api-test_CPPFLAGS += $(call installed_includes_fn, dpdk)
vpp-api-test_LDFLAGS += $(call installed_libs_fn, dpdk)
endif
endif
+ifeq ($($(PLATFORM)_uses_dpdk_cryptodev),yes)
+vpp-api-test_configure_args += --with-dpdk-crypto
+endif
+
diff --git a/vnet/vnet/devices/dpdk/ipsec/esp.h b/vnet/vnet/devices/dpdk/ipsec/esp.h
index 71282ac0cde..7ef90c49816 100644
--- a/vnet/vnet/devices/dpdk/ipsec/esp.h
+++ b/vnet/vnet/devices/dpdk/ipsec/esp.h
@@ -64,6 +64,11 @@ dpdk_esp_init ()
c->key_len = 32;
c->iv_len = 16;
+ c = &em->esp_crypto_algs[IPSEC_CRYPTO_ALG_AES_GCM_128];
+ c->algo = RTE_CRYPTO_CIPHER_AES_GCM;
+ c->key_len = 16;
+ c->iv_len = 8;
+
vec_validate (em->esp_integ_algs, IPSEC_INTEG_N_ALG - 1);
i = &em->esp_integ_algs[IPSEC_INTEG_ALG_SHA1_96];
@@ -85,6 +90,10 @@ dpdk_esp_init ()
i = &em->esp_integ_algs[IPSEC_INTEG_ALG_SHA_512_256];
i->algo = RTE_CRYPTO_AUTH_SHA512_HMAC;
i->trunc_size = 32;
+
+ i = &em->esp_integ_algs[IPSEC_INTEG_ALG_AES_GCM_128];
+ i->algo = RTE_CRYPTO_AUTH_AES_GCM;
+ i->trunc_size = 16;
}
static_always_inline int
@@ -150,6 +159,9 @@ translate_crypto_algo(ipsec_crypto_alg_t crypto_algo,
case IPSEC_CRYPTO_ALG_AES_CBC_256:
cipher_xform->cipher.algo = RTE_CRYPTO_CIPHER_AES_CBC;
break;
+ case IPSEC_CRYPTO_ALG_AES_GCM_128:
+ cipher_xform->cipher.algo = RTE_CRYPTO_CIPHER_AES_GCM;
+ break;
default:
return -1;
}
@@ -161,7 +173,7 @@ translate_crypto_algo(ipsec_crypto_alg_t crypto_algo,
static_always_inline int
translate_integ_algo(ipsec_integ_alg_t integ_alg,
- struct rte_crypto_sym_xform *auth_xform)
+ struct rte_crypto_sym_xform *auth_xform, int use_esn)
{
switch (integ_alg) {
case IPSEC_INTEG_ALG_NONE:
@@ -188,6 +200,11 @@ translate_integ_algo(ipsec_integ_alg_t integ_alg,
auth_xform->auth.algo = RTE_CRYPTO_AUTH_SHA512_HMAC;
auth_xform->auth.digest_length = 32;
break;
+ case IPSEC_INTEG_ALG_AES_GCM_128:
+ auth_xform->auth.algo = RTE_CRYPTO_AUTH_AES_GCM;
+ auth_xform->auth.digest_length = 16;
+ auth_xform->auth.add_auth_data_length = use_esn? 12 : 8;
+ break;
default:
return -1;
}
@@ -209,6 +226,16 @@ create_sym_sess(ipsec_sa_t *sa, crypto_sa_session_t *sa_sess, u8 is_outbound)
uword key = 0, *data;
crypto_worker_qp_key_t *p_key = (crypto_worker_qp_key_t *)&key;
+ if (sa->crypto_alg == IPSEC_CRYPTO_ALG_AES_GCM_128)
+ {
+ sa->crypto_key_len -= 4;
+ clib_memcpy(&sa->salt, &sa->crypto_key[sa->crypto_key_len], 4);
+ }
+ else
+ {
+ sa->salt = (u32) rand();
+ }
+
cipher_xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER;
cipher_xform.cipher.key.data = sa->crypto_key;
cipher_xform.cipher.key.length = sa->crypto_key_len;
@@ -221,7 +248,7 @@ create_sym_sess(ipsec_sa_t *sa, crypto_sa_session_t *sa_sess, u8 is_outbound)
return -1;
p_key->cipher_algo = cipher_xform.cipher.algo;
- if (translate_integ_algo(sa->integ_alg, &auth_xform) < 0)
+ if (translate_integ_algo(sa->integ_alg, &auth_xform, sa->use_esn) < 0)
return -1;
p_key->auth_algo = auth_xform.auth.algo;
diff --git a/vnet/vnet/devices/dpdk/ipsec/esp_decrypt.c b/vnet/vnet/devices/dpdk/ipsec/esp_decrypt.c
index c898d05e27f..2c43e24b531 100644
--- a/vnet/vnet/devices/dpdk/ipsec/esp_decrypt.c
+++ b/vnet/vnet/devices/dpdk/ipsec/esp_decrypt.c
@@ -127,13 +127,12 @@ dpdk_esp_decrypt_node_fn (vlib_main_t * vm,
while (n_left_from > 0 && n_left_to_next > 0)
{
- u32 bi0, sa_index0 = ~0, seq, icv_size;
+ u32 bi0, sa_index0 = ~0, seq, icv_size, iv_size;
vlib_buffer_t * b0;
esp_header_t * esp0;
ipsec_sa_t * sa0;
struct rte_mbuf * mb0 = 0;
const int BLOCK_SIZE = 16;
- const int IV_SIZE = 16;
crypto_sa_session_t * sa_sess;
void * sess;
u16 qp_index;
@@ -209,6 +208,7 @@ dpdk_esp_decrypt_node_fn (vlib_main_t * vm,
rte_crypto_op_attach_sym_session(cop, sess);
icv_size = em->esp_integ_algs[sa0->integ_alg].trunc_size;
+ iv_size = em->esp_crypto_algs[sa0->crypto_alg].iv_len;
/* Convert vlib buffer to mbuf */
mb0 = rte_mbuf_from_vlib_buffer(b0);
@@ -218,7 +218,7 @@ dpdk_esp_decrypt_node_fn (vlib_main_t * vm,
/* Outer IP header has already been stripped */
u16 payload_len = rte_pktmbuf_pkt_len(mb0) - sizeof (esp_header_t) -
- IV_SIZE - icv_size;
+ iv_size - icv_size;
if ((payload_len & (BLOCK_SIZE - 1)) || (payload_len <= 0))
{
@@ -239,46 +239,82 @@ dpdk_esp_decrypt_node_fn (vlib_main_t * vm,
struct rte_crypto_sym_op *sym_cop = (struct rte_crypto_sym_op *)(cop + 1);
sym_cop->m_src = mb0;
- sym_cop->cipher.data.offset = sizeof (esp_header_t) + IV_SIZE;
+ sym_cop->cipher.data.offset = sizeof (esp_header_t) + iv_size;
sym_cop->cipher.data.length = payload_len;
- sym_cop->cipher.iv.data =
- rte_pktmbuf_mtod_offset(mb0, void*, sizeof (esp_header_t));
- sym_cop->cipher.iv.phys_addr =
- rte_pktmbuf_mtophys_offset(mb0, sizeof (esp_header_t));
- sym_cop->cipher.iv.length = IV_SIZE;
-
- if (sa0->use_esn)
- {
- dpdk_cop_priv_t* priv = (dpdk_cop_priv_t*) (sym_cop + 1);
- u8* payload_end =
- rte_pktmbuf_mtod_offset(mb0, u8*, sizeof(esp_header_t) + IV_SIZE +
- payload_len);
-
- memcpy (priv->icv, payload_end, icv_size);
- *((u32*) payload_end) = sa0->seq_hi;
- sym_cop->auth.data.offset = 0;
- sym_cop->auth.data.length =
- sizeof(esp_header_t) + IV_SIZE + payload_len + sizeof(sa0->seq_hi);
- sym_cop->auth.digest.data = priv->icv;
- sym_cop->auth.digest.phys_addr =
- cop->phys_addr + (uintptr_t) priv->icv - (uintptr_t) cop;
- sym_cop->auth.digest.length = icv_size;
- }
- else
- {
- sym_cop->auth.data.offset = 0;
- sym_cop->auth.data.length = sizeof(esp_header_t) +
- IV_SIZE + payload_len;
-
- sym_cop->auth.digest.data =
- rte_pktmbuf_mtod_offset(mb0, void*,
- rte_pktmbuf_pkt_len(mb0) - icv_size);
- sym_cop->auth.digest.phys_addr =
- rte_pktmbuf_mtophys_offset(mb0,
- rte_pktmbuf_pkt_len(mb0) - icv_size);
- sym_cop->auth.digest.length = icv_size;
- }
+ u8 *iv = rte_pktmbuf_mtod_offset(mb0, void*, sizeof (esp_header_t));
+ dpdk_cop_priv_t * priv = (dpdk_cop_priv_t *)(sym_cop + 1);
+
+ if (sa0->crypto_alg == IPSEC_CRYPTO_ALG_AES_GCM_128)
+ {
+ dpdk_gcm_cnt_blk *icb = &priv->cb;
+ icb->salt = sa0->salt;
+ clib_memcpy(icb->iv, iv, 8);
+ icb->cnt = clib_host_to_net_u32(1);
+ sym_cop->cipher.iv.data = (u8 *)icb;
+ sym_cop->cipher.iv.phys_addr = rte_pktmbuf_mtophys_offset(mb0,
+ (u8 *)icb - rte_pktmbuf_mtod(mb0, u8 *));
+ sym_cop->cipher.iv.length = 16;
+
+ u8 *aad = priv->aad;
+ clib_memcpy(aad, iv - sizeof(esp_header_t), 8);
+ sym_cop->auth.aad.data = aad;
+ sym_cop->auth.aad.phys_addr = cop->phys_addr +
+ (uintptr_t)aad - (uintptr_t)cop;
+ if (sa0->use_esn)
+ {
+ *((u32*)&aad[8]) = sa0->seq_hi;
+ sym_cop->auth.aad.length = 12;
+ }
+ else
+ {
+ sym_cop->auth.aad.length = 8;
+ }
+
+ sym_cop->auth.digest.data = rte_pktmbuf_mtod_offset(mb0, void*,
+ rte_pktmbuf_pkt_len(mb0) - icv_size);
+ sym_cop->auth.digest.phys_addr = rte_pktmbuf_mtophys_offset(mb0,
+ rte_pktmbuf_pkt_len(mb0) - icv_size);
+ sym_cop->auth.digest.length = icv_size;
+
+ }
+ else
+ {
+ sym_cop->cipher.iv.data = rte_pktmbuf_mtod_offset(mb0, void*,
+ sizeof (esp_header_t));
+ sym_cop->cipher.iv.phys_addr = rte_pktmbuf_mtophys_offset(mb0,
+ sizeof (esp_header_t));
+ sym_cop->cipher.iv.length = iv_size;
+
+ if (sa0->use_esn)
+ {
+ dpdk_cop_priv_t* priv = (dpdk_cop_priv_t*) (sym_cop + 1);
+ u8* payload_end = rte_pktmbuf_mtod_offset(
+ mb0, u8*, sizeof(esp_header_t) + iv_size + payload_len);
+
+ clib_memcpy (priv->icv, payload_end, icv_size);
+ *((u32*) payload_end) = sa0->seq_hi;
+ sym_cop->auth.data.offset = 0;
+ sym_cop->auth.data.length = sizeof(esp_header_t) + iv_size
+ + payload_len + sizeof(sa0->seq_hi);
+ sym_cop->auth.digest.data = priv->icv;
+ sym_cop->auth.digest.phys_addr = cop->phys_addr
+ + (uintptr_t) priv->icv - (uintptr_t) cop;
+ sym_cop->auth.digest.length = icv_size;
+ }
+ else
+ {
+ sym_cop->auth.data.offset = 0;
+ sym_cop->auth.data.length = sizeof(esp_header_t) +
+ iv_size + payload_len;
+
+ sym_cop->auth.digest.data = rte_pktmbuf_mtod_offset(mb0, void*,
+ rte_pktmbuf_pkt_len(mb0) - icv_size);
+ sym_cop->auth.digest.phys_addr = rte_pktmbuf_mtophys_offset(mb0,
+ rte_pktmbuf_pkt_len(mb0) - icv_size);
+ sym_cop->auth.digest.length = icv_size;
+ }
+ }
trace:
if (PREDICT_FALSE(b0->flags & VLIB_BUFFER_IS_TRACED))
@@ -391,8 +427,7 @@ dpdk_esp_decrypt_post_node_fn (vlib_main_t * vm,
while (n_left_from > 0 && n_left_to_next > 0)
{
esp_footer_t * f0;
- const u32 IV_SIZE = 16;
- u32 bi0, next0, icv_size;
+ u32 bi0, next0, icv_size, iv_size;
vlib_buffer_t * b0 = 0;
ip4_header_t *ih4 = 0, *oh4 = 0;
ip6_header_t *ih6 = 0, *oh6 = 0;
@@ -415,6 +450,7 @@ dpdk_esp_decrypt_post_node_fn (vlib_main_t * vm,
to_next += 1;
icv_size = em->esp_integ_algs[sa0->integ_alg].trunc_size;
+ iv_size = em->esp_crypto_algs[sa0->crypto_alg].iv_len;
if (sa0->use_anti_replay)
{
@@ -428,7 +464,7 @@ dpdk_esp_decrypt_post_node_fn (vlib_main_t * vm,
}
ih4 = (ip4_header_t *) (b0->data + sizeof(ethernet_header_t));
- vlib_buffer_advance (b0, sizeof (esp_header_t) + IV_SIZE);
+ vlib_buffer_advance (b0, sizeof (esp_header_t) + iv_size);
b0->current_length -= (icv_size + 2);
b0->flags = VLIB_BUFFER_TOTAL_LENGTH_VALID;
@@ -475,33 +511,31 @@ dpdk_esp_decrypt_post_node_fn (vlib_main_t * vm,
{
if (PREDICT_FALSE(transport_ip6))
{
- next0 = ESP_DECRYPT_NEXT_IP6_INPUT;
ih6 = (ip6_header_t *) (b0->data + sizeof(ethernet_header_t));
vlib_buffer_advance (b0, -sizeof(ip6_header_t));
oh6 = vlib_buffer_get_current (b0);
memmove(oh6, ih6, sizeof(ip6_header_t));
+ next0 = ESP_DECRYPT_NEXT_IP6_INPUT;
oh6->protocol = f0->next_header;
oh6->payload_length =
- clib_host_to_net_u16 (vlib_buffer_length_in_chain(vm, b0) -
- sizeof (ip6_header_t));
+ clib_host_to_net_u16 (
+ vlib_buffer_length_in_chain(vm, b0) -
+ sizeof (ip6_header_t));
}
else
{
- next0 = ESP_DECRYPT_NEXT_IP4_INPUT;
vlib_buffer_advance (b0, -sizeof(ip4_header_t));
oh4 = vlib_buffer_get_current (b0);
+ memmove(oh4, ih4, sizeof(ip4_header_t));
+ next0 = ESP_DECRYPT_NEXT_IP4_INPUT;
oh4->ip_version_and_header_length = 0x45;
- oh4->tos = ih4->tos;
oh4->fragment_id = 0;
oh4->flags_and_fragment_offset = 0;
- oh4->ttl = ih4->ttl;
oh4->protocol = f0->next_header;
- oh4->src_address.as_u32 = ih4->src_address.as_u32;
- oh4->dst_address.as_u32 = ih4->dst_address.as_u32;
- oh4->length =
- clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0));
+ oh4->length = clib_host_to_net_u16 (
+ vlib_buffer_length_in_chain (vm, b0));
oh4->checksum = ip4_header_checksum (oh4);
}
}
diff --git a/vnet/vnet/devices/dpdk/ipsec/esp_encrypt.c b/vnet/vnet/devices/dpdk/ipsec/esp_encrypt.c
index aef4b90d51a..7e41007c92c 100644
--- a/vnet/vnet/devices/dpdk/ipsec/esp_encrypt.c
+++ b/vnet/vnet/devices/dpdk/ipsec/esp_encrypt.c
@@ -147,7 +147,7 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm,
u8 next_hdr_type;
u8 transport_mode = 0;
const int BLOCK_SIZE = 16;
- const int IV_SIZE = 16;
+ u32 iv_size;
u16 orig_sz;
crypto_sa_session_t *sa_sess;
void *sess;
@@ -196,6 +196,7 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm,
bi_to_enq[qp_index] += 1;
ssize_t adv;
+ iv_size = em->esp_crypto_algs[sa0->crypto_alg].iv_len;
ih0 = vlib_buffer_get_current (b0);
orig_sz = b0->current_length;
is_ipv6 = (ih0->ip4.ip_version_and_header_length & 0xF0) == 0x60;
@@ -223,11 +224,11 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm,
((u8 *) vlib_buffer_get_current (b0) -
sizeof (ethernet_header_t));
ethernet_header_t *oeh0 =
- (ethernet_header_t *) ((u8 *) ieh0 + (adv - IV_SIZE));
+ (ethernet_header_t *) ((u8 *) ieh0 + (adv - iv_size));
clib_memcpy (oeh0, ieh0, sizeof (ethernet_header_t));
}
- vlib_buffer_advance (b0, adv - IV_SIZE);
+ vlib_buffer_advance (b0, adv - iv_size);
/* XXX IP6/ip4 and IP4/IP6 not supported, only IP4/IP4 and IP6/IP6 */
@@ -258,11 +259,20 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm,
else
{
ip_hdr_size = sizeof (ip4_header_t);
- next_hdr_type = IP_PROTOCOL_IP_IN_IP;
oh0 = vlib_buffer_get_current (b0);
+ if (PREDICT_TRUE (sa0->is_tunnel))
+ {
+ next_hdr_type = IP_PROTOCOL_IP_IN_IP;
+ oh0->ip4.tos = ih0->ip4.tos;
+ }
+ else
+ {
+ next_hdr_type = ih0->ip4.protocol;
+ memmove (oh0, ih0, sizeof (ip4_header_t));
+ }
+
oh0->ip4.ip_version_and_header_length = 0x45;
- oh0->ip4.tos = ih0->ip4.tos;
oh0->ip4.fragment_id = 0;
oh0->ip4.flags_and_fragment_offset = 0;
oh0->ip4.ttl = 254;
@@ -299,13 +309,6 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm,
{
next0 = ESP_ENCRYPT_NEXT_INTERFACE_OUTPUT;
transport_mode = 1;
- /*ipv6 already handled */
- if (PREDICT_TRUE (!is_ipv6))
- {
- next_hdr_type = ih0->ip4.protocol;
- oh0->ip4.src_address.as_u32 = ih0->ip4.src_address.as_u32;
- oh0->ip4.dst_address.as_u32 = ih0->ip4.dst_address.as_u32;
- }
}
ASSERT (sa0->crypto_alg < IPSEC_CRYPTO_N_ALG);
@@ -337,8 +340,6 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm,
dpdk_cop_priv_t *priv = (dpdk_cop_priv_t *) (sym_cop + 1);
vnet_buffer (b0)->unused[0] = next0;
- priv->iv[0] = sa0->seq;
- priv->iv[1] = sa0->seq_hi;
mb0 = rte_mbuf_from_vlib_buffer (b0);
mb0->data_len = b0->current_length;
@@ -348,21 +349,71 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm,
rte_crypto_op_attach_sym_session (cop, sess);
sym_cop->m_src = mb0;
- sym_cop->cipher.data.offset = ip_hdr_size + sizeof (esp_header_t);
- sym_cop->cipher.data.length = BLOCK_SIZE * blocks + IV_SIZE;
- sym_cop->cipher.iv.data = (u8 *) priv->iv;
- sym_cop->cipher.iv.phys_addr = cop->phys_addr +
- (uintptr_t) priv->iv - (uintptr_t) cop;
- sym_cop->cipher.iv.length = IV_SIZE;
+ dpdk_gcm_cnt_blk *icb = &priv->cb;
+ icb->salt = sa0->salt;
+ icb->iv[0] = sa0->seq;
+ icb->iv[1] = sa0->seq_hi;
+
+ if (sa0->crypto_alg == IPSEC_CRYPTO_ALG_AES_GCM_128)
+ {
+ icb->cnt = clib_host_to_net_u32 (1);
+ clib_memcpy (vlib_buffer_get_current (b0) + ip_hdr_size +
+ sizeof (esp_header_t), icb->iv, 8);
+ sym_cop->cipher.data.offset =
+ ip_hdr_size + sizeof (esp_header_t) + iv_size;
+ sym_cop->cipher.data.length = BLOCK_SIZE * blocks;
+ sym_cop->cipher.iv.length = 16;
+ }
+ else
+ {
+ sym_cop->cipher.data.offset =
+ ip_hdr_size + sizeof (esp_header_t);
+ sym_cop->cipher.data.length = BLOCK_SIZE * blocks + iv_size;
+ sym_cop->cipher.iv.length = iv_size;
+ }
+
+ sym_cop->cipher.iv.data = (u8 *) icb;
+ sym_cop->cipher.iv.phys_addr = cop->phys_addr + (uintptr_t) icb
+ - (uintptr_t) cop;
+
ASSERT (sa0->integ_alg < IPSEC_INTEG_N_ALG);
ASSERT (sa0->integ_alg != IPSEC_INTEG_ALG_NONE);
- sym_cop->auth.data.offset = ip_hdr_size;
- sym_cop->auth.data.length = b0->current_length - ip_hdr_size -
- em->esp_integ_algs[sa0->integ_alg].trunc_size;
+ if (PREDICT_FALSE (sa0->integ_alg == IPSEC_INTEG_ALG_AES_GCM_128))
+ {
+ u8 *aad = priv->aad;
+ clib_memcpy (aad, vlib_buffer_get_current (b0) + ip_hdr_size,
+ 8);
+ sym_cop->auth.aad.data = aad;
+ sym_cop->auth.aad.phys_addr = cop->phys_addr +
+ (uintptr_t) aad - (uintptr_t) cop;
+
+ if (PREDICT_FALSE (sa0->use_esn))
+ {
+ *((u32 *) & aad[8]) = sa0->seq_hi;
+ sym_cop->auth.aad.length = 12;
+ }
+ else
+ {
+ sym_cop->auth.aad.length = 8;
+ }
+ }
+ else
+ {
+ sym_cop->auth.data.offset = ip_hdr_size;
+ sym_cop->auth.data.length = b0->current_length - ip_hdr_size
+ - em->esp_integ_algs[sa0->integ_alg].trunc_size;
+ if (PREDICT_FALSE (sa0->use_esn))
+ {
+ u8 *payload_end =
+ vlib_buffer_get_current (b0) + b0->current_length;
+ *((u32 *) payload_end) = sa0->seq_hi;
+ sym_cop->auth.data.length += sizeof (sa0->seq_hi);
+ }
+ }
sym_cop->auth.digest.data = vlib_buffer_get_current (b0) +
b0->current_length -
em->esp_integ_algs[sa0->integ_alg].trunc_size;
@@ -374,13 +425,6 @@ dpdk_esp_encrypt_node_fn (vlib_main_t * vm,
sym_cop->auth.digest.length =
em->esp_integ_algs[sa0->integ_alg].trunc_size;
- if (PREDICT_FALSE (sa0->use_esn))
- {
- u8 *payload_end =
- vlib_buffer_get_current (b0) + b0->current_length;
- *((u32 *) payload_end) = sa0->seq_hi;
- sym_cop->auth.data.length += sizeof (sa0->seq_hi);
- }
if (PREDICT_FALSE (is_ipv6))
{
diff --git a/vnet/vnet/devices/dpdk/ipsec/ipsec.h b/vnet/vnet/devices/dpdk/ipsec/ipsec.h
index e103655ca71..e6c7498c0d3 100644
--- a/vnet/vnet/devices/dpdk/ipsec/ipsec.h
+++ b/vnet/vnet/devices/dpdk/ipsec/ipsec.h
@@ -32,8 +32,19 @@
typedef struct
{
- u32 iv[4];
- u8 icv[64];
+ u32 salt;
+ u32 iv[2];
+ u32 cnt;
+} dpdk_gcm_cnt_blk;
+
+typedef struct
+{
+ dpdk_gcm_cnt_blk cb;
+ union
+ {
+ u8 aad[12];
+ u8 icv[64];
+ };
} dpdk_cop_priv_t;
typedef struct
diff --git a/vnet/vnet/ipsec/ipsec.h b/vnet/vnet/ipsec/ipsec.h
index 65d7bad378d..32c7edfc29d 100644
--- a/vnet/vnet/ipsec/ipsec.h
+++ b/vnet/vnet/ipsec/ipsec.h
@@ -31,11 +31,20 @@ typedef enum
IPSEC_POLICY_N_ACTION,
} ipsec_policy_action_t;
+#if DPDK_CRYPTO==1
+#define foreach_ipsec_crypto_alg \
+ _(0, NONE, "none") \
+ _(1, AES_CBC_128, "aes-cbc-128") \
+ _(2, AES_CBC_192, "aes-cbc-192") \
+ _(3, AES_CBC_256, "aes-cbc-256") \
+ _(4, AES_GCM_128, "aes-gcm-128")
+#else
#define foreach_ipsec_crypto_alg \
_(0, NONE, "none") \
_(1, AES_CBC_128, "aes-cbc-128") \
_(2, AES_CBC_192, "aes-cbc-192") \
_(3, AES_CBC_256, "aes-cbc-256")
+#endif
typedef enum
{
@@ -45,6 +54,17 @@ typedef enum
IPSEC_CRYPTO_N_ALG,
} ipsec_crypto_alg_t;
+#if DPDK_CRYPTO==1
+#define foreach_ipsec_integ_alg \
+ _(0, NONE, "none") \
+ _(1, MD5_96, "md5-96") /* RFC2403 */ \
+ _(2, SHA1_96, "sha1-96") /* RFC2404 */ \
+ _(3, SHA_256_96, "sha-256-96") /* draft-ietf-ipsec-ciph-sha-256-00 */ \
+ _(4, SHA_256_128, "sha-256-128") /* RFC4868 */ \
+ _(5, SHA_384_192, "sha-384-192") /* RFC4868 */ \
+ _(6, SHA_512_256, "sha-512-256") /* RFC4868 */ \
+ _(7, AES_GCM_128, "aes-gcm-128")
+#else
#define foreach_ipsec_integ_alg \
_(0, NONE, "none") \
_(1, MD5_96, "md5-96") /* RFC2403 */ \
@@ -53,6 +73,7 @@ typedef enum
_(4, SHA_256_128, "sha-256-128") /* RFC4868 */ \
_(5, SHA_384_192, "sha-384-192") /* RFC4868 */ \
_(6, SHA_512_256, "sha-512-256") /* RFC4868 */
+#endif
typedef enum
{
@@ -90,6 +111,8 @@ typedef struct
ip46_address_t tunnel_src_addr;
ip46_address_t tunnel_dst_addr;
+ u32 salt;
+
/* runtime */
u32 seq;
u32 seq_hi;
diff --git a/vnet/vnet/ipsec/ipsec_cli.c b/vnet/vnet/ipsec/ipsec_cli.c
index 8920924d04e..7ab85d4aefb 100644
--- a/vnet/vnet/ipsec/ipsec_cli.c
+++ b/vnet/vnet/ipsec/ipsec_cli.c
@@ -99,7 +99,7 @@ ipsec_sa_add_del_command_fn (vlib_main_t * vm,
&sa.crypto_alg))
{
if (sa.crypto_alg < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
- sa.crypto_alg > IPSEC_CRYPTO_ALG_AES_CBC_256)
+ sa.crypto_alg >= IPSEC_CRYPTO_N_ALG)
return clib_error_return (0, "unsupported crypto-alg: '%U'",
format_ipsec_crypto_alg, sa.crypto_alg);
}
@@ -109,8 +109,12 @@ ipsec_sa_add_del_command_fn (vlib_main_t * vm,
else if (unformat (line_input, "integ-alg %U", unformat_ipsec_integ_alg,
&sa.integ_alg))
{
+#if DPDK_CRYPTO==1
+ if (sa.integ_alg < IPSEC_INTEG_ALG_NONE ||
+#else
if (sa.integ_alg < IPSEC_INTEG_ALG_SHA1_96 ||
- sa.integ_alg > IPSEC_INTEG_ALG_SHA_512_256)
+#endif
+ sa.integ_alg >= IPSEC_INTEG_N_ALG)
return clib_error_return (0, "unsupported integ-alg: '%U'",
format_ipsec_integ_alg, sa.integ_alg);
}
@@ -137,6 +141,23 @@ ipsec_sa_add_del_command_fn (vlib_main_t * vm,
format_unformat_error, line_input);
}
+#if DPDK_CRYPTO==1
+ /*Special cases, aes-gcm-128 encryption */
+ if (sa.crypto_alg == IPSEC_CRYPTO_ALG_AES_GCM_128)
+ {
+ if (sa.integ_alg != IPSEC_INTEG_ALG_NONE
+ && sa.integ_alg != IPSEC_INTEG_ALG_AES_GCM_128)
+ return clib_error_return (0,
+ "unsupported: aes-gcm-128 crypto-alg needs none as integ-alg");
+ else /*set integ-alg internally to aes-gcm-128 */
+ sa.integ_alg = IPSEC_INTEG_ALG_AES_GCM_128;
+ }
+ else if (sa.integ_alg == IPSEC_INTEG_ALG_AES_GCM_128)
+ return clib_error_return (0, "unsupported integ-alg: aes-gcm-128");
+ else if (sa.integ_alg == IPSEC_INTEG_ALG_NONE)
+ return clib_error_return (0, "unsupported integ-alg: none");
+#endif
+
unformat_free (line_input);
if (sa.crypto_key_len > sizeof (sa.crypto_key))
diff --git a/vpp-api-test/Makefile.am b/vpp-api-test/Makefile.am
index d59c7e27f5c..27466fad2ca 100644
--- a/vpp-api-test/Makefile.am
+++ b/vpp-api-test/Makefile.am
@@ -13,7 +13,7 @@
AUTOMAKE_OPTIONS = foreign subdir-objects
-AM_CFLAGS = -Wall @Q_PLATFORM_DEFINE@ @Q_PLATFORM_PLUGPATH@ @DPDK@
+AM_CFLAGS = -Wall @Q_PLATFORM_DEFINE@ @Q_PLATFORM_PLUGPATH@ @DPDK@ @DPDK_CRYPTO@
libvatplugin_la_SOURCES = \
vat/plugin_api.c
diff --git a/vpp-api-test/configure.ac b/vpp-api-test/configure.ac
index 4c200458930..cf0af125253 100644
--- a/vpp-api-test/configure.ac
+++ b/vpp-api-test/configure.ac
@@ -24,9 +24,17 @@ AC_ARG_WITH(dpdk,
[with_dpdk=1],
[with_dpdk=0])
+AC_ARG_WITH(dpdk_crypto,
+ AC_HELP_STRING([--with-dpdk-crypto],[Use DPDK cryptodev]),
+ [with_dpdk_crypto=1],
+ [with_dpdk_crypto=0])
+
AC_SUBST(Q_PLATFORM_DEFINE,[-DQ_PLATFORM_${with_q_platform}])
AC_SUBST(Q_PLATFORM_PLUGPATH,[-DQ_PLUGIN_PREFIX=${with_q_plugin_prefix}])
AC_SUBST(DPDK,[-DDPDK=${with_dpdk}])
AM_CONDITIONAL(WITH_DPDK, test "$with_dpdk" = "1")
+AC_SUBST(DPDK_CRYPTO,[-DDPDK_CRYPTO=${with_dpdk_crypto}])
+AM_CONDITIONAL(WITH_DPDK_CRYPTO, test "$with_dpdk_crypto" = "1")
+
AC_OUTPUT([Makefile])
diff --git a/vpp-api-test/vat/api_format.c b/vpp-api-test/vat/api_format.c
index 8522428ea88..800fa2b3df0 100644
--- a/vpp-api-test/vat/api_format.c
+++ b/vpp-api-test/vat/api_format.c
@@ -11732,7 +11732,7 @@ api_ipsec_sad_add_del_entry (vat_main_t * vam)
(i, "crypto_alg %U", unformat_ipsec_crypto_alg, &crypto_alg))
{
if (crypto_alg < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
- crypto_alg > IPSEC_INTEG_ALG_SHA_512_256)
+ crypto_alg >= IPSEC_CRYPTO_N_ALG)
{
clib_warning ("unsupported crypto-alg: '%U'",
format_ipsec_crypto_alg, crypto_alg);
@@ -11745,8 +11745,12 @@ api_ipsec_sad_add_del_entry (vat_main_t * vam)
if (unformat
(i, "integ_alg %U", unformat_ipsec_integ_alg, &integ_alg))
{
+#if DPDK_CRYPTO==1
+ if (integ_alg < IPSEC_INTEG_ALG_NONE ||
+#else
if (integ_alg < IPSEC_INTEG_ALG_SHA1_96 ||
- integ_alg > IPSEC_INTEG_ALG_SHA_512_256)
+#endif
+ integ_alg >= IPSEC_INTEG_N_ALG)
{
clib_warning ("unsupported integ-alg: '%U'",
format_ipsec_integ_alg, integ_alg);
@@ -11763,6 +11767,33 @@ api_ipsec_sad_add_del_entry (vat_main_t * vam)
}
+#if DPDK_CRYPTO==1
+ /*Special cases, aes-gcm-128 encryption */
+ if (crypto_alg == IPSEC_CRYPTO_ALG_AES_GCM_128)
+ {
+ if (integ_alg != IPSEC_INTEG_ALG_NONE
+ && integ_alg != IPSEC_INTEG_ALG_AES_GCM_128)
+ {
+ clib_warning
+ ("unsupported: aes-gcm-128 crypto-alg needs none as integ-alg");
+ return -99;
+ }
+ else /*set integ-alg internally to aes-gcm-128 */
+ integ_alg = IPSEC_INTEG_ALG_AES_GCM_128;
+ }
+ else if (integ_alg == IPSEC_INTEG_ALG_AES_GCM_128)
+ {
+ clib_warning ("unsupported integ-alg: aes-gcm-128");
+ return -99;
+ }
+ else if (integ_alg == IPSEC_INTEG_ALG_NONE)
+ {
+ clib_warning ("unsupported integ-alg: none");
+ return -99;
+ }
+#endif
+
+
M (IPSEC_SAD_ADD_DEL_ENTRY, ipsec_sad_add_del_entry);
mp->sad_id = ntohl (sad_id);
diff --git a/vpp/vpp-api/api.c b/vpp/vpp-api/api.c
index 8f0165a124e..1da0729f4f1 100644
--- a/vpp/vpp-api/api.c
+++ b/vpp/vpp-api/api.c
@@ -6566,7 +6566,7 @@ static void vl_api_ipsec_sad_add_del_entry_t_handler
sa.protocol = mp->protocol;
/* check for unsupported crypto-alg */
if (mp->crypto_algorithm < IPSEC_CRYPTO_ALG_AES_CBC_128 ||
- mp->crypto_algorithm > IPSEC_CRYPTO_ALG_AES_CBC_256)
+ mp->crypto_algorithm >= IPSEC_CRYPTO_N_ALG)
{
clib_warning ("unsupported crypto-alg: '%U'", format_ipsec_crypto_alg,
mp->crypto_algorithm);
@@ -6577,14 +6577,48 @@ static void vl_api_ipsec_sad_add_del_entry_t_handler
sa.crypto_key_len = mp->crypto_key_length;
clib_memcpy (&sa.crypto_key, mp->crypto_key, sizeof (sa.crypto_key));
/* check for unsupported integ-alg */
+#if DPDK_CRYPTO==1
+ if (mp->integrity_algorithm < IPSEC_INTEG_ALG_NONE ||
+#else
if (mp->integrity_algorithm < IPSEC_INTEG_ALG_SHA1_96 ||
- mp->integrity_algorithm > IPSEC_INTEG_ALG_SHA_512_256)
+#endif
+ mp->integrity_algorithm >= IPSEC_INTEG_N_ALG)
{
clib_warning ("unsupported integ-alg: '%U'", format_ipsec_integ_alg,
mp->integrity_algorithm);
rv = VNET_API_ERROR_UNIMPLEMENTED;
goto out;
}
+
+#if DPDK_CRYPTO==1
+ /*Special cases, aes-gcm-128 encryption */
+ if (mp->crypto_algorithm == IPSEC_CRYPTO_ALG_AES_GCM_128)
+ {
+ if (mp->integrity_algorithm != IPSEC_INTEG_ALG_NONE
+ && mp->integrity_algorithm != IPSEC_INTEG_ALG_AES_GCM_128)
+ {
+ clib_warning
+ ("unsupported: aes-gcm-128 crypto-alg needs none as integ-alg");
+ rv = VNET_API_ERROR_UNIMPLEMENTED;
+ goto out;
+ }
+ else /*set integ-alg internally to aes-gcm-128 */
+ mp->integrity_algorithm = IPSEC_INTEG_ALG_AES_GCM_128;
+ }
+ else if (mp->integrity_algorithm == IPSEC_INTEG_ALG_AES_GCM_128)
+ {
+ clib_warning ("unsupported integ-alg: aes-gcm-128");
+ rv = VNET_API_ERROR_UNIMPLEMENTED;
+ goto out;
+ }
+ else if (mp->integrity_algorithm == IPSEC_INTEG_ALG_NONE)
+ {
+ clib_warning ("unsupported integ-alg: none");
+ rv = VNET_API_ERROR_UNIMPLEMENTED;
+ goto out;
+ }
+#endif
+
sa.integ_alg = mp->integrity_algorithm;
sa.integ_key_len = mp->integrity_key_length;
clib_memcpy (&sa.integ_key, mp->integrity_key, sizeof (sa.integ_key));