diff --git a/include/sys/util.h b/include/sys/util.h index 6a9718332b9..b678dec08bc 100644 --- a/include/sys/util.h +++ b/include/sys/util.h @@ -18,6 +18,7 @@ #include #include +#include /* 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 */ diff --git a/lib/os/CMakeLists.txt b/lib/os/CMakeLists.txt index d5aad76c7cd..926ce27f35a 100644 --- a/lib/os/CMakeLists.txt +++ b/lib/os/CMakeLists.txt @@ -8,6 +8,7 @@ zephyr_sources( crc8_sw.c crc7_sw.c fdtable.c + hex.c mempool.c rb.c thread_entry.c diff --git a/lib/os/hex.c b/lib/os/hex.c new file mode 100644 index 00000000000..e9f46f8a2ca --- /dev/null +++ b/lib/os/hex.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2019 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +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; +} diff --git a/subsys/bluetooth/mesh/shell.c b/subsys/bluetooth/mesh/shell.c index 7d486a10a3e..4b84d9a9828 100644 --- a/subsys/bluetooth/mesh/shell.c +++ b/subsys/bluetooth/mesh/shell.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -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); diff --git a/subsys/bluetooth/shell/bt.c b/subsys/bluetooth/shell/bt.c index f78360768e0..68cccfca251 100644 --- a/subsys/bluetooth/shell/bt.c +++ b/subsys/bluetooth/shell/bt.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -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; diff --git a/subsys/net/l2/bluetooth/bluetooth_shell.c b/subsys/net/l2/bluetooth/bluetooth_shell.c index 5c89c7d3108..44292e712ea 100644 --- a/subsys/net/l2/bluetooth/bluetooth_shell.c +++ b/subsys/net/l2/bluetooth/bluetooth_shell.c @@ -25,21 +25,6 @@ LOG_MODULE_REGISTER(net_bt_shell, CONFIG_NET_L2_BT_LOG_LEVEL); #include #include -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; diff --git a/subsys/testsuite/include/test_ecc_utils.h b/subsys/testsuite/include/test_ecc_utils.h index 891d6694957..b3efb93d004 100644 --- a/subsys/testsuite/include/test_ecc_utils.h +++ b/subsys/testsuite/include/test_ecc_utils.h @@ -64,16 +64,6 @@ #include #include -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 */ diff --git a/tests/crypto/tinycrypt/src/ecc_dsa.c b/tests/crypto/tinycrypt/src/ecc_dsa.c index 123e9ed1db5..d06af15969b 100644 --- a/tests/crypto/tinycrypt/src/ecc_dsa.c +++ b/tests/crypto/tinycrypt/src/ecc_dsa.c @@ -66,6 +66,7 @@ #include #include #include +#include #include #include @@ -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!"); diff --git a/tests/crypto/tinycrypt/src/test_ecc_utils.c b/tests/crypto/tinycrypt/src/test_ecc_utils.c index c1fc111dd51..d4b94c01610 100644 --- a/tests/crypto/tinycrypt/src/test_ecc_utils.c +++ b/tests/crypto/tinycrypt/src/test_ecc_utils.c @@ -58,71 +58,13 @@ #include #include +#include #include #include #include #include -int hex2int(char hex) -{ - uint8_t dec; - - if ('0' <= hex && hex <= '9') { - dec = hex - '0'; - } else if ('a' <= hex && hex <= 'f') { - dec = hex - 'a' + 10; - } else if ('A' <= hex && hex <= 'F') { - dec = hex - 'A' + 10; - } else { - return -1; - } - - return dec; -} - -/* - * 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) -{ - - int dec; - - if (buflen < hexlen / 2 + hexlen % 2) { - return false; - } - - /* if hexlen is uneven, insert leading zero nibble */ - if (hexlen % 2) { - dec = hex2int(hex[0]); - if (dec == -1) { - return false; - } - buf[0] = dec; - buf++; - hex++; - } - - /* regular hex conversion */ - for (size_t i = 0; i < hexlen / 2; i++) { - dec = hex2int(hex[2 * i]); - if (dec == -1) { - return false; - } - buf[i] = dec << 4; - - dec = hex2int(hex[2 * i + 1]); - if (dec == -1) { - return false; - } - buf[i] += dec; - } - return hexlen / 2 + hexlen % 2; -} - /* * Convert hex string to zero-padded nanoECC scalar */ @@ -144,7 +86,7 @@ void string2scalar(unsigned int *scalar, unsigned int num_word32, char *str) (void)memset(tmp, 0, padding / 2); - if (false == hex2bin(tmp + padding / 2, num_bytes, str, hexlen)) { + if (hex2bin(str, hexlen, tmp + padding / 2, num_bytes) == 0) { k_panic(); } uECC_vli_bytesToNative(scalar, tmp, num_bytes);