ip: xfrm: Add AEAD support
This patch allows the user to create/manage AEAD algorithms with the ip xfrm command. AEAD algorithms are also known as combined- mode algorithms. They provide the functionality of encryption algorithms as well as authentication algorithms. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
parent
a37b01c1f0
commit
1758a81f49
39
ip/ipxfrm.c
39
ip/ipxfrm.c
|
|
@ -154,7 +154,8 @@ const char *strxf_xfrmproto(__u8 proto)
|
||||||
|
|
||||||
static const struct typeent algo_types[]= {
|
static const struct typeent algo_types[]= {
|
||||||
{ "enc", XFRMA_ALG_CRYPT }, { "auth", XFRMA_ALG_AUTH },
|
{ "enc", XFRMA_ALG_CRYPT }, { "auth", XFRMA_ALG_AUTH },
|
||||||
{ "comp", XFRMA_ALG_COMP }, { NULL, -1 }
|
{ "comp", XFRMA_ALG_COMP }, { "aead", XFRMA_ALG_AEAD },
|
||||||
|
{ NULL, -1 }
|
||||||
};
|
};
|
||||||
|
|
||||||
int xfrm_algotype_getbyname(char *name)
|
int xfrm_algotype_getbyname(char *name)
|
||||||
|
|
@ -525,8 +526,8 @@ void xfrm_selector_print(struct xfrm_selector *sel, __u16 family,
|
||||||
fprintf(fp, "%s", _SL_);
|
fprintf(fp, "%s", _SL_);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xfrm_algo_print(struct xfrm_algo *algo, int type, int len,
|
static void __xfrm_algo_print(struct xfrm_algo *algo, int type, int len,
|
||||||
FILE *fp, const char *prefix)
|
FILE *fp, const char *prefix, int newline)
|
||||||
{
|
{
|
||||||
int keylen;
|
int keylen;
|
||||||
int i;
|
int i;
|
||||||
|
|
@ -558,6 +559,32 @@ static void xfrm_algo_print(struct xfrm_algo *algo, int type, int len,
|
||||||
fprintf(fp, " (%d bits)", algo->alg_key_len);
|
fprintf(fp, " (%d bits)", algo->alg_key_len);
|
||||||
|
|
||||||
fin:
|
fin:
|
||||||
|
if (newline)
|
||||||
|
fprintf(fp, "%s", _SL_);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void xfrm_algo_print(struct xfrm_algo *algo, int type, int len,
|
||||||
|
FILE *fp, const char *prefix)
|
||||||
|
{
|
||||||
|
return __xfrm_algo_print(algo, type, len, fp, prefix, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void xfrm_aead_print(struct xfrm_algo_aead *algo, int len,
|
||||||
|
FILE *fp, const char *prefix)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
struct xfrm_algo algo;
|
||||||
|
char key[algo->alg_key_len / 8];
|
||||||
|
} base;
|
||||||
|
|
||||||
|
memcpy(base.algo.alg_name, algo->alg_name, sizeof(base.algo.alg_name));
|
||||||
|
base.algo.alg_key_len = algo->alg_key_len;
|
||||||
|
memcpy(base.algo.alg_key, algo->alg_key, algo->alg_key_len / 8);
|
||||||
|
|
||||||
|
__xfrm_algo_print(&base.algo, XFRMA_ALG_AEAD, len, fp, prefix, 0);
|
||||||
|
|
||||||
|
fprintf(fp, " %d", algo->alg_icv_len);
|
||||||
|
|
||||||
fprintf(fp, "%s", _SL_);
|
fprintf(fp, "%s", _SL_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -635,6 +662,12 @@ void xfrm_xfrma_print(struct rtattr *tb[], __u16 family,
|
||||||
XFRMA_ALG_AUTH, RTA_PAYLOAD(rta), fp, prefix);
|
XFRMA_ALG_AUTH, RTA_PAYLOAD(rta), fp, prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tb[XFRMA_ALG_AEAD]) {
|
||||||
|
struct rtattr *rta = tb[XFRMA_ALG_AEAD];
|
||||||
|
xfrm_aead_print((struct xfrm_algo_aead *)RTA_DATA(rta),
|
||||||
|
RTA_PAYLOAD(rta), fp, prefix);
|
||||||
|
}
|
||||||
|
|
||||||
if (tb[XFRMA_ALG_CRYPT]) {
|
if (tb[XFRMA_ALG_CRYPT]) {
|
||||||
struct rtattr *rta = tb[XFRMA_ALG_CRYPT];
|
struct rtattr *rta = tb[XFRMA_ALG_CRYPT];
|
||||||
xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta),
|
xfrm_algo_print((struct xfrm_algo *) RTA_DATA(rta),
|
||||||
|
|
|
||||||
|
|
@ -89,8 +89,10 @@ static void usage(void)
|
||||||
fprintf(stderr, "ENCAP-TYPE := espinudp | espinudp-nonike\n");
|
fprintf(stderr, "ENCAP-TYPE := espinudp | espinudp-nonike\n");
|
||||||
|
|
||||||
fprintf(stderr, "ALGO-LIST := [ ALGO-LIST ] | [ ALGO ]\n");
|
fprintf(stderr, "ALGO-LIST := [ ALGO-LIST ] | [ ALGO ]\n");
|
||||||
fprintf(stderr, "ALGO := ALGO_TYPE ALGO_NAME ALGO_KEY\n");
|
fprintf(stderr, "ALGO := ALGO_TYPE ALGO_NAME ALGO_KEY "
|
||||||
|
"[ ALGO_ICV_LEN ]\n");
|
||||||
fprintf(stderr, "ALGO_TYPE := [ ");
|
fprintf(stderr, "ALGO_TYPE := [ ");
|
||||||
|
fprintf(stderr, "%s | ", strxf_algotype(XFRMA_ALG_AEAD));
|
||||||
fprintf(stderr, "%s | ", strxf_algotype(XFRMA_ALG_CRYPT));
|
fprintf(stderr, "%s | ", strxf_algotype(XFRMA_ALG_CRYPT));
|
||||||
fprintf(stderr, "%s | ", strxf_algotype(XFRMA_ALG_AUTH));
|
fprintf(stderr, "%s | ", strxf_algotype(XFRMA_ALG_AUTH));
|
||||||
fprintf(stderr, "%s ", strxf_algotype(XFRMA_ALG_COMP));
|
fprintf(stderr, "%s ", strxf_algotype(XFRMA_ALG_COMP));
|
||||||
|
|
@ -113,7 +115,7 @@ static void usage(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xfrm_algo_parse(struct xfrm_algo *alg, enum xfrm_attr_type_t type,
|
static int xfrm_algo_parse(struct xfrm_algo *alg, enum xfrm_attr_type_t type,
|
||||||
char *name, char *key, int max)
|
char *name, char *key, char *buf, int max)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
int slen = strlen(key);
|
int slen = strlen(key);
|
||||||
|
|
@ -153,7 +155,7 @@ static int xfrm_algo_parse(struct xfrm_algo *alg, enum xfrm_attr_type_t type,
|
||||||
if (get_u8(&val, vbuf, 16))
|
if (get_u8(&val, vbuf, 16))
|
||||||
invarg("\"ALGOKEY\" is invalid", key);
|
invarg("\"ALGOKEY\" is invalid", key);
|
||||||
|
|
||||||
alg->alg_key[j] = val;
|
buf[j] = val;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
len = slen;
|
len = slen;
|
||||||
|
|
@ -161,7 +163,7 @@ static int xfrm_algo_parse(struct xfrm_algo *alg, enum xfrm_attr_type_t type,
|
||||||
if (len > max)
|
if (len > max)
|
||||||
invarg("\"ALGOKEY\" makes buffer overflow\n", key);
|
invarg("\"ALGOKEY\" makes buffer overflow\n", key);
|
||||||
|
|
||||||
strncpy(alg->alg_key, key, len);
|
strncpy(buf, key, len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -235,6 +237,7 @@ static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv)
|
||||||
} req;
|
} req;
|
||||||
struct xfrm_replay_state replay;
|
struct xfrm_replay_state replay;
|
||||||
char *idp = NULL;
|
char *idp = NULL;
|
||||||
|
char *aeadop = NULL;
|
||||||
char *ealgop = NULL;
|
char *ealgop = NULL;
|
||||||
char *aalgop = NULL;
|
char *aalgop = NULL;
|
||||||
char *calgop = NULL;
|
char *calgop = NULL;
|
||||||
|
|
@ -327,20 +330,31 @@ static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv)
|
||||||
/* try to assume ALGO */
|
/* try to assume ALGO */
|
||||||
int type = xfrm_algotype_getbyname(*argv);
|
int type = xfrm_algotype_getbyname(*argv);
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case XFRMA_ALG_AEAD:
|
||||||
case XFRMA_ALG_CRYPT:
|
case XFRMA_ALG_CRYPT:
|
||||||
case XFRMA_ALG_AUTH:
|
case XFRMA_ALG_AUTH:
|
||||||
case XFRMA_ALG_COMP:
|
case XFRMA_ALG_COMP:
|
||||||
{
|
{
|
||||||
/* ALGO */
|
/* ALGO */
|
||||||
struct {
|
struct {
|
||||||
struct xfrm_algo alg;
|
union {
|
||||||
|
struct xfrm_algo alg;
|
||||||
|
struct xfrm_algo_aead aead;
|
||||||
|
} u;
|
||||||
char buf[XFRM_ALGO_KEY_BUF_SIZE];
|
char buf[XFRM_ALGO_KEY_BUF_SIZE];
|
||||||
} alg;
|
} alg = {};
|
||||||
int len;
|
int len;
|
||||||
|
__u32 icvlen;
|
||||||
char *name;
|
char *name;
|
||||||
char *key;
|
char *key;
|
||||||
|
char *buf;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
case XFRMA_ALG_AEAD:
|
||||||
|
if (aeadop)
|
||||||
|
duparg("ALGOTYPE", *argv);
|
||||||
|
aeadop = *argv;
|
||||||
|
break;
|
||||||
case XFRMA_ALG_CRYPT:
|
case XFRMA_ALG_CRYPT:
|
||||||
if (ealgop)
|
if (ealgop)
|
||||||
duparg("ALGOTYPE", *argv);
|
duparg("ALGOTYPE", *argv);
|
||||||
|
|
@ -371,11 +385,27 @@ static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv)
|
||||||
NEXT_ARG();
|
NEXT_ARG();
|
||||||
key = *argv;
|
key = *argv;
|
||||||
|
|
||||||
memset(&alg, 0, sizeof(alg));
|
buf = alg.u.alg.alg_key;
|
||||||
|
len = sizeof(alg.u.alg);
|
||||||
|
|
||||||
|
if (type != XFRMA_ALG_AEAD)
|
||||||
|
goto parse_algo;
|
||||||
|
|
||||||
|
if (!NEXT_ARG_OK())
|
||||||
|
missarg("ALGOICVLEN");
|
||||||
|
NEXT_ARG();
|
||||||
|
if (get_u32(&icvlen, *argv, 0))
|
||||||
|
invarg("\"aead\" ICV length is invalid",
|
||||||
|
*argv);
|
||||||
|
alg.u.aead.alg_icv_len = icvlen;
|
||||||
|
|
||||||
|
buf = alg.u.aead.alg_key;
|
||||||
|
len = sizeof(alg.u.aead);
|
||||||
|
|
||||||
|
parse_algo:
|
||||||
xfrm_algo_parse((void *)&alg, type, name, key,
|
xfrm_algo_parse((void *)&alg, type, name, key,
|
||||||
sizeof(alg.buf));
|
buf, sizeof(alg.buf));
|
||||||
len = sizeof(struct xfrm_algo) + alg.alg.alg_key_len;
|
len += alg.u.alg.alg_key_len;
|
||||||
|
|
||||||
addattr_l(&req.n, sizeof(req.buf), type,
|
addattr_l(&req.n, sizeof(req.buf), type,
|
||||||
(void *)&alg, len);
|
(void *)&alg, len);
|
||||||
|
|
@ -432,7 +462,7 @@ static int xfrm_state_modify(int cmd, unsigned flags, int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ealgop || aalgop || calgop) {
|
if (aeadop || ealgop || aalgop || calgop) {
|
||||||
if (!xfrm_xfrmproto_is_ipsec(req.xsinfo.id.proto)) {
|
if (!xfrm_xfrmproto_is_ipsec(req.xsinfo.id.proto)) {
|
||||||
fprintf(stderr, "\"ALGO\" is invalid with proto=%s\n",
|
fprintf(stderr, "\"ALGO\" is invalid with proto=%s\n",
|
||||||
strxf_xfrmproto(req.xsinfo.id.proto));
|
strxf_xfrmproto(req.xsinfo.id.proto));
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue