Coverage Report

Created: 2026-10-14 06:52

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libzip/lib/zip_crypto_openssl.c
Line
Count
Source
1
/*
2
  zip_crypto_openssl.c -- OpenSSL wrapper.
3
  Copyright (C) 2018-2024 Dieter Baron and Thomas Klausner
4
5
  This file is part of libzip, a library to manipulate ZIP archives.
6
  The authors can be contacted at <info@libzip.org>
7
8
  Redistribution and use in source and binary forms, with or without
9
  modification, are permitted provided that the following conditions
10
  are met:
11
  1. Redistributions of source code must retain the above copyright
12
  notice, this list of conditions and the following disclaimer.
13
  2. Redistributions in binary form must reproduce the above copyright
14
  notice, this list of conditions and the following disclaimer in
15
  the documentation and/or other materials provided with the
16
  distribution.
17
  3. The names of the authors may not be used to endorse or promote
18
  products derived from this software without specific prior
19
  written permission.
20
21
  THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
22
  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23
  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27
  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28
  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
29
  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30
  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31
  IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
*/
33
34
#include <stdlib.h>
35
#include <string.h>
36
37
#include "zipint.h"
38
39
#include "zip_crypto.h"
40
41
#include <limits.h>
42
#include <openssl/rand.h>
43
44
#ifdef USE_OPENSSL_3_API
45
static _zip_crypto_hmac_t *hmac_new() {
46
    _zip_crypto_hmac_t *hmac = (_zip_crypto_hmac_t *)malloc(sizeof(*hmac));
47
    if (hmac != NULL) {
48
        hmac->mac = NULL;
49
        hmac->ctx = NULL;
50
    }
51
    return hmac;
52
}
53
static void hmac_free(_zip_crypto_hmac_t *hmac) {
54
    if (hmac != NULL) {
55
        if (hmac->ctx != NULL) {
56
            EVP_MAC_CTX_free(hmac->ctx);
57
        }
58
        if (hmac->mac != NULL) {
59
            EVP_MAC_free(hmac->mac);
60
        }
61
        free(hmac);
62
    }
63
}
64
#endif
65
66
0
_zip_crypto_aes_t *_zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error) {
67
0
    _zip_crypto_aes_t *aes;
68
0
    const EVP_CIPHER *cipher_type;
69
70
0
    switch (key_size) {
71
0
    case 128:
72
0
        cipher_type = EVP_aes_128_ecb();
73
0
        break;
74
0
    case 192:
75
0
        cipher_type = EVP_aes_192_ecb();
76
0
        break;
77
0
    case 256:
78
0
        cipher_type = EVP_aes_256_ecb();
79
0
        break;
80
0
    default:
81
0
        zip_error_set(error, ZIP_ER_INTERNAL, 0);
82
0
        return NULL;
83
0
    }
84
85
#ifdef USE_OPENSSL_1_0_API
86
    if ((aes = (_zip_crypto_aes_t *)malloc(sizeof(*aes))) == NULL) {
87
        zip_error_set(error, ZIP_ER_MEMORY, 0);
88
        return NULL;
89
    }
90
    memset(aes, 0, sizeof(*aes));
91
#else
92
0
    if ((aes = EVP_CIPHER_CTX_new()) == NULL) {
93
0
        zip_error_set(error, ZIP_ER_MEMORY, 0);
94
0
        return NULL;
95
0
    }
96
0
#endif
97
98
0
    if (EVP_EncryptInit_ex(aes, cipher_type, NULL, key, NULL) != 1) {
99
#ifdef USE_OPENSSL_1_0_API
100
        free(aes);
101
#else
102
0
        EVP_CIPHER_CTX_free(aes);
103
0
#endif
104
0
        zip_error_set(error, ZIP_ER_INTERNAL, 0);
105
0
        return NULL;
106
0
    }
107
108
0
    return aes;
109
0
}
110
111
0
void _zip_crypto_aes_free(_zip_crypto_aes_t *aes) {
112
0
    if (aes == NULL) {
113
0
        return;
114
0
    }
115
116
#ifdef USE_OPENSSL_1_0_API
117
    EVP_CIPHER_CTX_cleanup(aes);
118
    _zip_crypto_clear(aes, sizeof(*aes));
119
    free(aes);
120
#else
121
0
    EVP_CIPHER_CTX_free(aes);
122
0
#endif
123
0
}
124
125
126
0
bool _zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out) {
127
0
    int len = 0;
128
0
    if (EVP_EncryptUpdate(aes, out, &len, in, ZIP_CRYPTO_AES_BLOCK_LENGTH) != 1 || len != ZIP_CRYPTO_AES_BLOCK_LENGTH) {
129
0
        return false;
130
0
    }
131
0
    return true;
132
0
}
133
134
135
0
_zip_crypto_hmac_t *_zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error) {
136
0
    _zip_crypto_hmac_t *hmac;
137
138
0
    if (secret_length > INT_MAX) {
139
0
        zip_error_set(error, ZIP_ER_INVAL, 0);
140
0
        return NULL;
141
0
    }
142
143
#ifdef USE_OPENSSL_3_API
144
    if ((hmac = hmac_new()) == NULL || (hmac->mac = EVP_MAC_fetch(NULL, "HMAC", "provider=default")) == NULL || (hmac->ctx = EVP_MAC_CTX_new(hmac->mac)) == NULL) {
145
        hmac_free(hmac);
146
        zip_error_set(error, ZIP_ER_MEMORY, 0);
147
        return NULL;
148
    }
149
150
    {
151
        OSSL_PARAM params[2];
152
        params[0] = OSSL_PARAM_construct_utf8_string("digest", "SHA1", 0);
153
        params[1] = OSSL_PARAM_construct_end();
154
155
        if (!EVP_MAC_init(hmac->ctx, (const unsigned char *)secret, secret_length, params)) {
156
            zip_error_set(error, ZIP_ER_INTERNAL, 0);
157
            hmac_free(hmac);
158
            return NULL;
159
        }
160
    }
161
#else
162
#ifdef USE_OPENSSL_1_0_API
163
    if ((hmac = (_zip_crypto_hmac_t *)malloc(sizeof(*hmac))) == NULL) {
164
        zip_error_set(error, ZIP_ER_MEMORY, 0);
165
        return NULL;
166
    }
167
168
    HMAC_CTX_init(hmac);
169
#else
170
0
    if ((hmac = HMAC_CTX_new()) == NULL) {
171
0
        zip_error_set(error, ZIP_ER_MEMORY, 0);
172
0
        return NULL;
173
0
    }
174
0
#endif
175
176
0
    if (HMAC_Init_ex(hmac, secret, (int)secret_length, EVP_sha1(), NULL) != 1) {
177
0
        zip_error_set(error, ZIP_ER_INTERNAL, 0);
178
#ifdef USE_OPENSSL_1_0_API
179
        free(hmac);
180
#else
181
0
        HMAC_CTX_free(hmac);
182
0
#endif
183
0
        return NULL;
184
0
    }
185
0
#endif
186
187
0
    return hmac;
188
0
}
189
190
191
0
void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac) {
192
0
    if (hmac == NULL) {
193
0
        return;
194
0
    }
195
196
#if defined(USE_OPENSSL_3_API)
197
    hmac_free(hmac);
198
#elif defined(USE_OPENSSL_1_0_API)
199
    HMAC_CTX_cleanup(hmac);
200
    _zip_crypto_clear(hmac, sizeof(*hmac));
201
    free(hmac);
202
#else
203
0
    HMAC_CTX_free(hmac);
204
0
#endif
205
0
}
206
207
208
0
bool _zip_crypto_hmac_output(_zip_crypto_hmac_t *hmac, zip_uint8_t *data) {
209
#ifdef USE_OPENSSL_3_API
210
    size_t length = 0;
211
    return EVP_MAC_final(hmac->ctx, data, &length, ZIP_CRYPTO_SHA1_LENGTH) == 1 && length == ZIP_CRYPTO_SHA1_LENGTH;
212
#else
213
0
    unsigned int length = 0;
214
0
    return HMAC_Final(hmac, data, &length) == 1 && length == ZIP_CRYPTO_SHA1_LENGTH;
215
0
#endif
216
0
}
217
218
219
8.78k
bool zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length) {
220
8.78k
    return RAND_bytes(buffer, length) == 1;
221
8.78k
}