-/* $OpenBSD: ip_ah.c,v 1.163 2021/10/24 17:08:27 bluhm Exp $ */
+/* $OpenBSD: ip_ah.c,v 1.164 2021/10/24 22:34:19 tobhe Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
ah_input(struct mbuf **mp, struct tdb *tdb, int skip, int protoff)
{
const struct auth_hash *ahx = tdb->tdb_authalgxform;
- struct mbuf *m = *mp;
- struct tdb_crypto *tc = NULL;
- u_int32_t btsx, esn;
- u_int8_t hl;
+ struct mbuf *m = *mp, *m1, *m0;
+ struct cryptodesc *crda = NULL;
+ struct cryptop *crp = NULL;
+ int roff;
+ uint32_t btsx, esn;
+ uint8_t *ptr = NULL;
+ uint8_t hl;
int error, rplen, clen;
- u_int64_t ibytes;
+ uint64_t ibytes;
+ uint64_t rpl;
#ifdef ENCDEBUG
char buf[INET6_ADDRSTRLEN];
#endif
- struct cryptodesc *crda = NULL;
- struct cryptop *crp = NULL;
+ uint8_t calc[AH_ALEN_MAX];
rplen = AH_FLENGTH + sizeof(u_int32_t);
}
/* Allocate IPsec-specific opaque crypto info. */
- tc = malloc(sizeof(*tc) + skip + rplen + ahx->authsize, M_XDATA,
- M_NOWAIT | M_ZERO);
- if (tc == NULL) {
- DPRINTF("failed to allocate tdb_crypto");
+ ptr = malloc(skip + rplen + ahx->authsize, M_XDATA, M_NOWAIT | M_ZERO);
+ if (ptr == NULL) {
+ DPRINTF("failed to allocate buffer");
ahstat_inc(ahs_crypto);
error = ENOBUFS;
goto drop;
* Save the authenticator, the skipped portion of the packet,
* and the AH header.
*/
- m_copydata(m, 0, skip + rplen + ahx->authsize, tc + 1);
+ m_copydata(m, 0, skip + rplen + ahx->authsize, ptr);
/* Zeroize the authenticator on the packet. */
m_copyback(m, skip + rplen, ahx->authsize, ipseczeroes, M_NOWAIT);
crp->crp_buf = (caddr_t)m;
crp->crp_sid = tdb->tdb_cryptoid;
- /* These are passed as-is to the callback. */
- tc->tc_skip = skip;
- tc->tc_protoff = protoff;
- tc->tc_spi = tdb->tdb_spi;
- tc->tc_proto = tdb->tdb_sproto;
- tc->tc_rdomain = tdb->tdb_rdomain;
- memcpy(&tc->tc_dst, &tdb->tdb_dst, sizeof(union sockaddr_union));
- tc->tc_rpl = tdb->tdb_rpl;
-
KERNEL_LOCK();
while ((error = crypto_invoke(crp)) == EAGAIN) {
/* Reset the session ID */
/* Release the crypto descriptors */
crypto_freereq(crp);
-
- return ah_input_cb(tdb, tc, mp, clen);
-
- drop:
- m_freemp(mp);
- crypto_freereq(crp);
- free(tc, M_XDATA, 0);
- return error;
-}
-
-int
-ah_input_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf **mp, int clen)
-{
- const struct auth_hash *ahx = tdb->tdb_authalgxform;
- struct mbuf *m = *mp;
- int roff, rplen, skip, protoff;
- u_int64_t rpl;
- u_int32_t btsx, esn;
- caddr_t ptr;
- unsigned char calc[AH_ALEN_MAX];
- struct mbuf *m1, *m0;
-#ifdef ENCDEBUG
- char buf[INET6_ADDRSTRLEN];
-#endif
-
- NET_ASSERT_LOCKED();
-
- skip = tc->tc_skip;
- protoff = tc->tc_protoff;
- rpl = tc->tc_rpl;
-
- rplen = AH_FLENGTH + sizeof(u_int32_t);
+ crp = NULL;
/* Copy authenticator off the packet. */
m_copydata(m, skip + rplen, ahx->authsize, calc);
- ptr = (caddr_t) (tc + 1);
-
/* Verify authenticator. */
if (timingsafe_bcmp(ptr + skip + rplen, calc, ahx->authsize)) {
DPRINTF("authentication failed for packet in SA %s/%08x",
ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
ntohl(tdb->tdb_spi));
ahstat_inc(ahs_badauth);
- goto baddone;
+ error = -1;
+ goto drop;
}
/* Fix the Next Protocol field. */
- ((u_int8_t *) ptr)[protoff] = ((u_int8_t *) ptr)[skip];
+ ptr[protoff] = ptr[skip];
/* Copyback the saved (uncooked) network headers. */
m_copyback(m, 0, skip, ptr, M_NOWAIT);
+ free(ptr, M_XDATA, 0);
+ ptr = NULL;
+
/* Replay window checking, if applicable. */
if (tdb->tdb_wnd > 0) {
m_copydata(m, skip + offsetof(struct ah, ah_rpl),
ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
ntohl(tdb->tdb_spi));
ahstat_inc(ahs_wrap);
- goto baddone;
+ error = -1;
+ goto drop;
case 2:
DPRINTF("old packet received in SA %s/%08x",
ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
ntohl(tdb->tdb_spi));
ahstat_inc(ahs_replay);
- goto baddone;
+ error = -1;
+ goto drop;
case 3:
DPRINTF("duplicate packet received in SA %s/%08x",
ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
ntohl(tdb->tdb_spi));
ahstat_inc(ahs_replay);
- goto baddone;
+ error = -1;
+ goto drop;
default:
DPRINTF("bogus value from checkreplaywindow() "
"in SA %s/%08x",
ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
ntohl(tdb->tdb_spi));
ahstat_inc(ahs_replay);
- goto baddone;
+ error = -1;
+ goto drop;
}
}
ipsp_address(&tdb->tdb_dst, buf, sizeof(buf)),
ntohl(tdb->tdb_spi));
ahstat_inc(ahs_hdrops);
- goto baddone;
+ error = -1;
+ goto drop;
}
/* Remove the AH header from the mbuf. */
m->m_pkthdr.len -= rplen + ahx->authsize;
}
- free(tc, M_XDATA, 0);
-
return ipsec_common_input_cb(mp, tdb, skip, protoff);
- baddone:
+ drop:
+ free(ptr, M_XDATA, 0);
m_freemp(mp);
- free(tc, M_XDATA, 0);
- return -1;
+ crypto_freereq(crp);
+ return error;
}
/*
{
const struct auth_hash *ahx = tdb->tdb_authalgxform;
struct cryptodesc *crda;
- struct tdb_crypto *tc = NULL;
struct mbuf *mi;
struct cryptop *crp = NULL;
- u_int64_t replay64;
- u_int16_t iplen;
+ uint64_t replay64;
+ uint16_t iplen;
int error, rplen, roff, ilen, olen;
- u_int8_t prot;
+ uint8_t *ptr = NULL;
+ uint8_t prot;
struct ah *ah;
#if NBPFILTER > 0
struct ifnet *encif;
crda->crd_flags |= CRD_F_ESN;
}
- /* Allocate IPsec-specific opaque crypto info. */
- tc = malloc(sizeof(*tc) + skip, M_XDATA, M_NOWAIT | M_ZERO);
- if (tc == NULL) {
- DPRINTF("failed to allocate tdb_crypto");
+ ptr = malloc(skip, M_XDATA, M_NOWAIT | M_ZERO);
+ if (ptr == NULL) {
+ DPRINTF("failed to allocate buffer");
ahstat_inc(ahs_crypto);
error = ENOBUFS;
goto drop;
}
/* Save the skipped portion of the packet. */
- m_copydata(m, 0, skip, tc + 1);
+ m_copydata(m, 0, skip, ptr);
/*
* Fix IP header length on the header used for
*/
switch (tdb->tdb_dst.sa.sa_family) {
case AF_INET:
- memcpy((caddr_t) &iplen, ((caddr_t)(tc + 1)) +
+ memcpy((caddr_t) &iplen, ((caddr_t)ptr) +
offsetof(struct ip, ip_len), sizeof(u_int16_t));
iplen = htons(ntohs(iplen) + rplen + ahx->authsize);
m_copyback(m, offsetof(struct ip, ip_len),
#ifdef INET6
case AF_INET6:
- memcpy((caddr_t) &iplen, ((caddr_t)(tc + 1)) +
+ memcpy((caddr_t) &iplen, ((caddr_t)ptr) +
offsetof(struct ip6_hdr, ip6_plen), sizeof(u_int16_t));
iplen = htons(ntohs(iplen) + rplen + ahx->authsize);
m_copyback(m, offsetof(struct ip6_hdr, ip6_plen),
}
/* Fix the Next Header field in saved header. */
- ((u_int8_t *) (tc + 1))[protoff] = IPPROTO_AH;
+ ptr[protoff] = IPPROTO_AH;
/* Update the Next Protocol field in the IP header. */
prot = IPPROTO_AH;
crp->crp_buf = (caddr_t)m;
crp->crp_sid = tdb->tdb_cryptoid;
- /* These are passed as-is to the callback. */
- tc->tc_skip = skip;
- tc->tc_protoff = protoff;
- tc->tc_spi = tdb->tdb_spi;
- tc->tc_proto = tdb->tdb_sproto;
- tc->tc_rdomain = tdb->tdb_rdomain;
- memcpy(&tc->tc_dst, &tdb->tdb_dst, sizeof(union sockaddr_union));
-
KERNEL_LOCK();
while ((error = crypto_invoke(crp)) == EAGAIN) {
/* Reset the session ID */
/* Release the crypto descriptors */
crypto_freereq(crp);
-
- return ah_output_cb(tdb, tc, m, ilen, olen);
-
- drop:
- m_freem(m);
- crypto_freereq(crp);
- free(tc, M_XDATA, 0);
- return error;
-}
-
-/*
- * AH output callback.
- */
-int
-ah_output_cb(struct tdb *tdb, struct tdb_crypto *tc, struct mbuf *m, int ilen,
- int olen)
-{
- int skip = tc->tc_skip;
- caddr_t ptr = (caddr_t) (tc + 1);
- int error;
+ crp = NULL;
/*
* Copy original headers (with the new protocol number) back
* in place.
*/
m_copyback(m, 0, skip, ptr, M_NOWAIT);
-
- /* No longer needed. */
- free(tc, M_XDATA, 0);
+ free(ptr, M_XDATA, 0);
+ ptr = NULL;
/* Call the IPsec input callback. */
error = ipsp_process_done(m, tdb);
if (error)
ahstat_inc(ahs_outfail);
return error;
+
+ drop:
+ free(ptr, M_XDATA, 0);
+ m_freem(m);
+ crypto_freereq(crp);
+ return error;
}