xref: /aosp_15_r20/external/zlib/contrib/minizip/crypt.h (revision 86ee64e75fa5f8bce2c8c356138035642429cd05)
1*86ee64e7SAndroid Build Coastguard Worker /* crypt.h -- base code for crypt/uncrypt ZIPfile
2*86ee64e7SAndroid Build Coastguard Worker 
3*86ee64e7SAndroid Build Coastguard Worker 
4*86ee64e7SAndroid Build Coastguard Worker    Version 1.01e, February 12th, 2005
5*86ee64e7SAndroid Build Coastguard Worker 
6*86ee64e7SAndroid Build Coastguard Worker    Copyright (C) 1998-2005 Gilles Vollant
7*86ee64e7SAndroid Build Coastguard Worker 
8*86ee64e7SAndroid Build Coastguard Worker    This code is a modified version of crypting code in Infozip distribution
9*86ee64e7SAndroid Build Coastguard Worker 
10*86ee64e7SAndroid Build Coastguard Worker    The encryption/decryption parts of this source code (as opposed to the
11*86ee64e7SAndroid Build Coastguard Worker    non-echoing password parts) were originally written in Europe.  The
12*86ee64e7SAndroid Build Coastguard Worker    whole source package can be freely distributed, including from the USA.
13*86ee64e7SAndroid Build Coastguard Worker    (Prior to January 2000, re-export from the US was a violation of US law.)
14*86ee64e7SAndroid Build Coastguard Worker 
15*86ee64e7SAndroid Build Coastguard Worker    This encryption code is a direct transcription of the algorithm from
16*86ee64e7SAndroid Build Coastguard Worker    Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
17*86ee64e7SAndroid Build Coastguard Worker    file (appnote.txt) is distributed with the PKZIP program (even in the
18*86ee64e7SAndroid Build Coastguard Worker    version without encryption capabilities).
19*86ee64e7SAndroid Build Coastguard Worker 
20*86ee64e7SAndroid Build Coastguard Worker    If you don't need crypting in your application, just define symbols
21*86ee64e7SAndroid Build Coastguard Worker    NOCRYPT and NOUNCRYPT.
22*86ee64e7SAndroid Build Coastguard Worker 
23*86ee64e7SAndroid Build Coastguard Worker    This code support the "Traditional PKWARE Encryption".
24*86ee64e7SAndroid Build Coastguard Worker 
25*86ee64e7SAndroid Build Coastguard Worker    The new AES encryption added on Zip format by Winzip (see the page
26*86ee64e7SAndroid Build Coastguard Worker    http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong
27*86ee64e7SAndroid Build Coastguard Worker    Encryption is not supported.
28*86ee64e7SAndroid Build Coastguard Worker */
29*86ee64e7SAndroid Build Coastguard Worker 
30*86ee64e7SAndroid Build Coastguard Worker #define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
31*86ee64e7SAndroid Build Coastguard Worker 
32*86ee64e7SAndroid Build Coastguard Worker /***********************************************************************
33*86ee64e7SAndroid Build Coastguard Worker  * Return the next byte in the pseudo-random sequence
34*86ee64e7SAndroid Build Coastguard Worker  */
decrypt_byte(unsigned long * pkeys,const z_crc_t * pcrc_32_tab)35*86ee64e7SAndroid Build Coastguard Worker static int decrypt_byte(unsigned long* pkeys, const z_crc_t* pcrc_32_tab) {
36*86ee64e7SAndroid Build Coastguard Worker     unsigned temp;  /* POTENTIAL BUG:  temp*(temp^1) may overflow in an
37*86ee64e7SAndroid Build Coastguard Worker                      * unpredictable manner on 16-bit systems; not a problem
38*86ee64e7SAndroid Build Coastguard Worker                      * with any known compiler so far, though */
39*86ee64e7SAndroid Build Coastguard Worker 
40*86ee64e7SAndroid Build Coastguard Worker     (void)pcrc_32_tab;
41*86ee64e7SAndroid Build Coastguard Worker     temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
42*86ee64e7SAndroid Build Coastguard Worker     return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
43*86ee64e7SAndroid Build Coastguard Worker }
44*86ee64e7SAndroid Build Coastguard Worker 
45*86ee64e7SAndroid Build Coastguard Worker /***********************************************************************
46*86ee64e7SAndroid Build Coastguard Worker  * Update the encryption keys with the next byte of plain text
47*86ee64e7SAndroid Build Coastguard Worker  */
update_keys(unsigned long * pkeys,const z_crc_t * pcrc_32_tab,int c)48*86ee64e7SAndroid Build Coastguard Worker static int update_keys(unsigned long* pkeys, const z_crc_t* pcrc_32_tab, int c) {
49*86ee64e7SAndroid Build Coastguard Worker     (*(pkeys+0)) = CRC32((*(pkeys+0)), c);
50*86ee64e7SAndroid Build Coastguard Worker     (*(pkeys+1)) += (*(pkeys+0)) & 0xff;
51*86ee64e7SAndroid Build Coastguard Worker     (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
52*86ee64e7SAndroid Build Coastguard Worker     {
53*86ee64e7SAndroid Build Coastguard Worker       register int keyshift = (int)((*(pkeys+1)) >> 24);
54*86ee64e7SAndroid Build Coastguard Worker       (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
55*86ee64e7SAndroid Build Coastguard Worker     }
56*86ee64e7SAndroid Build Coastguard Worker     return c;
57*86ee64e7SAndroid Build Coastguard Worker }
58*86ee64e7SAndroid Build Coastguard Worker 
59*86ee64e7SAndroid Build Coastguard Worker 
60*86ee64e7SAndroid Build Coastguard Worker /***********************************************************************
61*86ee64e7SAndroid Build Coastguard Worker  * Initialize the encryption keys and the random header according to
62*86ee64e7SAndroid Build Coastguard Worker  * the given password.
63*86ee64e7SAndroid Build Coastguard Worker  */
init_keys(const char * passwd,unsigned long * pkeys,const z_crc_t * pcrc_32_tab)64*86ee64e7SAndroid Build Coastguard Worker static void init_keys(const char* passwd, unsigned long* pkeys, const z_crc_t* pcrc_32_tab) {
65*86ee64e7SAndroid Build Coastguard Worker     *(pkeys+0) = 305419896L;
66*86ee64e7SAndroid Build Coastguard Worker     *(pkeys+1) = 591751049L;
67*86ee64e7SAndroid Build Coastguard Worker     *(pkeys+2) = 878082192L;
68*86ee64e7SAndroid Build Coastguard Worker     while (*passwd != '\0') {
69*86ee64e7SAndroid Build Coastguard Worker         update_keys(pkeys,pcrc_32_tab,(int)*passwd);
70*86ee64e7SAndroid Build Coastguard Worker         passwd++;
71*86ee64e7SAndroid Build Coastguard Worker     }
72*86ee64e7SAndroid Build Coastguard Worker }
73*86ee64e7SAndroid Build Coastguard Worker 
74*86ee64e7SAndroid Build Coastguard Worker #define zdecode(pkeys,pcrc_32_tab,c) \
75*86ee64e7SAndroid Build Coastguard Worker     (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
76*86ee64e7SAndroid Build Coastguard Worker 
77*86ee64e7SAndroid Build Coastguard Worker #define zencode(pkeys,pcrc_32_tab,c,t) \
78*86ee64e7SAndroid Build Coastguard Worker     (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), (Byte)t^(c))
79*86ee64e7SAndroid Build Coastguard Worker 
80*86ee64e7SAndroid Build Coastguard Worker #ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
81*86ee64e7SAndroid Build Coastguard Worker 
82*86ee64e7SAndroid Build Coastguard Worker #define RAND_HEAD_LEN  12
83*86ee64e7SAndroid Build Coastguard Worker    /* "last resort" source for second part of crypt seed pattern */
84*86ee64e7SAndroid Build Coastguard Worker #  ifndef ZCR_SEED2
85*86ee64e7SAndroid Build Coastguard Worker #    define ZCR_SEED2 3141592654UL      /* use PI as default pattern */
86*86ee64e7SAndroid Build Coastguard Worker #  endif
87*86ee64e7SAndroid Build Coastguard Worker 
crypthead(const char * passwd,unsigned char * buf,int bufSize,unsigned long * pkeys,const z_crc_t * pcrc_32_tab,unsigned long crcForCrypting)88*86ee64e7SAndroid Build Coastguard Worker static unsigned crypthead(const char* passwd,       /* password string */
89*86ee64e7SAndroid Build Coastguard Worker                           unsigned char* buf,       /* where to write header */
90*86ee64e7SAndroid Build Coastguard Worker                           int bufSize,
91*86ee64e7SAndroid Build Coastguard Worker                           unsigned long* pkeys,
92*86ee64e7SAndroid Build Coastguard Worker                           const z_crc_t* pcrc_32_tab,
93*86ee64e7SAndroid Build Coastguard Worker                           unsigned long crcForCrypting) {
94*86ee64e7SAndroid Build Coastguard Worker     unsigned n;                  /* index in random header */
95*86ee64e7SAndroid Build Coastguard Worker     int t;                       /* temporary */
96*86ee64e7SAndroid Build Coastguard Worker     int c;                       /* random byte */
97*86ee64e7SAndroid Build Coastguard Worker     unsigned char header[RAND_HEAD_LEN-2]; /* random header */
98*86ee64e7SAndroid Build Coastguard Worker     static unsigned calls = 0;   /* ensure different random header each time */
99*86ee64e7SAndroid Build Coastguard Worker 
100*86ee64e7SAndroid Build Coastguard Worker     if (bufSize<RAND_HEAD_LEN)
101*86ee64e7SAndroid Build Coastguard Worker       return 0;
102*86ee64e7SAndroid Build Coastguard Worker 
103*86ee64e7SAndroid Build Coastguard Worker     /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
104*86ee64e7SAndroid Build Coastguard Worker      * output of rand() to get less predictability, since rand() is
105*86ee64e7SAndroid Build Coastguard Worker      * often poorly implemented.
106*86ee64e7SAndroid Build Coastguard Worker      */
107*86ee64e7SAndroid Build Coastguard Worker     if (++calls == 1)
108*86ee64e7SAndroid Build Coastguard Worker     {
109*86ee64e7SAndroid Build Coastguard Worker         srand((unsigned)(time(NULL) ^ ZCR_SEED2));
110*86ee64e7SAndroid Build Coastguard Worker     }
111*86ee64e7SAndroid Build Coastguard Worker     init_keys(passwd, pkeys, pcrc_32_tab);
112*86ee64e7SAndroid Build Coastguard Worker     for (n = 0; n < RAND_HEAD_LEN-2; n++)
113*86ee64e7SAndroid Build Coastguard Worker     {
114*86ee64e7SAndroid Build Coastguard Worker         c = (rand() >> 7) & 0xff;
115*86ee64e7SAndroid Build Coastguard Worker         header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);
116*86ee64e7SAndroid Build Coastguard Worker     }
117*86ee64e7SAndroid Build Coastguard Worker     /* Encrypt random header (last two bytes is high word of crc) */
118*86ee64e7SAndroid Build Coastguard Worker     init_keys(passwd, pkeys, pcrc_32_tab);
119*86ee64e7SAndroid Build Coastguard Worker     for (n = 0; n < RAND_HEAD_LEN-2; n++)
120*86ee64e7SAndroid Build Coastguard Worker     {
121*86ee64e7SAndroid Build Coastguard Worker         buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);
122*86ee64e7SAndroid Build Coastguard Worker     }
123*86ee64e7SAndroid Build Coastguard Worker     buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);
124*86ee64e7SAndroid Build Coastguard Worker     buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);
125*86ee64e7SAndroid Build Coastguard Worker     return n;
126*86ee64e7SAndroid Build Coastguard Worker }
127*86ee64e7SAndroid Build Coastguard Worker 
128*86ee64e7SAndroid Build Coastguard Worker #endif
129