cocos-engine-external/sources/unzip/crypt.h

169 lines
5.2 KiB
C

/* crypt.h -- base code for traditional PKWARE encryption
Version 1.2.0, September 16th, 2017
Copyright (C) 2012-2017 Nathan Moinvaziri
https://github.com/nmoinvaz/minizip
Copyright (C) 1998-2005 Gilles Vollant
Modifications for Info-ZIP crypting
http://www.winimage.com/zLibDll/minizip.html
Copyright (C) 2003 Terry Thorsen
This code is a modified version of crypting code in Info-ZIP distribution
Copyright (C) 1990-2000 Info-ZIP. All rights reserved.
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#ifndef _MINICRYPT_H
#define _MINICRYPT_H
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
# ifndef ZCR_SEED2
# define ZCR_SEED2 3141592654UL /* use PI as default pattern */
# endif
#if ZLIB_VERNUM < 0x1270
typedef unsigned long z_crc_t;
#endif
#define RAND_HEAD_LEN 12
/***************************************************************************/
#define CRC32(c, b) ((*(pcrc_32_tab+(((uint32_t)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
/***************************************************************************/
#define zdecode(pkeys,pcrc_32_tab,c) \
(update_keys(pkeys,pcrc_32_tab, c ^= decrypt_byte(pkeys)))
#define zencode(pkeys,pcrc_32_tab,c,t) \
(t = decrypt_byte(pkeys), update_keys(pkeys,pcrc_32_tab,c), t^(c))
/***************************************************************************/
/* Return the next byte in the pseudo-random sequence */
static uint8_t decrypt_byte(uint32_t *pkeys)
{
unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
* unpredictable manner on 16-bit systems; not a problem
* with any known compiler so far, though */
temp = ((uint32_t)(*(pkeys + 2)) & 0xffff) | 2;
return (uint8_t)(((temp * (temp ^ 1)) >> 8) & 0xff);
}
/* Update the encryption keys with the next byte of plain text */
static uint8_t update_keys(uint32_t *pkeys, const z_crc_t *pcrc_32_tab, int32_t c)
{
(*(pkeys + 0)) = (uint32_t)CRC32((*(pkeys + 0)), c);
(*(pkeys + 1)) += (*(pkeys + 0)) & 0xff;
(*(pkeys + 1)) = (*(pkeys + 1)) * 134775813L + 1;
{
int32_t keyshift = (int32_t)((*(pkeys + 1)) >> 24);
(*(pkeys + 2)) = (uint32_t)CRC32((*(pkeys + 2)), keyshift);
}
return c;
}
/* Initialize the encryption keys and the random header according to the given password. */
static void init_keys(const char *passwd, uint32_t *pkeys, const z_crc_t *pcrc_32_tab)
{
*(pkeys + 0) = 305419896L;
*(pkeys + 1) = 591751049L;
*(pkeys + 2) = 878082192L;
while (*passwd != 0)
{
update_keys(pkeys, pcrc_32_tab, *passwd);
passwd += 1;
}
}
#ifndef NOCRYPT
/* Generate cryptographically secure random numbers */
static int cryptrand(unsigned char *buf, unsigned int len)
{
/*
Important This API is deprecated. New and existing software should
start using Cryptography Next Generation APIs.
Microsoft may remove this API in future releases.
see: https://docs.microsoft.com/zh-cn/windows/desktop/api/wincrypt/nf-wincrypt-cryptgenrandom
*/
#define CRYPTGENRANDOM_DEPRECATED 1
#if defined(_WIN32) && !defined(CRYPTGENRANDOM_DEPRECATED)
HCRYPTPROV provider;
unsigned __int64 pentium_tsc[1];
int rlen = 0;
int result = 0;
if (CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
{
result = CryptGenRandom(provider, len, buf);
CryptReleaseContext(provider, 0);
if (result)
return len;
}
for (rlen = 0; rlen < (int)len; ++rlen)
{
if (rlen % 8 == 0)
QueryPerformanceCounter((LARGE_INTEGER *)pentium_tsc);
buf[rlen] = ((unsigned char*)pentium_tsc)[rlen % 8];
}
return rlen;
#else
static unsigned calls = 0; /* ensure different random header each time */
/* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
* output of rand() to get less predictability, since rand() is
* often poorly implemented.
*/
if (++calls == 1)
{
srand((unsigned)(time(NULL) ^ ZCR_SEED2));
}
for(unsigned int i = 0; i < len; ++i){
buf[i] = rand() % 256;
}
return len;
#endif
}
/* Create encryption header */
static int crypthead(const char *passwd, uint8_t *buf, int buf_size, uint32_t *pkeys,
const z_crc_t *pcrc_32_tab, uint8_t verify1, uint8_t verify2)
{
uint8_t n = 0; /* index in random header */
uint8_t header[RAND_HEAD_LEN - 2]; /* random header */
uint16_t t = 0; /* temporary */
if (buf_size < RAND_HEAD_LEN)
return 0;
init_keys(passwd, pkeys, pcrc_32_tab);
/* First generate RAND_HEAD_LEN-2 random bytes. */
cryptrand(header, RAND_HEAD_LEN - 2);
/* Encrypt random header (last two bytes is high word of crc) */
init_keys(passwd, pkeys, pcrc_32_tab);
for (n = 0; n < RAND_HEAD_LEN - 2; n++)
buf[n] = (uint8_t)zencode(pkeys, pcrc_32_tab, header[n], t);
buf[n++] = (uint8_t)zencode(pkeys, pcrc_32_tab, verify1, t);
buf[n++] = (uint8_t)zencode(pkeys, pcrc_32_tab, verify2, t);
return n;
}
#endif
/***************************************************************************/
#endif