dpp_supplicant.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /*
  2. * wpa_supplicant - DPP
  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 "common/dpp.h"
  11. #include "wpa_supplicant_i.h"
  12. #include "dpp_supplicant.h"
  13. static unsigned int wpas_dpp_next_id(struct wpa_supplicant *wpa_s)
  14. {
  15. struct dpp_bootstrap_info *bi;
  16. unsigned int max_id = 0;
  17. dl_list_for_each(bi, &wpa_s->dpp_bootstrap, struct dpp_bootstrap_info,
  18. list) {
  19. if (bi->id > max_id)
  20. max_id = bi->id;
  21. }
  22. return max_id + 1;
  23. }
  24. /**
  25. * wpas_dpp_qr_code - Parse and add DPP bootstrapping info from a QR Code
  26. * @wpa_s: Pointer to wpa_supplicant data
  27. * @cmd: DPP URI read from a QR Code
  28. * Returns: Identifier of the stored info or -1 on failure
  29. */
  30. int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd)
  31. {
  32. struct dpp_bootstrap_info *bi;
  33. bi = dpp_parse_qr_code(cmd);
  34. if (!bi)
  35. return -1;
  36. bi->id = wpas_dpp_next_id(wpa_s);
  37. dl_list_add(&wpa_s->dpp_bootstrap, &bi->list);
  38. return bi->id;
  39. }
  40. static char * get_param(const char *cmd, const char *param)
  41. {
  42. const char *pos, *end;
  43. char *val;
  44. size_t len;
  45. pos = os_strstr(cmd, param);
  46. if (!pos)
  47. return NULL;
  48. pos += os_strlen(param);
  49. end = os_strchr(pos, ' ');
  50. if (end)
  51. len = end - pos;
  52. else
  53. len = os_strlen(pos);
  54. val = os_malloc(len + 1);
  55. if (!val)
  56. return NULL;
  57. os_memcpy(val, pos, len);
  58. val[len] = '\0';
  59. return val;
  60. }
  61. int wpas_dpp_bootstrap_gen(struct wpa_supplicant *wpa_s, const char *cmd)
  62. {
  63. char *chan = NULL, *mac = NULL, *info = NULL, *pk = NULL, *curve = NULL;
  64. char *key = NULL;
  65. u8 *privkey = NULL;
  66. size_t privkey_len = 0;
  67. size_t len;
  68. int ret = -1;
  69. struct dpp_bootstrap_info *bi;
  70. bi = os_zalloc(sizeof(*bi));
  71. if (!bi)
  72. goto fail;
  73. if (os_strstr(cmd, "type=qrcode"))
  74. bi->type = DPP_BOOTSTRAP_QR_CODE;
  75. else
  76. goto fail;
  77. chan = get_param(cmd, " chan=");
  78. mac = get_param(cmd, " mac=");
  79. info = get_param(cmd, " info=");
  80. curve = get_param(cmd, " curve=");
  81. key = get_param(cmd, " key=");
  82. if (key) {
  83. privkey_len = os_strlen(key) / 2;
  84. privkey = os_malloc(privkey_len);
  85. if (!privkey ||
  86. hexstr2bin(key, privkey, privkey_len) < 0)
  87. goto fail;
  88. }
  89. pk = dpp_keygen(bi, curve, privkey, privkey_len);
  90. if (!pk)
  91. goto fail;
  92. len = 4; /* "DPP:" */
  93. if (chan) {
  94. if (dpp_parse_uri_chan_list(bi, chan) < 0)
  95. goto fail;
  96. len += 3 + os_strlen(chan); /* C:...; */
  97. }
  98. if (mac) {
  99. if (dpp_parse_uri_mac(bi, mac) < 0)
  100. goto fail;
  101. len += 3 + os_strlen(mac); /* M:...; */
  102. }
  103. if (info) {
  104. if (dpp_parse_uri_info(bi, info) < 0)
  105. goto fail;
  106. len += 3 + os_strlen(info); /* I:...; */
  107. }
  108. len += 4 + os_strlen(pk);
  109. bi->uri = os_malloc(len + 1);
  110. if (!bi->uri)
  111. goto fail;
  112. os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%s%s%sK:%s;;",
  113. chan ? "C:" : "", chan ? chan : "", chan ? ";" : "",
  114. mac ? "M:" : "", mac ? mac : "", mac ? ";" : "",
  115. info ? "I:" : "", info ? info : "", info ? ";" : "",
  116. pk);
  117. bi->id = wpas_dpp_next_id(wpa_s);
  118. dl_list_add(&wpa_s->dpp_bootstrap, &bi->list);
  119. ret = bi->id;
  120. bi = NULL;
  121. fail:
  122. os_free(curve);
  123. os_free(pk);
  124. os_free(chan);
  125. os_free(mac);
  126. os_free(info);
  127. str_clear_free(key);
  128. bin_clear_free(privkey, privkey_len);
  129. dpp_bootstrap_info_free(bi);
  130. return ret;
  131. }
  132. static struct dpp_bootstrap_info *
  133. dpp_bootstrap_get_id(struct wpa_supplicant *wpa_s, unsigned int id)
  134. {
  135. struct dpp_bootstrap_info *bi;
  136. dl_list_for_each(bi, &wpa_s->dpp_bootstrap, struct dpp_bootstrap_info,
  137. list) {
  138. if (bi->id == id)
  139. return bi;
  140. }
  141. return NULL;
  142. }
  143. static int dpp_bootstrap_del(struct wpa_supplicant *wpa_s, unsigned int id)
  144. {
  145. struct dpp_bootstrap_info *bi, *tmp;
  146. int found = 0;
  147. dl_list_for_each_safe(bi, tmp, &wpa_s->dpp_bootstrap,
  148. struct dpp_bootstrap_info, list) {
  149. if (id && bi->id != id)
  150. continue;
  151. found = 1;
  152. dl_list_del(&bi->list);
  153. dpp_bootstrap_info_free(bi);
  154. }
  155. if (id == 0)
  156. return 0; /* flush succeeds regardless of entries found */
  157. return found ? 0 : -1;
  158. }
  159. int wpas_dpp_bootstrap_remove(struct wpa_supplicant *wpa_s, const char *id)
  160. {
  161. unsigned int id_val;
  162. if (os_strcmp(id, "*") == 0) {
  163. id_val = 0;
  164. } else {
  165. id_val = atoi(id);
  166. if (id_val == 0)
  167. return -1;
  168. }
  169. return dpp_bootstrap_del(wpa_s, id_val);
  170. }
  171. const char * wpas_dpp_bootstrap_get_uri(struct wpa_supplicant *wpa_s,
  172. unsigned int id)
  173. {
  174. struct dpp_bootstrap_info *bi;
  175. bi = dpp_bootstrap_get_id(wpa_s, id);
  176. if (!bi)
  177. return NULL;
  178. return bi->uri;
  179. }
  180. int wpas_dpp_init(struct wpa_supplicant *wpa_s)
  181. {
  182. dl_list_init(&wpa_s->dpp_bootstrap);
  183. wpa_s->dpp_init_done = 1;
  184. return 0;
  185. }
  186. void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
  187. {
  188. if (!wpa_s->dpp_init_done)
  189. return;
  190. dpp_bootstrap_del(wpa_s, 0);
  191. }