]>
Commit | Line | Data |
---|---|---|
c3c366eb MN |
1 | /*- |
2 | * Copyright (c) 2014 Michihiro NAKAJIMA | |
3 | * All rights reserved. | |
4 | * | |
5 | * Redistribution and use in source and binary forms, with or without | |
6 | * modification, are permitted provided that the following conditions | |
7 | * are met: | |
8 | * 1. Redistributions of source code must retain the above copyright | |
9 | * notice, this list of conditions and the following disclaimer. | |
10 | * 2. Redistributions in binary form must reproduce the above copyright | |
11 | * notice, this list of conditions and the following disclaimer in the | |
12 | * documentation and/or other materials provided with the distribution. | |
13 | * | |
14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR | |
15 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
16 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
17 | * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, | |
18 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
19 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
20 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
21 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
23 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | */ | |
25 | ||
26 | #include "archive_platform.h" | |
27 | ||
28 | #ifdef HAVE_STRING_H | |
29 | #include <string.h> | |
30 | #endif | |
31 | #include "archive.h" | |
e317cc0e | 32 | #include "archive_hmac_private.h" |
c3c366eb | 33 | |
11855358 TK |
34 | /* |
35 | * On systems that do not support any recognized crypto libraries, | |
36 | * the archive_hmac.c file is expected to define no usable symbols. | |
37 | * | |
38 | * But some compilers and linkers choke on empty object files, so | |
39 | * define a public symbol that will always exist. This could | |
40 | * be removed someday if this file gains another always-present | |
41 | * symbol definition. | |
42 | */ | |
43 | int __libarchive_hmac_build_hack(void) { | |
44 | return 0; | |
45 | } | |
46 | ||
47 | ||
c7fcc6b2 | 48 | #ifdef ARCHIVE_HMAC_USE_Apple_CommonCrypto |
c3c366eb MN |
49 | |
50 | static int | |
51 | __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) | |
52 | { | |
53 | CCHmacInit(ctx, kCCHmacAlgSHA1, key, key_len); | |
54 | return 0; | |
55 | } | |
56 | ||
57 | static void | |
58 | __hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, | |
59 | size_t data_len) | |
60 | { | |
61 | CCHmacUpdate(ctx, data, data_len); | |
62 | } | |
63 | ||
64 | static void | |
65 | __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) | |
66 | { | |
67 | CCHmacFinal(ctx, out); | |
68 | *out_len = 20; | |
69 | } | |
70 | ||
71 | static void | |
72 | __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) | |
73 | { | |
74 | memset(ctx, 0, sizeof(*ctx)); | |
75 | } | |
76 | ||
178bf9b8 MN |
77 | #elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) |
78 | ||
bb290293 BK |
79 | #ifndef BCRYPT_HASH_REUSABLE_FLAG |
80 | # define BCRYPT_HASH_REUSABLE_FLAG 0x00000020 | |
81 | #endif | |
82 | ||
178bf9b8 MN |
83 | static int |
84 | __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) | |
85 | { | |
ebef6c49 | 86 | #ifdef __GNUC__ |
e5ade325 | 87 | #pragma GCC diagnostic ignored "-Wcast-qual" |
ebef6c49 | 88 | #endif |
178bf9b8 MN |
89 | BCRYPT_ALG_HANDLE hAlg; |
90 | BCRYPT_HASH_HANDLE hHash; | |
91 | DWORD hash_len; | |
92 | PBYTE hash; | |
93 | ULONG result; | |
94 | NTSTATUS status; | |
95 | ||
96 | ctx->hAlg = NULL; | |
97 | status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA1_ALGORITHM, | |
98 | MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG); | |
99 | if (!BCRYPT_SUCCESS(status)) | |
100 | return -1; | |
101 | status = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH, (PUCHAR)&hash_len, | |
102 | sizeof(hash_len), &result, 0); | |
103 | if (!BCRYPT_SUCCESS(status)) { | |
104 | BCryptCloseAlgorithmProvider(hAlg, 0); | |
105 | return -1; | |
106 | } | |
107 | hash = (PBYTE)HeapAlloc(GetProcessHeap(), 0, hash_len); | |
108 | if (hash == NULL) { | |
109 | BCryptCloseAlgorithmProvider(hAlg, 0); | |
110 | return -1; | |
111 | } | |
112 | status = BCryptCreateHash(hAlg, &hHash, NULL, 0, | |
113 | (PUCHAR)key, (ULONG)key_len, BCRYPT_HASH_REUSABLE_FLAG); | |
114 | if (!BCRYPT_SUCCESS(status)) { | |
115 | BCryptCloseAlgorithmProvider(hAlg, 0); | |
116 | HeapFree(GetProcessHeap(), 0, hash); | |
117 | return -1; | |
118 | } | |
119 | ||
120 | ctx->hAlg = hAlg; | |
121 | ctx->hHash = hHash; | |
122 | ctx->hash_len = hash_len; | |
123 | ctx->hash = hash; | |
124 | ||
125 | return 0; | |
126 | } | |
127 | ||
128 | static void | |
129 | __hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, | |
130 | size_t data_len) | |
131 | { | |
132 | BCryptHashData(ctx->hHash, (PUCHAR)(uintptr_t)data, (ULONG)data_len, 0); | |
133 | } | |
134 | ||
135 | static void | |
136 | __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) | |
137 | { | |
138 | BCryptFinishHash(ctx->hHash, ctx->hash, ctx->hash_len, 0); | |
139 | if (ctx->hash_len == *out_len) | |
140 | memcpy(out, ctx->hash, *out_len); | |
141 | } | |
142 | ||
143 | static void | |
144 | __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) | |
145 | { | |
146 | if (ctx->hAlg != NULL) { | |
147 | BCryptCloseAlgorithmProvider(ctx->hAlg, 0); | |
148 | HeapFree(GetProcessHeap(), 0, ctx->hash); | |
149 | ctx->hAlg = NULL; | |
150 | } | |
151 | } | |
152 | ||
f96a7114 | 153 | #elif defined(HAVE_LIBMBEDCRYPTO) && defined(HAVE_MBEDTLS_MD_H) |
f9b3ac20 | 154 | |
f96a7114 MM |
155 | static int |
156 | __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) | |
157 | { | |
158 | const mbedtls_md_info_t *info; | |
159 | int ret; | |
160 | ||
161 | mbedtls_md_init(ctx); | |
162 | info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1); | |
163 | if (info == NULL) { | |
164 | mbedtls_md_free(ctx); | |
165 | return (-1); | |
166 | } | |
167 | ret = mbedtls_md_setup(ctx, info, 1); | |
168 | if (ret != 0) { | |
169 | mbedtls_md_free(ctx); | |
170 | return (-1); | |
171 | } | |
172 | ret = mbedtls_md_hmac_starts(ctx, key, key_len); | |
173 | if (ret != 0) { | |
174 | mbedtls_md_free(ctx); | |
175 | return (-1); | |
176 | } | |
177 | return 0; | |
178 | } | |
179 | ||
180 | static void | |
181 | __hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, | |
182 | size_t data_len) | |
183 | { | |
184 | mbedtls_md_hmac_update(ctx, data, data_len); | |
185 | } | |
186 | ||
187 | static void __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) | |
188 | { | |
189 | (void)out_len; /* UNUSED */ | |
190 | ||
191 | mbedtls_md_hmac_finish(ctx, out); | |
192 | } | |
193 | ||
194 | static void __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) | |
195 | { | |
196 | mbedtls_md_free(ctx); | |
197 | memset(ctx, 0, sizeof(*ctx)); | |
198 | } | |
199 | ||
48e40df7 | 200 | #elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_HMAC_H) |
c3c366eb MN |
201 | |
202 | static int | |
203 | __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) | |
204 | { | |
205 | hmac_sha1_set_key(ctx, key_len, key); | |
206 | return 0; | |
207 | } | |
208 | ||
209 | static void | |
210 | __hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, | |
211 | size_t data_len) | |
212 | { | |
213 | hmac_sha1_update(ctx, data_len, data); | |
214 | } | |
215 | ||
216 | static void | |
217 | __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) | |
218 | { | |
219 | hmac_sha1_digest(ctx, (unsigned)*out_len, out); | |
220 | } | |
221 | ||
222 | static void | |
223 | __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) | |
224 | { | |
225 | memset(ctx, 0, sizeof(*ctx)); | |
226 | } | |
227 | ||
228 | #elif defined(HAVE_LIBCRYPTO) | |
229 | ||
230 | static int | |
231 | __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) | |
232 | { | |
4dc59629 | 233 | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
4ebfd961 | 234 | EVP_MAC *mac; |
4dc59629 | 235 | |
4ebfd961 EC |
236 | char sha1[] = "SHA1"; |
237 | OSSL_PARAM params[] = { | |
238 | OSSL_PARAM_utf8_string("digest", sha1, sizeof(sha1) - 1), | |
239 | OSSL_PARAM_END | |
240 | }; | |
241 | ||
242 | mac = EVP_MAC_fetch(NULL, "HMAC", NULL); | |
4dc59629 | 243 | *ctx = EVP_MAC_CTX_new(mac); |
4ebfd961 | 244 | EVP_MAC_free(mac); |
4dc59629 MM |
245 | if (*ctx == NULL) |
246 | return -1; | |
4ebfd961 | 247 | |
4dc59629 MM |
248 | EVP_MAC_init(*ctx, key, key_len, params); |
249 | #else | |
89a6ed13 TM |
250 | *ctx = HMAC_CTX_new(); |
251 | if (*ctx == NULL) | |
252 | return -1; | |
253 | HMAC_Init_ex(*ctx, key, key_len, EVP_sha1(), NULL); | |
4dc59629 | 254 | #endif |
c3c366eb MN |
255 | return 0; |
256 | } | |
257 | ||
258 | static void | |
259 | __hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, | |
260 | size_t data_len) | |
261 | { | |
4dc59629 MM |
262 | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
263 | EVP_MAC_update(*ctx, data, data_len); | |
264 | #else | |
89a6ed13 | 265 | HMAC_Update(*ctx, data, data_len); |
4dc59629 | 266 | #endif |
c3c366eb MN |
267 | } |
268 | ||
269 | static void | |
270 | __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) | |
271 | { | |
4dc59629 MM |
272 | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
273 | size_t len = *out_len; | |
274 | #else | |
c3c366eb | 275 | unsigned int len = (unsigned int)*out_len; |
4dc59629 | 276 | #endif |
f96a7114 | 277 | |
4dc59629 MM |
278 | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
279 | EVP_MAC_final(*ctx, out, &len, *out_len); | |
280 | #else | |
89a6ed13 | 281 | HMAC_Final(*ctx, out, &len); |
4dc59629 | 282 | #endif |
c3c366eb MN |
283 | *out_len = len; |
284 | } | |
285 | ||
286 | static void | |
287 | __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) | |
288 | { | |
4dc59629 MM |
289 | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
290 | EVP_MAC_CTX_free(*ctx); | |
291 | #else | |
89a6ed13 | 292 | HMAC_CTX_free(*ctx); |
4dc59629 | 293 | #endif |
89a6ed13 | 294 | *ctx = NULL; |
c3c366eb MN |
295 | } |
296 | ||
297 | #else | |
298 | ||
299 | /* Stub */ | |
300 | static int | |
301 | __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) | |
302 | { | |
303 | (void)ctx;/* UNUSED */ | |
304 | (void)key;/* UNUSED */ | |
305 | (void)key_len;/* UNUSED */ | |
306 | return -1; | |
307 | } | |
308 | ||
309 | static void | |
310 | __hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, | |
311 | size_t data_len) | |
312 | { | |
313 | (void)ctx;/* UNUSED */ | |
314 | (void)data;/* UNUSED */ | |
315 | (void)data_len;/* UNUSED */ | |
316 | } | |
317 | ||
318 | static void | |
7f875fa2 | 319 | __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) |
c3c366eb MN |
320 | { |
321 | (void)ctx;/* UNUSED */ | |
322 | (void)out;/* UNUSED */ | |
7f875fa2 | 323 | (void)out_len;/* UNUSED */ |
c3c366eb MN |
324 | } |
325 | ||
326 | static void | |
327 | __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) | |
328 | { | |
329 | (void)ctx;/* UNUSED */ | |
330 | } | |
331 | ||
332 | #endif | |
333 | ||
334 | const struct archive_hmac __archive_hmac = { | |
335 | &__hmac_sha1_init, | |
336 | &__hmac_sha1_update, | |
337 | &__hmac_sha1_final, | |
338 | &__hmac_sha1_cleanup, | |
339 | }; |