diff options
author | David S. Miller <davem@davemloft.net> | 2006-09-22 15:17:35 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-09-22 15:17:35 -0700 |
commit | e4bec827feda76d5e7417a2696a75424834d564f (patch) | |
tree | bd899e0c2fbf7f6dd1d33ce0610d88fc4a8864ee | |
parent | 44e36b42a8378be1dcf7e6f8a1cb2710a8903387 (diff) | |
download | linux-e4bec827feda76d5e7417a2696a75424834d564f.tar.gz linux-e4bec827feda76d5e7417a2696a75424834d564f.tar.bz2 linux-e4bec827feda76d5e7417a2696a75424834d564f.zip |
[IPSEC] esp: Defer output IV initialization to first use.
First of all, if the xfrm_state only gets used for input
packets this entropy is a complete waste.
Secondly, it is often the case that a configuration loads
many rules (perhaps even dynamically) and they don't all
necessarily ever get used.
This get_random_bytes() call was showing up in the profiles
for xfrm_state inserts which is how I noticed this.
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/esp.h | 5 | ||||
-rw-r--r-- | net/ipv4/esp4.c | 9 | ||||
-rw-r--r-- | net/ipv6/esp6.c | 9 |
3 files changed, 17 insertions, 6 deletions
diff --git a/include/net/esp.h b/include/net/esp.h index 064366d66eea..713d039f4af7 100644 --- a/include/net/esp.h +++ b/include/net/esp.h @@ -15,13 +15,14 @@ struct esp_data struct { u8 *key; /* Key */ int key_len; /* Key length */ - u8 *ivec; /* ivec buffer */ + int padlen; /* 0..255 */ /* ivlen is offset from enc_data, where encrypted data start. * It is logically different of crypto_tfm_alg_ivsize(tfm). * We assume that it is either zero (no ivec), or * >= crypto_tfm_alg_ivsize(tfm). */ int ivlen; - int padlen; /* 0..255 */ + int ivinitted; + u8 *ivec; /* ivec buffer */ struct crypto_blkcipher *tfm; /* crypto handle */ } conf; diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index e87377e1d6b6..13b29360d102 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -95,8 +95,13 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) esph->seq_no = htonl(++x->replay.oseq); xfrm_aevent_doreplay(x); - if (esp->conf.ivlen) + if (esp->conf.ivlen) { + if (unlikely(!esp->conf.ivinitted)) { + get_random_bytes(esp->conf.ivec, esp->conf.ivlen); + esp->conf.ivinitted = 1; + } crypto_blkcipher_set_iv(tfm, esp->conf.ivec, esp->conf.ivlen); + } do { struct scatterlist *sg = &esp->sgbuf[0]; @@ -378,7 +383,7 @@ static int esp_init_state(struct xfrm_state *x) esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL); if (unlikely(esp->conf.ivec == NULL)) goto error; - get_random_bytes(esp->conf.ivec, esp->conf.ivlen); + esp->conf.ivinitted = 0; } if (crypto_blkcipher_setkey(tfm, esp->conf.key, esp->conf.key_len)) goto error; diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index ae50b9511151..e78680a9985b 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -99,8 +99,13 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) esph->seq_no = htonl(++x->replay.oseq); xfrm_aevent_doreplay(x); - if (esp->conf.ivlen) + if (esp->conf.ivlen) { + if (unlikely(!esp->conf.ivinitted)) { + get_random_bytes(esp->conf.ivec, esp->conf.ivlen); + esp->conf.ivinitted = 1; + } crypto_blkcipher_set_iv(tfm, esp->conf.ivec, esp->conf.ivlen); + } do { struct scatterlist *sg = &esp->sgbuf[0]; @@ -353,7 +358,7 @@ static int esp6_init_state(struct xfrm_state *x) esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL); if (unlikely(esp->conf.ivec == NULL)) goto error; - get_random_bytes(esp->conf.ivec, esp->conf.ivlen); + esp->conf.ivinitted = 0; } if (crypto_blkcipher_setkey(tfm, esp->conf.key, esp->conf.key_len)) goto error; |