Annotation of embedaddon/php/ext/zip/lib/zip_source_pkware.c, revision 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>