aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/tcp.h29
-rw-r--r--net/ipv4/tcp.c127
-rw-r--r--net/ipv4/tcp_ipv4.c140
-rw-r--r--net/ipv4/tcp_output.c14
-rw-r--r--net/ipv6/tcp_ipv6.c127
5 files changed, 242 insertions, 195 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 92d7b551dc55..31f5bbfc59bc 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1112,20 +1112,12 @@ struct tcp_md5sig_pool {
1112#define TCP_MD5SIG_MAXKEYS (~(u32)0) /* really?! */ 1112#define TCP_MD5SIG_MAXKEYS (~(u32)0) /* really?! */
1113 1113
1114/* - functions */ 1114/* - functions */
1115extern int tcp_calc_md5_hash(char *md5_hash, 1115extern int tcp_v4_md5_hash_skb(char *md5_hash,
1116 struct tcp_md5sig_key *key, 1116 struct tcp_md5sig_key *key,
1117 int bplen, 1117 struct sock *sk,
1118 struct tcphdr *th, 1118 struct request_sock *req,
1119 unsigned int tcplen, 1119 struct sk_buff *skb);
1120 struct tcp_md5sig_pool *hp); 1120
1121
1122extern int tcp_v4_calc_md5_hash(char *md5_hash,
1123 struct tcp_md5sig_key *key,
1124 struct sock *sk,
1125 struct dst_entry *dst,
1126 struct request_sock *req,
1127 struct tcphdr *th,
1128 unsigned int tcplen);
1129extern struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk, 1121extern struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk,
1130 struct sock *addr_sk); 1122 struct sock *addr_sk);
1131 1123
@@ -1152,6 +1144,11 @@ extern void tcp_free_md5sig_pool(void);
1152 1144
1153extern struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu); 1145extern struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu);
1154extern void __tcp_put_md5sig_pool(void); 1146extern void __tcp_put_md5sig_pool(void);
1147extern int tcp_md5_hash_header(struct tcp_md5sig_pool *, struct tcphdr *);
1148extern int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *, struct sk_buff *,
1149 unsigned header_len);
1150extern int tcp_md5_hash_key(struct tcp_md5sig_pool *hp,
1151 struct tcp_md5sig_key *key);
1155 1152
1156static inline 1153static inline
1157struct tcp_md5sig_pool *tcp_get_md5sig_pool(void) 1154struct tcp_md5sig_pool *tcp_get_md5sig_pool(void)
@@ -1381,10 +1378,8 @@ struct tcp_sock_af_ops {
1381 int (*calc_md5_hash) (char *location, 1378 int (*calc_md5_hash) (char *location,
1382 struct tcp_md5sig_key *md5, 1379 struct tcp_md5sig_key *md5,
1383 struct sock *sk, 1380 struct sock *sk,
1384 struct dst_entry *dst,
1385 struct request_sock *req, 1381 struct request_sock *req,
1386 struct tcphdr *th, 1382 struct sk_buff *skb);
1387 unsigned int len);
1388 int (*md5_add) (struct sock *sk, 1383 int (*md5_add) (struct sock *sk,
1389 struct sock *addr_sk, 1384 struct sock *addr_sk,
1390 u8 *newkey, 1385 u8 *newkey,
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 827e6132af5f..0b491bf03db4 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2465,76 +2465,6 @@ static unsigned long tcp_md5sig_users;
2465static struct tcp_md5sig_pool **tcp_md5sig_pool; 2465static struct tcp_md5sig_pool **tcp_md5sig_pool;
2466static DEFINE_SPINLOCK(tcp_md5sig_pool_lock); 2466static DEFINE_SPINLOCK(tcp_md5sig_pool_lock);
2467 2467
2468int tcp_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
2469 int bplen,
2470 struct tcphdr *th, unsigned int tcplen,
2471 struct tcp_md5sig_pool *hp)
2472{
2473 struct scatterlist sg[4];
2474 __u16 data_len;
2475 int block = 0;
2476 __sum16 cksum;
2477 struct hash_desc *desc = &hp->md5_desc;
2478 int err;
2479 unsigned int nbytes = 0;
2480
2481 sg_init_table(sg, 4);
2482
2483 /* 1. The TCP pseudo-header */
2484 sg_set_buf(&sg[block++], &hp->md5_blk, bplen);
2485 nbytes += bplen;
2486
2487 /* 2. The TCP header, excluding options, and assuming a
2488 * checksum of zero
2489 */
2490 cksum = th->check;
2491 th->check = 0;
2492 sg_set_buf(&sg[block++], th, sizeof(*th));
2493 nbytes += sizeof(*th);
2494
2495 /* 3. The TCP segment data (if any) */
2496 data_len = tcplen - (th->doff << 2);
2497 if (data_len > 0) {
2498 u8 *data = (u8 *)th + (th->doff << 2);
2499 sg_set_buf(&sg[block++], data, data_len);
2500 nbytes += data_len;
2501 }
2502
2503 /* 4. an independently-specified key or password, known to both
2504 * TCPs and presumably connection-specific
2505 */
2506 sg_set_buf(&sg[block++], key->key, key->keylen);
2507 nbytes += key->keylen;
2508
2509 sg_mark_end(&sg[block - 1]);
2510
2511 /* Now store the hash into the packet */
2512 err = crypto_hash_init(desc);
2513 if (err) {
2514 if (net_ratelimit())
2515 printk(KERN_WARNING "%s(): hash_init failed\n", __func__);
2516 return -1;
2517 }
2518 err = crypto_hash_update(desc, sg, nbytes);
2519 if (err) {
2520 if (net_ratelimit())
2521 printk(KERN_WARNING "%s(): hash_update failed\n", __func__);
2522 return -1;
2523 }
2524 err = crypto_hash_final(desc, md5_hash);
2525 if (err) {
2526 if (net_ratelimit())
2527 printk(KERN_WARNING "%s(): hash_final failed\n", __func__);
2528 return -1;
2529 }
2530
2531 /* Reset header */
2532 th->check = cksum;
2533
2534 return 0;
2535}
2536EXPORT_SYMBOL(tcp_calc_md5_hash);
2537
2538static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool **pool) 2468static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool **pool)
2539{ 2469{
2540 int cpu; 2470 int cpu;
@@ -2658,6 +2588,63 @@ void __tcp_put_md5sig_pool(void)
2658} 2588}
2659 2589
2660EXPORT_SYMBOL(__tcp_put_md5sig_pool); 2590EXPORT_SYMBOL(__tcp_put_md5sig_pool);
2591
2592int tcp_md5_hash_header(struct tcp_md5sig_pool *hp,
2593 struct tcphdr *th)
2594{
2595 struct scatterlist sg;
2596 int err;
2597
2598 __sum16 old_checksum = th->check;
2599 th->check = 0;
2600 /* options aren't included in the hash */
2601 sg_init_one(&sg, th, sizeof(struct tcphdr));
2602 err = crypto_hash_update(&hp->md5_desc, &sg, sizeof(struct tcphdr));
2603 th->check = old_checksum;
2604 return err;
2605}
2606
2607EXPORT_SYMBOL(tcp_md5_hash_header);
2608
2609int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *hp,
2610 struct sk_buff *skb, unsigned header_len)
2611{
2612 struct scatterlist sg;
2613 const struct tcphdr *tp = tcp_hdr(skb);
2614 struct hash_desc *desc = &hp->md5_desc;
2615 unsigned i;
2616 const unsigned head_data_len = skb_headlen(skb) > header_len ?
2617 skb_headlen(skb) - header_len : 0;
2618 const struct skb_shared_info *shi = skb_shinfo(skb);
2619
2620 sg_init_table(&sg, 1);
2621
2622 sg_set_buf(&sg, ((u8 *) tp) + header_len, head_data_len);
2623 if (crypto_hash_update(desc, &sg, head_data_len))
2624 return 1;
2625
2626 for (i = 0; i < shi->nr_frags; ++i) {
2627 const struct skb_frag_struct *f = &shi->frags[i];
2628 sg_set_page(&sg, f->page, f->size, f->page_offset);
2629 if (crypto_hash_update(desc, &sg, f->size))
2630 return 1;
2631 }
2632
2633 return 0;
2634}
2635
2636EXPORT_SYMBOL(tcp_md5_hash_skb_data);
2637
2638int tcp_md5_hash_key(struct tcp_md5sig_pool *hp, struct tcp_md5sig_key *key)
2639{
2640 struct scatterlist sg;
2641
2642 sg_init_one(&sg, key->key, key->keylen);
2643 return crypto_hash_update(&hp->md5_desc, &sg, key->keylen);
2644}
2645
2646EXPORT_SYMBOL(tcp_md5_hash_key);
2647
2661#endif 2648#endif
2662 2649
2663void tcp_done(struct sock *sk) 2650void tcp_done(struct sock *sk)
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 29adc668ad51..5400d75ff17a 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -87,9 +87,8 @@ int sysctl_tcp_low_latency __read_mostly;
87#ifdef CONFIG_TCP_MD5SIG 87#ifdef CONFIG_TCP_MD5SIG
88static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, 88static struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk,
89 __be32 addr); 89 __be32 addr);
90static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, 90static int tcp_v4_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key,
91 __be32 saddr, __be32 daddr, 91 __be32 daddr, __be32 saddr, struct tcphdr *th);
92 struct tcphdr *th, unsigned int tcplen);
93#else 92#else
94static inline 93static inline
95struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr) 94struct tcp_md5sig_key *tcp_v4_md5_do_lookup(struct sock *sk, __be32 addr)
@@ -583,11 +582,9 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
583 arg.iov[0].iov_len += TCPOLEN_MD5SIG_ALIGNED; 582 arg.iov[0].iov_len += TCPOLEN_MD5SIG_ALIGNED;
584 rep.th.doff = arg.iov[0].iov_len / 4; 583 rep.th.doff = arg.iov[0].iov_len / 4;
585 584
586 tcp_v4_do_calc_md5_hash((__u8 *)&rep.opt[1], 585 tcp_v4_md5_hash_hdr((__u8 *) &rep.opt[1],
587 key, 586 key, ip_hdr(skb)->daddr,
588 ip_hdr(skb)->daddr, 587 ip_hdr(skb)->saddr, &rep.th);
589 ip_hdr(skb)->saddr,
590 &rep.th, arg.iov[0].iov_len);
591 } 588 }
592#endif 589#endif
593 arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr, 590 arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
@@ -657,11 +654,9 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
657 arg.iov[0].iov_len += TCPOLEN_MD5SIG_ALIGNED; 654 arg.iov[0].iov_len += TCPOLEN_MD5SIG_ALIGNED;
658 rep.th.doff = arg.iov[0].iov_len/4; 655 rep.th.doff = arg.iov[0].iov_len/4;
659 656
660 tcp_v4_do_calc_md5_hash((__u8 *)&rep.opt[offset], 657 tcp_v4_md5_hash_hdr((__u8 *) &rep.opt[offset],
661 key, 658 key, ip_hdr(skb)->daddr,
662 ip_hdr(skb)->daddr, 659 ip_hdr(skb)->saddr, &rep.th);
663 ip_hdr(skb)->saddr,
664 &rep.th, arg.iov[0].iov_len);
665 } 660 }
666#endif 661#endif
667 arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr, 662 arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
@@ -989,28 +984,16 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval,
989 newkey, cmd.tcpm_keylen); 984 newkey, cmd.tcpm_keylen);
990} 985}
991 986
992static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, 987static int tcp_v4_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp,
993 __be32 saddr, __be32 daddr, 988 __be32 daddr, __be32 saddr, int nbytes)
994 struct tcphdr *th,
995 unsigned int tcplen)
996{ 989{
997 struct tcp_md5sig_pool *hp;
998 struct tcp4_pseudohdr *bp; 990 struct tcp4_pseudohdr *bp;
999 int err; 991 struct scatterlist sg;
1000
1001 /*
1002 * Okay, so RFC2385 is turned on for this connection,
1003 * so we need to generate the MD5 hash for the packet now.
1004 */
1005
1006 hp = tcp_get_md5sig_pool();
1007 if (!hp)
1008 goto clear_hash_noput;
1009 992
1010 bp = &hp->md5_blk.ip4; 993 bp = &hp->md5_blk.ip4;
1011 994
1012 /* 995 /*
1013 * The TCP pseudo-header (in the order: source IP address, 996 * 1. the TCP pseudo-header (in the order: source IP address,
1014 * destination IP address, zero-padded protocol number, and 997 * destination IP address, zero-padded protocol number, and
1015 * segment length) 998 * segment length)
1016 */ 999 */
@@ -1018,48 +1001,95 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
1018 bp->daddr = daddr; 1001 bp->daddr = daddr;
1019 bp->pad = 0; 1002 bp->pad = 0;
1020 bp->protocol = IPPROTO_TCP; 1003 bp->protocol = IPPROTO_TCP;
1021 bp->len = htons(tcplen); 1004 bp->len = cpu_to_be16(nbytes);
1022 1005
1023 err = tcp_calc_md5_hash(md5_hash, key, sizeof(*bp), 1006 sg_init_one(&sg, bp, sizeof(*bp));
1024 th, tcplen, hp); 1007 return crypto_hash_update(&hp->md5_desc, &sg, sizeof(*bp));
1025 if (err) 1008}
1009
1010static int tcp_v4_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key,
1011 __be32 daddr, __be32 saddr, struct tcphdr *th)
1012{
1013 struct tcp_md5sig_pool *hp;
1014 struct hash_desc *desc;
1015
1016 hp = tcp_get_md5sig_pool();
1017 if (!hp)
1018 goto clear_hash_noput;
1019 desc = &hp->md5_desc;
1020
1021 if (crypto_hash_init(desc))
1022 goto clear_hash;
1023 if (tcp_v4_md5_hash_pseudoheader(hp, daddr, saddr, th->doff << 2))
1024 goto clear_hash;
1025 if (tcp_md5_hash_header(hp, th))
1026 goto clear_hash;
1027 if (tcp_md5_hash_key(hp, key))
1028 goto clear_hash;
1029 if (crypto_hash_final(desc, md5_hash))
1026 goto clear_hash; 1030 goto clear_hash;
1027 1031
1028 /* Free up the crypto pool */
1029 tcp_put_md5sig_pool(); 1032 tcp_put_md5sig_pool();
1030out:
1031 return 0; 1033 return 0;
1034
1032clear_hash: 1035clear_hash:
1033 tcp_put_md5sig_pool(); 1036 tcp_put_md5sig_pool();
1034clear_hash_noput: 1037clear_hash_noput:
1035 memset(md5_hash, 0, 16); 1038 memset(md5_hash, 0, 16);
1036 goto out; 1039 return 1;
1037} 1040}
1038 1041
1039int tcp_v4_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, 1042int tcp_v4_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key,
1040 struct sock *sk, 1043 struct sock *sk, struct request_sock *req,
1041 struct dst_entry *dst, 1044 struct sk_buff *skb)
1042 struct request_sock *req,
1043 struct tcphdr *th,
1044 unsigned int tcplen)
1045{ 1045{
1046 struct tcp_md5sig_pool *hp;
1047 struct hash_desc *desc;
1048 struct tcphdr *th = tcp_hdr(skb);
1046 __be32 saddr, daddr; 1049 __be32 saddr, daddr;
1047 1050
1048 if (sk) { 1051 if (sk) {
1049 saddr = inet_sk(sk)->saddr; 1052 saddr = inet_sk(sk)->saddr;
1050 daddr = inet_sk(sk)->daddr; 1053 daddr = inet_sk(sk)->daddr;
1054 } else if (req) {
1055 saddr = inet_rsk(req)->loc_addr;
1056 daddr = inet_rsk(req)->rmt_addr;
1051 } else { 1057 } else {
1052 struct rtable *rt = (struct rtable *)dst; 1058 const struct iphdr *iph = ip_hdr(skb);
1053 BUG_ON(!rt); 1059 saddr = iph->saddr;
1054 saddr = rt->rt_src; 1060 daddr = iph->daddr;
1055 daddr = rt->rt_dst;
1056 } 1061 }
1057 return tcp_v4_do_calc_md5_hash(md5_hash, key, 1062
1058 saddr, daddr, 1063 hp = tcp_get_md5sig_pool();
1059 th, tcplen); 1064 if (!hp)
1065 goto clear_hash_noput;
1066 desc = &hp->md5_desc;
1067
1068 if (crypto_hash_init(desc))
1069 goto clear_hash;
1070
1071 if (tcp_v4_md5_hash_pseudoheader(hp, daddr, saddr, skb->len))
1072 goto clear_hash;
1073 if (tcp_md5_hash_header(hp, th))
1074 goto clear_hash;
1075 if (tcp_md5_hash_skb_data(hp, skb, th->doff << 2))
1076 goto clear_hash;
1077 if (tcp_md5_hash_key(hp, key))
1078 goto clear_hash;
1079 if (crypto_hash_final(desc, md5_hash))
1080 goto clear_hash;
1081
1082 tcp_put_md5sig_pool();
1083 return 0;
1084
1085clear_hash:
1086 tcp_put_md5sig_pool();
1087clear_hash_noput:
1088 memset(md5_hash, 0, 16);
1089 return 1;
1060} 1090}
1061 1091
1062EXPORT_SYMBOL(tcp_v4_calc_md5_hash); 1092EXPORT_SYMBOL(tcp_v4_md5_hash_skb);
1063 1093
1064static int tcp_v4_inbound_md5_hash(struct sock *sk, struct sk_buff *skb) 1094static int tcp_v4_inbound_md5_hash(struct sock *sk, struct sk_buff *skb)
1065{ 1095{
@@ -1104,10 +1134,9 @@ static int tcp_v4_inbound_md5_hash(struct sock *sk, struct sk_buff *skb)
1104 /* Okay, so this is hash_expected and hash_location - 1134 /* Okay, so this is hash_expected and hash_location -
1105 * so we need to calculate the checksum. 1135 * so we need to calculate the checksum.
1106 */ 1136 */
1107 genhash = tcp_v4_do_calc_md5_hash(newhash, 1137 genhash = tcp_v4_md5_hash_skb(newhash,
1108 hash_expected, 1138 hash_expected,
1109 iph->saddr, iph->daddr, 1139 NULL, NULL, skb);
1110 th, skb->len);
1111 1140
1112 if (genhash || memcmp(hash_location, newhash, 16) != 0) { 1141 if (genhash || memcmp(hash_location, newhash, 16) != 0) {
1113 if (net_ratelimit()) { 1142 if (net_ratelimit()) {
@@ -1356,6 +1385,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
1356 if (newkey != NULL) 1385 if (newkey != NULL)
1357 tcp_v4_md5_do_add(newsk, inet_sk(sk)->daddr, 1386 tcp_v4_md5_do_add(newsk, inet_sk(sk)->daddr,
1358 newkey, key->keylen); 1387 newkey, key->keylen);
1388 newsk->sk_route_caps &= ~NETIF_F_GSO_MASK;
1359 } 1389 }
1360#endif 1390#endif
1361 1391
@@ -1719,7 +1749,7 @@ struct inet_connection_sock_af_ops ipv4_specific = {
1719#ifdef CONFIG_TCP_MD5SIG 1749#ifdef CONFIG_TCP_MD5SIG
1720static struct tcp_sock_af_ops tcp_sock_ipv4_specific = { 1750static struct tcp_sock_af_ops tcp_sock_ipv4_specific = {
1721 .md5_lookup = tcp_v4_md5_lookup, 1751 .md5_lookup = tcp_v4_md5_lookup,
1722 .calc_md5_hash = tcp_v4_calc_md5_hash, 1752 .calc_md5_hash = tcp_v4_md5_hash_skb,
1723 .md5_add = tcp_v4_md5_add_func, 1753 .md5_add = tcp_v4_md5_add_func,
1724 .md5_parse = tcp_v4_parse_md5_keys, 1754 .md5_parse = tcp_v4_parse_md5_keys,
1725}; 1755};
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 36a19707f67f..958ff486165f 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -540,8 +540,10 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
540 * room for it. 540 * room for it.
541 */ 541 */
542 md5 = tp->af_specific->md5_lookup(sk, sk); 542 md5 = tp->af_specific->md5_lookup(sk, sk);
543 if (md5) 543 if (md5) {
544 tcp_header_size += TCPOLEN_MD5SIG_ALIGNED; 544 tcp_header_size += TCPOLEN_MD5SIG_ALIGNED;
545 sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
546 }
545#endif 547#endif
546 548
547 skb_push(skb, tcp_header_size); 549 skb_push(skb, tcp_header_size);
@@ -602,10 +604,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it,
602 /* Calculate the MD5 hash, as we have all we need now */ 604 /* Calculate the MD5 hash, as we have all we need now */
603 if (md5) { 605 if (md5) {
604 tp->af_specific->calc_md5_hash(md5_hash_location, 606 tp->af_specific->calc_md5_hash(md5_hash_location,
605 md5, 607 md5, sk, NULL, skb);
606 sk, NULL, NULL,
607 tcp_hdr(skb),
608 skb->len);
609 } 608 }
610#endif 609#endif
611 610
@@ -2264,10 +2263,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
2264 /* Okay, we have all we need - do the md5 hash if needed */ 2263 /* Okay, we have all we need - do the md5 hash if needed */
2265 if (md5) { 2264 if (md5) {
2266 tp->af_specific->calc_md5_hash(md5_hash_location, 2265 tp->af_specific->calc_md5_hash(md5_hash_location,
2267 md5, 2266 md5, NULL, req, skb);
2268 NULL, dst, req,
2269 tcp_hdr(skb),
2270 skb->len);
2271 } 2267 }
2272#endif 2268#endif
2273 2269
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index ca5b93a5c02a..ae45f9835014 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -736,64 +736,105 @@ static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval,
736 return tcp_v6_md5_do_add(sk, &sin6->sin6_addr, newkey, cmd.tcpm_keylen); 736 return tcp_v6_md5_do_add(sk, &sin6->sin6_addr, newkey, cmd.tcpm_keylen);
737} 737}
738 738
739static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, 739static int tcp_v6_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp,
740 struct in6_addr *saddr, 740 struct in6_addr *daddr,
741 struct in6_addr *daddr, 741 struct in6_addr *saddr, int nbytes)
742 struct tcphdr *th, unsigned int tcplen)
743{ 742{
744 struct tcp_md5sig_pool *hp;
745 struct tcp6_pseudohdr *bp; 743 struct tcp6_pseudohdr *bp;
746 int err; 744 struct scatterlist sg;
747
748 hp = tcp_get_md5sig_pool();
749 if (!hp) {
750 printk(KERN_WARNING "%s(): hash pool not found...\n", __func__);
751 goto clear_hash_noput;
752 }
753 745
754 bp = &hp->md5_blk.ip6; 746 bp = &hp->md5_blk.ip6;
755
756 /* 1. TCP pseudo-header (RFC2460) */ 747 /* 1. TCP pseudo-header (RFC2460) */
757 ipv6_addr_copy(&bp->saddr, saddr); 748 ipv6_addr_copy(&bp->saddr, saddr);
758 ipv6_addr_copy(&bp->daddr, daddr); 749 ipv6_addr_copy(&bp->daddr, daddr);
759 bp->len = htonl(tcplen); 750 bp->protocol = cpu_to_be32(IPPROTO_TCP);
760 bp->protocol = htonl(IPPROTO_TCP); 751 bp->len = cpu_to_be16(nbytes);
761 752
762 err = tcp_calc_md5_hash(md5_hash, key, sizeof(*bp), 753 sg_init_one(&sg, bp, sizeof(*bp));
763 th, tcplen, hp); 754 return crypto_hash_update(&hp->md5_desc, &sg, sizeof(*bp));
755}
764 756
765 if (err) 757static int tcp_v6_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key,
758 struct in6_addr *daddr, struct in6_addr *saddr,
759 struct tcphdr *th)
760{
761 struct tcp_md5sig_pool *hp;
762 struct hash_desc *desc;
763
764 hp = tcp_get_md5sig_pool();
765 if (!hp)
766 goto clear_hash_noput;
767 desc = &hp->md5_desc;
768
769 if (crypto_hash_init(desc))
770 goto clear_hash;
771 if (tcp_v6_md5_hash_pseudoheader(hp, daddr, saddr, th->doff << 2))
772 goto clear_hash;
773 if (tcp_md5_hash_header(hp, th))
774 goto clear_hash;
775 if (tcp_md5_hash_key(hp, key))
776 goto clear_hash;
777 if (crypto_hash_final(desc, md5_hash))
766 goto clear_hash; 778 goto clear_hash;
767 779
768 /* Free up the crypto pool */
769 tcp_put_md5sig_pool(); 780 tcp_put_md5sig_pool();
770out:
771 return 0; 781 return 0;
782
772clear_hash: 783clear_hash:
773 tcp_put_md5sig_pool(); 784 tcp_put_md5sig_pool();
774clear_hash_noput: 785clear_hash_noput:
775 memset(md5_hash, 0, 16); 786 memset(md5_hash, 0, 16);
776 goto out; 787 return 1;
777} 788}
778 789
779static int tcp_v6_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, 790static int tcp_v6_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key,
780 struct sock *sk, 791 struct sock *sk, struct request_sock *req,
781 struct dst_entry *dst, 792 struct sk_buff *skb)
782 struct request_sock *req,
783 struct tcphdr *th, unsigned int tcplen)
784{ 793{
785 struct in6_addr *saddr, *daddr; 794 struct in6_addr *saddr, *daddr;
795 struct tcp_md5sig_pool *hp;
796 struct hash_desc *desc;
797 struct tcphdr *th = tcp_hdr(skb);
786 798
787 if (sk) { 799 if (sk) {
788 saddr = &inet6_sk(sk)->saddr; 800 saddr = &inet6_sk(sk)->saddr;
789 daddr = &inet6_sk(sk)->daddr; 801 daddr = &inet6_sk(sk)->daddr;
790 } else { 802 } else if (req) {
791 saddr = &inet6_rsk(req)->loc_addr; 803 saddr = &inet6_rsk(req)->loc_addr;
792 daddr = &inet6_rsk(req)->rmt_addr; 804 daddr = &inet6_rsk(req)->rmt_addr;
805 } else {
806 struct ipv6hdr *ip6h = ipv6_hdr(skb);
807 saddr = &ip6h->saddr;
808 daddr = &ip6h->daddr;
793 } 809 }
794 return tcp_v6_do_calc_md5_hash(md5_hash, key, 810
795 saddr, daddr, 811 hp = tcp_get_md5sig_pool();
796 th, tcplen); 812 if (!hp)
813 goto clear_hash_noput;
814 desc = &hp->md5_desc;
815
816 if (crypto_hash_init(desc))
817 goto clear_hash;
818
819 if (tcp_v6_md5_hash_pseudoheader(hp, daddr, saddr, skb->len))
820 goto clear_hash;
821 if (tcp_md5_hash_header(hp, th))
822 goto clear_hash;
823 if (tcp_md5_hash_skb_data(hp, skb, th->doff << 2))
824 goto clear_hash;
825 if (tcp_md5_hash_key(hp, key))
826 goto clear_hash;
827 if (crypto_hash_final(desc, md5_hash))
828 goto clear_hash;
829
830 tcp_put_md5sig_pool();
831 return 0;
832
833clear_hash:
834 tcp_put_md5sig_pool();
835clear_hash_noput:
836 memset(md5_hash, 0, 16);
837 return 1;
797} 838}
798 839
799static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) 840static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb)
@@ -834,10 +875,10 @@ static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb)
834 } 875 }
835 876
836 /* check the signature */ 877 /* check the signature */
837 genhash = tcp_v6_do_calc_md5_hash(newhash, 878 genhash = tcp_v6_md5_hash_skb(newhash,
838 hash_expected, 879 hash_expected,
839 &ip6h->saddr, &ip6h->daddr, 880 NULL, NULL, skb);
840 th, skb->len); 881
841 if (genhash || memcmp(hash_location, newhash, 16) != 0) { 882 if (genhash || memcmp(hash_location, newhash, 16) != 0) {
842 if (net_ratelimit()) { 883 if (net_ratelimit()) {
843 printk(KERN_INFO "MD5 Hash %s for " 884 printk(KERN_INFO "MD5 Hash %s for "
@@ -974,10 +1015,9 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
974 (TCPOPT_NOP << 16) | 1015 (TCPOPT_NOP << 16) |
975 (TCPOPT_MD5SIG << 8) | 1016 (TCPOPT_MD5SIG << 8) |
976 TCPOLEN_MD5SIG); 1017 TCPOLEN_MD5SIG);
977 tcp_v6_do_calc_md5_hash((__u8 *)&opt[1], key, 1018 tcp_v6_md5_hash_hdr((__u8 *)&opt[1], key,
978 &ipv6_hdr(skb)->daddr, 1019 &ipv6_hdr(skb)->daddr,
979 &ipv6_hdr(skb)->saddr, 1020 &ipv6_hdr(skb)->saddr, t1);
980 t1, tot_len);
981 } 1021 }
982#endif 1022#endif
983 1023
@@ -1064,10 +1104,9 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
1064 if (key) { 1104 if (key) {
1065 *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | 1105 *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) |
1066 (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG); 1106 (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG);
1067 tcp_v6_do_calc_md5_hash((__u8 *)topt, key, 1107 tcp_v6_md5_hash_hdr((__u8 *)topt, key,
1068 &ipv6_hdr(skb)->daddr, 1108 &ipv6_hdr(skb)->daddr,
1069 &ipv6_hdr(skb)->saddr, 1109 &ipv6_hdr(skb)->saddr, t1);
1070 t1, tot_len);
1071 } 1110 }
1072#endif 1111#endif
1073 1112
@@ -1783,7 +1822,7 @@ static struct inet_connection_sock_af_ops ipv6_specific = {
1783#ifdef CONFIG_TCP_MD5SIG 1822#ifdef CONFIG_TCP_MD5SIG
1784static struct tcp_sock_af_ops tcp_sock_ipv6_specific = { 1823static struct tcp_sock_af_ops tcp_sock_ipv6_specific = {
1785 .md5_lookup = tcp_v6_md5_lookup, 1824 .md5_lookup = tcp_v6_md5_lookup,
1786 .calc_md5_hash = tcp_v6_calc_md5_hash, 1825 .calc_md5_hash = tcp_v6_md5_hash_skb,
1787 .md5_add = tcp_v6_md5_add_func, 1826 .md5_add = tcp_v6_md5_add_func,
1788 .md5_parse = tcp_v6_parse_md5_keys, 1827 .md5_parse = tcp_v6_parse_md5_keys,
1789}; 1828};
@@ -1815,7 +1854,7 @@ static struct inet_connection_sock_af_ops ipv6_mapped = {
1815#ifdef CONFIG_TCP_MD5SIG 1854#ifdef CONFIG_TCP_MD5SIG
1816static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific = { 1855static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific = {
1817 .md5_lookup = tcp_v4_md5_lookup, 1856 .md5_lookup = tcp_v4_md5_lookup,
1818 .calc_md5_hash = tcp_v4_calc_md5_hash, 1857 .calc_md5_hash = tcp_v4_md5_hash_skb,
1819 .md5_add = tcp_v6_md5_add_func, 1858 .md5_add = tcp_v6_md5_add_func,
1820 .md5_parse = tcp_v6_parse_md5_keys, 1859 .md5_parse = tcp_v6_parse_md5_keys,
1821}; 1860};