diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2006-07-30 01:41:01 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2006-09-20 21:46:14 -0400 |
commit | 6b7326c8497f954c2cfcb4c49fe42be5b80887bc (patch) | |
tree | 5739c37f7a72d1ef281fbbb5bbc1483226eec198 /net/ipv4/esp4.c | |
parent | 04ff12609445c7b462d7fc7f2d30dad442c922f3 (diff) |
[IPSEC] ESP: Use block ciphers where applicable
This patch converts IPSec/ESP to use the new block cipher type where
applicable. Similar to the HMAC conversion, existing algorithm names
have been kept for compatibility.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'net/ipv4/esp4.c')
-rw-r--r-- | net/ipv4/esp4.c | 49 |
1 files changed, 29 insertions, 20 deletions
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index fc2f8ce441de..7c63ae494742 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c | |||
@@ -1,3 +1,4 @@ | |||
1 | #include <linux/err.h> | ||
1 | #include <linux/module.h> | 2 | #include <linux/module.h> |
2 | #include <net/ip.h> | 3 | #include <net/ip.h> |
3 | #include <net/xfrm.h> | 4 | #include <net/xfrm.h> |
@@ -16,7 +17,8 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) | |||
16 | int err; | 17 | int err; |
17 | struct iphdr *top_iph; | 18 | struct iphdr *top_iph; |
18 | struct ip_esp_hdr *esph; | 19 | struct ip_esp_hdr *esph; |
19 | struct crypto_tfm *tfm; | 20 | struct crypto_blkcipher *tfm; |
21 | struct blkcipher_desc desc; | ||
20 | struct esp_data *esp; | 22 | struct esp_data *esp; |
21 | struct sk_buff *trailer; | 23 | struct sk_buff *trailer; |
22 | int blksize; | 24 | int blksize; |
@@ -36,7 +38,9 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) | |||
36 | esp = x->data; | 38 | esp = x->data; |
37 | alen = esp->auth.icv_trunc_len; | 39 | alen = esp->auth.icv_trunc_len; |
38 | tfm = esp->conf.tfm; | 40 | tfm = esp->conf.tfm; |
39 | blksize = ALIGN(crypto_tfm_alg_blocksize(tfm), 4); | 41 | desc.tfm = tfm; |
42 | desc.flags = 0; | ||
43 | blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4); | ||
40 | clen = ALIGN(clen + 2, blksize); | 44 | clen = ALIGN(clen + 2, blksize); |
41 | if (esp->conf.padlen) | 45 | if (esp->conf.padlen) |
42 | clen = ALIGN(clen, esp->conf.padlen); | 46 | clen = ALIGN(clen, esp->conf.padlen); |
@@ -92,7 +96,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) | |||
92 | xfrm_aevent_doreplay(x); | 96 | xfrm_aevent_doreplay(x); |
93 | 97 | ||
94 | if (esp->conf.ivlen) | 98 | if (esp->conf.ivlen) |
95 | crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); | 99 | crypto_blkcipher_set_iv(tfm, esp->conf.ivec, esp->conf.ivlen); |
96 | 100 | ||
97 | do { | 101 | do { |
98 | struct scatterlist *sg = &esp->sgbuf[0]; | 102 | struct scatterlist *sg = &esp->sgbuf[0]; |
@@ -103,14 +107,17 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) | |||
103 | goto error; | 107 | goto error; |
104 | } | 108 | } |
105 | skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen); | 109 | skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen); |
106 | crypto_cipher_encrypt(tfm, sg, sg, clen); | 110 | err = crypto_blkcipher_encrypt(&desc, sg, sg, clen); |
107 | if (unlikely(sg != &esp->sgbuf[0])) | 111 | if (unlikely(sg != &esp->sgbuf[0])) |
108 | kfree(sg); | 112 | kfree(sg); |
109 | } while (0); | 113 | } while (0); |
110 | 114 | ||
115 | if (unlikely(err)) | ||
116 | goto error; | ||
117 | |||
111 | if (esp->conf.ivlen) { | 118 | if (esp->conf.ivlen) { |
112 | memcpy(esph->enc_data, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); | 119 | memcpy(esph->enc_data, esp->conf.ivec, esp->conf.ivlen); |
113 | crypto_cipher_get_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); | 120 | crypto_blkcipher_get_iv(tfm, esp->conf.ivec, esp->conf.ivlen); |
114 | } | 121 | } |
115 | 122 | ||
116 | if (esp->auth.icv_full_len) { | 123 | if (esp->auth.icv_full_len) { |
@@ -121,8 +128,6 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) | |||
121 | 128 | ||
122 | ip_send_check(top_iph); | 129 | ip_send_check(top_iph); |
123 | 130 | ||
124 | err = 0; | ||
125 | |||
126 | error: | 131 | error: |
127 | return err; | 132 | return err; |
128 | } | 133 | } |
@@ -137,8 +142,10 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) | |||
137 | struct iphdr *iph; | 142 | struct iphdr *iph; |
138 | struct ip_esp_hdr *esph; | 143 | struct ip_esp_hdr *esph; |
139 | struct esp_data *esp = x->data; | 144 | struct esp_data *esp = x->data; |
145 | struct crypto_blkcipher *tfm = esp->conf.tfm; | ||
146 | struct blkcipher_desc desc = { .tfm = tfm }; | ||
140 | struct sk_buff *trailer; | 147 | struct sk_buff *trailer; |
141 | int blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4); | 148 | int blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4); |
142 | int alen = esp->auth.icv_trunc_len; | 149 | int alen = esp->auth.icv_trunc_len; |
143 | int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen; | 150 | int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen; |
144 | int nfrags; | 151 | int nfrags; |
@@ -146,6 +153,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) | |||
146 | u8 nexthdr[2]; | 153 | u8 nexthdr[2]; |
147 | struct scatterlist *sg; | 154 | struct scatterlist *sg; |
148 | int padlen; | 155 | int padlen; |
156 | int err; | ||
149 | 157 | ||
150 | if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr))) | 158 | if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr))) |
151 | goto out; | 159 | goto out; |
@@ -178,7 +186,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) | |||
178 | 186 | ||
179 | /* Get ivec. This can be wrong, check against another impls. */ | 187 | /* Get ivec. This can be wrong, check against another impls. */ |
180 | if (esp->conf.ivlen) | 188 | if (esp->conf.ivlen) |
181 | crypto_cipher_set_iv(esp->conf.tfm, esph->enc_data, crypto_tfm_alg_ivsize(esp->conf.tfm)); | 189 | crypto_blkcipher_set_iv(tfm, esph->enc_data, esp->conf.ivlen); |
182 | 190 | ||
183 | sg = &esp->sgbuf[0]; | 191 | sg = &esp->sgbuf[0]; |
184 | 192 | ||
@@ -188,9 +196,11 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) | |||
188 | goto out; | 196 | goto out; |
189 | } | 197 | } |
190 | skb_to_sgvec(skb, sg, sizeof(struct ip_esp_hdr) + esp->conf.ivlen, elen); | 198 | skb_to_sgvec(skb, sg, sizeof(struct ip_esp_hdr) + esp->conf.ivlen, elen); |
191 | crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen); | 199 | err = crypto_blkcipher_decrypt(&desc, sg, sg, elen); |
192 | if (unlikely(sg != &esp->sgbuf[0])) | 200 | if (unlikely(sg != &esp->sgbuf[0])) |
193 | kfree(sg); | 201 | kfree(sg); |
202 | if (unlikely(err)) | ||
203 | return err; | ||
194 | 204 | ||
195 | if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2)) | 205 | if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2)) |
196 | BUG(); | 206 | BUG(); |
@@ -254,7 +264,7 @@ out: | |||
254 | static u32 esp4_get_max_size(struct xfrm_state *x, int mtu) | 264 | static u32 esp4_get_max_size(struct xfrm_state *x, int mtu) |
255 | { | 265 | { |
256 | struct esp_data *esp = x->data; | 266 | struct esp_data *esp = x->data; |
257 | u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4); | 267 | u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4); |
258 | 268 | ||
259 | if (x->props.mode) { | 269 | if (x->props.mode) { |
260 | mtu = ALIGN(mtu + 2, blksize); | 270 | mtu = ALIGN(mtu + 2, blksize); |
@@ -293,7 +303,7 @@ static void esp_destroy(struct xfrm_state *x) | |||
293 | if (!esp) | 303 | if (!esp) |
294 | return; | 304 | return; |
295 | 305 | ||
296 | crypto_free_tfm(esp->conf.tfm); | 306 | crypto_free_blkcipher(esp->conf.tfm); |
297 | esp->conf.tfm = NULL; | 307 | esp->conf.tfm = NULL; |
298 | kfree(esp->conf.ivec); | 308 | kfree(esp->conf.ivec); |
299 | esp->conf.ivec = NULL; | 309 | esp->conf.ivec = NULL; |
@@ -307,6 +317,7 @@ static void esp_destroy(struct xfrm_state *x) | |||
307 | static int esp_init_state(struct xfrm_state *x) | 317 | static int esp_init_state(struct xfrm_state *x) |
308 | { | 318 | { |
309 | struct esp_data *esp = NULL; | 319 | struct esp_data *esp = NULL; |
320 | struct crypto_blkcipher *tfm; | ||
310 | 321 | ||
311 | /* null auth and encryption can have zero length keys */ | 322 | /* null auth and encryption can have zero length keys */ |
312 | if (x->aalg) { | 323 | if (x->aalg) { |
@@ -351,13 +362,11 @@ static int esp_init_state(struct xfrm_state *x) | |||
351 | } | 362 | } |
352 | esp->conf.key = x->ealg->alg_key; | 363 | esp->conf.key = x->ealg->alg_key; |
353 | esp->conf.key_len = (x->ealg->alg_key_len+7)/8; | 364 | esp->conf.key_len = (x->ealg->alg_key_len+7)/8; |
354 | if (x->props.ealgo == SADB_EALG_NULL) | 365 | tfm = crypto_alloc_blkcipher(x->ealg->alg_name, 0, CRYPTO_ALG_ASYNC); |
355 | esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_ECB); | 366 | if (IS_ERR(tfm)) |
356 | else | ||
357 | esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_CBC); | ||
358 | if (esp->conf.tfm == NULL) | ||
359 | goto error; | 367 | goto error; |
360 | esp->conf.ivlen = crypto_tfm_alg_ivsize(esp->conf.tfm); | 368 | esp->conf.tfm = tfm; |
369 | esp->conf.ivlen = crypto_blkcipher_ivsize(tfm); | ||
361 | esp->conf.padlen = 0; | 370 | esp->conf.padlen = 0; |
362 | if (esp->conf.ivlen) { | 371 | if (esp->conf.ivlen) { |
363 | esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL); | 372 | esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL); |
@@ -365,7 +374,7 @@ static int esp_init_state(struct xfrm_state *x) | |||
365 | goto error; | 374 | goto error; |
366 | get_random_bytes(esp->conf.ivec, esp->conf.ivlen); | 375 | get_random_bytes(esp->conf.ivec, esp->conf.ivlen); |
367 | } | 376 | } |
368 | if (crypto_cipher_setkey(esp->conf.tfm, esp->conf.key, esp->conf.key_len)) | 377 | if (crypto_blkcipher_setkey(tfm, esp->conf.key, esp->conf.key_len)) |
369 | goto error; | 378 | goto error; |
370 | x->props.header_len = sizeof(struct ip_esp_hdr) + esp->conf.ivlen; | 379 | x->props.header_len = sizeof(struct ip_esp_hdr) + esp->conf.ivlen; |
371 | if (x->props.mode) | 380 | if (x->props.mode) |