commit 1ec9222b606e8ad3e1270c17a627e393068e7ae8
parent 59aac5395b7f1e00d8c85e8b2c43758cb8cb86fb
Author: Christian Grothoff <christian@grothoff.org>
Date: Mon, 6 Jul 2026 11:05:20 +0200
use constant-time string equality check for authorization codes
Diffstat:
1 file changed, 33 insertions(+), 6 deletions(-)
diff --git a/src/challenger/challenger-httpd_token.c b/src/challenger/challenger-httpd_token.c
@@ -33,6 +33,33 @@
/**
+ * Compare two NUL-terminated strings @a a and @a b in constant time
+ * with respect to their contents. Used for comparing secret/MAC
+ * material (authorization codes, PKCE challenges) to avoid leaking
+ * information via a timing oracle, as plain strcmp() short-circuits
+ * at the first differing byte. Note that the string lengths may
+ * still leak, which is acceptable here as the token length is not
+ * a secret at all.
+ *
+ * @param a first string
+ * @param b second string
+ * @return 0 if the strings are equal, non-zero otherwise
+ */
+static int
+ct_strcmp (const char *a,
+ const char *b)
+{
+ size_t alen = strlen (a);
+
+ if (strlen (b) != alen)
+ return 1;
+ return GNUNET_memcmp_ct_ (a,
+ b,
+ alen);
+}
+
+
+/**
* Context for a /token operation.
*/
struct TokenContext
@@ -513,8 +540,8 @@ CH_handler_token (struct CH_HandlerContext *hc,
"Failed to encode hash to Base64 URL");
}
- if (0 != strcmp (encoded_hash,
- code_challenge))
+ if (0 != ct_strcmp (encoded_hash,
+ code_challenge))
{
GNUNET_break_op (0);
json_decref (address);
@@ -536,8 +563,8 @@ CH_handler_token (struct CH_HandlerContext *hc,
break;
case CHALLENGER_CM_PLAIN:
{
- if (0 != strcmp (bc->code_verifier,
- code_challenge))
+ if (0 != ct_strcmp (bc->code_verifier,
+ code_challenge))
{
GNUNET_break_op (0);
json_decref (address);
@@ -599,8 +626,8 @@ CH_handler_token (struct CH_HandlerContext *hc,
GNUNET_free (client_redirect_uri);
GNUNET_free (client_state);
GNUNET_free (code_challenge);
- if (0 != strcmp (code,
- bc->code))
+ if (0 != ct_strcmp (code,
+ bc->code))
{
GNUNET_break_op (0);
GNUNET_free (code);