diff options
author | Markus Friedl <markus@cvs.openbsd.org> | 2004-06-08 19:47:25 +0000 |
---|---|---|
committer | Markus Friedl <markus@cvs.openbsd.org> | 2004-06-08 19:47:25 +0000 |
commit | b3f24646e2fb015bc166f8f92151871622fb9c02 (patch) | |
tree | b46f681348bf994fceacfb2f933bd16ccf03ac62 | |
parent | 49f35b7ba3eab70964cebbc937c6eca40ec9ffe1 (diff) |
factor out md5 code; ok+tests henning@, djm@, hshoexer@
-rw-r--r-- | sys/netinet/tcp_input.c | 138 | ||||
-rw-r--r-- | sys/netinet/tcp_output.c | 75 | ||||
-rw-r--r-- | sys/netinet/tcp_subr.c | 77 | ||||
-rw-r--r-- | sys/netinet/tcp_var.h | 4 |
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); |