mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 11:46:19 +00:00
[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>
This commit is contained in:
parent
6fbf2cb774
commit
1a6509d991
7 changed files with 347 additions and 32 deletions
|
@ -298,6 +298,12 @@ struct sadb_x_sec_ctx {
|
|||
#define SADB_X_EALG_BLOWFISHCBC 7
|
||||
#define SADB_EALG_NULL 11
|
||||
#define SADB_X_EALG_AESCBC 12
|
||||
#define SADB_X_EALG_AES_CCM_ICV8 14
|
||||
#define SADB_X_EALG_AES_CCM_ICV12 15
|
||||
#define SADB_X_EALG_AES_CCM_ICV16 16
|
||||
#define SADB_X_EALG_AES_GCM_ICV8 18
|
||||
#define SADB_X_EALG_AES_GCM_ICV12 19
|
||||
#define SADB_X_EALG_AES_GCM_ICV16 20
|
||||
#define SADB_X_EALG_CAMELLIACBC 22
|
||||
#define SADB_EALG_MAX 253 /* last EALG */
|
||||
/* private allocations should use 249-255 (RFC2407) */
|
||||
|
|
|
@ -96,6 +96,13 @@ struct xfrm_algo {
|
|||
char alg_key[0];
|
||||
};
|
||||
|
||||
struct xfrm_algo_aead {
|
||||
char alg_name[64];
|
||||
int alg_key_len; /* in bits */
|
||||
int alg_icv_len; /* in bits */
|
||||
char alg_key[0];
|
||||
};
|
||||
|
||||
struct xfrm_stats {
|
||||
__u32 replay_window;
|
||||
__u32 replay;
|
||||
|
@ -270,6 +277,7 @@ enum xfrm_attr_type_t {
|
|||
XFRMA_LASTUSED,
|
||||
XFRMA_POLICY_TYPE, /* struct xfrm_userpolicy_type */
|
||||
XFRMA_MIGRATE,
|
||||
XFRMA_ALG_AEAD, /* struct xfrm_algo_aead */
|
||||
__XFRMA_MAX
|
||||
|
||||
#define XFRMA_MAX (__XFRMA_MAX - 1)
|
||||
|
|
|
@ -159,6 +159,7 @@ struct xfrm_state
|
|||
struct xfrm_algo *aalg;
|
||||
struct xfrm_algo *ealg;
|
||||
struct xfrm_algo *calg;
|
||||
struct xfrm_algo_aead *aead;
|
||||
|
||||
/* Data for encapsulator */
|
||||
struct xfrm_encap_tmpl *encap;
|
||||
|
@ -1108,6 +1109,10 @@ static inline int xfrm_id_proto_match(u8 proto, u8 userproto)
|
|||
/*
|
||||
* xfrm algorithm information
|
||||
*/
|
||||
struct xfrm_algo_aead_info {
|
||||
u16 icv_truncbits;
|
||||
};
|
||||
|
||||
struct xfrm_algo_auth_info {
|
||||
u16 icv_truncbits;
|
||||
u16 icv_fullbits;
|
||||
|
@ -1127,6 +1132,7 @@ struct xfrm_algo_desc {
|
|||
char *compat;
|
||||
u8 available:1;
|
||||
union {
|
||||
struct xfrm_algo_aead_info aead;
|
||||
struct xfrm_algo_auth_info auth;
|
||||
struct xfrm_algo_encr_info encr;
|
||||
struct xfrm_algo_comp_info comp;
|
||||
|
@ -1343,6 +1349,8 @@ extern struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id);
|
|||
extern struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name, int probe);
|
||||
extern struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name, int probe);
|
||||
extern struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe);
|
||||
extern struct xfrm_algo_desc *xfrm_aead_get_byname(char *name, int icv_len,
|
||||
int probe);
|
||||
|
||||
struct hash_desc;
|
||||
struct scatterlist;
|
||||
|
|
|
@ -439,32 +439,53 @@ static void esp_destroy(struct xfrm_state *x)
|
|||
kfree(esp);
|
||||
}
|
||||
|
||||
static int esp_init_state(struct xfrm_state *x)
|
||||
static int esp_init_aead(struct xfrm_state *x)
|
||||
{
|
||||
struct esp_data *esp = NULL;
|
||||
struct esp_data *esp = x->data;
|
||||
struct crypto_aead *aead;
|
||||
int err;
|
||||
|
||||
aead = crypto_alloc_aead(x->aead->alg_name, 0, 0);
|
||||
err = PTR_ERR(aead);
|
||||
if (IS_ERR(aead))
|
||||
goto error;
|
||||
|
||||
esp->aead = aead;
|
||||
|
||||
err = crypto_aead_setkey(aead, x->aead->alg_key,
|
||||
(x->aead->alg_key_len + 7) / 8);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
err = crypto_aead_setauthsize(aead, x->aead->alg_icv_len / 8);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
error:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int esp_init_authenc(struct xfrm_state *x)
|
||||
{
|
||||
struct esp_data *esp = x->data;
|
||||
struct crypto_aead *aead;
|
||||
struct crypto_authenc_key_param *param;
|
||||
struct rtattr *rta;
|
||||
char *key;
|
||||
char *p;
|
||||
char authenc_name[CRYPTO_MAX_ALG_NAME];
|
||||
u32 align;
|
||||
unsigned int keylen;
|
||||
int err;
|
||||
|
||||
err = -EINVAL;
|
||||
if (x->ealg == NULL)
|
||||
return -EINVAL;
|
||||
goto error;
|
||||
|
||||
err = -ENAMETOOLONG;
|
||||
if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME, "authenc(%s,%s)",
|
||||
x->aalg ? x->aalg->alg_name : "digest_null",
|
||||
x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME)
|
||||
return -ENAMETOOLONG;
|
||||
|
||||
esp = kzalloc(sizeof(*esp), GFP_KERNEL);
|
||||
if (esp == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
x->data = esp;
|
||||
goto error;
|
||||
|
||||
aead = crypto_alloc_aead(authenc_name, 0, 0);
|
||||
err = PTR_ERR(aead);
|
||||
|
@ -512,8 +533,6 @@ static int esp_init_state(struct xfrm_state *x)
|
|||
goto free_key;
|
||||
}
|
||||
|
||||
esp->padlen = 0;
|
||||
|
||||
param->enckeylen = cpu_to_be32((x->ealg->alg_key_len + 7) / 8);
|
||||
memcpy(p, x->ealg->alg_key, (x->ealg->alg_key_len + 7) / 8);
|
||||
|
||||
|
@ -522,9 +541,35 @@ static int esp_init_state(struct xfrm_state *x)
|
|||
free_key:
|
||||
kfree(key);
|
||||
|
||||
error:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int esp_init_state(struct xfrm_state *x)
|
||||
{
|
||||
struct esp_data *esp;
|
||||
struct crypto_aead *aead;
|
||||
u32 align;
|
||||
int err;
|
||||
|
||||
esp = kzalloc(sizeof(*esp), GFP_KERNEL);
|
||||
if (esp == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
x->data = esp;
|
||||
|
||||
if (x->aead)
|
||||
err = esp_init_aead(x);
|
||||
else
|
||||
err = esp_init_authenc(x);
|
||||
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
aead = esp->aead;
|
||||
|
||||
esp->padlen = 0;
|
||||
|
||||
x->props.header_len = sizeof(struct ip_esp_hdr) +
|
||||
crypto_aead_ivsize(aead);
|
||||
if (x->props.mode == XFRM_MODE_TUNNEL)
|
||||
|
|
|
@ -382,35 +382,53 @@ static void esp6_destroy(struct xfrm_state *x)
|
|||
kfree(esp);
|
||||
}
|
||||
|
||||
static int esp6_init_state(struct xfrm_state *x)
|
||||
static int esp_init_aead(struct xfrm_state *x)
|
||||
{
|
||||
struct esp_data *esp = NULL;
|
||||
struct esp_data *esp = x->data;
|
||||
struct crypto_aead *aead;
|
||||
int err;
|
||||
|
||||
aead = crypto_alloc_aead(x->aead->alg_name, 0, 0);
|
||||
err = PTR_ERR(aead);
|
||||
if (IS_ERR(aead))
|
||||
goto error;
|
||||
|
||||
esp->aead = aead;
|
||||
|
||||
err = crypto_aead_setkey(aead, x->aead->alg_key,
|
||||
(x->aead->alg_key_len + 7) / 8);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
err = crypto_aead_setauthsize(aead, x->aead->alg_icv_len / 8);
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
error:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int esp_init_authenc(struct xfrm_state *x)
|
||||
{
|
||||
struct esp_data *esp = x->data;
|
||||
struct crypto_aead *aead;
|
||||
struct crypto_authenc_key_param *param;
|
||||
struct rtattr *rta;
|
||||
char *key;
|
||||
char *p;
|
||||
char authenc_name[CRYPTO_MAX_ALG_NAME];
|
||||
u32 align;
|
||||
unsigned int keylen;
|
||||
int err;
|
||||
|
||||
err = -EINVAL;
|
||||
if (x->ealg == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
if (x->encap)
|
||||
return -EINVAL;
|
||||
goto error;
|
||||
|
||||
err = -ENAMETOOLONG;
|
||||
if (snprintf(authenc_name, CRYPTO_MAX_ALG_NAME, "authenc(%s,%s)",
|
||||
x->aalg ? x->aalg->alg_name : "digest_null",
|
||||
x->ealg->alg_name) >= CRYPTO_MAX_ALG_NAME)
|
||||
return -ENAMETOOLONG;
|
||||
|
||||
esp = kzalloc(sizeof(*esp), GFP_KERNEL);
|
||||
if (esp == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
x->data = esp;
|
||||
goto error;
|
||||
|
||||
aead = crypto_alloc_aead(authenc_name, 0, 0);
|
||||
err = PTR_ERR(aead);
|
||||
|
@ -458,8 +476,6 @@ static int esp6_init_state(struct xfrm_state *x)
|
|||
goto free_key;
|
||||
}
|
||||
|
||||
esp->padlen = 0;
|
||||
|
||||
param->enckeylen = cpu_to_be32((x->ealg->alg_key_len + 7) / 8);
|
||||
memcpy(p, x->ealg->alg_key, (x->ealg->alg_key_len + 7) / 8);
|
||||
|
||||
|
@ -468,9 +484,38 @@ static int esp6_init_state(struct xfrm_state *x)
|
|||
free_key:
|
||||
kfree(key);
|
||||
|
||||
error:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int esp6_init_state(struct xfrm_state *x)
|
||||
{
|
||||
struct esp_data *esp;
|
||||
struct crypto_aead *aead;
|
||||
u32 align;
|
||||
int err;
|
||||
|
||||
if (x->encap)
|
||||
return -EINVAL;
|
||||
|
||||
esp = kzalloc(sizeof(*esp), GFP_KERNEL);
|
||||
if (esp == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
x->data = esp;
|
||||
|
||||
if (x->aead)
|
||||
err = esp_init_aead(x);
|
||||
else
|
||||
err = esp_init_authenc(x);
|
||||
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
aead = esp->aead;
|
||||
|
||||
esp->padlen = 0;
|
||||
|
||||
x->props.header_len = sizeof(struct ip_esp_hdr) +
|
||||
crypto_aead_ivsize(aead);
|
||||
switch (x->props.mode) {
|
||||
|
|
|
@ -28,6 +28,105 @@
|
|||
* that instantiated crypto transforms have correct parameters for IPsec
|
||||
* purposes.
|
||||
*/
|
||||
static struct xfrm_algo_desc aead_list[] = {
|
||||
{
|
||||
.name = "rfc4106(gcm(aes))",
|
||||
|
||||
.uinfo = {
|
||||
.aead = {
|
||||
.icv_truncbits = 64,
|
||||
}
|
||||
},
|
||||
|
||||
.desc = {
|
||||
.sadb_alg_id = SADB_X_EALG_AES_GCM_ICV8,
|
||||
.sadb_alg_ivlen = 8,
|
||||
.sadb_alg_minbits = 128,
|
||||
.sadb_alg_maxbits = 256
|
||||
}
|
||||
},
|
||||
{
|
||||
.name = "rfc4106(gcm(aes))",
|
||||
|
||||
.uinfo = {
|
||||
.aead = {
|
||||
.icv_truncbits = 96,
|
||||
}
|
||||
},
|
||||
|
||||
.desc = {
|
||||
.sadb_alg_id = SADB_X_EALG_AES_GCM_ICV12,
|
||||
.sadb_alg_ivlen = 8,
|
||||
.sadb_alg_minbits = 128,
|
||||
.sadb_alg_maxbits = 256
|
||||
}
|
||||
},
|
||||
{
|
||||
.name = "rfc4106(gcm(aes))",
|
||||
|
||||
.uinfo = {
|
||||
.aead = {
|
||||
.icv_truncbits = 128,
|
||||
}
|
||||
},
|
||||
|
||||
.desc = {
|
||||
.sadb_alg_id = SADB_X_EALG_AES_GCM_ICV16,
|
||||
.sadb_alg_ivlen = 8,
|
||||
.sadb_alg_minbits = 128,
|
||||
.sadb_alg_maxbits = 256
|
||||
}
|
||||
},
|
||||
{
|
||||
.name = "rfc4309(ccm(aes))",
|
||||
|
||||
.uinfo = {
|
||||
.aead = {
|
||||
.icv_truncbits = 64,
|
||||
}
|
||||
},
|
||||
|
||||
.desc = {
|
||||
.sadb_alg_id = SADB_X_EALG_AES_CCM_ICV8,
|
||||
.sadb_alg_ivlen = 8,
|
||||
.sadb_alg_minbits = 128,
|
||||
.sadb_alg_maxbits = 256
|
||||
}
|
||||
},
|
||||
{
|
||||
.name = "rfc4309(ccm(aes))",
|
||||
|
||||
.uinfo = {
|
||||
.aead = {
|
||||
.icv_truncbits = 96,
|
||||
}
|
||||
},
|
||||
|
||||
.desc = {
|
||||
.sadb_alg_id = SADB_X_EALG_AES_CCM_ICV12,
|
||||
.sadb_alg_ivlen = 8,
|
||||
.sadb_alg_minbits = 128,
|
||||
.sadb_alg_maxbits = 256
|
||||
}
|
||||
},
|
||||
{
|
||||
.name = "rfc4309(ccm(aes))",
|
||||
|
||||
.uinfo = {
|
||||
.aead = {
|
||||
.icv_truncbits = 128,
|
||||
}
|
||||
},
|
||||
|
||||
.desc = {
|
||||
.sadb_alg_id = SADB_X_EALG_AES_CCM_ICV16,
|
||||
.sadb_alg_ivlen = 8,
|
||||
.sadb_alg_minbits = 128,
|
||||
.sadb_alg_maxbits = 256
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
static struct xfrm_algo_desc aalg_list[] = {
|
||||
{
|
||||
.name = "hmac(digest_null)",
|
||||
|
@ -332,6 +431,11 @@ static struct xfrm_algo_desc calg_list[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static inline int aead_entries(void)
|
||||
{
|
||||
return ARRAY_SIZE(aead_list);
|
||||
}
|
||||
|
||||
static inline int aalg_entries(void)
|
||||
{
|
||||
return ARRAY_SIZE(aalg_list);
|
||||
|
@ -354,6 +458,13 @@ struct xfrm_algo_list {
|
|||
u32 mask;
|
||||
};
|
||||
|
||||
static const struct xfrm_algo_list xfrm_aead_list = {
|
||||
.algs = aead_list,
|
||||
.entries = ARRAY_SIZE(aead_list),
|
||||
.type = CRYPTO_ALG_TYPE_AEAD,
|
||||
.mask = CRYPTO_ALG_TYPE_MASK,
|
||||
};
|
||||
|
||||
static const struct xfrm_algo_list xfrm_aalg_list = {
|
||||
.algs = aalg_list,
|
||||
.entries = ARRAY_SIZE(aalg_list),
|
||||
|
@ -461,6 +572,33 @@ struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(xfrm_calg_get_byname);
|
||||
|
||||
struct xfrm_aead_name {
|
||||
const char *name;
|
||||
int icvbits;
|
||||
};
|
||||
|
||||
static int xfrm_aead_name_match(const struct xfrm_algo_desc *entry,
|
||||
const void *data)
|
||||
{
|
||||
const struct xfrm_aead_name *aead = data;
|
||||
const char *name = aead->name;
|
||||
|
||||
return aead->icvbits == entry->uinfo.aead.icv_truncbits && name &&
|
||||
!strcmp(name, entry->name);
|
||||
}
|
||||
|
||||
struct xfrm_algo_desc *xfrm_aead_get_byname(char *name, int icv_len, int probe)
|
||||
{
|
||||
struct xfrm_aead_name data = {
|
||||
.name = name,
|
||||
.icvbits = icv_len,
|
||||
};
|
||||
|
||||
return xfrm_find_algo(&xfrm_aead_list, xfrm_aead_name_match, &data,
|
||||
probe);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(xfrm_aead_get_byname);
|
||||
|
||||
struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx)
|
||||
{
|
||||
if (idx >= aalg_entries())
|
||||
|
|
|
@ -31,6 +31,11 @@
|
|||
#include <linux/in6.h>
|
||||
#endif
|
||||
|
||||
static inline int aead_len(struct xfrm_algo_aead *alg)
|
||||
{
|
||||
return sizeof(*alg) + ((alg->alg_key_len + 7) / 8);
|
||||
}
|
||||
|
||||
static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type)
|
||||
{
|
||||
struct nlattr *rt = attrs[type];
|
||||
|
@ -68,6 +73,22 @@ static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int verify_aead(struct nlattr **attrs)
|
||||
{
|
||||
struct nlattr *rt = attrs[XFRMA_ALG_AEAD];
|
||||
struct xfrm_algo_aead *algp;
|
||||
|
||||
if (!rt)
|
||||
return 0;
|
||||
|
||||
algp = nla_data(rt);
|
||||
if (nla_len(rt) < aead_len(algp))
|
||||
return -EINVAL;
|
||||
|
||||
algp->alg_name[CRYPTO_MAX_ALG_NAME - 1] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void verify_one_addr(struct nlattr **attrs, enum xfrm_attr_type_t type,
|
||||
xfrm_address_t **addrp)
|
||||
{
|
||||
|
@ -119,20 +140,28 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
|
|||
switch (p->id.proto) {
|
||||
case IPPROTO_AH:
|
||||
if (!attrs[XFRMA_ALG_AUTH] ||
|
||||
attrs[XFRMA_ALG_AEAD] ||
|
||||
attrs[XFRMA_ALG_CRYPT] ||
|
||||
attrs[XFRMA_ALG_COMP])
|
||||
goto out;
|
||||
break;
|
||||
|
||||
case IPPROTO_ESP:
|
||||
if ((!attrs[XFRMA_ALG_AUTH] &&
|
||||
!attrs[XFRMA_ALG_CRYPT]) ||
|
||||
attrs[XFRMA_ALG_COMP])
|
||||
if (attrs[XFRMA_ALG_COMP])
|
||||
goto out;
|
||||
if (!attrs[XFRMA_ALG_AUTH] &&
|
||||
!attrs[XFRMA_ALG_CRYPT] &&
|
||||
!attrs[XFRMA_ALG_AEAD])
|
||||
goto out;
|
||||
if ((attrs[XFRMA_ALG_AUTH] ||
|
||||
attrs[XFRMA_ALG_CRYPT]) &&
|
||||
attrs[XFRMA_ALG_AEAD])
|
||||
goto out;
|
||||
break;
|
||||
|
||||
case IPPROTO_COMP:
|
||||
if (!attrs[XFRMA_ALG_COMP] ||
|
||||
attrs[XFRMA_ALG_AEAD] ||
|
||||
attrs[XFRMA_ALG_AUTH] ||
|
||||
attrs[XFRMA_ALG_CRYPT])
|
||||
goto out;
|
||||
|
@ -143,6 +172,7 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
|
|||
case IPPROTO_ROUTING:
|
||||
if (attrs[XFRMA_ALG_COMP] ||
|
||||
attrs[XFRMA_ALG_AUTH] ||
|
||||
attrs[XFRMA_ALG_AEAD] ||
|
||||
attrs[XFRMA_ALG_CRYPT] ||
|
||||
attrs[XFRMA_ENCAP] ||
|
||||
attrs[XFRMA_SEC_CTX] ||
|
||||
|
@ -155,6 +185,8 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if ((err = verify_aead(attrs)))
|
||||
goto out;
|
||||
if ((err = verify_one_alg(attrs, XFRMA_ALG_AUTH)))
|
||||
goto out;
|
||||
if ((err = verify_one_alg(attrs, XFRMA_ALG_CRYPT)))
|
||||
|
@ -208,6 +240,31 @@ static int attach_one_algo(struct xfrm_algo **algpp, u8 *props,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int attach_aead(struct xfrm_algo_aead **algpp, u8 *props,
|
||||
struct nlattr *rta)
|
||||
{
|
||||
struct xfrm_algo_aead *p, *ualg;
|
||||
struct xfrm_algo_desc *algo;
|
||||
|
||||
if (!rta)
|
||||
return 0;
|
||||
|
||||
ualg = nla_data(rta);
|
||||
|
||||
algo = xfrm_aead_get_byname(ualg->alg_name, ualg->alg_icv_len, 1);
|
||||
if (!algo)
|
||||
return -ENOSYS;
|
||||
*props = algo->desc.sadb_alg_id;
|
||||
|
||||
p = kmemdup(ualg, aead_len(ualg), GFP_KERNEL);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
strcpy(p->alg_name, algo->name);
|
||||
*algpp = p;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int xfrm_user_sec_ctx_size(struct xfrm_sec_ctx *xfrm_ctx)
|
||||
{
|
||||
int len = 0;
|
||||
|
@ -286,6 +343,9 @@ static struct xfrm_state *xfrm_state_construct(struct xfrm_usersa_info *p,
|
|||
|
||||
copy_from_user_state(x, p);
|
||||
|
||||
if ((err = attach_aead(&x->aead, &x->props.ealgo,
|
||||
attrs[XFRMA_ALG_AEAD])))
|
||||
goto error;
|
||||
if ((err = attach_one_algo(&x->aalg, &x->props.aalgo,
|
||||
xfrm_aalg_get_byname,
|
||||
attrs[XFRMA_ALG_AUTH])))
|
||||
|
@ -510,6 +570,8 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
|
|||
if (x->lastused)
|
||||
NLA_PUT_U64(skb, XFRMA_LASTUSED, x->lastused);
|
||||
|
||||
if (x->aead)
|
||||
NLA_PUT(skb, XFRMA_ALG_AEAD, aead_len(x->aead), x->aead);
|
||||
if (x->aalg)
|
||||
NLA_PUT(skb, XFRMA_ALG_AUTH, xfrm_alg_len(x->aalg), x->aalg);
|
||||
if (x->ealg)
|
||||
|
@ -1808,6 +1870,7 @@ static const int xfrm_msg_min[XFRM_NR_MSGTYPES] = {
|
|||
#undef XMSGSIZE
|
||||
|
||||
static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
|
||||
[XFRMA_ALG_AEAD] = { .len = sizeof(struct xfrm_algo_aead) },
|
||||
[XFRMA_ALG_AUTH] = { .len = sizeof(struct xfrm_algo) },
|
||||
[XFRMA_ALG_CRYPT] = { .len = sizeof(struct xfrm_algo) },
|
||||
[XFRMA_ALG_COMP] = { .len = sizeof(struct xfrm_algo) },
|
||||
|
@ -1972,6 +2035,8 @@ static int xfrm_notify_sa_flush(struct km_event *c)
|
|||
static inline size_t xfrm_sa_len(struct xfrm_state *x)
|
||||
{
|
||||
size_t l = 0;
|
||||
if (x->aead)
|
||||
l += nla_total_size(aead_len(x->aead));
|
||||
if (x->aalg)
|
||||
l += nla_total_size(xfrm_alg_len(x->aalg));
|
||||
if (x->ealg)
|
||||
|
|
Loading…
Reference in a new issue