Add SHA2 support to IKEv2 implementation
The following patch adds a stronger cryptographic suite to IKEv2 implementation.
The following algorithms can now be used for integrity checking in IKEv2 implementation (responder and initiator):
- hmac-sha2-256-128
- hmac-sha2-384-192
- hmac-sha2-512-256
The default integrity checking method was set to hmac-sha2-256-128.
The default PRF function was set sha2-256.
Change-Id: Ia82b4cbbf3067b19b8487040dbefbaf4c9319548
Signed-off-by: Berenger Foucher <berenger.foucher@stagiaires.ssi.gouv.fr>
diff --git a/src/vnet/ipsec/ikev2.c b/src/vnet/ipsec/ikev2.c
index 34ab87c..05a4bab 100644
--- a/src/vnet/ipsec/ikev2.c
+++ b/src/vnet/ipsec/ikev2.c
@@ -1480,6 +1480,7 @@
ikev2_sa_transform_t *tr;
ikev2_sa_proposal_t *proposals;
u8 encr_type = 0;
+ u8 integ_type = 0;
if (!child->r_proposals)
{
@@ -1550,8 +1551,21 @@
tr = ikev2_sa_get_td_for_type (proposals, IKEV2_TRANSFORM_TYPE_INTEG);
if (tr)
{
- if (tr->integ_type != IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA1_96)
+ switch (tr->integ_type)
{
+ case IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA2_256_128:
+ integ_type = IPSEC_INTEG_ALG_SHA_256_128;
+ break;
+ case IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA2_384_192:
+ integ_type = IPSEC_INTEG_ALG_SHA_384_192;
+ break;
+ case IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA2_512_256:
+ integ_type = IPSEC_INTEG_ALG_SHA_512_256;
+ break;
+ case IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA1_96:
+ integ_type = IPSEC_INTEG_ALG_SHA1_96;
+ break;
+ default:
ikev2_set_state (sa, IKEV2_STATE_NO_PROPOSAL_CHOSEN);
return 1;
}
@@ -1580,7 +1594,7 @@
rem_ckey = child->sk_ei;
}
- a.integ_alg = IPSEC_INTEG_ALG_SHA1_96;
+ a.integ_alg = integ_type;
a.local_integ_key_len = vec_len (loc_ikey);
clib_memcpy (a.local_integ_key, loc_ikey, a.local_integ_key_len);
a.remote_integ_key_len = vec_len (rem_ikey);
@@ -2043,6 +2057,7 @@
}
}
+
static uword
ikev2_node_fn (vlib_main_t * vm,
vlib_node_runtime_t * node, vlib_frame_t * frame)
@@ -2163,7 +2178,7 @@
}
}
}
- else
+ else //received sa_init without initiator flag
{
ikev2_process_sa_init_resp (vm, sa0, ike0);
@@ -2458,7 +2473,7 @@
};
/* *INDENT-ON* */
-
+// set ikev2 proposals when vpp is used as initiator
static clib_error_t *
ikev2_set_initiator_proposals (vlib_main_t * vm, ikev2_sa_t * sa,
ikev2_transforms_set * ts,
@@ -2476,7 +2491,7 @@
vec_foreach (td, km->supported_transforms)
{
if (td->type == IKEV2_TRANSFORM_TYPE_ENCR
- && td->encr_type == IKEV2_TRANSFORM_ENCR_TYPE_AES_CBC
+ && td->encr_type == ts->crypto_alg
&& td->key_len == ts->crypto_key_size / 8)
{
u16 attr[2];
@@ -2501,7 +2516,7 @@
vec_foreach (td, km->supported_transforms)
{
if (td->type == IKEV2_TRANSFORM_TYPE_INTEG
- && td->integ_type == IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA1_96)
+ && td->integ_type == ts->integ_alg)
{
vec_add1 (proposal->transforms, *td);
error = 0;
@@ -2510,6 +2525,8 @@
}
if (error)
{
+ clib_warning
+ ("Didn't find any supported algorithm for IKEV2_TRANSFORM_TYPE_INTEG");
r = clib_error_return (0, "Unsupported algorithm");
return r;
}
@@ -2521,7 +2538,7 @@
vec_foreach (td, km->supported_transforms)
{
if (td->type == IKEV2_TRANSFORM_TYPE_PRF
- && td->prf_type == IKEV2_TRANSFORM_PRF_TYPE_PRF_HMAC_SHA1)
+ && td->prf_type == IKEV2_TRANSFORM_PRF_TYPE_PRF_HMAC_SHA2_256)
{
vec_add1 (proposal->transforms, *td);
error = 0;
diff --git a/src/vnet/ipsec/ikev2_crypto.c b/src/vnet/ipsec/ikev2_crypto.c
index 5a35dfc..d595570 100644
--- a/src/vnet/ipsec/ikev2_crypto.c
+++ b/src/vnet/ipsec/ikev2_crypto.c
@@ -339,6 +339,15 @@
r = vec_new (u8, tr->key_len);
+ if (tr->md == EVP_sha1 ())
+ {
+ clib_warning ("integrity checking with sha1");
+ }
+ else if (tr->md == EVP_sha256 ())
+ {
+ clib_warning ("integrity checking with sha256");
+ }
+
/* verify integrity of data */
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
hctx = HMAC_CTX_new ();
@@ -780,6 +789,9 @@
ikev2_sa_transform_t *tr;
/* vector of supported transforms - in order of preference */
+
+ //Encryption
+
vec_add2 (km->supported_transforms, tr, 1);
tr->type = IKEV2_TRANSFORM_TYPE_ENCR;
tr->encr_type = IKEV2_TRANSFORM_ENCR_TYPE_AES_CBC;
@@ -801,6 +813,28 @@
tr->block_size = 128 / 8;
tr->cipher = EVP_aes_128_cbc ();
+ //PRF
+ vec_add2 (km->supported_transforms, tr, 1);
+ tr->type = IKEV2_TRANSFORM_TYPE_PRF;
+ tr->prf_type = IKEV2_TRANSFORM_PRF_TYPE_PRF_HMAC_SHA2_256;
+ tr->key_len = 256 / 8;
+ tr->key_trunc = 256 / 8;
+ tr->md = EVP_sha256 ();
+
+ vec_add2 (km->supported_transforms, tr, 1);
+ tr->type = IKEV2_TRANSFORM_TYPE_PRF;
+ tr->prf_type = IKEV2_TRANSFORM_PRF_TYPE_PRF_HMAC_SHA2_384;
+ tr->key_len = 384 / 8;
+ tr->key_trunc = 384 / 8;
+ tr->md = EVP_sha384 ();
+
+ vec_add2 (km->supported_transforms, tr, 1);
+ tr->type = IKEV2_TRANSFORM_TYPE_PRF;
+ tr->prf_type = IKEV2_TRANSFORM_PRF_TYPE_PRF_HMAC_SHA2_512;
+ tr->key_len = 512 / 8;
+ tr->key_trunc = 512 / 8;
+ tr->md = EVP_sha512 ();
+
vec_add2 (km->supported_transforms, tr, 1);
tr->type = IKEV2_TRANSFORM_TYPE_PRF;
tr->prf_type = IKEV2_TRANSFORM_PRF_TYPE_PRF_HMAC_SHA1;
@@ -808,6 +842,35 @@
tr->key_trunc = 160 / 8;
tr->md = EVP_sha1 ();
+ //Integrity
+ vec_add2 (km->supported_transforms, tr, 1);
+ tr->type = IKEV2_TRANSFORM_TYPE_INTEG;
+ tr->integ_type = IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA2_256_128;
+ tr->key_len = 256 / 8;
+ tr->key_trunc = 128 / 8;
+ tr->md = EVP_sha256 ();
+
+ vec_add2 (km->supported_transforms, tr, 1);
+ tr->type = IKEV2_TRANSFORM_TYPE_INTEG;
+ tr->integ_type = IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA2_384_192;
+ tr->key_len = 384 / 8;
+ tr->key_trunc = 192 / 8;
+ tr->md = EVP_sha384 ();
+
+ vec_add2 (km->supported_transforms, tr, 1);
+ tr->type = IKEV2_TRANSFORM_TYPE_INTEG;
+ tr->integ_type = IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA2_512_256;
+ tr->key_len = 512 / 8;
+ tr->key_trunc = 256 / 8;
+ tr->md = EVP_sha512 ();
+
+ vec_add2 (km->supported_transforms, tr, 1);
+ tr->type = IKEV2_TRANSFORM_TYPE_INTEG;
+ tr->integ_type = IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA1_160;
+ tr->key_len = 160 / 8;
+ tr->key_trunc = 160 / 8;
+ tr->md = EVP_sha1 ();
+
vec_add2 (km->supported_transforms, tr, 1);
tr->type = IKEV2_TRANSFORM_TYPE_INTEG;
tr->integ_type = IKEV2_TRANSFORM_INTEG_TYPE_AUTH_HMAC_SHA1_96;
@@ -815,6 +878,7 @@
tr->key_trunc = 96 / 8;
tr->md = EVP_sha1 ();
+
#if defined(OPENSSL_NO_CISCO_FECDH)
vec_add2 (km->supported_transforms, tr, 1);
tr->type = IKEV2_TRANSFORM_TYPE_DH;