Skip to content
Permalink
Browse files

kernel: lib: Add convert functions for hex strings and binary arrays

Move duplicate hex2bin and add bin2hex function so that application can
use the functions and avoid code duplication.

Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
  • Loading branch information...
joerchan authored and carlescufi committed May 28, 2019
1 parent 743f3db commit 7a93e948a9ff059b8aba293cfcae5bbdf5bf33b7
@@ -18,6 +18,7 @@

#include <zephyr/types.h>
#include <stdbool.h>
#include <stddef.h>

/* Helper to pass a int as a pointer or vice-versa. */
#define POINTER_TO_UINT(x) ((uintptr_t) (x))
@@ -122,6 +123,56 @@ static inline s64_t arithmetic_shift_right(s64_t value, u8_t shift)
return (value >> shift) | (sign_ext << (64 - shift));
}

/**
* @brief Convert a single character into a hexadecimal nibble.
*
* @param[in] c The character to convert
* @param x The address of storage for the converted number.
*
* @return Zero on success or (negative) error code otherwise.
*/
int char2hex(char c, u8_t *x);

/**
* @brief Convert a single hexadecimal nibble into a character.
*
* @param[in] c The number to convert
* @param x The address of storage for the converted character.
*
* @return Zero on success or (negative) error code otherwise.
*/
int hex2char(u8_t x, char *c);

/**
* @brief Convert a binary array into string representation.
*
* @param[in] buf The binary array to convert
* @param[in] buflen The length of the binary array to convert
* @param[out] hex Address of where to store the string representation.
* @param[in] hexlen Size of the storage area for string representation.
*
* @return The length of the converted string, or 0 if an error occurred.
*/
size_t bin2hex(const u8_t *buf, size_t buflen, char *hex, size_t hexlen);

/*
* Convert hex string to byte string
* Return number of bytes written to buf, or 0 on error
* @return The length of the converted array, or 0 if an error occurred.
*/

/**
* @brief Convert a hexadecimal string into a binary array.
*
* @param[in] hex The hexadecimal string to convert
* @param[in] hexlen The length of the hexadecimal string to convert.
* @param[out] buf Address of where to store the binary data
* @param[in] buflen Size of the storage area for binary data
*
* @return The length of the binary array , or 0 if an error occurred.
*/
size_t hex2bin(const char *hex, size_t hexlen, u8_t *buf, size_t buflen);

#endif /* !_ASMLANGUAGE */

/* KB, MB, GB */
@@ -8,6 +8,7 @@ zephyr_sources(
crc8_sw.c
crc7_sw.c
fdtable.c
hex.c
mempool.c
rb.c
thread_entry.c
@@ -0,0 +1,91 @@
/*
* Copyright (c) 2019 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <stddef.h>
#include <zephyr/types.h>
#include <errno.h>
#include <sys/util.h>

int char2hex(char c, u8_t *x)
{
if (c >= '0' && c <= '9') {
*x = c - '0';
} else if (c >= 'a' && c <= 'f') {
*x = c - 'a' + 10;
} else if (c >= 'A' && c <= 'F') {
*x = c - 'A' + 10;
} else {
return -EINVAL;
}

return 0;
}

int hex2char(u8_t x, char *c)
{
if (x <= 9) {
*c = x + '0';
} else if (x >= 10 && x <= 15) {
*c = x - 10 + 'a';
} else {
return -EINVAL;
}

return 0;
}

size_t bin2hex(const u8_t *buf, size_t buflen, char *hex, size_t hexlen)
{
if ((hexlen + 1) < buflen * 2) {
return 0;
}

for (size_t i = 0; i < buflen; i++) {
if (hex2char(buf[i] >> 4, &hex[2 * i]) < 0) {
return 0;
}
if (hex2char(buf[i] & 0xf, &hex[2 * i + 1]) < 0) {
return 0;
}
}

hex[2 * buflen] = '\0';
return 2 * buflen;
}

size_t hex2bin(const char *hex, size_t hexlen, u8_t *buf, size_t buflen)
{
u8_t dec;

if (buflen < hexlen / 2 + hexlen % 2) {
return 0;
}

/* if hexlen is uneven, insert leading zero nibble */
if (hexlen % 2) {
if (char2hex(hex[0], &dec) < 0) {
return 0;
}
buf[0] = dec;
hex++;
buf++;
}

/* regular hex conversion */
for (size_t i = 0; i < hexlen / 2; i++) {
if (char2hex(hex[2 * i], &dec) < 0) {
return 0;
}
buf[i] = dec << 4;

if (char2hex(hex[2 * i + 1], &dec) < 0) {
return 0;
}
buf[i] += dec;
}

return hexlen / 2 + hexlen % 2;
}
@@ -13,6 +13,7 @@
#include <ctype.h>
#include <zephyr.h>
#include <sys/printk.h>
#include <sys/util.h>

