1From c6cd5e9c10edc68caf6936a3d3274f758e9cd03d Mon Sep 17 00:00:00 2001 2From: Zdenek Dohnal <zdohnal@redhat.com> 3Date: Tue, 3 Oct 2023 13:59:40 +0200 4Subject: [PATCH] cups/hash.c: Put support for MacOS/Win SSL libs back 5 6- I mustn't remove their support in patch release - this should happen in 72.5 only. 8- I have put back support for several hashes as well - they 9should be removed in 2.5. 10- restrict usage of second block hashing only if OpenSSL/LibreSSL/GnuTLS 11 is available 12 13Upstream: https://github.com/OpenPrinting/cups/commit/c6cd5e9c10edc68caf6936a3d3274f758e9cd03d 14Signed-off-by: Fabrice Fontaine <fontaine.fabrice@gmail.com> 15--- 16 cups/hash.c | 271 +++++++++++++++++++++++++++++++++++++++++++++++++--- 17 1 file changed, 260 insertions(+), 11 deletions(-) 18 19diff --git a/cups/hash.c b/cups/hash.c 20index 93ca552c8..c447bab4e 100644 21--- a/cups/hash.c 22+++ b/cups/hash.c 23@@ -12,8 +12,13 @@ 24 #include "md5-internal.h" 25 #ifdef HAVE_OPENSSL 26 # include <openssl/evp.h> 27-#else // HAVE_GNUTLS 28+#elif defined(HAVE_GNUTLS) 29 # include <gnutls/crypto.h> 30+#elif __APPLE__ 31+# include <CommonCrypto/CommonDigest.h> 32+#elif _WIN32 33+# include <windows.h> 34+# include <bcrypt.h> 35 #endif // HAVE_OPENSSL 36 37 38@@ -193,17 +198,18 @@ hash_data(const char *algorithm, // I - Algorithm 39 const void *b, // I - Second block or `NULL` for none 40 size_t blen) // I - Length of second block or `0` for none 41 { 42+#if defined(HAVE_OPENSSL) || defined(HAVE_GNUTLS) 43 unsigned hashlen; // Length of hash 44 unsigned char hashtemp[64]; // Temporary hash buffer 45-#ifdef HAVE_OPENSSL 46- const EVP_MD *md = NULL; // Message digest implementation 47- EVP_MD_CTX *ctx; // Context 48-#else // HAVE_GNUTLS 49- gnutls_digest_algorithm_t alg = GNUTLS_DIG_UNKNOWN; 50- // Algorithm 51- gnutls_hash_hd_t ctx; // Context 52-#endif // HAVE_OPENSSL 53+#else 54+ if (strcmp(algorithm, "md5") && (b || blen != 0)) 55+ { 56+ // Second block hashing is not supported without OpenSSL or GnuTLS 57+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unsupported without GnuTLS or OpenSSL/LibreSSL."), 1); 58 59+ return (-1); 60+ } 61+#endif 62 63 if (!strcmp(algorithm, "md5")) 64 { 65@@ -223,6 +229,10 @@ hash_data(const char *algorithm, // I - Algorithm 66 } 67 68 #ifdef HAVE_OPENSSL 69+ const EVP_MD *md = NULL; // Message digest implementation 70+ EVP_MD_CTX *ctx; // Context 71+ 72+ 73 if (!strcmp(algorithm, "sha")) 74 { 75 // SHA-1 76@@ -244,6 +254,14 @@ hash_data(const char *algorithm, // I - Algorithm 77 { 78 md = EVP_sha512(); 79 } 80+ else if (!strcmp(algorithm, "sha2-512_224")) 81+ { 82+ md = EVP_sha512_224(); 83+ } 84+ else if (!strcmp(algorithm, "sha2-512_256")) 85+ { 86+ md = EVP_sha512_256(); 87+ } 88 89 if (md) 90 { 91@@ -262,7 +280,13 @@ hash_data(const char *algorithm, // I - Algorithm 92 return ((ssize_t)hashlen); 93 } 94 95-#else // HAVE_GNUTLS 96+#elif defined(HAVE_GNUTLS) 97+ gnutls_digest_algorithm_t alg = GNUTLS_DIG_UNKNOWN; // Algorithm 98+ gnutls_hash_hd_t ctx; // Context 99+ unsigned char temp[64]; // Temporary hash buffer 100+ size_t tempsize = 0; // Truncate to this size? 101+ 102+ 103 if (!strcmp(algorithm, "sha")) 104 { 105 // SHA-1 106@@ -284,9 +308,32 @@ hash_data(const char *algorithm, // I - Algorithm 107 { 108 alg = GNUTLS_DIG_SHA512; 109 } 110+ else if (!strcmp(algorithm, "sha2-512_224")) 111+ { 112+ alg = GNUTLS_DIG_SHA512; 113+ tempsize = 28; 114+ } 115+ else if (!strcmp(algorithm, "sha2-512_256")) 116+ { 117+ alg = GNUTLS_DIG_SHA512; 118+ tempsize = 32; 119+ } 120 121 if (alg != GNUTLS_DIG_UNKNOWN) 122 { 123+ if (tempsize > 0) 124+ { 125+ // Truncate result to tempsize bytes... 126+ 127+ if (hashsize < tempsize) 128+ goto too_small; 129+ 130+ gnutls_hash_fast(alg, a, alen, temp); 131+ memcpy(hash, temp, tempsize); 132+ 133+ return ((ssize_t)tempsize); 134+ } 135+ 136 hashlen = gnutls_hash_get_len(alg); 137 138 if (hashlen > hashsize) 139@@ -302,7 +349,209 @@ hash_data(const char *algorithm, // I - Algorithm 140 141 return ((ssize_t)hashlen); 142 } 143-#endif // HAVE_OPENSSL 144+ 145+#elif __APPLE__ 146+ if (!strcmp(algorithm, "sha")) 147+ { 148+ // SHA-1... 149+ 150+ CC_SHA1_CTX ctx; // SHA-1 context 151+ 152+ if (hashsize < CC_SHA1_DIGEST_LENGTH) 153+ goto too_small; 154+ 155+ CC_SHA1_Init(&ctx); 156+ CC_SHA1_Update(&ctx, a, (CC_LONG)alen); 157+ CC_SHA1_Final(hash, &ctx); 158+ 159+ return (CC_SHA1_DIGEST_LENGTH); 160+ } 161+# ifdef CC_SHA224_DIGEST_LENGTH 162+ else if (!strcmp(algorithm, "sha2-224")) 163+ { 164+ CC_SHA256_CTX ctx; // SHA-224 context 165+ 166+ if (hashsize < CC_SHA224_DIGEST_LENGTH) 167+ goto too_small; 168+ 169+ CC_SHA224_Init(&ctx); 170+ CC_SHA224_Update(&ctx, a, (CC_LONG)alen); 171+ CC_SHA224_Final(hash, &ctx); 172+ 173+ return (CC_SHA224_DIGEST_LENGTH); 174+ } 175+# endif /* CC_SHA224_DIGEST_LENGTH */ 176+ else if (!strcmp(algorithm, "sha2-256")) 177+ { 178+ CC_SHA256_CTX ctx; // SHA-256 context 179+ 180+ if (hashsize < CC_SHA256_DIGEST_LENGTH) 181+ goto too_small; 182+ 183+ CC_SHA256_Init(&ctx); 184+ CC_SHA256_Update(&ctx, a, (CC_LONG)alen); 185+ CC_SHA256_Final(hash, &ctx); 186+ 187+ return (CC_SHA256_DIGEST_LENGTH); 188+ } 189+ else if (!strcmp(algorithm, "sha2-384")) 190+ { 191+ CC_SHA512_CTX ctx; // SHA-384 context 192+ 193+ if (hashsize < CC_SHA384_DIGEST_LENGTH) 194+ goto too_small; 195+ 196+ CC_SHA384_Init(&ctx); 197+ CC_SHA384_Update(&ctx, a, (CC_LONG)alen); 198+ CC_SHA384_Final(hash, &ctx); 199+ 200+ return (CC_SHA384_DIGEST_LENGTH); 201+ } 202+ else if (!strcmp(algorithm, "sha2-512")) 203+ { 204+ CC_SHA512_CTX ctx; // SHA-512 context 205+ 206+ if (hashsize < CC_SHA512_DIGEST_LENGTH) 207+ goto too_small; 208+ 209+ CC_SHA512_Init(&ctx); 210+ CC_SHA512_Update(&ctx, a, (CC_LONG)alen); 211+ CC_SHA512_Final(hash, &ctx); 212+ 213+ return (CC_SHA512_DIGEST_LENGTH); 214+ } 215+# ifdef CC_SHA224_DIGEST_LENGTH 216+ else if (!strcmp(algorithm, "sha2-512_224")) 217+ { 218+ CC_SHA512_CTX ctx; // SHA-512 context 219+ unsigned char temp[CC_SHA512_DIGEST_LENGTH]; 220+ // SHA-512 hash 221+ 222+ // SHA2-512 truncated to 224 bits (28 bytes)... 223+ 224+ if (hashsize < CC_SHA224_DIGEST_LENGTH) 225+ goto too_small; 226+ 227+ CC_SHA512_Init(&ctx); 228+ CC_SHA512_Update(&ctx, a, (CC_LONG)alen); 229+ CC_SHA512_Final(temp, &ctx); 230+ 231+ memcpy(hash, temp, CC_SHA224_DIGEST_LENGTH); 232+ 233+ return (CC_SHA224_DIGEST_LENGTH); 234+ } 235+# endif // CC_SHA224_DIGEST_LENGTH 236+ else if (!strcmp(algorithm, "sha2-512_256")) 237+ { 238+ CC_SHA512_CTX ctx; // SHA-512 context 239+ unsigned char temp[CC_SHA512_DIGEST_LENGTH]; 240+ // SHA-512 hash 241+ 242+ // SHA2-512 truncated to 256 bits (32 bytes)... 243+ 244+ if (hashsize < CC_SHA256_DIGEST_LENGTH) 245+ goto too_small; 246+ 247+ CC_SHA512_Init(&ctx); 248+ CC_SHA512_Update(&ctx, a, (CC_LONG)alen); 249+ CC_SHA512_Final(temp, &ctx); 250+ 251+ memcpy(hash, temp, CC_SHA256_DIGEST_LENGTH); 252+ 253+ return (CC_SHA256_DIGEST_LENGTH); 254+ } 255+ 256+#elif _WIN32 257+ // Use Windows CNG APIs to perform hashing... 258+ BCRYPT_ALG_HANDLE alg; // Algorithm handle 259+ LPCWSTR algid = NULL; // Algorithm ID 260+ ssize_t hashlen; // Hash length 261+ NTSTATUS status; // Status of hash 262+ unsigned char temp[64]; // Temporary hash buffer 263+ size_t tempsize = 0; // Truncate to this size? 264+ 265+ 266+ if (!strcmp(algorithm, "sha")) 267+ { 268+ algid = BCRYPT_SHA1_ALGORITHM; 269+ hashlen = 20; 270+ } 271+ else if (!strcmp(algorithm, "sha2-256")) 272+ { 273+ algid = BCRYPT_SHA256_ALGORITHM; 274+ hashlen = 32; 275+ } 276+ else if (!strcmp(algorithm, "sha2-384")) 277+ { 278+ algid = BCRYPT_SHA384_ALGORITHM; 279+ hashlen = 48; 280+ } 281+ else if (!strcmp(algorithm, "sha2-512")) 282+ { 283+ algid = BCRYPT_SHA512_ALGORITHM; 284+ hashlen = 64; 285+ } 286+ else if (!strcmp(algorithm, "sha2-512_224")) 287+ { 288+ algid = BCRYPT_SHA512_ALGORITHM; 289+ hashlen = tempsize = 28; 290+ } 291+ else if (!strcmp(algorithm, "sha2-512_256")) 292+ { 293+ algid = BCRYPT_SHA512_ALGORITHM; 294+ hashlen = tempsize = 32; 295+ } 296+ 297+ if (algid) 298+ { 299+ if (hashsize < (size_t)hashlen) 300+ goto too_small; 301+ 302+ if ((status = BCryptOpenAlgorithmProvider(&alg, algid, NULL, 0)) < 0) 303+ { 304+ DEBUG_printf(("2cupsHashData: BCryptOpenAlgorithmProvider returned %d.", status)); 305+ 306+ if (status == STATUS_INVALID_PARAMETER) 307+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad algorithm parameter."), 1); 308+ else 309+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unable to access cryptographic provider."), 1); 310+ 311+ return (-1); 312+ } 313+ 314+ if (tempsize > 0) 315+ { 316+ // Do a truncated SHA2-512 hash... 317+ status = BCryptHash(alg, NULL, 0, (PUCHAR)a, (ULONG)alen, temp, sizeof(temp)); 318+ memcpy(hash, temp, hashlen); 319+ } 320+ else 321+ { 322+ // Hash directly to buffer... 323+ status = BCryptHash(alg, NULL, 0, (PUCHAR)a, (ULONG)alen, hash, (ULONG)hashlen); 324+ } 325+ 326+ BCryptCloseAlgorithmProvider(alg, 0); 327+ 328+ if (status < 0) 329+ { 330+ DEBUG_printf(("2cupsHashData: BCryptHash returned %d.", status)); 331+ 332+ if (status == STATUS_INVALID_PARAMETER) 333+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad hashing parameter."), 1); 334+ else 335+ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Hashing failed."), 1); 336+ 337+ return (-1); 338+ } 339+ 340+ return (hashlen); 341+ } 342+ 343+#else 344+ if (hashsize < 64) 345+ goto too_small; 346+#endif // __APPLE__ 347 348 // Unknown hash algorithm... 349 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unknown hash algorithm."), 1); 350