2 * Hashing function for CUPS.
4 * Copyright 2015-2016 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 * file is 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>
24 #endif /* __APPLE__ */
28 * 'cupsHashData()' - Perform a hash function on the given data.
30 * The "algorithm" argument can be any of the registered, non-deprecated IPP
31 * hash algorithms for the "job-password-encryption" attribute, including
32 * "sha" for SHA-1, "sha-256" for SHA2-256, etc.
34 * The "hash" argument points to a buffer of "hashsize" bytes and should be at
35 * least 64 bytes in length for all of the supported algorithms.
37 * The returned hash is binary data.
39 * @since CUPS 2.2/macOS 10.12@
42 ssize_t
/* O - Size of hash or -1 on error */
43 cupsHashData(const char *algorithm
, /* I - Algorithm name */
44 const void *data
, /* I - Data to hash */
45 size_t datalen
, /* I - Length of data to hash */
46 unsigned char *hash
, /* I - Hash buffer */
47 size_t hashsize
) /* I - Size of hash buffer */
49 if (!algorithm
|| !data
|| datalen
== 0 || !hash
|| hashsize
== 0)
51 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, _("Bad arguments to function"), 1);
56 if (!strcmp(algorithm
, "sha"))
62 CC_SHA1_CTX ctx
; /* SHA-1 context */
64 if (hashsize
< CC_SHA1_DIGEST_LENGTH
)
68 CC_SHA1_Update(&ctx
, data
, (CC_LONG
)datalen
);
69 CC_SHA1_Final(hash
, &ctx
);
71 return (CC_SHA1_DIGEST_LENGTH
);
73 else if (!strcmp(algorithm
, "sha2-224"))
75 CC_SHA256_CTX ctx
; /* SHA-224 context */
77 if (hashsize
< CC_SHA224_DIGEST_LENGTH
)
81 CC_SHA224_Update(&ctx
, data
, (CC_LONG
)datalen
);
82 CC_SHA224_Final(hash
, &ctx
);
84 return (CC_SHA224_DIGEST_LENGTH
);
86 else if (!strcmp(algorithm
, "sha2-256"))
88 CC_SHA256_CTX ctx
; /* SHA-256 context */
90 if (hashsize
< CC_SHA256_DIGEST_LENGTH
)
94 CC_SHA256_Update(&ctx
, data
, (CC_LONG
)datalen
);
95 CC_SHA256_Final(hash
, &ctx
);
97 return (CC_SHA256_DIGEST_LENGTH
);
99 else if (!strcmp(algorithm
, "sha2-384"))
101 CC_SHA512_CTX ctx
; /* SHA-384 context */
103 if (hashsize
< CC_SHA384_DIGEST_LENGTH
)
106 CC_SHA384_Init(&ctx
);
107 CC_SHA384_Update(&ctx
, data
, (CC_LONG
)datalen
);
108 CC_SHA384_Final(hash
, &ctx
);
110 return (CC_SHA384_DIGEST_LENGTH
);
112 else if (!strcmp(algorithm
, "sha2-512"))
114 CC_SHA512_CTX ctx
; /* SHA-512 context */
116 if (hashsize
< CC_SHA512_DIGEST_LENGTH
)
119 CC_SHA512_Init(&ctx
);
120 CC_SHA512_Update(&ctx
, data
, (CC_LONG
)datalen
);
121 CC_SHA512_Final(hash
, &ctx
);
123 return (CC_SHA512_DIGEST_LENGTH
);
125 else if (!strcmp(algorithm
, "sha2-512_224"))
127 CC_SHA512_CTX ctx
; /* SHA-512 context */
128 unsigned char temp
[CC_SHA512_DIGEST_LENGTH
];
132 * SHA2-512 truncated to 224 bits (28 bytes)...
135 if (hashsize
< CC_SHA224_DIGEST_LENGTH
)
138 CC_SHA512_Init(&ctx
);
139 CC_SHA512_Update(&ctx
, data
, (CC_LONG
)datalen
);
140 CC_SHA512_Final(temp
, &ctx
);
142 memcpy(hash
, temp
, CC_SHA224_DIGEST_LENGTH
);
144 return (CC_SHA224_DIGEST_LENGTH
);
146 else if (!strcmp(algorithm
, "sha2-512_256"))
148 CC_SHA512_CTX ctx
; /* SHA-512 context */
149 unsigned char temp
[CC_SHA512_DIGEST_LENGTH
];
153 * SHA2-512 truncated to 256 bits (32 bytes)...
156 if (hashsize
< CC_SHA256_DIGEST_LENGTH
)
159 CC_SHA512_Init(&ctx
);
160 CC_SHA512_Update(&ctx
, data
, (CC_LONG
)datalen
);
161 CC_SHA512_Final(temp
, &ctx
);
163 memcpy(hash
, temp
, CC_SHA256_DIGEST_LENGTH
);
165 return (CC_SHA256_DIGEST_LENGTH
);
168 #elif defined(HAVE_GNUTLS)
169 gnutls_digest_algorithm_t alg
= GNUTLS_DIG_UNKNOWN
;
171 unsigned char temp
[64]; /* Temporary hash buffer */
172 size_t tempsize
= 0; /* Truncate to this size? */
174 if (!strcmp(algorithm
, "sha"))
175 alg
= GNUTLS_DIG_SHA1
;
176 else if (!strcmp(algorithm
, "sha2-224"))
177 alg
= GNUTLS_DIG_SHA224
;
178 else if (!strcmp(algorithm
, "sha2-256"))
179 alg
= GNUTLS_DIG_SHA256
;
180 else if (!strcmp(algorithm
, "sha2-384"))
181 alg
= GNUTLS_DIG_SHA384
;
182 else if (!strcmp(algorithm
, "sha2-512"))
183 alg
= GNUTLS_DIG_SHA512
;
184 else if (!strcmp(algorithm
, "sha2-512_224"))
186 alg
= GNUTLS_DIG_SHA512
;
189 else if (!strcmp(algorithm
, "sha2-512_256"))
191 alg
= GNUTLS_DIG_SHA512
;
195 if (alg
!= GNUTLS_DIG_UNKNOWN
)
200 * Truncate result to tempsize bytes...
203 if (hashsize
< tempsize
)
206 gnutls_hash_fast(alg
, data
, datalen
, temp
);
207 memcpy(hash
, temp
, tempsize
);
209 return ((ssize_t
)tempsize
);
212 if (hashsize
< gnutls_hash_get_len(alg
))
215 gnutls_hash_fast(alg
, data
, datalen
, hash
);
217 return (gnutls_hash_get_len(alg
));
222 * No hash support without CommonCrypto or GNU TLS...
227 #endif /* __APPLE__ */
230 * Unknown hash algorithm...
233 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, _("Unknown hash algorithm."), 1);
238 * We get here if the buffer is too small.
243 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, _("Hash buffer too small."), 1);