Annotation of embedaddon/php/ext/zip/lib/zip_source_pkware.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:   zip_source_pkware.c -- Traditional PKWARE de/encryption routines
                      3:   Copyright (C) 2009 Dieter Baron and Thomas Klausner
                      4: 
                      5:   This file is part of libzip, a library to manipulate ZIP archives.
                      6:   The authors can be contacted at <libzip@nih.at>
                      7: 
                      8:   Redistribution and use in source and binary forms, with or without
                      9:   modification, are permitted provided that the following conditions
                     10:   are met:
                     11:   1. Redistributions of source code must retain the above copyright
                     12:      notice, this list of conditions and the following disclaimer.
                     13:   2. Redistributions in binary form must reproduce the above copyright
                     14:      notice, this list of conditions and the following disclaimer in
                     15:      the documentation and/or other materials provided with the
                     16:      distribution.
                     17:   3. The names of the authors may not be used to endorse or promote
                     18:      products derived from this software without specific prior
                     19:      written permission.
                     20:  
                     21:   THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
                     22:   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     23:   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     24:   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
                     25:   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     26:   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
                     27:   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     28:   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
                     29:   IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
                     30:   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
                     31:   IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     32: */
                     33: 
                     34: 
                     35: 
                     36: #include <stdlib.h>
                     37: #include <string.h>
                     38: 
                     39: #include "zipint.h"
                     40: 
                     41: struct trad_pkware {
                     42:     int e[2];
                     43: 
                     44:     zip_uint32_t key[3];
                     45: };
                     46: 
                     47: #define HEADERLEN      12
                     48: #define KEY0           305419896
                     49: #define KEY1           591751049
                     50: #define KEY2           878082192
                     51: 
                     52: static const uLongf *crc = NULL;
                     53: 
                     54: #define CRC32(c, b) (crc[((c) ^ (b)) & 0xff] ^ ((c) >> 8))
                     55: 
                     56: 
                     57: 
                     58: static void decrypt(struct trad_pkware *, zip_uint8_t *,
                     59:                    const zip_uint8_t *, zip_uint64_t, int);
                     60: static int decrypt_header(struct zip_source *, struct trad_pkware *);
                     61: static zip_int64_t pkware_decrypt(struct zip_source *, void *, void *,
                     62:                                  zip_uint64_t, enum zip_source_cmd);
                     63: static void pkware_free(struct trad_pkware *);
                     64: 
                     65: 
                     66: 
                     67: ZIP_EXTERN(struct zip_source *)
                     68: zip_source_pkware(struct zip *za, struct zip_source *src,
                     69:                  zip_uint16_t em, int flags, const char *password)
                     70: {
                     71:     struct trad_pkware *ctx;
                     72:     struct zip_source *s2;
                     73: 
                     74:     if (password == NULL || src == NULL || em != ZIP_EM_TRAD_PKWARE) {
                     75:        _zip_error_set(&za->error, ZIP_ER_INVAL, 0);
                     76:        return NULL;
                     77:     }
                     78:     if (flags & ZIP_CODEC_ENCODE) {
                     79:        _zip_error_set(&za->error, ZIP_ER_ENCRNOTSUPP, 0);
                     80:        return NULL;
                     81:     }
                     82: 
                     83:     if (crc == NULL)
                     84:        crc = get_crc_table();
                     85: 
                     86:     if ((ctx=(struct trad_pkware *)malloc(sizeof(*ctx))) == NULL) {
                     87:        _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
                     88:        return NULL;
                     89:     }
                     90: 
                     91:     ctx->e[0] = ctx->e[1] = 0;
                     92: 
                     93:     ctx->key[0] = KEY0;
                     94:     ctx->key[1] = KEY1;
                     95:     ctx->key[2] = KEY2;
                     96:     decrypt(ctx, NULL, (const zip_uint8_t *)password, strlen(password), 1);
                     97: 
                     98:     if ((s2=zip_source_layered(za, src, pkware_decrypt, ctx)) == NULL) {
                     99:        pkware_free(ctx);
                    100:        return NULL;
                    101:     }
                    102: 
                    103:     return s2;
                    104: }
                    105: 
                    106: 
                    107: 
                    108: static void
                    109: decrypt(struct trad_pkware *ctx, zip_uint8_t *out, const zip_uint8_t *in,
                    110:        zip_uint64_t len, int update_only)
                    111: {
                    112:     zip_uint16_t tmp;
                    113:     zip_uint64_t i;
                    114:     Bytef b;
                    115: 
                    116:     for (i=0; i<len; i++) {
                    117:        b = in[i];
                    118: 
                    119:        if (!update_only) {
                    120:            /* decrypt next byte */
                    121:            tmp = ctx->key[2] | 2;
                    122:            tmp = (tmp * (tmp ^ 1)) >> 8;
                    123:            b ^= tmp;
                    124:        }
                    125: 
                    126:        /* store cleartext */
                    127:        if (out)
                    128:            out[i] = b;
                    129: 
                    130:        /* update keys */
                    131:        ctx->key[0] = CRC32(ctx->key[0], b);
                    132:        ctx->key[1] = (ctx->key[1] + (ctx->key[0] & 0xff)) * 134775813 + 1;
                    133:        b = ctx->key[1] >> 24;
                    134:        ctx->key[2] = CRC32(ctx->key[2], b);
                    135:     }
                    136: }
                    137: 
                    138: 
                    139: 
                    140: static int
                    141: decrypt_header(struct zip_source *src, struct trad_pkware *ctx)
                    142: {
                    143:     zip_uint8_t header[HEADERLEN];
                    144:     struct zip_stat st;
                    145:     zip_int64_t n;
                    146:     unsigned short dostime, dosdate;
                    147: 
                    148:     if ((n=zip_source_read(src, header, HEADERLEN)) < 0) {
                    149:        zip_source_error(src, ctx->e, ctx->e+1);
                    150:        return -1;
                    151:     }
                    152:     
                    153:     if (n != HEADERLEN) {
                    154:        ctx->e[0] = ZIP_ER_EOF;
                    155:        ctx->e[1] = 0;
                    156:        return -1;
                    157:     }
                    158: 
                    159:     decrypt(ctx, header, header, HEADERLEN, 0);
                    160: 
                    161:     if (zip_source_stat(src, &st) < 0) {
                    162:        /* stat failed, skip password validation */
                    163:        return 0;
                    164:     }
                    165: 
                    166:     _zip_u2d_time(st.mtime, &dostime, &dosdate);
                    167: 
                    168:     if (header[HEADERLEN-1] != st.crc>>24
                    169:        && header[HEADERLEN-1] != dostime>>8) {
                    170:        ctx->e[0] = ZIP_ER_WRONGPASSWD;
                    171:        ctx->e[1] = 0;
                    172:        return -1;
                    173:     }
                    174: 
                    175:     return 0;
                    176: }
                    177: 
                    178: 
                    179: 
                    180: static zip_int64_t
                    181: pkware_decrypt(struct zip_source *src, void *ud, void *data,
                    182:               zip_uint64_t len, enum zip_source_cmd cmd)
                    183: {
                    184:     struct trad_pkware *ctx;
                    185:     zip_int64_t n;
                    186: 
                    187:     ctx = (struct trad_pkware *)ud;
                    188: 
                    189:     switch (cmd) {
                    190:     case ZIP_SOURCE_OPEN:
                    191:        if (decrypt_header(src, ctx) < 0)
                    192:            return -1;
                    193:        return 0;
                    194: 
                    195:     case ZIP_SOURCE_READ:
                    196:        if ((n=zip_source_read(src, data, len)) < 0)
                    197:            return ZIP_SOURCE_ERR_LOWER;
                    198: 
                    199:        decrypt(ud, (zip_uint8_t *)data, (zip_uint8_t *)data, (zip_uint64_t)n,
                    200:                0);
                    201:        return n;
                    202: 
                    203:     case ZIP_SOURCE_CLOSE:
                    204:        return 0;
                    205: 
                    206:     case ZIP_SOURCE_STAT:
                    207:        {
                    208:            struct zip_stat *st;
                    209: 
                    210:            st = (struct zip_stat *)data;
                    211: 
                    212:            st->encryption_method = ZIP_EM_NONE;
                    213:            st->valid |= ZIP_STAT_ENCRYPTION_METHOD;
                    214:            /* XXX: deduce HEADERLEN from size for uncompressed */
                    215:            if (st->valid & ZIP_STAT_COMP_SIZE)
                    216:                st->comp_size -= HEADERLEN;
                    217:        }
                    218:        return 0;
                    219: 
                    220:     case ZIP_SOURCE_ERROR:
                    221:        memcpy(data, ctx->e, sizeof(int)*2);
                    222:        return sizeof(int)*2;
                    223: 
                    224:     case ZIP_SOURCE_FREE:
                    225:        pkware_free(ctx);
                    226:        return 0;
                    227: 
                    228:     default:
                    229:        ctx->e[0] = ZIP_ER_INVAL;
                    230:        ctx->e[1] = 0;
                    231:        return -1;
                    232:     }
                    233: }
                    234: 
                    235: 
                    236: 
                    237: static void
                    238: pkware_free(struct trad_pkware *ctx)
                    239: {
                    240:     free(ctx);
                    241: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>