kusano 7d535a
/* crypt.h -- base code for crypt/uncrypt ZIPfile
kusano 7d535a
kusano 7d535a
kusano 7d535a
   Version 1.01e, February 12th, 2005
kusano 7d535a
kusano 7d535a
   Copyright (C) 1998-2005 Gilles Vollant
kusano 7d535a
kusano 7d535a
   This code is a modified version of crypting code in Infozip distribution
kusano 7d535a
kusano 7d535a
   The encryption/decryption parts of this source code (as opposed to the
kusano 7d535a
   non-echoing password parts) were originally written in Europe.  The
kusano 7d535a
   whole source package can be freely distributed, including from the USA.
kusano 7d535a
   (Prior to January 2000, re-export from the US was a violation of US law.)
kusano 7d535a
kusano 7d535a
   This encryption code is a direct transcription of the algorithm from
kusano 7d535a
   Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
kusano 7d535a
   file (appnote.txt) is distributed with the PKZIP program (even in the
kusano 7d535a
   version without encryption capabilities).
kusano 7d535a
kusano 7d535a
   If you don't need crypting in your application, just define symbols
kusano 7d535a
   NOCRYPT and NOUNCRYPT.
kusano 7d535a
kusano 7d535a
   This code support the "Traditional PKWARE Encryption".
kusano 7d535a
kusano 7d535a
   The new AES encryption added on Zip format by Winzip (see the page
kusano 7d535a
   http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong
kusano 7d535a
   Encryption is not supported.
kusano 7d535a
*/
kusano 7d535a
kusano 7d535a
#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
kusano 7d535a
kusano 7d535a
/***********************************************************************
kusano 7d535a
 * Return the next byte in the pseudo-random sequence
kusano 7d535a
 */
kusano 7d535a
static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
kusano 7d535a
{
kusano 7d535a
    unsigned temp;  /* POTENTIAL BUG:  temp*(temp^1) may overflow in an
kusano 7d535a
                     * unpredictable manner on 16-bit systems; not a problem
kusano 7d535a
                     * with any known compiler so far, though */
kusano 7d535a
kusano 7d535a
    temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
kusano 7d535a
    return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
/***********************************************************************
kusano 7d535a
 * Update the encryption keys with the next byte of plain text
kusano 7d535a
 */
kusano 7d535a
static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c)
kusano 7d535a
{
kusano 7d535a
    (*(pkeys+0)) = CRC32((*(pkeys+0)), c);
kusano 7d535a
    (*(pkeys+1)) += (*(pkeys+0)) & 0xff;
kusano 7d535a
    (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
kusano 7d535a
    {
kusano 7d535a
      register int keyshift = (int)((*(pkeys+1)) >> 24);
kusano 7d535a
      (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
kusano 7d535a
    }
kusano 7d535a
    return c;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
kusano 7d535a
/***********************************************************************
kusano 7d535a
 * Initialize the encryption keys and the random header according to
kusano 7d535a
 * the given password.
kusano 7d535a
 */
kusano 7d535a
static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)
kusano 7d535a
{
kusano 7d535a
    *(pkeys+0) = 305419896L;
kusano 7d535a
    *(pkeys+1) = 591751049L;
kusano 7d535a
    *(pkeys+2) = 878082192L;
kusano 7d535a
    while (*passwd != '\0') {
kusano 7d535a
        update_keys(pkeys,pcrc_32_tab,(int)*passwd);
kusano 7d535a
        passwd++;
kusano 7d535a
    }
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
#define zdecode(pkeys,pcrc_32_tab,c) \
kusano 7d535a
    (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
kusano 7d535a
kusano 7d535a
#define zencode(pkeys,pcrc_32_tab,c,t) \
kusano 7d535a
    (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))
kusano 7d535a
kusano 7d535a
#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
kusano 7d535a
kusano 7d535a
#define RAND_HEAD_LEN  12
kusano 7d535a
   /* "last resort" source for second part of crypt seed pattern */
kusano 7d535a
#  ifndef ZCR_SEED2
kusano 7d535a
#    define ZCR_SEED2 3141592654UL     /* use PI as default pattern */
kusano 7d535a
#  endif
kusano 7d535a
kusano 7d535a
static int crypthead(const char* passwd,      /* password string */
kusano 7d535a
                     unsigned char* buf,      /* where to write header */
kusano 7d535a
                     int bufSize,
kusano 7d535a
                     unsigned long* pkeys,
kusano 7d535a
                     const unsigned long* pcrc_32_tab,
kusano 7d535a
                     unsigned long crcForCrypting)
kusano 7d535a
{
kusano 7d535a
    int n;                       /* index in random header */
kusano 7d535a
    int t;                       /* temporary */
kusano 7d535a
    int c;                       /* random byte */
kusano 7d535a
    unsigned char header[RAND_HEAD_LEN-2]; /* random header */
kusano 7d535a
    static unsigned calls = 0;   /* ensure different random header each time */
kusano 7d535a
kusano 7d535a
    if (bufSize
kusano 7d535a
      return 0;
kusano 7d535a
kusano 7d535a
    /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
kusano 7d535a
     * output of rand() to get less predictability, since rand() is
kusano 7d535a
     * often poorly implemented.
kusano 7d535a
     */
kusano 7d535a
    if (++calls == 1)
kusano 7d535a
    {
kusano 7d535a
        srand((unsigned)(time(NULL) ^ ZCR_SEED2));
kusano 7d535a
    }
kusano 7d535a
    init_keys(passwd, pkeys, pcrc_32_tab);
kusano 7d535a
    for (n = 0; n < RAND_HEAD_LEN-2; n++)
kusano 7d535a
    {
kusano 7d535a
        c = (rand() >> 7) & 0xff;
kusano 7d535a
        header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);
kusano 7d535a
    }
kusano 7d535a
    /* Encrypt random header (last two bytes is high word of crc) */
kusano 7d535a
    init_keys(passwd, pkeys, pcrc_32_tab);
kusano 7d535a
    for (n = 0; n < RAND_HEAD_LEN-2; n++)
kusano 7d535a
    {
kusano 7d535a
        buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);
kusano 7d535a
    }
kusano 7d535a
    buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);
kusano 7d535a
    buf[n++] = (unsigned char)zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);
kusano 7d535a
    return n;
kusano 7d535a
}
kusano 7d535a
kusano 7d535a
#endif