]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
Update api for base16_decode_update and base16_decode_update.
authorNiels Möller <nisse@lysator.liu.se>
Wed, 29 Oct 2025 20:12:15 +0000 (21:12 +0100)
committerNiels Möller <nisse@lysator.liu.se>
Thu, 30 Oct 2025 09:04:51 +0000 (10:04 +0100)
Make *dst_length an input argument, should hold size of dst buffer.
Fail if decoding would exceed this size.

ChangeLog
base16-decode.c
base16.h
base64-decode.c
base64.h
examples/base16dec.c
sexp-transport.c
testsuite/base16-test.c
testsuite/base64-test.c
testsuite/ed25519-test.c
testsuite/ed448-test.c

index dbaf31a34a6dae28ff72f9ad410777e678824031..f8a141f9dab81c4068b68c1dec7cd00944407f93 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2025-10-30  Niels Möller  <nisse@lysator.liu.se>
+
+       * 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  <nisse@lysator.liu.se>
 
        * base64-encode.c (base64_encode_group): Delete unused and
index fc33123677bed32d9f80f16e5ae0ee35a64fe2b2..549799294b90a2f212f129792c079a8ba849e430 100644 (file)
@@ -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<src_length; i++)
     {
-    case -1:
-      return -1;
-    case -2:
-      return 0;
-    default:
-      assert(digit >= 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; i<src_length; i++)
-    switch(base16_decode_single(ctx, dst + done, src[i]))
-      {
-      case -1:
-       return 0;
-      case 1:
-       done++;
-       /* Fall through */
-      case 0:
-       break;
-      default:
-       abort();
-      }
-  
   assert(done <= BASE16_DECODE_LENGTH(src_length));
 
   *dst_length = done;
index 755e6ed321eb87b6b90cbd9843c4fc7dddb214c6..2876c3474632ef19b486081dbb44b1048c88b285 100644 (file)
--- a/base16.h
+++ b/base16.h
@@ -89,9 +89,10 @@ base16_decode_single(struct base16_decode_ctx *ctx,
                     char src);
 
 /* Returns 1 on success, 0 on error. DST should point to an area of
- * size at least BASE16_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. BASE16_DECODE_LENGTH(src_length) is always sufficient.
+ * *DST_LENGTH is updated to reflect the amount of data actually
+ * generated. */
 int
 base16_decode_update(struct base16_decode_ctx *ctx,
                     size_t *dst_length,
index b993117ad8eb111ec2000d3102ff08c115e32ab7..8956258f4af08060d237cb6d8043b9d1047e6f8b 100644 (file)
@@ -75,46 +75,9 @@ base64_decode_single(struct base64_decode_ctx *ctx,
                     uint8_t *dst,
                     char src)
 {
-  int data = ctx->table[(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<<ctx->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; i<src_length; i++)
-    switch(base64_decode_single(ctx, dst + done, src[i]))
-      {
-      case -1:
-       return 0;
-      case 1:
-       done++;
-       /* Fall through */
-      case 0:
-       break;
-      default:
-       abort();
-      }
-  
+  for (i = done = 0; i<src_length; i++)
+    {
+      int data = ctx->table[(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<<ctx->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;
index a809209b34823ddfbc286c3abbfc5409654ed0c4..dcf70bad4f860fed45b9ab05b415f56ea1158a50 100644 (file)
--- 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,
index 1185b3e1bf8f5195b29dd5db6bdadab461f61319..6d2b2ecedc696a2c56efd0040a3d2bdc3a538ce1 100644 (file)
@@ -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;
index 1a34db7129b0d0ef251ddd5f1e9834c753e6546e..5dcc990e6cd8903a064e1c4227417b414ef333c3 100644 (file)
@@ -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))
index 8318770dd064f794473a5947039ec40c75e7623f..e0961f259402e50a612d3a2c2dde5332d7b33268 100644 (file)
@@ -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);
index f021e357d62561c53795b87d3be09e836ce9a959..48eff6b098de0785870f2d9e74b232fa32e461d8 100644 (file)
@@ -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);
 }
index 7e13881c0ba5ecceb73d5799c8e6ed764ea22833..ee9e8c777f9992e46dad40c5745c96d7f20126f4 100644 (file)
@@ -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);
index 7ea2da4f9b00d990bd8547176e3c6ba8e1732c6c..cc85ddb05b86e38360a52bacd4667d01fb1c35a1 100644 (file)
@@ -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);