blob: 8d7beef204e8315aaf1bf3a4c5cfdd83ae335d0a [file] [log] [blame]
Dmitry Shmidt5af38c32010-02-10 11:10:39 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdlib.h>
18#include <errno.h>
19#include <fcntl.h>
Olivier Baillyff2c0d82010-11-17 11:45:07 -080020#include <string.h>
Dmitry Shmidt5af38c32010-02-10 11:10:39 -080021
22#include <sys/socket.h>
23#include <sys/stat.h>
Olivier Baillyff2c0d82010-11-17 11:45:07 -080024#include <sys/ioctl.h>
Dmitry Shmidt5af38c32010-02-10 11:10:39 -080025#include <sys/types.h>
26#include <sys/wait.h>
27
28#include <netinet/in.h>
29#include <arpa/inet.h>
30
Dmitry Shmidt84c65a62010-03-03 13:14:30 -080031#include <linux/wireless.h>
32
Kenny Roota2d7e3e2010-03-15 14:26:36 -070033#include <openssl/evp.h>
34#include <openssl/sha.h>
35
Dmitry Shmidt5af38c32010-02-10 11:10:39 -080036#define LOG_TAG "SoftapController"
Elliott Hughesbbd56262015-12-04 15:45:10 -080037#include <android-base/file.h>
38#include <android-base/stringprintf.h>
Dmitry Shmidt5af38c32010-02-10 11:10:39 -080039#include <cutils/log.h>
Dmitry Shmidt389f8d12011-07-21 15:16:04 -070040#include <netutils/ifc.h>
Irfan Sheriff78dcb762011-07-22 15:20:21 -070041#include <private/android_filesystem_config.h>
Dmitry Shmidtfe15b632011-07-19 13:55:25 -070042#include "wifi.h"
Sasha Levitskiy25753d52013-01-10 12:48:39 -080043#include "ResponseCode.h"
Dmitry Shmidt5af38c32010-02-10 11:10:39 -080044
45#include "SoftapController.h"
Ashwini Patil508f10f2015-08-07 18:05:03 +053046#include <dirent.h>
Dmitry Shmidt5af38c32010-02-10 11:10:39 -080047
Dan Albert5407e142015-03-16 10:05:59 -070048using android::base::StringPrintf;
49using android::base::WriteStringToFile;
50
Nalla Kartheekcad2dc82016-08-31 12:26:14 +053051#ifdef LIBWPA_CLIENT_EXISTS
52#include <dirent.h>
53#include "wpa_ctrl.h"
54#endif
55
Lalit Kansarad1dcf202016-12-20 01:37:02 +053056std:: string hostapd_unix_file(StringPrintf("/data/misc/wifi/hostapd/wlan0"));
Nalla Kartheek71feca62016-12-08 15:35:51 +053057#ifdef LIBWPA_CLIENT_EXISTS
Nalla Kartheekcad2dc82016-08-31 12:26:14 +053058static const char HOSTAPD_DHCP_DIR[] = "/data/misc/dhcp";
59#endif
Irfan Sheriff78dcb762011-07-22 15:20:21 -070060static const char HOSTAPD_CONF_FILE[] = "/data/misc/wifi/hostapd.conf";
Sasha Levitskiy25753d52013-01-10 12:48:39 -080061static const char HOSTAPD_BIN_FILE[] = "/system/bin/hostapd";
Nalla Kartheek5ed655a2017-03-07 14:38:42 +053062static const char HOSTAPD_SOCKETS_DIR[] = "/data/misc/wifi/hostapd";
Dedy Lansky56adaf42015-09-06 14:27:22 +030063static const char WIFI_HOSTAPD_GLOBAL_CTRL_IFACE[] = "/data/misc/wifi/hostapd/global";
Irfan Sheriff78dcb762011-07-22 15:20:21 -070064
Sasha Levitskiy25753d52013-01-10 12:48:39 -080065SoftapController::SoftapController()
66 : mPid(0) {}
Dmitry Shmidt5af38c32010-02-10 11:10:39 -080067
68SoftapController::~SoftapController() {
Dmitry Shmidt84c65a62010-03-03 13:14:30 -080069}
70
Nalla Kartheekcad2dc82016-08-31 12:26:14 +053071#ifdef LIBWPA_CLIENT_EXISTS
72void *SoftapController::threadStart(void *obj){
73 SoftapController *me = reinterpret_cast<SoftapController *>(obj);
74 struct wpa_ctrl *ctrl;
75 int count = 0;
76
77 ALOGD("SoftapController::threadStart...");
78
79 DIR *dir = NULL;
80
81 dir = opendir(HOSTAPD_SOCKETS_DIR);
82 if (NULL == dir && errno == ENOENT) {
83 mkdir(HOSTAPD_SOCKETS_DIR, S_IRWXU|S_IRWXG|S_IRWXO);
84 chown(HOSTAPD_SOCKETS_DIR, AID_WIFI, AID_WIFI);
85 chmod(HOSTAPD_SOCKETS_DIR, S_IRWXU|S_IRWXG);
86 } else {
87 if (dir != NULL) { /* Directory already exists */
88 ALOGD("%s already exists", HOSTAPD_SOCKETS_DIR);
89 closedir(dir);
90 }
91 if (errno == EACCES) {
92 ALOGE("Cant open %s , check permissions ", HOSTAPD_SOCKETS_DIR);
93 }
94 }
95 chmod(HOSTAPD_DHCP_DIR, S_IRWXU|S_IRWXG|S_IRWXO);
96
Nalla Kartheek5ed655a2017-03-07 14:38:42 +053097 ctrl = wpa_ctrl_open2(hostapd_unix_file.c_str(), HOSTAPD_SOCKETS_DIR);
Nalla Kartheekcad2dc82016-08-31 12:26:14 +053098 while (ctrl == NULL) {
99 /*
100 * Try to connect to hostapd via wpa_ctrl interface.
101 * During conneciton process, it is possible that hostapd
102 * has station connected to it.
103 * Set sleep time to a appropriate value to lower the
104 * ratio that miss the STA-CONNECTED msg from hostapd
105 */
106 usleep(20000);
Nalla Kartheek5ed655a2017-03-07 14:38:42 +0530107 ctrl = wpa_ctrl_open2(hostapd_unix_file.c_str(), HOSTAPD_SOCKETS_DIR);
Nalla Kartheekcad2dc82016-08-31 12:26:14 +0530108 if (ctrl != NULL || count >= 150) {
109 break;
110 }
111 count ++;
112 }
113 if (count == 150 && ctrl == NULL) {
114 ALOGE("Connection to hostapd Error.");
115 return NULL;
116 }
117
118 if (wpa_ctrl_attach(ctrl) != 0) {
119 wpa_ctrl_close(ctrl);
120 ALOGE("Attach to hostapd Error.");
121 return NULL;
122 }
123
124 while (me->mHostapdFlag) {
125 int res = 0;
126 char buf[256];
127 char dest_str[300];
128 while (wpa_ctrl_pending(ctrl)) {
129 size_t len = sizeof(buf) - 1;
130 res = wpa_ctrl_recv(ctrl, buf, &len);
131 if (res == 0) {
132 buf[len] = '\0';
133 ALOGD("Get event from hostapd (%s)", buf);
134 memset(dest_str, 0x0, sizeof(dest_str));
135 snprintf(dest_str, sizeof(dest_str), "IfaceMessage active %s", buf);
136 me->mSocketClient->sendMsg(ResponseCode::InterfaceMessage, dest_str, false);
137 } else {
138 break;
139 }
140 }
141
142 if (res < 0) {
143 break;
144 }
145 sleep(2);
146 }
147
148 wpa_ctrl_detach(ctrl);
149 wpa_ctrl_close(ctrl);
150
Nalla Kartheek5ed655a2017-03-07 14:38:42 +0530151 ALOGD("SoftapController::threadExit");
Nalla Kartheekcad2dc82016-08-31 12:26:14 +0530152 return NULL;
153}
154#endif
155
Nalla Kartheekb9210a72016-11-17 09:56:14 +0530156int SoftapController::startSoftap(bool global_ctrl_iface = false, SocketClient *socketClient = NULL,
157 const char *ifname = NULL) {
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800158 pid_t pid = 1;
Ashwini Patil508f10f2015-08-07 18:05:03 +0530159 DIR *dir = NULL;
Dedy Lansky56adaf42015-09-06 14:27:22 +0300160 int ret;
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800161
Nalla Kartheeka4c1b662016-09-14 15:48:34 +0530162 mSocketClient = socketClient;
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800163 if (mPid) {
Sasha Levitskiy25753d52013-01-10 12:48:39 -0800164 ALOGE("SoftAP is already running");
165 return ResponseCode::SoftapStatusResult;
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800166 }
Irfan Sheriff7e9eb7b2012-06-15 16:11:31 -0700167
Dmitry Shmidt6fa06b72014-09-05 16:39:29 -0700168 if (ensure_entropy_file_exists() < 0) {
169 ALOGE("Wi-Fi entropy file was not created");
170 }
171
Dmitry Shmidt389f8d12011-07-21 15:16:04 -0700172 if ((pid = fork()) < 0) {
Steve Block5ea0c052012-01-06 19:18:11 +0000173 ALOGE("fork failed (%s)", strerror(errno));
Sasha Levitskiy25753d52013-01-10 12:48:39 -0800174 return ResponseCode::ServiceStartFailed;
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800175 }
Irfan Sheriff7e9eb7b2012-06-15 16:11:31 -0700176
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800177 if (!pid) {
Dmitry Shmidt01e182f2011-07-25 10:51:56 -0700178 ensure_entropy_file_exists();
Dedy Lansky56adaf42015-09-06 14:27:22 +0300179 if (global_ctrl_iface) {
180 ret = execl(HOSTAPD_BIN_FILE, HOSTAPD_BIN_FILE,
181 "-e", WIFI_ENTROPY_FILE, "-ddd",
182 "-g", WIFI_HOSTAPD_GLOBAL_CTRL_IFACE,
183 HOSTAPD_CONF_FILE, (char *)NULL);
184 } else {
185 ret = execl(HOSTAPD_BIN_FILE, HOSTAPD_BIN_FILE,
186 "-e", WIFI_ENTROPY_FILE, HOSTAPD_CONF_FILE,
187 (char *)NULL);
188 }
189 if (ret) {
Steve Block5ea0c052012-01-06 19:18:11 +0000190 ALOGE("execl failed (%s)", strerror(errno));
Dmitry Shmidt389f8d12011-07-21 15:16:04 -0700191 }
Sasha Levitskiy25753d52013-01-10 12:48:39 -0800192 ALOGE("SoftAP failed to start");
193 return ResponseCode::ServiceStartFailed;
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800194 } else {
Irfan Sheriff7e9eb7b2012-06-15 16:11:31 -0700195 mPid = pid;
Sasha Levitskiy25753d52013-01-10 12:48:39 -0800196 ALOGD("SoftAP started successfully");
Irfan Sheriff7e9eb7b2012-06-15 16:11:31 -0700197 usleep(AP_BSS_START_DELAY);
Ashwini Patil508f10f2015-08-07 18:05:03 +0530198 dir = opendir(HOSTAPD_SOCKETS_DIR);
199 if (NULL == dir && errno == ENOENT) {
200 mkdir(HOSTAPD_SOCKETS_DIR, S_IRWXU|S_IRWXG|S_IRWXO);
201 chown(HOSTAPD_SOCKETS_DIR, AID_WIFI, AID_WIFI);
202 chmod(HOSTAPD_SOCKETS_DIR, S_IRWXU|S_IRWXG);
203 } else {
204 if (dir != NULL) { /* Directory already exists */
205 ALOGD("%s already exists", HOSTAPD_SOCKETS_DIR);
206 closedir(dir);
207 }
208 if (errno == EACCES) {
209 ALOGE("Cant open %s , check permissions ", HOSTAPD_SOCKETS_DIR);
210 }
211 }
Nalla Kartheekb9210a72016-11-17 09:56:14 +0530212 if (ifname != NULL) {
213 std:: string wbuf(StringPrintf("/data/misc/wifi/hostapd/%s",ifname));
214 hostapd_unix_file = wbuf;
215 }
Nalla Kartheek71feca62016-12-08 15:35:51 +0530216#ifdef LIBWPA_CLIENT_EXISTS
217 mHostapdFlag = true;
Nalla Kartheeka4c1b662016-09-14 15:48:34 +0530218 if (mSocketClient != NULL) {
219 if ((mThreadErr = pthread_create(&mThread, NULL, SoftapController::threadStart, this)) != 0) {
220 ALOGE("pthread_create failed for hostapd listen socket (%s)", strerror(errno));
221 }
Nalla Kartheekcad2dc82016-08-31 12:26:14 +0530222 }
223#endif
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800224 }
Sasha Levitskiy25753d52013-01-10 12:48:39 -0800225 return ResponseCode::SoftapStatusResult;
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800226}
227
228int SoftapController::stopSoftap() {
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800229
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800230 if (mPid == 0) {
Sasha Levitskiy25753d52013-01-10 12:48:39 -0800231 ALOGE("SoftAP is not running");
232 return ResponseCode::SoftapStatusResult;
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800233 }
Dmitry Shmidt389f8d12011-07-21 15:16:04 -0700234
Nalla Kartheekcad2dc82016-08-31 12:26:14 +0530235#ifdef LIBWPA_CLIENT_EXISTS
236 mHostapdFlag = false;
237 if (mThreadErr == 0) {
238 pthread_join(mThread, NULL);
239 }
240#endif
241
Sasha Levitskiy25753d52013-01-10 12:48:39 -0800242 ALOGD("Stopping the SoftAP service...");
Dmitry Shmidt389f8d12011-07-21 15:16:04 -0700243 kill(mPid, SIGTERM);
244 waitpid(mPid, NULL, 0);
Irfan Sheriff7e9eb7b2012-06-15 16:11:31 -0700245
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800246 mPid = 0;
Sasha Levitskiy25753d52013-01-10 12:48:39 -0800247 ALOGD("SoftAP stopped successfully");
Dmitry Shmidt3df450a2010-03-18 13:06:47 -0700248 usleep(AP_BSS_STOP_DELAY);
Sasha Levitskiy25753d52013-01-10 12:48:39 -0800249 return ResponseCode::SoftapStatusResult;
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800250}
251
252bool SoftapController::isSoftapStarted() {
Sasha Levitskiy25753d52013-01-10 12:48:39 -0800253 return (mPid != 0);
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800254}
255
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800256/*
257 * Arguments:
Sasha Levitskiy25753d52013-01-10 12:48:39 -0800258 * argv[2] - wlan interface
259 * argv[3] - SSID
Dmitry Shmidteb59b572013-04-16 13:16:05 -0700260 * argv[4] - Broadcast/Hidden
Dmitry Shmidt85e6c5f2013-06-10 14:35:43 -0700261 * argv[5] - Channel
262 * argv[6] - Security
263 * argv[7] - Key
Dmitry Shmidt84c65a62010-03-03 13:14:30 -0800264 */
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800265int SoftapController::setSoftap(int argc, char *argv[]) {
Dmitry Shmidteb59b572013-04-16 13:16:05 -0700266 int hidden = 0;
Dmitry Shmidt85e6c5f2013-06-10 14:35:43 -0700267 int channel = AP_CHANNEL_DEFAULT;
Irfan Sheriff78dcb762011-07-22 15:20:21 -0700268
Dmitry Shmidteb59b572013-04-16 13:16:05 -0700269 if (argc < 5) {
270 ALOGE("Softap set is missing arguments. Please use:");
Dmitry Shmidt85e6c5f2013-06-10 14:35:43 -0700271 ALOGE("softap <wlan iface> <SSID> <hidden/broadcast> <channel> <wpa2?-psk|open> <passphrase>");
Dmitry Shmidteb59b572013-04-16 13:16:05 -0700272 return ResponseCode::CommandSyntaxError;
273 }
274
275 if (!strcasecmp(argv[4], "hidden"))
276 hidden = 1;
277
Dmitry Shmidt85e6c5f2013-06-10 14:35:43 -0700278 if (argc >= 5) {
279 channel = atoi(argv[5]);
280 if (channel <= 0)
281 channel = AP_CHANNEL_DEFAULT;
282 }
Irfan Sheriff78dcb762011-07-22 15:20:21 -0700283
Dan Albert5407e142015-03-16 10:05:59 -0700284 std::string wbuf(StringPrintf("interface=%s\n"
Elliott Hughesbd378322015-02-04 13:25:14 -0800285 "driver=nl80211\n"
286 "ctrl_interface=/data/misc/wifi/hostapd\n"
287 "ssid=%s\n"
288 "channel=%d\n"
289 "ieee80211n=1\n"
Elliott Hughes4674fae2015-02-11 20:38:23 -0800290 "hw_mode=%c\n"
Elliott Hughesbd378322015-02-04 13:25:14 -0800291 "ignore_broadcast_ssid=%d\n"
292 "wowlan_triggers=any\n",
Elliott Hughes4674fae2015-02-11 20:38:23 -0800293 argv[2], argv[3], channel, (channel <= 14) ? 'g' : 'a', hidden));
Dmitry Shmidt85e6c5f2013-06-10 14:35:43 -0700294
Elliott Hughesbd378322015-02-04 13:25:14 -0800295 std::string fbuf;
Dmitry Shmidt85e6c5f2013-06-10 14:35:43 -0700296 if (argc > 7) {
Elliott Hughesbd378322015-02-04 13:25:14 -0800297 char psk_str[2*SHA256_DIGEST_LENGTH+1];
Dmitry Shmidt85e6c5f2013-06-10 14:35:43 -0700298 if (!strcmp(argv[6], "wpa-psk")) {
Adam Langley986d0972015-11-04 14:35:25 -0800299 if (!generatePsk(argv[3], argv[7], psk_str)) {
300 return ResponseCode::OperationFailed;
301 }
Dan Albert5407e142015-03-16 10:05:59 -0700302 fbuf = StringPrintf("%swpa=3\nwpa_pairwise=TKIP CCMP\nwpa_psk=%s\n", wbuf.c_str(), psk_str);
Dmitry Shmidt85e6c5f2013-06-10 14:35:43 -0700303 } else if (!strcmp(argv[6], "wpa2-psk")) {
Adam Langley986d0972015-11-04 14:35:25 -0800304 if (!generatePsk(argv[3], argv[7], psk_str)) {
305 return ResponseCode::OperationFailed;
306 }
Dan Albert5407e142015-03-16 10:05:59 -0700307 fbuf = StringPrintf("%swpa=2\nrsn_pairwise=CCMP\nwpa_psk=%s\n", wbuf.c_str(), psk_str);
Dmitry Shmidt85e6c5f2013-06-10 14:35:43 -0700308 } else if (!strcmp(argv[6], "open")) {
Elliott Hughesbd378322015-02-04 13:25:14 -0800309 fbuf = wbuf;
Dmitry Shmidteb59b572013-04-16 13:16:05 -0700310 }
Dmitry Shmidt85e6c5f2013-06-10 14:35:43 -0700311 } else if (argc > 6) {
312 if (!strcmp(argv[6], "open")) {
Elliott Hughesbd378322015-02-04 13:25:14 -0800313 fbuf = wbuf;
Irfan Sheriff78dcb762011-07-22 15:20:21 -0700314 }
315 } else {
Elliott Hughesbd378322015-02-04 13:25:14 -0800316 fbuf = wbuf;
Irfan Sheriff78dcb762011-07-22 15:20:21 -0700317 }
318
Dan Albert5407e142015-03-16 10:05:59 -0700319 if (!WriteStringToFile(fbuf, HOSTAPD_CONF_FILE, 0660, AID_SYSTEM, AID_WIFI)) {
Steve Block5ea0c052012-01-06 19:18:11 +0000320 ALOGE("Cannot write to \"%s\": %s", HOSTAPD_CONF_FILE, strerror(errno));
Sasha Levitskiy25753d52013-01-10 12:48:39 -0800321 return ResponseCode::OperationFailed;
Irfan Sheriff78dcb762011-07-22 15:20:21 -0700322 }
Elliott Hughesbd378322015-02-04 13:25:14 -0800323 return ResponseCode::SoftapStatusResult;
Dmitry Shmidt5af38c32010-02-10 11:10:39 -0800324}
Dmitry Shmidt31fd6c52010-03-12 10:01:58 -0800325
Sasha Levitskiy25753d52013-01-10 12:48:39 -0800326/*
327 * Arguments:
328 * argv[2] - interface name
329 * argv[3] - AP or P2P or STA
330 */
331int SoftapController::fwReloadSoftap(int argc, char *argv[])
332{
Sasha Levitskiy25753d52013-01-10 12:48:39 -0800333 char *fwpath = NULL;
334
335 if (argc < 4) {
336 ALOGE("SoftAP fwreload is missing arguments. Please use: softap <wlan iface> <AP|P2P|STA>");
337 return ResponseCode::CommandSyntaxError;
338 }
339
340 if (strcmp(argv[3], "AP") == 0) {
341 fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_AP);
342 } else if (strcmp(argv[3], "P2P") == 0) {
343 fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_P2P);
344 } else if (strcmp(argv[3], "STA") == 0) {
345 fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_STA);
Dmitry Shmidt680d7652016-03-21 14:02:54 -0700346 } else {
Sasha Levitskiy25753d52013-01-10 12:48:39 -0800347 return ResponseCode::CommandParameterError;
Dmitry Shmidt680d7652016-03-21 14:02:54 -0700348 }
349 if (!fwpath) {
350 ALOGE("Softap fwReload - NULL path for %s", argv[3]);
351 return ResponseCode::SoftapStatusResult;
352 }
Sasha Levitskiy25753d52013-01-10 12:48:39 -0800353 if (wifi_change_fw_path((const char *)fwpath)) {
354 ALOGE("Softap fwReload failed");
355 return ResponseCode::OperationFailed;
356 }
357 else {
358 ALOGD("Softap fwReload - Ok");
359 }
360 return ResponseCode::SoftapStatusResult;
361}
362
Adam Langley986d0972015-11-04 14:35:25 -0800363bool SoftapController::generatePsk(char *ssid, char *passphrase, char *psk_str) {
Irfan Sheriff78dcb762011-07-22 15:20:21 -0700364 unsigned char psk[SHA256_DIGEST_LENGTH];
Adam Langley986d0972015-11-04 14:35:25 -0800365
Irfan Sheriff78dcb762011-07-22 15:20:21 -0700366 // Use the PKCS#5 PBKDF2 with 4096 iterations
Adam Langley986d0972015-11-04 14:35:25 -0800367 if (PKCS5_PBKDF2_HMAC_SHA1(passphrase, strlen(passphrase),
368 reinterpret_cast<const unsigned char *>(ssid),
369 strlen(ssid), 4096, SHA256_DIGEST_LENGTH,
370 psk) != 1) {
371 ALOGE("Cannot generate PSK using PKCS#5 PBKDF2");
372 return false;
373 }
374
375 for (int j=0; j < SHA256_DIGEST_LENGTH; j++) {
Sasha Levitskiy25753d52013-01-10 12:48:39 -0800376 sprintf(&psk_str[j*2], "%02x", psk[j]);
Irfan Sheriff78dcb762011-07-22 15:20:21 -0700377 }
Adam Langley986d0972015-11-04 14:35:25 -0800378
379 return true;
Dmitry Shmidt666fe252011-03-08 11:01:58 -0800380}