From d6ba2397803c5f2d6a39a8684239c53f84e73b80 Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Wed, 22 Jul 2026 23:48:16 +0200 Subject: aes: always require full inputs I.e. no 31 digit for 128-bit blocks, reuse code, etc. Also, generalize hex string parsing. --- aes/include/aes/all.h | 1 + aes/include/aes/hex.h | 25 ++++++++++++++++ aes/src/block.c | 15 +++------- aes/src/hex.c | 42 ++++++++++++++++++++++++++ aes/src/key.c | 81 +++++++++++++-------------------------------------- 5 files changed, 92 insertions(+), 72 deletions(-) create mode 100644 aes/include/aes/hex.h create mode 100644 aes/src/hex.c (limited to 'aes') diff --git a/aes/include/aes/all.h b/aes/include/aes/all.h index fb0a191..8c4b04d 100644 --- a/aes/include/aes/all.h +++ b/aes/include/aes/all.h @@ -10,6 +10,7 @@ #include "block.h" #include "box.h" #include "error.h" +#include "hex.h" #include "key.h" #include "mode.h" #include "padding.h" diff --git a/aes/include/aes/hex.h b/aes/include/aes/hex.h new file mode 100644 index 0000000..d0e4586 --- /dev/null +++ b/aes/include/aes/hex.h @@ -0,0 +1,25 @@ +// Copyright (c) 2026 Egor Tensin +// This file is part of the "AES tools" project. +// For details, see https://github.com/egor-tensin/aes-tools. +// Distributed under the MIT License. + +#pragma once + +#include "error.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +AES_StatusCode aes_parse_hex_string( + unsigned char* dest, + const char* src, + size_t numof_bytes, + AES_ErrorDetails* err_details +); + +#ifdef __cplusplus +} +#endif diff --git a/aes/src/block.c b/aes/src/block.c index 3fbd24f..1b72b62 100644 --- a/aes/src/block.c +++ b/aes/src/block.c @@ -77,19 +77,12 @@ AES_StatusCode aes_parse_block(AES_Block* dest, const char* src, AES_ErrorDetail if (src == NULL) return aes_error_null_argument(err_details, "src"); - const char* cursor = src; - AES_ALIGN(unsigned char, 16) bytes[16]; - for (int i = 0; i < 16; ++i) { - int n; - unsigned int byte; - if (sscanf(cursor, "%2x%n", &byte, &n) != 1) - return aes_error_parse(err_details, src, "a 128-bit block"); - bytes[i] = (unsigned char)byte; - cursor += n; - } + AES_StatusCode status = aes_parse_hex_string(bytes, src, sizeof(bytes), err_details); + if (aes_is_error(status)) + return status; *dest = aes_load_block_aligned(bytes); - return AES_SUCCESS; + return status; } diff --git a/aes/src/hex.c b/aes/src/hex.c new file mode 100644 index 0000000..62b6e5a --- /dev/null +++ b/aes/src/hex.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2026 Egor Tensin + * This file is part of the "AES tools" project. + * For details, see https://github.com/egor-tensin/aes-tools. + * Distributed under the MIT License. + */ + +#include + +#include +#include + +AES_StatusCode aes_parse_hex_string( + unsigned char* dest, + const char* src, + size_t numof_bytes, + AES_ErrorDetails* err_details +) { + if (dest == NULL) + return aes_error_null_argument(err_details, "dest"); + if (src == NULL) + return aes_error_null_argument(err_details, "src"); + + char what[30]; + snprintf(what, sizeof(what), "a %zu-byte hex string", numof_bytes); + + const char* cursor = src; + + for (size_t i = 0; i < numof_bytes; ++i) { + int n; + unsigned int byte; + if (sscanf(cursor, "%2x%n", &byte, &n) != 1 || n != 2) + return aes_error_parse(err_details, src, what); + dest[i] = (unsigned char)byte; + cursor += n; + } + + if (*cursor != '\0') + return aes_error_parse(err_details, src, what); + + return AES_SUCCESS; +} diff --git a/aes/src/key.c b/aes/src/key.c index 64cd460..1251a8c 100644 --- a/aes/src/key.c +++ b/aes/src/key.c @@ -98,6 +98,11 @@ AES_StatusCode aes256_format_key( } AES_StatusCode aes128_parse_key(AES128_Key* dest, const char* src, AES_ErrorDetails* err_details) { + if (dest == NULL) + return aes_error_null_argument(err_details, "dest"); + if (src == NULL) + return aes_error_null_argument(err_details, "src"); + return aes_parse_block(&dest->key, src, err_details); } @@ -107,40 +112,17 @@ AES_StatusCode aes192_parse_key(AES192_Key* dest, const char* src, AES_ErrorDeta if (src == NULL) return aes_error_null_argument(err_details, "src"); - const char* cursor = src; + AES_ALIGN(unsigned char, 16) bytes[32]; + memset(bytes, 0x00, sizeof(bytes)); - { - AES_ALIGN(unsigned char, 16) bytes[16]; - - for (int i = 0; i < 16; ++i) { - int n; - unsigned int byte; - if (sscanf(cursor, "%2x%n", &byte, &n) != 1) - return aes_error_parse(err_details, src, "a 192-bit block"); - bytes[i] = (unsigned char)byte; - cursor += n; - } - - dest->lo = aes_load_block_aligned(bytes); - } - - { - AES_ALIGN(unsigned char, 16) bytes[16]; + AES_StatusCode status = aes_parse_hex_string(bytes, src, 24, err_details); + if (aes_is_error(status)) + return status; - for (int i = 0; i < 8; ++i) { - int n; - unsigned int byte; - if (sscanf(cursor, "%2x%n", &byte, &n) != 1) - return aes_error_parse(err_details, src, "a 192-bit block"); - bytes[i] = (unsigned char)byte; - cursor += n; - } - - memset(bytes + 8, 0x00, 8); - dest->hi = aes_load_block_aligned(bytes); - } + dest->lo = aes_load_block_aligned(bytes); + dest->hi = aes_load_block_aligned(bytes + 16); - return AES_SUCCESS; + return status; } AES_StatusCode aes256_parse_key(AES256_Key* dest, const char* src, AES_ErrorDetails* err_details) { @@ -149,37 +131,14 @@ AES_StatusCode aes256_parse_key(AES256_Key* dest, const char* src, AES_ErrorDeta if (src == NULL) return aes_error_null_argument(err_details, "src"); - const char* cursor = src; + AES_ALIGN(unsigned char, 16) bytes[32]; - { - AES_ALIGN(unsigned char, 16) bytes[16]; + AES_StatusCode status = aes_parse_hex_string(bytes, src, sizeof(bytes), err_details); + if (aes_is_error(status)) + return status; - for (int i = 0; i < 16; ++i) { - int n; - unsigned int byte; - if (sscanf(cursor, "%2x%n", &byte, &n) != 1) - return aes_error_parse(err_details, src, "a 256-bit block"); - bytes[i] = (unsigned char)byte; - cursor += n; - } + dest->lo = aes_load_block_aligned(bytes); + dest->hi = aes_load_block_aligned(bytes + 16); - dest->lo = aes_load_block_aligned(bytes); - } - - { - AES_ALIGN(unsigned char, 16) bytes[16]; - - for (int i = 0; i < 16; ++i) { - int n; - unsigned int byte; - if (sscanf(cursor, "%2x%n", &byte, &n) != 1) - return aes_error_parse(err_details, src, "a 256-bit block"); - bytes[i] = (unsigned char)byte; - cursor += n; - } - - dest->hi = aes_load_block_aligned(bytes); - } - - return AES_SUCCESS; + return status; } -- cgit v1.3