#include "amduat/util/hex.h" #include #include #include size_t amduat_hex_encoded_len(size_t byte_len) { if (byte_len > (SIZE_MAX / 2u)) { return 0; } return byte_len * 2u; } size_t amduat_hex_encoded_size(size_t byte_len) { size_t encoded_len = amduat_hex_encoded_len(byte_len); if (encoded_len == 0 && byte_len != 0) { return 0; } if (encoded_len > (SIZE_MAX - 1u)) { return 0; } return encoded_len + 1u; } bool amduat_hex_encode_lower(const uint8_t *bytes, size_t byte_len, char *out, size_t out_len) { static const char kHexLower[] = "0123456789abcdef"; size_t encoded_len = amduat_hex_encoded_len(byte_len); size_t encoded_size = amduat_hex_encoded_size(byte_len); if (encoded_len == 0 && byte_len != 0) { return false; } if (encoded_size == 0 || out == NULL || out_len < encoded_size) { return false; } if (byte_len > 0 && bytes == NULL) { return false; } for (size_t i = 0; i < byte_len; ++i) { uint8_t byte = bytes[i]; out[i * 2u] = kHexLower[(byte >> 4u) & 0x0fu]; out[i * 2u + 1u] = kHexLower[byte & 0x0fu]; } out[encoded_len] = '\0'; return true; } static bool amduat_hex_nibble(char c, uint8_t *out) { if (c >= '0' && c <= '9') { *out = (uint8_t)(c - '0'); return true; } if (c >= 'a' && c <= 'f') { *out = (uint8_t)(c - 'a' + 10); return true; } if (c >= 'A' && c <= 'F') { *out = (uint8_t)(c - 'A' + 10); return true; } return false; } bool amduat_hex_decode(const char *hex, uint8_t *out, size_t out_len) { if (hex == NULL) { return false; } if (out_len > 0 && out == NULL) { return false; } size_t hex_len = strlen(hex); if ((hex_len & 1u) != 0u) { return false; } size_t expected_len = hex_len / 2u; if (expected_len != out_len) { return false; } for (size_t i = 0; i < out_len; ++i) { uint8_t hi = 0; uint8_t lo = 0; if (!amduat_hex_nibble(hex[i * 2u], &hi) || !amduat_hex_nibble(hex[i * 2u + 1u], &lo)) { return false; } out[i] = (uint8_t)((hi << 4u) | lo); } return true; } bool amduat_hex_decode_alloc(const char *hex, uint8_t **out, size_t *out_len) { if (out != NULL) { *out = NULL; } if (out_len != NULL) { *out_len = 0; } if (hex == NULL || out == NULL || out_len == NULL) { return false; } size_t hex_len = strlen(hex); if ((hex_len & 1u) != 0u) { return false; } size_t bytes_len = hex_len / 2u; if (bytes_len == 0) { return true; } uint8_t *buf = (uint8_t *)malloc(bytes_len); if (buf == NULL) { return false; } if (!amduat_hex_decode(hex, buf, bytes_len)) { free(buf); return false; } *out = buf; *out_len = bytes_len; return true; }