Author: vanhu
Date: Fri Feb 18 09:40:13 2011
New Revision: 218794
URL: http://svn.freebsd.org/changeset/base/218794

Log:
  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
  MFC after:    1w

Modified:
  head/UPDATING
  head/sys/netipsec/key.c
  head/sys/netipsec/xform.h
  head/sys/netipsec/xform_ah.c
  head/sys/netipsec/xform_esp.c

Modified: head/UPDATING
==============================================================================
--- head/UPDATING       Fri Feb 18 08:38:24 2011        (r218793)
+++ head/UPDATING       Fri Feb 18 09:40:13 2011        (r218794)
@@ -9,6 +9,16 @@ handbook.
 Items affecting the ports and packages system can be found in
 /usr/ports/UPDATING.  Please read that file before running portupgrade.
 
+20110218:
+       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
+       actual 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.
+
 NOTE TO PEOPLE WHO THINK THAT FreeBSD 9.x IS SLOW:
        FreeBSD 9.x has many debugging features turned on, in both the kernel
        and userland.  These features attempt to detect incorrect use of

Modified: head/sys/netipsec/key.c
==============================================================================
--- head/sys/netipsec/key.c     Fri Feb 18 08:38:24 2011        (r218793)
+++ head/sys/netipsec/key.c     Fri Feb 18 09:40:13 2011        (r218794)
@@ -6095,6 +6095,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));
@@ -6120,7 +6123,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: head/sys/netipsec/xform.h
==============================================================================
--- head/sys/netipsec/xform.h   Fri Feb 18 08:38:24 2011        (r218793)
+++ head/sys/netipsec/xform.h   Fri Feb 18 09:40:13 2011        (r218794)
@@ -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: head/sys/netipsec/xform_ah.c
==============================================================================
--- head/sys/netipsec/xform_ah.c        Fri Feb 18 08:38:24 2011        
(r218793)
+++ head/sys/netipsec/xform_ah.c        Fri Feb 18 09:40:13 2011        
(r218794)
@@ -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: head/sys/netipsec/xform_esp.c
==============================================================================
--- head/sys/netipsec/xform_esp.c       Fri Feb 18 08:38:24 2011        
(r218793)
+++ head/sys/netipsec/xform_esp.c       Fri Feb 18 09:40:13 2011        
(r218794)
@@ -303,7 +303,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
@@ -456,8 +468,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;
@@ -525,6 +537,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
@@ -533,13 +555,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__,
@@ -552,7 +574,7 @@ esp_input_cb(struct cryptop *crp)
                }
 
                /* Remove trailing authenticator */
-               m_adj(m, -AH_HMAC_HASHLEN);
+               m_adj(m, -alen);
        }
 
        /* Release the crypto descriptors */
@@ -696,7 +718,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;
 
@@ -950,7 +981,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;
 
                /*
@@ -959,8 +990,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
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to