DOSBox-X
|
00001 /* crypt.h -- base code for crypt/uncrypt ZIPfile 00002 00003 00004 Version 1.01e, February 12th, 2005 00005 00006 Copyright (C) 1998-2005 Gilles Vollant 00007 00008 This code is a modified version of crypting code in Infozip distribution 00009 00010 The encryption/decryption parts of this source code (as opposed to the 00011 non-echoing password parts) were originally written in Europe. The 00012 whole source package can be freely distributed, including from the USA. 00013 (Prior to January 2000, re-export from the US was a violation of US law.) 00014 00015 This encryption code is a direct transcription of the algorithm from 00016 Roger Schlafly, described by Phil Katz in the file appnote.txt. This 00017 file (appnote.txt) is distributed with the PKZIP program (even in the 00018 version without encryption capabilities). 00019 00020 If you don't need crypting in your application, just define symbols 00021 NOCRYPT and NOUNCRYPT. 00022 00023 This code support the "Traditional PKWARE Encryption". 00024 00025 The new AES encryption added on Zip format by Winzip (see the page 00026 http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong 00027 Encryption is not supported. 00028 */ 00029 00030 #define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) 00031 00032 /*********************************************************************** 00033 * Return the next byte in the pseudo-random sequence 00034 */ 00035 static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab) 00036 { 00037 unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an 00038 * unpredictable manner on 16-bit systems; not a problem 00039 * with any known compiler so far, though */ 00040 00041 temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; 00042 return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); 00043 } 00044 00045 /*********************************************************************** 00046 * Update the encryption keys with the next byte of plain text 00047 */ 00048 static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c) 00049 { 00050 (*(pkeys+0)) = CRC32((*(pkeys+0)), c); 00051 (*(pkeys+1)) += (*(pkeys+0)) & 0xff; 00052 (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; 00053 { 00054 register int keyshift = (int)((*(pkeys+1)) >> 24); 00055 (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); 00056 } 00057 return c; 00058 } 00059 00060 00061 /*********************************************************************** 00062 * Initialize the encryption keys and the random header according to 00063 * the given password. 00064 */ 00065 static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab) 00066 { 00067 *(pkeys+0) = 305419896L; 00068 *(pkeys+1) = 591751049L; 00069 *(pkeys+2) = 878082192L; 00070 while (*passwd != '\0') { 00071 update_keys(pkeys,pcrc_32_tab,(int)*passwd); 00072 passwd++; 00073 } 00074 } 00075 00076 #define zdecode(pkeys,pcrc_32_tab,c) \ 00077 (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) 00078 00079 #define zencode(pkeys,pcrc_32_tab,c,t) \ 00080 (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) 00081 00082 #ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED 00083 00084 #define RAND_HEAD_LEN 12 00085 /* "last resort" source for second part of crypt seed pattern */ 00086 # ifndef ZCR_SEED2 00087 # define ZCR_SEED2 3141592654UL /* use PI as default pattern */ 00088 # endif 00089 00090 static int crypthead(const char* passwd, /* password string */ 00091 unsigned char* buf, /* where to write header */ 00092 int bufSize, 00093 unsigned long* pkeys, 00094 const unsigned long* pcrc_32_tab, 00095 unsigned long crcForCrypting) 00096 { 00097 int n; /* index in random header */ 00098 int t; /* temporary */ 00099 int c; /* random byte */ 00100 unsigned char header[RAND_HEAD_LEN-2]; /* random header */ 00101 static unsigned calls = 0; /* ensure different random header each time */ 00102 00103 if (bufSize<RAND_HEAD_LEN) 00104 return 0; 00105 00106 /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the 00107 * output of rand() to get less predictability, since rand() is 00108 * often poorly implemented. 00109 */ 00110 if (++calls == 1) 00111 { 00112 srand((unsigned)(time(NULL) ^ ZCR_SEED2)); 00113 } 00114 init_keys(passwd, pkeys, pcrc_32_tab); 00115 for (n = 0; n < RAND_HEAD_LEN-2; n++) 00116 { 00117 c = (rand() >> 7) & 0xff; 00118 header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); 00119 } 00120 /* Encrypt random header (last two bytes is high word of crc) */ 00121 init_keys(passwd, pkeys, pcrc_32_tab); 00122 for (n = 0; n < RAND_HEAD_LEN-2; n++) 00123 { 00124 buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); 00125 } 00126 buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); 00127 buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); 00128 return n; 00129 } 00130 00131 #endif