base32, base64: disallow non-canonical encodings
authorPádraig Brady <P@draigBrady.com>
Thu, 26 Oct 2023 15:25:03 +0000 (16:25 +0100)
committerPádraig Brady <P@draigBrady.com>
Fri, 27 Oct 2023 11:29:36 +0000 (12:29 +0100)
Unconditionally disallow encodings that don't have
appropriate zero bits before padding characters.
This handles one class of encoding variations discussed at:
https://eprint.iacr.org/2022/361.pdf
Note the other variations discussed there, due to optional
padding characters are already disallowed.

* lib/base32.c: Check that discarded bits in the encoding are zero.
* lib/base64.c: Likewise.
* tests/test-base32.c: Add test cases.
* tests/test-base64.c: Likewise.

ChangeLog
lib/base32.c
lib/base64.c
tests/test-base32.c
tests/test-base64.c

index 82e7021279ff903f4d7b559d6ceb728daf24fa65..c9f4186f82998689193481026849ab61f2b5f95f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2023-10-26  Pádraig Brady  <P@draigBrady.com>
+
+       base32, base64: disallow non-canonical encodings
+       * lib/base32.c: Check that discarded bits in the encoding are zero.
+       * lib/base64.c: Likewise.
+       * tests/test-base32.c: Add test cases.
+       * tests/test-base64.c: Likewise.
+
 2023-10-26  Bruno Haible  <bruno@clisp.org>
 
        fenv: Add tests.
index 2d692a2b3830e3048de20492287217ca2d27a99f..777328f56dc41f189144c50aef6d8843adb09ed7 100644 (file)
@@ -354,6 +354,10 @@ decode_8 (char const *restrict in, idx_t inlen,
       if (in[3] != '=' || in[4] != '=' || in[5] != '='
           || in[6] != '=' || in[7] != '=')
         return_false;
+
+      /* Reject non-canonical encodings.  */
+      if (base32_to_int[to_uchar (in[1])] & 0x03)
+        return_false;
     }
   else
     {
@@ -372,6 +376,10 @@ decode_8 (char const *restrict in, idx_t inlen,
         {
           if (in[5] != '=' || in[6] != '=' || in[7] != '=')
             return_false;
+
+          /* Reject non-canonical encodings.  */
+          if (base32_to_int[to_uchar (in[3])] & 0x0f)
+            return_false;
         }
       else
         {
@@ -389,6 +397,10 @@ decode_8 (char const *restrict in, idx_t inlen,
             {
               if (in[6] != '=' || in[7] != '=')
                 return_false;
+
+              /* Reject non-canonical encodings.  */
+              if (base32_to_int[to_uchar (in[4])] & 0x01)
+                return_false;
             }
           else
             {
@@ -415,6 +427,12 @@ decode_8 (char const *restrict in, idx_t inlen,
                       --*outleft;
                     }
                 }
+              else
+                {
+                  /* Reject non-canonical encodings.  */
+                  if (base32_to_int[to_uchar (in[6])] & 0x07)
+                    return_false;
+                }
             }
         }
     }
index 59a2135bf150944676eea005f911ca06987a6de3..da3e8aefb8badd61414f8c3956b4bfa1d97c796b 100644 (file)
@@ -396,6 +396,10 @@ decode_4 (char const *restrict in, idx_t inlen,
 
       if (in[3] != '=')
         return_false;
+
+      /* Reject non-canonical encodings.  */
+      if (base64_to_int[to_uchar (in[1])] & 0x0f)
+        return_false;
     }
   else
     {
@@ -416,6 +420,10 @@ decode_4 (char const *restrict in, idx_t inlen,
         {
           if (inlen != 4)
             return_false;
+
+          /* Reject non-canonical encodings.  */
+          if (base64_to_int[to_uchar (in[2])] & 0x03)
+            return_false;
         }
       else
         {
index 2e7d3c53b317de406dc2ecd35ec88c80f38c0fe4..16fb982edbe62dff4a77e7a6f2a9361c7803abe6 100644 (file)
@@ -256,5 +256,20 @@ main (void)
   ok = base32_decode_alloc_ctx (NULL, "AABBAA=A", 8, &p, &len);
   ASSERT (!ok);
 
+  ok = base32_decode_alloc_ctx (NULL, "FZ======", 8, &p, &len);
+  ASSERT (!ok);
+
+  ok = base32_decode_alloc_ctx (NULL, "FYXB====", 8, &p, &len);
+  ASSERT (!ok);
+
+  ok = base32_decode_alloc_ctx (NULL, "FYXC5===", 8, &p, &len);
+  ASSERT (!ok);
+
+  ok = base32_decode_alloc_ctx (NULL, "FYXC4LR=", 8, &p, &len);
+  ASSERT (!ok);
+
+  ok = base32_decode_alloc_ctx (NULL, "FZ======FY======", 16, &p, &len);
+  ASSERT (!ok);
+
   return 0;
 }
index 5196db09f45cb926cb504c2493c373641cbb7d5f..0da5f990545be1dedf26f88cfb2f86a55f2a8d4a 100644 (file)
@@ -233,5 +233,14 @@ main (void)
   ok = base64_decode_alloc_ctx (NULL, "aax=X", 5, &p, &len);
   ASSERT (!ok);
 
+  ok = base64_decode_alloc_ctx (NULL, "SGVsbG9=", 8, &p, &len);
+  ASSERT (!ok);
+
+  ok = base64_decode_alloc_ctx (NULL, "TR==", 4, &p, &len);
+  ASSERT (!ok);
+
+  ok = base64_decode_alloc_ctx (NULL, "TWF=TWE=", 8, &p, &len);
+  ASSERT (!ok);
+
   return 0;
 }