Index: kitsh/buildsrc/kitsh-0.0/Makefile.common.in ================================================================== --- kitsh/buildsrc/kitsh-0.0/Makefile.common.in +++ kitsh/buildsrc/kitsh-0.0/Makefile.common.in @@ -13,16 +13,17 @@ LDRUNPATH = @LDRUNPATH@ EXTRA_KIT_DEPS = @EXTRA_KIT_DEPS@ EXTRA_VFS_OBJS = @EXTRA_VFS_OBJS@ TCLSH_NATIVE = tclsh LDFLAGS_ADD = @LDFLAGS_ADD@ +DIR2C_FLAGS = @DIR2C_FLAGS@ # Build targets ## VFS Build cvfs_data_tcl.o: cvfs_data_tcl.c cvfs_data_tcl.c: dir2c.tcl starpack.vfs cvfs_data.c - "$(TCLSH_NATIVE)" dir2c.tcl tcl starpack.vfs > cvfs_data_tcl.c + "$(TCLSH_NATIVE)" dir2c.tcl tcl starpack.vfs $(DIR2C_FLAGS) > cvfs_data_tcl.c ## Tcl scripts that need to be converted to C headers cvfs.tcl.h: cvfs.tcl "$(TCLSH_NATIVE)" ./stringify.tcl cvfs.tcl > cvfs.tcl.h Index: kitsh/buildsrc/kitsh-0.0/aclocal.m4 ================================================================== --- kitsh/buildsrc/kitsh-0.0/aclocal.m4 +++ kitsh/buildsrc/kitsh-0.0/aclocal.m4 @@ -558,5 +558,28 @@ LDFLAGS="${OLD_LDFLAGS}" AC_SUBST(LDRUNPATH) ]) + +AC_DEFUN(DC_SET_DIR2C_FLAGS, [ + AC_MSG_CHECKING([if we should obsufcate the CVFS]) + + AC_ARG_WITH(obsfucated-cvfs, AC_HELP_STRING([--with-obsfucated-cvfs], [Obsfucate CVFS filesystem (requires --enable-kit-storage=cvfs)]), [ + obsfucate_cvfs=$withval + ], [ + obsfucate_cvfs='no' + ]) + + case "$obsfucate_cvfs" in + yes) + AC_MSG_RESULT([yes]) + DIR2C_FLAGS='--obsfucate' + ;; + *) + AC_MSG_RESULT([no]) + DIR2C_FLAGS='' + ;; + esac + + AC_SUBST(DIR2C_FLAGS) +]) Index: kitsh/buildsrc/kitsh-0.0/configure.ac ================================================================== --- kitsh/buildsrc/kitsh-0.0/configure.ac +++ kitsh/buildsrc/kitsh-0.0/configure.ac @@ -188,10 +188,13 @@ AC_DEFINE([CVFS_MAKE_LOADABLE], [1], [Specify that the C-VFS should be able to be loaded]) dnl Add appropriate dependencies EXTRA_KIT_DEPS="cvfs.tcl.h" EXTRA_VFS_OBJS="${EXTRA_VFS_OBJS} cvfs_data_tcl.o" + + dnl Set any flags as required + DC_SET_DIR2C_FLAGS ] ) AC_SUBST(EXTRA_KIT_DEPS) AC_SUBST(LDFLAGS_ADD) Index: kitsh/buildsrc/kitsh-0.0/cvfs_data.c ================================================================== --- kitsh/buildsrc/kitsh-0.0/cvfs_data.c +++ kitsh/buildsrc/kitsh-0.0/cvfs_data.c @@ -4,14 +4,16 @@ # include #endif typedef struct cvfs_data *(cmd_getData_t)(const char *, unsigned long); typedef unsigned long (cmd_getChildren_t)(const char *, unsigned long *, unsigned long); +typedef void (cmd_decryptFile_t)(const char *, struct cvfs_data *); /* Your implementation must provide these */ static cmd_getData_t *getCmdData(const char *hashkey); static cmd_getChildren_t *getCmdChildren(const char *hashkey); +static cmd_decryptFile_t *getCmdDecryptFile(const char *hashkey); /* Tcl Commands */ static int getMetadata(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { cmd_getData_t *cmd_getData; cmd_getChildren_t *cmd_getChildren; @@ -107,10 +109,11 @@ } static int getData(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { struct cvfs_data *finfo = NULL; cmd_getData_t *cmd_getData; + cmd_decryptFile_t *cmd_decryptFile; const char *hashkey; const char *file; const char *end_str; Tcl_Obj *ret_str; long start = 0; @@ -160,10 +163,18 @@ if (finfo == NULL) { Tcl_SetResult(interp, "No such file or directory", TCL_STATIC); return(TCL_ERROR); } + + if (finfo->type == CVFS_FILETYPE_OBSFUCATED_FILE || finfo->type == CVFS_FILETYPE_ENCRYPTED_FILE) { + cmd_decryptFile = getCmdDecryptFile(hashkey); + + if (cmd_decryptFile != NULL) { + cmd_decryptFile(file, finfo); + } + } if (finfo->type != CVFS_FILETYPE_FILE) { Tcl_SetResult(interp, "Not a file", TCL_STATIC); return(TCL_ERROR); Index: kitsh/buildsrc/kitsh-0.0/dir2c.tcl ================================================================== --- kitsh/buildsrc/kitsh-0.0/dir2c.tcl +++ kitsh/buildsrc/kitsh-0.0/dir2c.tcl @@ -1,9 +1,16 @@ #! /usr/bin/env tclsh + +set obsfucate 0 +if {[lindex $argv end] == "--obsfucate"} { + set obsfucate 1 + + set argv [lrange $argv 0 end-1] +} if {[llength $argv] != 2} { - puts stderr "Usage: dir2c.tcl " + puts stderr "Usage: dir2c.tcl \[--obsfucate\]" exit 1 } set hashkey [lindex $argv 0] @@ -72,10 +79,105 @@ set ret "\"$ret\"" return $ret } + +# Encrypt the data +proc random_byte {} { + set value [expr {int(256 * rand())}] + + return $value +} + +proc encrypt_key_generate {method} { + switch -- $method { + "rotate_subst" { + set key(method) $method + set key(rotate_length) [random_byte] + + set key_data [list] + while {[llength $key_data] != 256} { + set value [random_byte] + if {[lsearch -exact $key_data $value] != -1} { + continue + } + + lappend key_data $value + } + + foreach value $key_data { + append key(subst) [format %c $value] + } + + return [array get key] + } + } + error "not implemented" +} + +proc encrypt_key_export {key_dict target} { + array set key $key_dict + + switch -- $key(method) { + "rotate_subst" { + switch -- $target { + "c" { + set retval ".type = CVFS_KEYTYPE_ROTATE_SUBST,\n" + append retval ".typedata.rotate_subst.rotate_length = $key(rotate_length),\n" + append retval ".typedata.rotate_subst.subst = [stringify $key(subst)]\n" + + return $retval + } + } + } + } + + error "not implemented" +} + +proc encrypt {data key_dict {decrypt 0}} { + array set key $key_dict + + switch -- $key(method) { + "rotate_subst" { + set retval "" + set datalen [string length $data] + + for {set i 0} {$i < $datalen} {incr i $key(rotate_length)} { + set map [list] + for {set j 0} {$j < 256} {incr j} { + if {$decrypt} { + lappend map [format %c $j] [string index $key(subst) $j] + } else { + lappend map [string index $key(subst) $j] [format %c $j] + } + } + + set end [expr {$i + $key(rotate_length) - 1}] + + set block [string range $data $i $end] + set block [string map $map $block] + + append retval $block + + set key_end [string index $key(subst) 0] + set key(subst) [string range $key(subst) 1 end]$key_end + } + + return $retval + } + "aes" { + package require aes + } + } + error "not implemented" +} + +proc decrypt {data key_dict} { + return [encrypt $data $key_dict 1] +} # This function must be kept in-sync with the generated C function below proc cvfs_hash {path} { set h 0 set g 0 @@ -93,10 +195,15 @@ set h [expr {$h & ((~$g) & 0xffffffff)}] } return $h } + +# If encryption is requested, generate a key +if {$obsfucate} { + set obsfucation_key [encrypt_key_generate "rotate_subst"] +} # Generate list of files to include in output set files [recursive_glob $startdir] # Insert dummy entry cooresponding to C dummy entry @@ -115,33 +222,55 @@ # define HAVE_UNISTD_H 1 # endif # ifndef HAVE_STRING_H # define HAVE_STRING_H 1 # endif +# ifndef HAVE_STDLIB_H +# define HAVE_STDLIB_H 1 +# endif # endif # ifdef HAVE_UNISTD_H # include # endif # ifdef HAVE_STRING_H # include # endif +# ifdef HAVE_STDLIB_H +# include +# endif # ifndef LOADED_CVFS_COMMON # define LOADED_CVFS_COMMON 1 typedef enum { - CVFS_FILETYPE_FILE, - CVFS_FILETYPE_DIR + CVFS_FILETYPE_FILE = 0, + CVFS_FILETYPE_DIR = 1, + CVFS_FILETYPE_OBSFUCATED_FILE = 2, + CVFS_FILETYPE_ENCRYPTED_FILE = 3, } cvfs_filetype_t; struct cvfs_data { const char * name; unsigned long index; unsigned long size; cvfs_filetype_t type; const unsigned char * data; }; + +typedef enum { + CVFS_KEYTYPE_ROTATE_SUBST = 0, +} cvfs_keytype_t; + +struct cvfs_key { + cvfs_keytype_t type; + union { + struct { + int rotate_length; + unsigned char *subst; + } rotate_subst; + } typedata; +}; static unsigned long cvfs_hash(const unsigned char *path) { unsigned long i, h = 0, g = 0; for (i = 0; path[i]; i++) { @@ -153,10 +282,28 @@ h &= ((~g) & 0xffffffffLU); } return(h); } + +#include +static int cvfs_decrypt(unsigned char *out, const unsigned char *in, unsigned long in_out_length, struct cvfs_key *key) { + unsigned long i; + unsigned char in_ch, out_ch; + int ch_idx; + + for (i = 0; i < in_out_length; i++) { + in_ch = in[i]; + + ch_idx = (in_ch + (i / key->typedata.rotate_subst.rotate_length)) % 256; + + out_ch = key->typedata.rotate_subst.subst[ch_idx]; + out[i] = out_ch; + } + + return(0); +} # endif /* !LOADED_CVFS_COMMON */} puts "" puts "static struct cvfs_data ${code_tag}_data\[\] = {" @@ -174,19 +321,24 @@ unset -nocomplain finfo type file stat $file finfo switch -- $finfo(type) { "file" { - set type "CVFS_FILETYPE_FILE" set size $finfo(size) set fd [open $file] fconfigure $fd -translation binary set data [read $fd] close $fd - set data "(unsigned char *) [stringify $data]" + if {$obsfucate} { + set type "CVFS_FILETYPE_OBSFUCATED_FILE" + set data "(unsigned char *) [stringify [encrypt $data $obsfucation_key]]" + } else { + set type "CVFS_FILETYPE_FILE" + set data "(unsigned char *) [stringify $data]" + } } "directory" { set type "CVFS_FILETYPE_DIR" set data "NULL" set size 0 @@ -348,24 +500,51 @@ puts "\t}" puts "" puts "\treturn(num_children);" puts "}" puts "" + +if {$obsfucate} { + puts "static void ${code_tag}_decryptFile(const char *path, struct cvfs_data *finfo) {" + puts "\tstatic struct cvfs_key key = { [string map [list "\n" " "] [encrypt_key_export $obsfucation_key "c"]] };" + puts "\tunsigned char *new_data;" + puts "\tint decrypt_ret;" + puts "" + puts "\tnew_data = malloc(finfo->size);" + puts "\tdecrypt_ret = cvfs_decrypt(new_data, finfo->data, finfo->size, &key);" + puts "\tif (decrypt_ret != 0) {" + puts "\t\tfree(new_data);" + puts "" + puts "\t\treturn;" + puts "\t}" + puts "\tfinfo->data = new_data;" + puts "\tfinfo->type = CVFS_FILETYPE_FILE;" + puts "\treturn;" + puts "}" + puts "" +} puts "# ifdef CVFS_MAKE_LOADABLE" set fd [open "cvfs_data.c"] puts [read $fd] close $fd - puts "static cmd_getData_t *getCmdData(const char *hashkey) {" puts "\treturn(${code_tag}_getData);" puts "}" puts "" puts "static cmd_getChildren_t *getCmdChildren(const char *hashkey) {" puts "\treturn(${code_tag}_getChildren);" +puts "}" +puts "" +puts "static cmd_decryptFile_t *getCmdDecryptFile(const char *hashkey) {" +if {$obsfucate} { + puts "\treturn(${code_tag}_decryptFile);" +} else { + puts "\treturn(NULL);" +} puts "}" puts "" puts "int Cvfs_data_${hashkey}_Init(Tcl_Interp *interp) {" puts "\tTcl_Command tclCreatComm_ret;"