macsec: fix SA initialization
[cascardo/linux.git] / drivers / net / macsec.c
index 92eaab9..0e7eff7 100644 (file)
@@ -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);
@@ -1234,7 +1262,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 +1436,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,
@@ -1645,7 +1674,7 @@ static int macsec_add_rxsa(struct sk_buff *skb, struct genl_info *info)
        if (tb_sa[MACSEC_SA_ATTR_ACTIVE])
                rx_sa->active = !!nla_get_u8(tb_sa[MACSEC_SA_ATTR_ACTIVE]);
 
-       nla_memcpy(rx_sa->key.id, tb_sa[MACSEC_SA_ATTR_KEY], MACSEC_KEYID_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);
 
@@ -1784,7 +1813,7 @@ static int macsec_add_txsa(struct sk_buff *skb, struct genl_info *info)
                return -ENOMEM;
        }
 
-       nla_memcpy(tx_sa->key.id, tb_sa[MACSEC_SA_ATTR_KEY], MACSEC_KEYID_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 = nla_get_u32(tb_sa[MACSEC_SA_ATTR_PN]);
@@ -2143,16 +2172,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 +2230,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 +2274,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 +2311,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 +2441,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;
@@ -2843,7 +2919,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;
 
@@ -3170,9 +3246,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 */
@@ -3191,10 +3267,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) ||
@@ -3312,6 +3389,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);