summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.in5
-rw-r--r--navit/Makefile.am2
-rw-r--r--navit/file.c85
-rw-r--r--navit/file.h1
-rw-r--r--navit/map/binfile/binfile.c30
-rw-r--r--navit/maptool/Makefile.am2
-rw-r--r--navit/maptool/maptool.h1
-rw-r--r--navit/maptool/zip.c104
-rw-r--r--navit/zipfile.h9
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;