summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Friedl <markus@cvs.openbsd.org>2004-06-08 19:47:25 +0000
committerMarkus Friedl <markus@cvs.openbsd.org>2004-06-08 19:47:25 +0000
commitb3f24646e2fb015bc166f8f92151871622fb9c02 (patch)
treeb46f681348bf994fceacfb2f933bd16ccf03ac62
parent49f35b7ba3eab70964cebbc937c6eca40ec9ffe1 (diff)
factor out md5 code; ok+tests henning@, djm@, hshoexer@
-rw-r--r--sys/netinet/tcp_input.c138
-rw-r--r--sys/netinet/tcp_output.c75
-rw-r--r--sys/netinet/tcp_subr.c77
-rw-r--r--sys/netinet/tcp_var.h4
4 files changed, 96 insertions, 198 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index a11b872a3bc..0be4cb792c6 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_input.c,v 1.171 2004/05/31 11:02:11 markus Exp $ */
+/* $OpenBSD: tcp_input.c,v 1.172 2004/06/08 19:47:24 markus Exp $ */
/* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */
/*
@@ -109,10 +109,6 @@ struct tcpipv6hdr tcp_saveti6;
#define M_V4_LEN(m) (M_PH_LEN(m) - sizeof(struct ip))
#endif /* INET6 */
-#ifdef TCP_SIGNATURE
-#include <crypto/md5.h>
-#endif
-
int tcprexmtthresh = 3;
int tcptv_keep_init = TCPTV_KEEP_INIT;
@@ -2188,10 +2184,7 @@ tcp_dooptions(tp, cp, cnt, th, m, iphlen, oi)
struct tdb *tdb = NULL;
#endif /* TCP_SIGNATURE */
-#ifdef TCP_SIGNATURE
- if (cp)
-#endif /* TCP_SIGNATURE */
- for (; cnt > 0; cnt -= optlen, cp += optlen) {
+ for (; cp && cnt > 0; cnt -= optlen, cp += optlen) {
opt = cp[0];
if (opt == TCPOPT_EOL)
break;
@@ -2323,7 +2316,6 @@ tcp_dooptions(tp, cp, cnt, th, m, iphlen, oi)
}
if (sigp) {
- MD5_CTX ctx;
char sig[16];
if (tdb == NULL) {
@@ -2331,77 +2323,8 @@ tcp_dooptions(tp, cp, cnt, th, m, iphlen, oi)
return (-1);
}
- MD5Init(&ctx);
-
- switch(tp->pf) {
- case 0:
-#ifdef INET
- case AF_INET:
- {
- struct ippseudo ippseudo;
-
- ippseudo.ippseudo_src =
- mtod(m, struct ip *)->ip_src;
- ippseudo.ippseudo_dst =
- mtod(m, struct ip *)->ip_dst;
- ippseudo.ippseudo_pad = 0;
- ippseudo.ippseudo_p = IPPROTO_TCP;
- ippseudo.ippseudo_len = htons(
- m->m_pkthdr.len - iphlen);
-
- MD5Update(&ctx, (char *)&ippseudo,
- sizeof(struct ippseudo));
- }
- break;
-#endif /* INET */
-#ifdef INET6
- case AF_INET6:
- {
- struct ip6_hdr_pseudo ip6pseudo;
-
- bzero(&ip6pseudo, sizeof(ip6pseudo));
- ip6pseudo.ip6ph_src =
- mtod(m, struct ip6_hdr *)->ip6_src;
- ip6pseudo.ip6ph_dst =
- mtod(m, struct ip6_hdr *)->ip6_dst;
- in6_clearscope(&ip6pseudo.ip6ph_src);
- in6_clearscope(&ip6pseudo.ip6ph_dst);
- ip6pseudo.ip6ph_nxt = IPPROTO_TCP;
- ip6pseudo.ip6ph_len = htonl(m->m_pkthdr.len -
- iphlen);
-
- MD5Update(&ctx, (char *)&ip6pseudo,
- sizeof(ip6pseudo));
- }
- break;
-#endif /* INET6 */
- }
-
- {
- struct tcphdr tcphdr;
-
- tcphdr.th_sport = th->th_sport;
- tcphdr.th_dport = th->th_dport;
- tcphdr.th_seq = htonl(th->th_seq);
- tcphdr.th_ack = htonl(th->th_ack);
- tcphdr.th_off = th->th_off;
- tcphdr.th_x2 = th->th_x2;
- tcphdr.th_flags = th->th_flags;
- tcphdr.th_win = htons(th->th_win);
- tcphdr.th_sum = 0;
- tcphdr.th_urp = htons(th->th_urp);
-
- MD5Update(&ctx, (char *)&tcphdr,
- sizeof(struct tcphdr));
- }
-
- if (m_apply(m, iphlen + th->th_off * sizeof(uint32_t),
- m->m_pkthdr.len - (iphlen + th->th_off * sizeof(uint32_t)),
- tcp_signature_apply, (caddr_t)&ctx))
- return (-1);
-
- MD5Update(&ctx, tdb->tdb_amxkey, tdb->tdb_amxkeylen);
- MD5Final(sig, &ctx);
+ if (tcp_signature(tdb, tp->pf, m, th, iphlen, 1, sig) < 0)
+ return (-1);
if (bcmp(sig, sigp, 16)) {
tcpstat.tcps_rcvbadsig++;
@@ -4196,7 +4119,6 @@ syn_cache_respond(sc, m)
#ifdef TCP_SIGNATURE
if (sc->sc_flags & SCF_SIGNATURE) {
- MD5_CTX ctx;
union sockaddr_union src, dst;
struct tdb *tdb;
@@ -4230,56 +4152,16 @@ syn_cache_respond(sc, m)
return (EPERM);
}
- MD5Init(&ctx);
-
- switch (sc->sc_src.sa.sa_family) {
- case 0: /*default to PF_INET*/
-#ifdef INET
- case AF_INET:
- {
- struct ippseudo ippseudo;
-
- ippseudo.ippseudo_src = ip->ip_src;
- ippseudo.ippseudo_dst = ip->ip_dst;
- ippseudo.ippseudo_pad = 0;
- ippseudo.ippseudo_p = IPPROTO_TCP;
- ippseudo.ippseudo_len = htons(tlen - hlen);
-
- MD5Update(&ctx, (char *)&ippseudo,
- sizeof(struct ippseudo));
-
- }
- break;
-#endif /* INET */
-#ifdef INET6
- case AF_INET6:
- {
- struct ip6_hdr_pseudo ip6pseudo;
-
- bzero(&ip6pseudo, sizeof(ip6pseudo));
- ip6pseudo.ip6ph_src = ip6->ip6_src;
- ip6pseudo.ip6ph_dst = ip6->ip6_dst;
- in6_clearscope(&ip6pseudo.ip6ph_src);
- in6_clearscope(&ip6pseudo.ip6ph_dst);
- ip6pseudo.ip6ph_nxt = IPPROTO_TCP;
- ip6pseudo.ip6ph_len = htonl(tlen - hlen);
-
- MD5Update(&ctx, (char *)&ip6pseudo,
- sizeof(ip6pseudo));
- }
- break;
-#endif /* INET6 */
- }
-
- th->th_sum = 0;
- MD5Update(&ctx, (char *)th, sizeof(struct tcphdr));
- MD5Update(&ctx, tdb->tdb_amxkey, tdb->tdb_amxkeylen);
-
/* Send signature option */
*(optp++) = TCPOPT_SIGNATURE;
*(optp++) = TCPOLEN_SIGNATURE;
- MD5Final(optp, &ctx);
+ if (tcp_signature(tdb, sc->sc_src.sa.sa_family, m, th,
+ hlen, 0, optp) < 0) {
+ if (m)
+ m_freem(m);
+ return (EINVAL);
+ }
optp += 16;
/* Pad options list to the next 32 bit boundary and
diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c
index b921b40c0be..6fecca6ba02 100644
--- a/sys/netinet/tcp_output.c
+++ b/sys/netinet/tcp_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_output.c,v 1.69 2004/06/05 11:56:50 markus Exp $ */
+/* $OpenBSD: tcp_output.c,v 1.70 2004/06/08 19:47:24 markus Exp $ */
/* $NetBSD: tcp_output.c,v 1.16 1997/06/03 16:17:09 kml Exp $ */
/*
@@ -103,10 +103,6 @@
#include <netinet6/in6_var.h>
#endif /* INET6 */
-#ifdef TCP_SIGNATURE
-#include <crypto/md5.h>
-#endif /* TCP_SIGNATURE */
-
#ifdef notyet
extern struct mbuf *m_copypack();
#endif
@@ -891,7 +887,7 @@ send:
#ifdef TCP_SIGNATURE
if (tp->t_flags & TF_SIGNATURE) {
- MD5_CTX ctx;
+ int iphlen;
union sockaddr_union src, dst;
struct tdb *tdb;
@@ -902,6 +898,7 @@ send:
case 0: /*default to PF_INET*/
#ifdef INET
case AF_INET:
+ iphlen = sizeof(struct ip);
src.sa.sa_len = sizeof(struct sockaddr_in);
src.sa.sa_family = AF_INET;
src.sin.sin_addr = mtod(m, struct ip *)->ip_src;
@@ -912,6 +909,7 @@ send:
#endif /* INET */
#ifdef INET6
case AF_INET6:
+ iphlen = sizeof(struct ip6_hdr);
src.sa.sa_len = sizeof(struct sockaddr_in6);
src.sa.sa_family = AF_INET6;
src.sin6.sin6_addr = mtod(m, struct ip6_hdr *)->ip6_src;
@@ -922,74 +920,15 @@ send:
#endif /* INET6 */
}
- /* XXX gettdbbysrcdst() should really be called at spltdb(). */
+ /* XXX gettdbbysrcdst() should really be called at spltdb(). */
/* XXX this is splsoftnet(), currently they are the same. */
tdb = gettdbbysrcdst(0, &src, &dst, IPPROTO_TCP);
if (tdb == NULL)
return (EPERM);
- MD5Init(&ctx);
-
- switch (tp->pf) {
- case 0: /*default to PF_INET*/
-#ifdef INET
- case AF_INET:
- {
- struct ippseudo ippseudo;
- struct ipovly *ipovly;
-
- ipovly = mtod(m, struct ipovly *);
-
- ippseudo.ippseudo_src = ipovly->ih_src;
- ippseudo.ippseudo_dst = ipovly->ih_dst;
- ippseudo.ippseudo_pad = 0;
- ippseudo.ippseudo_p = IPPROTO_TCP;
- ippseudo.ippseudo_len = ntohs(ipovly->ih_len) + len +
- optlen;
- ippseudo.ippseudo_len = htons(ippseudo.ippseudo_len);
- MD5Update(&ctx, (char *)&ippseudo,
- sizeof(struct ippseudo));
- }
- break;
-#endif /* INET */
-#ifdef INET6
- case AF_INET6:
- {
- struct ip6_hdr_pseudo ip6pseudo;
- struct ip6_hdr *ip6;
-
- ip6 = mtod(m, struct ip6_hdr *);
- bzero(&ip6pseudo, sizeof(ip6pseudo));
- ip6pseudo.ip6ph_src = ip6->ip6_src;
- ip6pseudo.ip6ph_dst = ip6->ip6_dst;
- in6_clearscope(&ip6pseudo.ip6ph_src);
- in6_clearscope(&ip6pseudo.ip6ph_dst);
- ip6pseudo.ip6ph_nxt = IPPROTO_TCP;
- ip6pseudo.ip6ph_len =
- htonl(sizeof(struct tcphdr) + len + optlen);
-
- MD5Update(&ctx, (char *)&ip6pseudo,
- sizeof(ip6pseudo));
- }
- break;
-#endif /* INET6 */
- }
-
- {
- u_int16_t thsum = th->th_sum;
-
- /* RFC 2385 requires th_sum == 0 */
- th->th_sum = 0;
- MD5Update(&ctx, (char *)th, sizeof(struct tcphdr));
- th->th_sum = thsum;
- }
-
- if (len && m_apply(m, hdrlen, len, tcp_signature_apply,
- (caddr_t)&ctx))
+ if (tcp_signature(tdb, tp->pf, m, th, iphlen, 0,
+ mtod(m, caddr_t) + hdrlen - optlen + sigoff) < 0)
return (EINVAL);
-
- MD5Update(&ctx, tdb->tdb_amxkey, tdb->tdb_amxkeylen);
- MD5Final(mtod(m, caddr_t) + hdrlen - optlen + sigoff, &ctx);
}
#endif /* TCP_SIGNATURE */
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 1071892c6be..13116592f04 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_subr.c,v 1.80 2004/05/07 14:42:27 millert Exp $ */
+/* $OpenBSD: tcp_subr.c,v 1.81 2004/06/08 19:47:24 markus Exp $ */
/* $NetBSD: tcp_subr.c,v 1.22 1996/02/13 23:44:00 christos Exp $ */
/*
@@ -1022,6 +1022,81 @@ tcp_signature_apply(fstate, data, len)
MD5Update((MD5_CTX *)fstate, (char *)data, len);
return 0;
}
+
+int
+tcp_signature(struct tdb *tdb, int af, struct mbuf *m, struct tcphdr *th,
+ int iphlen, int doswap, char *sig)
+{
+ MD5_CTX ctx;
+ int len;
+ struct tcphdr th0;
+
+ MD5Init(&ctx);
+
+ switch(af) {
+ case 0:
+#ifdef INET
+ case AF_INET: {
+ struct ippseudo ippseudo;
+ struct ip *ip;
+
+ ip = mtod(m, struct ip *);
+
+ ippseudo.ippseudo_src = ip->ip_src;
+ ippseudo.ippseudo_dst = ip->ip_dst;
+ ippseudo.ippseudo_pad = 0;
+ ippseudo.ippseudo_p = IPPROTO_TCP;
+ ippseudo.ippseudo_len = htons(m->m_pkthdr.len - iphlen);
+
+ MD5Update(&ctx, (char *)&ippseudo,
+ sizeof(struct ippseudo));
+ break;
+ }
+#endif
+#ifdef INET6
+ case AF_INET6: {
+ struct ip6_hdr_pseudo ip6pseudo;
+ struct ip6_hdr *ip6;
+
+ ip6 = mtod(m, struct ip6_hdr *);
+ bzero(&ip6pseudo, sizeof(ip6pseudo));
+ ip6pseudo.ip6ph_src = ip6->ip6_src;
+ ip6pseudo.ip6ph_dst = ip6->ip6_dst;
+ in6_clearscope(&ip6pseudo.ip6ph_src);
+ in6_clearscope(&ip6pseudo.ip6ph_dst);
+ ip6pseudo.ip6ph_nxt = IPPROTO_TCP;
+ ip6pseudo.ip6ph_len = htonl(m->m_pkthdr.len - iphlen);
+
+ MD5Update(&ctx, (char *)&ip6pseudo,
+ sizeof(ip6pseudo));
+ break;
+ }
+#endif
+ }
+
+ th0 = *th;
+ th0.th_sum = 0;
+
+ if (doswap) {
+ HTONL(th0.th_seq);
+ HTONL(th0.th_ack);
+ HTONS(th0.th_win);
+ HTONS(th0.th_urp);
+ }
+ MD5Update(&ctx, (char *)&th0, sizeof(th0));
+
+ len = m->m_pkthdr.len - iphlen - th->th_off * sizeof(uint32_t);
+
+ if (len > 0 &&
+ m_apply(m, iphlen + th->th_off * sizeof(uint32_t), len,
+ tcp_signature_apply, (caddr_t)&ctx))
+ return (-1);
+
+ MD5Update(&ctx, tdb->tdb_amxkey, tdb->tdb_amxkeylen);
+ MD5Final(sig, &ctx);
+
+ return (0);
+}
#endif /* TCP_SIGNATURE */
#define TCP_RNDISS_ROUNDS 16
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index dbc9718f540..9ac219cc61d 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_var.h,v 1.63 2004/04/25 04:34:05 markus Exp $ */
+/* $OpenBSD: tcp_var.h,v 1.64 2004/06/08 19:47:24 markus Exp $ */
/* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */
/*
@@ -618,6 +618,8 @@ u_long tcp_seq_subtract(u_long, u_long );
#endif /* TCP_SACK */
#ifdef TCP_SIGNATURE
int tcp_signature_apply(caddr_t, caddr_t, unsigned int);
+int tcp_signature(struct tdb *, int, struct mbuf *, struct tcphdr *,
+ int, int, char *);
#endif /* TCP_SIGNATURE */
void tcp_rndiss_init(void);
tcp_seq tcp_rndiss_next(void);