From 3f463202bdd8684c649ee9eb5d9ba867dc6e8f08 Mon Sep 17 00:00:00 2001
From: =?utf8?q?P=C3=A1draig=20Brady?=
Date: Thu, 26 Oct 2023 16:25:03 +0100
Subject: [PATCH] base32, base64: disallow non-canonical encodings
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 | 8 ++++++++
lib/base32.c | 18 ++++++++++++++++++
lib/base64.c | 8 ++++++++
tests/test-base32.c | 15 +++++++++++++++
tests/test-base64.c | 9 +++++++++
5 files changed, 58 insertions(+)
diff --git a/ChangeLog b/ChangeLog
index 82e7021279..c9f4186f82 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2023-10-26 Pádraig Brady
+
+ 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
fenv: Add tests.
diff --git a/lib/base32.c b/lib/base32.c
index 2d692a2b38..777328f56d 100644
--- a/lib/base32.c
+++ b/lib/base32.c
@@ -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;
+ }
}
}
}
diff --git a/lib/base64.c b/lib/base64.c
index 59a2135bf1..da3e8aefb8 100644
--- a/lib/base64.c
+++ b/lib/base64.c
@@ -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
{
diff --git a/tests/test-base32.c b/tests/test-base32.c
index 2e7d3c53b3..16fb982edb 100644
--- a/tests/test-base32.c
+++ b/tests/test-base32.c
@@ -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;
}
diff --git a/tests/test-base64.c b/tests/test-base64.c
index 5196db09f4..0da5f99054 100644
--- a/tests/test-base64.c
+++ b/tests/test-base64.c
@@ -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;
}
--
2.39.5