macsec: Add support for GCM-AES-256 cipher suite
authorFelix Walter <felix.walter@cloudandheat.com>
Fri, 5 Jan 2018 13:33:31 +0000 (14:33 +0100)
committerDavid S. Miller <davem@davemloft.net>
Tue, 9 Jan 2018 16:34:18 +0000 (11:34 -0500)
This adds support for the GCM-AES-256 cipher suite as specified in
IEEE 802.1AEbn-2011. The prepared cipher suite selection mechanism is used,
with GCM-AES-128 being the default cipher suite as defined in the standard.

Signed-off-by: Felix Walter <felix.walter@cloudandheat.com>
Cc: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/macsec.c
include/uapi/linux/if_macsec.h

index 1d025ab..f522715 100644 (file)
@@ -393,7 +393,12 @@ static struct macsec_cb *macsec_skb_cb(struct sk_buff *skb)
 #define MACSEC_PORT_SCB (0x0000)
 #define MACSEC_UNDEF_SCI ((__force sci_t)0xffffffffffffffffULL)
 
-#define DEFAULT_SAK_LEN 16
+#define MACSEC_GCM_AES_128_SAK_LEN 16
+#define MACSEC_GCM_AES_256_SAK_LEN 32
+
+#define MAX_SAK_LEN MACSEC_GCM_AES_256_SAK_LEN
+
+#define DEFAULT_SAK_LEN MACSEC_GCM_AES_128_SAK_LEN
 #define DEFAULT_SEND_SCI true
 #define DEFAULT_ENCRYPT false
 #define DEFAULT_ENCODING_SA 0
@@ -1600,7 +1605,7 @@ static const struct nla_policy macsec_genl_sa_policy[NUM_MACSEC_SA_ATTR] = {
        [MACSEC_SA_ATTR_KEYID] = { .type = NLA_BINARY,
                                   .len = MACSEC_KEYID_LEN, },
        [MACSEC_SA_ATTR_KEY] = { .type = NLA_BINARY,
-                                .len = MACSEC_MAX_KEY_LEN, },
+                                .len = MAX_SAK_LEN, },
 };
 
 static int parse_sa_config(struct nlattr **attrs, struct nlattr **tb_sa)
@@ -2362,15 +2367,26 @@ static int nla_put_secy(struct macsec_secy *secy, struct sk_buff *skb)
 {
        struct macsec_tx_sc *tx_sc = &secy->tx_sc;
        struct nlattr *secy_nest = nla_nest_start(skb, MACSEC_ATTR_SECY);
+       u64 csid;
 
        if (!secy_nest)
                return 1;
 
+       switch (secy->key_len) {
+       case MACSEC_GCM_AES_128_SAK_LEN:
+               csid = MACSEC_CIPHER_ID_GCM_AES_128;
+               break;
+       case MACSEC_GCM_AES_256_SAK_LEN:
+               csid = MACSEC_CIPHER_ID_GCM_AES_256;
+               break;
+       default:
+               goto cancel;
+       }
+
        if (nla_put_sci(skb, MACSEC_SECY_ATTR_SCI, secy->sci,
                        MACSEC_SECY_ATTR_PAD) ||
            nla_put_u64_64bit(skb, MACSEC_SECY_ATTR_CIPHER_SUITE,
-                             MACSEC_DEFAULT_CIPHER_ID,
-                             MACSEC_SECY_ATTR_PAD) ||
+                             csid, MACSEC_SECY_ATTR_PAD) ||
            nla_put_u8(skb, MACSEC_SECY_ATTR_ICV_LEN, secy->icv_len) ||
            nla_put_u8(skb, MACSEC_SECY_ATTR_OPER, secy->operational) ||
            nla_put_u8(skb, MACSEC_SECY_ATTR_PROTECT, secy->protect_frames) ||
@@ -3015,8 +3031,8 @@ static void macsec_setup(struct net_device *dev)
        eth_zero_addr(dev->broadcast);
 }
 
