Version in base suite: 1.10.2-1 Base version: libjwt_1.10.2-1 Target version: libjwt_1.10.2-1+deb12u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/libj/libjwt/libjwt_1.10.2-1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/libj/libjwt/libjwt_1.10.2-1+deb12u1.dsc changelog | 7 ++ libjwt-gnutls0.symbols | 1 libjwt0.symbols | 1 patches/CVE-2024-25189-1.patch | 130 +++++++++++++++++++++++++++++++++++++++++ patches/CVE-2024-25189-2.patch | 33 ++++++++++ patches/series | 2 6 files changed, 174 insertions(+) diff -Nru libjwt-1.10.2/debian/changelog libjwt-1.10.2/debian/changelog --- libjwt-1.10.2/debian/changelog 2019-07-14 17:03:00.000000000 +0000 +++ libjwt-1.10.2/debian/changelog 2024-02-19 21:03:02.000000000 +0000 @@ -1,3 +1,10 @@ +libjwt (1.10.2-1+deb12u1) bookworm; urgency=medium + + * CVE-2024-25189 (Closes: #1063534) + fix a timing side channel via strcmp() + + -- Thorsten Alteholz Mon, 19 Feb 2024 22:03:02 +0100 + libjwt (1.10.2-1) unstable; urgency=medium * New upstream release 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 14:13:51.000000000 +0000 +++ libjwt-1.10.2/debian/libjwt-gnutls0.symbols 2024-02-19 21:03:02.000000000 +0000 @@ -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/libjwt0.symbols libjwt-1.10.2/debian/libjwt0.symbols --- libjwt-1.10.2/debian/libjwt0.symbols 2019-01-13 14:13:51.000000000 +0000 +++ libjwt-1.10.2/debian/libjwt0.symbols 2024-02-19 21:03:02.000000000 +0000 @@ -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 00:00:00.000000000 +0000 +++ libjwt-1.10.2/debian/patches/CVE-2024-25189-1.patch 2024-02-19 21:03:02.000000000 +0000 @@ -0,0 +1,130 @@ +commit f73bac57c5bece16ac24f1a70022aa34355fc1bf +Author: Ben Collins +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 + Signed-off-by: Ben Collins + +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 ++/* Copyright (C) 2015-2024 Ben Collins + 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 ++/* Copyright (C) 2015-2024 Ben Collins + 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 00:00:00.000000000 +0000 +++ libjwt-1.10.2/debian/patches/CVE-2024-25189-2.patch 2024-02-19 21:03:02.000000000 +0000 @@ -0,0 +1,33 @@ +commit a5d61ef4f1b383876e0a78534383f38159471fd6 +Author: Ben Collins +Date: Fri Feb 9 09:50:34 2024 -0500 + + Rework jwt_strcmp() to use less branching + + Signed-off-by: Ben Collins + +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 14:13:51.000000000 +0000 +++ libjwt-1.10.2/debian/patches/series 2024-02-19 21:03:02.000000000 +0000 @@ -1,4 +1,6 @@ use-b64.patch +CVE-2024-25189-1.patch +CVE-2024-25189-2.patch # do not add patches below zzz-gnutls-soname.patch