diff --git a/patch/macsec-Netlink-support-of-XPN-cipher-suites-IEEE-802.patch b/patch/macsec-Netlink-support-of-XPN-cipher-suites-IEEE-802.patch new file mode 100644 index 000000000000..86d5890a350c --- /dev/null +++ b/patch/macsec-Netlink-support-of-XPN-cipher-suites-IEEE-802.patch @@ -0,0 +1,438 @@ +From 48ef50fa866aae087f63c7de8a47e76537f88691 Mon Sep 17 00:00:00 2001 + +From: Era Mayflower + +Subject: [PATCH] macsec: Netlink support of XPN cipher suites (IEEE 802.1AEbw) + +Netlink support of extended packet number cipher suites, +allows adding and updating XPN macsec interfaces. + +Added support in: + * Creating interfaces with GCM-AES-XPN-128 and GCM-AES-XPN-256 suites. + * Setting and getting 64bit packet numbers with of SAs. + * Setting (only on SA creation) and getting ssci of SAs. + * Setting salt when installing a SAK. + +Added 2 cipher suite identifiers according to 802.1AE-2018 table 14-1: + * MACSEC_CIPHER_ID_GCM_AES_XPN_128 + * MACSEC_CIPHER_ID_GCM_AES_XPN_256 + +In addition, added 2 new netlink attribute types: + * MACSEC_SA_ATTR_SSCI + * MACSEC_SA_ATTR_SALT + +Depends on: macsec: Support XPN frame handling - IEEE 802.1AEbw. + +Signed-off-by: Era Mayflower +Signed-off-by: David S. Miller +--- + drivers/net/macsec.c | 164 +++++++++++++++++++++++++++++++++++++--- + include/uapi/linux/if_macsec.h | 8 +- + 2 files changed, 157 insertions(+), 15 deletions(-) + +diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c +index a41a6cd78..0b86908b9 100644 +--- a/drivers/net/macsec.c ++++ b/drivers/net/macsec.c +@@ -25,6 +25,9 @@ + + #include + ++#define MACSEC_DEFAULT_PN_LEN 4 ++#define MACSEC_XPN_PN_LEN 8 ++ + #define MACSEC_SALT_LEN 12 + #define MACSEC_NUM_AN 4 /* 2 bits for the association number */ + +@@ -444,11 +447,13 @@ static struct macsec_cb *macsec_skb_cb(struct sk_buff *skb) + #define MACSEC_PORT_ES (htons(0x0001)) + #define MACSEC_PORT_SCB (0x0000) + #define MACSEC_UNDEF_SCI ((__force sci_t)0xffffffffffffffffULL) ++#define MACSEC_UNDEF_SSCI ((__force ssci_t)0xffffffff) + + #define MACSEC_GCM_AES_128_SAK_LEN 16 + #define MACSEC_GCM_AES_256_SAK_LEN 32 + + #define DEFAULT_SAK_LEN MACSEC_GCM_AES_128_SAK_LEN ++#define DEFAULT_XPN false + #define DEFAULT_SEND_SCI true + #define DEFAULT_ENCRYPT false + #define DEFAULT_ENCODING_SA 0 +@@ -1438,6 +1443,7 @@ static int init_rx_sa(struct macsec_rx_sa *rx_sa, char *sak, int key_len, + return PTR_ERR(rx_sa->key.tfm); + } + ++ rx_sa->ssci = MACSEC_UNDEF_SSCI; + rx_sa->active = false; + rx_sa->next_pn = 1; + refcount_set(&rx_sa->refcnt, 1); +@@ -1536,6 +1542,7 @@ static int init_tx_sa(struct macsec_tx_sa *tx_sa, char *sak, int key_len, + return PTR_ERR(tx_sa->key.tfm); + } + ++ tx_sa->ssci = MACSEC_UNDEF_SSCI; + tx_sa->active = false; + refcount_set(&tx_sa->refcnt, 1); + spin_lock_init(&tx_sa->lock); +@@ -1579,6 +1586,16 @@ static int nla_put_sci(struct sk_buff *skb, int attrtype, sci_t value, + return nla_put_u64_64bit(skb, attrtype, (__force u64)value, padattr); + } + ++static ssci_t nla_get_ssci(const struct nlattr *nla) ++{ ++ return (__force ssci_t)nla_get_u32(nla); ++} ++ ++static int nla_put_ssci(struct sk_buff *skb, int attrtype, ssci_t value) ++{ ++ return nla_put_u32(skb, attrtype, (__force u64)value); ++} ++ + static struct macsec_tx_sa *get_txsa_from_nl(struct net *net, + struct nlattr **attrs, + struct nlattr **tb_sa, +@@ -1694,11 +1711,14 @@ static const struct nla_policy macsec_genl_rxsc_policy[NUM_MACSEC_RXSC_ATTR] = { + static const struct nla_policy macsec_genl_sa_policy[NUM_MACSEC_SA_ATTR] = { + [MACSEC_SA_ATTR_AN] = { .type = NLA_U8 }, + [MACSEC_SA_ATTR_ACTIVE] = { .type = NLA_U8 }, +- [MACSEC_SA_ATTR_PN] = { .type = NLA_U32 }, ++ [MACSEC_SA_ATTR_PN] = { .type = NLA_MIN_LEN, .len = 4 }, + [MACSEC_SA_ATTR_KEYID] = { .type = NLA_BINARY, + .len = MACSEC_KEYID_LEN, }, + [MACSEC_SA_ATTR_KEY] = { .type = NLA_BINARY, + .len = MACSEC_MAX_KEY_LEN, }, ++ [MACSEC_SA_ATTR_SSCI] = { .type = NLA_U32 }, ++ [MACSEC_SA_ATTR_SALT] = { .type = NLA_BINARY, ++ .len = MACSEC_SALT_LEN, }, + }; + + static int parse_sa_config(struct nlattr **attrs, struct nlattr **tb_sa) +@@ -1737,7 +1757,8 @@ static bool validate_add_rxsa(struct nlattr **attrs) + if (nla_get_u8(attrs[MACSEC_SA_ATTR_AN]) >= MACSEC_NUM_AN) + return false; + +- if (attrs[MACSEC_SA_ATTR_PN] && nla_get_u32(attrs[MACSEC_SA_ATTR_PN]) == 0) ++ if (attrs[MACSEC_SA_ATTR_PN] && ++ *(u64 *)nla_data(attrs[MACSEC_SA_ATTR_PN]) == 0) + return false; + + if (attrs[MACSEC_SA_ATTR_ACTIVE]) { +@@ -1759,6 +1780,7 @@ static int macsec_add_rxsa(struct sk_buff *skb, struct genl_info *info) + struct macsec_rx_sc *rx_sc; + struct macsec_rx_sa *rx_sa; + unsigned char assoc_num; ++ int pn_len; + struct nlattr *tb_rxsc[MACSEC_RXSC_ATTR_MAX + 1]; + struct nlattr *tb_sa[MACSEC_SA_ATTR_MAX + 1]; + int err; +@@ -1791,6 +1813,29 @@ static int macsec_add_rxsa(struct sk_buff *skb, struct genl_info *info) + return -EINVAL; + } + ++ pn_len = secy->xpn ? MACSEC_XPN_PN_LEN : MACSEC_DEFAULT_PN_LEN; ++ if (nla_len(tb_sa[MACSEC_SA_ATTR_PN]) != pn_len) { ++ pr_notice("macsec: nl: add_rxsa: bad pn length: %d != %d\n", ++ nla_len(tb_sa[MACSEC_SA_ATTR_PN]), pn_len); ++ rtnl_unlock(); ++ return -EINVAL; ++ } ++ ++ if (secy->xpn) { ++ if (!tb_sa[MACSEC_SA_ATTR_SSCI] || !tb_sa[MACSEC_SA_ATTR_SALT]) { ++ rtnl_unlock(); ++ return -EINVAL; ++ } ++ ++ if (nla_len(tb_sa[MACSEC_SA_ATTR_SALT]) != MACSEC_SALT_LEN) { ++ pr_notice("macsec: nl: add_rxsa: bad salt length: %d != %d\n", ++ nla_len(tb_sa[MACSEC_SA_ATTR_SALT]), ++ MACSEC_SA_ATTR_SALT); ++ rtnl_unlock(); ++ return -EINVAL; ++ } ++ } ++ + rx_sa = rtnl_dereference(rx_sc->sa[assoc_num]); + if (rx_sa) { + rtnl_unlock(); +@@ -1813,13 +1858,19 @@ static int macsec_add_rxsa(struct sk_buff *skb, struct genl_info *info) + + if (tb_sa[MACSEC_SA_ATTR_PN]) { + spin_lock_bh(&rx_sa->lock); +- rx_sa->next_pn_halves.lower = nla_get_u32(tb_sa[MACSEC_SA_ATTR_PN]); ++ rx_sa->next_pn = nla_get_u64(tb_sa[MACSEC_SA_ATTR_PN]); + spin_unlock_bh(&rx_sa->lock); + } + + if (tb_sa[MACSEC_SA_ATTR_ACTIVE]) + rx_sa->active = !!nla_get_u8(tb_sa[MACSEC_SA_ATTR_ACTIVE]); + ++ if (secy->xpn) { ++ rx_sa->ssci = nla_get_ssci(tb_sa[MACSEC_SA_ATTR_SSCI]); ++ nla_memcpy(rx_sa->key.salt.bytes, tb_sa[MACSEC_SA_ATTR_SALT], ++ MACSEC_SALT_LEN); ++ } ++ + nla_memcpy(rx_sa->key.id, tb_sa[MACSEC_SA_ATTR_KEYID], MACSEC_KEYID_LEN); + rx_sa->sc = rx_sc; + rcu_assign_pointer(rx_sc->sa[assoc_num], rx_sa); +@@ -1915,6 +1966,7 @@ static int macsec_add_txsa(struct sk_buff *skb, struct genl_info *info) + struct macsec_tx_sc *tx_sc; + struct macsec_tx_sa *tx_sa; + unsigned char assoc_num; ++ int pn_len; + struct nlattr *tb_sa[MACSEC_SA_ATTR_MAX + 1]; + int err; + +@@ -1946,6 +1998,29 @@ static int macsec_add_txsa(struct sk_buff *skb, struct genl_info *info) + return -EINVAL; + } + ++ pn_len = secy->xpn ? MACSEC_XPN_PN_LEN : MACSEC_DEFAULT_PN_LEN; ++ if (nla_len(tb_sa[MACSEC_SA_ATTR_PN]) != pn_len) { ++ pr_notice("macsec: nl: add_txsa: bad pn length: %d != %d\n", ++ nla_len(tb_sa[MACSEC_SA_ATTR_PN]), pn_len); ++ rtnl_unlock(); ++ return -EINVAL; ++ } ++ ++ if (secy->xpn) { ++ if (!tb_sa[MACSEC_SA_ATTR_SSCI] || !tb_sa[MACSEC_SA_ATTR_SALT]) { ++ rtnl_unlock(); ++ return -EINVAL; ++ } ++ ++ if (nla_len(tb_sa[MACSEC_SA_ATTR_SALT]) != MACSEC_SALT_LEN) { ++ pr_notice("macsec: nl: add_txsa: bad salt length: %d != %d\n", ++ nla_len(tb_sa[MACSEC_SA_ATTR_SALT]), ++ MACSEC_SA_ATTR_SALT); ++ rtnl_unlock(); ++ return -EINVAL; ++ } ++ } ++ + tx_sa = rtnl_dereference(tx_sc->sa[assoc_num]); + if (tx_sa) { + rtnl_unlock(); +@@ -1966,10 +2041,16 @@ static int macsec_add_txsa(struct sk_buff *skb, struct genl_info *info) + return err; + } + ++ if (secy->xpn) { ++ tx_sa->ssci = nla_get_ssci(tb_sa[MACSEC_SA_ATTR_SSCI]); ++ nla_memcpy(tx_sa->key.salt.bytes, tb_sa[MACSEC_SA_ATTR_SALT], ++ MACSEC_SALT_LEN); ++ } ++ + nla_memcpy(tx_sa->key.id, tb_sa[MACSEC_SA_ATTR_KEYID], MACSEC_KEYID_LEN); + + spin_lock_bh(&tx_sa->lock); +- tx_sa->next_pn_halves.lower = nla_get_u32(tb_sa[MACSEC_SA_ATTR_PN]); ++ tx_sa->next_pn = nla_get_u64(tb_sa[MACSEC_SA_ATTR_PN]); + spin_unlock_bh(&tx_sa->lock); + + if (tb_sa[MACSEC_SA_ATTR_ACTIVE]) +@@ -2107,7 +2188,9 @@ static bool validate_upd_sa(struct nlattr **attrs) + { + if (!attrs[MACSEC_SA_ATTR_AN] || + attrs[MACSEC_SA_ATTR_KEY] || +- attrs[MACSEC_SA_ATTR_KEYID]) ++ attrs[MACSEC_SA_ATTR_KEYID] || ++ attrs[MACSEC_SA_ATTR_SSCI] || ++ attrs[MACSEC_SA_ATTR_SALT]) + return false; + + if (nla_get_u8(attrs[MACSEC_SA_ATTR_AN]) >= MACSEC_NUM_AN) +@@ -2152,8 +2235,18 @@ static int macsec_upd_txsa(struct sk_buff *skb, struct genl_info *info) + } + + if (tb_sa[MACSEC_SA_ATTR_PN]) { ++ int pn_len; ++ ++ pn_len = secy->xpn ? MACSEC_XPN_PN_LEN : MACSEC_DEFAULT_PN_LEN; ++ if (nla_len(tb_sa[MACSEC_SA_ATTR_PN]) != pn_len) { ++ pr_notice("macsec: nl: upd_txsa: bad pn length: %d != %d\n", ++ nla_len(tb_sa[MACSEC_SA_ATTR_PN]), pn_len); ++ rtnl_unlock(); ++ return -EINVAL; ++ } ++ + spin_lock_bh(&tx_sa->lock); +- tx_sa->next_pn_halves.lower = nla_get_u32(tb_sa[MACSEC_SA_ATTR_PN]); ++ tx_sa->next_pn = nla_get_u64(tb_sa[MACSEC_SA_ATTR_PN]); + spin_unlock_bh(&tx_sa->lock); + } + +@@ -2200,8 +2293,18 @@ static int macsec_upd_rxsa(struct sk_buff *skb, struct genl_info *info) + } + + if (tb_sa[MACSEC_SA_ATTR_PN]) { ++ int pn_len; ++ ++ pn_len = secy->xpn ? MACSEC_XPN_PN_LEN : MACSEC_DEFAULT_PN_LEN; ++ if (nla_len(tb_sa[MACSEC_SA_ATTR_PN]) != pn_len) { ++ pr_notice("macsec: nl: upd_rxsa: bad pn length: %d != %d\n", ++ nla_len(tb_sa[MACSEC_SA_ATTR_PN]), pn_len); ++ rtnl_unlock(); ++ return -EINVAL; ++ } ++ + spin_lock_bh(&rx_sa->lock); +- rx_sa->next_pn_halves.lower = nla_get_u32(tb_sa[MACSEC_SA_ATTR_PN]); ++ rx_sa->next_pn = nla_get_u64(tb_sa[MACSEC_SA_ATTR_PN]); + spin_unlock_bh(&rx_sa->lock); + } + +@@ -2467,10 +2570,10 @@ static int nla_put_secy(struct macsec_secy *secy, struct sk_buff *skb) + + switch (secy->key_len) { + case MACSEC_GCM_AES_128_SAK_LEN: +- csid = MACSEC_DEFAULT_CIPHER_ID; ++ csid = secy->xpn ? MACSEC_CIPHER_ID_GCM_AES_XPN_128 : MACSEC_DEFAULT_CIPHER_ID; + break; + case MACSEC_GCM_AES_256_SAK_LEN: +- csid = MACSEC_CIPHER_ID_GCM_AES_256; ++ csid = secy->xpn ? MACSEC_CIPHER_ID_GCM_AES_XPN_256 : MACSEC_CIPHER_ID_GCM_AES_256; + break; + default: + goto cancel; +@@ -2552,6 +2655,8 @@ static int dump_secy(struct macsec_secy *secy, struct net_device *dev, + for (i = 0, j = 1; i < MACSEC_NUM_AN; i++) { + struct macsec_tx_sa *tx_sa = rtnl_dereference(tx_sc->sa[i]); + struct nlattr *txsa_nest; ++ u64 pn; ++ int pn_len; + + if (!tx_sa) + continue; +@@ -2562,9 +2667,18 @@ static int dump_secy(struct macsec_secy *secy, struct net_device *dev, + goto nla_put_failure; + } + ++ if (secy->xpn) { ++ pn = tx_sa->next_pn; ++ pn_len = MACSEC_XPN_PN_LEN; ++ } else { ++ pn = tx_sa->next_pn_halves.lower; ++ pn_len = MACSEC_DEFAULT_PN_LEN; ++ } ++ + if (nla_put_u8(skb, MACSEC_SA_ATTR_AN, i) || +- nla_put_u32(skb, MACSEC_SA_ATTR_PN, tx_sa->next_pn_halves.lower) || ++ nla_put(skb, MACSEC_SA_ATTR_PN, pn_len, &pn) || + nla_put(skb, MACSEC_SA_ATTR_KEYID, MACSEC_KEYID_LEN, tx_sa->key.id) || ++ (secy->xpn && nla_put_ssci(skb, MACSEC_SA_ATTR_SSCI, tx_sa->ssci)) || + nla_put_u8(skb, MACSEC_SA_ATTR_ACTIVE, tx_sa->active)) { + nla_nest_cancel(skb, txsa_nest); + nla_nest_cancel(skb, txsa_list); +@@ -2636,6 +2750,8 @@ static int dump_secy(struct macsec_secy *secy, struct net_device *dev, + for (i = 0, k = 1; i < MACSEC_NUM_AN; i++) { + struct macsec_rx_sa *rx_sa = rtnl_dereference(rx_sc->sa[i]); + struct nlattr *rxsa_nest; ++ u64 pn; ++ int pn_len; + + if (!rx_sa) + continue; +@@ -2664,9 +2780,18 @@ static int dump_secy(struct macsec_secy *secy, struct net_device *dev, + } + nla_nest_end(skb, attr); + ++ if (secy->xpn) { ++ pn = rx_sa->next_pn; ++ pn_len = MACSEC_XPN_PN_LEN; ++ } else { ++ pn = rx_sa->next_pn_halves.lower; ++ pn_len = MACSEC_DEFAULT_PN_LEN; ++ } ++ + if (nla_put_u8(skb, MACSEC_SA_ATTR_AN, i) || +- nla_put_u32(skb, MACSEC_SA_ATTR_PN, rx_sa->next_pn_halves.lower) || ++ nla_put(skb, MACSEC_SA_ATTR_PN, pn_len, &pn) || + nla_put(skb, MACSEC_SA_ATTR_KEYID, MACSEC_KEYID_LEN, rx_sa->key.id) || ++ (secy->xpn && nla_put_ssci(skb, MACSEC_SA_ATTR_SSCI, rx_sa->ssci)) || + nla_put_u8(skb, MACSEC_SA_ATTR_ACTIVE, rx_sa->active)) { + nla_nest_cancel(skb, rxsa_nest); + nla_nest_cancel(skb, rxsc_nest); +@@ -3173,9 +3298,19 @@ static int macsec_changelink_common(struct net_device *dev, + case MACSEC_CIPHER_ID_GCM_AES_128: + case MACSEC_DEFAULT_CIPHER_ID: + secy->key_len = MACSEC_GCM_AES_128_SAK_LEN; ++ secy->xpn = false; + break; + case MACSEC_CIPHER_ID_GCM_AES_256: + secy->key_len = MACSEC_GCM_AES_256_SAK_LEN; ++ secy->xpn = false; ++ break; ++ case MACSEC_CIPHER_ID_GCM_AES_XPN_128: ++ secy->key_len = MACSEC_GCM_AES_128_SAK_LEN; ++ secy->xpn = true; ++ break; ++ case MACSEC_CIPHER_ID_GCM_AES_XPN_256: ++ secy->key_len = MACSEC_GCM_AES_256_SAK_LEN; ++ secy->xpn = true; + break; + default: + return -EINVAL; +@@ -3314,6 +3449,7 @@ static int macsec_add_dev(struct net_device *dev, sci_t sci, u8 icv_len) + secy->validate_frames = MACSEC_VALIDATE_DEFAULT; + secy->protect_frames = true; + secy->replay_protect = false; ++ secy->xpn = DEFAULT_XPN; + + secy->sci = sci; + secy->tx_sc.active = true; +@@ -3448,6 +3584,8 @@ static int macsec_validate_attr(struct nlattr *tb[], struct nlattr *data[], + switch (csid) { + case MACSEC_CIPHER_ID_GCM_AES_128: + case MACSEC_CIPHER_ID_GCM_AES_256: ++ case MACSEC_CIPHER_ID_GCM_AES_XPN_128: ++ case MACSEC_CIPHER_ID_GCM_AES_XPN_256: + case MACSEC_DEFAULT_CIPHER_ID: + if (icv_len < MACSEC_MIN_ICV_LEN || + icv_len > MACSEC_STD_ICV_LEN) +@@ -3521,10 +3659,10 @@ static int macsec_fill_info(struct sk_buff *skb, + + switch (secy->key_len) { + case MACSEC_GCM_AES_128_SAK_LEN: +- csid = MACSEC_DEFAULT_CIPHER_ID; ++ csid = secy->xpn ? MACSEC_CIPHER_ID_GCM_AES_XPN_128 : MACSEC_DEFAULT_CIPHER_ID; + break; + case MACSEC_GCM_AES_256_SAK_LEN: +- csid = MACSEC_CIPHER_ID_GCM_AES_256; ++ csid = secy->xpn ? MACSEC_CIPHER_ID_GCM_AES_XPN_256 : MACSEC_CIPHER_ID_GCM_AES_256; + break; + default: + goto nla_put_failure; +diff --git a/include/uapi/linux/if_macsec.h b/include/uapi/linux/if_macsec.h +index 98e4d5d7c..df638ba7a 100644 +--- a/include/uapi/linux/if_macsec.h ++++ b/include/uapi/linux/if_macsec.h +@@ -22,9 +22,11 @@ + + #define MACSEC_KEYID_LEN 16 + +-/* cipher IDs as per IEEE802.1AEbn-2011 */ ++/* cipher IDs as per IEEE802.1AE-2018 (Table 14-1) */ + #define MACSEC_CIPHER_ID_GCM_AES_128 0x0080C20001000001ULL + #define MACSEC_CIPHER_ID_GCM_AES_256 0x0080C20001000002ULL ++#define MACSEC_CIPHER_ID_GCM_AES_XPN_128 0x0080C20001000003ULL ++#define MACSEC_CIPHER_ID_GCM_AES_XPN_256 0x0080C20001000004ULL + + /* deprecated cipher ID for GCM-AES-128 */ + #define MACSEC_DEFAULT_CIPHER_ID 0x0080020001000001ULL +@@ -87,11 +89,13 @@ enum macsec_sa_attrs { + MACSEC_SA_ATTR_UNSPEC, + MACSEC_SA_ATTR_AN, /* config/dump, u8 0..3 */ + MACSEC_SA_ATTR_ACTIVE, /* config/dump, u8 0..1 */ +- MACSEC_SA_ATTR_PN, /* config/dump, u32 */ ++ MACSEC_SA_ATTR_PN, /* config/dump, u32/u64 (u64 if XPN) */ + MACSEC_SA_ATTR_KEY, /* config, data */ + MACSEC_SA_ATTR_KEYID, /* config/dump, 128-bit */ + MACSEC_SA_ATTR_STATS, /* dump, nested, macsec_sa_stats_attr */ + MACSEC_SA_ATTR_PAD, ++ MACSEC_SA_ATTR_SSCI, /* config/dump, u32 - XPN only */ ++ MACSEC_SA_ATTR_SALT, /* config, 96-bit - XPN only */ + __MACSEC_SA_ATTR_END, + NUM_MACSEC_SA_ATTR = __MACSEC_SA_ATTR_END, + MACSEC_SA_ATTR_MAX = __MACSEC_SA_ATTR_END - 1, diff --git a/patch/macsec-Support-XPN-frame-handling-IEEE-802.1AEbw.patch b/patch/macsec-Support-XPN-frame-handling-IEEE-802.1AEbw.patch new file mode 100644 index 000000000000..ce1df815ace8 --- /dev/null +++ b/patch/macsec-Support-XPN-frame-handling-IEEE-802.1AEbw.patch @@ -0,0 +1,426 @@ +From a21ecf0e033807b976967286e6c392f48ee2049f Mon Sep 17 00:00:00 2001 + +From: Era Mayflower + +Subject: [PATCH] macsec: Support XPN frame handling - IEEE 802.1AEbw + +Support extended packet number cipher suites (802.1AEbw) frames handling. +This does not include the needed netlink patches. + + * Added xpn boolean field to `struct macsec_secy`. + * Added ssci field to `struct_macsec_tx_sa` (802.1AE figure 10-5). + * Added ssci field to `struct_macsec_rx_sa` (802.1AE figure 10-5). + * Added salt field to `struct macsec_key` (802.1AE 10.7 NOTE 1). + * Created pn_t type for easy access to lower and upper halves. + * Created salt_t type for easy access to the "ssci" and "pn" parts. + * Created `macsec_fill_iv_xpn` function to create IV in XPN mode. + * Support in PN recovery and preliminary replay check in XPN mode. + +In addition, according to IEEE 802.1AEbw figure 10-5, the PN of incoming +frame can be 0 when XPN cipher suite is used, so fixed the function +`macsec_validate_skb` to fail on PN=0 only if XPN is off. + +Signed-off-by: Era Mayflower +Signed-off-by: David S. Miller +--- + drivers/net/macsec.c | 157 ++++++++++++++++++++++++++++++++++++++++---------- + 1 file changed, 125 insertions(+), 32 deletions(-) + +diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c +index df7d6de7c..a41a6cd78 100644 +--- a/drivers/net/macsec.c ++++ b/drivers/net/macsec.c +@@ -21,10 +21,38 @@ + #include + #include + #include ++#include + + #include + ++#define MACSEC_SALT_LEN 12 ++#define MACSEC_NUM_AN 4 /* 2 bits for the association number */ ++ + typedef u64 __bitwise sci_t; ++typedef u32 __bitwise ssci_t; ++ ++typedef union salt { ++ struct { ++ u32 ssci; ++ u64 pn; ++ } __packed; ++ u8 bytes[MACSEC_SALT_LEN]; ++} __packed salt_t; ++ ++typedef union pn { ++ struct { ++#if defined(__LITTLE_ENDIAN_BITFIELD) ++ u32 lower; ++ u32 upper; ++#elif defined(__BIG_ENDIAN_BITFIELD) ++ u32 upper; ++ u32 lower; ++#else ++#error "Please fix " ++#endif ++ }; ++ u64 full64; ++} pn_t; + + #define MACSEC_SCI_LEN 8 + +@@ -63,7 +91,6 @@ struct macsec_eth_header { + #define GCM_AES_IV_LEN 12 + #define DEFAULT_ICV_LEN 16 + +-#define MACSEC_NUM_AN 4 /* 2 bits for the association number */ + + #define for_each_rxsc(secy, sc) \ + for (sc = rcu_dereference_bh(secy->rx_sc); \ +@@ -74,6 +101,16 @@ struct macsec_eth_header { + sc; \ + sc = rtnl_dereference(sc->next)) + ++#define pn_same_half(pn1, pn2) (!(((pn1) >> 31) ^ ((pn2) >> 31))) ++ ++struct gcm_iv_xpn { ++ union { ++ u8 short_secure_channel_id[4]; ++ ssci_t ssci; ++ }; ++ __be64 pn; ++} __packed; ++ + struct gcm_iv { + union { + u8 secure_channel_id[8]; +@@ -86,10 +123,12 @@ struct gcm_iv { + * struct macsec_key - SA key + * @id: user-provided key identifier + * @tfm: crypto struct, key storage ++ * @salt: salt used to generate IV in XPN cipher suites + */ + struct macsec_key { + u8 id[MACSEC_KEYID_LEN]; + struct crypto_aead *tfm; ++ salt_t salt; + }; + + struct macsec_rx_sc_stats { +@@ -142,12 +181,17 @@ struct macsec_dev_stats { + * @next_pn: packet number expected for the next packet + * @lock: protects next_pn manipulations + * @key: key structure ++ * @ssci: short secure channel identifier + * @stats: per-SA stats + */ + struct macsec_rx_sa { + struct macsec_key key; ++ ssci_t ssci; + spinlock_t lock; +- u32 next_pn; ++ union { ++ pn_t next_pn_halves; ++ u64 next_pn; ++ }; + refcount_t refcnt; + bool active; + struct macsec_rx_sa_stats __percpu *stats; +@@ -183,12 +227,17 @@ struct macsec_rx_sc { + * @next_pn: packet number to use for the next packet + * @lock: protects next_pn manipulations + * @key: key structure ++ * @ssci: short secure channel identifier + * @stats: per-SA stats + */ + struct macsec_tx_sa { + struct macsec_key key; ++ ssci_t ssci; + spinlock_t lock; +- u32 next_pn; ++ union { ++ pn_t next_pn_halves; ++ u64 next_pn; ++ }; + refcount_t refcnt; + bool active; + struct macsec_tx_sa_stats __percpu *stats; +@@ -232,6 +281,7 @@ struct macsec_tx_sc { + * @key_len: length of keys used by the cipher suite + * @icv_len: length of ICV used by the cipher suite + * @validate_frames: validation mode ++ * @xpn: enable XPN for this SecY + * @operational: MAC_Operational flag + * @protect_frames: enable protection for this SecY + * @replay_protect: enable packet number checks on receive +@@ -246,6 +296,7 @@ struct macsec_secy { + u16 key_len; + u16 icv_len; + enum macsec_validation_type validate_frames; ++ bool xpn; + bool operational; + bool protect_frames; + bool replay_protect; +@@ -487,7 +538,7 @@ static void macsec_set_shortlen(struct macsec_eth_header *h, size_t data_len) + } + + /* validate MACsec packet according to IEEE 802.1AE-2006 9.12 */ +-static bool macsec_validate_skb(struct sk_buff *skb, u16 icv_len) ++static bool macsec_validate_skb(struct sk_buff *skb, u16 icv_len, bool xpn) + { + struct macsec_eth_header *h = (struct macsec_eth_header *)skb->data; + int len = skb->len - 2 * ETH_ALEN; +@@ -512,8 +563,8 @@ static bool macsec_validate_skb(struct sk_buff *skb, u16 icv_len) + if (h->unused) + return false; + +- /* rx.pn != 0 (figure 10-5) */ +- if (!h->packet_number) ++ /* rx.pn != 0 if not XPN (figure 10-5 with 802.11AEbw-2013 amendment) */ ++ if (!h->packet_number && !xpn) + return false; + + /* length check, f) g) h) i) */ +@@ -525,6 +576,15 @@ static bool macsec_validate_skb(struct sk_buff *skb, u16 icv_len) + #define MACSEC_NEEDED_HEADROOM (macsec_extra_len(true)) + #define MACSEC_NEEDED_TAILROOM MACSEC_STD_ICV_LEN + ++static void macsec_fill_iv_xpn(unsigned char *iv, ssci_t ssci, u64 pn, ++ salt_t salt) ++{ ++ struct gcm_iv_xpn *gcm_iv = (struct gcm_iv_xpn *)iv; ++ ++ gcm_iv->ssci = ssci ^ salt.ssci; ++ gcm_iv->pn = cpu_to_be64(pn) ^ salt.pn; ++} ++ + static void macsec_fill_iv(unsigned char *iv, sci_t sci, u32 pn) + { + struct gcm_iv *gcm_iv = (struct gcm_iv *)iv; +@@ -538,14 +598,18 @@ static struct macsec_eth_header *macsec_ethhdr(struct sk_buff *skb) + return (struct macsec_eth_header *)skb_mac_header(skb); + } + +-static u32 tx_sa_update_pn(struct macsec_tx_sa *tx_sa, struct macsec_secy *secy) ++static pn_t tx_sa_update_pn(struct macsec_tx_sa *tx_sa, ++ struct macsec_secy *secy) + { +- u32 pn; ++ pn_t pn; + + spin_lock_bh(&tx_sa->lock); +- pn = tx_sa->next_pn; ++ pn = tx_sa->next_pn_halves; ++ if (secy->xpn) ++ tx_sa->next_pn++; ++ else ++ tx_sa->next_pn_halves.lower++; + +- tx_sa->next_pn++; + if (tx_sa->next_pn == 0) { + pr_debug("PN wrapped, transitioning to !oper\n"); + tx_sa->active = false; +@@ -664,7 +728,7 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb, + struct macsec_tx_sa *tx_sa; + struct macsec_dev *macsec = macsec_priv(dev); + bool sci_present; +- u32 pn; ++ pn_t pn; + + secy = &macsec->secy; + tx_sc = &secy->tx_sc; +@@ -706,12 +770,12 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb, + memmove(hh, eth, 2 * ETH_ALEN); + + pn = tx_sa_update_pn(tx_sa, secy); +- if (pn == 0) { ++ if (pn.full64 == 0) { + macsec_txsa_put(tx_sa); + kfree_skb(skb); + return ERR_PTR(-ENOLINK); + } +- macsec_fill_sectag(hh, secy, pn, sci_present); ++ macsec_fill_sectag(hh, secy, pn.lower, sci_present); + macsec_set_shortlen(hh, unprotected_len - 2 * ETH_ALEN); + + skb_put(skb, secy->icv_len); +@@ -742,7 +806,10 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb, + return ERR_PTR(-ENOMEM); + } + +- macsec_fill_iv(iv, secy->sci, pn); ++ if (secy->xpn) ++ macsec_fill_iv_xpn(iv, tx_sa->ssci, pn.full64, tx_sa->key.salt); ++ else ++ macsec_fill_iv(iv, secy->sci, pn.lower); + + sg_init_table(sg, ret); + ret = skb_to_sgvec(skb, sg, 0, skb->len); +@@ -794,13 +861,14 @@ static bool macsec_post_decrypt(struct sk_buff *skb, struct macsec_secy *secy, u + u32 lowest_pn = 0; + + spin_lock(&rx_sa->lock); +- if (rx_sa->next_pn >= secy->replay_window) +- lowest_pn = rx_sa->next_pn - secy->replay_window; ++ if (rx_sa->next_pn_halves.lower >= secy->replay_window) ++ lowest_pn = rx_sa->next_pn_halves.lower - secy->replay_window; + + /* Now perform replay protection check again + * (see IEEE 802.1AE-2006 figure 10-5) + */ +- if (secy->replay_protect && pn < lowest_pn) { ++ if (secy->replay_protect && pn < lowest_pn && ++ (!secy->xpn || pn_same_half(pn, lowest_pn))) { + spin_unlock(&rx_sa->lock); + u64_stats_update_begin(&rxsc_stats->syncp); + rxsc_stats->stats.InPktsLate++; +@@ -849,8 +917,15 @@ static bool macsec_post_decrypt(struct sk_buff *skb, struct macsec_secy *secy, u + } + u64_stats_update_end(&rxsc_stats->syncp); + +- if (pn >= rx_sa->next_pn) +- rx_sa->next_pn = pn + 1; ++ // Instead of "pn >=" - to support pn overflow in xpn ++ if (pn + 1 > rx_sa->next_pn_halves.lower) { ++ rx_sa->next_pn_halves.lower = pn + 1; ++ } else if (secy->xpn && ++ !pn_same_half(pn, rx_sa->next_pn_halves.lower)) { ++ rx_sa->next_pn_halves.upper++; ++ rx_sa->next_pn_halves.lower = pn + 1; ++ } ++ + spin_unlock(&rx_sa->lock); + } + +@@ -937,6 +1012,7 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb, + unsigned char *iv; + struct aead_request *req; + struct macsec_eth_header *hdr; ++ u32 hdr_pn; + u16 icv_len = secy->icv_len; + + macsec_skb_cb(skb)->valid = false; +@@ -956,7 +1032,21 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb, + } + + hdr = (struct macsec_eth_header *)skb->data; +- macsec_fill_iv(iv, sci, ntohl(hdr->packet_number)); ++ hdr_pn = ntohl(hdr->packet_number); ++ ++ if (secy->xpn) { ++ pn_t recovered_pn = rx_sa->next_pn_halves; ++ ++ recovered_pn.lower = hdr_pn; ++ if (hdr_pn < rx_sa->next_pn_halves.lower && ++ !pn_same_half(hdr_pn, rx_sa->next_pn_halves.lower)) ++ recovered_pn.upper++; ++ ++ macsec_fill_iv_xpn(iv, rx_sa->ssci, recovered_pn.full64, ++ rx_sa->key.salt); ++ } else { ++ macsec_fill_iv(iv, sci, hdr_pn); ++ } + + sg_init_table(sg, ret); + ret = skb_to_sgvec(skb, sg, 0, skb->len); +@@ -1086,7 +1176,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) + struct macsec_rxh_data *rxd; + struct macsec_dev *macsec; + sci_t sci; +- u32 pn; ++ u32 hdr_pn; + bool cbit; + struct pcpu_rx_sc_stats *rxsc_stats; + struct pcpu_secy_stats *secy_stats; +@@ -1160,7 +1250,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) + secy_stats = this_cpu_ptr(macsec->stats); + rxsc_stats = this_cpu_ptr(rx_sc->stats); + +- if (!macsec_validate_skb(skb, secy->icv_len)) { ++ if (!macsec_validate_skb(skb, secy->icv_len, secy->xpn)) { + u64_stats_update_begin(&secy_stats->syncp); + secy_stats->stats.InPktsBadTag++; + u64_stats_update_end(&secy_stats->syncp); +@@ -1192,13 +1282,16 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) + } + + /* First, PN check to avoid decrypting obviously wrong packets */ +- pn = ntohl(hdr->packet_number); ++ hdr_pn = ntohl(hdr->packet_number); + if (secy->replay_protect) { + bool late; + + spin_lock(&rx_sa->lock); +- late = rx_sa->next_pn >= secy->replay_window && +- pn < (rx_sa->next_pn - secy->replay_window); ++ late = rx_sa->next_pn_halves.lower >= secy->replay_window && ++ hdr_pn < (rx_sa->next_pn_halves.lower - secy->replay_window); ++ ++ if (secy->xpn) ++ late = late && pn_same_half(rx_sa->next_pn_halves.lower, hdr_pn); + spin_unlock(&rx_sa->lock); + + if (late) { +@@ -1227,7 +1320,7 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) + return RX_HANDLER_CONSUMED; + } + +- if (!macsec_post_decrypt(skb, secy, pn)) ++ if (!macsec_post_decrypt(skb, secy, hdr_pn)) + goto drop; + + deliver: +@@ -1720,7 +1813,7 @@ static int macsec_add_rxsa(struct sk_buff *skb, struct genl_info *info) + + if (tb_sa[MACSEC_SA_ATTR_PN]) { + spin_lock_bh(&rx_sa->lock); +- rx_sa->next_pn = nla_get_u32(tb_sa[MACSEC_SA_ATTR_PN]); ++ rx_sa->next_pn_halves.lower = nla_get_u32(tb_sa[MACSEC_SA_ATTR_PN]); + spin_unlock_bh(&rx_sa->lock); + } + +@@ -1876,7 +1969,7 @@ static int macsec_add_txsa(struct sk_buff *skb, struct genl_info *info) + nla_memcpy(tx_sa->key.id, tb_sa[MACSEC_SA_ATTR_KEYID], MACSEC_KEYID_LEN); + + spin_lock_bh(&tx_sa->lock); +- tx_sa->next_pn = nla_get_u32(tb_sa[MACSEC_SA_ATTR_PN]); ++ tx_sa->next_pn_halves.lower = nla_get_u32(tb_sa[MACSEC_SA_ATTR_PN]); + spin_unlock_bh(&tx_sa->lock); + + if (tb_sa[MACSEC_SA_ATTR_ACTIVE]) +@@ -2060,7 +2153,7 @@ static int macsec_upd_txsa(struct sk_buff *skb, struct genl_info *info) + + if (tb_sa[MACSEC_SA_ATTR_PN]) { + spin_lock_bh(&tx_sa->lock); +- tx_sa->next_pn = nla_get_u32(tb_sa[MACSEC_SA_ATTR_PN]); ++ tx_sa->next_pn_halves.lower = nla_get_u32(tb_sa[MACSEC_SA_ATTR_PN]); + spin_unlock_bh(&tx_sa->lock); + } + +@@ -2108,7 +2201,7 @@ static int macsec_upd_rxsa(struct sk_buff *skb, struct genl_info *info) + + if (tb_sa[MACSEC_SA_ATTR_PN]) { + spin_lock_bh(&rx_sa->lock); +- rx_sa->next_pn = nla_get_u32(tb_sa[MACSEC_SA_ATTR_PN]); ++ rx_sa->next_pn_halves.lower = nla_get_u32(tb_sa[MACSEC_SA_ATTR_PN]); + spin_unlock_bh(&rx_sa->lock); + } + +@@ -2470,7 +2563,7 @@ static int dump_secy(struct macsec_secy *secy, struct net_device *dev, + } + + if (nla_put_u8(skb, MACSEC_SA_ATTR_AN, i) || +- nla_put_u32(skb, MACSEC_SA_ATTR_PN, tx_sa->next_pn) || ++ nla_put_u32(skb, MACSEC_SA_ATTR_PN, tx_sa->next_pn_halves.lower) || + nla_put(skb, MACSEC_SA_ATTR_KEYID, MACSEC_KEYID_LEN, tx_sa->key.id) || + nla_put_u8(skb, MACSEC_SA_ATTR_ACTIVE, tx_sa->active)) { + nla_nest_cancel(skb, txsa_nest); +@@ -2572,7 +2665,7 @@ static int dump_secy(struct macsec_secy *secy, struct net_device *dev, + nla_nest_end(skb, attr); + + if (nla_put_u8(skb, MACSEC_SA_ATTR_AN, i) || +- nla_put_u32(skb, MACSEC_SA_ATTR_PN, rx_sa->next_pn) || ++ nla_put_u32(skb, MACSEC_SA_ATTR_PN, rx_sa->next_pn_halves.lower) || + nla_put(skb, MACSEC_SA_ATTR_KEYID, MACSEC_KEYID_LEN, rx_sa->key.id) || + nla_put_u8(skb, MACSEC_SA_ATTR_ACTIVE, rx_sa->active)) { + nla_nest_cancel(skb, rxsa_nest); diff --git a/patch/netlink-add-NLA_MIN_LEN.patch b/patch/netlink-add-NLA_MIN_LEN.patch new file mode 100644 index 000000000000..1e637ce163f4 --- /dev/null +++ b/patch/netlink-add-NLA_MIN_LEN.patch @@ -0,0 +1,39 @@ +From 6f455f5f4e9c28aefaefbe18ce7304b499645d75 Mon Sep 17 00:00:00 2001 + +From: Johannes Berg + +Subject: [PATCH] netlink: add NLA_MIN_LEN + +Rather than using NLA_UNSPEC for this type of thing, use NLA_MIN_LEN +so we can make NLA_UNSPEC be NLA_REJECT under certain conditions for +future attributes. + +While at it, also use NLA_EXACT_LEN for the struct example. + +Signed-off-by: Johannes Berg +Signed-off-by: David S. Miller +--- + include/net/netlink.h | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/include/net/netlink.h b/include/net/netlink.h +index 39e1d875d..46c65b7cb 100644 +--- a/include/net/netlink.h ++++ b/include/net/netlink.h +@@ -180,6 +180,7 @@ enum { + NLA_S32, + NLA_S64, + NLA_BITFIELD32, ++ NLA_MIN_LEN, + __NLA_TYPE_MAX, + }; + +@@ -215,7 +216,7 @@ enum { + * static const struct nla_policy my_policy[ATTR_MAX+1] = { + * [ATTR_FOO] = { .type = NLA_U16 }, + * [ATTR_BAR] = { .type = NLA_STRING, .len = BARSIZ }, +- * [ATTR_BAZ] = { .len = sizeof(struct mystruct) }, ++ * [ATTR_BAZ] = { .type = NLA_EXACT_LEN, .len = sizeof(struct mystruct) }, + * [ATTR_GOO] = { .type = NLA_BITFIELD32, .validation_data = &myvalidflags }, + * }; + */ diff --git a/patch/series b/patch/series index ef690f970b2d..132077f7d5ee 100755 --- a/patch/series +++ b/patch/series @@ -36,6 +36,9 @@ e1000-Do-not-perform-reset-in-reset_task-if-we-are-a.patch 0004-dt-bindings-hwmon-Add-missing-documentation-for-lm75.patch 0005-dt-bindings-hwmon-Add-tmp75b-to-lm75.txt.patch 0006-device-tree-bindinds-add-NXP-PCT2075-as-compatible-d.patch +macsec-Support-XPN-frame-handling-IEEE-802.1AEbw.patch +netlink-add-NLA_MIN_LEN.patch +macsec-Netlink-support-of-XPN-cipher-suites-IEEE-802.patch # # (Marvell) # 0042-Marvell-a385-Micron-4G-flash-support.patch