00001
00012 #include "vif_mgmt.h"
00013 #include "mac_ie.h"
00014 #include "mfp.h"
00015 #include "mfp_bip.h"
00016
00017 #if NX_MFP
00018
00037 static bool mfp_is_group_addressed_privacy(uint16_t frame_cntl, uint8_t action)
00038 {
00039 return (((frame_cntl & MAC_FCTRL_TYPE_MASK) == MAC_FCTRL_MGT_T) &&
00040 ((frame_cntl & MAC_FCTRL_SUBT_MASK) == MAC_FCTRL_ACTION_ST) &&
00041 ((action == MAC_MESH_ACTION_CATEGORY) ||
00042 (action == MAC_MULTIHOP_ACTION_CATEGORY)));
00043 }
00044
00058 static bool mfp_check_mmic_ie(uint32_t frame, uint16_t length,
00059 uint16_t machdr_len, struct vif_info_tag *vif,
00060 struct sta_info_tag *sta)
00061 {
00062 struct key_info_tag *key;
00063 uint16_t key_id, i;
00064 uint64_t pn;
00065 uint64_t mic, mic_check;
00066 uint32_t mmic_ie;
00067
00068 if (length < machdr_len + 2 + MAC_MGMT_MIC_LEN)
00069 {
00070 return false;
00071 }
00072
00073 mmic_ie = mac_ie_mgmt_mic_find(frame + machdr_len + 2, length - machdr_len - 2);
00074
00075 if (mmic_ie == 0)
00076 {
00077 return false;
00078 }
00079
00080 key_id = co_read16p(mmic_ie + MAC_MGMT_MIC_KEYID_OFT);
00081 pn = co_read64p(mmic_ie + MAC_MGMT_MIC_IPN_OFT) & 0xffffff;
00082 mic = co_read64p(mmic_ie + MAC_MGMT_MIC_MIC_OFT);
00083
00084 if (key_id != 4 && key_id != 5)
00085 {
00086 return false;
00087 }
00088
00089 #if (RW_MESH_EN)
00090 if (vif->type == VIF_MESH_POINT)
00091 {
00092 key = &sta->sta_sec_info.key_mfp_mesh_info[key_id - MAC_DEFAULT_KEY_COUNT];
00093 }
00094 else
00095 #endif //(RW_MESH_EN)
00096 {
00097 key = &vif->key_info[key_id];
00098 }
00099
00100 if (!key->valid)
00101 {
00102 return false;
00103 }
00104
00105 if (pn <= key->rx_pn[0])
00106 {
00107 return false;
00108 }
00109
00110 key->rx_pn[0] = pn;
00111
00112
00113 for (i = 0; i < MAC_MGMT_MIC_MIC_LEN; i++)
00114 {
00115 co_write8p(mmic_ie + MAC_MGMT_MIC_MIC_OFT + i, 0);
00116 }
00117
00118 mic_check = mfp_compute_bip(key, frame, length - MAC_MGMT_MIC_LEN, machdr_len, 0);
00119 if (mic_check != mic)
00120 {
00121 return false;
00122 }
00123
00124 return true;
00125 }
00126
00127
00128
00129
00130
00131 bool mfp_is_robust_frame(uint16_t frame_cntl, uint8_t action)
00132 {
00133 if ((frame_cntl & MAC_FCTRL_TYPE_MASK) != MAC_FCTRL_MGT_T)
00134 return false;
00135
00136 switch (frame_cntl & MAC_FCTRL_SUBT_MASK) {
00137 case MAC_FCTRL_DEAUTHENT_ST:
00138 case MAC_FCTRL_DISASSOC_ST:
00139 return true;
00140 case MAC_FCTRL_ACTION_ST:
00141 switch (action) {
00142 case MAC_PUBLIC_ACTION_CATEGORY:
00143 case MAC_HT_ACTION_CATEGORY:
00144 case MAC_UNPROT_WNM_ACTION_CATEGORY:
00145 case MAC_SELF_PROT_ACTION_CATEGORY:
00146 case MAC_VENDOR_ACTION_CATEGORY:
00147 return false;
00148 default:
00149 return true;
00150 }
00151 default :
00152 return false;
00153 }
00154 }
00155
00156 bool mfp_ignore_mgmt_frame(struct rx_cntrl_rx_status *rx_status, uint32_t *frame,
00157 uint16_t frmlen, bool *upload)
00158 {
00159 struct vif_info_tag *vif;
00160 struct sta_info_tag *sta;
00161 uint8_t action;
00162
00163
00164 action = co_read8p((uint32_t)(CPU2HW(frame) + rx_status->machdr_len));
00165 if (!mfp_is_robust_frame(rx_status->frame_cntl, action))
00166 {
00167 return false;
00168 }
00169
00170
00171 if ((rx_status->sta_idx == INVALID_STA_IDX) ||
00172 (rx_status->vif_idx == INVALID_VIF_IDX))
00173 {
00174 *upload = false;
00175 return true;
00176 }
00177
00178 vif = &vif_info_tab[rx_status->vif_idx];
00179 sta = &sta_info_tab[rx_status->sta_idx];
00180
00181
00182
00183
00184
00185
00186
00187 if (! vif->default_key)
00188 {
00189 return false;
00190 }
00191
00192 if (rx_status->frame_info & RXU_CNTRL_GROUP_ADDRESSED)
00193 {
00194 if (mfp_is_group_addressed_privacy(rx_status->frame_cntl, action))
00195 {
00196
00197 return !(rx_status->frame_cntl & MAC_FCTRL_PROTECTEDFRAME);
00198 }
00199 else if (!vif->default_mgmt_key)
00200 {
00201
00202 return false;
00203 }
00204 else if (mfp_check_mmic_ie(CPU2HW(frame), frmlen, rx_status->machdr_len, vif, sta))
00205 {
00206
00207 return false;
00208 }
00209 else
00210 {
00211 *upload = false;
00212 return true;
00213 }
00214 }
00215 else if (!STA_CAPA(sta, MFP) ||
00216 (rx_status->frame_cntl & MAC_FCTRL_PROTECTEDFRAME))
00217 {
00218 return false;
00219 }
00220 else
00221 {
00222
00223 if ((MAC_FCTRL_IS(rx_status->frame_cntl, DEAUTHENT) ||
00224 MAC_FCTRL_IS(rx_status->frame_cntl, DISASSOC)) &&
00225 (action == MAC_RS_CLASS_2_FORBIDDEN ||
00226 action == MAC_RS_CLASS_3_FORBIDDEN))
00227 {
00228
00229 *upload = true;
00230 }
00231 else
00232 {
00233 *upload = false;
00234 }
00235 }
00236
00237 return true;
00238 }
00239
00240 enum mfp_protection mfp_protect_mgmt_frame(struct txdesc *txdesc,
00241 uint16_t fctl, uint8_t action)
00242 {
00243 struct hostdesc *host = &txdesc->host;
00244 struct vif_info_tag *vif = &vif_info_tab[host->vif_idx];
00245 struct sta_info_tag *sta = &sta_info_tab[host->staid];
00246
00247
00248 if ((host->staid == INVALID_STA_IDX) ||
00249 (!vif->default_key))
00250 {
00251 return MFP_NO_PROT;
00252 }
00253
00254 if (!mfp_is_robust_frame(fctl, action))
00255 {
00256
00257 return MFP_NO_PROT;
00258 }
00259
00260 if (MAC_ADDR_GROUP(&sta->mac_addr))
00261 {
00262 if (mfp_is_group_addressed_privacy(fctl, action))
00263 return MFP_UNICAST_PROT;
00264 else if (!vif->default_mgmt_key)
00265 return MFP_NO_PROT;
00266 else
00267 return MFP_MULTICAST_PROT;
00268 }
00269
00270 if (!STA_CAPA(sta, MFP))
00271 {
00272 return MFP_NO_PROT;
00273 }
00274
00275 return MFP_UNICAST_PROT;
00276 }
00277
00278
00279 int mfp_add_mgmt_mic(struct txdesc *txdesc, uint32_t frame, int len, uint32_t mmic)
00280 {
00281 struct hostdesc *host = &txdesc->host;
00282 struct vif_info_tag *vif = &vif_info_tab[host->vif_idx];
00283 struct key_info_tag *key;
00284 uint32_t mmic_ie;
00285 uint64_t mic;
00286 int i;
00287
00288 if (!vif->default_mgmt_key)
00289 {
00290 return 0;
00291 }
00292 key = vif->default_mgmt_key;
00293
00294 if (mmic)
00295 mmic_ie = mmic;
00296 else
00297 mmic_ie = frame + len;
00298
00299
00300 co_write8p(mmic_ie + MAC_MGMT_MIC_ID_OFT, MAC_ELTID_MGMT_MIC);
00301 co_write8p(mmic_ie + MAC_MGMT_MIC_LEN_OFT, MAC_MGMT_MIC_LEN - 2);
00302 co_write16p(mmic_ie + MAC_MGMT_MIC_KEYID_OFT, key->key_idx);
00303
00304
00305 key->tx_pn++;
00306 for (i = 0; i < MAC_MGMT_MIC_IPN_LEN; i++)
00307 {
00308 co_write8p(mmic_ie + MAC_MGMT_MIC_IPN_OFT + i, (key->tx_pn >> (8*i)) & 0xff);
00309 }
00310
00311
00312 for (i = 0; i < MAC_MGMT_MIC_MIC_LEN; i++)
00313 {
00314 co_write8p(mmic_ie + MAC_MGMT_MIC_MIC_OFT + i, 0);
00315 }
00316
00317 mic = mfp_compute_bip(key, frame, len, MAC_SHORT_MAC_HDR_LEN, mmic);
00318 for (i = 0; i < MAC_MGMT_MIC_MIC_LEN; i++)
00319 {
00320 co_write8p(mmic_ie + MAC_MGMT_MIC_MIC_OFT + i, (mic >> (8*i)) & 0xff);
00321 }
00322
00323 return MAC_MGMT_MIC_LEN;
00324 }
00325
00329 #endif