[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:
Herbert Xu
2008-01-28 19:37:29 -08:00
committed by David S. Miller
parent 6fbf2cb774
commit 1a6509d991
7 changed files with 347 additions and 32 deletions

View File

@@ -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())