History

mac80211: allow drivers to control software crypto

Some drivers unfortunately cannot support software crypto, but mac80211 currently assumes that they do. This has the issue that if the hardware enabling fails for some reason, the software fallback is used, which won't work. This clearly isn't desirable, the error should be reported and the key setting refused. Support this in mac80211 by allowing drivers to set a new HW flag IEEE80211_HW_SW_CRYPTO_CONTROL, in which case mac80211 will only allow software fallback if the set_key() method returns 1. The driver will also need to advertise supported cipher suites so that mac80211 doesn't advertise any (future) software ciphers that the driver can't actually do. While at it, to make it easier to support this, refactor the ieee80211_init_cipher_suites() code.

Johannes Berg committed 11 years ago

Commit fa7e1fb1 parent 54330bf3 files · +58 −29Browse files

Unified · Split

3 files
  1. include/net/mac80211.h +12 −0
  2. net/mac80211/key.c +7 −3
  3. net/mac80211/main.c +39 −26
include/net/mac80211.h+12−0
@@ -1634,6 +1634,12 @@ struct ieee80211_tx_control { · 1633 unmodified lines
16341634 * be created. It is expected user-space will create vifs as
16351635 * desired (and thus have them named as desired).
16361636 *
1637+ * @IEEE80211_HW_SW_CRYPTO_CONTROL: The driver wants to control which of the
1638+ * crypto algorithms can be done in software - so don't automatically
1639+ * try to fall back to it if hardware crypto fails, but do so only if
1640+ * the driver returns 1. This also forces the driver to advertise its
1641+ * supported cipher suites.
1642+ *
16371643 * @IEEE80211_HW_QUEUE_CONTROL: The driver wants to control per-interface
16381644 * queue mapping in order to use different queues (not just one per AC)
16391645 * for different virtual interfaces. See the doc section on HW queue
@@ -1681,6 +1687,7 @@ enum ieee80211_hw_flags { · 41 unmodified lines
16811687 IEEE80211_HW_MFP_CAPABLE = 1<<13,
16821688 IEEE80211_HW_WANT_MONITOR_VIF = 1<<14,
16831689 IEEE80211_HW_NO_AUTO_VIF = 1<<15,
1690+ IEEE80211_HW_SW_CRYPTO_CONTROL = 1<<16,
16841691 /* free slots */
16851692 IEEE80211_HW_REPORTS_TX_ACK_STATUS = 1<<18,
16861693 IEEE80211_HW_CONNECTION_MONITOR = 1<<19,
@@ -1955,6 +1962,11 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb); · 268 unmodified lines
19551962 * added; if you return 0 then hw_key_idx must be assigned to the
19561963 * hardware key index, you are free to use the full u8 range.
19571964 *
1965+ * Note that in the case that the @IEEE80211_HW_SW_CRYPTO_CONTROL flag is
1966+ * set, mac80211 will not automatically fall back to software crypto if
1967+ * enabling hardware crypto failed. The set_key() call may also return the
1968+ * value 1 to permit this specific key/algorithm to be done in software.
1969+ *
19581970 * When the cmd is %DISABLE_KEY then it must succeed.
19591971 *
19601972 * Note that it is permissible to not decrypt a frame even if a key
net/mac80211/key.c+7−3
@@ -90,7 +90,7 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) · 89 unmodified lines
9090 {
9191 struct ieee80211_sub_if_data *sdata;
9292 struct sta_info *sta;
93− int ret;
93+ int ret = -EOPNOTSUPP;
9494
9595 might_sleep();
9696
@@ -150,7 +150,7 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) · 53 unmodified lines
150150 return 0;
151151 }
152152
153− if (ret != -ENOSPC && ret != -EOPNOTSUPP)
153+ if (ret != -ENOSPC && ret != -EOPNOTSUPP && ret != 1)
154154 sdata_err(sdata,
155155 "failed to set key (%d, %pM) to hardware (%d)\n",
156156 key->conf.keyidx,
@@ -163,7 +163,11 @@ static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key) · 6 unmodified lines
163163 case WLAN_CIPHER_SUITE_TKIP:
164164 case WLAN_CIPHER_SUITE_CCMP:
165165 case WLAN_CIPHER_SUITE_AES_CMAC:
166− /* all of these we can do in software */
166+ /* all of these we can do in software - if driver can */
167+ if (ret == 1)
168+ return 0;
169+ if (key->local->hw.flags & IEEE80211_HW_SW_CRYPTO_CONTROL)
170+ return -EINVAL;
167171 return 0;
168172 default:
169173 return -EINVAL;
net/mac80211/main.c+39−26
@@ -658,7 +658,6 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local) · 657 unmodified lines
658658 bool have_wep = !(IS_ERR(local->wep_tx_tfm) ||
659659 IS_ERR(local->wep_rx_tfm));
660660 bool have_mfp = local->hw.flags & IEEE80211_HW_MFP_CAPABLE;
661− const struct ieee80211_cipher_scheme *cs = local->hw.cipher_schemes;
662661 int n_suites = 0, r = 0, w = 0;
663662 u32 *suites;
664663 static const u32 cipher_suites[] = {
@@ -672,12 +671,38 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local) · 7 unmodified lines
672671 WLAN_CIPHER_SUITE_AES_CMAC
673672 };
674673
675− /* Driver specifies the ciphers, we have nothing to do... */
676− if (local->hw.wiphy->cipher_suites && have_wep)
677− return 0;
674+ if (local->hw.flags & IEEE80211_HW_SW_CRYPTO_CONTROL ||
675+ local->hw.wiphy->cipher_suites) {
676+ /* If the driver advertises, or doesn't support SW crypto,
677+ * we only need to remove WEP if necessary.
678+ */
679+ if (have_wep)
680+ return 0;
681+
682+ /* well if it has _no_ ciphers ... fine */
683+ if (!local->hw.wiphy->n_cipher_suites)
684+ return 0;
685+
686+ /* Driver provides cipher suites, but we need to exclude WEP */
687+ suites = kmemdup(local->hw.wiphy->cipher_suites,
688+ sizeof(u32) * local->hw.wiphy->n_cipher_suites,
689+ GFP_KERNEL);
690+ if (!suites)
691+ return -ENOMEM;
678692
679− /* Set up cipher suites if driver relies on mac80211 cipher defs */
680− if (!local->hw.wiphy->cipher_suites && !cs) {
693+ for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) {
694+ u32 suite = local->hw.wiphy->cipher_suites[r];
695+
696+ if (suite == WLAN_CIPHER_SUITE_WEP40 ||
697+ suite == WLAN_CIPHER_SUITE_WEP104)
698+ continue;
699+ suites[w++] = suite;
700+ }
701+ } else if (!local->hw.cipher_schemes) {
702+ /* If the driver doesn't have cipher schemes, there's nothing
703+ * else to do other than assign the (software supported and
704+ * perhaps offloaded) cipher suites.
705+ */
681706 local->hw.wiphy->cipher_suites = cipher_suites;
682707 local->hw.wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
683708
@@ -689,12 +714,16 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local) · 5 unmodified lines
689714 local->hw.wiphy->n_cipher_suites -= 2;
690715 }
691716
717+ /* not dynamically allocated, so just return */
692718 return 0;
693− }
719+ } else {
720+ const struct ieee80211_cipher_scheme *cs;
694721
695− if (!local->hw.wiphy->cipher_suites) {
696− /*
697− * Driver specifies cipher schemes only
722+ cs = local->hw.cipher_schemes;
723+
724+ /* Driver specifies cipher schemes only (but not cipher suites
725+ * including the schemes)
726+ *
698727 * We start counting ciphers defined by schemes, TKIP and CCMP
699728 */
700729 n_suites = local->hw.n_cipher_schemes + 2;
@@ -724,22 +753,6 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local) · 23 unmodified lines
724753
725754 for (r = 0; r < local->hw.n_cipher_schemes; r++)
726755 suites[w++] = cs[r].cipher;
727− } else {
728− /* Driver provides cipher suites, but we need to exclude WEP */
729− suites = kmemdup(local->hw.wiphy->cipher_suites,
730− sizeof(u32) * local->hw.wiphy->n_cipher_suites,
731− GFP_KERNEL);
732− if (!suites)
733− return -ENOMEM;
734−
735− for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) {
736− u32 suite = local->hw.wiphy->cipher_suites[r];
737−
738− if (suite == WLAN_CIPHER_SUITE_WEP40 ||
739− suite == WLAN_CIPHER_SUITE_WEP104)
740− continue;
741− suites[w++] = suite;
742− }
743756 }
744757
745758 local->hw.wiphy->cipher_suites = suites;