svn commit: r221157 - in stable/8: . sys/netipsec sys/opencrypto

VANHULLEBUS Yvan vanhu at FreeBSD.org
Thu Apr 28 08:49:44 UTC 2011


Author: vanhu
Date: Thu Apr 28 08:49:43 2011
New Revision: 221157
URL: http://svn.freebsd.org/changeset/base/221157

Log:
  MFC 218794, 219026:
  Fixed IPsec's HMAC_SHA256-512 support to be RFC4868 compliant.
  This will break interoperability with all older versions of
  FreeBSD for those algorithms.
  
  Reviewed by:	bz, gnn
  Obtained from:	NETASQ

Modified:
  stable/8/UPDATING
  stable/8/sys/netipsec/key.c
  stable/8/sys/netipsec/xform.h
  stable/8/sys/netipsec/xform_ah.c
  stable/8/sys/netipsec/xform_esp.c
  stable/8/sys/opencrypto/xform.h
Directory Properties:
  stable/8/sys/   (props changed)

Modified: stable/8/UPDATING
==============================================================================
--- stable/8/UPDATING	Thu Apr 28 07:34:37 2011	(r221156)
+++ stable/8/UPDATING	Thu Apr 28 08:49:43 2011	(r221157)
@@ -15,6 +15,16 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 8.
 	debugging tools present in HEAD were left in place because
 	sun4v support still needs work to become production ready.
 
+20110428:
+	IPsec's HMAC_SHA256-512 support has been fixed to be RFC4868
+	compliant, and will now use half of hash for authentication.
+	This will break interoperability with all stacks (including all
+	older FreeBSD versions) who implement
+	draft-ietf-ipsec-ciph-sha-256-00 (they use 96 bits of hash for
+	authentication).
+	The only workaround with such peers is to use another HMAC
+	algorithm for IPsec ("phase 2") authentication.
+
 20110221:
 	8.2-RELEASE.
 

