Bug#1064550: bullseye-pu: libjwt/1.10.2-1+deb11u1
Package: release.debian.org
Severity: normal
Tags: bullseye
User: release.debian.org@packages.debian.org
Usertags: pu
The attached debdiff for libjwt fixes CVE-2024-25189 in Bullseye. It is
marked as no-dsa by the security team.
The fix is straightfoward and should not make any problems.
Thorsten
diff -Nru libjwt-1.10.2/debian/changelog libjwt-1.10.2/debian/changelog
--- libjwt-1.10.2/debian/changelog 2019-07-14 19:03:00.000000000 +0200
+++ libjwt-1.10.2/debian/changelog 2024-02-20 23:03:02.000000000 +0100
@@ -1,3 +1,10 @@
+libjwt (1.10.2-1+deb11u1) bullseye; urgency=medium
+
+ * CVE-2024-25189 (Closes: #1063534)
+ fix a timing side channel via strcmp()
+
+ -- Thorsten Alteholz <debian@alteholz.de> Tue, 20 Feb 2024 23:03:02 +0100
+
libjwt (1.10.2-1) unstable; urgency=medium
* New upstream release
diff -Nru libjwt-1.10.2/debian/libjwt0.symbols libjwt-1.10.2/debian/libjwt0.symbols
--- libjwt-1.10.2/debian/libjwt0.symbols 2019-01-13 15:13:51.000000000 +0100
+++ libjwt-1.10.2/debian/libjwt0.symbols 2024-02-20 23:03:02.000000000 +0100
@@ -38,5 +38,6 @@
jwt_sign_sha_hmac@Base 1.9.0
jwt_sign_sha_pem@Base 1.9.0
jwt_str_alg@Base 1.9.0
+ jwt_strcmp@Base 1.10.2
jwt_verify_sha_hmac@Base 1.9.0
jwt_verify_sha_pem@Base 1.9.0
diff -Nru libjwt-1.10.2/debian/libjwt-gnutls0.symbols libjwt-1.10.2/debian/libjwt-gnutls0.symbols
--- libjwt-1.10.2/debian/libjwt-gnutls0.symbols 2019-01-13 15:13:51.000000000 +0100
+++ libjwt-1.10.2/debian/libjwt-gnutls0.symbols 2024-02-20 23:03:02.000000000 +0100
@@ -38,5 +38,6 @@
jwt_sign_sha_hmac@Base 1.9.0
jwt_sign_sha_pem@Base 1.9.0
jwt_str_alg@Base 1.9.0
+ jwt_strcmp@Base 1.10.2
jwt_verify_sha_hmac@Base 1.9.0
jwt_verify_sha_pem@Base 1.9.0
diff -Nru libjwt-1.10.2/debian/patches/CVE-2024-25189-1.patch libjwt-1.10.2/debian/patches/CVE-2024-25189-1.patch
--- libjwt-1.10.2/debian/patches/CVE-2024-25189-1.patch 1970-01-01 01:00:00.000000000 +0100
+++ libjwt-1.10.2/debian/patches/CVE-2024-25189-1.patch 2024-02-20 23:03:02.000000000 +0100
@@ -0,0 +1,130 @@
+commit f73bac57c5bece16ac24f1a70022aa34355fc1bf
+Author: Ben Collins <bcollins@maclara-llc.com>
+Date: Fri Feb 9 09:03:35 2024 -0500
+
+ Implement a safer strcmp() function
+
+ As noted, the strcmp() function can be used for time-based side attacks.
+
+ I tried to test this and could not find a reasonable way to implement
+ this attack for several reasons:
+
+ 1) strcmp() is optimized to compare 4 and 8 bytes at a time when possible
+ on almost every modern system, making the attack almost impossible.
+ 2) Running 128 million iterations of strcmp() for a single byte attack
+ gave sub-nanosecond average differences (locally on same excution stack)
+ and almost as often as the comparison was correct, it was also wrong in
+ the reverse sense (i.e. two byte strcmp() took less time than single
+ byte).
+ 3) Adding noise from network, application stack, web server, etc. would
+ only add to the failure rate of guessing the differences above.
+
+ Erwan noted that there are proofs out there showing that signal noise
+ reduction can make this guessing more "accurate", but this proof also
+ noted it would take up to 4 billion guesses to completely cover this
+ attack surface. The claim was that 50k attempts per second would break
+ a 256-bit hmac in 22 hours. While this isn't impossible, it's very
+ implausible.
+
+ However, for the sake of cryptographic correctness, I implemented
+ jwt_strcmp() which always compares all bytes, and does so up to the
+ longest string in the 2-string set, without passing string boundaries.
+
+ This makes it time-consistent for len(max(a,b)) comparisons. I proofed
+ this using a 128 million interation average for various scenarious.
+
+ Reported-by: Erwan Legrand <moi@erwanlegrand.com>
+ Signed-off-by: Ben Collins <bcollins@maclara-llc.com>
+
+Index: libjwt-1.10.2/libjwt/jwt-gnutls.c
+===================================================================
+--- libjwt-1.10.2.orig/libjwt/jwt-gnutls.c 2024-02-19 22:38:58.575655983 +0100
++++ libjwt-1.10.2/libjwt/jwt-gnutls.c 2024-02-19 22:38:58.571655984 +0100
+@@ -90,7 +90,7 @@
+ jwt_Base64encode(buf, sig_check, len);
+ jwt_base64uri_encode(buf);
+
+- if (!strcmp(sig, buf))
++ if (!jwt_strcmp(sig, buf))
+ ret = 0;
+
+ free(sig_check);
+Index: libjwt-1.10.2/libjwt/jwt-openssl.c
+===================================================================
+--- libjwt-1.10.2.orig/libjwt/jwt-openssl.c 2024-02-19 22:38:58.575655983 +0100
++++ libjwt-1.10.2/libjwt/jwt-openssl.c 2024-02-19 22:38:58.571655984 +0100
+@@ -140,7 +140,7 @@
+ jwt_base64uri_encode(buf);
+
+ /* And now... */
+- ret = strcmp(buf, sig) ? EINVAL : 0;
++ ret = jwt_strcmp(buf, sig) ? EINVAL : 0;
+
+ jwt_verify_hmac_done:
+ BIO_free_all(b64);
+Index: libjwt-1.10.2/libjwt/jwt-private.h
+===================================================================
+--- libjwt-1.10.2.orig/libjwt/jwt-private.h 2024-02-19 22:38:58.575655983 +0100
++++ libjwt-1.10.2/libjwt/jwt-private.h 2024-02-19 22:41:41.667637551 +0100
+@@ -1,4 +1,4 @@
+-/* Copyright (C) 2015-2017 Ben Collins <ben@cyphre.com>
++/* Copyright (C) 2015-2024 Ben Collins <ben@cyphre.com>
+ This file is part of the JWT C Library
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+@@ -36,4 +36,7 @@
+
+ int jwt_verify_sha_pem(jwt_t *jwt, const char *head, const char *sig_b64);
+
++/* A time-safe strcmp function */
++int jwt_strcmp(const char *str1, const char *str2);
++
+ #endif /* JWT_PRIVATE_H */
+Index: libjwt-1.10.2/libjwt/jwt.c
+===================================================================
+--- libjwt-1.10.2.orig/libjwt/jwt.c 2024-02-19 22:38:58.575655983 +0100
++++ libjwt-1.10.2/libjwt/jwt.c 2024-02-19 22:44:53.223612621 +0100
+@@ -1,4 +1,4 @@
+-/* Copyright (C) 2015-2018 Ben Collins <ben@cyphre.com>
++/* Copyright (C) 2015-2024 Ben Collins <ben@cyphre.com>
+ This file is part of the JWT C Library
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+@@ -16,6 +16,37 @@
+ #include "jwt-private.h"
+ #include "config.h"
+
++/* A time-safe strcmp function */
++int jwt_strcmp(const char *str1, const char *str2)
++{
++ /* Get the LONGEST length */
++ int len1 = strlen(str1);
++ int len2 = strlen(str2);
++ int len_max = len1 >= len2 ? len1 : len2;
++
++ int i, ret = 0;
++
++ /* Iterate the entire longest string no matter what. Only testing
++ * the shortest string would still allow attacks for
++ * "a" == "aKJSDHkjashaaHJASJ", adding a character each time one
++ * is found. */
++ for (i = 0; i < len_max; i++) {
++ char c1, c2;
++
++ c1 = len1 < i ? str1[i] : '\0';
++ c2 = len2 < i ? str2[i] : '\0';
++
++ if (c1 != c2)
++ ret = 1;
++ }
++
++ /* Don't forget to check length */
++ if (len1 != len2)
++ ret = -1;
++
++ return ret;
++}
++
+ int jwt_Base64encode(char *coded_dst, const char *plain_src, int len_plain_src)
+ {
+ base64_encodestate _state;
diff -Nru libjwt-1.10.2/debian/patches/CVE-2024-25189-2.patch libjwt-1.10.2/debian/patches/CVE-2024-25189-2.patch
--- libjwt-1.10.2/debian/patches/CVE-2024-25189-2.patch 1970-01-01 01:00:00.000000000 +0100
+++ libjwt-1.10.2/debian/patches/CVE-2024-25189-2.patch 2024-02-20 23:03:02.000000000 +0100
@@ -0,0 +1,33 @@
+commit a5d61ef4f1b383876e0a78534383f38159471fd6
+Author: Ben Collins <bcollins@maclara-llc.com>
+Date: Fri Feb 9 09:50:34 2024 -0500
+
+ Rework jwt_strcmp() to use less branching
+
+ Signed-off-by: Ben Collins <bcollins@maclara-llc.com>
+
+Index: libjwt-1.10.2/libjwt/jwt.c
+===================================================================
+--- libjwt-1.10.2.orig/libjwt/jwt.c 2024-02-19 22:45:21.051608706 +0100
++++ libjwt-1.10.2/libjwt/jwt.c 2024-02-19 22:48:04.203584376 +0100
+@@ -33,16 +33,14 @@
+ for (i = 0; i < len_max; i++) {
+ char c1, c2;
+
+- c1 = len1 < i ? str1[i] : '\0';
+- c2 = len2 < i ? str2[i] : '\0';
++ c1 = (i < len1) ? str1[i] : 0;
++ c2 = (i < len2) ? str2[i] : 0;
+
+- if (c1 != c2)
+- ret = 1;
++ ret |= c1 ^ c2;
+ }
+
+ /* Don't forget to check length */
+- if (len1 != len2)
+- ret = -1;
++ ret |= len1 ^ len2;
+
+ return ret;
+ }
diff -Nru libjwt-1.10.2/debian/patches/series libjwt-1.10.2/debian/patches/series
--- libjwt-1.10.2/debian/patches/series 2019-01-13 15:13:51.000000000 +0100
+++ libjwt-1.10.2/debian/patches/series 2024-02-20 23:03:02.000000000 +0100
@@ -1,4 +1,7 @@
use-b64.patch
+CVE-2024-25189-1.patch
+CVE-2024-25189-2.patch
+
# do not add patches below
zzz-gnutls-soname.patch
Reply to: