Module Name: src Committed By: christos Date: Fri Apr 14 22:29:17 UTC 2017
Modified Files: src/sys/netipsec: xform_ah.c Log Message: - fix old refactoring which zeroed the wrong part of the buffer. - simplify. To generate a diff of this commit: cvs rdiff -u -r1.48 -r1.49 src/sys/netipsec/xform_ah.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/netipsec/xform_ah.c diff -u src/sys/netipsec/xform_ah.c:1.48 src/sys/netipsec/xform_ah.c:1.49 --- src/sys/netipsec/xform_ah.c:1.48 Fri Apr 14 14:06:11 2017 +++ src/sys/netipsec/xform_ah.c Fri Apr 14 18:29:17 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: xform_ah.c,v 1.48 2017/04/14 18:06:11 christos Exp $ */ +/* $NetBSD: xform_ah.c,v 1.49 2017/04/14 22:29:17 christos Exp $ */ /* $FreeBSD: src/sys/netipsec/xform_ah.c,v 1.1.4.1 2003/01/24 05:11:36 sam Exp $ */ /* $OpenBSD: ip_ah.c,v 1.63 2001/06/26 06:18:58 angelos Exp $ */ /* @@ -39,7 +39,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: xform_ah.c,v 1.48 2017/04/14 18:06:11 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: xform_ah.c,v 1.49 2017/04/14 22:29:17 christos Exp $"); #if defined(_KERNEL_OPT) #include "opt_inet.h" @@ -425,7 +425,7 @@ ah_massage_headers(struct mbuf **m0, int /* Zeroize all other options. */ count = ptr[off + 1]; - memcpy(ptr + off, ipseczeroes, count); + memcpy(ptr, ipseczeroes, count); off += count; break; } @@ -722,14 +722,12 @@ ah_input(struct mbuf *m, const struct se } /* Allocate IPsec-specific opaque crypto info. */ - if (mtag == NULL) { - tc = (struct tdb_crypto *) malloc(sizeof (struct tdb_crypto) + - skip + rplen + authsize, M_XDATA, M_NOWAIT|M_ZERO); - } else { - /* Hash verification has already been done successfully. */ - tc = (struct tdb_crypto *) malloc(sizeof (struct tdb_crypto), - M_XDATA, M_NOWAIT|M_ZERO); - } + size_t size = sizeof(*tc); + size_t extra = skip + rplen + authsize; + if (mtag == NULL) + size += extra; + + tc = malloc(size, M_XDATA, M_NOWAIT|M_ZERO); if (tc == NULL) { DPRINTF(("%s: failed to allocate tdb_crypto\n", __func__)); AH_STATINC(AH_STAT_CRYPTO); @@ -738,7 +736,7 @@ ah_input(struct mbuf *m, const struct se return ENOBUFS; } - error = m_makewritable(&m, 0, skip + rplen + authsize, M_NOWAIT); + error = m_makewritable(&m, 0, extra, M_NOWAIT); if (error) { m_freem(m); DPRINTF(("%s: failed to copyback_cow\n", __func__)); @@ -754,8 +752,7 @@ ah_input(struct mbuf *m, const struct se * Save the authenticator, the skipped portion of the packet, * and the AH header. */ - m_copydata(m, 0, skip + rplen + authsize, (tc + 1)); - + m_copydata(m, 0, extra, (tc + 1)); /* Zeroize the authenticator on the packet. */ m_copyback(m, skip + rplen, authsize, ipseczeroes); @@ -788,8 +785,8 @@ ah_input(struct mbuf *m, const struct se tc->tc_skip = skip; tc->tc_ptr = mtag; /* Save the mtag we've identified. */ - DPRINTF(("%s: hash over %d bytes, skip %d: " - "crda len %d skip %d inject %d\n", __func__, + DPRINTF(("%s: mtag %p hash over %d bytes, skip %d: " + "crda len %d skip %d inject %d\n", __func__, mtag, crp->crp_ilen, tc->tc_skip, crda->crd_len, crda->crd_skip, crda->crd_inject)); @@ -906,10 +903,10 @@ ah_input_cb(struct cryptop *crp) */ if (mtag == NULL) { ptr = (char *) (tc + 1); + const u_int8_t *pppp = ptr + skip + rplen; /* Verify authenticator. */ - if (!consttime_memequal(ptr + skip + rplen, calc, authsize)) { - u_int8_t *pppp = ptr + skip+rplen; + if (!consttime_memequal(pppp, calc, authsize)) { DPRINTF(("%s: authentication hash mismatch " \ "over %d bytes " \ "for packet in SA %s/%08lx:\n" \ @@ -1012,9 +1009,9 @@ ah_output( struct tdb_crypto *tc; struct mbuf *mi; struct cryptop *crp; - u_int16_t iplen; + uint16_t iplen; int error, rplen, authsize, maxpacketsize, roff; - u_int8_t prot; + uint8_t prot; struct newah *ah; IPSEC_SPLASSERT_SOFTNET("ah_output"); @@ -1029,16 +1026,19 @@ ah_output( /* Figure out header size. */ rplen = HDRSIZE(sav); + size_t ipoffs; /* Check for maximum packet size violations. */ switch (sav->sah->saidx.dst.sa.sa_family) { #ifdef INET case AF_INET: maxpacketsize = IP_MAXPACKET; + ipoffs = offsetof(struct ip, ip_len); break; #endif /* INET */ #ifdef INET6 case AF_INET6: maxpacketsize = IPV6_MAXPACKET; + ipoffs = offsetof(struct ip6_hdr, ip6_plen); break; #endif /* INET6 */ default: @@ -1145,8 +1145,7 @@ ah_output( crda->crd_klen = _KEYBITS(sav->key_auth); /* Allocate IPsec-specific opaque crypto info. */ - tc = (struct tdb_crypto *) malloc( - sizeof(struct tdb_crypto) + skip, M_XDATA, M_NOWAIT|M_ZERO); + tc = malloc(sizeof(*tc) + skip, M_XDATA, M_NOWAIT|M_ZERO); if (tc == NULL) { crypto_freereq(crp); DPRINTF(("%s: failed to allocate tdb_crypto\n", __func__)); @@ -1155,48 +1154,29 @@ ah_output( goto bad; } + uint8_t *pext = (char *)(tc + 1); /* Save the skipped portion of the packet. */ - m_copydata(m, 0, skip, (tc + 1)); + m_copydata(m, 0, skip, pext); /* * Fix IP header length on the header used for * authentication. We don't need to fix the original * header length as it will be fixed by our caller. */ - switch (sav->sah->saidx.dst.sa.sa_family) { -#ifdef INET - case AF_INET: - bcopy(((char *)(tc + 1)) + - offsetof(struct ip, ip_len), - &iplen, sizeof(u_int16_t)); - iplen = htons(ntohs(iplen) + rplen + authsize); - m_copyback(m, offsetof(struct ip, ip_len), - sizeof(u_int16_t), &iplen); - break; -#endif /* INET */ - -#ifdef INET6 - case AF_INET6: - bcopy(((char *)(tc + 1)) + - offsetof(struct ip6_hdr, ip6_plen), - &iplen, sizeof(u_int16_t)); - iplen = htons(ntohs(iplen) + rplen + authsize); - m_copyback(m, offsetof(struct ip6_hdr, ip6_plen), - sizeof(u_int16_t), &iplen); - break; -#endif /* INET6 */ - } + memcpy(&iplen, pext + ipoffs, sizeof(iplen)); + iplen = htons(ntohs(iplen) + rplen + authsize); + m_copyback(m, ipoffs, sizeof(iplen), &iplen); /* Fix the Next Header field in saved header. */ - ((u_int8_t *) (tc + 1))[protoff] = IPPROTO_AH; + pext[protoff] = IPPROTO_AH; /* Update the Next Protocol field in the IP header. */ prot = IPPROTO_AH; - m_copyback(m, protoff, sizeof(u_int8_t), &prot); + m_copyback(m, protoff, sizeof(prot), &prot); /* "Massage" the packet headers for crypto processing. */ error = ah_massage_headers(&m, sav->sah->saidx.dst.sa.sa_family, - skip, ahx->type, 1); + skip, ahx->type, 1); if (error != 0) { m = NULL; /* mbuf was free'd by ah_massage_headers. */ free(tc, M_XDATA);