1 /*
2  * wpa_supplicant/hostapd / common helper functions, etc.
3  * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "utils/includes.h"
10 
11 #include "utils/common.h"
12 #include <time.h>
13 
14 extern time_t mktime(struct tm*);
15 
16 /**
17  * inc_byte_array - Increment arbitrary length byte array by one
18  * @counter: Pointer to byte array
19  * @len: Length of the counter in bytes
20  *
21  * This function increments the last byte of the counter by one and continues
22  * rolling over to more significant bytes if the byte was incremented from
23  * 0xff to 0x00.
24  */
inc_byte_array(u8 * counter,size_t len)25 void inc_byte_array(u8 *counter, size_t len)
26 {
27 	int pos = len - 1;
28 	while (pos >= 0) {
29 		counter[pos]++;
30 		if (counter[pos] != 0)
31 			break;
32 		pos--;
33 	}
34 }
35 
hex2num(char c)36 static int hex2num(char c)
37 {
38 	if (c >= '0' && c <= '9')
39 		return c - '0';
40 	if (c >= 'a' && c <= 'f')
41 		return c - 'a' + 10;
42 	if (c >= 'A' && c <= 'F')
43 		return c - 'A' + 10;
44 	return -1;
45 }
46 
47 
hex2byte(const char * hex)48 int hex2byte(const char *hex)
49 {
50 	int a, b;
51 	a = hex2num(*hex++);
52 	if (a < 0)
53 		return -1;
54 	b = hex2num(*hex++);
55 	if (b < 0)
56 		return -1;
57 	return (a << 4) | b;
58 }
59 
60 
61 /**
62  * hexstr2bin - Convert ASCII hex string into binary data
63  * @hex: ASCII hex string (e.g., "01ab")
64  * @buf: Buffer for the binary data
65  * @len: Length of the text to convert in bytes (of buf); hex will be double
66  * this size
67  * Returns: 0 on success, -1 on failure (invalid hex string)
68  */
hexstr2bin(const char * hex,u8 * buf,size_t len)69 int hexstr2bin(const char *hex, u8 *buf, size_t len)
70 {
71 	size_t i;
72 	int a;
73 	const char *ipos = hex;
74 	u8 *opos = buf;
75 
76 	for (i = 0; i < len; i++) {
77 		a = hex2byte(ipos);
78 		if (a < 0)
79 			return -1;
80 		*opos++ = a;
81 		ipos += 2;
82 	}
83 	return 0;
84 }
85 
wpa_get_ntp_timestamp(u8 * buf)86 void wpa_get_ntp_timestamp(u8 *buf)
87 {
88 	struct os_time now;
89 	u32 sec, usec;
90 	be32 tmp;
91 
92 	/* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */
93 	os_get_time(&now);
94 	sec = now.sec + 2208988800U; /* Epoch to 1900 */
95 	/* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */
96 	usec = now.usec;
97 	usec = 4295 * usec - (usec >> 5) - (usec >> 9);
98 	tmp = host_to_be32(sec);
99 	os_memcpy(buf, (u8 *) &tmp, 4);
100 	tmp = host_to_be32(usec);
101 	os_memcpy(buf + 4, (u8 *) &tmp, 4);
102 }
printf_encode(char * txt,size_t maxlen,const u8 * data,size_t len)103 void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len)
104 {
105 	char *end = txt + maxlen;
106 	size_t i;
107 
108 	for (i = 0; i < len; i++) {
109 		if (txt + 4 >= end)
110 			break;
111 
112 		switch (data[i]) {
113 		case '\"':
114 			*txt++ = '\\';
115 			*txt++ = '\"';
116 			break;
117 		case '\\':
118 			*txt++ = '\\';
119 			*txt++ = '\\';
120 			break;
121 		case '\033':
122 			*txt++ = '\\';
123 			*txt++ = 'e';
124 			break;
125 		case '\n':
126 			*txt++ = '\\';
127 			*txt++ = 'n';
128 			break;
129 		case '\r':
130 			*txt++ = '\\';
131 			*txt++ = 'r';
132 			break;
133 		case '\t':
134 			*txt++ = '\\';
135 			*txt++ = 't';
136 			break;
137 		default:
138 			if (data[i] >= 32 && data[i] <= 127) {
139 				*txt++ = data[i];
140 			} else {
141 				txt += os_snprintf(txt, end - txt, "\\x%02x",
142 						   data[i]);
143 			}
144 			break;
145 		}
146 	}
147 
148 	*txt = '\0';
149 }
150 
151 
printf_decode(u8 * buf,size_t maxlen,const char * str)152 size_t printf_decode(u8 *buf, size_t maxlen, const char *str)
153 {
154 	const char *pos = str;
155 	size_t len = 0;
156 	int val;
157 
158 	while (*pos) {
159 		if (len + 1 >= maxlen)
160 			break;
161 		switch (*pos) {
162 		case '\\':
163 			pos++;
164 			switch (*pos) {
165 			case '\\':
166 				buf[len++] = '\\';
167 				pos++;
168 				break;
169 			case '"':
170 				buf[len++] = '"';
171 				pos++;
172 				break;
173 			case 'n':
174 				buf[len++] = '\n';
175 				pos++;
176 				break;
177 			case 'r':
178 				buf[len++] = '\r';
179 				pos++;
180 				break;
181 			case 't':
182 				buf[len++] = '\t';
183 				pos++;
184 				break;
185 			case 'e':
186 				buf[len++] = '\033';
187 				pos++;
188 				break;
189 			case 'x':
190 				pos++;
191 				val = hex2byte(pos);
192 				if (val < 0) {
193 					val = hex2num(*pos);
194 					if (val < 0)
195 						break;
196 					buf[len++] = val;
197 					pos++;
198 				} else {
199 					buf[len++] = val;
200 					pos += 2;
201 				}
202 				break;
203 			case '0':
204 			case '1':
205 			case '2':
206 			case '3':
207 			case '4':
208 			case '5':
209 			case '6':
210 			case '7':
211 				val = *pos++ - '0';
212 				if (*pos >= '0' && *pos <= '7')
213 					val = val * 8 + (*pos++ - '0');
214 				if (*pos >= '0' && *pos <= '7')
215 					val = val * 8 + (*pos++ - '0');
216 				buf[len++] = val;
217 				break;
218 			default:
219 				break;
220 			}
221 			break;
222 		default:
223 			buf[len++] = *pos++;
224 			break;
225 		}
226 	}
227 	if (maxlen > len)
228 		buf[len] = '\0';
229 
230 	return len;
231 }
232 
233 
234 
wpa_config_parse_string(const char * value,size_t * len)235 char * wpa_config_parse_string(const char *value, size_t *len)
236 {
237 	if (*value == '"') {
238 		const char *pos;
239 		char *str;
240 		value++;
241 		pos = os_strrchr(value, '"');
242 		if (pos == NULL || pos[1] != '\0')
243 			return NULL;
244 		*len = pos - value;
245 		str = dup_binstr(value, *len);
246 		if (str == NULL)
247 			return NULL;
248 		return str;
249 	} else if (*value == 'P' && value[1] == '"') {
250 		const char *pos;
251 		char *tstr, *str;
252 		size_t tlen;
253 		value += 2;
254 		pos = os_strrchr(value, '"');
255 		if (pos == NULL || pos[1] != '\0')
256 			return NULL;
257 		tlen = pos - value;
258 		tstr = dup_binstr(value, tlen);
259 		if (tstr == NULL)
260 			return NULL;
261 
262 		str = os_malloc(tlen + 1);
263 		if (str == NULL) {
264 			os_free(tstr);
265 			return NULL;
266 		}
267 
268 		*len = printf_decode((u8 *) str, tlen + 1, tstr);
269 		os_free(tstr);
270 
271 		return str;
272 	} else {
273 		u8 *str;
274 		size_t tlen, hlen = os_strlen(value);
275 #ifndef ESP_SUPPLICANT
276 		if (hlen & 1)
277 			return NULL;
278 #else
279 		if (hlen == 5 || hlen == 13) {
280 			*len = hlen;
281 			str = (u8 *)os_malloc(*len + 1);
282 			if (str == NULL) {
283 				return NULL;
284 			}
285 			memcpy(str, value, *len);
286 			str[*len] = '\0';
287 			return (char *) str;
288 	        }
289 #endif
290 		tlen = hlen / 2;
291 		str = os_malloc(tlen + 1);
292 		if (str == NULL)
293 			return NULL;
294 		if (hexstr2bin(value, str, tlen)) {
295 			os_free(str);
296 			return NULL;
297 		}
298 		str[tlen] = '\0';
299 		*len = tlen;
300 		return (char *) str;
301 	}
302 }
303 
304 
wpa_is_hex(const u8 * data,size_t len)305 int wpa_is_hex(const u8 *data, size_t len)
306 {
307 	size_t i;
308 
309 	for (i = 0; i < len; i++) {
310 		if (data[i] < 32 || data[i] >= 127)
311 			return 1;
312 	}
313 	return 0;
314 }
315 
316 
wpa_merge_byte_arrays(u8 * res,size_t res_len,const u8 * src1,size_t src1_len,const u8 * src2,size_t src2_len)317 size_t wpa_merge_byte_arrays(u8 *res, size_t res_len,
318 			 const u8 *src1, size_t src1_len,
319 			 const u8 *src2, size_t src2_len)
320 {
321 	size_t len = 0;
322 
323 	os_memset(res, 0, res_len);
324 
325 	if (src1) {
326 		if (src1_len >= res_len) {
327 			os_memcpy(res, src1, res_len);
328 			return res_len;
329 		}
330 
331 		os_memcpy(res, src1, src1_len);
332 		len += src1_len;
333 	}
334 
335 	if (src2) {
336 		if (len + src2_len >= res_len) {
337 			os_memcpy(res + len, src2, res_len - len);
338 			return res_len;
339 		}
340 
341 		os_memcpy(res + len, src2, src2_len);
342 		len += src2_len;
343 	}
344 
345 	return len;
346 }
347 
348 
dup_binstr(const void * src,size_t len)349 char * dup_binstr(const void *src, size_t len)
350 {
351 	char *res;
352 
353 	if (src == NULL)
354 		return NULL;
355 	res = os_malloc(len + 1);
356 	if (res == NULL)
357 		return NULL;
358 	os_memcpy(res, src, len);
359 	res[len] = '\0';
360 
361 	return res;
362 }
wpa_bin_clear_free(void * bin,size_t len)363 void wpa_bin_clear_free(void *bin, size_t len)
364 {
365 	if (bin) {
366 		os_memset(bin, 0, len);
367 		os_free(bin);
368 	}
369 }
370 
int_array_len(const int * a)371 int int_array_len(const int *a)
372 {
373 	int i;
374 	for (i = 0; a && a[i]; i++)
375 		;
376 	return i;
377 }
378 
bin_clear_free(void * bin,size_t len)379 void bin_clear_free(void *bin, size_t len)
380 {
381 	if (bin) {
382 		os_memset(bin, 0, len);
383 		os_free(bin);
384 	}
385 }
386 
str_clear_free(char * str)387 void str_clear_free(char *str)
388 {
389 	if (str) {
390 		size_t len = os_strlen(str);
391 		os_memset(str, 0, len);
392 		os_free(str);
393 	}
394 }
395 
os_gmtime(os_time_t t,struct os_tm * tm)396 int os_gmtime(os_time_t t, struct os_tm *tm)
397 {
398 	struct tm *tm2;
399 	time_t t2 = t;
400 
401 	tm2 = gmtime(&t2);
402 	if (tm2 == NULL)
403 		return -1;
404 	tm->sec = tm2->tm_sec;
405 	tm->min = tm2->tm_min;
406 	tm->hour = tm2->tm_hour;
407 	tm->day = tm2->tm_mday;
408 	tm->month = tm2->tm_mon + 1;
409 	tm->year = tm2->tm_year + 1900;
410 	return 0;
411 }
412 
os_mktime(int year,int month,int day,int hour,int min,int sec,os_time_t * t)413 int os_mktime(int year, int month, int day, int hour, int min, int sec,
414 		os_time_t *t)
415 {
416 	struct tm tm;
417 
418 	if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
419 			hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
420 			sec > 60)
421 		return -1;
422 
423 	os_memset(&tm, 0, sizeof(tm));
424 	tm.tm_year = year - 1900;
425 	tm.tm_mon = month - 1;
426 	tm.tm_mday = day;
427 	tm.tm_hour = hour;
428 	tm.tm_min = min;
429 	tm.tm_sec = sec;
430 
431 	*t = (os_time_t) mktime(&tm);
432 	return 0;
433 }
434 
get_param(const char * cmd,const char * param)435 char * get_param(const char *cmd, const char *param)
436 {
437 	const char *pos, *end;
438 	char *val;
439 	size_t len;
440 
441 	pos = os_strstr(cmd, param);
442 	if (!pos)
443 		return NULL;
444 
445 	pos += os_strlen(param);
446 	end = os_strchr(pos, ' ');
447 	if (end)
448 		len = end - pos;
449 	else
450 		len = os_strlen(pos);
451 	val = os_malloc(len + 1);
452 	if (!val)
453 		return NULL;
454 	os_memcpy(val, pos, len);
455 	val[len] = '\0';
456 	return val;
457 }
458 
os_memdup(const void * src,size_t len)459 void * os_memdup(const void *src, size_t len)
460 {
461 	void *r = os_malloc(len);
462 
463 	if (r && src)
464 		os_memcpy(r, src, len);
465 	return r;
466 }
467 
468 /**
469  * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format)
470  * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455)
471  * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
472  * Returns: Characters used (> 0) on success, -1 on failure
473  */
hwaddr_aton2(const char * txt,u8 * addr)474 int hwaddr_aton2(const char *txt, u8 *addr)
475 {
476 	int i;
477 	const char *pos = txt;
478 
479 	for (i = 0; i < 6; i++) {
480 		int a, b;
481 
482 		while (*pos == ':' || *pos == '.' || *pos == '-')
483 			pos++;
484 
485 		a = hex2num(*pos++);
486 		if (a < 0)
487 			return -1;
488 		b = hex2num(*pos++);
489 		if (b < 0)
490 			return -1;
491 		*addr++ = (a << 4) | b;
492 	}
493 
494 	return pos - txt;
495 }
496 
os_reltime_expired(struct os_time * now,struct os_time * ts,os_time_t timeout_secs)497 static inline int os_reltime_expired(struct os_time *now,
498 				     struct os_time *ts,
499 				     os_time_t timeout_secs)
500 {
501 	struct os_time age;
502 
503 	os_time_sub(now, ts, &age);
504 	return (age.sec > timeout_secs) ||
505 		(age.sec == timeout_secs && age.usec > 0);
506 }
507 
os_time_expired(struct os_time * now,struct os_time * ts,os_time_t timeout_secs)508 int os_time_expired(struct os_time *now,
509 		struct os_time *ts,
510 		os_time_t timeout_secs)
511 {
512 	return os_reltime_expired(now, ts, timeout_secs);
513 }
514 
rssi_to_rcpi(int rssi)515 u8 rssi_to_rcpi(int rssi)
516 {
517 	if (!rssi)
518 		return 255; /* not available */
519 	if (rssi < -110)
520 		return 0;
521 	if (rssi > 0)
522 		return 220;
523 	return (rssi + 110) * 2;
524 }
525 
526 /**
527  * wpa_ssid_txt - Convert SSID to a printable string
528  * @ssid: SSID (32-octet string)
529  * @ssid_len: Length of ssid in octets
530  * Returns: Pointer to a printable string
531  *
532  * This function can be used to convert SSIDs into printable form. In most
533  * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard
534  * does not limit the used character set, so anything could be used in an SSID.
535  *
536  * This function uses a static buffer, so only one call can be used at the
537  * time, i.e., this is not re-entrant and the returned buffer must be used
538  * before calling this again.
539  */
wpa_ssid_txt(const u8 * ssid,size_t ssid_len)540 const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len)
541 {
542 	static char ssid_txt[SSID_MAX_LEN * 4 + 1];
543 
544 	if (ssid == NULL) {
545 		ssid_txt[0] = '\0';
546 		return ssid_txt;
547 	}
548 
549 	printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len);
550 	return ssid_txt;
551 }
552