diff --git a/sys/fmt/fmt.c b/sys/fmt/fmt.c
index 5ea21e8b8e9a705a766cc6d15d5c2b2c3d7e9e86..58aa01483b45a4cc13ef744371e622d09a4af3af 100644
--- a/sys/fmt/fmt.c
+++ b/sys/fmt/fmt.c
@@ -132,18 +132,22 @@ static uint8_t _hex_nib(uint8_t nib)
     return _byte_mod25((nib & 0x1f) + 9);
 }
 
+uint8_t fmt_hex_byte(const char *hex)
+{
+    return (_hex_nib(hex[0]) << 4) | _hex_nib(hex[1]);
+}
+
 size_t fmt_hex_bytes(uint8_t *out, const char *hex)
 {
     size_t len = fmt_strlen(hex);
 
     if (len & 1) {
-        out = NULL;
         return 0;
     }
 
     size_t final_len = len >> 1;
     for (size_t i = 0, j = 0; j < final_len; i += 2, j++) {
-        out[j] = (_hex_nib(hex[i]) << 4) | _hex_nib(hex[i+1]);
+        out[j] = fmt_hex_byte(hex + i);
     }
 
     return final_len;
diff --git a/sys/include/fmt.h b/sys/include/fmt.h
index 229f9396112267c227f70598b9f1e3478d1476e9..7176494d3098f6071807d8d75e69f8071f5a718f 100644
--- a/sys/include/fmt.h
+++ b/sys/include/fmt.h
@@ -91,6 +91,17 @@ size_t fmt_bytes_hex(char *out, const uint8_t *ptr, size_t n);
  */
 size_t fmt_bytes_hex_reverse(char *out, const uint8_t *ptr, size_t n);
 
+/**
+ * @brief Converts a sequence of two hex characters to a byte
+ *
+ * The hex characters sequence must contain valid hexadecimal characters
+ * otherwise the result is undefined.
+ *
+ * @param[in]  hex  Pointer to input buffer
+ * @returns    byte based on hex string
+ */
+uint8_t fmt_hex_byte(const char *hex);
+
 /**
  * @brief Converts a sequence of hex bytes to an array of bytes
  *
diff --git a/tests/unittests/tests-fmt/tests-fmt.c b/tests/unittests/tests-fmt/tests-fmt.c
index 949405ff7f506fa57af14618adaf119c5e6eac9d..0a7d537828c19432d58f74bee427413fbd907cd6 100644
--- a/tests/unittests/tests-fmt/tests-fmt.c
+++ b/tests/unittests/tests-fmt/tests-fmt.c
@@ -118,6 +118,31 @@ static void test_fmt_bytes_hex_reverse(void)
     TEST_ASSERT_EQUAL_STRING("zz", &out[9]);
 }
 
+static void test_fmt_hex_byte(void)
+{
+    char hex[3] = "00";
+    uint8_t byte;
+
+    byte = fmt_hex_byte(hex);
+    TEST_ASSERT_EQUAL_INT(0x00, byte);
+
+    memcpy(hex, "12", 2);
+    byte = fmt_hex_byte(hex);
+    TEST_ASSERT_EQUAL_INT(0x12, byte);
+
+    memcpy(hex, "AB", 2);
+    byte = fmt_hex_byte(hex);
+    TEST_ASSERT_EQUAL_INT(0xAB, byte);
+
+    memcpy(hex, "CD", 2);
+    byte = fmt_hex_byte(hex);
+    TEST_ASSERT_EQUAL_INT(0xCD, byte);
+
+    memcpy(hex, "EF", 2);
+    byte = fmt_hex_byte(hex);
+    TEST_ASSERT_EQUAL_INT(0xEF, byte);
+}
+
 static void test_fmt_hex_bytes(void)
 {
     uint8_t val = 0;
@@ -772,6 +797,7 @@ Test *tests_fmt_tests(void)
         new_TestFixture(test_fmt_byte_hex),
         new_TestFixture(test_fmt_bytes_hex),
         new_TestFixture(test_fmt_bytes_hex_reverse),
+        new_TestFixture(test_fmt_hex_byte),
         new_TestFixture(test_fmt_hex_bytes),
         new_TestFixture(test_fmt_u32_hex),
         new_TestFixture(test_fmt_u64_hex),