ipsec: add support for chained buffers
Type: feature Change-Id: Ie072a7c2bbb1e4a77f7001754f01897efd30fc53 Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
This commit is contained in:
committed by
Damjan Marion
parent
16d974ec59
commit
efcad1a9d2
File diff suppressed because it is too large
Load Diff
@@ -122,6 +122,21 @@ UNITTEST_REGISTER_CRYPTO_TEST (nist_aes256_cbc) = {
|
||||
.ciphertext = TEST_DATA (ciphertext256),
|
||||
};
|
||||
|
||||
UNITTEST_REGISTER_CRYPTO_TEST (nist_aes256_cbc_chained) = {
|
||||
.name = "NIST SP 800-38A [chained]",
|
||||
.alg = VNET_CRYPTO_ALG_AES_256_CBC,
|
||||
.iv = TEST_DATA (iv),
|
||||
.key = TEST_DATA (key256),
|
||||
.is_chained = 1,
|
||||
.pt_chunks = {
|
||||
TEST_DATA_CHUNK (plaintext, 0, 32),
|
||||
TEST_DATA_CHUNK (plaintext, 32, 32),
|
||||
},
|
||||
.ct_chunks = {
|
||||
TEST_DATA_CHUNK (ciphertext256, 0, 32),
|
||||
TEST_DATA_CHUNK (ciphertext256, 32, 32),
|
||||
},
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/*
|
||||
|
||||
@@ -244,6 +244,26 @@ UNITTEST_REGISTER_CRYPTO_TEST (aes_gcm256_tc4) = {
|
||||
.aad = TEST_DATA(tc4_aad),
|
||||
.tag = TEST_DATA (tc4_tag256),
|
||||
};
|
||||
|
||||
UNITTEST_REGISTER_CRYPTO_TEST (aes_gcm256_tc4_chain) = {
|
||||
.name = "256-GCM Spec. TC4 [chained]",
|
||||
.alg = VNET_CRYPTO_ALG_AES_256_GCM,
|
||||
.iv = TEST_DATA (tc3_iv),
|
||||
.key = TEST_DATA (tc3_key256),
|
||||
.aad = TEST_DATA(tc4_aad),
|
||||
.tag = TEST_DATA (tc4_tag256),
|
||||
.is_chained = 1,
|
||||
.pt_chunks = {
|
||||
TEST_DATA_CHUNK (tc4_plaintext, 0, 20),
|
||||
TEST_DATA_CHUNK (tc4_plaintext, 20, 20),
|
||||
TEST_DATA_CHUNK (tc4_plaintext, 40, 20),
|
||||
},
|
||||
.ct_chunks = {
|
||||
TEST_DATA_CHUNK (tc4_ciphertext256, 0, 20),
|
||||
TEST_DATA_CHUNK (tc4_ciphertext256, 20, 20),
|
||||
TEST_DATA_CHUNK (tc4_ciphertext256, 40, 20),
|
||||
},
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/*
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#ifndef included_unittest_crypto_crypto_h
|
||||
#define included_unittest_crypto_crypto_h
|
||||
|
||||
#define CRYPTO_TEST_MAX_OP_CHUNKS 8
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 length;
|
||||
@@ -29,6 +31,11 @@ typedef struct unittest_crypto_test_registration
|
||||
vnet_crypto_alg_t alg;
|
||||
unittest_crypto_test_data_t iv, key, digest, plaintext, ciphertext, aad,
|
||||
tag;
|
||||
u8 is_chained;
|
||||
|
||||
/* plaintext and cipher text data used for testing chained buffers */
|
||||
unittest_crypto_test_data_t pt_chunks[CRYPTO_TEST_MAX_OP_CHUNKS + 1];
|
||||
unittest_crypto_test_data_t ct_chunks[CRYPTO_TEST_MAX_OP_CHUNKS + 1];
|
||||
|
||||
/* next */
|
||||
struct unittest_crypto_test_registration *next;
|
||||
@@ -52,6 +59,7 @@ typedef struct
|
||||
extern crypto_test_main_t crypto_test_main;
|
||||
|
||||
#define TEST_DATA(n) { .data = (u8 *) n, .length = sizeof (n)}
|
||||
#define TEST_DATA_CHUNK(s,off,n) { .data = (u8 *) s + off, .length = n}
|
||||
|
||||
#define UNITTEST_REGISTER_CRYPTO_TEST(x) \
|
||||
unittest_crypto_test_registration_t __unittest_crypto_test_##x; \
|
||||
|
||||
@@ -191,6 +191,18 @@ UNITTEST_REGISTER_CRYPTO_TEST (rfc_2202_md5_tc7) = {
|
||||
.plaintext = TEST_DATA (md5_tc7_data),
|
||||
.digest = TEST_DATA (md5_tc7_digest),
|
||||
};
|
||||
|
||||
UNITTEST_REGISTER_CRYPTO_TEST (rfc_2202_md5_tc7_chained) = {
|
||||
.name = "RFC2202 HMAC-MD5 TC7 [chained]",
|
||||
.alg = VNET_CRYPTO_ALG_HMAC_MD5,
|
||||
.key = TEST_DATA (md5_tc6_key),
|
||||
.digest = TEST_DATA (md5_tc7_digest),
|
||||
.is_chained = 1,
|
||||
.pt_chunks = {
|
||||
TEST_DATA_CHUNK (md5_tc7_data, 0, 40),
|
||||
TEST_DATA_CHUNK (md5_tc7_data, 40, 33)
|
||||
},
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/*
|
||||
|
||||
@@ -218,6 +218,21 @@ UNITTEST_REGISTER_CRYPTO_TEST (rfc_2202_sha1_tc7) = {
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
UNITTEST_REGISTER_CRYPTO_TEST (rfc_2202_sha1_tc7_chained) = {
|
||||
.name = "RFC2202 HMAC-SHA-1 TC7 [chained]",
|
||||
.alg = VNET_CRYPTO_ALG_HMAC_SHA1,
|
||||
.key = TEST_DATA (sha1_tc6_key),
|
||||
.digest = TEST_DATA (sha1_tc7_digest),
|
||||
|
||||
.is_chained = 1,
|
||||
.pt_chunks = {
|
||||
TEST_DATA_CHUNK (sha1_tc7_data, 0, 40),
|
||||
TEST_DATA_CHUNK (sha1_tc7_data, 40, 33)
|
||||
},
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/*
|
||||
* fd.io coding-style-patch-verification: ON
|
||||
*
|
||||
|
||||
@@ -584,6 +584,20 @@ UNITTEST_REGISTER_CRYPTO_TEST (rfc4231_tc7_sha512) = {
|
||||
.plaintext = TEST_DATA (tc7_data),
|
||||
.digest = TEST_DATA (tc7_digest_sha512),
|
||||
};
|
||||
|
||||
UNITTEST_REGISTER_CRYPTO_TEST (rfc4231_tc7_sha512_chain) = {
|
||||
.name = "RFC4231 TC7 [chained]",
|
||||
.alg = VNET_CRYPTO_ALG_HMAC_SHA512,
|
||||
.key = TEST_DATA (tc7_key),
|
||||
.digest = TEST_DATA (tc7_digest_sha512),
|
||||
.is_chained = 1,
|
||||
.pt_chunks = {
|
||||
TEST_DATA_CHUNK (tc7_data, 0, 50),
|
||||
TEST_DATA_CHUNK (tc7_data, 50, 50),
|
||||
TEST_DATA_CHUNK (tc7_data, 100, 50),
|
||||
TEST_DATA_CHUNK (tc7_data, 150, 2),
|
||||
},
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/*
|
||||
|
||||
+315
-112
File diff suppressed because it is too large
Load Diff
+24
-6
@@ -74,14 +74,24 @@ format_vnet_crypto_handlers (u8 * s, va_list * args)
|
||||
od = cm->opt_data + id;
|
||||
if (first == 0)
|
||||
s = format (s, "\n%U", format_white_space, indent);
|
||||
s = format (s, "%-20U%-20U", format_vnet_crypto_op_type, od->type,
|
||||
format_vnet_crypto_engine, od->active_engine_index,s);
|
||||
s = format (s, "%-22U%-20U", format_vnet_crypto_op_type, od->type, 0,
|
||||
format_vnet_crypto_engine, od->active_engine_index_simple,s);
|
||||
|
||||
vec_foreach (e, cm->engines)
|
||||
{
|
||||
if (e->ops_handlers[id] != 0)
|
||||
s = format (s, "%U ", format_vnet_crypto_engine, e - cm->engines);
|
||||
}
|
||||
|
||||
s = format (s, "\n%U", format_white_space, indent);
|
||||
s = format (s, "%-22U%-20U", format_vnet_crypto_op_type, od->type, 1,
|
||||
format_vnet_crypto_engine,
|
||||
od->active_engine_index_chained);
|
||||
vec_foreach (e, cm->engines)
|
||||
{
|
||||
if (e->chained_ops_handlers[id] != 0)
|
||||
s = format (s, "%U ", format_vnet_crypto_engine, e - cm->engines);
|
||||
}
|
||||
first = 0;
|
||||
}
|
||||
return s;
|
||||
@@ -98,7 +108,7 @@ show_crypto_handlers_command_fn (vlib_main_t * vm,
|
||||
if (unformat_user (input, unformat_line_input, line_input))
|
||||
unformat_free (line_input);
|
||||
|
||||
vlib_cli_output (vm, "%-20s%-20s%-20s%s", "Algo", "Type", "Active",
|
||||
vlib_cli_output (vm, "%-20s%-22s%-20s%s", "Algo", "Type", "Active",
|
||||
"Candidates");
|
||||
|
||||
for (i = 0; i < VNET_CRYPTO_N_ALGS; i++)
|
||||
@@ -128,6 +138,7 @@ set_crypto_handler_command_fn (vlib_main_t * vm,
|
||||
char **args = 0, *s, **arg, *engine = 0;
|
||||
int all = 0;
|
||||
clib_error_t *error = 0;
|
||||
crypto_op_class_type_t oct = CRYPTO_OP_BOTH;
|
||||
|
||||
if (!unformat_user (input, unformat_line_input, line_input))
|
||||
return 0;
|
||||
@@ -136,6 +147,12 @@ set_crypto_handler_command_fn (vlib_main_t * vm,
|
||||
{
|
||||
if (unformat (line_input, "all"))
|
||||
all = 1;
|
||||
else if (unformat (line_input, "simple"))
|
||||
oct = CRYPTO_OP_SIMPLE;
|
||||
else if (unformat (line_input, "chained"))
|
||||
oct = CRYPTO_OP_CHAINED;
|
||||
else if (unformat (line_input, "both"))
|
||||
oct = CRYPTO_OP_BOTH;
|
||||
else if (unformat (line_input, "%s", &s))
|
||||
vec_add1 (args, s);
|
||||
else
|
||||
@@ -163,7 +180,7 @@ set_crypto_handler_command_fn (vlib_main_t * vm,
|
||||
hash_foreach_mem (key, value, cm->alg_index_by_name,
|
||||
({
|
||||
(void) value;
|
||||
rc += vnet_crypto_set_handler (key, engine);
|
||||
rc += vnet_crypto_set_handler2 (key, engine, oct);
|
||||
}));
|
||||
/* *INDENT-ON* */
|
||||
|
||||
@@ -174,7 +191,7 @@ set_crypto_handler_command_fn (vlib_main_t * vm,
|
||||
{
|
||||
vec_foreach (arg, args)
|
||||
{
|
||||
rc = vnet_crypto_set_handler (arg[0], engine);
|
||||
rc = vnet_crypto_set_handler2 (arg[0], engine, oct);
|
||||
if (rc)
|
||||
{
|
||||
vlib_cli_output (vm, "failed to set engine %s for %s!",
|
||||
@@ -195,7 +212,8 @@ done:
|
||||
VLIB_CLI_COMMAND (set_crypto_handler_command, static) =
|
||||
{
|
||||
.path = "set crypto handler",
|
||||
.short_help = "set crypto handler cipher [cipher2 cipher3 ...] engine",
|
||||
.short_help = "set crypto handler cipher [cipher2 cipher3 ...] engine"
|
||||
" [simple|chained]",
|
||||
.function = set_crypto_handler_command_fn,
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
+144
-39
@@ -19,31 +19,52 @@
|
||||
|
||||
vnet_crypto_main_t crypto_main;
|
||||
|
||||
static_always_inline void
|
||||
crypto_set_op_status (vnet_crypto_op_t * ops[], u32 n_ops, int status)
|
||||
{
|
||||
while (n_ops--)
|
||||
{
|
||||
ops[0]->status = status;
|
||||
ops++;
|
||||
}
|
||||
}
|
||||
|
||||
static_always_inline u32
|
||||
vnet_crypto_process_ops_call_handler (vlib_main_t * vm,
|
||||
vnet_crypto_main_t * cm,
|
||||
vnet_crypto_op_id_t opt,
|
||||
vnet_crypto_op_t * ops[], u32 n_ops)
|
||||
vnet_crypto_op_t * ops[],
|
||||
vnet_crypto_op_chunk_t * chunks,
|
||||
u32 n_ops)
|
||||
{
|
||||
u32 rv = 0;
|
||||
if (n_ops == 0)
|
||||
return 0;
|
||||
|
||||
if (cm->ops_handlers[opt] == 0)
|
||||
if (chunks)
|
||||
{
|
||||
while (n_ops--)
|
||||
{
|
||||
ops[0]->status = VNET_CRYPTO_OP_STATUS_FAIL_NO_HANDLER;
|
||||
ops++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (cm->ops_handlers[opt]) (vm, ops, n_ops);
|
||||
if (cm->chained_ops_handlers[opt] == 0)
|
||||
crypto_set_op_status (ops, n_ops,
|
||||
VNET_CRYPTO_OP_STATUS_FAIL_NO_HANDLER);
|
||||
else
|
||||
rv = (cm->chained_ops_handlers[opt]) (vm, ops, chunks, n_ops);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cm->ops_handlers[opt] == 0)
|
||||
crypto_set_op_status (ops, n_ops,
|
||||
VNET_CRYPTO_OP_STATUS_FAIL_NO_HANDLER);
|
||||
else
|
||||
rv = (cm->ops_handlers[opt]) (vm, ops, n_ops);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
u32
|
||||
vnet_crypto_process_ops (vlib_main_t * vm, vnet_crypto_op_t ops[], u32 n_ops)
|
||||
static_always_inline u32
|
||||
vnet_crypto_process_ops_inline (vlib_main_t * vm, vnet_crypto_op_t ops[],
|
||||
vnet_crypto_op_chunk_t * chunks, u32 n_ops)
|
||||
{
|
||||
vnet_crypto_main_t *cm = &crypto_main;
|
||||
const int op_q_size = VLIB_FRAME_SIZE;
|
||||
@@ -61,7 +82,8 @@ vnet_crypto_process_ops (vlib_main_t * vm, vnet_crypto_op_t ops[], u32 n_ops)
|
||||
if (current_op_type != opt || n_op_queue >= op_q_size)
|
||||
{
|
||||
rv += vnet_crypto_process_ops_call_handler (vm, cm, current_op_type,
|
||||
op_queue, n_op_queue);
|
||||
op_queue, chunks,
|
||||
n_op_queue);
|
||||
n_op_queue = 0;
|
||||
current_op_type = opt;
|
||||
}
|
||||
@@ -70,10 +92,23 @@ vnet_crypto_process_ops (vlib_main_t * vm, vnet_crypto_op_t ops[], u32 n_ops)
|
||||
}
|
||||
|
||||
rv += vnet_crypto_process_ops_call_handler (vm, cm, current_op_type,
|
||||
op_queue, n_op_queue);
|
||||
op_queue, chunks, n_op_queue);
|
||||
return rv;
|
||||
}
|
||||
|
||||
u32
|
||||
vnet_crypto_process_ops (vlib_main_t * vm, vnet_crypto_op_t ops[], u32 n_ops)
|
||||
{
|
||||
return vnet_crypto_process_ops_inline (vm, ops, 0, n_ops);
|
||||
}
|
||||
|
||||
u32
|
||||
vnet_crypto_process_chained_ops (vlib_main_t * vm, vnet_crypto_op_t ops[],
|
||||
vnet_crypto_op_chunk_t * chunks, u32 n_ops)
|
||||
{
|
||||
return vnet_crypto_process_ops_inline (vm, ops, chunks, n_ops);
|
||||
}
|
||||
|
||||
u32
|
||||
vnet_crypto_register_engine (vlib_main_t * vm, char *name, int prio,
|
||||
char *desc)
|
||||
@@ -91,13 +126,40 @@ vnet_crypto_register_engine (vlib_main_t * vm, char *name, int prio,
|
||||
return p - cm->engines;
|
||||
}
|
||||
|
||||
static_always_inline void
|
||||
crypto_set_active_engine (vnet_crypto_op_data_t * od,
|
||||
vnet_crypto_op_id_t id, u32 ei,
|
||||
crypto_op_class_type_t oct)
|
||||
{
|
||||
vnet_crypto_main_t *cm = &crypto_main;
|
||||
vnet_crypto_engine_t *ce = vec_elt_at_index (cm->engines, ei);
|
||||
|
||||
if (oct == CRYPTO_OP_BOTH || oct == CRYPTO_OP_CHAINED)
|
||||
{
|
||||
if (ce->chained_ops_handlers[id])
|
||||
{
|
||||
od->active_engine_index_chained = ei;
|
||||
cm->chained_ops_handlers[id] = ce->chained_ops_handlers[id];
|
||||
}
|
||||
}
|
||||
|
||||
if (oct == CRYPTO_OP_BOTH || oct == CRYPTO_OP_SIMPLE)
|
||||
{
|
||||
if (ce->ops_handlers[id])
|
||||
{
|
||||
od->active_engine_index_simple = ei;
|
||||
cm->ops_handlers[id] = ce->ops_handlers[id];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
vnet_crypto_set_handler (char *alg_name, char *engine)
|
||||
vnet_crypto_set_handler2 (char *alg_name, char *engine,
|
||||
crypto_op_class_type_t oct)
|
||||
{
|
||||
uword *p;
|
||||
vnet_crypto_main_t *cm = &crypto_main;
|
||||
vnet_crypto_alg_data_t *ad;
|
||||
vnet_crypto_engine_t *ce;
|
||||
int i;
|
||||
|
||||
p = hash_get_mem (cm->alg_index_by_name, alg_name);
|
||||
@@ -110,20 +172,15 @@ vnet_crypto_set_handler (char *alg_name, char *engine)
|
||||
if (!p)
|
||||
return -1;
|
||||
|
||||
ce = vec_elt_at_index (cm->engines, p[0]);
|
||||
|
||||
for (i = 0; i < VNET_CRYPTO_OP_N_TYPES; i++)
|
||||
for (i = 0; i < VNET_CRYPTO_OP_N_TYPES; i += 2)
|
||||
{
|
||||
vnet_crypto_op_data_t *od;
|
||||
vnet_crypto_op_id_t id = ad->op_by_type[i];
|
||||
if (id == 0)
|
||||
continue;
|
||||
|
||||
od = cm->opt_data + id;
|
||||
if (ce->ops_handlers[id])
|
||||
{
|
||||
od->active_engine_index = p[0];
|
||||
cm->ops_handlers[id] = ce->ops_handlers[id];
|
||||
}
|
||||
crypto_set_active_engine (od, id, p[0], oct);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -138,33 +195,77 @@ vnet_crypto_is_set_handler (vnet_crypto_alg_t alg)
|
||||
}
|
||||
|
||||
void
|
||||
vnet_crypto_register_ops_handler (vlib_main_t * vm, u32 engine_index,
|
||||
vnet_crypto_op_id_t opt,
|
||||
vnet_crypto_ops_handler_t * fn)
|
||||
vnet_crypto_register_ops_handler_inline (vlib_main_t * vm, u32 engine_index,
|
||||
vnet_crypto_op_id_t opt,
|
||||
vnet_crypto_ops_handler_t * fn,
|
||||
vnet_crypto_chained_ops_handler_t *
|
||||
cfn)
|
||||
{
|
||||
vnet_crypto_main_t *cm = &crypto_main;
|
||||
vnet_crypto_engine_t *ae, *e = vec_elt_at_index (cm->engines, engine_index);
|
||||
vnet_crypto_op_data_t *otd = cm->opt_data + opt;
|
||||
vec_validate_aligned (cm->ops_handlers, VNET_CRYPTO_N_OP_IDS - 1,
|
||||
CLIB_CACHE_LINE_BYTES);
|
||||
e->ops_handlers[opt] = fn;
|
||||
vec_validate_aligned (cm->chained_ops_handlers, VNET_CRYPTO_N_OP_IDS - 1,
|
||||
CLIB_CACHE_LINE_BYTES);
|
||||
|
||||
if (otd->active_engine_index == ~0)
|
||||
if (fn)
|
||||
{
|
||||
otd->active_engine_index = engine_index;
|
||||
cm->ops_handlers[opt] = fn;
|
||||
return;
|
||||
e->ops_handlers[opt] = fn;
|
||||
if (otd->active_engine_index_simple == ~0)
|
||||
{
|
||||
otd->active_engine_index_simple = engine_index;
|
||||
cm->ops_handlers[opt] = fn;
|
||||
}
|
||||
|
||||
ae = vec_elt_at_index (cm->engines, otd->active_engine_index_simple);
|
||||
if (ae->priority < e->priority)
|
||||
crypto_set_active_engine (otd, opt, engine_index, CRYPTO_OP_SIMPLE);
|
||||
}
|
||||
ae = vec_elt_at_index (cm->engines, otd->active_engine_index);
|
||||
if (ae->priority < e->priority)
|
||||
|
||||
if (cfn)
|
||||
{
|
||||
otd->active_engine_index = engine_index;
|
||||
cm->ops_handlers[opt] = fn;
|
||||
e->chained_ops_handlers[opt] = cfn;
|
||||
if (otd->active_engine_index_chained == ~0)
|
||||
{
|
||||
otd->active_engine_index_chained = engine_index;
|
||||
cm->chained_ops_handlers[opt] = cfn;
|
||||
}
|
||||
|
||||
ae = vec_elt_at_index (cm->engines, otd->active_engine_index_chained);
|
||||
if (ae->priority < e->priority)
|
||||
crypto_set_active_engine (otd, opt, engine_index, CRYPTO_OP_CHAINED);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
vnet_crypto_register_ops_handler (vlib_main_t * vm, u32 engine_index,
|
||||
vnet_crypto_op_id_t opt,
|
||||
vnet_crypto_ops_handler_t * fn)
|
||||
{
|
||||
vnet_crypto_register_ops_handler_inline (vm, engine_index, opt, fn, 0);
|
||||
}
|
||||
|
||||
void
|
||||
vnet_crypto_register_chained_ops_handler (vlib_main_t * vm, u32 engine_index,
|
||||
vnet_crypto_op_id_t opt,
|
||||
vnet_crypto_chained_ops_handler_t *
|
||||
fn)
|
||||
{
|
||||
vnet_crypto_register_ops_handler_inline (vm, engine_index, opt, 0, fn);
|
||||
}
|
||||
|
||||
void
|
||||
vnet_crypto_register_ops_handlers (vlib_main_t * vm, u32 engine_index,
|
||||
vnet_crypto_op_id_t opt,
|
||||
vnet_crypto_ops_handler_t * fn,
|
||||
vnet_crypto_chained_ops_handler_t * cfn)
|
||||
{
|
||||
vnet_crypto_register_ops_handler_inline (vm, engine_index, opt, fn, cfn);
|
||||
}
|
||||
|
||||
void
|
||||
vnet_crypto_register_key_handler (vlib_main_t * vm, u32 engine_index,
|
||||
vnet_crypto_key_handler_t * key_handler)
|
||||
@@ -253,10 +354,13 @@ vnet_crypto_init_cipher_data (vnet_crypto_alg_t alg, vnet_crypto_op_id_t eid,
|
||||
{
|
||||
vnet_crypto_op_type_t eopt, dopt;
|
||||
vnet_crypto_main_t *cm = &crypto_main;
|
||||
|
||||
cm->algs[alg].name = name;
|
||||
cm->opt_data[eid].alg = cm->opt_data[did].alg = alg;
|
||||
cm->opt_data[eid].active_engine_index = ~0;
|
||||
cm->opt_data[did].active_engine_index = ~0;
|
||||
cm->opt_data[eid].active_engine_index_simple = ~0;
|
||||
cm->opt_data[did].active_engine_index_simple = ~0;
|
||||
cm->opt_data[eid].active_engine_index_chained = ~0;
|
||||
cm->opt_data[did].active_engine_index_chained = ~0;
|
||||
if (is_aead)
|
||||
{
|
||||
eopt = VNET_CRYPTO_OP_TYPE_AEAD_ENCRYPT;
|
||||
@@ -282,7 +386,8 @@ vnet_crypto_init_hmac_data (vnet_crypto_alg_t alg,
|
||||
cm->algs[alg].name = name;
|
||||
cm->algs[alg].op_by_type[VNET_CRYPTO_OP_TYPE_HMAC] = id;
|
||||
cm->opt_data[id].alg = alg;
|
||||
cm->opt_data[id].active_engine_index = ~0;
|
||||
cm->opt_data[id].active_engine_index_simple = ~0;
|
||||
cm->opt_data[id].active_engine_index_chained = ~0;
|
||||
cm->opt_data[id].type = VNET_CRYPTO_OP_TYPE_HMAC;
|
||||
hash_set_mem (cm->alg_index_by_name, name, alg);
|
||||
}
|
||||
|
||||
+85
-10
@@ -116,38 +116,82 @@ typedef enum
|
||||
} vnet_crypto_op_id_t;
|
||||
/* *INDENT-ON* */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CRYPTO_OP_SIMPLE,
|
||||
CRYPTO_OP_CHAINED,
|
||||
CRYPTO_OP_BOTH,
|
||||
} crypto_op_class_type_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *name;
|
||||
vnet_crypto_op_id_t op_by_type[VNET_CRYPTO_OP_N_TYPES];
|
||||
} vnet_crypto_alg_data_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 *src;
|
||||
u8 *dst;
|
||||
u32 len;
|
||||
} vnet_crypto_op_chunk_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
|
||||
uword user_data;
|
||||
vnet_crypto_op_id_t op:16;
|
||||
vnet_crypto_op_status_t status:8;
|
||||
u8 flags;
|
||||
#define VNET_CRYPTO_OP_FLAG_INIT_IV (1 << 0)
|
||||
#define VNET_CRYPTO_OP_FLAG_HMAC_CHECK (1 << 1)
|
||||
u32 key_index;
|
||||
u32 len;
|
||||
#define VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS (1 << 2)
|
||||
|
||||
union
|
||||
{
|
||||
u8 digest_len;
|
||||
u8 tag_len;
|
||||
};
|
||||
u16 aad_len;
|
||||
u8 digest_len, tag_len;
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
u8 *src;
|
||||
u8 *dst;
|
||||
};
|
||||
|
||||
/* valid if VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS is set */
|
||||
u16 n_chunks;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
u32 len;
|
||||
/* valid if VNET_CRYPTO_OP_FLAG_CHAINED_BUFFERS is set */
|
||||
u32 chunk_index;
|
||||
};
|
||||
|
||||
u32 key_index;
|
||||
u8 *iv;
|
||||
u8 *src;
|
||||
u8 *dst;
|
||||
u8 *aad;
|
||||
u8 *tag;
|
||||
u8 *digest;
|
||||
uword user_data;
|
||||
|
||||
union
|
||||
{
|
||||
u8 *tag;
|
||||
u8 *digest;
|
||||
};
|
||||
} vnet_crypto_op_t;
|
||||
|
||||
STATIC_ASSERT_SIZEOF (vnet_crypto_op_t, CLIB_CACHE_LINE_BYTES);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
vnet_crypto_op_type_t type;
|
||||
vnet_crypto_alg_t alg;
|
||||
u32 active_engine_index;
|
||||
u32 active_engine_index_simple;
|
||||
u32 active_engine_index_chained;
|
||||
} vnet_crypto_op_data_t;
|
||||
|
||||
typedef struct
|
||||
@@ -158,6 +202,11 @@ typedef struct
|
||||
|
||||
typedef u32 vnet_crypto_key_index_t;
|
||||
|
||||
typedef u32 (vnet_crypto_chained_ops_handler_t) (vlib_main_t * vm,
|
||||
vnet_crypto_op_t * ops[],
|
||||
vnet_crypto_op_chunk_t *
|
||||
chunks, u32 n_ops);
|
||||
|
||||
typedef u32 (vnet_crypto_ops_handler_t) (vlib_main_t * vm,
|
||||
vnet_crypto_op_t * ops[], u32 n_ops);
|
||||
|
||||
@@ -171,6 +220,18 @@ u32 vnet_crypto_register_engine (vlib_main_t * vm, char *name, int prio,
|
||||
void vnet_crypto_register_ops_handler (vlib_main_t * vm, u32 engine_index,
|
||||
vnet_crypto_op_id_t opt,
|
||||
vnet_crypto_ops_handler_t * oph);
|
||||
|
||||
void vnet_crypto_register_chained_ops_handler (vlib_main_t * vm,
|
||||
u32 engine_index,
|
||||
vnet_crypto_op_id_t opt,
|
||||
vnet_crypto_chained_ops_handler_t
|
||||
* oph);
|
||||
void vnet_crypto_register_ops_handlers (vlib_main_t * vm, u32 engine_index,
|
||||
vnet_crypto_op_id_t opt,
|
||||
vnet_crypto_ops_handler_t * fn,
|
||||
vnet_crypto_chained_ops_handler_t *
|
||||
cfn);
|
||||
|
||||
void vnet_crypto_register_key_handler (vlib_main_t * vm, u32 engine_index,
|
||||
vnet_crypto_key_handler_t * keyh);
|
||||
|
||||
@@ -181,6 +242,8 @@ typedef struct
|
||||
int priority;
|
||||
vnet_crypto_key_handler_t *key_op_handler;
|
||||
vnet_crypto_ops_handler_t *ops_handlers[VNET_CRYPTO_N_OP_IDS];
|
||||
vnet_crypto_chained_ops_handler_t
|
||||
* chained_ops_handlers[VNET_CRYPTO_N_OP_IDS];
|
||||
} vnet_crypto_engine_t;
|
||||
|
||||
typedef struct
|
||||
@@ -188,6 +251,7 @@ typedef struct
|
||||
vnet_crypto_alg_data_t *algs;
|
||||
vnet_crypto_thread_t *threads;
|
||||
vnet_crypto_ops_handler_t **ops_handlers;
|
||||
vnet_crypto_chained_ops_handler_t **chained_ops_handlers;
|
||||
vnet_crypto_op_data_t opt_data[VNET_CRYPTO_N_OP_IDS];
|
||||
vnet_crypto_engine_t *engines;
|
||||
vnet_crypto_key_t *keys;
|
||||
@@ -200,10 +264,14 @@ extern vnet_crypto_main_t crypto_main;
|
||||
u32 vnet_crypto_submit_ops (vlib_main_t * vm, vnet_crypto_op_t ** jobs,
|
||||
u32 n_jobs);
|
||||
|
||||
u32 vnet_crypto_process_chained_ops (vlib_main_t * vm, vnet_crypto_op_t ops[],
|
||||
vnet_crypto_op_chunk_t * chunks,
|
||||
u32 n_ops);
|
||||
u32 vnet_crypto_process_ops (vlib_main_t * vm, vnet_crypto_op_t ops[],
|
||||
u32 n_ops);
|
||||
|
||||
int vnet_crypto_set_handler (char *ops_handler_name, char *engine);
|
||||
int vnet_crypto_set_handler2 (char *ops_handler_name, char *engine,
|
||||
crypto_op_class_type_t oct);
|
||||
int vnet_crypto_is_set_handler (vnet_crypto_alg_t alg);
|
||||
|
||||
u32 vnet_crypto_key_add (vlib_main_t * vm, vnet_crypto_alg_t alg,
|
||||
@@ -225,6 +293,7 @@ vnet_crypto_op_init (vnet_crypto_op_t * op, vnet_crypto_op_id_t type)
|
||||
op->op = type;
|
||||
op->flags = 0;
|
||||
op->key_index = ~0;
|
||||
op->n_chunks = 0;
|
||||
}
|
||||
|
||||
static_always_inline vnet_crypto_op_type_t
|
||||
@@ -243,6 +312,12 @@ vnet_crypto_get_key (vnet_crypto_key_index_t index)
|
||||
return vec_elt_at_index (cm->keys, index);
|
||||
}
|
||||
|
||||
static_always_inline int
|
||||
vnet_crypto_set_handler (char *alg_name, char *engine)
|
||||
{
|
||||
return vnet_crypto_set_handler2 (alg_name, engine, CRYPTO_OP_BOTH);
|
||||
}
|
||||
|
||||
#endif /* included_vnet_crypto_crypto_h */
|
||||
|
||||
/*
|
||||
|
||||
@@ -54,7 +54,7 @@ format_vnet_crypto_op (u8 * s, va_list * args)
|
||||
vnet_crypto_op_id_t op = va_arg (*args, int); // vnet_crypto_op_id_t);
|
||||
vnet_crypto_op_data_t *otd = cm->opt_data + op;
|
||||
|
||||
return format (s, "%U-%U", format_vnet_crypto_op_type, otd->type,
|
||||
return format (s, "%U-%U", format_vnet_crypto_op_type, otd->type, 0,
|
||||
format_vnet_crypto_alg, otd->alg);
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ u8 *
|
||||
format_vnet_crypto_op_type (u8 * s, va_list * args)
|
||||
{
|
||||
vnet_crypto_op_type_t opt = va_arg (*args, vnet_crypto_op_type_t);
|
||||
int is_chained = va_arg (*args, int);
|
||||
char *strings[] = {
|
||||
#define _(n, s) [VNET_CRYPTO_OP_TYPE_##n] = s,
|
||||
foreach_crypto_op_type
|
||||
@@ -71,7 +72,7 @@ format_vnet_crypto_op_type (u8 * s, va_list * args)
|
||||
if (opt >= VNET_CRYPTO_OP_N_TYPES)
|
||||
return format (s, "unknown");
|
||||
|
||||
return format (s, "%s", strings[opt]);
|
||||
return format (s, "%s%s", strings[opt], is_chained ? "-chained" : "");
|
||||
}
|
||||
|
||||
u8 *
|
||||
|
||||
+369
-75
File diff suppressed because it is too large
Load Diff
+161
-22
File diff suppressed because it is too large
Load Diff
@@ -90,8 +90,12 @@ typedef struct
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
|
||||
vnet_crypto_op_t *crypto_ops;
|
||||
vnet_crypto_op_t *integ_ops;
|
||||
vnet_crypto_op_t *chained_crypto_ops;
|
||||
vnet_crypto_op_t *chained_integ_ops;
|
||||
vnet_crypto_op_chunk_t *chunks;
|
||||
} ipsec_per_thread_data_t;
|
||||
|
||||
typedef struct
|
||||
|
||||
+11
-47
@@ -556,7 +556,7 @@ class IpsecTra4(object):
|
||||
p.scapy_tra_sa.seq_num = 351
|
||||
p.vpp_tra_sa.seq_num = 351
|
||||
|
||||
def verify_tra_basic4(self, count=1):
|
||||
def verify_tra_basic4(self, count=1, payload_size=54):
|
||||
""" ipsec v4 transport basic test """
|
||||
self.vapi.cli("clear errors")
|
||||
self.vapi.cli("clear ipsec sa")
|
||||
@@ -565,7 +565,8 @@ class IpsecTra4(object):
|
||||
send_pkts = self.gen_encrypt_pkts(p.scapy_tra_sa, self.tra_if,
|
||||
src=self.tra_if.remote_ip4,
|
||||
dst=self.tra_if.local_ip4,
|
||||
count=count)
|
||||
count=count,
|
||||
payload_size=payload_size)
|
||||
recv_pkts = self.send_and_expect(self.tra_if, send_pkts,
|
||||
self.tra_if)
|
||||
for rx in recv_pkts:
|
||||
@@ -611,14 +612,16 @@ class IpsecTra4Tests(IpsecTra4):
|
||||
|
||||
class IpsecTra6(object):
|
||||
""" verify methods for Transport v6 """
|
||||
def verify_tra_basic6(self, count=1):
|
||||
def verify_tra_basic6(self, count=1, payload_size=54):
|
||||
self.vapi.cli("clear errors")
|
||||
self.vapi.cli("clear ipsec sa")
|
||||
try:
|
||||
p = self.params[socket.AF_INET6]
|
||||
send_pkts = self.gen_encrypt_pkts6(p.scapy_tra_sa, self.tra_if,
|
||||
src=self.tra_if.remote_ip6,
|
||||
dst=self.tra_if.local_ip6,
|
||||
count=count)
|
||||
count=count,
|
||||
payload_size=payload_size)
|
||||
recv_pkts = self.send_and_expect(self.tra_if, send_pkts,
|
||||
self.tra_if)
|
||||
for rx in recv_pkts:
|
||||
@@ -834,7 +837,8 @@ class IpsecTun4(object):
|
||||
send_pkts = self.gen_encrypt_pkts(p.scapy_tun_sa, self.tun_if,
|
||||
src=p.remote_tun_if_host,
|
||||
dst=self.pg1.remote_ip4,
|
||||
count=count)
|
||||
count=count,
|
||||
payload_size=payload_size)
|
||||
recv_pkts = self.send_and_expect(self.tun_if, send_pkts, self.pg1)
|
||||
self.verify_decrypted(p, recv_pkts)
|
||||
|
||||
@@ -857,41 +861,6 @@ class IpsecTun4(object):
|
||||
self.logger.info(self.vapi.ppcli("show ipsec sa 4"))
|
||||
self.verify_counters4(p, count, n_rx)
|
||||
|
||||
""" verify methods for Transport v4 """
|
||||
def verify_tun_44_bad_packet_sizes(self, p):
|
||||
# with a buffer size of 2048, 1989 bytes of payload
|
||||
# means there isn't space to insert the ESP header
|
||||
N_PKTS = 63
|
||||
for p_siz in [1989, 8500]:
|
||||
send_pkts = self.gen_encrypt_pkts(p.scapy_tun_sa, self.tun_if,
|
||||
src=p.remote_tun_if_host,
|
||||
dst=self.pg1.remote_ip4,
|
||||
count=N_PKTS,
|
||||
payload_size=p_siz)
|
||||
self.send_and_assert_no_replies(self.tun_if, send_pkts)
|
||||
send_pkts = self.gen_pkts(self.pg1, src=self.pg1.remote_ip4,
|
||||
dst=p.remote_tun_if_host, count=N_PKTS,
|
||||
payload_size=p_siz)
|
||||
self.send_and_assert_no_replies(self.pg1, send_pkts,
|
||||
self.tun_if)
|
||||
|
||||
# both large packets on decrpyt count against chained buffers
|
||||
# the 9000 bytes one does on encrypt
|
||||
self.assertEqual(2 * N_PKTS,
|
||||
self.statistics.get_err_counter(
|
||||
'/err/%s/chained buffers (packet dropped)' %
|
||||
self.tun4_decrypt_node_name))
|
||||
self.assertEqual(N_PKTS,
|
||||
self.statistics.get_err_counter(
|
||||
'/err/%s/chained buffers (packet dropped)' %
|
||||
self.tun4_encrypt_node_name))
|
||||
|
||||
# on encrypt the 1989 size is no trailer space
|
||||
self.assertEqual(N_PKTS,
|
||||
self.statistics.get_err_counter(
|
||||
'/err/%s/no trailer space (packet dropped)' %
|
||||
self.tun4_encrypt_node_name))
|
||||
|
||||
def verify_tun_reass_44(self, p):
|
||||
self.vapi.cli("clear errors")
|
||||
self.vapi.ip_reassembly_enable_disable(
|
||||
@@ -996,12 +965,6 @@ class IpsecTun4Tests(IpsecTun4):
|
||||
self.verify_tun_44(self.params[socket.AF_INET], count=127)
|
||||
|
||||
|
||||
class IpsecTunEsp4Tests(IpsecTun4):
|
||||
def test_tun_bad_packet_sizes(self):
|
||||
""" ipsec v4 tunnel bad packet size """
|
||||
self.verify_tun_44_bad_packet_sizes(self.params[socket.AF_INET])
|
||||
|
||||
|
||||
class IpsecTun6(object):
|
||||
""" verify methods for Tunnel v6 """
|
||||
def verify_counters6(self, p_in, p_out, count, worker=None):
|
||||
@@ -1064,7 +1027,8 @@ class IpsecTun6(object):
|
||||
send_pkts = self.gen_encrypt_pkts6(p_in.scapy_tun_sa, self.tun_if,
|
||||
src=p_in.remote_tun_if_host,
|
||||
dst=self.pg1.remote_ip6,
|
||||
count=count)
|
||||
count=count,
|
||||
payload_size=payload_size)
|
||||
recv_pkts = self.send_and_expect(self.tun_if, send_pkts, self.pg1)
|
||||
self.verify_decrypted6(p_in, recv_pkts)
|
||||
|
||||
|
||||
+19
-4
@@ -10,7 +10,7 @@ from template_ipsec import IpsecTra46Tests, IpsecTun46Tests, TemplateIpsec, \
|
||||
config_tun_params, IPsecIPv4Params, IPsecIPv6Params, \
|
||||
IpsecTra4, IpsecTun4, IpsecTra6, IpsecTun6, \
|
||||
IpsecTun6HandoffTests, IpsecTun4HandoffTests, \
|
||||
IpsecTra6ExtTests, IpsecTunEsp4Tests
|
||||
IpsecTra6ExtTests
|
||||
from vpp_ipsec import VppIpsecSpd, VppIpsecSpdEntry, VppIpsecSA,\
|
||||
VppIpsecSpdItfBinding
|
||||
from vpp_ip_route import VppIpRoute, VppRoutePath
|
||||
@@ -18,6 +18,7 @@ from vpp_ip import DpoProto
|
||||
from vpp_papi import VppEnum
|
||||
|
||||
NUM_PKTS = 67
|
||||
engines_supporting_chain_bufs = ["openssl"]
|
||||
|
||||
|
||||
class ConfigIpsecESP(TemplateIpsec):
|
||||
@@ -288,8 +289,7 @@ class TemplateIpsecEsp(ConfigIpsecESP):
|
||||
|
||||
|
||||
class TestIpsecEsp1(TemplateIpsecEsp, IpsecTra46Tests,
|
||||
IpsecTun46Tests, IpsecTunEsp4Tests,
|
||||
IpsecTra6ExtTests):
|
||||
IpsecTun46Tests, IpsecTra6ExtTests):
|
||||
""" Ipsec ESP - TUN & TRA tests """
|
||||
pass
|
||||
|
||||
@@ -469,7 +469,7 @@ class RunTestIpsecEspAll(ConfigIpsecESP,
|
||||
def run_test(self):
|
||||
self.run_a_test(self.engine, self.flag, self.algo)
|
||||
|
||||
def run_a_test(self, engine, flag, algo):
|
||||
def run_a_test(self, engine, flag, algo, payload_size=None):
|
||||
self.vapi.cli("set crypto handler all %s" % engine)
|
||||
|
||||
self.ipv4_params = IPsecIPv4Params()
|
||||
@@ -508,6 +508,21 @@ class RunTestIpsecEspAll(ConfigIpsecESP,
|
||||
self.verify_tun_44(self.params[socket.AF_INET],
|
||||
count=NUM_PKTS)
|
||||
|
||||
LARGE_PKT_SZ = [
|
||||
4010, # ICV ends up splitted accross 2 buffers in esp_decrypt
|
||||
# for transport4; transport6 takes normal path
|
||||
|
||||
4020, # same as above but tra4 and tra6 are switched
|
||||
]
|
||||
if self.engine in engines_supporting_chain_bufs:
|
||||
for sz in LARGE_PKT_SZ:
|
||||
self.verify_tra_basic4(count=NUM_PKTS, payload_size=sz)
|
||||
self.verify_tra_basic6(count=NUM_PKTS, payload_size=sz)
|
||||
self.verify_tun_66(self.params[socket.AF_INET6],
|
||||
count=NUM_PKTS, payload_size=sz)
|
||||
self.verify_tun_44(self.params[socket.AF_INET],
|
||||
count=NUM_PKTS, payload_size=sz)
|
||||
|
||||
#
|
||||
# remove the SPDs, SAs, etc
|
||||
#
|
||||
|
||||
Reference in New Issue
Block a user