예제 #1
0
파일: zip.c 프로젝트: PDXostc/navit
void
write_zipmember(struct zip_info *zip_info, char *name, int filelen, char *data, int data_size)
{
	struct zip_lfh lfh = {
		0x04034b50,
		0x0a,
		0x0,
		0x0,
		zip_info->time,
		zip_info->date,
		0x0,
		0x0,
		0x0,
		filelen,
		0x0,
	};
	struct zip_cd cd = {
		0x02014b50,
		0x17,
		0x00,
		0x0a,
		0x00,
		0x0000,
		0x0,
		zip_info->time,
		zip_info->date,
		0x0,
		0x0,
		0x0,
		filelen,
		0x0000,
		0x0000,
		0x0000,
		0x0000,
		0x0,
		zip_info->offset,
	};
	struct zip_cd_ext cd_ext = {
		0x1,
		0x8,
		zip_info->offset,
	};
#ifdef HAVE_LIBCRYPTO
	struct zip_enc enc = {
		0x9901,
		0x7,
		0x2,
		'A','E',
		0x1,
		0x0,
	};
	unsigned char salt[8], key[34], verify[2], mac[10];
#endif
	char *filename;
	int crc=0,len,comp_size=data_size;
	uLongf destlen=data_size+data_size/500+12;
	char *compbuffer;

	compbuffer = malloc(destlen);
	if (!compbuffer) {
	  fprintf(stderr, "No more memory.\n");
	  exit (1);
	}
#ifdef HAVE_LIBCRYPTO
	if (zip_info->passwd) {	
		RAND_bytes(salt, sizeof(salt));
		PKCS5_PBKDF2_HMAC_SHA1(zip_info->passwd, strlen(zip_info->passwd), salt, sizeof(salt), 1000, sizeof(key), key);
		verify[0]=key[32];
		verify[1]=key[33];
	} else {
#endif
		crc=crc32(0, NULL, 0);
		crc=crc32(crc, (unsigned char *)data, data_size);
#ifdef HAVE_LIBCRYPTO
	}
#endif
	lfh.zipmthd=zip_info->compression_level ? 8:0;
#ifdef HAVE_ZLIB
	if (zip_info->compression_level) {
		int error=compress2_int((Byte *)compbuffer, &destlen, (Bytef *)data, data_size, zip_info->compression_level);
		if (error == Z_OK) {
			if (destlen < data_size) {
				data=compbuffer;
				comp_size=destlen;
			} else
				lfh.zipmthd=0;
		} else {
			fprintf(stderr,"compress2 returned %d\n", error);
		}
	}
#endif
	lfh.zipcrc=crc;
	lfh.zipsize=comp_size;
	lfh.zipuncmp=data_size;
#ifdef HAVE_LIBCRYPTO
	if (zip_info->passwd) {
		enc.compress_method=lfh.zipmthd;
		lfh.zipmthd=99;
		lfh.zipxtraln+=sizeof(enc);
		lfh.zipgenfld|=1;
		lfh.zipsize+=sizeof(salt)+sizeof(verify)+sizeof(mac);
	}
#endif
	cd.zipccrc=crc;
	cd.zipcsiz=lfh.zipsize;
	cd.zipcunc=data_size;
	cd.zipcmthd=lfh.zipmthd;
	if (zip_info->zip64) {
		cd.zipofst=0xffffffff;
		cd.zipcxtl+=sizeof(cd_ext);
	}
#ifdef HAVE_LIBCRYPTO
	if (zip_info->passwd) {
		cd.zipcmthd=99;
		cd.zipcxtl+=sizeof(enc);
		cd.zipcflg|=1;
	}
#endif
	filename=g_alloca(filelen+1);
	strcpy(filename, name);
	len=strlen(filename);
	while (len < filelen) {
		filename[len++]='_';
	}
	filename[filelen]='\0';
	zip_write(zip_info, &lfh, sizeof(lfh));
	zip_write(zip_info, filename, filelen);
	zip_info->offset+=sizeof(lfh)+filelen;
#ifdef HAVE_LIBCRYPTO
	if (zip_info->passwd) {
		unsigned char counter[16], xor[16], *datap=(unsigned char *)data;
		int size=comp_size;
		AES_KEY aeskey;
		zip_write(zip_info, &enc, sizeof(enc));
		zip_write(zip_info, salt, sizeof(salt));
		zip_write(zip_info, verify, sizeof(verify));
		zip_info->offset+=sizeof(enc)+sizeof(salt)+sizeof(verify);
		AES_set_encrypt_key(key, 128, &aeskey);
		memset(counter, 0, sizeof(counter));
		while (size > 0) {
			int i,curr_size,idx=0;
			do {
				counter[idx]++;
			} while (!counter[idx++]);
			AES_encrypt(counter, xor, &aeskey);
			curr_size=size;
			if (curr_size > sizeof(xor))
				curr_size=sizeof(xor);
			for (i = 0 ; i < curr_size ; i++) 
				*datap++^=xor[i];
			size-=curr_size;
		}
	}
#endif
	zip_write(zip_info, data, comp_size);
	zip_info->offset+=comp_size;
#ifdef HAVE_LIBCRYPTO
	if (zip_info->passwd) {
		unsigned int maclen=sizeof(mac);
		unsigned char mactmp[maclen*2];
		HMAC(EVP_sha1(), key+16, 16, (unsigned char *)data, comp_size, mactmp, &maclen);
		zip_write(zip_info, mactmp, sizeof(mac));
		zip_info->offset+=sizeof(mac);
	}
#endif
	fwrite(&cd, sizeof(cd), 1, zip_info->dir);
	fwrite(filename, filelen, 1, zip_info->dir);
	zip_info->dir_size+=sizeof(cd)+filelen;
	if (zip_info->zip64) {
		fwrite(&cd_ext, sizeof(cd_ext), 1, zip_info->dir);
		zip_info->dir_size+=sizeof(cd_ext);
	}
#ifdef HAVE_LIBCRYPTO
	if (zip_info->passwd) {
		fwrite(&enc, sizeof(enc), 1, zip_info->dir);
		zip_info->dir_size+=sizeof(enc);
	}
#endif
	
	free(compbuffer);
}
예제 #2
0
파일: zip.c 프로젝트: justinzane/navit
void
write_zipmember(struct zip_info *zip_info, char *name, int filelen, char *data, int data_size)
{
	struct zip_lfh lfh = {
		0x04034b50,
		0x0a,
		0x0,
		0x0,
		zip_info->time,
		zip_info->date,
		0x0,
		0x0,
		0x0,
		filelen,
		0x0,
	};
	struct zip_cd cd = {
		0x02014b50,
		0x17,
		0x00,
		0x0a,
		0x00,
		0x0000,
		0x0,
		zip_info->time,
		zip_info->date,
		0x0,
		0x0,
		0x0,
		filelen,
		0x0000,
		0x0000,
		0x0000,
		0x0000,
		0x0,
		zip_info->offset,
	};
	struct zip_cd_ext cd_ext = {
		0x1,
		0x8,
		zip_info->offset,
	};
	char filename[filelen+1];
	int error,crc,len,comp_size=data_size;
	uLongf destlen=data_size+data_size/500+12;
	char *compbuffer;

	compbuffer = malloc(destlen);
	if (!compbuffer) {
	  fprintf(stderr, "No more memory.\n");
	  exit (1);
	}

	crc=crc32(0, NULL, 0);
	crc=crc32(crc, (unsigned char *)data, data_size);
#ifdef HAVE_ZLIB
	if (zip_info->compression_level) {
		error=compress2_int((Byte *)compbuffer, &destlen, (Bytef *)data, data_size, zip_info->compression_level);
		if (error == Z_OK) {
			if (destlen < data_size) {
				data=compbuffer;
				comp_size=destlen;
			}
		} else {
			fprintf(stderr,"compress2 returned %d\n", error);
		}
	}
#endif
	lfh.zipcrc=crc;
	lfh.zipsize=comp_size;
	lfh.zipuncmp=data_size;
	lfh.zipmthd=zip_info->compression_level ? 8:0;
	cd.zipccrc=crc;
	cd.zipcsiz=comp_size;
	cd.zipcunc=data_size;
	cd.zipcmthd=zip_info->compression_level ? 8:0;
	if (zip_info->zip64) {
		cd.zipofst=0xffffffff;
		cd.zipcxtl=sizeof(cd_ext);
	}
	strcpy(filename, name);
	len=strlen(filename);
	while (len < filelen) {
		filename[len++]='_';
	}
	filename[filelen]='\0';
	fwrite(&lfh, sizeof(lfh), 1, zip_info->res);
	fwrite(filename, filelen, 1, zip_info->res);
	fwrite(data, comp_size, 1, zip_info->res);
	zip_info->offset+=sizeof(lfh)+filelen+comp_size;
	fwrite(&cd, sizeof(cd), 1, zip_info->dir);
	fwrite(filename, filelen, 1, zip_info->dir);
	zip_info->dir_size+=sizeof(cd)+filelen;
	if (zip_info->zip64) {
		fwrite(&cd_ext, sizeof(cd_ext), 1, zip_info->dir);
		zip_info->dir_size+=sizeof(cd_ext);
	}
	
	free(compbuffer);
}