DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
include/crypt.h
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