Code Review
/
vpp.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
review
|
tree
raw
|
inline
| side by side
ipsec: add support for RFC-4543 ENCR_NULL_AUTH_AES_GMAC
[vpp.git]
/
src
/
vnet
/
ipsec
/
esp_encrypt.c
diff --git
a/src/vnet/ipsec/esp_encrypt.c
b/src/vnet/ipsec/esp_encrypt.c
index
88e93b9
..
a836453
100644
(file)
--- a/
src/vnet/ipsec/esp_encrypt.c
+++ b/
src/vnet/ipsec/esp_encrypt.c
@@
-182,9
+182,9
@@
ext_hdr_is_pre_esp (u8 nexthdr)
return !u8x16_is_all_zero (ext_hdr_types == u8x16_splat (nexthdr));
#else
return !u8x16_is_all_zero (ext_hdr_types == u8x16_splat (nexthdr));
#else
- return (
(nexthdr ^ IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS)
|
-
(nexthdr ^ IP_PROTOCOL_IPV6_ROUTE)
|
-
((nexthdr ^ IP_PROTOCOL_IPV6_FRAGMENTATION) != 0
));
+ return (
!(nexthdr ^ IP_PROTOCOL_IP6_HOP_BY_HOP_OPTIONS) |
|
+
!(nexthdr ^ IP_PROTOCOL_IPV6_ROUTE) |
|
+
!(nexthdr ^ IP_PROTOCOL_IPV6_FRAGMENTATION
));
#endif
}
#endif
}
@@
-219,17
+219,18
@@
esp_get_ip6_hdr_len (ip6_header_t * ip6, ip6_ext_header_t ** ext_hdr)
* encryption mode: IVs must be unpredictable for AES-CBC whereas it can
* be predictable but should never be reused with the same key material
* for CTR and GCM.
* encryption mode: IVs must be unpredictable for AES-CBC whereas it can
* be predictable but should never be reused with the same key material
* for CTR and GCM.
- * We use a packet counter as the IV for CTR and GCM, and to ensure the
- * IV is unpredictable for CBC, it is then encrypted using the same key
- * as the message. You can refer to NIST SP800-38a and NIST SP800-38d
- * for more details. */
+ * To avoid reusing the same IVs between multiple VPP instances and between
+ * restarts, we use a properly chosen PRNG to generate IVs. To ensure the IV is
+ * unpredictable for CBC, it is then encrypted using the same key as the
+ * message. You can refer to NIST SP800-38a and NIST SP800-38d for more
+ * details. */
static_always_inline void *
esp_generate_iv (ipsec_sa_t *sa, void *payload, int iv_sz)
{
ASSERT (iv_sz >= sizeof (u64));
u64 *iv = (u64 *) (payload - iv_sz);
clib_memset_u8 (iv, 0, iv_sz);
static_always_inline void *
esp_generate_iv (ipsec_sa_t *sa, void *payload, int iv_sz)
{
ASSERT (iv_sz >= sizeof (u64));
u64 *iv = (u64 *) (payload - iv_sz);
clib_memset_u8 (iv, 0, iv_sz);
- *iv =
sa->iv_counter++
;
+ *iv =
clib_pcg64i_random_r (&sa->iv_prng)
;
return iv;
}
return iv;
}
@@
-414,6
+415,12
@@
esp_prepare_sync_op (vlib_main_t *vm, ipsec_per_thread_data_t *ptd,
op->aad_len = esp_aad_fill (op->aad, esp, sa0, seq_hi);
op->tag = payload + crypto_len;
op->tag_len = 16;
op->aad_len = esp_aad_fill (op->aad, esp, sa0, seq_hi);
op->tag = payload + crypto_len;
op->tag_len = 16;
+ if (PREDICT_FALSE (ipsec_sa_is_set_IS_NULL_GMAC (sa0)))
+ {
+ /* RFC-4543 ENCR_NULL_AUTH_AES_GMAC: IV is part of AAD */
+ crypto_start -= iv_sz;
+ crypto_len += iv_sz;
+ }
}
else
{
}
else
{
@@
-434,7
+441,7
@@
esp_prepare_sync_op (vlib_main_t *vm, ipsec_per_thread_data_t *ptd,
crypto_len += iv_sz;
}
crypto_len += iv_sz;
}
- if (
lb != b[0]
)
+ if (
PREDICT_FALSE (lb != b[0])
)
{
/* is chained */
op->flags |= VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS;
{
/* is chained */
op->flags |= VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS;
@@
-497,7
+504,7
@@
esp_prepare_async_frame (vlib_main_t *vm, ipsec_per_thread_data_t *ptd,
esp_post_data_t *post = esp_post_data (b);
u8 *tag, *iv, *aad = 0;
u8 flag = 0;
esp_post_data_t *post = esp_post_data (b);
u8 *tag, *iv, *aad = 0;
u8 flag = 0;
-
u32
key_index;
+
const u32 key_index = sa->crypto_
key_index;
i16 crypto_start_offset, integ_start_offset;
u16 crypto_total_len, integ_total_len;
i16 crypto_start_offset, integ_start_offset;
u16 crypto_total_len, integ_total_len;
@@
-508,8
+515,6
@@
esp_prepare_async_frame (vlib_main_t *vm, ipsec_per_thread_data_t *ptd,
crypto_total_len = integ_total_len = payload_len - icv_sz;
tag = payload + crypto_total_len;
crypto_total_len = integ_total_len = payload_len - icv_sz;
tag = payload + crypto_total_len;
- key_index = sa->linked_key_index;
-
/* generate the IV in front of the payload */
void *pkt_iv = esp_generate_iv (sa, payload, iv_sz);
/* generate the IV in front of the payload */
void *pkt_iv = esp_generate_iv (sa, payload, iv_sz);
@@
-523,7
+528,12
@@
esp_prepare_async_frame (vlib_main_t *vm, ipsec_per_thread_data_t *ptd,
/* constuct aad in a scratch space in front of the nonce */
aad = (u8 *) nonce - sizeof (esp_aead_t);
esp_aad_fill (aad, esp, sa, sa->seq_hi);
/* constuct aad in a scratch space in front of the nonce */
aad = (u8 *) nonce - sizeof (esp_aead_t);
esp_aad_fill (aad, esp, sa, sa->seq_hi);
- key_index = sa->crypto_key_index;
+ if (PREDICT_FALSE (ipsec_sa_is_set_IS_NULL_GMAC (sa)))
+ {
+ /* RFC-4543 ENCR_NULL_AUTH_AES_GMAC: IV is part of AAD */
+ crypto_start_offset -= iv_sz;
+ crypto_total_len += iv_sz;
+ }
}
else
{
}
else
{
@@
-705,7
+715,7
@@
esp_encrypt_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
is_async = im->async_mode | ipsec_sa_is_set_IS_ASYNC (sa0);
}
is_async = im->async_mode | ipsec_sa_is_set_IS_ASYNC (sa0);
}
- if (PREDICT_FALSE (~0 == sa0->thread_index))
+ if (PREDICT_FALSE (
(u16)
~0 == sa0->thread_index))
{
/* this is the first packet to use this SA, claim the SA
* for this thread. this could happen simultaneously on
{
/* this is the first packet to use this SA, claim the SA
* for this thread. this could happen simultaneously on
@@
-1001,6
+1011,16
@@
esp_encrypt_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
{
async_frames[async_op] =
vnet_crypto_async_get_frame (vm, async_op);
{
async_frames[async_op] =
vnet_crypto_async_get_frame (vm, async_op);
+
+ if (PREDICT_FALSE (!async_frames[async_op]))
+ {
+ err = ESP_ENCRYPT_ERROR_NO_AVAIL_FRAME;
+ esp_encrypt_set_next_index (b[0], node, thread_index, err,
+ n_noop, noop_nexts, drop_next,
+ current_sa_index);
+ goto trace;
+ }
+
/* Save the frame to the list we'll submit at the end */
vec_add1 (ptd->async_frames, async_frames[async_op]);
}
/* Save the frame to the list we'll submit at the end */
vec_add1 (ptd->async_frames, async_frames[async_op]);
}
@@
-1090,7
+1110,7
@@
esp_encrypt_inline (vlib_main_t *vm, vlib_node_runtime_t *node,
n_noop += esp_async_recycle_failed_submit (
vm, *async_frame, node, ESP_ENCRYPT_ERROR_CRYPTO_ENGINE_ERROR,
IPSEC_SA_ERROR_CRYPTO_ENGINE_ERROR, n_noop, noop_bi,
n_noop += esp_async_recycle_failed_submit (
vm, *async_frame, node, ESP_ENCRYPT_ERROR_CRYPTO_ENGINE_ERROR,
IPSEC_SA_ERROR_CRYPTO_ENGINE_ERROR, n_noop, noop_bi,
- noop_nexts, drop_next);
+ noop_nexts, drop_next
, true
);
vnet_crypto_async_reset_frame (*async_frame);
vnet_crypto_async_free_frame (vm, *async_frame);
}
vnet_crypto_async_reset_frame (*async_frame);
vnet_crypto_async_free_frame (vm, *async_frame);
}