Modified: stable/8/sys/netipsec/key.c
==============================================================================
--- stable/8/sys/netipsec/key.c	Thu Apr 28 07:34:37 2011	(r221156)
+++ stable/8/sys/netipsec/key.c	Thu Apr 28 08:49:43 2011	(r221157)
@@ -6103,6 +6103,9 @@ key_getsizes_ah(
 		case SADB_X_AALG_MD5:	*min = *max = 16; break;
 		case SADB_X_AALG_SHA:	*min = *max = 20; break;
 		case SADB_X_AALG_NULL:	*min = 1; *max = 256; break;
+		case SADB_X_AALG_SHA2_256: *min = *max = 32; break;
+		case SADB_X_AALG_SHA2_384: *min = *max = 48; break;
+		case SADB_X_AALG_SHA2_512: *min = *max = 64; break;
 		default:
 			DPRINTF(("%s: unknown AH algorithm %u\n",
 				__func__, alg));
@@ -6128,7 +6131,11 @@ key_getcomb_ah()
 	for (i = 1; i <= SADB_AALG_MAX; i++) {
 #if 1
 		/* we prefer HMAC algorithms, not old algorithms */
-		if (i != SADB_AALG_SHA1HMAC && i != SADB_AALG_MD5HMAC)
+		if (i != SADB_AALG_SHA1HMAC &&
+		    i != SADB_AALG_MD5HMAC  &&
+		    i != SADB_X_AALG_SHA2_256 &&
+		    i != SADB_X_AALG_SHA2_384 &&
+		    i != SADB_X_AALG_SHA2_512)
 			continue;
 #endif
 		algo = ah_algorithm_lookup(i);

Modified: stable/8/sys/netipsec/xform.h
==============================================================================
--- stable/8/sys/netipsec/xform.h	Thu Apr 28 07:34:37 2011	(r221156)
+++ stable/8/sys/netipsec/xform.h	Thu Apr 28 08:49:43 2011	(r221157)
@@ -46,6 +46,7 @@
 #include <opencrypto/xform.h>
 
 #define	AH_HMAC_HASHLEN		12	/* 96 bits of authenticator */
+#define	AH_HMAC_MAXHASHLEN	(SHA2_512_HASH_LEN/2)	/* Keep this updated */
 #define	AH_HMAC_INITIAL_RPL	1	/* replay counter initial value */
 
 /*

Modified: stable/8/sys/netipsec/xform_ah.c
==============================================================================
--- stable/8/sys/netipsec/xform_ah.c	Thu Apr 28 07:34:37 2011	(r221156)
+++ stable/8/sys/netipsec/xform_ah.c	Thu Apr 28 08:49:43 2011	(r221157)
@@ -85,8 +85,7 @@
  * to use a fixed 16-byte authenticator.  The new algorithm use 12-byte
  * authenticator.
  */
-#define	AUTHSIZE(sav) \
-	((sav->flags & SADB_X_EXT_OLD) ? 16 : AH_HMAC_HASHLEN)
+#define	AUTHSIZE(sav)	ah_authsize(sav)
 
 VNET_DEFINE(int, ah_enable) = 1;	/* control flow of packets with AH */
 VNET_DEFINE(int, ah_cleartos) = 1;	/* clear ip_tos when doing AH calc */
@@ -105,6 +104,27 @@ static unsigned char ipseczeroes[256];	/
 static int ah_input_cb(struct cryptop*);
 static int ah_output_cb(struct cryptop*);
 
+static int
+ah_authsize(struct secasvar *sav)
+{
+
+	IPSEC_ASSERT(sav != NULL, ("%s: sav == NULL", __func__));
+
+	if (sav->flags & SADB_X_EXT_OLD)
+		return 16;
+
+	switch (sav->alg_auth) {
+	case SADB_X_AALG_SHA2_256:
+		return 16;
+	case SADB_X_AALG_SHA2_384:
+		return 24;
+	case SADB_X_AALG_SHA2_512:
+		return 32;
+	default:
+		return AH_HMAC_HASHLEN;
+	}
+	/* NOTREACHED */
+}
 /*
  * NB: this is public for use by the PF_KEY support.
  */

Modified: stable/8/sys/netipsec/xform_esp.c
==============================================================================
--- stable/8/sys/netipsec/xform_esp.c	Thu Apr 28 07:34:37 2011	(r221156)
+++ stable/8/sys/netipsec/xform_esp.c	Thu Apr 28 08:49:43 2011	(r221157)
@@ -297,7 +297,19 @@ esp_input(struct mbuf *m, struct secasva
 	else
 		hlen = sizeof (struct newesp) + sav->ivlen;
 	/* Authenticator hash size */
-	alen = esph ? AH_HMAC_HASHLEN : 0;
+	if (esph != NULL) {
+		switch (esph->type) {
+		case CRYPTO_SHA2_256_HMAC:
+		case CRYPTO_SHA2_384_HMAC:
+		case CRYPTO_SHA2_512_HMAC:
+			alen = esph->hashsize/2;
+			break;
+		default:
+			alen = AH_HMAC_HASHLEN;
+			break;
+		}
+	}else
+		alen = 0;
 
 	/*
 	 * Verify payload length is multiple of encryption algorithm
@@ -450,8 +462,8 @@ esp_input(struct mbuf *m, struct secasva
 static int
 esp_input_cb(struct cryptop *crp)
 {
-	u_int8_t lastthree[3], aalg[AH_HMAC_HASHLEN];
-	int hlen, skip, protoff, error;
+	u_int8_t lastthree[3], aalg[AH_HMAC_MAXHASHLEN];
+	int hlen, skip, protoff, error, alen;
 	struct mbuf *m;
 	struct cryptodesc *crd;
 	struct auth_hash *esph;
@@ -519,6 +531,16 @@ esp_input_cb(struct cryptop *crp)
 
 	/* If authentication was performed, check now. */
 	if (esph != NULL) {
+		switch (esph->type) {
+		case CRYPTO_SHA2_256_HMAC:
+		case CRYPTO_SHA2_384_HMAC:
+		case CRYPTO_SHA2_512_HMAC:
+			alen = esph->hashsize/2;
+			break;
+		default:
+			alen = AH_HMAC_HASHLEN;
+			break;
+		}
 		/*
 		 * If we have a tag, it means an IPsec-aware NIC did
 		 * the verification for us.  Otherwise we need to
@@ -527,13 +549,13 @@ esp_input_cb(struct cryptop *crp)
 		V_ahstat.ahs_hist[sav->alg_auth]++;
 		if (mtag == NULL) {
 			/* Copy the authenticator from the packet */
-			m_copydata(m, m->m_pkthdr.len - AH_HMAC_HASHLEN,
-				AH_HMAC_HASHLEN, aalg);
+			m_copydata(m, m->m_pkthdr.len - alen,
+				alen, aalg);
 
 			ptr = (caddr_t) (tc + 1);
 
 			/* Verify authenticator */
-			if (bcmp(ptr, aalg, AH_HMAC_HASHLEN) != 0) {
+			if (bcmp(ptr, aalg, alen) != 0) {
 				DPRINTF(("%s: "
 		    "authentication hash mismatch for packet in SA %s/%08lx\n",
 				    __func__,
@@ -546,7 +568,7 @@ esp_input_cb(struct cryptop *crp)
 		}
 
 		/* Remove trailing authenticator */
-		m_adj(m, -AH_HMAC_HASHLEN);
+		m_adj(m, -alen);
 	}
 
 	/* Release the crypto descriptors */
@@ -690,7 +712,16 @@ esp_output(
 	plen = rlen + padding;		/* Padded payload length. */
 
 	if (esph)
+		switch (esph->type) {
+		case CRYPTO_SHA2_256_HMAC:
+		case CRYPTO_SHA2_384_HMAC:
+		case CRYPTO_SHA2_512_HMAC:
+			alen = esph->hashsize/2;
+			break;
+		default:
 		alen = AH_HMAC_HASHLEN;
+			break;
+		}
 	else
 		alen = 0;
 
@@ -944,7 +975,7 @@ esp_output_cb(struct cryptop *crp)
 #ifdef REGRESSION
 	/* Emulate man-in-the-middle attack when ipsec_integrity is TRUE. */
 	if (V_ipsec_integrity) {
-		static unsigned char ipseczeroes[AH_HMAC_HASHLEN];
+		static unsigned char ipseczeroes[AH_HMAC_MAXHASHLEN];
 		struct auth_hash *esph;
 
 		/*
@@ -953,8 +984,20 @@ esp_output_cb(struct cryptop *crp)
 		 */
 		esph = sav->tdb_authalgxform;
 		if (esph !=  NULL) {
-			m_copyback(m, m->m_pkthdr.len - AH_HMAC_HASHLEN,
-			    AH_HMAC_HASHLEN, ipseczeroes);
+			int alen;
+
+			switch (esph->type) {
+			case CRYPTO_SHA2_256_HMAC:
+			case CRYPTO_SHA2_384_HMAC:
+			case CRYPTO_SHA2_512_HMAC:
+				alen = esph->hashsize/2;
+				break;
+			default:
+				alen = AH_HMAC_HASHLEN;
+				break;
+			}
+			m_copyback(m, m->m_pkthdr.len - alen,
+			    alen, ipseczeroes);
 		}
 	}
 #endif

Modified: stable/8/sys/opencrypto/xform.h
==============================================================================
--- stable/8/sys/opencrypto/xform.h	Thu Apr 28 07:34:37 2011	(r221156)
+++ stable/8/sys/opencrypto/xform.h	Thu Apr 28 08:49:43 2011	(r221157)
@@ -43,7 +43,8 @@ struct auth_hash {
 	void (*Final) (u_int8_t *, void *);
 };
 
-#define	AH_ALEN_MAX	20	/* max authenticator hash length */
+/* XXX use a define common with other hash stuff ! */
+#define	AH_ALEN_MAX	64	/* max authenticator hash length */
 
 struct enc_xform {
 	int type;


More information about the svn-src-all mailing list