From 853e8c55a888fda7bd8c2f8f23e7bb7b7da7e990 Mon Sep 17 00:00:00 2001 From: tanjiro Kamado Date: Thu, 23 Jul 2026 04:15:04 +0530 Subject: [PATCH] fix out-of-bounds write in make_signature for mismatched EC key --- CHANGES.md | 1 + cups/jwt.c | 31 ++++++++++++++++++------------- cups/testjwt.c | 7 +++++++ 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 46d36faa2..6611daa20 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -15,6 +15,7 @@ v3.0.3 - YYYY-MM-DD - Fixed the example RPM spec file (Issue #150) - Fixed the `ipptool` "get-printer-attributes-suite.test" test file (Issue #154) - Fixed potential buffer overflow in `cupsCopyDestConflicts`. +- Fixed a buffer overflow in `cupsJWTSign` when the EC key curve did not match the algorithm. v3.0.2 - 2026-06-05 diff --git a/cups/jwt.c b/cups/jwt.c index 8ec3ad402..b06c2b684 100644 --- a/cups/jwt.c +++ b/cups/jwt.c @@ -2132,12 +2132,18 @@ make_signature(cups_jwt_t *jwt, // I - JWT s_len = (unsigned)BN_num_bytes(s); *sigsize = sig_sizes[alg - CUPS_JWA_ES256]; sig_len = *sigsize / 2; - ret = true; - // 0-pad raw coordinates - memset(signature, 0, *sigsize); - BN_bn2bin(r, signature + sig_len - r_len); - BN_bn2bin(s, signature + *sigsize - s_len); + // The key's curve has to match the algorithm - a larger curve gives + // coordinates that don't fit and `BN_bn2bin` would write before the + // buffer... + if (r_len <= sig_len && s_len <= sig_len) + { + // 0-pad raw coordinates + memset(signature, 0, *sigsize); + BN_bn2bin(r, signature + sig_len - r_len); + BN_bn2bin(s, signature + *sigsize - s_len); + ret = true; + } // Free the signature ECDSA_SIG_free(ec_sig); @@ -2161,16 +2167,15 @@ make_signature(cups_jwt_t *jwt, // I - JWT sig_len = *sigsize / 2; gnutls_decode_rs_value(&sig_datum, &r, &s); - memset(signature, 0, *sigsize); - if (r.size < sig_len) + // The key's curve has to match the algorithm - a larger curve gives + // coordinates that don't fit in the signature... + if (r.size <= sig_len && s.size <= sig_len) + { + memset(signature, 0, *sigsize); memcpy(signature + sig_len - r.size, r.data, r.size); - else - memcpy(signature, r.data + r.size - sig_len, sig_len); - if (s.size < sig_len) memcpy(signature + *sigsize - s.size, s.data, s.size); - else - memcpy(signature + sig_len, s.data + s.size - sig_len, sig_len); - ret = true; + ret = true; + } gnutls_free(r.data); gnutls_free(s.data); diff --git a/cups/testjwt.c b/cups/testjwt.c index 9e1957ed4..9eafa5a60 100644 --- a/cups/testjwt.c +++ b/cups/testjwt.c @@ -257,6 +257,13 @@ main(int argc, // I - Number of command-line arguments cupsJSONDelete(jwk); cupsJSONDelete(pubjwk); + // Signing with a key whose curve is larger than the algorithm (ES256 wants + // P-256, this is P-521) has to fail rather than write past the signature... + testBegin("cupsJWTSign(ES256 with mismatched P-521 key)"); + jwk = cupsJWTMakePrivateKey(CUPS_JWA_ES512); + testEnd(!cupsJWTSign(jwt, CUPS_JWA_ES256, jwk)); + cupsJSONDelete(jwk); + testBegin("cupsJWTDelete()"); cupsJWTDelete(jwt); testEnd(true);