Commit 1758a81f authored by Herbert Xu's avatar Herbert Xu Committed by Stephen Hemminger

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: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent a37b01c1
...@@ -154,7 +154,8 @@ const char *strxf_xfrmproto(__u8 proto) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment