diff options
-rw-r--r-- | configure.in | 5 | ||||
-rw-r--r-- | navit/Makefile.am | 2 | ||||
-rw-r--r-- | navit/file.c | 85 | ||||
-rw-r--r-- | navit/file.h | 1 | ||||
-rw-r--r-- | navit/map/binfile/binfile.c | 30 | ||||
-rw-r--r-- | navit/maptool/Makefile.am | 2 | ||||
-rw-r--r-- | navit/maptool/maptool.h | 1 | ||||
-rw-r--r-- | navit/maptool/zip.c | 104 | ||||
-rw-r--r-- | navit/zipfile.h | 9 |
9 files changed, 226 insertions, 13 deletions
diff --git a/configure.in b/configure.in index 8e3f04285..90bed84ad 100644 --- a/configure.in +++ b/configure.in @@ -264,6 +264,11 @@ else [plugins="no"; plugins_reason="package gmodule and dlopen missing"] ) fi + +# libcrypto +AC_CHECK_LIB(crypto, AES_encrypt, [CRYPTO_LIBS="-lcrypto";AC_DEFINE(HAVE_LIBCRYPTO, 1, [Define to 1 if you have libcrypto])]) +AC_SUBST(CRYPTO_LIBS) + # plugins AC_ARG_ENABLE(plugins, [ --disable-plugins disable plugins], [ plugins=$enableval;plugin_reason="configure parameter" ]) if test "x${plugins}" = "xyes"; then diff --git a/navit/Makefile.am b/navit/Makefile.am index 198761f62..b2339f932 100644 --- a/navit/Makefile.am +++ b/navit/Makefile.am @@ -105,7 +105,7 @@ if !PLUGINS navit_LDADD += $(wildcard $(top_builddir)/navit/*/*/*.la) endif -navit_LDADD += @NAVIT_LIBS@ @WORDEXP_LIBS@ @ZLIB_LIBS@ @INTLLIBS@ +navit_LDADD += @NAVIT_LIBS@ @WORDEXP_LIBS@ @ZLIB_LIBS@ @CRYPTO_LIBS@ @INTLLIBS@ if SUPPORT_WIN32 navit_LDADD += resource.rsc diff --git a/navit/file.c b/navit/file.c index b41d2695b..9b5e849ed 100644 --- a/navit/file.c +++ b/navit/file.c @@ -36,6 +36,15 @@ #include "atom.h" #include "config.h" +#ifdef HAVE_LIBCRYPTO +#include <openssl/sha.h> +#include <openssl/hmac.h> +#include <openssl/aes.h> +#include <openssl/evp.h> +#include <openssl/rand.h> +#endif + + #ifndef O_LARGEFILE #define O_LARGEFILE 0 #endif @@ -44,6 +53,7 @@ #define O_BINARY 0 #endif +#define CACHE_SIZE (10*1024*1024) #ifdef CACHE_SIZE static GHashTable *file_name_hash; #endif @@ -301,6 +311,81 @@ file_data_read_compressed(struct file *file, long long offset, int size, int siz return ret; } +unsigned char * +file_data_read_encrypted(struct file *file, long long offset, int size, int size_uncomp, int compressed, char *passwd) +{ +#ifdef HAVE_LIBCRYPTO + void *ret; + unsigned char *buffer = 0; + uLongf destLen=size_uncomp; + + if (file_cache) { + struct file_cache_id id={offset,size,file->name_id,1}; + ret=cache_lookup(file_cache,&id); + if (ret) + return ret; + ret=cache_insert_new(file_cache,&id,size_uncomp); + } else + ret=g_malloc(size_uncomp); + lseek(file->fd, offset, SEEK_SET); + + buffer = (unsigned char *)g_malloc(size); + if (read(file->fd, buffer, size) != size) { + g_free(ret); + ret=NULL; + } else { + unsigned char key[34], salt[8], verify[2], counter[16], xor[16], mac[10], mactmp[20], *datap; + int overhead=sizeof(salt)+sizeof(verify)+sizeof(mac); + int esize=size-overhead; + PKCS5_PBKDF2_HMAC_SHA1(passwd, strlen(passwd), (unsigned char *)buffer, 8, 1000, 34, key); + if (key[32] == buffer[8] && key[33] == buffer[9] && esize >= 0) { + AES_KEY aeskey; + AES_set_encrypt_key(key, 128, &aeskey); + datap=buffer+sizeof(salt)+sizeof(verify); + memset(counter, 0, sizeof(counter)); + while (esize > 0) { + int i,curr_size,idx=0; + do { + counter[idx]++; + } while (!counter[idx++]); + AES_encrypt(counter, xor, &aeskey); + curr_size=esize; + if (curr_size > sizeof(xor)) + curr_size=sizeof(xor); + for (i = 0 ; i < curr_size ; i++) + *datap++^=xor[i]; + esize-=curr_size; + } + size-=overhead; + datap=buffer+sizeof(salt)+sizeof(verify); + if (compressed) { + if (uncompress_int(ret, &destLen, (Bytef *)datap, size) != Z_OK) { + dbg(0,"uncompress failed\n"); + g_free(ret); + ret=NULL; + } + } else { + if (size == destLen) + memcpy(ret, destLen, buffer); + else { + dbg(0,"memcpy failed\n"); + g_free(ret); + ret=NULL; + } + } + } else { + g_free(ret); + ret=NULL; + } + } + g_free(buffer); + + return ret; +#else + return NULL; +#endif +} + void file_data_free(struct file *file, unsigned char *data) { diff --git a/navit/file.h b/navit/file.h index 00533add8..fde1aba34 100644 --- a/navit/file.h +++ b/navit/file.h @@ -68,6 +68,7 @@ unsigned char *file_data_read_all(struct file *file); int file_data_write(struct file *file, long long offset, int size, unsigned char *data); int file_get_contents(char *name, unsigned char **buffer, int *size); unsigned char *file_data_read_compressed(struct file *file, long long offset, int size, int size_uncomp); +unsigned char *file_data_read_encrypted(struct file *file, long long offset, int size, int size_uncomp, int compressed, char *passwd); void file_data_free(struct file *file, unsigned char *data); int file_exists(char *name); void file_remap_readonly(struct file *f); diff --git a/navit/map/binfile/binfile.c b/navit/map/binfile/binfile.c index b8ddd1075..125305516 100644 --- a/navit/map/binfile/binfile.c +++ b/navit/map/binfile/binfile.c @@ -217,16 +217,38 @@ binfile_read_lfh(struct file *fi, unsigned int offset) static unsigned char * binfile_read_content(struct file *fi, int offset, struct zip_lfh *lfh) { - offset+=sizeof(struct zip_lfh)+lfh->zipfnln+lfh->zipxtraln; + struct zip_enc *enc; + unsigned char *ret=NULL; + + offset+=sizeof(struct zip_lfh)+lfh->zipfnln; switch (lfh->zipmthd) { case 0: - return file_data_read(fi,offset, lfh->zipuncmp); + offset+=lfh->zipxtraln; + ret=file_data_read(fi,offset, lfh->zipuncmp); + break; case 8: - return file_data_read_compressed(fi,offset, lfh->zipsize, lfh->zipuncmp); + offset+=lfh->zipxtraln; + ret=file_data_read_compressed(fi,offset, lfh->zipsize, lfh->zipuncmp); + break; + case 99: + enc=(struct zip_enc *)file_data_read(fi, offset, sizeof(*enc)); + offset+=lfh->zipxtraln; + switch (enc->compress_method) { + case 0: + ret=file_data_read_encrypted(fi, offset, lfh->zipsize, lfh->zipuncmp, 0, "test"); + break; + case 8: + ret=file_data_read_encrypted(fi, offset, lfh->zipsize, lfh->zipuncmp, 1, "test"); + break; + default: + dbg(0,"Unknown encrypted compression method %d\n",enc->compress_method); + } + file_data_free(fi, (unsigned char *)enc); + break; default: dbg(0,"Unknown compression method %d\n", lfh->zipmthd); - return NULL; } + return ret; } static int diff --git a/navit/maptool/Makefile.am b/navit/maptool/Makefile.am index 2d5e39244..4688ab449 100644 --- a/navit/maptool/Makefile.am +++ b/navit/maptool/Makefile.am @@ -7,4 +7,4 @@ endif AM_CPPFLAGS = @NAVIT_CFLAGS@ -I$(top_srcdir)/navit @ZLIB_CFLAGS@ @POSTGRESQL_CFLAGS@ -DMODULE=maptool libmaptool_la_SOURCES = buffer.c ch.c coastline.c geom.c itembin.c misc.c osm.c sourcesink.c tempfile.c tile.c zip.c maptool.h maptool_SOURCES = maptool.c -maptool_LDADD = libmaptool.la ../libnavit.la @NAVIT_LIBS@ @WORDEXP_LIBS@ @ZLIB_LIBS@ @POSTGRESQL_LIBS@ @INTLLIBS@ @LIBC_LIBS@ +maptool_LDADD = libmaptool.la ../libnavit.la @NAVIT_LIBS@ @WORDEXP_LIBS@ @ZLIB_LIBS@ @POSTGRESQL_LIBS@ @CRYPTO_LIBS@ @INTLLIBS@ @LIBC_LIBS@ diff --git a/navit/maptool/maptool.h b/navit/maptool/maptool.h index 8f97f8e32..09c494c98 100644 --- a/navit/maptool/maptool.h +++ b/navit/maptool/maptool.h @@ -85,6 +85,7 @@ struct zip_info { int zip64; short date; short time; + char *passwd; FILE *res; FILE *index; FILE *dir; diff --git a/navit/maptool/zip.c b/navit/maptool/zip.c index 299910d0e..5c1c4b914 100644 --- a/navit/maptool/zip.c +++ b/navit/maptool/zip.c @@ -23,6 +23,14 @@ #include "maptool.h" #include "zipfile.h" +#ifdef HAVE_LIBCRYPTO +#include <openssl/sha.h> +#include <openssl/hmac.h> +#include <openssl/aes.h> +#include <openssl/evp.h> +#include <openssl/rand.h> +#endif + static int compress2_int(Byte *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level) { @@ -95,8 +103,19 @@ write_zipmember(struct zip_info *zip_info, char *name, int filelen, char *data, 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[filelen+1]; - int error,crc,len,comp_size=data_size; + int error,crc=0,len,comp_size=data_size; uLongf destlen=data_size+data_size/500+12; char *compbuffer; @@ -105,9 +124,19 @@ write_zipmember(struct zip_info *zip_info, char *name, int filelen, char *data, fprintf(stderr, "No more memory.\n"); exit (1); } - - crc=crc32(0, NULL, 0); - crc=crc32(crc, (unsigned char *)data, data_size); +#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 #ifdef HAVE_ZLIB if (zip_info->compression_level) { error=compress2_int((Byte *)compbuffer, &destlen, (Bytef *)data, data_size, zip_info->compression_level); @@ -125,14 +154,30 @@ write_zipmember(struct zip_info *zip_info, char *name, int filelen, char *data, lfh.zipsize=comp_size; lfh.zipuncmp=data_size; lfh.zipmthd=zip_info->compression_level ? 8:0; +#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=comp_size; + cd.zipcsiz=lfh.zipsize; cd.zipcunc=data_size; cd.zipcmthd=zip_info->compression_level ? 8:0; if (zip_info->zip64) { cd.zipofst=0xffffffff; - cd.zipcxtl=sizeof(cd_ext); + cd.zipcxtl+=sizeof(cd_ext); + } +#ifdef HAVE_LIBCRYPTO + if (zip_info->passwd) { + cd.zipcmthd=99; + cd.zipcxtl+=sizeof(enc); + cd.zipcflg|=1; } +#endif strcpy(filename, name); len=strlen(filename); while (len < filelen) { @@ -141,8 +186,47 @@ write_zipmember(struct zip_info *zip_info, char *name, int filelen, char *data, filename[filelen]='\0'; fwrite(&lfh, sizeof(lfh), 1, zip_info->res); fwrite(filename, filelen, 1, zip_info->res); + 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; + fwrite(&enc, sizeof(enc), 1, zip_info->res); + fwrite(salt, sizeof(salt), 1, zip_info->res); + fwrite(verify, sizeof(verify), 1, zip_info->res); + zip_info->offset+=sizeof(enc)+sizeof(salt)+sizeof(verify); + AES_set_encrypt_key(key, 128, &aeskey); + memset(counter, 0, sizeof(counter)); + fprintf(stderr,"size=%d\n",size); + 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++) { + fprintf(stderr,"0x%x=0x%x\n",datap[0],datap[0]^xor[i]); + *datap++^=xor[i]; + } + size-=curr_size; + } + } +#endif fwrite(data, comp_size, 1, zip_info->res); - zip_info->offset+=sizeof(lfh)+filelen+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); + fwrite(mactmp, sizeof(mac), 1, zip_info->res); + 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; @@ -150,6 +234,12 @@ write_zipmember(struct zip_info *zip_info, char *name, int filelen, char *data, 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); } diff --git a/navit/zipfile.h b/navit/zipfile.h index 402c074fb..d377f80c7 100644 --- a/navit/zipfile.h +++ b/navit/zipfile.h @@ -75,6 +75,15 @@ struct zip_cd_ext { unsigned long long zipofst; } __attribute__ ((packed)); +struct zip_enc { + short efield_header; + short efield_size; + short version; + char vendor_id1,vendor_id2; + char encryption_strength; + short compress_method; +} __attribute__ ((packed)); + struct zip_eoc { int zipesig; unsigned short zipedsk; |