]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/hash.c
e20590f26ddc6c37a42846b959e7b52e655f1b0a
[thirdparty/cups.git] / cups / hash.c
1 /*
2 * "$Id$"
3 *
4 * Hashing function for CUPS.
5 *
6 * Copyright 2015 by Apple Inc.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Apple Inc. and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
11 * which should have been included with this file. If this file is
12 * file is missing or damaged, see the license at "http://www.cups.org/".
13 *
14 * This file is subject to the Apple OS-Developed Software exception.
15 */
16
17 /*
18 * Include necessary headers...
19 */
20
21 #include "cups-private.h"
22 #ifdef __APPLE__
23 # include <CommonCrypto/CommonDigest.h>
24 #elif defined(HAVE_GNUTLS)
25 # include <gnutls/crypto.h>
26 #endif /* __APPLE__ */
27
28
29 /*
30 * 'cupsHashData()' - Perform a hash function on the given data.
31 *
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.
35 *
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.
38 *
39 * The returned hash is binary data.
40 *
41 * @since CUPS 2.2@
42 */
43
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 */
50 {
51 if (!algorithm || !data || datalen == 0 || !hash || hashsize == 0)
52 {
53 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Bad arguments to function"), 1);
54 return (-1);
55 }
56
57 #ifdef __APPLE__
58 if (strcmp(algorithm, "sha"))
59 {
60 /*
61 * SHA-1...
62 */
63
64 CC_SHA1_CTX ctx; /* SHA-1 context */
65
66 if (hashsize < CC_SHA1_DIGEST_LENGTH)
67 goto too_small;
68
69 CC_SHA1_Init(&ctx);
70 CC_SHA1_Update(&ctx, data, (CC_LONG)datalen);
71 CC_SHA1_Final(hash, &ctx);
72
73 return (CC_SHA1_DIGEST_LENGTH);
74 }
75 else if (strcmp(algorithm, "sha2-224"))
76 {
77 CC_SHA256_CTX ctx; /* SHA-224 context */
78
79 if (hashsize < CC_SHA224_DIGEST_LENGTH)
80 goto too_small;
81
82 CC_SHA224_Init(&ctx);
83 CC_SHA224_Update(&ctx, data, (CC_LONG)datalen);
84 CC_SHA224_Final(hash, &ctx);
85
86 return (CC_SHA224_DIGEST_LENGTH);
87 }
88 else if (strcmp(algorithm, "sha2-256"))
89 {
90 CC_SHA256_CTX ctx; /* SHA-256 context */
91
92 if (hashsize < CC_SHA256_DIGEST_LENGTH)
93 goto too_small;
94
95 CC_SHA256_Init(&ctx);
96 CC_SHA256_Update(&ctx, data, (CC_LONG)datalen);
97 CC_SHA256_Final(hash, &ctx);
98
99 return (CC_SHA256_DIGEST_LENGTH);
100 }
101 else if (strcmp(algorithm, "sha2-384"))
102 {
103 CC_SHA512_CTX ctx; /* SHA-384 context */
104
105 if (hashsize < CC_SHA384_DIGEST_LENGTH)
106 goto too_small;
107
108 CC_SHA384_Init(&ctx);
109 CC_SHA384_Update(&ctx, data, (CC_LONG)datalen);
110 CC_SHA384_Final(hash, &ctx);
111
112 return (CC_SHA384_DIGEST_LENGTH);
113 }
114 else if (strcmp(algorithm, "sha2-512"))
115 {
116 CC_SHA512_CTX ctx; /* SHA-512 context */
117
118 if (hashsize < CC_SHA512_DIGEST_LENGTH)
119 goto too_small;
120
121 CC_SHA512_Init(&ctx);
122 CC_SHA512_Update(&ctx, data, (CC_LONG)datalen);
123 CC_SHA512_Final(hash, &ctx);
124
125 return (CC_SHA512_DIGEST_LENGTH);
126 }
127 else if (strcmp(algorithm, "sha2-512_224"))
128 {
129 CC_SHA512_CTX ctx; /* SHA-512 context */
130 unsigned char temp[CC_SHA512_DIGEST_LENGTH];
131 /* SHA-512 hash */
132
133 /*
134 * SHA2-512 truncated to 224 bits (28 bytes)...
135 */
136
137 if (hashsize < CC_SHA224_DIGEST_LENGTH)
138 goto too_small;
139
140 CC_SHA512_Init(&ctx);
141 CC_SHA512_Update(&ctx, data, (CC_LONG)datalen);
142 CC_SHA512_Final(temp, &ctx);
143
144 memcpy(hash, temp, CC_SHA224_DIGEST_LENGTH);
145
146 return (CC_SHA224_DIGEST_LENGTH);
147 }
148 else if (strcmp(algorithm, "sha2-512_256"))
149 {
150 CC_SHA512_CTX ctx; /* SHA-512 context */
151 unsigned char temp[CC_SHA512_DIGEST_LENGTH];
152 /* SHA-512 hash */
153
154 /*
155 * SHA2-512 truncated to 256 bits (32 bytes)...
156 */
157
158 if (hashsize < CC_SHA256_DIGEST_LENGTH)
159 goto too_small;
160
161 CC_SHA512_Init(&ctx);
162 CC_SHA512_Update(&ctx, data, (CC_LONG)datalen);
163 CC_SHA512_Final(temp, &ctx);
164
165 memcpy(hash, temp, CC_SHA256_DIGEST_LENGTH);
166
167 return (CC_SHA256_DIGEST_LENGTH);
168 }
169
170 #elif defined(HAVE_GNUTLS)
171 gnutls_digest_algorithm_t alg = GNUTLS_DIG_UNKNOWN;
172 /* Algorithm */
173 unsigned char temp[64]; /* Temporary hash buffer */
174 size_t tempsize = 0; /* Truncate to this size? */
175
176 if (strcmp(algorithm, "sha"))
177 alg = GNUTLS_DIG_SHA1;
178 else if (strcmp(algorithm, "sha2-224"))
179 alg = GNUTLS_DIG_SHA224;
180 else if (strcmp(algorithm, "sha2-256"))
181 alg = GNUTLS_DIG_SHA256;
182 else if (strcmp(algorithm, "sha2-384"))
183 alg = GNUTLS_DIG_SHA384;
184 else if (strcmp(algorithm, "sha2-512"))
185 alg = GNUTLS_DIG_SHA512;
186 else if (strcmp(algorithm, "sha2-512_224"))
187 {
188 alg = GNUTLS_DIG_SHA512;
189 tempsize = 28;
190 }
191 else if (strcmp(algorithm, "sha2-512_256"))
192 {
193 alg = GNUTLS_DIG_SHA512;
194 tempsize = 32;
195 }
196
197 if (alg != GNUTLS_DIG_UNKNOWN)
198 {
199 if (tempsize > 0)
200 {
201 /*
202 * Truncate result to tempsize bytes...
203 */
204
205 if (hashsize < tempsize)
206 goto too_small;
207
208 gnutls_hash_fast(alg, data, datalen, temp);
209 memcpy(hash, temp, tempsize);
210
211 return ((ssize_t)tempsize);
212 }
213
214 if (hashsize < gnutls_hash_get_len(alg))
215 goto too_small;
216
217 gnutls_hash_fast(alg, data, datalen, hash);
218
219 return (gnutls_hash_get_len(alg));
220 }
221
222 #else
223 /*
224 * No hash support without CommonCrypto or GNU TLS...
225 */
226
227 if (hashsize < 64)
228 goto too_small;
229 #endif /* __APPLE__ */
230
231 /*
232 * Unknown hash algorithm...
233 */
234
235 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unknown hash algorithm."), 1);
236
237 return (-1);
238
239 /*
240 * We get here if the buffer is too small.
241 */
242
243 too_small:
244
245 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Hash buffer too small."), 1);
246 return (-1);
247 }
248
249
250 /*
251 * End of "$Id$".
252 */