From: Niels Möller Date: Wed, 29 Oct 2025 20:12:15 +0000 (+0100) Subject: Update api for base16_decode_update and base16_decode_update. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=11c087e6b71d9b0b656913dd502de1b2296fa7eb;p=thirdparty%2Fnettle.git Update api for base16_decode_update and base16_decode_update. Make *dst_length an input argument, should hold size of dst buffer. Fail if decoding would exceed this size. --- diff --git a/ChangeLog b/ChangeLog index dbaf31a3..f8a141f9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2025-10-30 Niels Möller + + * base16-decode.c (base16_decode_single): Rewrite as a call to + base16_decode_update. + (base16_decode_update): Make *dst_length an input argument, should + hold size of dst buffer. Fail if decoding would exceed this size. + Update all callers. + * base64-decode.c (base64_decode_single, base64_decode_update): + Analogous changes. + 2025-10-29 Niels Möller * base64-encode.c (base64_encode_group): Delete unused and diff --git a/base16-decode.c b/base16-decode.c index fc331236..54979929 100644 --- a/base16-decode.c +++ b/base16-decode.c @@ -68,63 +68,45 @@ base16_decode_single(struct base16_decode_ctx *ctx, uint8_t *dst, char src) { - /* Avoid signed char for indexing. */ - unsigned char usrc = src; - int digit; + size_t dst_length = 1; + return base16_decode_update (ctx, &dst_length, dst, 1, &src) + ? dst_length : -1; +} - if (usrc >= 0x80) - return -1; +int +base16_decode_update(struct base16_decode_ctx *ctx, + size_t *dst_length, + uint8_t *dst, + size_t src_length, + const char *src) +{ + size_t done; + size_t i; - digit = hex_decode_table[usrc]; - switch (digit) + for (i = done = 0; i= 0); - assert(digit < 0x10); + unsigned char usrc = src[i]; + if (usrc >= 0x80) + return -1; + + int digit = hex_decode_table[usrc]; + if (digit == HEX_SPACE) + continue; + if (digit < 0 || done >= *dst_length) + return -1; + assert(digit < 0x10); if (ctx->bits) { - *dst = (ctx->word << 4) | digit; + dst[done++] = (ctx->word << 4) | digit; ctx->bits = 0; - return 1; } else { ctx->word = digit; ctx->bits = 4; - return 0; } } -} - -int -base16_decode_update(struct base16_decode_ctx *ctx, - size_t *dst_length, - uint8_t *dst, - size_t src_length, - const char *src) -{ - size_t done; - size_t i; - - for (i = done = 0; itable[(uint8_t) src]; - - switch(data) - { - default: - assert(data >= 0 && data < 0x40); - - if (ctx->padding) - return -1; - - ctx->word = ctx->word << 6 | data; - ctx->bits += 6; - - if (ctx->bits >= 8) - { - ctx->bits -= 8; - dst[0] = ctx->word >> ctx->bits; - return 1; - } - else return 0; - - case TABLE_INVALID: - return -1; - - case TABLE_SPACE: - return 0; - - case TABLE_END: - /* There can be at most two padding characters. */ - if (!ctx->bits || ctx->padding > 2) - return -1; - - if (ctx->word & ( (1<bits) - 1)) - /* We shouldn't have any leftover bits */ - return -1; - - ctx->padding++; - ctx->bits -= 2; - return 0; - } + size_t dst_length = 1; + return base64_decode_update (ctx, &dst_length, dst, 1, &src) + ? dst_length : -1; } int @@ -127,20 +90,44 @@ base64_decode_update(struct base64_decode_ctx *ctx, size_t done; size_t i; - for (i = 0, done = 0; itable[(uint8_t) src[i]]; + switch (data) + { + default: + assert(data >= 0 && data < 0x40); + + if (ctx->padding || (done >= *dst_length)) + return -1; + + ctx->word = ctx->word << 6 | data; + ctx->bits += 6; + + if (ctx->bits >= 8) + { + ctx->bits -= 8; + dst[done++] = ctx->word >> ctx->bits; + } + break; + case TABLE_INVALID: + return -1; + case TABLE_SPACE: + continue; + case TABLE_END: + /* There can be at most two padding characters. */ + if (!ctx->bits || ctx->padding > 2) + return -1; + + if (ctx->word & ( (1<bits) - 1)) + /* We shouldn't have any leftover bits */ + return -1; + + ctx->padding++; + ctx->bits -= 2; + break; + } + } assert(done <= BASE64_DECODE_LENGTH(src_length)); *dst_length = done; diff --git a/base64.h b/base64.h index a809209b..dcf70bad 100644 --- a/base64.h +++ b/base64.h @@ -148,8 +148,10 @@ base64_decode_single(struct base64_decode_ctx *ctx, char src); /* Returns 1 on success, 0 on error. DST should point to an area of - * size at least BASE64_DECODE_LENGTH(length). The amount of data - * generated is returned in *DST_LENGTH. */ + * size *DST_LENGTH. Decoding returns failure it output would exceed + * this size. BASE64_DECODE_LENGTH(length) is always sufficient. + * *DST_LENGTH is updated to reflect the amount of data actually + * generated. */ int base64_decode_update(struct base64_decode_ctx *ctx, size_t *dst_length, diff --git a/examples/base16dec.c b/examples/base16dec.c index 1185b3e1..6d2b2ece 100644 --- a/examples/base16dec.c +++ b/examples/base16dec.c @@ -76,7 +76,7 @@ main(int argc UNUSED, char **argv UNUSED) for (;;) { int nbytes; /* Number of bytes read frmo disk at each iteration */ - size_t decoded_bytes; /* Bytes actually generated at each iteration */ + size_t result_size = DECODED_SIZE; nbytes = fread(buffer, 1, CHUNK_SIZE, stdin); @@ -87,13 +87,13 @@ main(int argc UNUSED, char **argv UNUSED) } /* Decodes one chunk: */ - if (!base16_decode_update(&b16_ctx, &decoded_bytes, result, nbytes, buffer)) + if (!base16_decode_update(&b16_ctx, &result_size, result, nbytes, buffer)) { werror ("Error decoding input (not base16?)\n"); return EXIT_FAILURE; } - if (!write_data (stdout, decoded_bytes, result)) + if (!write_data (stdout, result_size, result)) { werror ("Error writing file: %s\n", strerror(errno)); return EXIT_FAILURE; diff --git a/sexp-transport.c b/sexp-transport.c index 1a34db71..5dcc990e 100644 --- a/sexp-transport.c +++ b/sexp-transport.c @@ -82,7 +82,7 @@ sexp_transport_iterator_first(struct sexp_iterator *iterator, return 0; base64_decode_init(&ctx); - + coded_length = end - in; if (base64_decode_update(&ctx, &coded_length, input + out, end - in, (const char*) (input + in)) && base64_decode_final(&ctx)) diff --git a/testsuite/base16-test.c b/testsuite/base16-test.c index 8318770d..e0961f25 100644 --- a/testsuite/base16-test.c +++ b/testsuite/base16-test.c @@ -23,7 +23,7 @@ test_base16 (size_t data_length, const uint8_t *data, ASSERT (0x33 == buffer[ascii_length]); base16_decode_init (&decode); - done = BASE16_DECODE_LENGTH (ascii_length); + done = data_length; ASSERT (base16_decode_update(&decode, &done, check, ascii_length, buffer)); ASSERT (done == data_length); diff --git a/testsuite/base64-test.c b/testsuite/base64-test.c index f021e357..48eff6b0 100644 --- a/testsuite/base64-test.c +++ b/testsuite/base64-test.c @@ -132,6 +132,7 @@ static inline int base64_decode_in_place (struct base64_decode_ctx *ctx, size_t *dst_length, size_t length, uint8_t *data) { + *dst_length = length; return base64_decode_update (ctx, dst_length, data, length, (const char *) data); } diff --git a/testsuite/ed25519-test.c b/testsuite/ed25519-test.c index 7e13881c..ee9e8c77 100644 --- a/testsuite/ed25519-test.c +++ b/testsuite/ed25519-test.c @@ -43,7 +43,7 @@ static void decode_hex (size_t length, uint8_t *dst, const char *src) { struct base16_decode_ctx ctx; - size_t out_size; + size_t out_size = length; base16_decode_init (&ctx); ASSERT (base16_decode_update (&ctx, &out_size, dst, 2*length, src)); ASSERT (out_size == length); diff --git a/testsuite/ed448-test.c b/testsuite/ed448-test.c index 7ea2da4f..cc85ddb0 100644 --- a/testsuite/ed448-test.c +++ b/testsuite/ed448-test.c @@ -44,7 +44,7 @@ static void decode_hex (size_t length, uint8_t *dst, const char *src) { struct base16_decode_ctx ctx; - size_t out_size; + size_t out_size = length; base16_decode_init (&ctx); ASSERT (base16_decode_update (&ctx, &out_size, dst, 2*length, src)); ASSERT (out_size == length);