[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>
This commit is contained in:
parent
44e36b42a8
commit
e4bec827fe
3 changed files with 17 additions and 6 deletions
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue