diff options
Diffstat (limited to 'drivers/net/macsec.c')
-rw-r--r-- | drivers/net/macsec.c | 169 |
1 files changed, 124 insertions, 45 deletions
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 8f3c55d03..a70b6c460 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -605,12 +605,41 @@ static void macsec_encrypt_done(struct crypto_async_request *base, int err) dev_put(dev); } +static struct aead_request *macsec_alloc_req(struct crypto_aead *tfm, + unsigned char **iv, + struct scatterlist **sg) +{ + size_t size, iv_offset, sg_offset; + struct aead_request *req; + void *tmp; + + size = sizeof(struct aead_request) + crypto_aead_reqsize(tfm); + iv_offset = size; + size += GCM_AES_IV_LEN; + + size = ALIGN(size, __alignof__(struct scatterlist)); + sg_offset = size; + size += sizeof(struct scatterlist) * (MAX_SKB_FRAGS + 1); + + tmp = kmalloc(size, GFP_ATOMIC); + if (!tmp) + return NULL; + + *iv = (unsigned char *)(tmp + iv_offset); + *sg = (struct scatterlist *)(tmp + sg_offset); + req = tmp; + + aead_request_set_tfm(req, tfm); + + return req; +} + static struct sk_buff *macsec_encrypt(struct sk_buff *skb, struct net_device *dev) { int ret; - struct scatterlist sg[MAX_SKB_FRAGS + 1]; - unsigned char iv[GCM_AES_IV_LEN]; + struct scatterlist *sg; + unsigned char *iv; struct ethhdr *eth; struct macsec_eth_header *hh; size_t unprotected_len; @@ -668,8 +697,6 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb, macsec_fill_sectag(hh, secy, pn); macsec_set_shortlen(hh, unprotected_len - 2 * ETH_ALEN); - macsec_fill_iv(iv, secy->sci, pn); - skb_put(skb, secy->icv_len); if (skb->len - ETH_HLEN > macsec_priv(dev)->real_dev->mtu) { @@ -684,13 +711,15 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb, return ERR_PTR(-EINVAL); } - req = aead_request_alloc(tx_sa->key.tfm, GFP_ATOMIC); + req = macsec_alloc_req(tx_sa->key.tfm, &iv, &sg); if (!req) { macsec_txsa_put(tx_sa); kfree_skb(skb); return ERR_PTR(-ENOMEM); } + macsec_fill_iv(iv, secy->sci, pn); + sg_init_table(sg, MAX_SKB_FRAGS + 1); skb_to_sgvec(skb, sg, 0, skb->len); @@ -861,7 +890,6 @@ static void macsec_decrypt_done(struct crypto_async_request *base, int err) out: macsec_rxsa_put(rx_sa); dev_put(dev); - return; } static struct sk_buff *macsec_decrypt(struct sk_buff *skb, @@ -871,8 +899,8 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb, struct macsec_secy *secy) { int ret; - struct scatterlist sg[MAX_SKB_FRAGS + 1]; - unsigned char iv[GCM_AES_IV_LEN]; + struct scatterlist *sg; + unsigned char *iv; struct aead_request *req; struct macsec_eth_header *hdr; u16 icv_len = secy->icv_len; @@ -882,7 +910,7 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb, if (!skb) return ERR_PTR(-ENOMEM); - req = aead_request_alloc(rx_sa->key.tfm, GFP_ATOMIC); + req = macsec_alloc_req(rx_sa->key.tfm, &iv, &sg); if (!req) { kfree_skb(skb); return ERR_PTR(-ENOMEM); @@ -914,7 +942,6 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb, } macsec_skb_cb(skb)->req = req; - macsec_skb_cb(skb)->rx_sa = rx_sa; skb->dev = dev; aead_request_set_callback(req, 0, macsec_decrypt_done, skb); @@ -1141,6 +1168,8 @@ static rx_handler_result_t macsec_handle_frame(struct sk_buff **pskb) } } + macsec_skb_cb(skb)->rx_sa = rx_sa; + /* Disabled && !changed text => skip validation */ if (hdr->tci_an & MACSEC_TCI_C || secy->validate_frames != MACSEC_VALIDATE_DISABLED) @@ -1234,7 +1263,7 @@ static struct crypto_aead *macsec_alloc_tfm(char *key, int key_len, int icv_len) struct crypto_aead *tfm; int ret; - tfm = crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC); + tfm = crypto_alloc_aead("gcm(aes)", 0, 0); if (!tfm || IS_ERR(tfm)) return NULL; @@ -1408,9 +1437,10 @@ static sci_t nla_get_sci(const struct nlattr *nla) return (__force sci_t)nla_get_u64(nla); } -static int nla_put_sci(struct sk_buff *skb, int attrtype, sci_t value) +static int nla_put_sci(struct sk_buff *skb, int attrtype, sci_t value, + int padattr) { - return nla_put_u64(skb, attrtype, (__force u64)value); + return nla_put_u64_64bit(skb, attrtype, (__force u64)value, padattr); } static struct macsec_tx_sa *get_txsa_from_nl(struct net *net, @@ -2143,16 +2173,36 @@ static int copy_rx_sc_stats(struct sk_buff *skb, sum.InPktsUnusedSA += tmp.InPktsUnusedSA; } - if (nla_put_u64(skb, MACSEC_RXSC_STATS_ATTR_IN_OCTETS_VALIDATED, sum.InOctetsValidated) || - nla_put_u64(skb, MACSEC_RXSC_STATS_ATTR_IN_OCTETS_DECRYPTED, sum.InOctetsDecrypted) || - nla_put_u64(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_UNCHECKED, sum.InPktsUnchecked) || - nla_put_u64(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_DELAYED, sum.InPktsDelayed) || - nla_put_u64(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_OK, sum.InPktsOK) || - nla_put_u64(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_INVALID, sum.InPktsInvalid) || - nla_put_u64(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_LATE, sum.InPktsLate) || - nla_put_u64(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_NOT_VALID, sum.InPktsNotValid) || - nla_put_u64(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_NOT_USING_SA, sum.InPktsNotUsingSA) || - nla_put_u64(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_UNUSED_SA, sum.InPktsUnusedSA)) + if (nla_put_u64_64bit(skb, MACSEC_RXSC_STATS_ATTR_IN_OCTETS_VALIDATED, + sum.InOctetsValidated, + MACSEC_RXSC_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_RXSC_STATS_ATTR_IN_OCTETS_DECRYPTED, + sum.InOctetsDecrypted, + MACSEC_RXSC_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_UNCHECKED, + sum.InPktsUnchecked, + MACSEC_RXSC_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_DELAYED, + sum.InPktsDelayed, + MACSEC_RXSC_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_OK, + sum.InPktsOK, + MACSEC_RXSC_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_INVALID, + sum.InPktsInvalid, + MACSEC_RXSC_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_LATE, + sum.InPktsLate, + MACSEC_RXSC_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_NOT_VALID, + sum.InPktsNotValid, + MACSEC_RXSC_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_NOT_USING_SA, + sum.InPktsNotUsingSA, + MACSEC_RXSC_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_RXSC_STATS_ATTR_IN_PKTS_UNUSED_SA, + sum.InPktsUnusedSA, + MACSEC_RXSC_STATS_ATTR_PAD)) return -EMSGSIZE; return 0; @@ -2181,10 +2231,18 @@ static int copy_tx_sc_stats(struct sk_buff *skb, sum.OutOctetsEncrypted += tmp.OutOctetsEncrypted; } - if (nla_put_u64(skb, MACSEC_TXSC_STATS_ATTR_OUT_PKTS_PROTECTED, sum.OutPktsProtected) || - nla_put_u64(skb, MACSEC_TXSC_STATS_ATTR_OUT_PKTS_ENCRYPTED, sum.OutPktsEncrypted) || - nla_put_u64(skb, MACSEC_TXSC_STATS_ATTR_OUT_OCTETS_PROTECTED, sum.OutOctetsProtected) || - nla_put_u64(skb, MACSEC_TXSC_STATS_ATTR_OUT_OCTETS_ENCRYPTED, sum.OutOctetsEncrypted)) + if (nla_put_u64_64bit(skb, MACSEC_TXSC_STATS_ATTR_OUT_PKTS_PROTECTED, + sum.OutPktsProtected, + MACSEC_TXSC_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_TXSC_STATS_ATTR_OUT_PKTS_ENCRYPTED, + sum.OutPktsEncrypted, + MACSEC_TXSC_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_TXSC_STATS_ATTR_OUT_OCTETS_PROTECTED, + sum.OutOctetsProtected, + MACSEC_TXSC_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_TXSC_STATS_ATTR_OUT_OCTETS_ENCRYPTED, + sum.OutOctetsEncrypted, + MACSEC_TXSC_STATS_ATTR_PAD)) return -EMSGSIZE; return 0; @@ -2217,14 +2275,30 @@ static int copy_secy_stats(struct sk_buff *skb, sum.InPktsOverrun += tmp.InPktsOverrun; } - if (nla_put_u64(skb, MACSEC_SECY_STATS_ATTR_OUT_PKTS_UNTAGGED, sum.OutPktsUntagged) || - nla_put_u64(skb, MACSEC_SECY_STATS_ATTR_IN_PKTS_UNTAGGED, sum.InPktsUntagged) || - nla_put_u64(skb, MACSEC_SECY_STATS_ATTR_OUT_PKTS_TOO_LONG, sum.OutPktsTooLong) || - nla_put_u64(skb, MACSEC_SECY_STATS_ATTR_IN_PKTS_NO_TAG, sum.InPktsNoTag) || - nla_put_u64(skb, MACSEC_SECY_STATS_ATTR_IN_PKTS_BAD_TAG, sum.InPktsBadTag) || - nla_put_u64(skb, MACSEC_SECY_STATS_ATTR_IN_PKTS_UNKNOWN_SCI, sum.InPktsUnknownSCI) || - nla_put_u64(skb, MACSEC_SECY_STATS_ATTR_IN_PKTS_NO_SCI, sum.InPktsNoSCI) || - nla_put_u64(skb, MACSEC_SECY_STATS_ATTR_IN_PKTS_OVERRUN, sum.InPktsOverrun)) + if (nla_put_u64_64bit(skb, MACSEC_SECY_STATS_ATTR_OUT_PKTS_UNTAGGED, + sum.OutPktsUntagged, + MACSEC_SECY_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_SECY_STATS_ATTR_IN_PKTS_UNTAGGED, + sum.InPktsUntagged, + MACSEC_SECY_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_SECY_STATS_ATTR_OUT_PKTS_TOO_LONG, + sum.OutPktsTooLong, + MACSEC_SECY_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_SECY_STATS_ATTR_IN_PKTS_NO_TAG, + sum.InPktsNoTag, + MACSEC_SECY_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_SECY_STATS_ATTR_IN_PKTS_BAD_TAG, + sum.InPktsBadTag, + MACSEC_SECY_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_SECY_STATS_ATTR_IN_PKTS_UNKNOWN_SCI, + sum.InPktsUnknownSCI, + MACSEC_SECY_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_SECY_STATS_ATTR_IN_PKTS_NO_SCI, + sum.InPktsNoSCI, + MACSEC_SECY_STATS_ATTR_PAD) || + nla_put_u64_64bit(skb, MACSEC_SECY_STATS_ATTR_IN_PKTS_OVERRUN, + sum.InPktsOverrun, + MACSEC_SECY_STATS_ATTR_PAD)) return -EMSGSIZE; return 0; @@ -2238,9 +2312,11 @@ static int nla_put_secy(struct macsec_secy *secy, struct sk_buff *skb) if (!secy_nest) return 1; - if (nla_put_sci(skb, MACSEC_SECY_ATTR_SCI, secy->sci) || - nla_put_u64(skb, MACSEC_SECY_ATTR_CIPHER_SUITE, - MACSEC_DEFAULT_CIPHER_ID) || + 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) || 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) || @@ -2366,7 +2442,8 @@ static int dump_secy(struct macsec_secy *secy, struct net_device *dev, } if (nla_put_u8(skb, MACSEC_RXSC_ATTR_ACTIVE, rx_sc->active) || - nla_put_sci(skb, MACSEC_RXSC_ATTR_SCI, rx_sc->sci)) { + nla_put_sci(skb, MACSEC_RXSC_ATTR_SCI, rx_sc->sci, + MACSEC_RXSC_ATTR_PAD)) { nla_nest_cancel(skb, rxsc_nest); nla_nest_cancel(skb, rxsc_list); goto nla_put_failure; @@ -2844,7 +2921,7 @@ static void macsec_free_netdev(struct net_device *dev) static void macsec_setup(struct net_device *dev) { ether_setup(dev); - dev->tx_queue_len = 0; + dev->priv_flags |= IFF_NO_QUEUE; dev->netdev_ops = &macsec_netdev_ops; dev->destructor = macsec_free_netdev; @@ -3171,9 +3248,9 @@ static struct net *macsec_get_link_net(const struct net_device *dev) static size_t macsec_get_size(const struct net_device *dev) { return 0 + - nla_total_size(8) + /* SCI */ + nla_total_size_64bit(8) + /* SCI */ nla_total_size(1) + /* ICV_LEN */ - nla_total_size(8) + /* CIPHER_SUITE */ + nla_total_size_64bit(8) + /* CIPHER_SUITE */ nla_total_size(4) + /* WINDOW */ nla_total_size(1) + /* ENCODING_SA */ nla_total_size(1) + /* ENCRYPT */ @@ -3192,10 +3269,11 @@ 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; - if (nla_put_sci(skb, IFLA_MACSEC_SCI, secy->sci) || + 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(skb, IFLA_MACSEC_CIPHER_SUITE, - MACSEC_DEFAULT_CIPHER_ID) || + nla_put_u64_64bit(skb, IFLA_MACSEC_CIPHER_SUITE, + MACSEC_DEFAULT_CIPHER_ID, 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) || @@ -3313,6 +3391,7 @@ static void __exit macsec_exit(void) genl_unregister_family(&macsec_fam); rtnl_link_unregister(&macsec_link_ops); unregister_netdevice_notifier(&macsec_notifier); + rcu_barrier(); } module_init(macsec_init); |