driver_macsec_qca.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899
  1. /*
  2. * Wired Ethernet driver interface for QCA MACsec driver
  3. * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
  4. * Copyright (c) 2004, Gunter Burchardt <tira@isx.de>
  5. * Copyright (c) 2013-2014, Qualcomm Atheros, Inc.
  6. *
  7. * This software may be distributed under the terms of the BSD license.
  8. * See README for more details.
  9. */
  10. #include "includes.h"
  11. #include <sys/ioctl.h>
  12. #include <net/if.h>
  13. #include <inttypes.h>
  14. #ifdef __linux__
  15. #include <netpacket/packet.h>
  16. #include <net/if_arp.h>
  17. #include <net/if.h>
  18. #endif /* __linux__ */
  19. #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
  20. #include <net/if_dl.h>
  21. #include <net/if_media.h>
  22. #endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) */
  23. #ifdef __sun__
  24. #include <sys/sockio.h>
  25. #endif /* __sun__ */
  26. #include "utils/common.h"
  27. #include "utils/eloop.h"
  28. #include "common/defs.h"
  29. #include "common/ieee802_1x_defs.h"
  30. #include "pae/ieee802_1x_kay.h"
  31. #include "driver.h"
  32. #include "nss_macsec_secy.h"
  33. #include "nss_macsec_secy_rx.h"
  34. #include "nss_macsec_secy_tx.h"
  35. #define MAXSC 16
  36. /* TCI field definition */
  37. #define TCI_ES 0x40
  38. #define TCI_SC 0x20
  39. #define TCI_SCB 0x10
  40. #define TCI_E 0x08
  41. #define TCI_C 0x04
  42. #ifdef _MSC_VER
  43. #pragma pack(push, 1)
  44. #endif /* _MSC_VER */
  45. #ifdef _MSC_VER
  46. #pragma pack(pop)
  47. #endif /* _MSC_VER */
  48. static const u8 pae_group_addr[ETH_ALEN] =
  49. { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
  50. struct macsec_qca_data {
  51. char ifname[IFNAMSIZ + 1];
  52. u32 secy_id;
  53. void *ctx;
  54. int sock; /* raw packet socket for driver access */
  55. int pf_sock;
  56. int membership, multi, iff_allmulti, iff_up;
  57. /* shadow */
  58. Boolean always_include_sci;
  59. Boolean use_es;
  60. Boolean use_scb;
  61. Boolean protect_frames;
  62. Boolean replay_protect;
  63. u32 replay_window;
  64. };
  65. static int macsec_qca_multicast_membership(int sock, int ifindex,
  66. const u8 *addr, int add)
  67. {
  68. #ifdef __linux__
  69. struct packet_mreq mreq;
  70. if (sock < 0)
  71. return -1;
  72. os_memset(&mreq, 0, sizeof(mreq));
  73. mreq.mr_ifindex = ifindex;
  74. mreq.mr_type = PACKET_MR_MULTICAST;
  75. mreq.mr_alen = ETH_ALEN;
  76. os_memcpy(mreq.mr_address, addr, ETH_ALEN);
  77. if (setsockopt(sock, SOL_PACKET,
  78. add ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP,
  79. &mreq, sizeof(mreq)) < 0) {
  80. wpa_printf(MSG_ERROR, "setsockopt: %s", strerror(errno));
  81. return -1;
  82. }
  83. return 0;
  84. #else /* __linux__ */
  85. return -1;
  86. #endif /* __linux__ */
  87. }
  88. static int macsec_qca_get_ssid(void *priv, u8 *ssid)
  89. {
  90. ssid[0] = 0;
  91. return 0;
  92. }
  93. static int macsec_qca_get_bssid(void *priv, u8 *bssid)
  94. {
  95. /* Report PAE group address as the "BSSID" for macsec connection. */
  96. os_memcpy(bssid, pae_group_addr, ETH_ALEN);
  97. return 0;
  98. }
  99. static int macsec_qca_get_capa(void *priv, struct wpa_driver_capa *capa)
  100. {
  101. os_memset(capa, 0, sizeof(*capa));
  102. capa->flags = WPA_DRIVER_FLAGS_WIRED;
  103. return 0;
  104. }
  105. static int macsec_qca_get_ifflags(const char *ifname, int *flags)
  106. {
  107. struct ifreq ifr;
  108. int s;
  109. s = socket(PF_INET, SOCK_DGRAM, 0);
  110. if (s < 0) {
  111. wpa_printf(MSG_ERROR, "socket: %s", strerror(errno));
  112. return -1;
  113. }
  114. os_memset(&ifr, 0, sizeof(ifr));
  115. os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
  116. if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
  117. wpa_printf(MSG_ERROR, "ioctl[SIOCGIFFLAGS]: %s",
  118. strerror(errno));
  119. close(s);
  120. return -1;
  121. }
  122. close(s);
  123. *flags = ifr.ifr_flags & 0xffff;
  124. return 0;
  125. }
  126. static int macsec_qca_set_ifflags(const char *ifname, int flags)
  127. {
  128. struct ifreq ifr;
  129. int s;
  130. s = socket(PF_INET, SOCK_DGRAM, 0);
  131. if (s < 0) {
  132. wpa_printf(MSG_ERROR, "socket: %s", strerror(errno));
  133. return -1;
  134. }
  135. os_memset(&ifr, 0, sizeof(ifr));
  136. os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
  137. ifr.ifr_flags = flags & 0xffff;
  138. if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
  139. wpa_printf(MSG_ERROR, "ioctl[SIOCSIFFLAGS]: %s",
  140. strerror(errno));
  141. close(s);
  142. return -1;
  143. }
  144. close(s);
  145. return 0;
  146. }
  147. #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
  148. static int macsec_qca_get_ifstatus(const char *ifname, int *status)
  149. {
  150. struct ifmediareq ifmr;
  151. int s;
  152. s = socket(PF_INET, SOCK_DGRAM, 0);
  153. if (s < 0) {
  154. wpa_print(MSG_ERROR, "socket: %s", strerror(errno));
  155. return -1;
  156. }
  157. os_memset(&ifmr, 0, sizeof(ifmr));
  158. os_strlcpy(ifmr.ifm_name, ifname, IFNAMSIZ);
  159. if (ioctl(s, SIOCGIFMEDIA, (caddr_t) &ifmr) < 0) {
  160. wpa_printf(MSG_ERROR, "ioctl[SIOCGIFMEDIA]: %s",
  161. strerror(errno));
  162. close(s);
  163. return -1;
  164. }
  165. close(s);
  166. *status = (ifmr.ifm_status & (IFM_ACTIVE | IFM_AVALID)) ==
  167. (IFM_ACTIVE | IFM_AVALID);
  168. return 0;
  169. }
  170. #endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */
  171. static int macsec_qca_multi(const char *ifname, const u8 *addr, int add)
  172. {
  173. struct ifreq ifr;
  174. int s;
  175. #ifdef __sun__
  176. return -1;
  177. #endif /* __sun__ */
  178. s = socket(PF_INET, SOCK_DGRAM, 0);
  179. if (s < 0) {
  180. wpa_printf(MSG_ERROR, "socket: %s", strerror(errno));
  181. return -1;
  182. }
  183. os_memset(&ifr, 0, sizeof(ifr));
  184. os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
  185. #ifdef __linux__
  186. ifr.ifr_hwaddr.sa_family = AF_UNSPEC;
  187. os_memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN);
  188. #endif /* __linux__ */
  189. #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
  190. {
  191. struct sockaddr_dl *dlp;
  192. dlp = (struct sockaddr_dl *) &ifr.ifr_addr;
  193. dlp->sdl_len = sizeof(struct sockaddr_dl);
  194. dlp->sdl_family = AF_LINK;
  195. dlp->sdl_index = 0;
  196. dlp->sdl_nlen = 0;
  197. dlp->sdl_alen = ETH_ALEN;
  198. dlp->sdl_slen = 0;
  199. os_memcpy(LLADDR(dlp), addr, ETH_ALEN);
  200. }
  201. #endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */
  202. #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
  203. {
  204. struct sockaddr *sap;
  205. sap = (struct sockaddr *) &ifr.ifr_addr;
  206. sap->sa_len = sizeof(struct sockaddr);
  207. sap->sa_family = AF_UNSPEC;
  208. os_memcpy(sap->sa_data, addr, ETH_ALEN);
  209. }
  210. #endif /* defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) */
  211. if (ioctl(s, add ? SIOCADDMULTI : SIOCDELMULTI, (caddr_t) &ifr) < 0) {
  212. wpa_printf(MSG_ERROR, "ioctl[SIOC{ADD/DEL}MULTI]: %s",
  213. strerror(errno));
  214. close(s);
  215. return -1;
  216. }
  217. close(s);
  218. return 0;
  219. }
  220. static void __macsec_drv_init(struct macsec_qca_data *drv)
  221. {
  222. int ret = 0;
  223. fal_rx_ctl_filt_t rx_ctl_filt;
  224. fal_tx_ctl_filt_t tx_ctl_filt;
  225. wpa_printf(MSG_INFO, "%s: secy_id=%d", __func__, drv->secy_id);
  226. /* Enable Secy and Let EAPoL bypass */
  227. ret = nss_macsec_secy_en_set(drv->secy_id, TRUE);
  228. if (ret)
  229. wpa_printf(MSG_ERROR, "nss_macsec_secy_en_set: FAIL");
  230. ret = nss_macsec_secy_sc_sa_mapping_mode_set(drv->secy_id,
  231. FAL_SC_SA_MAP_1_4);
  232. if (ret)
  233. wpa_printf(MSG_ERROR,
  234. "nss_macsec_secy_sc_sa_mapping_mode_set: FAIL");
  235. os_memset(&rx_ctl_filt, 0, sizeof(rx_ctl_filt));
  236. rx_ctl_filt.bypass = 1;
  237. rx_ctl_filt.match_type = IG_CTL_COMPARE_ETHER_TYPE;
  238. rx_ctl_filt.match_mask = 0xffff;
  239. rx_ctl_filt.ether_type_da_range = 0x888e;
  240. ret = nss_macsec_secy_rx_ctl_filt_set(drv->secy_id, 0, &rx_ctl_filt);
  241. if (ret)
  242. wpa_printf(MSG_ERROR, "nss_macsec_secy_rx_ctl_filt_set: FAIL");
  243. os_memset(&tx_ctl_filt, 0, sizeof(tx_ctl_filt));
  244. tx_ctl_filt.bypass = 1;
  245. tx_ctl_filt.match_type = EG_CTL_COMPARE_ETHER_TYPE;
  246. tx_ctl_filt.match_mask = 0xffff;
  247. tx_ctl_filt.ether_type_da_range = 0x888e;
  248. ret = nss_macsec_secy_tx_ctl_filt_set(drv->secy_id, 0, &tx_ctl_filt);
  249. if (ret)
  250. wpa_printf(MSG_ERROR, "nss_macsec_secy_tx_ctl_filt_set: FAIL");
  251. }
  252. static void __macsec_drv_deinit(struct macsec_qca_data *drv)
  253. {
  254. nss_macsec_secy_en_set(drv->secy_id, FALSE);
  255. nss_macsec_secy_rx_sc_del_all(drv->secy_id);
  256. nss_macsec_secy_tx_sc_del_all(drv->secy_id);
  257. }
  258. static void * macsec_qca_init(void *ctx, const char *ifname)
  259. {
  260. struct macsec_qca_data *drv;
  261. int flags;
  262. drv = os_zalloc(sizeof(*drv));
  263. if (drv == NULL)
  264. return NULL;
  265. os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname));
  266. drv->ctx = ctx;
  267. /* Board specific settings */
  268. if (os_memcmp("eth2", drv->ifname, 4) == 0)
  269. drv->secy_id = 1;
  270. else if (os_memcmp("eth3", drv->ifname, 4) == 0)
  271. drv->secy_id = 2;
  272. else
  273. drv->secy_id = -1;
  274. #ifdef __linux__
  275. drv->pf_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
  276. if (drv->pf_sock < 0)
  277. wpa_printf(MSG_ERROR, "socket(PF_PACKET): %s", strerror(errno));
  278. #else /* __linux__ */
  279. drv->pf_sock = -1;
  280. #endif /* __linux__ */
  281. if (macsec_qca_get_ifflags(ifname, &flags) == 0 &&
  282. !(flags & IFF_UP) &&
  283. macsec_qca_set_ifflags(ifname, flags | IFF_UP) == 0) {
  284. drv->iff_up = 1;
  285. }
  286. if (macsec_qca_multicast_membership(drv->pf_sock,
  287. if_nametoindex(drv->ifname),
  288. pae_group_addr, 1) == 0) {
  289. wpa_printf(MSG_DEBUG,
  290. "%s: Added multicast membership with packet socket",
  291. __func__);
  292. drv->membership = 1;
  293. } else if (macsec_qca_multi(ifname, pae_group_addr, 1) == 0) {
  294. wpa_printf(MSG_DEBUG,
  295. "%s: Added multicast membership with SIOCADDMULTI",
  296. __func__);
  297. drv->multi = 1;
  298. } else if (macsec_qca_get_ifflags(ifname, &flags) < 0) {
  299. wpa_printf(MSG_INFO, "%s: Could not get interface flags",
  300. __func__);
  301. os_free(drv);
  302. return NULL;
  303. } else if (flags & IFF_ALLMULTI) {
  304. wpa_printf(MSG_DEBUG,
  305. "%s: Interface is already configured for multicast",
  306. __func__);
  307. } else if (macsec_qca_set_ifflags(ifname, flags | IFF_ALLMULTI) < 0) {
  308. wpa_printf(MSG_INFO, "%s: Failed to enable allmulti",
  309. __func__);
  310. os_free(drv);
  311. return NULL;
  312. } else {
  313. wpa_printf(MSG_DEBUG, "%s: Enabled allmulti mode", __func__);
  314. drv->iff_allmulti = 1;
  315. }
  316. #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
  317. {
  318. int status;
  319. wpa_printf(MSG_DEBUG, "%s: waiting for link to become active",
  320. __func__);
  321. while (macsec_qca_get_ifstatus(ifname, &status) == 0 &&
  322. status == 0)
  323. sleep(1);
  324. }
  325. #endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */
  326. return drv;
  327. }
  328. static void macsec_qca_deinit(void *priv)
  329. {
  330. struct macsec_qca_data *drv = priv;
  331. int flags;
  332. if (drv->membership &&
  333. macsec_qca_multicast_membership(drv->pf_sock,
  334. if_nametoindex(drv->ifname),
  335. pae_group_addr, 0) < 0) {
  336. wpa_printf(MSG_DEBUG,
  337. "%s: Failed to remove PAE multicast group (PACKET)",
  338. __func__);
  339. }
  340. if (drv->multi &&
  341. macsec_qca_multi(drv->ifname, pae_group_addr, 0) < 0) {
  342. wpa_printf(MSG_DEBUG,
  343. "%s: Failed to remove PAE multicast group (SIOCDELMULTI)",
  344. __func__);
  345. }
  346. if (drv->iff_allmulti &&
  347. (macsec_qca_get_ifflags(drv->ifname, &flags) < 0 ||
  348. macsec_qca_set_ifflags(drv->ifname, flags & ~IFF_ALLMULTI) < 0)) {
  349. wpa_printf(MSG_DEBUG, "%s: Failed to disable allmulti mode",
  350. __func__);
  351. }
  352. if (drv->iff_up &&
  353. macsec_qca_get_ifflags(drv->ifname, &flags) == 0 &&
  354. (flags & IFF_UP) &&
  355. macsec_qca_set_ifflags(drv->ifname, flags & ~IFF_UP) < 0) {
  356. wpa_printf(MSG_DEBUG, "%s: Failed to set the interface down",
  357. __func__);
  358. }
  359. if (drv->pf_sock != -1)
  360. close(drv->pf_sock);
  361. os_free(drv);
  362. }
  363. static int macsec_qca_macsec_init(void *priv, struct macsec_init_params *params)
  364. {
  365. struct macsec_qca_data *drv = priv;
  366. drv->always_include_sci = params->always_include_sci;
  367. drv->use_es = params->use_es;
  368. drv->use_scb = params->use_scb;
  369. wpa_printf(MSG_DEBUG, "%s: es=%d, scb=%d, sci=%d",
  370. __func__, drv->use_es, drv->use_scb,
  371. drv->always_include_sci);
  372. __macsec_drv_init(drv);
  373. return 0;
  374. }
  375. static int macsec_qca_macsec_deinit(void *priv)
  376. {
  377. struct macsec_qca_data *drv = priv;
  378. wpa_printf(MSG_DEBUG, "%s", __func__);
  379. __macsec_drv_deinit(drv);
  380. return 0;
  381. }
  382. static int macsec_qca_enable_protect_frames(void *priv, Boolean enabled)
  383. {
  384. struct macsec_qca_data *drv = priv;
  385. int ret = 0;
  386. wpa_printf(MSG_DEBUG, "%s: enabled=%d", __func__, enabled);
  387. drv->protect_frames = enabled;
  388. return ret;
  389. }
  390. static int macsec_qca_set_replay_protect(void *priv, Boolean enabled,
  391. unsigned int window)
  392. {
  393. struct macsec_qca_data *drv = priv;
  394. int ret = 0;
  395. wpa_printf(MSG_DEBUG, "%s: enabled=%d, win=%u",
  396. __func__, enabled, window);
  397. drv->replay_protect = enabled;
  398. drv->replay_window = window;
  399. return ret;
  400. }
  401. static int macsec_qca_set_current_cipher_suite(void *priv, u64 cs)
  402. {
  403. if (cs != CS_ID_GCM_AES_128) {
  404. wpa_printf(MSG_ERROR,
  405. "%s: NOT supported CipherSuite: %016" PRIx64,
  406. __func__, cs);
  407. return -1;
  408. }
  409. /* Support default Cipher Suite 0080020001000001 (GCM-AES-128) */
  410. wpa_printf(MSG_DEBUG, "%s: default support aes-gcm-128", __func__);
  411. return 0;
  412. }
  413. static int macsec_qca_enable_controlled_port(void *priv, Boolean enabled)
  414. {
  415. struct macsec_qca_data *drv = priv;
  416. int ret = 0;
  417. wpa_printf(MSG_DEBUG, "%s: enable=%d", __func__, enabled);
  418. ret += nss_macsec_secy_controlled_port_en_set(drv->secy_id, enabled);
  419. return ret;
  420. }
  421. static int macsec_qca_get_receive_lowest_pn(void *priv, struct receive_sa *sa)
  422. {
  423. struct macsec_qca_data *drv = priv;
  424. int ret = 0;
  425. u32 next_pn = 0;
  426. bool enabled = FALSE;
  427. u32 win;
  428. u32 channel = sa->sc->channel;
  429. ret += nss_macsec_secy_rx_sa_next_pn_get(drv->secy_id, channel, sa->an,
  430. &next_pn);
  431. ret += nss_macsec_secy_rx_sc_replay_protect_get(drv->secy_id, channel,
  432. &enabled);
  433. ret += nss_macsec_secy_rx_sc_anti_replay_window_get(drv->secy_id,
  434. channel, &win);
  435. if (enabled)
  436. sa->lowest_pn = (next_pn > win) ? (next_pn - win) : 1;
  437. else
  438. sa->lowest_pn = next_pn;
  439. wpa_printf(MSG_DEBUG, "%s: lpn=0x%x", __func__, sa->lowest_pn);
  440. return ret;
  441. }
  442. static int macsec_qca_get_transmit_next_pn(void *priv, struct transmit_sa *sa)
  443. {
  444. struct macsec_qca_data *drv = priv;
  445. int ret = 0;
  446. u32 channel = sa->sc->channel;
  447. ret += nss_macsec_secy_tx_sa_next_pn_get(drv->secy_id, channel, sa->an,
  448. &sa->next_pn);
  449. wpa_printf(MSG_DEBUG, "%s: npn=0x%x", __func__, sa->next_pn);
  450. return ret;
  451. }
  452. int macsec_qca_set_transmit_next_pn(void *priv, struct transmit_sa *sa)
  453. {
  454. struct macsec_qca_data *drv = priv;
  455. int ret = 0;
  456. u32 channel = sa->sc->channel;
  457. ret += nss_macsec_secy_tx_sa_next_pn_set(drv->secy_id, channel, sa->an,
  458. sa->next_pn);
  459. wpa_printf(MSG_INFO, "%s: npn=0x%x", __func__, sa->next_pn);
  460. return ret;
  461. }
  462. static int macsec_qca_get_available_receive_sc(void *priv, u32 *channel)
  463. {
  464. struct macsec_qca_data *drv = priv;
  465. int ret = 0;
  466. u32 sc_ch = 0;
  467. bool in_use = FALSE;
  468. for (sc_ch = 0; sc_ch < MAXSC; sc_ch++) {
  469. ret = nss_macsec_secy_rx_sc_in_used_get(drv->secy_id, sc_ch,
  470. &in_use);
  471. if (ret)
  472. continue;
  473. if (!in_use) {
  474. *channel = sc_ch;
  475. wpa_printf(MSG_DEBUG, "%s: channel=%d",
  476. __func__, *channel);
  477. return 0;
  478. }
  479. }
  480. wpa_printf(MSG_DEBUG, "%s: no available channel", __func__);
  481. return -1;
  482. }
  483. static int macsec_qca_create_receive_sc(void *priv, u32 channel,
  484. const u8 *sci_addr, u16 sci_port,
  485. unsigned int conf_offset,
  486. int validation)
  487. {
  488. struct macsec_qca_data *drv = priv;
  489. int ret = 0;
  490. fal_rx_prc_lut_t entry;
  491. fal_rx_sc_validate_frame_e vf;
  492. enum validate_frames validate_frames = validation;
  493. wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
  494. /* rx prc lut */
  495. os_memset(&entry, 0, sizeof(entry));
  496. os_memcpy(entry.sci, sci_addr, ETH_ALEN);
  497. entry.sci[6] = (sci_port >> 8) & 0xf;
  498. entry.sci[7] = sci_port & 0xf;
  499. entry.sci_mask = 0xf;
  500. entry.valid = 1;
  501. entry.channel = channel;
  502. entry.action = FAL_RX_PRC_ACTION_PROCESS;
  503. entry.offset = conf_offset;
  504. /* rx validate frame */
  505. if (validate_frames == Strict)
  506. vf = FAL_RX_SC_VALIDATE_FRAME_STRICT;
  507. else if (validate_frames == Checked)
  508. vf = FAL_RX_SC_VALIDATE_FRAME_CHECK;
  509. else
  510. vf = FAL_RX_SC_VALIDATE_FRAME_DISABLED;
  511. ret += nss_macsec_secy_rx_prc_lut_set(drv->secy_id, channel, &entry);
  512. ret += nss_macsec_secy_rx_sc_create(drv->secy_id, channel);
  513. ret += nss_macsec_secy_rx_sc_validate_frame_set(drv->secy_id, channel,
  514. vf);
  515. ret += nss_macsec_secy_rx_sc_replay_protect_set(drv->secy_id, channel,
  516. drv->replay_protect);
  517. ret += nss_macsec_secy_rx_sc_anti_replay_window_set(drv->secy_id,
  518. channel,
  519. drv->replay_window);
  520. return ret;
  521. }
  522. static int macsec_qca_delete_receive_sc(void *priv, u32 channel)
  523. {
  524. struct macsec_qca_data *drv = priv;
  525. int ret = 0;
  526. fal_rx_prc_lut_t entry;
  527. wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
  528. /* rx prc lut */
  529. os_memset(&entry, 0, sizeof(entry));
  530. ret += nss_macsec_secy_rx_sc_del(drv->secy_id, channel);
  531. ret += nss_macsec_secy_rx_prc_lut_set(drv->secy_id, channel, &entry);
  532. return ret;
  533. }
  534. static int macsec_qca_create_receive_sa(void *priv, u32 channel, u8 an,
  535. u32 lowest_pn, const u8 *sak)
  536. {
  537. struct macsec_qca_data *drv = priv;
  538. int ret = 0;
  539. fal_rx_sak_t rx_sak;
  540. int i = 0;
  541. wpa_printf(MSG_DEBUG, "%s, channel=%d, an=%d, lpn=0x%x",
  542. __func__, channel, an, lowest_pn);
  543. os_memset(&rx_sak, 0, sizeof(rx_sak));
  544. for (i = 0; i < 16; i++)
  545. rx_sak.sak[i] = sak[15 - i];
  546. ret += nss_macsec_secy_rx_sa_create(drv->secy_id, channel, an);
  547. ret += nss_macsec_secy_rx_sak_set(drv->secy_id, channel, an, &rx_sak);
  548. return ret;
  549. }
  550. static int macsec_qca_enable_receive_sa(void *priv, u32 channel, u8 an)
  551. {
  552. struct macsec_qca_data *drv = priv;
  553. int ret = 0;
  554. wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel, an);
  555. ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, an, TRUE);
  556. return ret;
  557. }
  558. static int macsec_qca_disable_receive_sa(void *priv, u32 channel, u8 an)
  559. {
  560. struct macsec_qca_data *drv = priv;
  561. int ret = 0;
  562. wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel, an);
  563. ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, an, FALSE);
  564. return ret;
  565. }
  566. static int macsec_qca_get_available_transmit_sc(void *priv, u32 *channel)
  567. {
  568. struct macsec_qca_data *drv = priv;
  569. int ret = 0;
  570. u32 sc_ch = 0;
  571. bool in_use = FALSE;
  572. for (sc_ch = 0; sc_ch < MAXSC; sc_ch++) {
  573. ret = nss_macsec_secy_tx_sc_in_used_get(drv->secy_id, sc_ch,
  574. &in_use);
  575. if (ret)
  576. continue;
  577. if (!in_use) {
  578. *channel = sc_ch;
  579. wpa_printf(MSG_DEBUG, "%s: channel=%d",
  580. __func__, *channel);
  581. return 0;
  582. }
  583. }
  584. wpa_printf(MSG_DEBUG, "%s: no avaiable channel", __func__);
  585. return -1;
  586. }
  587. static int macsec_qca_create_transmit_sc(void *priv, u32 channel,
  588. const u8 *sci_addr, u16 sci_port,
  589. unsigned int conf_offset)
  590. {
  591. struct macsec_qca_data *drv = priv;
  592. int ret = 0;
  593. fal_tx_class_lut_t entry;
  594. u8 psci[ETH_ALEN + 2];
  595. wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
  596. /* class lut */
  597. os_memset(&entry, 0, sizeof(entry));
  598. entry.valid = 1;
  599. entry.action = FAL_TX_CLASS_ACTION_FORWARD;
  600. entry.channel = channel;
  601. os_memcpy(psci, sci_addr, ETH_ALEN);
  602. psci[6] = (sci_port >> 8) & 0xf;
  603. psci[7] = sci_port & 0xf;
  604. ret += nss_macsec_secy_tx_class_lut_set(drv->secy_id, channel, &entry);
  605. ret += nss_macsec_secy_tx_sc_create(drv->secy_id, channel, psci, 8);
  606. ret += nss_macsec_secy_tx_sc_protect_set(drv->secy_id, channel,
  607. drv->protect_frames);
  608. ret += nss_macsec_secy_tx_sc_confidentiality_offset_set(drv->secy_id,
  609. channel,
  610. conf_offset);
  611. return ret;
  612. }
  613. static int macsec_qca_delete_transmit_sc(void *priv, u32 channel)
  614. {
  615. struct macsec_qca_data *drv = priv;
  616. int ret = 0;
  617. fal_tx_class_lut_t entry;
  618. wpa_printf(MSG_DEBUG, "%s: channel=%d", __func__, channel);
  619. /* class lut */
  620. os_memset(&entry, 0, sizeof(entry));
  621. ret += nss_macsec_secy_tx_class_lut_set(drv->secy_id, channel, &entry);
  622. ret += nss_macsec_secy_tx_sc_del(drv->secy_id, channel);
  623. return ret;
  624. }
  625. static int macsec_qca_create_transmit_sa(void *priv, struct transmit_sa *sa)
  626. {
  627. struct macsec_qca_data *drv = priv;
  628. int ret = 0;
  629. u8 tci = 0;
  630. fal_tx_sak_t tx_sak;
  631. int i;
  632. u32 channel = sa->sc->channel;
  633. wpa_printf(MSG_DEBUG,
  634. "%s: channel=%d, an=%d, next_pn=0x%x, confidentiality=%d",
  635. __func__, channel, sa->an, sa->next_pn, sa->confidentiality);
  636. if (drv->always_include_sci)
  637. tci |= TCI_SC;
  638. else if (drv->use_es)
  639. tci |= TCI_ES;
  640. else if (drv->use_scb)
  641. tci |= TCI_SCB;
  642. if (sa->confidentiality)
  643. tci |= TCI_E | TCI_C;
  644. os_memset(&tx_sak, 0, sizeof(tx_sak));
  645. for (i = 0; i < 16; i++)
  646. tx_sak.sak[i] = sa->pkey->key[15 - i];
  647. ret += nss_macsec_secy_tx_sa_next_pn_set(drv->secy_id, channel, sa->an,
  648. sa->next_pn);
  649. ret += nss_macsec_secy_tx_sak_set(drv->secy_id, channel, sa->an,
  650. &tx_sak);
  651. ret += nss_macsec_secy_tx_sc_tci_7_2_set(drv->secy_id, channel,
  652. (tci >> 2));
  653. ret += nss_macsec_secy_tx_sc_an_set(drv->secy_id, channel, sa->an);
  654. return ret;
  655. }
  656. static int macsec_qca_enable_transmit_sa(void *priv, struct transmit_sa *sa)
  657. {
  658. struct macsec_qca_data *drv = priv;
  659. int ret = 0;
  660. u32 channel = sa->sc->channel;
  661. wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
  662. sa->an);
  663. ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an,
  664. TRUE);
  665. return ret;
  666. }
  667. static int macsec_qca_disable_transmit_sa(void *priv, struct transmit_sa *sa)
  668. {
  669. struct macsec_qca_data *drv = priv;
  670. int ret = 0;
  671. u32 channel = sa->sc->channel;
  672. wpa_printf(MSG_DEBUG, "%s: channel=%d, an=%d", __func__, channel,
  673. sa->an);
  674. ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an,
  675. FALSE);
  676. return ret;
  677. }
  678. const struct wpa_driver_ops wpa_driver_macsec_qca_ops = {
  679. .name = "macsec_qca",
  680. .desc = "QCA MACsec Ethernet driver",
  681. .get_ssid = macsec_qca_get_ssid,
  682. .get_bssid = macsec_qca_get_bssid,
  683. .get_capa = macsec_qca_get_capa,
  684. .init = macsec_qca_init,
  685. .deinit = macsec_qca_deinit,
  686. .macsec_init = macsec_qca_macsec_init,
  687. .macsec_deinit = macsec_qca_macsec_deinit,
  688. .enable_protect_frames = macsec_qca_enable_protect_frames,
  689. .set_replay_protect = macsec_qca_set_replay_protect,
  690. .set_current_cipher_suite = macsec_qca_set_current_cipher_suite,
  691. .enable_controlled_port = macsec_qca_enable_controlled_port,
  692. .get_receive_lowest_pn = macsec_qca_get_receive_lowest_pn,
  693. .get_transmit_next_pn = macsec_qca_get_transmit_next_pn,
  694. .set_transmit_next_pn = macsec_qca_set_transmit_next_pn,
  695. .get_available_receive_sc = macsec_qca_get_available_receive_sc,
  696. .create_receive_sc = macsec_qca_create_receive_sc,
  697. .delete_receive_sc = macsec_qca_delete_receive_sc,
  698. .create_receive_sa = macsec_qca_create_receive_sa,
  699. .enable_receive_sa = macsec_qca_enable_receive_sa,
  700. .disable_receive_sa = macsec_qca_disable_receive_sa,
  701. .get_available_transmit_sc = macsec_qca_get_available_transmit_sc,
  702. .create_transmit_sc = macsec_qca_create_transmit_sc,
  703. .delete_transmit_sc = macsec_qca_delete_transmit_sc,
  704. .create_transmit_sa = macsec_qca_create_transmit_sa,
  705. .enable_transmit_sa = macsec_qca_enable_transmit_sa,
  706. .disable_transmit_sa = macsec_qca_disable_transmit_sa,
  707. };