Date: Thu, 28 Apr 2011 08:49:43 +0000 (UTC) From: VANHULLEBUS Yvan <vanhu@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org Subject: svn commit: r221157 - in stable/8: . sys/netipsec sys/opencrypto Message-ID: <201104280849.p3S8nhgN014130@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201104280849.p3S8nhgN014130>