Rizin
unix-like reverse engineering framework and cli tools
zip_crypto_win.c
Go to the documentation of this file.
1 /*
2  zip_crypto_win.c -- Windows Crypto API wrapper.
3  Copyright (C) 2018-2021 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 #include <stdlib.h>
34 #include <limits.h>
35 
36 #include "zipint.h"
37 
38 #include "zip_crypto.h"
39 
40 #define WIN32_LEAN_AND_MEAN
41 #define NOCRYPT
42 
43 #include <windows.h>
44 
45 #include <bcrypt.h>
46 
47 #pragma comment(lib, "bcrypt.lib")
48 
49 /*
50 
51 This code is using the Cryptography API: Next Generation (CNG)
52 https://docs.microsoft.com/en-us/windows/desktop/seccng/cng-portal
53 
54 This API is supported on
55  - Windows Vista or later (client OS)
56  - Windows Server 2008 (server OS)
57  - Windows Embedded Compact 2013 (don't know about Windows Embedded Compact 7)
58 
59 The code was developed for Windows Embedded Compact 2013 (WEC2013),
60 but should be working for all of the above mentioned OSes.
61 
62 There are 2 restrictions for WEC2013, Windows Vista and Windows Server 2008:
63 
64 1.) The function "BCryptDeriveKeyPBKDF2" is not available
65 
66 I found some code which is implementing this function using the deprecated Crypto API here:
67 https://www.idrix.fr/Root/content/view/37/54/
68 
69 I took this code and converted it to the newer CNG API. The original code was more
70 flexible, but this is not needed here so i refactored it a bit and just kept what is needed.
71 
72 The define "HAS_BCRYPTDERIVEKEYPBKDF2" controls whether "BCryptDeriveKeyPBKDF2"
73 of the CNG API is used or not. This define must not be set if you are compiling for WEC2013 or Windows Vista.
74 
75 
76 2.) "BCryptCreateHash" can't manage the memory needed for the hash object internally
77 
78 On Windows 7 or later it is possible to pass NULL for the hash object buffer.
79 This is not supported on WEC2013, so we have to handle the memory allocation/deallocation ourselves.
80 There is no #ifdef to control that, because this is working for all supported OSes.
81 
82 */
83 
84 #if !defined(WINCE) && !defined(__MINGW32__)
85 #define HAS_BCRYPTDERIVEKEYPBKDF2
86 #endif
87 
88 #ifdef HAS_BCRYPTDERIVEKEYPBKDF2
89 
90 bool
91 _zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_uint8_t *salt, zip_uint16_t salt_length, zip_uint16_t iterations, zip_uint8_t *output, zip_uint16_t output_length) {
92  BCRYPT_ALG_HANDLE hAlgorithm = NULL;
93  bool result;
94 
95  if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&hAlgorithm, BCRYPT_SHA1_ALGORITHM, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG))) {
96  return false;
97  }
98 
99  result = BCRYPT_SUCCESS(BCryptDeriveKeyPBKDF2(hAlgorithm, (PUCHAR)key, (ULONG)key_length, (PUCHAR)salt, salt_length, iterations, output, output_length, 0));
100 
101  BCryptCloseAlgorithmProvider(hAlgorithm, 0);
102 
103  return result;
104 }
105 
106 #else
107 
108 #include <math.h>
109 
110 #define DIGEST_SIZE 20
111 #define BLOCK_SIZE 64
112 
113 typedef struct {
114  BCRYPT_ALG_HANDLE hAlgorithm;
115  BCRYPT_HASH_HANDLE hInnerHash;
116  BCRYPT_HASH_HANDLE hOuterHash;
117  ULONG cbHashObject;
118  PUCHAR pbInnerHash;
119  PUCHAR pbOuterHash;
120 } PRF_CTX;
121 
122 static void
123 hmacFree(PRF_CTX *pContext) {
124  if (pContext->hOuterHash)
125  BCryptDestroyHash(pContext->hOuterHash);
126  if (pContext->hInnerHash)
127  BCryptDestroyHash(pContext->hInnerHash);
128  free(pContext->pbOuterHash);
129  free(pContext->pbInnerHash);
130  if (pContext->hAlgorithm)
131  BCryptCloseAlgorithmProvider(pContext->hAlgorithm, 0);
132 }
133 
134 static BOOL
135 hmacPrecomputeDigest(BCRYPT_HASH_HANDLE hHash, PUCHAR pbPassword, DWORD cbPassword, BYTE mask) {
137  DWORD i;
138 
139  if (cbPassword > BLOCK_SIZE) {
140  return FALSE;
141  }
142 
143  memset(buffer, mask, sizeof(buffer));
144 
145  for (i = 0; i < cbPassword; ++i) {
146  buffer[i] = (char)(pbPassword[i] ^ mask);
147  }
148 
149  return BCRYPT_SUCCESS(BCryptHashData(hHash, buffer, sizeof(buffer), 0));
150 }
151 
152 static BOOL
153 hmacInit(PRF_CTX *pContext, PUCHAR pbPassword, DWORD cbPassword) {
154  BOOL bStatus = FALSE;
155  ULONG cbResult;
156  BYTE key[DIGEST_SIZE];
157 
158  if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&pContext->hAlgorithm, BCRYPT_SHA1_ALGORITHM, NULL, 0)) || !BCRYPT_SUCCESS(BCryptGetProperty(pContext->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&pContext->cbHashObject, sizeof(pContext->cbHashObject), &cbResult, 0)) || ((pContext->pbInnerHash = malloc(pContext->cbHashObject)) == NULL) || ((pContext->pbOuterHash = malloc(pContext->cbHashObject)) == NULL) || !BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &pContext->hInnerHash, pContext->pbInnerHash, pContext->cbHashObject, NULL, 0, 0)) || !BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &pContext->hOuterHash, pContext->pbOuterHash, pContext->cbHashObject, NULL, 0, 0))) {
159  goto hmacInit_end;
160  }
161 
162  if (cbPassword > BLOCK_SIZE) {
163  BCRYPT_HASH_HANDLE hHash = NULL;
164  PUCHAR pbHashObject = malloc(pContext->cbHashObject);
165  if (pbHashObject == NULL) {
166  goto hmacInit_end;
167  }
168 
169  bStatus = BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &hHash, pbHashObject, pContext->cbHashObject, NULL, 0, 0)) && BCRYPT_SUCCESS(BCryptHashData(hHash, pbPassword, cbPassword, 0)) && BCRYPT_SUCCESS(BCryptGetProperty(hHash, BCRYPT_HASH_LENGTH, (PUCHAR)&cbPassword, sizeof(cbPassword), &cbResult, 0)) && BCRYPT_SUCCESS(BCryptFinishHash(hHash, key, cbPassword, 0));
170 
171  if (hHash)
172  BCryptDestroyHash(hHash);
173  free(pbHashObject);
174 
175  if (!bStatus) {
176  goto hmacInit_end;
177  }
178 
179  pbPassword = key;
180  }
181 
182  bStatus = hmacPrecomputeDigest(pContext->hInnerHash, pbPassword, cbPassword, 0x36) && hmacPrecomputeDigest(pContext->hOuterHash, pbPassword, cbPassword, 0x5C);
183 
184 hmacInit_end:
185 
186  if (bStatus == FALSE)
187  hmacFree(pContext);
188 
189  return bStatus;
190 }
191 
192 static BOOL
193 hmacCalculateInternal(BCRYPT_HASH_HANDLE hHashTemplate, PUCHAR pbData, DWORD cbData, PUCHAR pbOutput, DWORD cbOutput, DWORD cbHashObject) {
194  BOOL success = FALSE;
195  BCRYPT_HASH_HANDLE hHash = NULL;
196  PUCHAR pbHashObject = malloc(cbHashObject);
197 
198  if (pbHashObject == NULL) {
199  return FALSE;
200  }
201 
202  if (BCRYPT_SUCCESS(BCryptDuplicateHash(hHashTemplate, &hHash, pbHashObject, cbHashObject, 0))) {
203  success = BCRYPT_SUCCESS(BCryptHashData(hHash, pbData, cbData, 0)) && BCRYPT_SUCCESS(BCryptFinishHash(hHash, pbOutput, cbOutput, 0));
204 
205  BCryptDestroyHash(hHash);
206  }
207 
208  free(pbHashObject);
209 
210  return success;
211 }
212 
213 static BOOL
214 hmacCalculate(PRF_CTX *pContext, PUCHAR pbData, DWORD cbData, PUCHAR pbDigest) {
215  DWORD cbResult;
216  DWORD cbHashObject;
217 
218  return BCRYPT_SUCCESS(BCryptGetProperty(pContext->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&cbHashObject, sizeof(cbHashObject), &cbResult, 0)) && hmacCalculateInternal(pContext->hInnerHash, pbData, cbData, pbDigest, DIGEST_SIZE, cbHashObject) && hmacCalculateInternal(pContext->hOuterHash, pbDigest, DIGEST_SIZE, pbDigest, DIGEST_SIZE, cbHashObject);
219 }
220 
221 static void
222 myxor(LPBYTE ptr1, LPBYTE ptr2, DWORD dwLen) {
223  while (dwLen--)
224  *ptr1++ ^= *ptr2++;
225 }
226 
227 BOOL
228 pbkdf2(PUCHAR pbPassword, ULONG cbPassword, PUCHAR pbSalt, ULONG cbSalt, DWORD cIterations, PUCHAR pbDerivedKey, ULONG cbDerivedKey) {
229  BOOL bStatus = FALSE;
230  DWORD l, r, dwULen, i, j;
231  BYTE Ti[DIGEST_SIZE];
232  BYTE V[DIGEST_SIZE];
233  LPBYTE U = malloc(max((cbSalt + 4), DIGEST_SIZE));
234  PRF_CTX prfCtx = {0};
235 
236  if (U == NULL) {
237  return FALSE;
238  }
239 
240  if (pbPassword == NULL || cbPassword == 0 || pbSalt == NULL || cbSalt == 0 || cIterations == 0 || pbDerivedKey == NULL || cbDerivedKey == 0) {
241  free(U);
242  return FALSE;
243  }
244 
245  if (!hmacInit(&prfCtx, pbPassword, cbPassword)) {
246  goto PBKDF2_end;
247  }
248 
249  l = (DWORD)ceil((double)cbDerivedKey / (double)DIGEST_SIZE);
250  r = cbDerivedKey - (l - 1) * DIGEST_SIZE;
251 
252  for (i = 1; i <= l; i++) {
253  ZeroMemory(Ti, DIGEST_SIZE);
254  for (j = 0; j < cIterations; j++) {
255  if (j == 0) {
256  /* construct first input for PRF */
257  memcpy(U, pbSalt, cbSalt);
258  U[cbSalt] = (BYTE)((i & 0xFF000000) >> 24);
259  U[cbSalt + 1] = (BYTE)((i & 0x00FF0000) >> 16);
260  U[cbSalt + 2] = (BYTE)((i & 0x0000FF00) >> 8);
261  U[cbSalt + 3] = (BYTE)((i & 0x000000FF));
262  dwULen = cbSalt + 4;
263  }
264  else {
265  memcpy(U, V, DIGEST_SIZE);
266  dwULen = DIGEST_SIZE;
267  }
268 
269  if (!hmacCalculate(&prfCtx, U, dwULen, V)) {
270  goto PBKDF2_end;
271  }
272 
273  myxor(Ti, V, DIGEST_SIZE);
274  }
275 
276  if (i != l) {
277  memcpy(&pbDerivedKey[(i - 1) * DIGEST_SIZE], Ti, DIGEST_SIZE);
278  }
279  else {
280  /* Take only the first r bytes */
281  memcpy(&pbDerivedKey[(i - 1) * DIGEST_SIZE], Ti, r);
282  }
283  }
284 
285  bStatus = TRUE;
286 
287 PBKDF2_end:
288 
289  hmacFree(&prfCtx);
290  free(U);
291  return bStatus;
292 }
293 
294 bool
295 _zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_uint8_t *salt, zip_uint16_t salt_length, zip_uint16_t iterations, zip_uint8_t *output, zip_uint16_t output_length) {
296  return (key_length <= ZIP_UINT32_MAX) && pbkdf2((PUCHAR)key, (ULONG)key_length, (PUCHAR)salt, salt_length, iterations, output, output_length);
297 }
298 
299 #endif
300 
301 
303  BCRYPT_ALG_HANDLE hAlgorithm;
304  BCRYPT_KEY_HANDLE hKey;
306  PUCHAR pbKeyObject;
307 };
308 
311  _zip_crypto_aes_t *aes = (_zip_crypto_aes_t *)calloc(1, sizeof(*aes));
312 
313  ULONG cbResult;
314  ULONG key_length = key_size / 8;
315 
316  if (aes == NULL) {
318  return NULL;
319  }
320 
321  if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&aes->hAlgorithm, BCRYPT_AES_ALGORITHM, NULL, 0))) {
323  return NULL;
324  }
325 
326  if (!BCRYPT_SUCCESS(BCryptSetProperty(aes->hAlgorithm, BCRYPT_CHAINING_MODE, (PUCHAR)BCRYPT_CHAIN_MODE_ECB, sizeof(BCRYPT_CHAIN_MODE_ECB), 0))) {
328  return NULL;
329  }
330 
331  if (!BCRYPT_SUCCESS(BCryptGetProperty(aes->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&aes->cbKeyObject, sizeof(aes->cbKeyObject), &cbResult, 0))) {
333  return NULL;
334  }
335 
336  aes->pbKeyObject = malloc(aes->cbKeyObject);
337  if (aes->pbKeyObject == NULL) {
340  return NULL;
341  }
342 
343  if (!BCRYPT_SUCCESS(BCryptGenerateSymmetricKey(aes->hAlgorithm, &aes->hKey, aes->pbKeyObject, aes->cbKeyObject, (PUCHAR)key, key_length, 0))) {
345  return NULL;
346  }
347 
348  return aes;
349 }
350 
351 void
353  if (aes == NULL) {
354  return;
355  }
356 
357  if (aes->hKey != NULL) {
358  BCryptDestroyKey(aes->hKey);
359  }
360 
361  if (aes->pbKeyObject != NULL) {
362  free(aes->pbKeyObject);
363  }
364 
365  if (aes->hAlgorithm != NULL) {
366  BCryptCloseAlgorithmProvider(aes->hAlgorithm, 0);
367  }
368 
369  free(aes);
370 }
371 
372 bool
374  ULONG cbResult;
375  NTSTATUS status = BCryptEncrypt(aes->hKey, (PUCHAR)in, ZIP_CRYPTO_AES_BLOCK_LENGTH, NULL, NULL, 0, (PUCHAR)out, ZIP_CRYPTO_AES_BLOCK_LENGTH, &cbResult, 0);
376  return BCRYPT_SUCCESS(status);
377 }
378 
380  BCRYPT_ALG_HANDLE hAlgorithm;
381  BCRYPT_HASH_HANDLE hHash;
383  PUCHAR pbHashObject;
385  PUCHAR pbHash;
386 };
387 
388 /* https://code.msdn.microsoft.com/windowsdesktop/Hmac-Computation-Sample-11fe8ec1/sourcecode?fileId=42820&pathId=283874677 */
389 
393  ULONG cbResult;
394  _zip_crypto_hmac_t *hmac;
395 
396  if (secret_length > INT_MAX) {
398  return NULL;
399  }
400 
401  hmac = (_zip_crypto_hmac_t *)calloc(1, sizeof(*hmac));
402 
403  if (hmac == NULL) {
405  return NULL;
406  }
407 
408  status = BCryptOpenAlgorithmProvider(&hmac->hAlgorithm, BCRYPT_SHA1_ALGORITHM, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG);
409  if (!BCRYPT_SUCCESS(status)) {
410  _zip_crypto_hmac_free(hmac);
411  return NULL;
412  }
413 
414  status = BCryptGetProperty(hmac->hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR)&hmac->cbHashObject, sizeof(hmac->cbHashObject), &cbResult, 0);
415  if (!BCRYPT_SUCCESS(status)) {
416  _zip_crypto_hmac_free(hmac);
417  return NULL;
418  }
419 
420  hmac->pbHashObject = malloc(hmac->cbHashObject);
421  if (hmac->pbHashObject == NULL) {
422  _zip_crypto_hmac_free(hmac);
424  return NULL;
425  }
426 
427  status = BCryptGetProperty(hmac->hAlgorithm, BCRYPT_HASH_LENGTH, (PUCHAR)&hmac->cbHash, sizeof(hmac->cbHash), &cbResult, 0);
428  if (!BCRYPT_SUCCESS(status)) {
429  _zip_crypto_hmac_free(hmac);
430  return NULL;
431  }
432 
433  hmac->pbHash = malloc(hmac->cbHash);
434  if (hmac->pbHash == NULL) {
435  _zip_crypto_hmac_free(hmac);
437  return NULL;
438  }
439 
440  status = BCryptCreateHash(hmac->hAlgorithm, &hmac->hHash, hmac->pbHashObject, hmac->cbHashObject, (PUCHAR)secret, (ULONG)secret_length, 0);
441  if (!BCRYPT_SUCCESS(status)) {
442  _zip_crypto_hmac_free(hmac);
443  return NULL;
444  }
445 
446  return hmac;
447 }
448 
449 void
451  if (hmac == NULL) {
452  return;
453  }
454 
455  if (hmac->hHash != NULL) {
456  BCryptDestroyHash(hmac->hHash);
457  }
458 
459  if (hmac->pbHash != NULL) {
460  free(hmac->pbHash);
461  }
462 
463  if (hmac->pbHashObject != NULL) {
464  free(hmac->pbHashObject);
465  }
466 
467  if (hmac->hAlgorithm) {
468  BCryptCloseAlgorithmProvider(hmac->hAlgorithm, 0);
469  }
470 
471  free(hmac);
472 }
473 
474 bool
476  if (hmac == NULL || length > ULONG_MAX) {
477  return false;
478  }
479 
480  return BCRYPT_SUCCESS(BCryptHashData(hmac->hHash, data, (ULONG)length, 0));
481 }
482 
483 bool
485  if (hmac == NULL) {
486  return false;
487  }
488 
489  return BCRYPT_SUCCESS(BCryptFinishHash(hmac->hHash, data, hmac->cbHash, 0));
490 }
491 
492 ZIP_EXTERN bool
494  return BCRYPT_SUCCESS(BCryptGenRandom(NULL, buffer, length, BCRYPT_USE_SYSTEM_PREFERRED_RNG));
495 }
#define mask()
lzma_index ** i
Definition: index.h:629
const lzma_allocator const uint8_t * in
Definition: block.h:527
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
#define INT_MAX
Definition: cp-demangle.c:131
#define NULL
Definition: cris-opc.c:27
#define BLOCK_SIZE
#define r
Definition: crypto_rc6.c:12
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len key
Definition: sflib.h:118
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void length
Definition: sflib.h:133
int max
Definition: enough.c:225
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
return memset(p, 0, total)
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
ZIP_EXTERN void zip_error_set(zip_error_t *_Nullable, int, int)
Definition: zip_error.c:126
#define ZIP_ER_MEMORY
Definition: zip.h:119
#define ZIP_EXTERN
Definition: zip.h:54
#define ZIP_ER_INVAL
Definition: zip.h:123
void * malloc(size_t size)
Definition: malloc.c:123
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
static const char struct stat static buf struct stat static buf static vhangup int status
Definition: sflib.h:145
unsigned char BYTE
Definition: lz4.c:286
#define TRUE
Definition: mybfd.h:103
#define FALSE
Definition: mybfd.h:102
BCRYPT_ALG_HANDLE hAlgorithm
BCRYPT_KEY_HANDLE hKey
BCRYPT_ALG_HANDLE hAlgorithm
BCRYPT_HASH_HANDLE hHash
Definition: buffer.h:15
Definition: zip.h:284
#define V(handle, symbol)
void error(const char *msg)
Definition: untgz.c:593
LONG NTSTATUS
Definition: win.h:198
ULONG
DWORD
#define ZIP_CRYPTO_AES_BLOCK_LENGTH
Definition: zip_crypto.h:38
bool _zip_crypto_hmac(_zip_crypto_hmac_t *hmac, zip_uint8_t *data, zip_uint64_t length)
bool _zip_crypto_hmac_output(_zip_crypto_hmac_t *hmac, zip_uint8_t *data)
bool _zip_crypto_pbkdf2(const zip_uint8_t *key, zip_uint64_t key_length, const zip_uint8_t *salt, zip_uint16_t salt_length, zip_uint16_t iterations, zip_uint8_t *output, zip_uint16_t output_length)
bool _zip_crypto_aes_encrypt_block(_zip_crypto_aes_t *aes, const zip_uint8_t *in, zip_uint8_t *out)
void _zip_crypto_hmac_free(_zip_crypto_hmac_t *hmac)
void _zip_crypto_aes_free(_zip_crypto_aes_t *aes)
_zip_crypto_aes_t * _zip_crypto_aes_new(const zip_uint8_t *key, zip_uint16_t key_size, zip_error_t *error)
ZIP_EXTERN bool zip_secure_random(zip_uint8_t *buffer, zip_uint16_t length)
_zip_crypto_hmac_t * _zip_crypto_hmac_new(const zip_uint8_t *secret, zip_uint64_t secret_length, zip_error_t *error)
diff_output_t output
Definition: zipcmp.c:237
uint64_t zip_uint64_t
Definition: zipconf.h:39
#define ZIP_UINT32_MAX
Definition: zipconf.h:51
uint8_t zip_uint8_t
Definition: zipconf.h:33
uint16_t zip_uint16_t
Definition: zipconf.h:35