|
@@ -510,7 +510,7 @@ 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_MAX_ICV_LEN
|
|
|
+#define MACSEC_NEEDED_TAILROOM MACSEC_STD_ICV_LEN
|
|
|
|
|
|
static void macsec_fill_iv(unsigned char *iv, sci_t sci, u32 pn)
|
|
|
{
|
|
@@ -1270,22 +1270,22 @@ static struct crypto_aead *macsec_alloc_tfm(char *key, int key_len, int icv_len)
|
|
|
int ret;
|
|
|
|
|
|
tfm = crypto_alloc_aead("gcm(aes)", 0, 0);
|
|
|
- if (!tfm || IS_ERR(tfm))
|
|
|
- return NULL;
|
|
|
+
|
|
|
+ if (IS_ERR(tfm))
|
|
|
+ return tfm;
|
|
|
|
|
|
ret = crypto_aead_setkey(tfm, key, key_len);
|
|
|
- if (ret < 0) {
|
|
|
- crypto_free_aead(tfm);
|
|
|
- return NULL;
|
|
|
- }
|
|
|
+ if (ret < 0)
|
|
|
+ goto fail;
|
|
|
|
|
|
ret = crypto_aead_setauthsize(tfm, icv_len);
|
|
|
- if (ret < 0) {
|
|
|
- crypto_free_aead(tfm);
|
|
|
- return NULL;
|
|
|
- }
|
|
|
+ if (ret < 0)
|
|
|
+ goto fail;
|
|
|
|
|
|
return tfm;
|
|
|
+fail:
|
|
|
+ crypto_free_aead(tfm);
|
|
|
+ return ERR_PTR(ret);
|
|
|
}
|
|
|
|
|
|
static int init_rx_sa(struct macsec_rx_sa *rx_sa, char *sak, int key_len,
|
|
@@ -1293,12 +1293,12 @@ static int init_rx_sa(struct macsec_rx_sa *rx_sa, char *sak, int key_len,
|
|
|
{
|
|
|
rx_sa->stats = alloc_percpu(struct macsec_rx_sa_stats);
|
|
|
if (!rx_sa->stats)
|
|
|
- return -1;
|
|
|
+ return -ENOMEM;
|
|
|
|
|
|
rx_sa->key.tfm = macsec_alloc_tfm(sak, key_len, icv_len);
|
|
|
- if (!rx_sa->key.tfm) {
|
|
|
+ if (IS_ERR(rx_sa->key.tfm)) {
|
|
|
free_percpu(rx_sa->stats);
|
|
|
- return -1;
|
|
|
+ return PTR_ERR(rx_sa->key.tfm);
|
|
|
}
|
|
|
|
|
|
rx_sa->active = false;
|
|
@@ -1391,12 +1391,12 @@ static int init_tx_sa(struct macsec_tx_sa *tx_sa, char *sak, int key_len,
|
|
|
{
|
|
|
tx_sa->stats = alloc_percpu(struct macsec_tx_sa_stats);
|
|
|
if (!tx_sa->stats)
|
|
|
- return -1;
|
|
|
+ return -ENOMEM;
|
|
|
|
|
|
tx_sa->key.tfm = macsec_alloc_tfm(sak, key_len, icv_len);
|
|
|
- if (!tx_sa->key.tfm) {
|
|
|
+ if (IS_ERR(tx_sa->key.tfm)) {
|
|
|
free_percpu(tx_sa->stats);
|
|
|
- return -1;
|
|
|
+ return PTR_ERR(tx_sa->key.tfm);
|
|
|
}
|
|
|
|
|
|
tx_sa->active = false;
|
|
@@ -1629,6 +1629,7 @@ static int macsec_add_rxsa(struct sk_buff *skb, struct genl_info *info)
|
|
|
unsigned char assoc_num;
|
|
|
struct nlattr *tb_rxsc[MACSEC_RXSC_ATTR_MAX + 1];
|
|
|
struct nlattr *tb_sa[MACSEC_SA_ATTR_MAX + 1];
|
|
|
+ int err;
|
|
|
|
|
|
if (!attrs[MACSEC_ATTR_IFINDEX])
|
|
|
return -EINVAL;
|
|
@@ -1665,13 +1666,19 @@ static int macsec_add_rxsa(struct sk_buff *skb, struct genl_info *info)
|
|
|
}
|
|
|
|
|
|
rx_sa = kmalloc(sizeof(*rx_sa), GFP_KERNEL);
|
|
|
- if (!rx_sa || init_rx_sa(rx_sa, nla_data(tb_sa[MACSEC_SA_ATTR_KEY]),
|
|
|
- secy->key_len, secy->icv_len)) {
|
|
|
- kfree(rx_sa);
|
|
|
+ if (!rx_sa) {
|
|
|
rtnl_unlock();
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
+ err = init_rx_sa(rx_sa, nla_data(tb_sa[MACSEC_SA_ATTR_KEY]),
|
|
|
+ secy->key_len, secy->icv_len);
|
|
|
+ if (err < 0) {
|
|
|
+ kfree(rx_sa);
|
|
|
+ rtnl_unlock();
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+
|
|
|
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]);
|
|
@@ -1777,6 +1784,7 @@ static int macsec_add_txsa(struct sk_buff *skb, struct genl_info *info)
|
|
|
struct macsec_tx_sa *tx_sa;
|
|
|
unsigned char assoc_num;
|
|
|
struct nlattr *tb_sa[MACSEC_SA_ATTR_MAX + 1];
|
|
|
+ int err;
|
|
|
|
|
|
if (!attrs[MACSEC_ATTR_IFINDEX])
|
|
|
return -EINVAL;
|
|
@@ -1813,13 +1821,19 @@ static int macsec_add_txsa(struct sk_buff *skb, struct genl_info *info)
|
|
|
}
|
|
|
|
|
|
tx_sa = kmalloc(sizeof(*tx_sa), GFP_KERNEL);
|
|
|
- if (!tx_sa || init_tx_sa(tx_sa, nla_data(tb_sa[MACSEC_SA_ATTR_KEY]),
|
|
|
- secy->key_len, secy->icv_len)) {
|
|
|
- kfree(tx_sa);
|
|
|
+ if (!tx_sa) {
|
|
|
rtnl_unlock();
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
+ err = init_tx_sa(tx_sa, nla_data(tb_sa[MACSEC_SA_ATTR_KEY]),
|
|
|
+ secy->key_len, secy->icv_len);
|
|
|
+ if (err < 0) {
|
|
|
+ kfree(tx_sa);
|
|
|
+ rtnl_unlock();
|
|
|
+ return err;
|
|
|
+ }
|
|
|
+
|
|
|
nla_memcpy(tx_sa->key.id, tb_sa[MACSEC_SA_ATTR_KEYID], MACSEC_KEYID_LEN);
|
|
|
|
|
|
spin_lock_bh(&tx_sa->lock);
|
|
@@ -3210,14 +3224,26 @@ static int macsec_validate_attr(struct nlattr *tb[], struct nlattr *data[])
|
|
|
if (data[IFLA_MACSEC_CIPHER_SUITE])
|
|
|
csid = nla_get_u64(data[IFLA_MACSEC_CIPHER_SUITE]);
|
|
|
|
|
|
- if (data[IFLA_MACSEC_ICV_LEN])
|
|
|
+ if (data[IFLA_MACSEC_ICV_LEN]) {
|
|
|
icv_len = nla_get_u8(data[IFLA_MACSEC_ICV_LEN]);
|
|
|
+ if (icv_len != DEFAULT_ICV_LEN) {
|
|
|
+ char dummy_key[DEFAULT_SAK_LEN] = { 0 };
|
|
|
+ struct crypto_aead *dummy_tfm;
|
|
|
+
|
|
|
+ dummy_tfm = macsec_alloc_tfm(dummy_key,
|
|
|
+ DEFAULT_SAK_LEN,
|
|
|
+ icv_len);
|
|
|
+ if (IS_ERR(dummy_tfm))
|
|
|
+ return PTR_ERR(dummy_tfm);
|
|
|
+ crypto_free_aead(dummy_tfm);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
switch (csid) {
|
|
|
case MACSEC_DEFAULT_CIPHER_ID:
|
|
|
case MACSEC_DEFAULT_CIPHER_ALT:
|
|
|
if (icv_len < MACSEC_MIN_ICV_LEN ||
|
|
|
- icv_len > MACSEC_MAX_ICV_LEN)
|
|
|
+ icv_len > MACSEC_STD_ICV_LEN)
|
|
|
return -EINVAL;
|
|
|
break;
|
|
|
default:
|