mirror of
https://github.com/espressif/esp-idf.git
synced 2025-11-25 03:39:35 +01:00
Add files required for DPP feature from upstream. These file expose the functionality to create DPP packets. Ported crypto layer from openssl to mbedtls. Interfacing to use these API will be added in seperate commit
494 lines
8.5 KiB
C
494 lines
8.5 KiB
C
/*
|
|
* wpa_supplicant/hostapd / common helper functions, etc.
|
|
* Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
|
|
*
|
|
* This software may be distributed under the terms of the BSD license.
|
|
* See README for more details.
|
|
*/
|
|
|
|
#include "utils/includes.h"
|
|
|
|
#include "utils/common.h"
|
|
#include <time.h>
|
|
|
|
/**
|
|
* inc_byte_array - Increment arbitrary length byte array by one
|
|
* @counter: Pointer to byte array
|
|
* @len: Length of the counter in bytes
|
|
*
|
|
* This function increments the last byte of the counter by one and continues
|
|
* rolling over to more significant bytes if the byte was incremented from
|
|
* 0xff to 0x00.
|
|
*/
|
|
void inc_byte_array(u8 *counter, size_t len)
|
|
{
|
|
int pos = len - 1;
|
|
while (pos >= 0) {
|
|
counter[pos]++;
|
|
if (counter[pos] != 0)
|
|
break;
|
|
pos--;
|
|
}
|
|
}
|
|
|
|
static int hex2num(char c)
|
|
{
|
|
if (c >= '0' && c <= '9')
|
|
return c - '0';
|
|
if (c >= 'a' && c <= 'f')
|
|
return c - 'a' + 10;
|
|
if (c >= 'A' && c <= 'F')
|
|
return c - 'A' + 10;
|
|
return -1;
|
|
}
|
|
|
|
|
|
int hex2byte(const char *hex)
|
|
{
|
|
int a, b;
|
|
a = hex2num(*hex++);
|
|
if (a < 0)
|
|
return -1;
|
|
b = hex2num(*hex++);
|
|
if (b < 0)
|
|
return -1;
|
|
return (a << 4) | b;
|
|
}
|
|
|
|
|
|
/**
|
|
* hexstr2bin - Convert ASCII hex string into binary data
|
|
* @hex: ASCII hex string (e.g., "01ab")
|
|
* @buf: Buffer for the binary data
|
|
* @len: Length of the text to convert in bytes (of buf); hex will be double
|
|
* this size
|
|
* Returns: 0 on success, -1 on failure (invalid hex string)
|
|
*/
|
|
int hexstr2bin(const char *hex, u8 *buf, size_t len)
|
|
{
|
|
size_t i;
|
|
int a;
|
|
const char *ipos = hex;
|
|
u8 *opos = buf;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
a = hex2byte(ipos);
|
|
if (a < 0)
|
|
return -1;
|
|
*opos++ = a;
|
|
ipos += 2;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void wpa_get_ntp_timestamp(u8 *buf)
|
|
{
|
|
struct os_time now;
|
|
u32 sec, usec;
|
|
be32 tmp;
|
|
|
|
/* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */
|
|
os_get_time(&now);
|
|
sec = now.sec + 2208988800U; /* Epoch to 1900 */
|
|
/* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */
|
|
usec = now.usec;
|
|
usec = 4295 * usec - (usec >> 5) - (usec >> 9);
|
|
tmp = host_to_be32(sec);
|
|
os_memcpy(buf, (u8 *) &tmp, 4);
|
|
tmp = host_to_be32(usec);
|
|
os_memcpy(buf + 4, (u8 *) &tmp, 4);
|
|
}
|
|
void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len)
|
|
{
|
|
char *end = txt + maxlen;
|
|
size_t i;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
if (txt + 4 >= end)
|
|
break;
|
|
|
|
switch (data[i]) {
|
|
case '\"':
|
|
*txt++ = '\\';
|
|
*txt++ = '\"';
|
|
break;
|
|
case '\\':
|
|
*txt++ = '\\';
|
|
*txt++ = '\\';
|
|
break;
|
|
case '\033':
|
|
*txt++ = '\\';
|
|
*txt++ = 'e';
|
|
break;
|
|
case '\n':
|
|
*txt++ = '\\';
|
|
*txt++ = 'n';
|
|
break;
|
|
case '\r':
|
|
*txt++ = '\\';
|
|
*txt++ = 'r';
|
|
break;
|
|
case '\t':
|
|
*txt++ = '\\';
|
|
*txt++ = 't';
|
|
break;
|
|
default:
|
|
if (data[i] >= 32 && data[i] <= 127) {
|
|
*txt++ = data[i];
|
|
} else {
|
|
txt += os_snprintf(txt, end - txt, "\\x%02x",
|
|
data[i]);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
*txt = '\0';
|
|
}
|
|
|
|
|
|
size_t printf_decode(u8 *buf, size_t maxlen, const char *str)
|
|
{
|
|
const char *pos = str;
|
|
size_t len = 0;
|
|
int val;
|
|
|
|
while (*pos) {
|
|
if (len + 1 >= maxlen)
|
|
break;
|
|
switch (*pos) {
|
|
case '\\':
|
|
pos++;
|
|
switch (*pos) {
|
|
case '\\':
|
|
buf[len++] = '\\';
|
|
pos++;
|
|
break;
|
|
case '"':
|
|
buf[len++] = '"';
|
|
pos++;
|
|
break;
|
|
case 'n':
|
|
buf[len++] = '\n';
|
|
pos++;
|
|
break;
|
|
case 'r':
|
|
buf[len++] = '\r';
|
|
pos++;
|
|
break;
|
|
case 't':
|
|
buf[len++] = '\t';
|
|
pos++;
|
|
break;
|
|
case 'e':
|
|
buf[len++] = '\033';
|
|
pos++;
|
|
break;
|
|
case 'x':
|
|
pos++;
|
|
val = hex2byte(pos);
|
|
if (val < 0) {
|
|
val = hex2num(*pos);
|
|
if (val < 0)
|
|
break;
|
|
buf[len++] = val;
|
|
pos++;
|
|
} else {
|
|
buf[len++] = val;
|
|
pos += 2;
|
|
}
|
|
break;
|
|
case '0':
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
case '4':
|
|
case '5':
|
|
case '6':
|
|
case '7':
|
|
val = *pos++ - '0';
|
|
if (*pos >= '0' && *pos <= '7')
|
|
val = val * 8 + (*pos++ - '0');
|
|
if (*pos >= '0' && *pos <= '7')
|
|
val = val * 8 + (*pos++ - '0');
|
|
buf[len++] = val;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
buf[len++] = *pos++;
|
|
break;
|
|
}
|
|
}
|
|
if (maxlen > len)
|
|
buf[len] = '\0';
|
|
|
|
return len;
|
|
}
|
|
|
|
|
|
|
|
char * wpa_config_parse_string(const char *value, size_t *len)
|
|
{
|
|
if (*value == '"') {
|
|
const char *pos;
|
|
char *str;
|
|
value++;
|
|
pos = os_strrchr(value, '"');
|
|
if (pos == NULL || pos[1] != '\0')
|
|
return NULL;
|
|
*len = pos - value;
|
|
str = dup_binstr(value, *len);
|
|
if (str == NULL)
|
|
return NULL;
|
|
return str;
|
|
} else if (*value == 'P' && value[1] == '"') {
|
|
const char *pos;
|
|
char *tstr, *str;
|
|
size_t tlen;
|
|
value += 2;
|
|
pos = os_strrchr(value, '"');
|
|
if (pos == NULL || pos[1] != '\0')
|
|
return NULL;
|
|
tlen = pos - value;
|
|
tstr = dup_binstr(value, tlen);
|
|
if (tstr == NULL)
|
|
return NULL;
|
|
|
|
str = os_malloc(tlen + 1);
|
|
if (str == NULL) {
|
|
os_free(tstr);
|
|
return NULL;
|
|
}
|
|
|
|
*len = printf_decode((u8 *) str, tlen + 1, tstr);
|
|
os_free(tstr);
|
|
|
|
return str;
|
|
} else {
|
|
u8 *str;
|
|
size_t tlen, hlen = os_strlen(value);
|
|
#ifndef ESP_SUPPLICANT
|
|
if (hlen & 1)
|
|
return NULL;
|
|
#else
|
|
if (hlen == 5 || hlen == 13) {
|
|
*len = hlen;
|
|
str = (u8 *)os_malloc(*len + 1);
|
|
if (str == NULL) {
|
|
return NULL;
|
|
}
|
|
memcpy(str, value, *len);
|
|
str[*len] = '\0';
|
|
return (char *) str;
|
|
}
|
|
#endif
|
|
tlen = hlen / 2;
|
|
str = os_malloc(tlen + 1);
|
|
if (str == NULL)
|
|
return NULL;
|
|
if (hexstr2bin(value, str, tlen)) {
|
|
os_free(str);
|
|
return NULL;
|
|
}
|
|
str[tlen] = '\0';
|
|
*len = tlen;
|
|
return (char *) str;
|
|
}
|
|
}
|
|
|
|
|
|
int wpa_is_hex(const u8 *data, size_t len)
|
|
{
|
|
size_t i;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
if (data[i] < 32 || data[i] >= 127)
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
size_t wpa_merge_byte_arrays(u8 *res, size_t res_len,
|
|
const u8 *src1, size_t src1_len,
|
|
const u8 *src2, size_t src2_len)
|
|
{
|
|
size_t len = 0;
|
|
|
|
os_memset(res, 0, res_len);
|
|
|
|
if (src1) {
|
|
if (src1_len >= res_len) {
|
|
os_memcpy(res, src1, res_len);
|
|
return res_len;
|
|
}
|
|
|
|
os_memcpy(res, src1, src1_len);
|
|
len += src1_len;
|
|
}
|
|
|
|
if (src2) {
|
|
if (len + src2_len >= res_len) {
|
|
os_memcpy(res + len, src2, res_len - len);
|
|
return res_len;
|
|
}
|
|
|
|
os_memcpy(res + len, src2, src2_len);
|
|
len += src2_len;
|
|
}
|
|
|
|
return len;
|
|
}
|
|
|
|
|
|
char * dup_binstr(const void *src, size_t len)
|
|
{
|
|
char *res;
|
|
|
|
if (src == NULL)
|
|
return NULL;
|
|
res = os_malloc(len + 1);
|
|
if (res == NULL)
|
|
return NULL;
|
|
os_memcpy(res, src, len);
|
|
res[len] = '\0';
|
|
|
|
return res;
|
|
}
|
|
void wpa_bin_clear_free(void *bin, size_t len)
|
|
{
|
|
if (bin) {
|
|
os_memset(bin, 0, len);
|
|
os_free(bin);
|
|
}
|
|
}
|
|
|
|
int int_array_len(const int *a)
|
|
{
|
|
int i;
|
|
for (i = 0; a && a[i]; i++)
|
|
;
|
|
return i;
|
|
}
|
|
|
|
void bin_clear_free(void *bin, size_t len)
|
|
{
|
|
if (bin) {
|
|
os_memset(bin, 0, len);
|
|
os_free(bin);
|
|
}
|
|
}
|
|
|
|
void str_clear_free(char *str)
|
|
{
|
|
if (str) {
|
|
size_t len = os_strlen(str);
|
|
os_memset(str, 0, len);
|
|
os_free(str);
|
|
}
|
|
}
|
|
|
|
int os_gmtime(os_time_t t, struct os_tm *tm)
|
|
{
|
|
struct tm *tm2;
|
|
time_t t2 = t;
|
|
|
|
tm2 = gmtime(&t2);
|
|
if (tm2 == NULL)
|
|
return -1;
|
|
tm->sec = tm2->tm_sec;
|
|
tm->min = tm2->tm_min;
|
|
tm->hour = tm2->tm_hour;
|
|
tm->day = tm2->tm_mday;
|
|
tm->month = tm2->tm_mon + 1;
|
|
tm->year = tm2->tm_year + 1900;
|
|
return 0;
|
|
}
|
|
|
|
int os_mktime(int year, int month, int day, int hour, int min, int sec,
|
|
os_time_t *t)
|
|
{
|
|
struct tm tm;
|
|
|
|
if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
|
|
hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
|
|
sec > 60)
|
|
return -1;
|
|
|
|
os_memset(&tm, 0, sizeof(tm));
|
|
tm.tm_year = year - 1900;
|
|
tm.tm_mon = month - 1;
|
|
tm.tm_mday = day;
|
|
tm.tm_hour = hour;
|
|
tm.tm_min = min;
|
|
tm.tm_sec = sec;
|
|
|
|
*t = (os_time_t) mktime(&tm);
|
|
return 0;
|
|
}
|
|
|
|
char * get_param(const char *cmd, const char *param)
|
|
{
|
|
const char *pos, *end;
|
|
char *val;
|
|
size_t len;
|
|
|
|
pos = os_strstr(cmd, param);
|
|
if (!pos)
|
|
return NULL;
|
|
|
|
pos += os_strlen(param);
|
|
end = os_strchr(pos, ' ');
|
|
if (end)
|
|
len = end - pos;
|
|
else
|
|
len = os_strlen(pos);
|
|
val = os_malloc(len + 1);
|
|
if (!val)
|
|
return NULL;
|
|
os_memcpy(val, pos, len);
|
|
val[len] = '\0';
|
|
return val;
|
|
}
|
|
|
|
void * os_memdup(const void *src, size_t len)
|
|
{
|
|
void *r = os_malloc(len);
|
|
|
|
if (r && src)
|
|
os_memcpy(r, src, len);
|
|
return r;
|
|
}
|
|
|
|
/**
|
|
* hwaddr_aton2 - Convert ASCII string to MAC address (in any known format)
|
|
* @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455)
|
|
* @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
|
|
* Returns: Characters used (> 0) on success, -1 on failure
|
|
*/
|
|
int hwaddr_aton2(const char *txt, u8 *addr)
|
|
{
|
|
int i;
|
|
const char *pos = txt;
|
|
|
|
for (i = 0; i < 6; i++) {
|
|
int a, b;
|
|
|
|
while (*pos == ':' || *pos == '.' || *pos == '-')
|
|
pos++;
|
|
|
|
a = hex2num(*pos++);
|
|
if (a < 0)
|
|
return -1;
|
|
b = hex2num(*pos++);
|
|
if (b < 0)
|
|
return -1;
|
|
*addr++ = (a << 4) | b;
|
|
}
|
|
|
|
return pos - txt;
|
|
}
|