#include <shell/shell.h>
#include <settings/settings.h>
@@ -205,37 +206,6 @@ static const struct bt_mesh_comp comp = {
.elem_count = ARRAY_SIZE(elements),
};

static u8_t hex2val(char c)
{
if (c >= '0' && c <= '9') {
return c - '0';
} else if (c >= 'a' && c <= 'f') {
return c - 'a' + 10;
} else if (c >= 'A' && c <= 'F') {
return c - 'A' + 10;
} else {
return 0;
}
}

static size_t hex2bin(const char *hex, u8_t *bin, size_t bin_len)
{
size_t len = 0;

while (*hex && len < bin_len) {
bin[len] = hex2val(*hex++) << 4;

if (!*hex) {
len++;
break;
}

bin[len++] |= hex2val(*hex++);
}

return len;
}

static void prov_complete(u16_t net_idx, u16_t addr)
{
shell_print(ctx_shell, "Local node provisioned, net_idx 0x%04x address "
@@ -395,7 +365,8 @@ static int cmd_static_oob(const struct shell *shell, size_t argc, char *argv[])
prov.static_val = NULL;
prov.static_val_len = 0U;
} else {
prov.static_val_len = hex2bin(argv[1], static_val, 16);
prov.static_val_len = hex2bin(argv[1], strlen(argv[1]),
static_val, 16);
if (prov.static_val_len) {
prov.static_val = static_val;
} else {
@@ -422,7 +393,7 @@ static int cmd_uuid(const struct shell *shell, size_t argc, char *argv[])
return -EINVAL;
}

len = hex2bin(argv[1], uuid, sizeof(uuid));
len = hex2bin(argv[1], strlen(argv[1]), uuid, sizeof(uuid));
if (len < 1) {
return -EINVAL;
}
@@ -727,7 +698,8 @@ static int cmd_net_send(const struct shell *shell, size_t argc, char *argv[])
return 0;
}

len = hex2bin(argv[1], msg.data, net_buf_simple_tailroom(&msg) - 4);
len = hex2bin(argv[1], strlen(argv[1]),
msg.data, net_buf_simple_tailroom(&msg) - 4);
net_buf_simple_add(&msg, len);

err = bt_mesh_trans_send(&tx, &msg, NULL, NULL);
@@ -940,7 +912,8 @@ static int cmd_net_key_add(const struct shell *shell, size_t argc, char *argv[])
if (argc > 2) {
size_t len;

len = hex2bin(argv[3], key_val, sizeof(key_val));
len = hex2bin(argv[3], strlen(argv[3]),
key_val, sizeof(key_val));
(void)memset(key_val, 0, sizeof(key_val) - len);
} else {
memcpy(key_val, default_key, sizeof(key_val));
@@ -981,7 +954,8 @@ static int cmd_app_key_add(const struct shell *shell, size_t argc, char *argv[])
if (argc > 3) {
size_t len;

len = hex2bin(argv[3], key_val, sizeof(key_val));
len = hex2bin(argv[3], strlen(argv[3]),
key_val, sizeof(key_val));
(void)memset(key_val, 0, sizeof(key_val) - len);
} else {
memcpy(key_val, default_key, sizeof(key_val));
@@ -1141,7 +1115,7 @@ static int cmd_mod_sub_add_va(const struct shell *shell, size_t argc,

elem_addr = strtoul(argv[1], NULL, 0);

len = hex2bin(argv[2], label, sizeof(label));
len = hex2bin(argv[2], strlen(argv[2]), label, sizeof(label));
(void)memset(label + len, 0, sizeof(label) - len);

mod_id = strtoul(argv[3], NULL, 0);
@@ -1189,7 +1163,7 @@ static int cmd_mod_sub_del_va(const struct shell *shell, size_t argc,

elem_addr = strtoul(argv[1], NULL, 0);

len = hex2bin(argv[2], label, sizeof(label));
len = hex2bin(argv[2], strlen(argv[2]), label, sizeof(label));
(void)memset(label + len, 0, sizeof(label) - len);

mod_id = strtoul(argv[3], NULL, 0);
@@ -18,6 +18,7 @@
#include <string.h>
#include <sys/printk.h>
#include <sys/byteorder.h>
#include <sys/util.h>
#include <zephyr.h>

#include <settings/settings.h>
@@ -229,21 +230,6 @@ static struct bt_conn_cb conn_callbacks = {
};
#endif /* CONFIG_BT_CONN */

static int char2hex(const char *c, u8_t *x)
{
if (*c >= '0' && *c <= '9') {
*x = *c - '0';
} else if (*c >= 'a' && *c <= 'f') {
*x = *c - 'a' + 10;
} else if (*c >= 'A' && *c <= 'F') {
*x = *c - 'A' + 10;
} else {
return -EINVAL;
}

return 0;
}

static int hexstr2array(const char *str, u8_t *array, u8_t size)
{
int i, j;
@@ -25,21 +25,6 @@ LOG_MODULE_REGISTER(net_bt_shell, CONFIG_NET_L2_BT_LOG_LEVEL);
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>

static int char2hex(const char *c, u8_t *x)
{
if (*c >= '0' && *c <= '9') {
*x = *c - '0';
} else if (*c >= 'a' && *c <= 'f') {
*x = *c - 'a' + 10;
} else if (*c >= 'A' && *c <= 'F') {
*x = *c - 'A' + 10;
} else {
return -EINVAL;
}

return 0;
}

static int str2bt_addr_le(const char *str, const char *type, bt_addr_le_t *addr)
{
int i, j;
@@ -64,16 +64,6 @@
#include <tinycrypt/ecc.h>
#include <test_utils.h>

int hex2int(char hex);


/*
* Convert hex string to byte string
* Return number of bytes written to buf, or 0 on error
*/
int hex2bin(uint8_t *buf, const size_t buflen, const char *hex,
const size_t hexlen);

/*
* Convert hex string to zero-padded nanoECC scalar
*/
@@ -66,6 +66,7 @@
#include <tinycrypt/sha256.h>
#include <test_utils.h>
#include <test_ecc_utils.h>
#include <sys/util.h>

#include <stdio.h>
#include <stdlib.h>
@@ -109,7 +110,7 @@ int sign_vectors(TCSha256State_t hash, char **d_vec, char **k_vec,
string2scalar(exp_r, NUM_ECC_WORDS, r_vec[i]);
string2scalar(exp_s, NUM_ECC_WORDS, s_vec[i]);

msglen = hex2bin(msg, BUF_SIZE, msg_vec[i], strlen(msg_vec[i]));
msglen = hex2bin(msg_vec[i], strlen(msg_vec[i]), msg, BUF_SIZE);

/**TESTPOINT: Check if msg imported*/
zassert_true(msglen, "failed to import message!");
@@ -366,7 +367,7 @@ int vrfy_vectors(TCSha256State_t hash, char **msg_vec, char **qx_vec, char **qy_
exp_rc = res_vec[i];

/* validate ECDSA: hash message, verify r+s */
msglen = hex2bin(msg, BUF_SIZE, msg_vec[i], strlen(msg_vec[i]));
msglen = hex2bin(msg_vec[i], strlen(msg_vec[i]), msg, BUF_SIZE);

/**TESTPOINT: Check if msg imported*/
zassert_true(msglen, "failed to import message!");

0 comments on commit 7a93e94

Please sign in to comment.
You can’t perform that action at this time.