Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 102870
b: refs/heads/master
c: 8d26d76
h: refs/heads/master
v: v3
  • Loading branch information
YOSHIFUJI Hideaki committed Jun 11, 2008
1 parent 8c78edc commit 05054d6
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 97 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 076fb7223357769c39f3ddf900bba6752369c76a
refs/heads/master: 8d26d76dd4a4c87ef037a44a42a0608ffc730199
7 changes: 7 additions & 0 deletions trunk/include/net/tcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -1117,6 +1117,13 @@ struct tcp_md5sig_pool {
#define TCP_MD5SIG_MAXKEYS (~(u32)0) /* really?! */

/* - functions */
extern int tcp_calc_md5_hash(char *md5_hash,
struct tcp_md5sig_key *key,
int bplen,
struct tcphdr *th,
unsigned int tcplen,
struct tcp_md5sig_pool *hp);

extern int tcp_v4_calc_md5_hash(char *md5_hash,
struct tcp_md5sig_key *key,
struct sock *sk,
Expand Down
70 changes: 70 additions & 0 deletions trunk/net/ipv4/tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2459,6 +2459,76 @@ static unsigned long tcp_md5sig_users;
static struct tcp_md5sig_pool **tcp_md5sig_pool;
static DEFINE_SPINLOCK(tcp_md5sig_pool_lock);

int tcp_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
int bplen,
struct tcphdr *th, unsigned int tcplen,
struct tcp_md5sig_pool *hp)
{
struct scatterlist sg[4];
__u16 data_len;
int block = 0;
__sum16 cksum;
struct hash_desc *desc = &hp->md5_desc;
int err;
unsigned int nbytes = 0;

sg_init_table(sg, 4);

/* 1. The TCP pseudo-header */
sg_set_buf(&sg[block++], &hp->md5_blk, bplen);
nbytes += bplen;

/* 2. The TCP header, excluding options, and assuming a
* checksum of zero
*/
cksum = th->check;
th->check = 0;
sg_set_buf(&sg[block++], th, sizeof(*th));
nbytes += sizeof(*th);

/* 3. The TCP segment data (if any) */
data_len = tcplen - (th->doff << 2);
if (data_len > 0) {
u8 *data = (u8 *)th + (th->doff << 2);
sg_set_buf(&sg[block++], data, data_len);
nbytes += data_len;
}

/* 4. an independently-specified key or password, known to both
* TCPs and presumably connection-specific
*/
sg_set_buf(&sg[block++], key->key, key->keylen);
nbytes += key->keylen;

sg_mark_end(&sg[block - 1]);

/* Now store the hash into the packet */
err = crypto_hash_init(desc);
if (err) {
if (net_ratelimit())
printk(KERN_WARNING "%s(): hash_init failed\n", __func__);
return -1;
}
err = crypto_hash_update(desc, sg, nbytes);
if (err) {
if (net_ratelimit())
printk(KERN_WARNING "%s(): hash_update failed\n", __func__);
return -1;
}
err = crypto_hash_final(desc, md5_hash);
if (err) {
if (net_ratelimit())
printk(KERN_WARNING "%s(): hash_final failed\n", __func__);
return -1;
}

/* Reset header */
th->check = cksum;

return 0;
}
EXPORT_SYMBOL(tcp_calc_md5_hash);

static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool **pool)
{
int cpu;
Expand Down
52 changes: 4 additions & 48 deletions trunk/net/ipv4/tcp_ipv4.c
Original file line number Diff line number Diff line change
Expand Up @@ -1006,15 +1006,9 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
struct tcphdr *th,
unsigned int tcplen)
{
struct scatterlist sg[4];
__u16 data_len;
int block = 0;
__sum16 old_checksum;
struct tcp_md5sig_pool *hp;
struct tcp4_pseudohdr *bp;
struct hash_desc *desc;
int err;
unsigned int nbytes = 0;

/*
* Okay, so RFC2385 is turned on for this connection,
Expand All @@ -1026,10 +1020,9 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
goto clear_hash_noput;

bp = &hp->md5_blk.ip4;
desc = &hp->md5_desc;

/*
* 1. the TCP pseudo-header (in the order: source IP address,
* The TCP pseudo-header (in the order: source IP address,
* destination IP address, zero-padded protocol number, and
* segment length)
*/
Expand All @@ -1039,50 +1032,13 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
bp->protocol = IPPROTO_TCP;
bp->len = htons(tcplen);

sg_init_table(sg, 4);

sg_set_buf(&sg[block++], bp, sizeof(*bp));
nbytes += sizeof(*bp);

/* 2. the TCP header, excluding options, and assuming a
* checksum of zero/
*/
old_checksum = th->check;
th->check = 0;
sg_set_buf(&sg[block++], th, sizeof(struct tcphdr));
nbytes += sizeof(struct tcphdr);

/* 3. the TCP segment data (if any) */
data_len = tcplen - (th->doff << 2);
if (data_len > 0) {
unsigned char *data = (unsigned char *)th + (th->doff << 2);
sg_set_buf(&sg[block++], data, data_len);
nbytes += data_len;
}

/* 4. an independently-specified key or password, known to both
* TCPs and presumably connection-specific
*/
sg_set_buf(&sg[block++], key->key, key->keylen);
nbytes += key->keylen;

sg_mark_end(&sg[block - 1]);

/* Now store the Hash into the packet */
err = crypto_hash_init(desc);
if (err)
goto clear_hash;
err = crypto_hash_update(desc, sg, nbytes);
if (err)
goto clear_hash;
err = crypto_hash_final(desc, md5_hash);
err = tcp_calc_md5_hash(md5_hash, key, sizeof(*bp),
th, tcplen, hp);
if (err)
goto clear_hash;

/* Reset header, and free up the crypto */
/* Free up the crypto pool */
tcp_put_md5sig_pool();
th->check = old_checksum;

out:
return 0;
clear_hash:
Expand Down
53 changes: 5 additions & 48 deletions trunk/net/ipv6/tcp_ipv6.c
Original file line number Diff line number Diff line change
Expand Up @@ -738,75 +738,32 @@ static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
struct in6_addr *daddr,
struct tcphdr *th, unsigned int tcplen)
{
struct scatterlist sg[4];
__u16 data_len;
int block = 0;
__sum16 cksum;
struct tcp_md5sig_pool *hp;
struct tcp6_pseudohdr *bp;
struct hash_desc *desc;
int err;
unsigned int nbytes = 0;

hp = tcp_get_md5sig_pool();
if (!hp) {
printk(KERN_WARNING "%s(): hash pool not found...\n", __func__);
goto clear_hash_noput;
}

bp = &hp->md5_blk.ip6;
desc = &hp->md5_desc;

/* 1. TCP pseudo-header (RFC2460) */
ipv6_addr_copy(&bp->saddr, saddr);
ipv6_addr_copy(&bp->daddr, daddr);
bp->len = htonl(tcplen);
bp->protocol = htonl(IPPROTO_TCP);

sg_init_table(sg, 4);

sg_set_buf(&sg[block++], bp, sizeof(*bp));
nbytes += sizeof(*bp);

/* 2. TCP header, excluding options */
cksum = th->check;
th->check = 0;
sg_set_buf(&sg[block++], th, sizeof(*th));
nbytes += sizeof(*th);

/* 3. TCP segment data (if any) */
data_len = tcplen - (th->doff << 2);
if (data_len > 0) {
u8 *data = (u8 *)th + (th->doff << 2);
sg_set_buf(&sg[block++], data, data_len);
nbytes += data_len;
}

/* 4. shared key */
sg_set_buf(&sg[block++], key->key, key->keylen);
nbytes += key->keylen;

sg_mark_end(&sg[block - 1]);
err = tcp_calc_md5_hash(md5_hash, key, sizeof(*bp),
th, tcplen, hp);

/* Now store the hash into the packet */
err = crypto_hash_init(desc);
if (err) {
printk(KERN_WARNING "%s(): hash_init failed\n", __func__);
goto clear_hash;
}
err = crypto_hash_update(desc, sg, nbytes);
if (err) {
printk(KERN_WARNING "%s(): hash_update failed\n", __func__);
goto clear_hash;
}
err = crypto_hash_final(desc, md5_hash);
if (err) {
printk(KERN_WARNING "%s(): hash_final failed\n", __func__);
if (err)
goto clear_hash;
}

/* Reset header, and free up the crypto */
/* Free up the crypto pool */
tcp_put_md5sig_pool();
th->check = cksum;
out:
return 0;
clear_hash:
Expand Down

0 comments on commit 05054d6

Please sign in to comment.