aboutsummaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_user.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm/xfrm_user.c')
-rw-r--r--net/xfrm/xfrm_user.c71
1 files changed, 68 insertions, 3 deletions
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)