dpp_hostapd.c 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634
  1. /*
  2. * hostapd / DPP integration
  3. * Copyright (c) 2017, Qualcomm Atheros, Inc.
  4. *
  5. * This software may be distributed under the terms of the BSD license.
  6. * See README for more details.
  7. */
  8. #include "utils/includes.h"
  9. #include "utils/common.h"
  10. #include "utils/eloop.h"
  11. #include "common/dpp.h"
  12. #include "common/gas.h"
  13. #include "common/wpa_ctrl.h"
  14. #include "hostapd.h"
  15. #include "ap_drv_ops.h"
  16. #include "gas_query_ap.h"
  17. #include "wpa_auth.h"
  18. #include "dpp_hostapd.h"
  19. static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator);
  20. static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  21. static struct dpp_configurator *
  22. hostapd_dpp_configurator_get_id(struct hostapd_data *hapd, unsigned int id)
  23. {
  24. struct dpp_configurator *conf;
  25. dl_list_for_each(conf, &hapd->dpp_configurator,
  26. struct dpp_configurator, list) {
  27. if (conf->id == id)
  28. return conf;
  29. }
  30. return NULL;
  31. }
  32. static unsigned int hapd_dpp_next_id(struct hostapd_data *hapd)
  33. {
  34. struct dpp_bootstrap_info *bi;
  35. unsigned int max_id = 0;
  36. dl_list_for_each(bi, &hapd->dpp_bootstrap, struct dpp_bootstrap_info,
  37. list) {
  38. if (bi->id > max_id)
  39. max_id = bi->id;
  40. }
  41. return max_id + 1;
  42. }
  43. /**
  44. * hostapd_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
  45. * @hapd: Pointer to hostapd_data
  46. * @cmd: DPP URI read from a QR Code
  47. * Returns: Identifier of the stored info or -1 on failure
  48. */
  49. int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd)
  50. {
  51. struct dpp_bootstrap_info *bi;
  52. struct dpp_authentication *auth = hapd->dpp_auth;
  53. bi = dpp_parse_qr_code(cmd);
  54. if (!bi)
  55. return -1;
  56. bi->id = hapd_dpp_next_id(hapd);
  57. dl_list_add(&hapd->dpp_bootstrap, &bi->list);
  58. if (auth && auth->response_pending &&
  59. dpp_notify_new_qr_code(auth, bi) == 1) {
  60. wpa_printf(MSG_DEBUG,
  61. "DPP: Sending out pending authentication response");
  62. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
  63. " freq=%u type=%d",
  64. MAC2STR(auth->peer_mac_addr), auth->curr_freq,
  65. DPP_PA_AUTHENTICATION_RESP);
  66. hostapd_drv_send_action(hapd, auth->curr_freq, 0,
  67. auth->peer_mac_addr,
  68. wpabuf_head(hapd->dpp_auth->resp_msg),
  69. wpabuf_len(hapd->dpp_auth->resp_msg));
  70. }
  71. return bi->id;
  72. }
  73. static char * get_param(const char *cmd, const char *param)
  74. {
  75. const char *pos, *end;
  76. char *val;
  77. size_t len;
  78. pos = os_strstr(cmd, param);
  79. if (!pos)
  80. return NULL;
  81. pos += os_strlen(param);
  82. end = os_strchr(pos, ' ');
  83. if (end)
  84. len = end - pos;
  85. else
  86. len = os_strlen(pos);
  87. val = os_malloc(len + 1);
  88. if (!val)
  89. return NULL;
  90. os_memcpy(val, pos, len);
  91. val[len] = '\0';
  92. return val;
  93. }
  94. int hostapd_dpp_bootstrap_gen(struct hostapd_data *hapd, const char *cmd)
  95. {
  96. char *chan = NULL, *mac = NULL, *info = NULL, *pk = NULL, *curve = NULL;
  97. char *key = NULL;
  98. u8 *privkey = NULL;
  99. size_t privkey_len = 0;
  100. size_t len;
  101. int ret = -1;
  102. struct dpp_bootstrap_info *bi;
  103. bi = os_zalloc(sizeof(*bi));
  104. if (!bi)
  105. goto fail;
  106. if (os_strstr(cmd, "type=qrcode"))
  107. bi->type = DPP_BOOTSTRAP_QR_CODE;
  108. else if (os_strstr(cmd, "type=pkex"))
  109. bi->type = DPP_BOOTSTRAP_PKEX;
  110. else
  111. goto fail;
  112. chan = get_param(cmd, " chan=");
  113. mac = get_param(cmd, " mac=");
  114. info = get_param(cmd, " info=");
  115. curve = get_param(cmd, " curve=");
  116. key = get_param(cmd, " key=");
  117. if (key) {
  118. privkey_len = os_strlen(key) / 2;
  119. privkey = os_malloc(privkey_len);
  120. if (!privkey ||
  121. hexstr2bin(key, privkey, privkey_len) < 0)
  122. goto fail;
  123. }
  124. pk = dpp_keygen(bi, curve, privkey, privkey_len);
  125. if (!pk)
  126. goto fail;
  127. len = 4; /* "DPP:" */
  128. if (chan) {
  129. if (dpp_parse_uri_chan_list(bi, chan) < 0)
  130. goto fail;
  131. len += 3 + os_strlen(chan); /* C:...; */
  132. }
  133. if (mac) {
  134. if (dpp_parse_uri_mac(bi, mac) < 0)
  135. goto fail;
  136. len += 3 + os_strlen(mac); /* M:...; */
  137. }
  138. if (info) {
  139. if (dpp_parse_uri_info(bi, info) < 0)
  140. goto fail;
  141. len += 3 + os_strlen(info); /* I:...; */
  142. }
  143. len += 4 + os_strlen(pk);
  144. bi->uri = os_malloc(len + 1);
  145. if (!bi->uri)
  146. goto fail;
  147. os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%s%s%sK:%s;;",
  148. chan ? "C:" : "", chan ? chan : "", chan ? ";" : "",
  149. mac ? "M:" : "", mac ? mac : "", mac ? ";" : "",
  150. info ? "I:" : "", info ? info : "", info ? ";" : "",
  151. pk);
  152. bi->id = hapd_dpp_next_id(hapd);
  153. dl_list_add(&hapd->dpp_bootstrap, &bi->list);
  154. ret = bi->id;
  155. bi = NULL;
  156. fail:
  157. os_free(curve);
  158. os_free(pk);
  159. os_free(chan);
  160. os_free(mac);
  161. os_free(info);
  162. str_clear_free(key);
  163. bin_clear_free(privkey, privkey_len);
  164. dpp_bootstrap_info_free(bi);
  165. return ret;
  166. }
  167. static struct dpp_bootstrap_info *
  168. dpp_bootstrap_get_id(struct hostapd_data *hapd, unsigned int id)
  169. {
  170. struct dpp_bootstrap_info *bi;
  171. dl_list_for_each(bi, &hapd->dpp_bootstrap, struct dpp_bootstrap_info,
  172. list) {
  173. if (bi->id == id)
  174. return bi;
  175. }
  176. return NULL;
  177. }
  178. static int dpp_bootstrap_del(struct hostapd_data *hapd, unsigned int id)
  179. {
  180. struct dpp_bootstrap_info *bi, *tmp;
  181. int found = 0;
  182. dl_list_for_each_safe(bi, tmp, &hapd->dpp_bootstrap,
  183. struct dpp_bootstrap_info, list) {
  184. if (id && bi->id != id)
  185. continue;
  186. found = 1;
  187. dl_list_del(&bi->list);
  188. dpp_bootstrap_info_free(bi);
  189. }
  190. if (id == 0)
  191. return 0; /* flush succeeds regardless of entries found */
  192. return found ? 0 : -1;
  193. }
  194. int hostapd_dpp_bootstrap_remove(struct hostapd_data *hapd, const char *id)
  195. {
  196. unsigned int id_val;
  197. if (os_strcmp(id, "*") == 0) {
  198. id_val = 0;
  199. } else {
  200. id_val = atoi(id);
  201. if (id_val == 0)
  202. return -1;
  203. }
  204. return dpp_bootstrap_del(hapd, id_val);
  205. }
  206. const char * hostapd_dpp_bootstrap_get_uri(struct hostapd_data *hapd,
  207. unsigned int id)
  208. {
  209. struct dpp_bootstrap_info *bi;
  210. bi = dpp_bootstrap_get_id(hapd, id);
  211. if (!bi)
  212. return NULL;
  213. return bi->uri;
  214. }
  215. int hostapd_dpp_bootstrap_info(struct hostapd_data *hapd, int id,
  216. char *reply, int reply_size)
  217. {
  218. struct dpp_bootstrap_info *bi;
  219. bi = dpp_bootstrap_get_id(hapd, id);
  220. if (!bi)
  221. return -1;
  222. return os_snprintf(reply, reply_size, "type=%s\n"
  223. "mac_addr=" MACSTR "\n"
  224. "info=%s\n"
  225. "num_freq=%u\n"
  226. "curve=%s\n",
  227. dpp_bootstrap_type_txt(bi->type),
  228. MAC2STR(bi->mac_addr),
  229. bi->info ? bi->info : "",
  230. bi->num_freq,
  231. bi->curve->name);
  232. }
  233. void hostapd_dpp_tx_status(struct hostapd_data *hapd, const u8 *dst,
  234. const u8 *data, size_t data_len, int ok)
  235. {
  236. wpa_printf(MSG_DEBUG, "DPP: TX status: dst=" MACSTR " ok=%d",
  237. MAC2STR(dst), ok);
  238. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX_STATUS "dst=" MACSTR
  239. " result=%s", MAC2STR(dst), ok ? "SUCCESS" : "FAILED");
  240. if (!hapd->dpp_auth) {
  241. wpa_printf(MSG_DEBUG,
  242. "DPP: Ignore TX status since there is no ongoing authentication exchange");
  243. return;
  244. }
  245. if (hapd->dpp_auth->remove_on_tx_status) {
  246. wpa_printf(MSG_DEBUG,
  247. "DPP: Terminate authentication exchange due to an earlier error");
  248. dpp_auth_deinit(hapd->dpp_auth);
  249. hapd->dpp_auth = NULL;
  250. return;
  251. }
  252. if (hapd->dpp_auth_ok_on_ack)
  253. hostapd_dpp_auth_success(hapd, 1);
  254. }
  255. static void hostapd_dpp_set_testing_options(struct hostapd_data *hapd,
  256. struct dpp_authentication *auth)
  257. {
  258. #ifdef CONFIG_TESTING_OPTIONS
  259. if (hapd->dpp_config_obj_override)
  260. auth->config_obj_override =
  261. os_strdup(hapd->dpp_config_obj_override);
  262. if (hapd->dpp_discovery_override)
  263. auth->discovery_override =
  264. os_strdup(hapd->dpp_discovery_override);
  265. if (hapd->dpp_groups_override)
  266. auth->groups_override = os_strdup(hapd->dpp_groups_override);
  267. auth->ignore_netaccesskey_mismatch =
  268. hapd->dpp_ignore_netaccesskey_mismatch;
  269. #endif /* CONFIG_TESTING_OPTIONS */
  270. }
  271. static void hostapd_dpp_set_configurator(struct hostapd_data *hapd,
  272. struct dpp_authentication *auth,
  273. const char *cmd)
  274. {
  275. const char *pos, *end;
  276. struct dpp_configuration *conf_sta = NULL, *conf_ap = NULL;
  277. struct dpp_configurator *conf = NULL;
  278. u8 ssid[32] = { "test" };
  279. size_t ssid_len = 4;
  280. char pass[64] = { };
  281. size_t pass_len = 0;
  282. u8 psk[PMK_LEN];
  283. int psk_set = 0;
  284. if (!cmd)
  285. return;
  286. wpa_printf(MSG_DEBUG, "DPP: Set configurator parameters: %s", cmd);
  287. pos = os_strstr(cmd, " ssid=");
  288. if (pos) {
  289. pos += 6;
  290. end = os_strchr(pos, ' ');
  291. ssid_len = end ? (size_t) (end - pos) : os_strlen(pos);
  292. ssid_len /= 2;
  293. if (ssid_len > sizeof(ssid) ||
  294. hexstr2bin(pos, ssid, ssid_len) < 0)
  295. goto fail;
  296. }
  297. pos = os_strstr(cmd, " pass=");
  298. if (pos) {
  299. pos += 6;
  300. end = os_strchr(pos, ' ');
  301. pass_len = end ? (size_t) (end - pos) : os_strlen(pos);
  302. pass_len /= 2;
  303. if (pass_len > sizeof(pass) - 1 || pass_len < 8 ||
  304. hexstr2bin(pos, (u8 *) pass, pass_len) < 0)
  305. goto fail;
  306. }
  307. pos = os_strstr(cmd, " psk=");
  308. if (pos) {
  309. pos += 5;
  310. if (hexstr2bin(pos, psk, PMK_LEN) < 0)
  311. goto fail;
  312. psk_set = 1;
  313. }
  314. if (os_strstr(cmd, " conf=sta-")) {
  315. conf_sta = os_zalloc(sizeof(struct dpp_configuration));
  316. if (!conf_sta)
  317. goto fail;
  318. os_memcpy(conf_sta->ssid, ssid, ssid_len);
  319. conf_sta->ssid_len = ssid_len;
  320. if (os_strstr(cmd, " conf=sta-psk")) {
  321. conf_sta->dpp = 0;
  322. if (psk_set) {
  323. os_memcpy(conf_sta->psk, psk, PMK_LEN);
  324. } else {
  325. conf_sta->passphrase = os_strdup(pass);
  326. if (!conf_sta->passphrase)
  327. goto fail;
  328. }
  329. } else if (os_strstr(cmd, " conf=sta-dpp")) {
  330. conf_sta->dpp = 1;
  331. } else {
  332. goto fail;
  333. }
  334. }
  335. if (os_strstr(cmd, " conf=ap-")) {
  336. conf_ap = os_zalloc(sizeof(struct dpp_configuration));
  337. if (!conf_ap)
  338. goto fail;
  339. os_memcpy(conf_ap->ssid, ssid, ssid_len);
  340. conf_ap->ssid_len = ssid_len;
  341. if (os_strstr(cmd, " conf=ap-psk")) {
  342. conf_ap->dpp = 0;
  343. if (psk_set) {
  344. os_memcpy(conf_ap->psk, psk, PMK_LEN);
  345. } else {
  346. conf_ap->passphrase = os_strdup(pass);
  347. if (!conf_ap->passphrase)
  348. goto fail;
  349. }
  350. } else if (os_strstr(cmd, " conf=ap-dpp")) {
  351. conf_ap->dpp = 1;
  352. } else {
  353. goto fail;
  354. }
  355. }
  356. pos = os_strstr(cmd, " expiry=");
  357. if (pos) {
  358. long int val;
  359. pos += 8;
  360. val = strtol(pos, NULL, 0);
  361. if (val <= 0)
  362. goto fail;
  363. if (conf_sta)
  364. conf_sta->netaccesskey_expiry = val;
  365. if (conf_ap)
  366. conf_ap->netaccesskey_expiry = val;
  367. }
  368. pos = os_strstr(cmd, " configurator=");
  369. if (pos) {
  370. auth->configurator = 1;
  371. pos += 14;
  372. conf = hostapd_dpp_configurator_get_id(hapd, atoi(pos));
  373. if (!conf) {
  374. wpa_printf(MSG_INFO,
  375. "DPP: Could not find the specified configurator");
  376. goto fail;
  377. }
  378. }
  379. auth->conf_sta = conf_sta;
  380. auth->conf_ap = conf_ap;
  381. auth->conf = conf;
  382. return;
  383. fail:
  384. wpa_printf(MSG_DEBUG, "DPP: Failed to set configurator parameters");
  385. dpp_configuration_free(conf_sta);
  386. dpp_configuration_free(conf_ap);
  387. }
  388. int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
  389. {
  390. const char *pos;
  391. struct dpp_bootstrap_info *peer_bi, *own_bi = NULL;
  392. const u8 *dst;
  393. int res;
  394. u8 allowed_roles = DPP_CAPAB_CONFIGURATOR;
  395. struct dpp_configuration *conf_sta = NULL, *conf_ap = NULL;
  396. pos = os_strstr(cmd, " peer=");
  397. if (!pos)
  398. return -1;
  399. pos += 6;
  400. peer_bi = dpp_bootstrap_get_id(hapd, atoi(pos));
  401. if (!peer_bi) {
  402. wpa_printf(MSG_INFO,
  403. "DPP: Could not find bootstrapping info for the identified peer");
  404. return -1;
  405. }
  406. pos = os_strstr(cmd, " own=");
  407. if (pos) {
  408. pos += 5;
  409. own_bi = dpp_bootstrap_get_id(hapd, atoi(pos));
  410. if (!own_bi) {
  411. wpa_printf(MSG_INFO,
  412. "DPP: Could not find bootstrapping info for the identified local entry");
  413. return -1;
  414. }
  415. if (peer_bi->curve != own_bi->curve) {
  416. wpa_printf(MSG_INFO,
  417. "DPP: Mismatching curves in bootstrapping info (peer=%s own=%s)",
  418. peer_bi->curve->name, own_bi->curve->name);
  419. return -1;
  420. }
  421. }
  422. pos = os_strstr(cmd, " role=");
  423. if (pos) {
  424. pos += 6;
  425. if (os_strncmp(pos, "configurator", 12) == 0)
  426. allowed_roles = DPP_CAPAB_CONFIGURATOR;
  427. else if (os_strncmp(pos, "enrollee", 8) == 0)
  428. allowed_roles = DPP_CAPAB_ENROLLEE;
  429. else if (os_strncmp(pos, "either", 6) == 0)
  430. allowed_roles = DPP_CAPAB_CONFIGURATOR |
  431. DPP_CAPAB_ENROLLEE;
  432. else
  433. goto fail;
  434. }
  435. if (hapd->dpp_auth)
  436. dpp_auth_deinit(hapd->dpp_auth);
  437. /* TODO: hw_modes */
  438. hapd->dpp_auth = dpp_auth_init(hapd->msg_ctx, peer_bi, own_bi,
  439. allowed_roles, 0, NULL, 0);
  440. if (!hapd->dpp_auth)
  441. goto fail;
  442. hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
  443. hostapd_dpp_set_configurator(hapd, hapd->dpp_auth, cmd);
  444. /* TODO: Support iteration over all frequencies and filtering of
  445. * frequencies based on locally enabled channels that allow initiation
  446. * of transmission. */
  447. if (is_zero_ether_addr(peer_bi->mac_addr)) {
  448. dst = broadcast;
  449. } else {
  450. dst = peer_bi->mac_addr;
  451. os_memcpy(hapd->dpp_auth->peer_mac_addr, peer_bi->mac_addr,
  452. ETH_ALEN);
  453. }
  454. hapd->dpp_auth_ok_on_ack = 0;
  455. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
  456. " freq=%u type=%d",
  457. MAC2STR(dst), hapd->dpp_auth->curr_freq,
  458. DPP_PA_AUTHENTICATION_REQ);
  459. res = hostapd_drv_send_action(hapd, hapd->dpp_auth->curr_freq, 0,
  460. dst, wpabuf_head(hapd->dpp_auth->req_msg),
  461. wpabuf_len(hapd->dpp_auth->req_msg));
  462. return res;
  463. fail:
  464. dpp_configuration_free(conf_sta);
  465. dpp_configuration_free(conf_ap);
  466. return -1;
  467. }
  468. int hostapd_dpp_listen(struct hostapd_data *hapd, const char *cmd)
  469. {
  470. int freq;
  471. freq = atoi(cmd);
  472. if (freq <= 0)
  473. return -1;
  474. if (os_strstr(cmd, " role=configurator"))
  475. hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR;
  476. else if (os_strstr(cmd, " role=enrollee"))
  477. hapd->dpp_allowed_roles = DPP_CAPAB_ENROLLEE;
  478. else
  479. hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR |
  480. DPP_CAPAB_ENROLLEE;
  481. hapd->dpp_qr_mutual = os_strstr(cmd, " qr=mutual") != NULL;
  482. if (freq != hapd->iface->freq && hapd->iface->freq > 0) {
  483. /* TODO: Listen operation on non-operating channel */
  484. wpa_printf(MSG_INFO,
  485. "DPP: Listen operation on non-operating channel (%d MHz) is not yet supported (operating channel: %d MHz)",
  486. freq, hapd->iface->freq);
  487. return -1;
  488. }
  489. return 0;
  490. }
  491. void hostapd_dpp_listen_stop(struct hostapd_data *hapd)
  492. {
  493. /* TODO: Stop listen operation on non-operating channel */
  494. }
  495. static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src,
  496. const u8 *hdr, const u8 *buf, size_t len,
  497. unsigned int freq)
  498. {
  499. const u8 *r_bootstrap, *i_bootstrap;
  500. u16 r_bootstrap_len, i_bootstrap_len;
  501. struct dpp_bootstrap_info *bi, *own_bi = NULL, *peer_bi = NULL;
  502. wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR,
  503. MAC2STR(src));
  504. r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
  505. &r_bootstrap_len);
  506. if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
  507. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
  508. "Missing or invalid required Responder Bootstrapping Key Hash attribute");
  509. return;
  510. }
  511. wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
  512. r_bootstrap, r_bootstrap_len);
  513. i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
  514. &i_bootstrap_len);
  515. if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
  516. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
  517. "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
  518. return;
  519. }
  520. wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
  521. i_bootstrap, i_bootstrap_len);
  522. /* Try to find own and peer bootstrapping key matches based on the
  523. * received hash values */
  524. dl_list_for_each(bi, &hapd->dpp_bootstrap, struct dpp_bootstrap_info,
  525. list) {
  526. if (!own_bi && bi->own &&
  527. os_memcmp(bi->pubkey_hash, r_bootstrap,
  528. SHA256_MAC_LEN) == 0) {
  529. wpa_printf(MSG_DEBUG,
  530. "DPP: Found matching own bootstrapping information");
  531. own_bi = bi;
  532. }
  533. if (!peer_bi && !bi->own &&
  534. os_memcmp(bi->pubkey_hash, i_bootstrap,
  535. SHA256_MAC_LEN) == 0) {
  536. wpa_printf(MSG_DEBUG,
  537. "DPP: Found matching peer bootstrapping information");
  538. peer_bi = bi;
  539. }
  540. if (own_bi && peer_bi)
  541. break;
  542. }
  543. if (!own_bi) {
  544. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
  545. "No matching own bootstrapping key found - ignore message");
  546. return;
  547. }
  548. if (hapd->dpp_auth) {
  549. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
  550. "Already in DPP authentication exchange - ignore new one");
  551. return;
  552. }
  553. hapd->dpp_auth_ok_on_ack = 0;
  554. hapd->dpp_auth = dpp_auth_req_rx(hapd->msg_ctx, hapd->dpp_allowed_roles,
  555. hapd->dpp_qr_mutual,
  556. peer_bi, own_bi, freq, hdr, buf, len);
  557. if (!hapd->dpp_auth) {
  558. wpa_printf(MSG_DEBUG, "DPP: No response generated");
  559. return;
  560. }
  561. hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
  562. hostapd_dpp_set_configurator(hapd, hapd->dpp_auth,
  563. hapd->dpp_configurator_params);
  564. os_memcpy(hapd->dpp_auth->peer_mac_addr, src, ETH_ALEN);
  565. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
  566. " freq=%u type=%d",
  567. MAC2STR(src), hapd->dpp_auth->curr_freq,
  568. DPP_PA_AUTHENTICATION_RESP);
  569. hostapd_drv_send_action(hapd, hapd->dpp_auth->curr_freq, 0,
  570. src, wpabuf_head(hapd->dpp_auth->resp_msg),
  571. wpabuf_len(hapd->dpp_auth->resp_msg));
  572. }
  573. static void hostapd_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
  574. enum gas_query_ap_result result,
  575. const struct wpabuf *adv_proto,
  576. const struct wpabuf *resp, u16 status_code)
  577. {
  578. struct hostapd_data *hapd = ctx;
  579. const u8 *pos;
  580. struct dpp_authentication *auth = hapd->dpp_auth;
  581. if (!auth || !auth->auth_success) {
  582. wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
  583. return;
  584. }
  585. if (!resp || status_code != WLAN_STATUS_SUCCESS) {
  586. wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
  587. goto fail;
  588. }
  589. wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response adv_proto",
  590. adv_proto);
  591. wpa_hexdump_buf(MSG_DEBUG, "DPP: Configuration Response (GAS response)",
  592. resp);
  593. if (wpabuf_len(adv_proto) != 10 ||
  594. !(pos = wpabuf_head(adv_proto)) ||
  595. pos[0] != WLAN_EID_ADV_PROTO ||
  596. pos[1] != 8 ||
  597. pos[3] != WLAN_EID_VENDOR_SPECIFIC ||
  598. pos[4] != 5 ||
  599. WPA_GET_BE24(&pos[5]) != OUI_WFA ||
  600. pos[8] != 0x1a ||
  601. pos[9] != 1) {
  602. wpa_printf(MSG_DEBUG,
  603. "DPP: Not a DPP Advertisement Protocol ID");
  604. goto fail;
  605. }
  606. if (dpp_conf_resp_rx(auth, resp) < 0) {
  607. wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
  608. goto fail;
  609. }
  610. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
  611. if (auth->ssid_len)
  612. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
  613. wpa_ssid_txt(auth->ssid, auth->ssid_len));
  614. if (auth->connector) {
  615. /* TODO: Save the Connector and consider using a command
  616. * to fetch the value instead of sending an event with
  617. * it. The Connector could end up being larger than what
  618. * most clients are ready to receive as an event
  619. * message. */
  620. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
  621. auth->connector);
  622. } else if (auth->passphrase[0]) {
  623. char hex[64 * 2 + 1];
  624. wpa_snprintf_hex(hex, sizeof(hex),
  625. (const u8 *) auth->passphrase,
  626. os_strlen(auth->passphrase));
  627. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
  628. hex);
  629. } else if (auth->psk_set) {
  630. char hex[PMK_LEN * 2 + 1];
  631. wpa_snprintf_hex(hex, sizeof(hex), auth->psk, PMK_LEN);
  632. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
  633. hex);
  634. }
  635. if (auth->c_sign_key) {
  636. char *hex;
  637. size_t hexlen;
  638. hexlen = 2 * wpabuf_len(auth->c_sign_key) + 1;
  639. hex = os_malloc(hexlen);
  640. if (hex) {
  641. wpa_snprintf_hex(hex, hexlen,
  642. wpabuf_head(auth->c_sign_key),
  643. wpabuf_len(auth->c_sign_key));
  644. wpa_msg(hapd->msg_ctx, MSG_INFO,
  645. DPP_EVENT_C_SIGN_KEY "%s", hex);
  646. os_free(hex);
  647. }
  648. }
  649. if (auth->net_access_key) {
  650. char *hex;
  651. size_t hexlen;
  652. hexlen = 2 * wpabuf_len(auth->net_access_key) + 1;
  653. hex = os_malloc(hexlen);
  654. if (hex) {
  655. wpa_snprintf_hex(hex, hexlen,
  656. wpabuf_head(auth->net_access_key),
  657. wpabuf_len(auth->net_access_key));
  658. if (auth->net_access_key_expiry)
  659. wpa_msg(hapd->msg_ctx, MSG_INFO,
  660. DPP_EVENT_NET_ACCESS_KEY "%s %lu", hex,
  661. (unsigned long)
  662. auth->net_access_key_expiry);
  663. else
  664. wpa_msg(hapd->msg_ctx, MSG_INFO,
  665. DPP_EVENT_NET_ACCESS_KEY "%s", hex);
  666. os_free(hex);
  667. }
  668. }
  669. dpp_auth_deinit(hapd->dpp_auth);
  670. hapd->dpp_auth = NULL;
  671. return;
  672. fail:
  673. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
  674. dpp_auth_deinit(hapd->dpp_auth);
  675. hapd->dpp_auth = NULL;
  676. }
  677. static void hostapd_dpp_start_gas_client(struct hostapd_data *hapd)
  678. {
  679. struct dpp_authentication *auth = hapd->dpp_auth;
  680. struct wpabuf *buf, *conf_req;
  681. char json[100];
  682. int res;
  683. int netrole_ap = 1;
  684. os_snprintf(json, sizeof(json),
  685. "{\"name\":\"Test\","
  686. "\"wi-fi_tech\":\"infra\","
  687. "\"netRole\":\"%s\"}",
  688. netrole_ap ? "ap" : "sta");
  689. wpa_printf(MSG_DEBUG, "DPP: GAS Config Attributes: %s", json);
  690. conf_req = dpp_build_conf_req(auth, json);
  691. if (!conf_req) {
  692. wpa_printf(MSG_DEBUG,
  693. "DPP: No configuration request data available");
  694. return;
  695. }
  696. buf = gas_build_initial_req(0, 10 + 2 + wpabuf_len(conf_req));
  697. if (!buf) {
  698. wpabuf_free(conf_req);
  699. return;
  700. }
  701. /* Advertisement Protocol IE */
  702. wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO);
  703. wpabuf_put_u8(buf, 8); /* Length */
  704. wpabuf_put_u8(buf, 0x7f);
  705. wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
  706. wpabuf_put_u8(buf, 5);
  707. wpabuf_put_be24(buf, OUI_WFA);
  708. wpabuf_put_u8(buf, DPP_OUI_TYPE);
  709. wpabuf_put_u8(buf, 0x01);
  710. /* GAS Query */
  711. wpabuf_put_le16(buf, wpabuf_len(conf_req));
  712. wpabuf_put_buf(buf, conf_req);
  713. wpabuf_free(conf_req);
  714. wpa_printf(MSG_DEBUG, "DPP: GAS request to " MACSTR " (freq %u MHz)",
  715. MAC2STR(auth->peer_mac_addr), auth->curr_freq);
  716. res = gas_query_ap_req(hapd->gas, auth->peer_mac_addr, auth->curr_freq,
  717. buf, hostapd_dpp_gas_resp_cb, hapd);
  718. if (res < 0) {
  719. wpa_msg(hapd->msg_ctx, MSG_DEBUG,
  720. "GAS: Failed to send Query Request");
  721. wpabuf_free(buf);
  722. } else {
  723. wpa_printf(MSG_DEBUG,
  724. "DPP: GAS query started with dialog token %u", res);
  725. }
  726. }
  727. static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator)
  728. {
  729. wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
  730. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_SUCCESS "init=%d",
  731. initiator);
  732. if (!hapd->dpp_auth->configurator)
  733. hostapd_dpp_start_gas_client(hapd);
  734. }
  735. static void hostapd_dpp_rx_auth_resp(struct hostapd_data *hapd, const u8 *src,
  736. const u8 *hdr, const u8 *buf, size_t len)
  737. {
  738. struct dpp_authentication *auth = hapd->dpp_auth;
  739. struct wpabuf *msg;
  740. wpa_printf(MSG_DEBUG, "DPP: Authentication Response from " MACSTR,
  741. MAC2STR(src));
  742. if (!auth) {
  743. wpa_printf(MSG_DEBUG,
  744. "DPP: No DPP Authentication in progress - drop");
  745. return;
  746. }
  747. if (!is_zero_ether_addr(auth->peer_mac_addr) &&
  748. os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
  749. wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
  750. MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
  751. return;
  752. }
  753. msg = dpp_auth_resp_rx(auth, hdr, buf, len);
  754. if (!msg) {
  755. if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
  756. wpa_printf(MSG_DEBUG, "DPP: Wait for full response");
  757. return;
  758. }
  759. wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
  760. return;
  761. }
  762. os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
  763. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
  764. " freq=%u type=%d", MAC2STR(src), auth->curr_freq,
  765. DPP_PA_AUTHENTICATION_CONF);
  766. hostapd_drv_send_action(hapd, auth->curr_freq, 0, src,
  767. wpabuf_head(msg), wpabuf_len(msg));
  768. wpabuf_free(msg);
  769. hapd->dpp_auth_ok_on_ack = 1;
  770. }
  771. static void hostapd_dpp_rx_auth_conf(struct hostapd_data *hapd, const u8 *src,
  772. const u8 *hdr, const u8 *buf, size_t len)
  773. {
  774. struct dpp_authentication *auth = hapd->dpp_auth;
  775. wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation from " MACSTR,
  776. MAC2STR(src));
  777. if (!auth) {
  778. wpa_printf(MSG_DEBUG,
  779. "DPP: No DPP Authentication in progress - drop");
  780. return;
  781. }
  782. if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
  783. wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected "
  784. MACSTR ") - drop", MAC2STR(auth->peer_mac_addr));
  785. return;
  786. }
  787. if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
  788. wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
  789. return;
  790. }
  791. hostapd_dpp_auth_success(hapd, 0);
  792. }
  793. static void hostapd_dpp_send_peer_disc_resp(struct hostapd_data *hapd,
  794. const u8 *src, unsigned int freq,
  795. u8 trans_id,
  796. enum dpp_status_error status)
  797. {
  798. struct wpabuf *msg;
  799. msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_RESP,
  800. 5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector));
  801. if (!msg)
  802. return;
  803. #ifdef CONFIG_TESTING_OPTIONS
  804. if (dpp_test == DPP_TEST_NO_TRANSACTION_ID_PEER_DISC_RESP) {
  805. wpa_printf(MSG_INFO, "DPP: TESTING - no Transaction ID");
  806. goto skip_trans_id;
  807. }
  808. #endif /* CONFIG_TESTING_OPTIONS */
  809. /* Transaction ID */
  810. wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID);
  811. wpabuf_put_le16(msg, 1);
  812. wpabuf_put_u8(msg, trans_id);
  813. #ifdef CONFIG_TESTING_OPTIONS
  814. skip_trans_id:
  815. if (dpp_test == DPP_TEST_NO_STATUS_PEER_DISC_RESP) {
  816. wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
  817. goto skip_status;
  818. }
  819. #endif /* CONFIG_TESTING_OPTIONS */
  820. /* DPP Status */
  821. wpabuf_put_le16(msg, DPP_ATTR_STATUS);
  822. wpabuf_put_le16(msg, 1);
  823. wpabuf_put_u8(msg, status);
  824. #ifdef CONFIG_TESTING_OPTIONS
  825. skip_status:
  826. if (dpp_test == DPP_TEST_NO_CONNECTOR_PEER_DISC_RESP) {
  827. wpa_printf(MSG_INFO, "DPP: TESTING - no Connector");
  828. goto skip_connector;
  829. }
  830. #endif /* CONFIG_TESTING_OPTIONS */
  831. /* DPP Connector */
  832. if (status == DPP_STATUS_OK) {
  833. wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR);
  834. wpabuf_put_le16(msg, os_strlen(hapd->conf->dpp_connector));
  835. wpabuf_put_str(msg, hapd->conf->dpp_connector);
  836. }
  837. #ifdef CONFIG_TESTING_OPTIONS
  838. skip_connector:
  839. #endif /* CONFIG_TESTING_OPTIONS */
  840. wpa_printf(MSG_DEBUG, "DPP: Send Peer Discovery Response to " MACSTR
  841. " status=%d", MAC2STR(src), status);
  842. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
  843. " freq=%u type=%d status=%d", MAC2STR(src), freq,
  844. DPP_PA_PEER_DISCOVERY_RESP, status);
  845. hostapd_drv_send_action(hapd, freq, 0, src,
  846. wpabuf_head(msg), wpabuf_len(msg));
  847. wpabuf_free(msg);
  848. }
  849. static void hostapd_dpp_rx_peer_disc_req(struct hostapd_data *hapd,
  850. const u8 *src,
  851. const u8 *buf, size_t len,
  852. unsigned int freq)
  853. {
  854. const u8 *connector, *trans_id;
  855. u16 connector_len, trans_id_len;
  856. struct os_time now;
  857. struct dpp_introduction intro;
  858. os_time_t expire;
  859. int expiration;
  860. enum dpp_status_error res;
  861. wpa_printf(MSG_DEBUG, "DPP: Peer Discovery Request from " MACSTR,
  862. MAC2STR(src));
  863. if (!hapd->wpa_auth ||
  864. !(hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) ||
  865. !(hapd->conf->wpa & WPA_PROTO_RSN)) {
  866. wpa_printf(MSG_DEBUG, "DPP: DPP AKM not in use");
  867. return;
  868. }
  869. if (!hapd->conf->dpp_connector || !hapd->conf->dpp_netaccesskey ||
  870. !hapd->conf->dpp_csign) {
  871. wpa_printf(MSG_DEBUG, "DPP: No own Connector/keys set");
  872. return;
  873. }
  874. os_get_time(&now);
  875. if (hapd->conf->dpp_netaccesskey_expiry &&
  876. hapd->conf->dpp_netaccesskey_expiry < now.sec) {
  877. wpa_printf(MSG_INFO, "DPP: Own netAccessKey expired");
  878. return;
  879. }
  880. trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID,
  881. &trans_id_len);
  882. if (!trans_id || trans_id_len != 1) {
  883. wpa_printf(MSG_DEBUG,
  884. "DPP: Peer did not include Transaction ID");
  885. return;
  886. }
  887. connector = dpp_get_attr(buf, len, DPP_ATTR_CONNECTOR, &connector_len);
  888. if (!connector) {
  889. wpa_printf(MSG_DEBUG,
  890. "DPP: Peer did not include its Connector");
  891. return;
  892. }
  893. res = dpp_peer_intro(&intro, hapd->conf->dpp_connector,
  894. wpabuf_head(hapd->conf->dpp_netaccesskey),
  895. wpabuf_len(hapd->conf->dpp_netaccesskey),
  896. wpabuf_head(hapd->conf->dpp_csign),
  897. wpabuf_len(hapd->conf->dpp_csign),
  898. connector, connector_len, &expire);
  899. if (res == 255) {
  900. wpa_printf(MSG_INFO,
  901. "DPP: Network Introduction protocol resulted in internal failure (peer "
  902. MACSTR ")", MAC2STR(src));
  903. return;
  904. }
  905. if (res != DPP_STATUS_OK) {
  906. wpa_printf(MSG_INFO,
  907. "DPP: Network Introduction protocol resulted in failure (peer "
  908. MACSTR " status %d)", MAC2STR(src), res);
  909. hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
  910. res);
  911. return;
  912. }
  913. if (!expire || hapd->conf->dpp_netaccesskey_expiry < expire)
  914. expire = hapd->conf->dpp_netaccesskey_expiry;
  915. if (expire)
  916. expiration = expire - now.sec;
  917. else
  918. expiration = 0;
  919. if (wpa_auth_pmksa_add2(hapd->wpa_auth, src, intro.pmk, intro.pmk_len,
  920. intro.pmkid, expiration,
  921. WPA_KEY_MGMT_DPP) < 0) {
  922. wpa_printf(MSG_ERROR, "DPP: Failed to add PMKSA cache entry");
  923. return;
  924. }
  925. hostapd_dpp_send_peer_disc_resp(hapd, src, freq, trans_id[0],
  926. DPP_STATUS_OK);
  927. }
  928. static void
  929. hostapd_dpp_rx_pkex_exchange_req(struct hostapd_data *hapd, const u8 *src,
  930. const u8 *buf, size_t len,
  931. unsigned int freq)
  932. {
  933. struct wpabuf *msg;
  934. wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request from " MACSTR,
  935. MAC2STR(src));
  936. /* TODO: Support multiple PKEX codes by iterating over all the enabled
  937. * values here */
  938. if (!hapd->dpp_pkex_code || !hapd->dpp_pkex_bi) {
  939. wpa_printf(MSG_DEBUG,
  940. "DPP: No PKEX code configured - ignore request");
  941. return;
  942. }
  943. if (hapd->dpp_pkex) {
  944. /* TODO: Support parallel operations */
  945. wpa_printf(MSG_DEBUG,
  946. "DPP: Already in PKEX session - ignore new request");
  947. return;
  948. }
  949. hapd->dpp_pkex = dpp_pkex_rx_exchange_req(hapd->msg_ctx,
  950. hapd->dpp_pkex_bi,
  951. hapd->own_addr, src,
  952. hapd->dpp_pkex_identifier,
  953. hapd->dpp_pkex_code,
  954. buf, len);
  955. if (!hapd->dpp_pkex) {
  956. wpa_printf(MSG_DEBUG,
  957. "DPP: Failed to process the request - ignore it");
  958. return;
  959. }
  960. msg = hapd->dpp_pkex->exchange_resp;
  961. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
  962. " freq=%u type=%d", MAC2STR(src), freq,
  963. DPP_PA_PKEX_EXCHANGE_RESP);
  964. hostapd_drv_send_action(hapd, freq, 0, src,
  965. wpabuf_head(msg), wpabuf_len(msg));
  966. if (hapd->dpp_pkex->failed) {
  967. wpa_printf(MSG_DEBUG,
  968. "DPP: Terminate PKEX exchange due to an earlier error");
  969. if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t)
  970. hapd->dpp_pkex->own_bi->pkex_t = hapd->dpp_pkex->t;
  971. dpp_pkex_free(hapd->dpp_pkex);
  972. hapd->dpp_pkex = NULL;
  973. }
  974. }
  975. static void
  976. hostapd_dpp_rx_pkex_exchange_resp(struct hostapd_data *hapd, const u8 *src,
  977. const u8 *buf, size_t len, unsigned int freq)
  978. {
  979. struct wpabuf *msg;
  980. wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response from " MACSTR,
  981. MAC2STR(src));
  982. /* TODO: Support multiple PKEX codes by iterating over all the enabled
  983. * values here */
  984. if (!hapd->dpp_pkex || !hapd->dpp_pkex->initiator ||
  985. hapd->dpp_pkex->exchange_done) {
  986. wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
  987. return;
  988. }
  989. os_memcpy(hapd->dpp_pkex->peer_mac, src, ETH_ALEN);
  990. msg = dpp_pkex_rx_exchange_resp(hapd->dpp_pkex, buf, len);
  991. if (!msg) {
  992. wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
  993. return;
  994. }
  995. wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request to " MACSTR,
  996. MAC2STR(src));
  997. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
  998. " freq=%u type=%d", MAC2STR(src), freq,
  999. DPP_PA_PKEX_COMMIT_REVEAL_REQ);
  1000. hostapd_drv_send_action(hapd, freq, 0, src,
  1001. wpabuf_head(msg), wpabuf_len(msg));
  1002. wpabuf_free(msg);
  1003. }
  1004. static void
  1005. hostapd_dpp_rx_pkex_commit_reveal_req(struct hostapd_data *hapd, const u8 *src,
  1006. const u8 *hdr, const u8 *buf, size_t len,
  1007. unsigned int freq)
  1008. {
  1009. struct wpabuf *msg;
  1010. struct dpp_pkex *pkex = hapd->dpp_pkex;
  1011. struct dpp_bootstrap_info *bi;
  1012. wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request from " MACSTR,
  1013. MAC2STR(src));
  1014. if (!pkex || pkex->initiator || !pkex->exchange_done) {
  1015. wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
  1016. return;
  1017. }
  1018. msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
  1019. if (!msg) {
  1020. wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
  1021. if (hapd->dpp_pkex->failed) {
  1022. wpa_printf(MSG_DEBUG, "DPP: Terminate PKEX exchange");
  1023. if (hapd->dpp_pkex->t > hapd->dpp_pkex->own_bi->pkex_t)
  1024. hapd->dpp_pkex->own_bi->pkex_t =
  1025. hapd->dpp_pkex->t;
  1026. dpp_pkex_free(hapd->dpp_pkex);
  1027. hapd->dpp_pkex = NULL;
  1028. }
  1029. return;
  1030. }
  1031. wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response to "
  1032. MACSTR, MAC2STR(src));
  1033. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
  1034. " freq=%u type=%d", MAC2STR(src), freq,
  1035. DPP_PA_PKEX_COMMIT_REVEAL_RESP);
  1036. hostapd_drv_send_action(hapd, freq, 0, src,
  1037. wpabuf_head(msg), wpabuf_len(msg));
  1038. wpabuf_free(msg);
  1039. bi = os_zalloc(sizeof(*bi));
  1040. if (!bi)
  1041. return;
  1042. bi->id = hapd_dpp_next_id(hapd);
  1043. bi->type = DPP_BOOTSTRAP_PKEX;
  1044. os_memcpy(bi->mac_addr, src, ETH_ALEN);
  1045. bi->num_freq = 1;
  1046. bi->freq[0] = freq;
  1047. bi->curve = pkex->own_bi->curve;
  1048. bi->pubkey = pkex->peer_bootstrap_key;
  1049. pkex->peer_bootstrap_key = NULL;
  1050. dpp_pkex_free(pkex);
  1051. hapd->dpp_pkex = NULL;
  1052. if (dpp_bootstrap_key_hash(bi) < 0) {
  1053. dpp_bootstrap_info_free(bi);
  1054. return;
  1055. }
  1056. dl_list_add(&hapd->dpp_bootstrap, &bi->list);
  1057. }
  1058. static void
  1059. hostapd_dpp_rx_pkex_commit_reveal_resp(struct hostapd_data *hapd, const u8 *src,
  1060. const u8 *hdr, const u8 *buf, size_t len,
  1061. unsigned int freq)
  1062. {
  1063. int res;
  1064. struct dpp_bootstrap_info *bi, *own_bi;
  1065. struct dpp_pkex *pkex = hapd->dpp_pkex;
  1066. char cmd[500];
  1067. wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response from " MACSTR,
  1068. MAC2STR(src));
  1069. if (!pkex || !pkex->initiator || !pkex->exchange_done) {
  1070. wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
  1071. return;
  1072. }
  1073. res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
  1074. if (res < 0) {
  1075. wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
  1076. return;
  1077. }
  1078. own_bi = pkex->own_bi;
  1079. bi = os_zalloc(sizeof(*bi));
  1080. if (!bi)
  1081. return;
  1082. bi->id = hapd_dpp_next_id(hapd);
  1083. bi->type = DPP_BOOTSTRAP_PKEX;
  1084. os_memcpy(bi->mac_addr, src, ETH_ALEN);
  1085. bi->num_freq = 1;
  1086. bi->freq[0] = freq;
  1087. bi->curve = own_bi->curve;
  1088. bi->pubkey = pkex->peer_bootstrap_key;
  1089. pkex->peer_bootstrap_key = NULL;
  1090. dpp_pkex_free(pkex);
  1091. hapd->dpp_pkex = NULL;
  1092. if (dpp_bootstrap_key_hash(bi) < 0) {
  1093. dpp_bootstrap_info_free(bi);
  1094. return;
  1095. }
  1096. dl_list_add(&hapd->dpp_bootstrap, &bi->list);
  1097. os_snprintf(cmd, sizeof(cmd), " peer=%u %s",
  1098. bi->id,
  1099. hapd->dpp_pkex_auth_cmd ? hapd->dpp_pkex_auth_cmd : "");
  1100. wpa_printf(MSG_DEBUG,
  1101. "DPP: Start authentication after PKEX with parameters: %s",
  1102. cmd);
  1103. if (hostapd_dpp_auth_init(hapd, cmd) < 0) {
  1104. wpa_printf(MSG_DEBUG,
  1105. "DPP: Authentication initialization failed");
  1106. return;
  1107. }
  1108. }
  1109. void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src,
  1110. const u8 *buf, size_t len, unsigned int freq)
  1111. {
  1112. u8 crypto_suite;
  1113. enum dpp_public_action_frame_type type;
  1114. const u8 *hdr;
  1115. unsigned int pkex_t;
  1116. if (len < DPP_HDR_LEN)
  1117. return;
  1118. if (WPA_GET_BE24(buf) != OUI_WFA || buf[3] != DPP_OUI_TYPE)
  1119. return;
  1120. hdr = buf;
  1121. buf += 4;
  1122. len -= 4;
  1123. crypto_suite = *buf++;
  1124. type = *buf++;
  1125. len -= 2;
  1126. wpa_printf(MSG_DEBUG,
  1127. "DPP: Received DPP Public Action frame crypto suite %u type %d from "
  1128. MACSTR " freq=%u",
  1129. crypto_suite, type, MAC2STR(src), freq);
  1130. if (crypto_suite != 1) {
  1131. wpa_printf(MSG_DEBUG, "DPP: Unsupported crypto suite %u",
  1132. crypto_suite);
  1133. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
  1134. " freq=%u type=%d ignore=unsupported-crypto-suite",
  1135. MAC2STR(src), freq, type);
  1136. return;
  1137. }
  1138. wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", buf, len);
  1139. if (dpp_check_attrs(buf, len) < 0) {
  1140. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
  1141. " freq=%u type=%d ignore=invalid-attributes",
  1142. MAC2STR(src), freq, type);
  1143. return;
  1144. }
  1145. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_RX "src=" MACSTR
  1146. " freq=%u type=%d", MAC2STR(src), freq, type);
  1147. switch (type) {
  1148. case DPP_PA_AUTHENTICATION_REQ:
  1149. hostapd_dpp_rx_auth_req(hapd, src, hdr, buf, len, freq);
  1150. break;
  1151. case DPP_PA_AUTHENTICATION_RESP:
  1152. hostapd_dpp_rx_auth_resp(hapd, src, hdr, buf, len);
  1153. break;
  1154. case DPP_PA_AUTHENTICATION_CONF:
  1155. hostapd_dpp_rx_auth_conf(hapd, src, hdr, buf, len);
  1156. break;
  1157. case DPP_PA_PEER_DISCOVERY_REQ:
  1158. hostapd_dpp_rx_peer_disc_req(hapd, src, buf, len, freq);
  1159. break;
  1160. case DPP_PA_PKEX_EXCHANGE_REQ:
  1161. hostapd_dpp_rx_pkex_exchange_req(hapd, src, buf, len, freq);
  1162. break;
  1163. case DPP_PA_PKEX_EXCHANGE_RESP:
  1164. hostapd_dpp_rx_pkex_exchange_resp(hapd, src, buf, len, freq);
  1165. break;
  1166. case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
  1167. hostapd_dpp_rx_pkex_commit_reveal_req(hapd, src, hdr, buf, len,
  1168. freq);
  1169. break;
  1170. case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
  1171. hostapd_dpp_rx_pkex_commit_reveal_resp(hapd, src, hdr, buf, len,
  1172. freq);
  1173. break;
  1174. default:
  1175. wpa_printf(MSG_DEBUG,
  1176. "DPP: Ignored unsupported frame subtype %d", type);
  1177. break;
  1178. }
  1179. if (hapd->dpp_pkex)
  1180. pkex_t = hapd->dpp_pkex->t;
  1181. else if (hapd->dpp_pkex_bi)
  1182. pkex_t = hapd->dpp_pkex_bi->pkex_t;
  1183. else
  1184. pkex_t = 0;
  1185. if (pkex_t >= PKEX_COUNTER_T_LIMIT) {
  1186. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_PKEX_T_LIMIT "id=0");
  1187. hostapd_dpp_pkex_remove(hapd, "*");
  1188. }
  1189. }
  1190. struct wpabuf *
  1191. hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa,
  1192. const u8 *query, size_t query_len)
  1193. {
  1194. struct dpp_authentication *auth = hapd->dpp_auth;
  1195. struct wpabuf *resp;
  1196. wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa));
  1197. if (!auth || !auth->auth_success ||
  1198. os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) {
  1199. wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
  1200. return NULL;
  1201. }
  1202. wpa_hexdump(MSG_DEBUG,
  1203. "DPP: Received Configuration Request (GAS Query Request)",
  1204. query, query_len);
  1205. resp = dpp_conf_req_rx(auth, query, query_len);
  1206. if (!resp)
  1207. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
  1208. return resp;
  1209. }
  1210. static unsigned int hostapd_dpp_next_configurator_id(struct hostapd_data *hapd)
  1211. {
  1212. struct dpp_configurator *conf;
  1213. unsigned int max_id = 0;
  1214. dl_list_for_each(conf, &hapd->dpp_configurator,
  1215. struct dpp_configurator, list) {
  1216. if (conf->id > max_id)
  1217. max_id = conf->id;
  1218. }
  1219. return max_id + 1;
  1220. }
  1221. int hostapd_dpp_configurator_add(struct hostapd_data *hapd, const char *cmd)
  1222. {
  1223. char *curve = NULL;
  1224. char *key = NULL;
  1225. u8 *privkey = NULL;
  1226. size_t privkey_len = 0;
  1227. int ret = -1;
  1228. struct dpp_configurator *conf = NULL;
  1229. curve = get_param(cmd, " curve=");
  1230. key = get_param(cmd, " key=");
  1231. if (key) {
  1232. privkey_len = os_strlen(key) / 2;
  1233. privkey = os_malloc(privkey_len);
  1234. if (!privkey ||
  1235. hexstr2bin(key, privkey, privkey_len) < 0)
  1236. goto fail;
  1237. }
  1238. conf = dpp_keygen_configurator(curve, privkey, privkey_len);
  1239. if (!conf)
  1240. goto fail;
  1241. conf->id = hostapd_dpp_next_configurator_id(hapd);
  1242. dl_list_add(&hapd->dpp_configurator, &conf->list);
  1243. ret = conf->id;
  1244. conf = NULL;
  1245. fail:
  1246. os_free(curve);
  1247. str_clear_free(key);
  1248. bin_clear_free(privkey, privkey_len);
  1249. dpp_configurator_free(conf);
  1250. return ret;
  1251. }
  1252. static int dpp_configurator_del(struct hostapd_data *hapd, unsigned int id)
  1253. {
  1254. struct dpp_configurator *conf, *tmp;
  1255. int found = 0;
  1256. dl_list_for_each_safe(conf, tmp, &hapd->dpp_configurator,
  1257. struct dpp_configurator, list) {
  1258. if (id && conf->id != id)
  1259. continue;
  1260. found = 1;
  1261. dl_list_del(&conf->list);
  1262. dpp_configurator_free(conf);
  1263. }
  1264. if (id == 0)
  1265. return 0; /* flush succeeds regardless of entries found */
  1266. return found ? 0 : -1;
  1267. }
  1268. int hostapd_dpp_configurator_remove(struct hostapd_data *hapd, const char *id)
  1269. {
  1270. unsigned int id_val;
  1271. if (os_strcmp(id, "*") == 0) {
  1272. id_val = 0;
  1273. } else {
  1274. id_val = atoi(id);
  1275. if (id_val == 0)
  1276. return -1;
  1277. }
  1278. return dpp_configurator_del(hapd, id_val);
  1279. }
  1280. int hostapd_dpp_pkex_add(struct hostapd_data *hapd, const char *cmd)
  1281. {
  1282. struct dpp_bootstrap_info *own_bi;
  1283. const char *pos, *end;
  1284. pos = os_strstr(cmd, " own=");
  1285. if (!pos)
  1286. return -1;
  1287. pos += 5;
  1288. own_bi = dpp_bootstrap_get_id(hapd, atoi(pos));
  1289. if (!own_bi) {
  1290. wpa_printf(MSG_DEBUG,
  1291. "DPP: Identified bootstrap info not found");
  1292. return -1;
  1293. }
  1294. if (own_bi->type != DPP_BOOTSTRAP_PKEX) {
  1295. wpa_printf(MSG_DEBUG,
  1296. "DPP: Identified bootstrap info not for PKEX");
  1297. return -1;
  1298. }
  1299. hapd->dpp_pkex_bi = own_bi;
  1300. own_bi->pkex_t = 0; /* clear pending errors on new code */
  1301. os_free(hapd->dpp_pkex_identifier);
  1302. hapd->dpp_pkex_identifier = NULL;
  1303. pos = os_strstr(cmd, " identifier=");
  1304. if (pos) {
  1305. pos += 12;
  1306. end = os_strchr(pos, ' ');
  1307. if (!end)
  1308. return -1;
  1309. hapd->dpp_pkex_identifier = os_malloc(end - pos + 1);
  1310. if (!hapd->dpp_pkex_identifier)
  1311. return -1;
  1312. os_memcpy(hapd->dpp_pkex_identifier, pos, end - pos);
  1313. hapd->dpp_pkex_identifier[end - pos] = '\0';
  1314. }
  1315. pos = os_strstr(cmd, " code=");
  1316. if (!pos)
  1317. return -1;
  1318. os_free(hapd->dpp_pkex_code);
  1319. hapd->dpp_pkex_code = os_strdup(pos + 6);
  1320. if (!hapd->dpp_pkex_code)
  1321. return -1;
  1322. if (os_strstr(cmd, " init=1")) {
  1323. struct wpabuf *msg;
  1324. wpa_printf(MSG_DEBUG, "DPP: Initiating PKEX");
  1325. dpp_pkex_free(hapd->dpp_pkex);
  1326. hapd->dpp_pkex = dpp_pkex_init(hapd->msg_ctx, own_bi,
  1327. hapd->own_addr,
  1328. hapd->dpp_pkex_identifier,
  1329. hapd->dpp_pkex_code);
  1330. if (!hapd->dpp_pkex)
  1331. return -1;
  1332. msg = hapd->dpp_pkex->exchange_req;
  1333. /* TODO: Which channel to use? */
  1334. wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
  1335. " freq=%u type=%d", MAC2STR(broadcast), 2437,
  1336. DPP_PA_PKEX_EXCHANGE_REQ);
  1337. hostapd_drv_send_action(hapd, 2437, 0, broadcast,
  1338. wpabuf_head(msg), wpabuf_len(msg));
  1339. }
  1340. /* TODO: Support multiple PKEX info entries */
  1341. os_free(hapd->dpp_pkex_auth_cmd);
  1342. hapd->dpp_pkex_auth_cmd = os_strdup(cmd);
  1343. return 1;
  1344. }
  1345. int hostapd_dpp_pkex_remove(struct hostapd_data *hapd, const char *id)
  1346. {
  1347. unsigned int id_val;
  1348. if (os_strcmp(id, "*") == 0) {
  1349. id_val = 0;
  1350. } else {
  1351. id_val = atoi(id);
  1352. if (id_val == 0)
  1353. return -1;
  1354. }
  1355. if ((id_val != 0 && id_val != 1) || !hapd->dpp_pkex_code)
  1356. return -1;
  1357. /* TODO: Support multiple PKEX entries */
  1358. os_free(hapd->dpp_pkex_code);
  1359. hapd->dpp_pkex_code = NULL;
  1360. os_free(hapd->dpp_pkex_identifier);
  1361. hapd->dpp_pkex_identifier = NULL;
  1362. os_free(hapd->dpp_pkex_auth_cmd);
  1363. hapd->dpp_pkex_auth_cmd = NULL;
  1364. hapd->dpp_pkex_bi = NULL;
  1365. /* TODO: Remove dpp_pkex only if it is for the identified PKEX code */
  1366. dpp_pkex_free(hapd->dpp_pkex);
  1367. hapd->dpp_pkex = NULL;
  1368. return 0;
  1369. }
  1370. int hostapd_dpp_init(struct hostapd_data *hapd)
  1371. {
  1372. dl_list_init(&hapd->dpp_bootstrap);
  1373. dl_list_init(&hapd->dpp_configurator);
  1374. hapd->dpp_allowed_roles = DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE;
  1375. hapd->dpp_init_done = 1;
  1376. return 0;
  1377. }
  1378. void hostapd_dpp_deinit(struct hostapd_data *hapd)
  1379. {
  1380. #ifdef CONFIG_TESTING_OPTIONS
  1381. os_free(hapd->dpp_config_obj_override);
  1382. hapd->dpp_config_obj_override = NULL;
  1383. os_free(hapd->dpp_discovery_override);
  1384. hapd->dpp_discovery_override = NULL;
  1385. os_free(hapd->dpp_groups_override);
  1386. hapd->dpp_groups_override = NULL;
  1387. hapd->dpp_ignore_netaccesskey_mismatch = 0;
  1388. #endif /* CONFIG_TESTING_OPTIONS */
  1389. if (!hapd->dpp_init_done)
  1390. return;
  1391. dpp_bootstrap_del(hapd, 0);
  1392. dpp_configurator_del(hapd, 0);
  1393. dpp_auth_deinit(hapd->dpp_auth);
  1394. hapd->dpp_auth = NULL;
  1395. hostapd_dpp_pkex_remove(hapd, "*");
  1396. hapd->dpp_pkex = NULL;
  1397. os_free(hapd->dpp_configurator_params);
  1398. hapd->dpp_configurator_params = NULL;
  1399. }