Coverage Report

Created: 2025-11-24 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
};