2 * Hashing function for CUPS.
4 * Copyright 2015-2017 by Apple Inc.
6 * These coded instructions, statements, and computer programs are the
7 * property of Apple Inc. and are protected by Federal copyright
8 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
9 * which should have been included with this file. If this file is
10 * missing or damaged, see the license at "http://www.cups.org/".
12 * This file is subject to the Apple OS-Developed Software exception.
16 * Include necessary headers...
19 #include "cups-private.h"
21 # include <CommonCrypto/CommonDigest.h>
22 #elif defined(HAVE_GNUTLS)
23 # include <gnutls/crypto.h>
25 # include "md5-private.h"
26 #endif /* __APPLE__ */
30 * 'cupsHashData()' - Perform a hash function on the given data.
32 * The "algorithm" argument can be any of the registered, non-deprecated IPP
33 * hash algorithms for the "job-password-encryption" attribute, including
34 * "sha" for SHA-1, "sha-256" for SHA2-256, etc.
36 * The "hash" argument points to a buffer of "hashsize" bytes and should be at
37 * least 64 bytes in length for all of the supported algorithms.
39 * The returned hash is binary data.
41 * @since CUPS 2.2/macOS 10.12@
44 ssize_t
/* O - Size of hash or -1 on error */
45 cupsHashData(const char *algorithm
, /* I - Algorithm name */
46 const void *data
, /* I - Data to hash */
47 size_t datalen
, /* I - Length of data to hash */
48 unsigned char *hash
, /* I - Hash buffer */
49 size_t hashsize
) /* I - Size of hash buffer */
51 if (!algorithm
|| !data
|| datalen
== 0 || !hash
|| hashsize
== 0)
53 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, _("Bad arguments to function"), 1);
58 if (!strcmp(algorithm
, "md5"))
61 * MD5 (deprecated but widely used...)
64 CC_MD5_CTX ctx
; /* MD5 context */
66 if (hashsize
< CC_MD5_DIGEST_LENGTH
)
70 CC_MD5_Update(&ctx
, data
, (CC_LONG
)datalen
);
71 CC_MD5_Final(hash
, &ctx
);
73 return (CC_MD5_DIGEST_LENGTH
);
75 else if (!strcmp(algorithm
, "sha"))
81 CC_SHA1_CTX ctx
; /* SHA-1 context */
83 if (hashsize
< CC_SHA1_DIGEST_LENGTH
)
87 CC_SHA1_Update(&ctx
, data
, (CC_LONG
)datalen
);
88 CC_SHA1_Final(hash
, &ctx
);
90 return (CC_SHA1_DIGEST_LENGTH
);
92 else if (!strcmp(algorithm
, "sha2-224"))
94 CC_SHA256_CTX ctx
; /* SHA-224 context */
96 if (hashsize
< CC_SHA224_DIGEST_LENGTH
)
100 CC_SHA224_Update(&ctx
, data
, (CC_LONG
)datalen
);
101 CC_SHA224_Final(hash
, &ctx
);
103 return (CC_SHA224_DIGEST_LENGTH
);
105 else if (!strcmp(algorithm
, "sha2-256"))
107 CC_SHA256_CTX ctx
; /* SHA-256 context */
109 if (hashsize
< CC_SHA256_DIGEST_LENGTH
)
112 CC_SHA256_Init(&ctx
);
113 CC_SHA256_Update(&ctx
, data
, (CC_LONG
)datalen
);
114 CC_SHA256_Final(hash
, &ctx
);
116 return (CC_SHA256_DIGEST_LENGTH
);
118 else if (!strcmp(algorithm
, "sha2-384"))
120 CC_SHA512_CTX ctx
; /* SHA-384 context */
122 if (hashsize
< CC_SHA384_DIGEST_LENGTH
)
125 CC_SHA384_Init(&ctx
);
126 CC_SHA384_Update(&ctx
, data
, (CC_LONG
)datalen
);
127 CC_SHA384_Final(hash
, &ctx
);
129 return (CC_SHA384_DIGEST_LENGTH
);
131 else if (!strcmp(algorithm
, "sha2-512"))
133 CC_SHA512_CTX ctx
; /* SHA-512 context */
135 if (hashsize
< CC_SHA512_DIGEST_LENGTH
)
138 CC_SHA512_Init(&ctx
);
139 CC_SHA512_Update(&ctx
, data
, (CC_LONG
)datalen
);
140 CC_SHA512_Final(hash
, &ctx
);
142 return (CC_SHA512_DIGEST_LENGTH
);
144 else if (!strcmp(algorithm
, "sha2-512_224"))
146 CC_SHA512_CTX ctx
; /* SHA-512 context */
147 unsigned char temp
[CC_SHA512_DIGEST_LENGTH
];
151 * SHA2-512 truncated to 224 bits (28 bytes)...
154 if (hashsize
< CC_SHA224_DIGEST_LENGTH
)
157 CC_SHA512_Init(&ctx
);
158 CC_SHA512_Update(&ctx
, data
, (CC_LONG
)datalen
);
159 CC_SHA512_Final(temp
, &ctx
);
161 memcpy(hash
, temp
, CC_SHA224_DIGEST_LENGTH
);
163 return (CC_SHA224_DIGEST_LENGTH
);
165 else if (!strcmp(algorithm
, "sha2-512_256"))
167 CC_SHA512_CTX ctx
; /* SHA-512 context */
168 unsigned char temp
[CC_SHA512_DIGEST_LENGTH
];
172 * SHA2-512 truncated to 256 bits (32 bytes)...
175 if (hashsize
< CC_SHA256_DIGEST_LENGTH
)
178 CC_SHA512_Init(&ctx
);
179 CC_SHA512_Update(&ctx
, data
, (CC_LONG
)datalen
);
180 CC_SHA512_Final(temp
, &ctx
);
182 memcpy(hash
, temp
, CC_SHA256_DIGEST_LENGTH
);
184 return (CC_SHA256_DIGEST_LENGTH
);
187 #elif defined(HAVE_GNUTLS)
188 gnutls_digest_algorithm_t alg
= GNUTLS_DIG_UNKNOWN
;
190 unsigned char temp
[64]; /* Temporary hash buffer */
191 size_t tempsize
= 0; /* Truncate to this size? */
193 if (!strcmp(algorithm
, "md5"))
194 alg
= GNUTLS_DIG_MD5
;
195 else if (!strcmp(algorithm
, "sha"))
196 alg
= GNUTLS_DIG_SHA1
;
197 else if (!strcmp(algorithm
, "sha2-224"))
198 alg
= GNUTLS_DIG_SHA224
;
199 else if (!strcmp(algorithm
, "sha2-256"))
200 alg
= GNUTLS_DIG_SHA256
;
201 else if (!strcmp(algorithm
, "sha2-384"))
202 alg
= GNUTLS_DIG_SHA384
;
203 else if (!strcmp(algorithm
, "sha2-512"))
204 alg
= GNUTLS_DIG_SHA512
;
205 else if (!strcmp(algorithm
, "sha2-512_224"))
207 alg
= GNUTLS_DIG_SHA512
;
210 else if (!strcmp(algorithm
, "sha2-512_256"))
212 alg
= GNUTLS_DIG_SHA512
;
216 if (alg
!= GNUTLS_DIG_UNKNOWN
)
221 * Truncate result to tempsize bytes...
224 if (hashsize
< tempsize
)
227 gnutls_hash_fast(alg
, data
, datalen
, temp
);
228 memcpy(hash
, temp
, tempsize
);
230 return ((ssize_t
)tempsize
);
233 if (hashsize
< gnutls_hash_get_len(alg
))
236 gnutls_hash_fast(alg
, data
, datalen
, hash
);
238 return (gnutls_hash_get_len(alg
));
243 * No hash support beyond MD5 without CommonCrypto or GNU TLS...
246 if (!strcmp(algorithm
, "md5"))
248 _cups_md5_state_t state
; /* MD5 state info */
250 _cupsMD5Init(&state
);
251 _cupsMD5Append(&state
, data
, datalen
);
252 _cupsMD5Finish(&state
, hash
);
256 else if (hashsize
< 64)
258 #endif /* __APPLE__ */
261 * Unknown hash algorithm...
264 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, _("Unknown hash algorithm."), 1);
269 * We get here if the buffer is too small.
274 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, _("Hash buffer too small."), 1);
280 * 'cupsHashString()' - Format a hash value as a hexadecimal string.
282 * The passed buffer must be at least 2 * hashsize + 1 characters in length.
285 const char * /* O - Formatted string */
287 const unsigned char *hash
, /* I - Hash */
288 size_t hashsize
, /* I - Size of hash */
289 char *buffer
, /* I - String buffer */
290 size_t bufsize
) /* I - Size of string buffer */
292 char *bufptr
= buffer
; /* Pointer into buffer */
293 static const char *hex
= "0123456789abcdef";
294 /* Hex characters (lowercase!) */
298 * Range check input...
301 if (!hash
|| hashsize
< 1 || !buffer
|| bufsize
< (2 * hashsize
+ 1))
309 * Loop until we've converted the whole hash...
314 *bufptr
++ = hex
[*hash
>> 4];
315 *bufptr
++ = hex
[*hash
& 15];