4 * Hashing function for CUPS.
6 * Copyright 2015 by Apple Inc.
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/".
14 * This file is subject to the Apple OS-Developed Software exception.
18 * Include necessary headers...
21 #include "cups-private.h"
23 # include <CommonCrypto/CommonDigest.h>
24 #elif defined(HAVE_GNUTLS)
25 # include <gnutls/crypto.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.
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
, "sha"))
64 CC_SHA1_CTX ctx
; /* SHA-1 context */
66 if (hashsize
< CC_SHA1_DIGEST_LENGTH
)
70 CC_SHA1_Update(&ctx
, data
, (CC_LONG
)datalen
);
71 CC_SHA1_Final(hash
, &ctx
);
73 return (CC_SHA1_DIGEST_LENGTH
);
75 else if (strcmp(algorithm
, "sha2-224"))
77 CC_SHA256_CTX ctx
; /* SHA-224 context */
79 if (hashsize
< CC_SHA224_DIGEST_LENGTH
)
83 CC_SHA224_Update(&ctx
, data
, (CC_LONG
)datalen
);
84 CC_SHA224_Final(hash
, &ctx
);
86 return (CC_SHA224_DIGEST_LENGTH
);
88 else if (strcmp(algorithm
, "sha2-256"))
90 CC_SHA256_CTX ctx
; /* SHA-256 context */
92 if (hashsize
< CC_SHA256_DIGEST_LENGTH
)
96 CC_SHA256_Update(&ctx
, data
, (CC_LONG
)datalen
);
97 CC_SHA256_Final(hash
, &ctx
);
99 return (CC_SHA256_DIGEST_LENGTH
);
101 else if (strcmp(algorithm
, "sha2-384"))
103 CC_SHA512_CTX ctx
; /* SHA-384 context */
105 if (hashsize
< CC_SHA384_DIGEST_LENGTH
)
108 CC_SHA384_Init(&ctx
);
109 CC_SHA384_Update(&ctx
, data
, (CC_LONG
)datalen
);
110 CC_SHA384_Final(hash
, &ctx
);
112 return (CC_SHA384_DIGEST_LENGTH
);
114 else if (strcmp(algorithm
, "sha2-512"))
116 CC_SHA512_CTX ctx
; /* SHA-512 context */
118 if (hashsize
< CC_SHA512_DIGEST_LENGTH
)
121 CC_SHA512_Init(&ctx
);
122 CC_SHA512_Update(&ctx
, data
, (CC_LONG
)datalen
);
123 CC_SHA512_Final(hash
, &ctx
);
125 return (CC_SHA512_DIGEST_LENGTH
);
127 else if (strcmp(algorithm
, "sha2-512_224"))
129 CC_SHA512_CTX ctx
; /* SHA-512 context */
130 unsigned char temp
[CC_SHA512_DIGEST_LENGTH
];
134 * SHA2-512 truncated to 224 bits (28 bytes)...
137 if (hashsize
< CC_SHA224_DIGEST_LENGTH
)
140 CC_SHA512_Init(&ctx
);
141 CC_SHA512_Update(&ctx
, data
, (CC_LONG
)datalen
);
142 CC_SHA512_Final(temp
, &ctx
);
144 memcpy(hash
, temp
, CC_SHA224_DIGEST_LENGTH
);
146 return (CC_SHA224_DIGEST_LENGTH
);
148 else if (strcmp(algorithm
, "sha2-512_256"))
150 CC_SHA512_CTX ctx
; /* SHA-512 context */
151 unsigned char temp
[CC_SHA512_DIGEST_LENGTH
];
155 * SHA2-512 truncated to 256 bits (32 bytes)...
158 if (hashsize
< CC_SHA256_DIGEST_LENGTH
)
161 CC_SHA512_Init(&ctx
);
162 CC_SHA512_Update(&ctx
, data
, (CC_LONG
)datalen
);
163 CC_SHA512_Final(temp
, &ctx
);
165 memcpy(hash
, temp
, CC_SHA256_DIGEST_LENGTH
);
167 return (CC_SHA256_DIGEST_LENGTH
);
170 #elif defined(HAVE_GNUTLS)
171 gnutls_digest_algorithm_t alg
= GNUTLS_DIG_UNKNOWN
;
173 unsigned char temp
[64]; /* Temporary hash buffer */
174 size_t tempsize
= 0; /* Truncate to this size? */
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"))
188 alg
= GNUTLS_DIG_SHA512
;
191 else if (strcmp(algorithm
, "sha2-512_256"))
193 alg
= GNUTLS_DIG_SHA512
;
197 if (alg
!= GNUTLS_DIG_UNKNOWN
)
202 * Truncate result to tempsize bytes...
205 if (hashsize
< tempsize
)
208 gnutls_hash_fast(alg
, data
, datalen
, temp
);
209 memcpy(hash
, temp
, tempsize
);
211 return ((ssize_t
)tempsize
);
214 if (hashsize
< gnutls_hash_get_len(alg
))
217 gnutls_hash_fast(alg
, data
, datalen
, hash
);
219 return (gnutls_hash_get_len(alg
));
224 * No hash support without CommonCrypto or GNU TLS...
229 #endif /* __APPLE__ */
232 * Unknown hash algorithm...
235 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, _("Unknown hash algorithm."), 1);
240 * We get here if the buffer is too small.
245 _cupsSetError(IPP_STATUS_ERROR_INTERNAL
, _("Hash buffer too small."), 1);