aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2008-01-28 22:37:29 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-31 22:27:03 -0500
commit1a6509d991225ad210de54c63314fd9542922095 (patch)
treeafe5c560388558bebd3e21b7c6f789a28a323a51 /net/xfrm
parent6fbf2cb77461a0cd0675228d20dd0f70d7b2251f (diff)
[IPSEC]: Add support for combined mode algorithms
This patch adds support for combined mode algorithms with GCM being the first algorithm supported. Combined mode algorithms can be added through the xfrm_user interface using the new algorithm payload type XFRMA_ALG_AEAD. Each algorithms is identified by its name and the ICV length. For the purposes of matching algorithms in xfrm_tmpl structures, combined mode algorithms occupy the same name space as encryption algorithms. This is in line with how they are negotiated using IKE. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/xfrm')
-rw-r--r--net/xfrm/xfrm_algo.c138
-rw-r--r--net/xfrm/xfrm_user.c71
2 files changed, 206 insertions, 3 deletions
diff --git a/net/xfrm/xfrm_algo.c b/net/xfrm/xfrm_algo.c
index 02e3ecf9585d..6cc15250de69 100644
--- a/net/xfrm/xfrm_algo.c
+++ b/net/xfrm/xfrm_algo.c
@@ -28,6 +28,105 @@
28 * that instantiated crypto transforms have correct parameters for IPsec 28 * that instantiated crypto transforms have correct parameters for IPsec
29 * purposes. 29 * purposes.
30 */ 30 */
31static struct xfrm_algo_desc aead_list[] = {
32{
33 .name = "rfc4106(gcm(aes))",
34
35 .uinfo = {
36 .aead = {
37 .icv_truncbits = 64,
38 }
39 },
40
41 .desc = {
42 .sadb_alg_id = SADB_X_EALG_AES_GCM_ICV8,
43 .sadb_alg_ivlen = 8,
44 .sadb_alg_minbits = 128,
45 .sadb_alg_maxbits = 256
46 }
47},
48{
49 .name = "rfc4106(gcm(aes))",
50
51 .uinfo = {
52 .aead = {
53 .icv_truncbits = 96,
54 }
55 },
56
57 .desc = {
58 .sadb_alg_id = SADB_X_EALG_AES_GCM_ICV12,
59 .sadb_alg_ivlen = 8,
60 .sadb_alg_minbits = 128,
61 .sadb_alg_maxbits = 256
62 }
63},
64{
65 .name = "rfc4106(gcm(aes))",
66
67 .uinfo = {
68 .aead = {
69 .icv_truncbits = 128,
70 }
71 },
72
73 .desc = {
74 .sadb_alg_id = SADB_X_EALG_AES_GCM_ICV16,
75 .sadb_alg_ivlen = 8,
76 .sadb_alg_minbits = 128,
77 .sadb_alg_maxbits = 256
78 }
79},
80{
81 .name = "rfc4309(ccm(aes))",
82
83 .uinfo = {
84 .aead = {
85 .icv_truncbits = 64,
86 }
87 },
88
89 .desc = {
90 .sadb_alg_id = SADB_X_EALG_AES_CCM_ICV8,
91 .sadb_alg_ivlen = 8,
92 .sadb_alg_minbits = 128,
93 .sadb_alg_maxbits = 256
94 }
95},
96{
97 .name = "rfc4309(ccm(aes))",
98
99 .uinfo = {
100 .aead = {
101 .icv_truncbits = 96,
102 }
103 },
104
105 .desc = {
106 .sadb_alg_id = SADB_X_EALG_AES_CCM_ICV12,
107 .sadb_alg_ivlen = 8,
108 .sadb_alg_minbits = 128,
109 .sadb_alg_maxbits = 256
110 }
111},
112{
113 .name = "rfc4309(ccm(aes))",
114
115 .uinfo = {
116 .aead = {
117 .icv_truncbits = 128,
118 }
119 },
120
121 .desc = {
122 .sadb_alg_id = SADB_X_EALG_AES_CCM_ICV16,
123 .sadb_alg_ivlen = 8,
124 .sadb_alg_minbits = 128,
125 .sadb_alg_maxbits = 256
126 }
127},
128};
129
31static struct xfrm_algo_desc aalg_list[] = { 130static struct xfrm_algo_desc aalg_list[] = {
32{ 131{
33 .name = "hmac(digest_null)", 132 .name = "hmac(digest_null)",
@@ -332,6 +431,11 @@ static struct xfrm_algo_desc calg_list[] = {
332}, 431},
333}; 432};
334 433
434static inline int aead_entries(void)
435{
436 return ARRAY_SIZE(aead_list);
437}
438
335static inline int aalg_entries(void) 439static inline int aalg_entries(void)
336{ 440{
337 return ARRAY_SIZE(aalg_list); 441 return ARRAY_SIZE(aalg_list);
@@ -354,6 +458,13 @@ struct xfrm_algo_list {
354 u32 mask; 458 u32 mask;
355}; 459};
356 460
461static const struct xfrm_algo_list xfrm_aead_list = {
462 .algs = aead_list,
463 .entries = ARRAY_SIZE(aead_list),
464 .type = CRYPTO_ALG_TYPE_AEAD,
465 .mask = CRYPTO_ALG_TYPE_MASK,
466};
467
357static const struct xfrm_algo_list xfrm_aalg_list = { 468static const struct xfrm_algo_list xfrm_aalg_list = {
358 .algs = aalg_list, 469 .algs = aalg_list,
359 .entries = ARRAY_SIZE(aalg_list), 470 .entries = ARRAY_SIZE(aalg_list),
@@ -461,6 +572,33 @@ struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe)
461} 572}
462EXPORT_SYMBOL_GPL(xfrm_calg_get_byname); 573EXPORT_SYMBOL_GPL(xfrm_calg_get_byname);
463 574
575struct xfrm_aead_name {
576 const char *name;
577 int icvbits;
578};
579
580static int xfrm_aead_name_match(const struct xfrm_algo_desc *entry,
581 const void *data)
582{
583 const struct xfrm_aead_name *aead = data;
584 const char *name = aead->name;
585
586 return aead->icvbits == entry->uinfo.aead.icv_truncbits && name &&
587 !strcmp(name, entry->name);
588}
589
590struct xfrm_algo_desc *xfrm_aead_get_byname(char *name, int icv_len, int probe)
591{
592 struct xfrm_aead_name data = {
593 .name = name,
594 .icvbits = icv_len,
595 };
596
597 return xfrm_find_algo(&xfrm_aead_list, xfrm_aead_name_match, &data,
598 probe);
599}
600EXPORT_SYMBOL_GPL(xfrm_aead_get_byname);
601
464struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx) 602struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx)
465{ 603{
466 if (idx >= aalg_entries()) 604 if (idx >= aalg_entries())
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index e0ccdf267813..78338079b7f5 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -31,6 +31,11 @@
31#include <linux/in6.h> 31#include <linux/in6.h>
32#endif 32#endif
33 33
34static inline int aead_len(struct xfrm_algo_aead *alg)
35{
36 return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
37}
38
34static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type) 39static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type)
35{ 40{
36 struct nlattr *rt = attrs[type]; 41 struct nlattr *rt = attrs[type];
@@ -68,6 +73,22 @@ static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type)
68 return 0; 73 return 0;
69} 74}
70 75
76static int verify_aead(struct nlattr **attrs)
77{
78 struct nlattr *rt = attrs[XFRMA_ALG_AEAD];
79 struct xfrm_algo_aead *algp;
80
81 if (!rt)
82 return 0;
83
84 algp = nla_data(rt);
85 if (nla_len(rt) < aead_len(algp))
86 return -EINVAL;
87
88 algp->alg_name[CRYPTO_MAX_ALG_NAME - 1] = '\0';
89 return 0;
90}
91
71static void verify_one_addr(struct nlattr **attrs, enum xfrm_attr_type_t type, 92static void verify_one_addr(struct nlattr **attrs, enum xfrm_attr_type_t type,
72 xfrm_address_t **addrp) 93 xfrm_address_t **addrp)
73{ 94{
@@ -119,20 +140,28 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
119 switch (p->id.proto) { 140 switch (p->id.proto) {
120 case IPPROTO_AH: 141 case IPPROTO_AH:
121 if (!attrs[XFRMA_ALG_AUTH] || 142 if (!attrs[XFRMA_ALG_AUTH] ||
143 attrs[XFRMA_ALG_AEAD] ||
122 attrs[XFRMA_ALG_CRYPT] || 144 attrs[XFRMA_ALG_CRYPT] ||
123 attrs[XFRMA_ALG_COMP]) 145 attrs[XFRMA_ALG_COMP])
124 goto out; 146 goto out;
125 break; 147 break;
126 148
127 case IPPROTO_ESP: 149 case IPPROTO_ESP:
128 if ((!attrs[XFRMA_ALG_AUTH] && 150 if (attrs[XFRMA_ALG_COMP])
129 !attrs[XFRMA_ALG_CRYPT]) || 151 goto out;
130 attrs[XFRMA_ALG_COMP]) 152 if (!attrs[XFRMA_ALG_AUTH] &&
153 !attrs[XFRMA_ALG_CRYPT] &&
154 !attrs[XFRMA_ALG_AEAD])
155 goto out;
156 if ((attrs[XFRMA_ALG_AUTH] ||
157 attrs[XFRMA_ALG_CRYPT]) &&
158 attrs[XFRMA_ALG_AEAD])
131 goto out; 159 goto out;
132 break; 160 break;
133 161
134 case IPPROTO_COMP: 162 case IPPROTO_COMP:
135 if (!attrs[XFRMA_ALG_COMP] || 163 if (!attrs[XFRMA_ALG_COMP] ||
164 attrs[XFRMA_ALG_AEAD] ||
136 attrs[XFRMA_ALG_AUTH] || 165 attrs[XFRMA_ALG_AUTH] ||
137 attrs[XFRMA_ALG_CRYPT]) 166 attrs[XFRMA_ALG_CRYPT])
138 goto out; 167 goto out;
@@ -143,6 +172,7 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
143 case IPPROTO_ROUTING: 172 case IPPROTO_ROUTING:
144 if (attrs[XFRMA_ALG_COMP] || 173 if (attrs[XFRMA_ALG_COMP] ||
145 attrs[XFRMA_ALG_AUTH] || 174 attrs[XFRMA_ALG_AUTH] ||
175 attrs[XFRMA_ALG_AEAD] ||
146 attrs[XFRMA_ALG_CRYPT] || 176 attrs[XFRMA_ALG_CRYPT] ||
147 attrs[XFRMA_ENCAP] || 177 attrs[XFRMA_ENCAP] ||
148 attrs[XFRMA_SEC_CTX] || 178 attrs[XFRMA_SEC_CTX] ||
@@ -155,6 +185,8 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
155 goto out; 185 goto out;
156 } 186 }
157 187
188 if ((err = verify_aead(attrs)))
189 goto out;
158 if ((err = verify_one_alg(attrs, XFRMA_ALG_AUTH))) 190 if ((err = verify_one_alg(attrs, XFRMA_ALG_AUTH)))
159 goto out; 191 goto out;
160 if ((err = verify_one_alg(attrs, XFRMA_ALG_CRYPT))) 192 if ((err = verify_one_alg(attrs, XFRMA_ALG_CRYPT)))
@@ -208,6 +240,31 @@ static int attach_one_algo(struct xfrm_algo **algpp, u8 *props,
208 return 0; 240 return 0;
209} 241}
210 242
243static int attach_aead(struct xfrm_algo_aead **algpp, u8 *props,
244 struct nlattr *rta)
245{
246 struct xfrm_algo_aead *p, *ualg;
247 struct xfrm_algo_desc *algo;
248
249 if (!rta)
250 return 0;
251
252 ualg = nla_data(rta);
253
254 algo = xfrm_aead_get_byname(ualg->alg_name, ualg->alg_icv_len, 1);
255 if (!algo)
256 return -ENOSYS;
257 *props = algo->desc.sadb_alg_id;
258
259 p = kmemdup(ualg, aead_len(ualg), GFP_KERNEL);
260 if (!p)
261 return -ENOMEM;
262
263 strcpy(p->alg_name, algo->name);
264 *algpp = p;
265 return 0;
266}
267
211static inline int xfrm_user_sec_ctx_size(struct xfrm_sec_ctx *xfrm_ctx) 268static inline int xfrm_user_sec_ctx_size(struct xfrm_sec_ctx *xfrm_ctx)
212{ 269{
213 int len = 0; 270 int len = 0;
@@ -286,6 +343,9 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p,
286 343
287 copy_from_user_state(x, p); 344 copy_from_user_state(x, p);
288 345
346 if ((err = attach_aead(&x->aead, &x->props.ealgo,
347 attrs[XFRMA_ALG_AEAD])))
348 goto error;
289 if ((err = attach_one_algo(&x->aalg, &x->props.aalgo, 349 if ((err = attach_one_algo(&x->aalg, &x->props.aalgo,
290 xfrm_aalg_get_byname, 350 xfrm_aalg_get_byname,
291 attrs[XFRMA_ALG_AUTH]))) 351 attrs[XFRMA_ALG_AUTH])))
@@ -510,6 +570,8 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
510 if (x->lastused) 570 if (x->lastused)
511 NLA_PUT_U64(skb, XFRMA_LASTUSED, x->lastused); 571 NLA_PUT_U64(skb, XFRMA_LASTUSED, x->lastused);
512 572
573 if (x->aead)
574 NLA_PUT(skb, XFRMA_ALG_AEAD, aead_len(x->aead), x->aead);
513 if (x->aalg) 575 if (x->aalg)
514 NLA_PUT(skb, XFRMA_ALG_AUTH, xfrm_alg_len(x->aalg), x->aalg); 576 NLA_PUT(skb, XFRMA_ALG_AUTH, xfrm_alg_len(x->aalg), x->aalg);
515 if (x->ealg) 577 if (x->ealg)
@@ -1808,6 +1870,7 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = {
1808#undef XMSGSIZE 1870#undef XMSGSIZE
1809 1871
1810static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { 1872static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
1873 [XFRMA_ALG_AEAD] = { .len = sizeof(struct xfrm_algo_aead) },
1811 [XFRMA_ALG_AUTH] = { .len = sizeof(struct xfrm_algo) }, 1874 [XFRMA_ALG_AUTH] = { .len = sizeof(struct xfrm_algo) },
1812 [XFRMA_ALG_CRYPT] = { .len = sizeof(struct xfrm_algo) }, 1875 [XFRMA_ALG_CRYPT] = { .len = sizeof(struct xfrm_algo) },
1813 [XFRMA_ALG_COMP] = { .len = sizeof(struct xfrm_algo) }, 1876 [XFRMA_ALG_COMP] = { .len = sizeof(struct xfrm_algo) },
@@ -1972,6 +2035,8 @@ static int xfrm_notify_sa_flush(struct km_event *c)
1972static inline size_t xfrm_sa_len(struct xfrm_state *x) 2035static inline size_t xfrm_sa_len(struct xfrm_state *x)
1973{ 2036{
1974 size_t l = 0; 2037 size_t l = 0;
2038 if (x->aead)
2039 l += nla_total_size(aead_len(x->aead));
1975 if (x->aalg) 2040 if (x->aalg)
1976 l += nla_total_size(xfrm_alg_len(x->aalg)); 2041 l += nla_total_size(xfrm_alg_len(x->aalg));
1977 if (x->ealg) 2042 if (x->ealg)