/src/libarchive/libarchive/archive_hmac.c
Line | Count | Source |
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" |
32 | | #include "archive_hmac_private.h" |
33 | | |
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 | 0 | int __libarchive_hmac_build_hack(void) { |
44 | 0 | return 0; |
45 | 0 | } |
46 | | |
47 | | |
48 | | #ifdef ARCHIVE_HMAC_USE_Apple_CommonCrypto |
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 | | |
77 | | #elif defined(_WIN32) && !defined(__CYGWIN__) && defined(HAVE_BCRYPT_H) |
78 | | |
79 | | #ifndef BCRYPT_HASH_REUSABLE_FLAG |
80 | | # define BCRYPT_HASH_REUSABLE_FLAG 0x00000020 |
81 | | #endif |
82 | | |
83 | | static int |
84 | | __hmac_sha1_init(archive_hmac_sha1_ctx *ctx, const uint8_t *key, size_t key_len) |
85 | | { |
86 | | #ifdef __GNUC__ |
87 | | #pragma GCC diagnostic ignored "-Wcast-qual" |
88 | | #endif |
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 | | |
153 | | #elif defined(HAVE_LIBMBEDCRYPTO) && defined(HAVE_MBEDTLS_MD_H) |
154 | | |
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 | | |
200 | | #elif defined(HAVE_LIBNETTLE) && defined(HAVE_NETTLE_HMAC_H) |
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 | 4.26k | { |
233 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
234 | | EVP_MAC *mac; |
235 | | |
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); |
243 | | *ctx = EVP_MAC_CTX_new(mac); |
244 | | EVP_MAC_free(mac); |
245 | | if (*ctx == NULL) |
246 | | return -1; |
247 | | |
248 | | EVP_MAC_init(*ctx, key, key_len, params); |
249 | | #else |
250 | 4.26k | *ctx = HMAC_CTX_new(); |
251 | 4.26k | if (*ctx == NULL) |
252 | 0 | return -1; |
253 | 4.26k | HMAC_Init_ex(*ctx, key, key_len, EVP_sha1(), NULL); |
254 | 4.26k | #endif |
255 | 4.26k | return 0; |
256 | 4.26k | } |
257 | | |
258 | | static void |
259 | | __hmac_sha1_update(archive_hmac_sha1_ctx *ctx, const uint8_t *data, |
260 | | size_t data_len) |
261 | 4.25k | { |
262 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
263 | | EVP_MAC_update(*ctx, data, data_len); |
264 | | #else |
265 | 4.25k | HMAC_Update(*ctx, data, data_len); |
266 | 4.25k | #endif |
267 | 4.25k | } |
268 | | |
269 | | static void |
270 | | __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) |
271 | 4.24k | { |
272 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
273 | | size_t len = *out_len; |
274 | | #else |
275 | 4.24k | unsigned int len = (unsigned int)*out_len; |
276 | 4.24k | #endif |
277 | | |
278 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
279 | | EVP_MAC_final(*ctx, out, &len, *out_len); |
280 | | #else |
281 | 4.24k | HMAC_Final(*ctx, out, &len); |
282 | 4.24k | #endif |
283 | 4.24k | *out_len = len; |
284 | 4.24k | } |
285 | | |
286 | | static void |
287 | | __hmac_sha1_cleanup(archive_hmac_sha1_ctx *ctx) |
288 | 4.26k | { |
289 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
290 | | EVP_MAC_CTX_free(*ctx); |
291 | | #else |
292 | 4.26k | HMAC_CTX_free(*ctx); |
293 | 4.26k | #endif |
294 | | *ctx = NULL; |
295 | 4.26k | } |
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 |
319 | | __hmac_sha1_final(archive_hmac_sha1_ctx *ctx, uint8_t *out, size_t *out_len) |
320 | | { |
321 | | (void)ctx;/* UNUSED */ |
322 | | (void)out;/* UNUSED */ |
323 | | (void)out_len;/* UNUSED */ |
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 | | }; |