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;