-static void macsec_changelink_common(struct net_device *dev,
-                                    struct nlattr *data[])
+static int macsec_changelink_common(struct net_device *dev,
+                                   struct nlattr *data[])
 {
        struct macsec_secy *secy;
        struct macsec_tx_sc *tx_sc;
@@ -3056,6 +3072,22 @@ static void macsec_changelink_common(struct net_device *dev,
 
        if (data[IFLA_MACSEC_VALIDATION])
                secy->validate_frames = nla_get_u8(data[IFLA_MACSEC_VALIDATION]);
+
+       if (data[IFLA_MACSEC_CIPHER_SUITE]) {
+               switch (nla_get_u64(data[IFLA_MACSEC_CIPHER_SUITE])) {
+               case MACSEC_CIPHER_ID_GCM_AES_128:
+               case MACSEC_DEFAULT_CIPHER_ALT:
+                       secy->key_len = MACSEC_GCM_AES_128_SAK_LEN;
+                       break;
+               case MACSEC_CIPHER_ID_GCM_AES_256:
+                       secy->key_len = MACSEC_GCM_AES_256_SAK_LEN;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
 }
 
 static int macsec_changelink(struct net_device *dev, struct nlattr *tb[],
@@ -3071,9 +3103,7 @@ static int macsec_changelink(struct net_device *dev, struct nlattr *tb[],
            data[IFLA_MACSEC_PORT])
                return -EINVAL;
 
-       macsec_changelink_common(dev, data);
-
-       return 0;
+       return macsec_changelink_common(dev, data);
 }
 
 static void macsec_del_dev(struct macsec_dev *macsec)
@@ -3270,8 +3300,11 @@ static int macsec_newlink(struct net *net, struct net_device *dev,
        if (err)
                goto unlink;
 
-       if (data)
-               macsec_changelink_common(dev, data);
+       if (data) {
+               err = macsec_changelink_common(dev, data);
+               if (err)
+                       goto del_dev;
+       }
 
        err = register_macsec_dev(real_dev, dev);
        if (err < 0)
@@ -3320,7 +3353,8 @@ static int macsec_validate_attr(struct nlattr *tb[], struct nlattr *data[],
        }
 
        switch (csid) {
-       case MACSEC_DEFAULT_CIPHER_ID:
+       case MACSEC_CIPHER_ID_GCM_AES_128:
+       case MACSEC_CIPHER_ID_GCM_AES_256:
        case MACSEC_DEFAULT_CIPHER_ALT:
                if (icv_len < MACSEC_MIN_ICV_LEN ||
                    icv_len > MACSEC_STD_ICV_LEN)
@@ -3390,12 +3424,24 @@ static int macsec_fill_info(struct sk_buff *skb,
 {
        struct macsec_secy *secy = &macsec_priv(dev)->secy;
        struct macsec_tx_sc *tx_sc = &secy->tx_sc;
+       u64 csid;
+
+       switch (secy->key_len) {
+       case MACSEC_GCM_AES_128_SAK_LEN:
+               csid = MACSEC_CIPHER_ID_GCM_AES_128;
+               break;
+       case MACSEC_GCM_AES_256_SAK_LEN:
+               csid = MACSEC_CIPHER_ID_GCM_AES_256;
+               break;
+       default:
+               goto nla_put_failure;
+       }
 
        if (nla_put_sci(skb, IFLA_MACSEC_SCI, secy->sci,
                        IFLA_MACSEC_PAD) ||
            nla_put_u8(skb, IFLA_MACSEC_ICV_LEN, secy->icv_len) ||
            nla_put_u64_64bit(skb, IFLA_MACSEC_CIPHER_SUITE,
-                             MACSEC_DEFAULT_CIPHER_ID, IFLA_MACSEC_PAD) ||
+                             csid, IFLA_MACSEC_PAD) ||
            nla_put_u8(skb, IFLA_MACSEC_ENCODING_SA, tx_sc->encoding_sa) ||
            nla_put_u8(skb, IFLA_MACSEC_ENCRYPT, tx_sc->encrypt) ||
            nla_put_u8(skb, IFLA_MACSEC_PROTECT, secy->protect_frames) ||
index 719d243..2e52283 100644 (file)
 #define MACSEC_GENL_NAME "macsec"
 #define MACSEC_GENL_VERSION 1
 
-#define MACSEC_MAX_KEY_LEN 128
+#define MACSEC_MAX_KEY_LEN 256
 
 #define MACSEC_KEYID_LEN 16
 
-#define MACSEC_DEFAULT_CIPHER_ID   0x0080020001000001ULL
-#define MACSEC_DEFAULT_CIPHER_ALT  0x0080C20001000001ULL
+/* cipher IDs as per IEEE802.1AEbn-2011 */
+#define MACSEC_CIPHER_ID_GCM_AES_128 0x0080C20001000001ULL
+#define MACSEC_CIPHER_ID_GCM_AES_256 0x0080C20001000002ULL
+
+#define MACSEC_DEFAULT_CIPHER_ID     MACSEC_CIPHER_ID_GCM_AES_128
+/* deprecated cipher ID for GCM-AES-128 */
+#define MACSEC_DEFAULT_CIPHER_ALT    0x0080020001000001ULL
 
 #define MACSEC_MIN_ICV_LEN 8
 #define MACSEC_MAX_ICV_LEN 32