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/ipv6/esp6.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/ipv6/esp6.c')
-rw-r--r-- | net/ipv6/esp6.c | 48 |
1 files changed, 28 insertions, 20 deletions
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index a278d5e862fe..46a7e687948e 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
@@ -24,6 +24,7 @@ | |||
24 | * This file is derived from net/ipv4/esp.c | 24 | * This file is derived from net/ipv4/esp.c |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <linux/err.h> | ||
27 | #include <linux/module.h> | 28 | #include <linux/module.h> |
28 | #include <net/ip.h> | 29 | #include <net/ip.h> |
29 | #include <net/xfrm.h> | 30 | #include <net/xfrm.h> |
@@ -44,7 +45,8 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
44 | int hdr_len; | 45 | int hdr_len; |
45 | struct ipv6hdr *top_iph; | 46 | struct ipv6hdr *top_iph; |
46 | struct ipv6_esp_hdr *esph; | 47 | struct ipv6_esp_hdr *esph; |
47 | struct crypto_tfm *tfm; | 48 | struct crypto_blkcipher *tfm; |
49 | struct blkcipher_desc desc; | ||
48 | struct esp_data *esp; | 50 | struct esp_data *esp; |
49 | struct sk_buff *trailer; | 51 | struct sk_buff *trailer; |
50 | int blksize; | 52 | int blksize; |
@@ -67,7 +69,9 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
67 | 69 | ||
68 | alen = esp->auth.icv_trunc_len; | 70 | alen = esp->auth.icv_trunc_len; |
69 | tfm = esp->conf.tfm; | 71 | tfm = esp->conf.tfm; |
70 | blksize = ALIGN(crypto_tfm_alg_blocksize(tfm), 4); | 72 | desc.tfm = tfm; |
73 | desc.flags = 0; | ||
74 | blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4); | ||
71 | clen = ALIGN(clen + 2, blksize); | 75 | clen = ALIGN(clen + 2, blksize); |
72 | if (esp->conf.padlen) | 76 | if (esp->conf.padlen) |
73 | clen = ALIGN(clen, esp->conf.padlen); | 77 | clen = ALIGN(clen, esp->conf.padlen); |
@@ -96,7 +100,7 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
96 | xfrm_aevent_doreplay(x); | 100 | xfrm_aevent_doreplay(x); |
97 | 101 | ||
98 | if (esp->conf.ivlen) | 102 | if (esp->conf.ivlen) |
99 | crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); | 103 | crypto_blkcipher_set_iv(tfm, esp->conf.ivec, esp->conf.ivlen); |
100 | 104 | ||
101 | do { | 105 | do { |
102 | struct scatterlist *sg = &esp->sgbuf[0]; | 106 | struct scatterlist *sg = &esp->sgbuf[0]; |
@@ -107,14 +111,17 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
107 | goto error; | 111 | goto error; |
108 | } | 112 | } |
109 | skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen); | 113 | skb_to_sgvec(skb, sg, esph->enc_data+esp->conf.ivlen-skb->data, clen); |
110 | crypto_cipher_encrypt(tfm, sg, sg, clen); | 114 | err = crypto_blkcipher_encrypt(&desc, sg, sg, clen); |
111 | if (unlikely(sg != &esp->sgbuf[0])) | 115 | if (unlikely(sg != &esp->sgbuf[0])) |
112 | kfree(sg); | 116 | kfree(sg); |
113 | } while (0); | 117 | } while (0); |
114 | 118 | ||
119 | if (unlikely(err)) | ||
120 | goto error; | ||
121 | |||
115 | if (esp->conf.ivlen) { | 122 | if (esp->conf.ivlen) { |
116 | memcpy(esph->enc_data, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); | 123 | memcpy(esph->enc_data, esp->conf.ivec, esp->conf.ivlen); |
117 | crypto_cipher_get_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); | 124 | crypto_blkcipher_get_iv(tfm, esp->conf.ivec, esp->conf.ivlen); |
118 | } | 125 | } |
119 | 126 | ||
120 | if (esp->auth.icv_full_len) { | 127 | if (esp->auth.icv_full_len) { |
@@ -123,8 +130,6 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
123 | pskb_put(skb, trailer, alen); | 130 | pskb_put(skb, trailer, alen); |
124 | } | 131 | } |
125 | 132 | ||
126 | err = 0; | ||
127 | |||
128 | error: | 133 | error: |
129 | return err; | 134 | return err; |
130 | } | 135 | } |
@@ -134,8 +139,10 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
134 | struct ipv6hdr *iph; | 139 | struct ipv6hdr *iph; |
135 | struct ipv6_esp_hdr *esph; | 140 | struct ipv6_esp_hdr *esph; |
136 | struct esp_data *esp = x->data; | 141 | struct esp_data *esp = x->data; |
142 | struct crypto_blkcipher *tfm = esp->conf.tfm; | ||
143 | struct blkcipher_desc desc = { .tfm = tfm }; | ||
137 | struct sk_buff *trailer; | 144 | struct sk_buff *trailer; |
138 | int blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4); | 145 | int blksize = ALIGN(crypto_blkcipher_blocksize(tfm), 4); |
139 | int alen = esp->auth.icv_trunc_len; | 146 | int alen = esp->auth.icv_trunc_len; |
140 | int elen = skb->len - sizeof(struct ipv6_esp_hdr) - esp->conf.ivlen - alen; | 147 | int elen = skb->len - sizeof(struct ipv6_esp_hdr) - esp->conf.ivlen - alen; |
141 | 148 | ||
@@ -182,7 +189,7 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
182 | 189 | ||
183 | /* Get ivec. This can be wrong, check against another impls. */ | 190 | /* Get ivec. This can be wrong, check against another impls. */ |
184 | if (esp->conf.ivlen) | 191 | if (esp->conf.ivlen) |
185 | crypto_cipher_set_iv(esp->conf.tfm, esph->enc_data, crypto_tfm_alg_ivsize(esp->conf.tfm)); | 192 | crypto_blkcipher_set_iv(tfm, esph->enc_data, esp->conf.ivlen); |
186 | 193 | ||
187 | { | 194 | { |
188 | u8 nexthdr[2]; | 195 | u8 nexthdr[2]; |
@@ -197,9 +204,11 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
197 | } | 204 | } |
198 | } | 205 | } |
199 | skb_to_sgvec(skb, sg, sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen, elen); | 206 | skb_to_sgvec(skb, sg, sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen, elen); |
200 | crypto_cipher_decrypt(esp->conf.tfm, sg, sg, elen); | 207 | ret = crypto_blkcipher_decrypt(&desc, sg, sg, elen); |
201 | if (unlikely(sg != &esp->sgbuf[0])) | 208 | if (unlikely(sg != &esp->sgbuf[0])) |
202 | kfree(sg); | 209 | kfree(sg); |
210 | if (unlikely(ret)) | ||
211 | goto out; | ||
203 | 212 | ||
204 | if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2)) | 213 | if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2)) |
205 | BUG(); | 214 | BUG(); |
@@ -225,7 +234,7 @@ out: | |||
225 | static u32 esp6_get_max_size(struct xfrm_state *x, int mtu) | 234 | static u32 esp6_get_max_size(struct xfrm_state *x, int mtu) |
226 | { | 235 | { |
227 | struct esp_data *esp = x->data; | 236 | struct esp_data *esp = x->data; |
228 | u32 blksize = ALIGN(crypto_tfm_alg_blocksize(esp->conf.tfm), 4); | 237 | u32 blksize = ALIGN(crypto_blkcipher_blocksize(esp->conf.tfm), 4); |
229 | 238 | ||
230 | if (x->props.mode) { | 239 | if (x->props.mode) { |
231 | mtu = ALIGN(mtu + 2, blksize); | 240 | mtu = ALIGN(mtu + 2, blksize); |
@@ -266,7 +275,7 @@ static void esp6_destroy(struct xfrm_state *x) | |||
266 | if (!esp) | 275 | if (!esp) |
267 | return; | 276 | return; |
268 | 277 | ||
269 | crypto_free_tfm(esp->conf.tfm); | 278 | crypto_free_blkcipher(esp->conf.tfm); |
270 | esp->conf.tfm = NULL; | 279 | esp->conf.tfm = NULL; |
271 | kfree(esp->conf.ivec); | 280 | kfree(esp->conf.ivec); |
272 | esp->conf.ivec = NULL; | 281 | esp->conf.ivec = NULL; |
@@ -280,6 +289,7 @@ static void esp6_destroy(struct xfrm_state *x) | |||
280 | static int esp6_init_state(struct xfrm_state *x) | 289 | static int esp6_init_state(struct xfrm_state *x) |
281 | { | 290 | { |
282 | struct esp_data *esp = NULL; | 291 | struct esp_data *esp = NULL; |
292 | struct crypto_blkcipher *tfm; | ||
283 | 293 | ||
284 | /* null auth and encryption can have zero length keys */ | 294 | /* null auth and encryption can have zero length keys */ |
285 | if (x->aalg) { | 295 | if (x->aalg) { |
@@ -327,13 +337,11 @@ static int esp6_init_state(struct xfrm_state *x) | |||
327 | } | 337 | } |
328 | esp->conf.key = x->ealg->alg_key; | 338 | esp->conf.key = x->ealg->alg_key; |
329 | esp->conf.key_len = (x->ealg->alg_key_len+7)/8; | 339 | esp->conf.key_len = (x->ealg->alg_key_len+7)/8; |
330 | if (x->props.ealgo == SADB_EALG_NULL) | 340 | tfm = crypto_alloc_blkcipher(x->ealg->alg_name, 0, CRYPTO_ALG_ASYNC); |
331 | esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_ECB); | 341 | if (IS_ERR(tfm)) |
332 | else | ||
333 | esp->conf.tfm = crypto_alloc_tfm(x->ealg->alg_name, CRYPTO_TFM_MODE_CBC); | ||
334 | if (esp->conf.tfm == NULL) | ||
335 | goto error; | 342 | goto error; |
336 | esp->conf.ivlen = crypto_tfm_alg_ivsize(esp->conf.tfm); | 343 | esp->conf.tfm = tfm; |
344 | esp->conf.ivlen = crypto_blkcipher_ivsize(tfm); | ||
337 | esp->conf.padlen = 0; | 345 | esp->conf.padlen = 0; |
338 | if (esp->conf.ivlen) { | 346 | if (esp->conf.ivlen) { |
339 | esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL); | 347 | esp->conf.ivec = kmalloc(esp->conf.ivlen, GFP_KERNEL); |
@@ -341,7 +349,7 @@ static int esp6_init_state(struct xfrm_state *x) | |||
341 | goto error; | 349 | goto error; |
342 | get_random_bytes(esp->conf.ivec, esp->conf.ivlen); | 350 | get_random_bytes(esp->conf.ivec, esp->conf.ivlen); |
343 | } | 351 | } |
344 | if (crypto_cipher_setkey(esp->conf.tfm, esp->conf.key, esp->conf.key_len)) | 352 | if (crypto_blkcipher_setkey(tfm, esp->conf.key, esp->conf.key_len)) |
345 | goto error; | 353 | goto error; |
346 | x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen; | 354 | x->props.header_len = sizeof(struct ipv6_esp_hdr) + esp->conf.ivlen; |
347 | if (x->props.mode) | 355 | if (x->props.mode) |