/*************************************************************************/ /* file_access_encrypted.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ /* http://www.godotengine.org */ /*************************************************************************/ /* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining */ /* a copy of this software and associated documentation files (the */ /* "Software"), to deal in the Software without restriction, including */ /* without limitation the rights to use, copy, modify, merge, publish, */ /* distribute, sublicense, and/or sell copies of the Software, and to */ /* permit persons to whom the Software is furnished to do so, subject to */ /* the following conditions: */ /* */ /* The above copyright notice and this permission notice shall be */ /* included in all copies or substantial portions of the Software. */ /* */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ #include "file_access_encrypted.h" #include "aes256.h" #include "md5.h" #include "os/copymem.h" #include "print_string.h" #define COMP_MAGIC 0x43454447 #include "core/variant.h" #include Error FileAccessEncrypted::open_and_parse(FileAccess *p_base,const Vector& p_key,Mode p_mode) { //print_line("open and parse!"); ERR_FAIL_COND_V(file!=NULL,ERR_ALREADY_IN_USE); ERR_FAIL_COND_V(p_key.size()!=32,ERR_INVALID_PARAMETER); pos=0; eofed=false; if (p_mode==MODE_WRITE_AES256) { data.clear(); writing=true; file=p_base; mode=p_mode; key=p_key; } else if (p_mode==MODE_READ) { writing=false; key=p_key; uint32_t magic = p_base->get_32(); print_line("MAGIC: "+itos(magic)); ERR_FAIL_COND_V(magic!=COMP_MAGIC,ERR_FILE_UNRECOGNIZED); mode=Mode(p_base->get_32()); ERR_FAIL_INDEX_V(mode,MODE_MAX,ERR_FILE_CORRUPT); ERR_FAIL_COND_V(mode==0,ERR_FILE_CORRUPT); print_line("MODE: "+itos(mode)); unsigned char md5d[16]; p_base->get_buffer(md5d,16); length=p_base->get_64(); base=p_base->get_pos(); ERR_FAIL_COND_V(p_base->get_len() < base+length, ERR_FILE_CORRUPT ); int ds = length; if (ds % 16) { ds+=16-(ds % 16); } data.resize(ds); int blen = p_base->get_buffer(data.ptr(),ds); ERR_FAIL_COND_V(blen!=ds,ERR_FILE_CORRUPT); aes256_context ctx; aes256_init(&ctx,key.ptr()); for(size_t i=0;i key; key.resize(32); for(int i=0;i<32;i++) { key[i]=cs[i]; } return open_and_parse(p_base,key,p_mode); } Error FileAccessEncrypted::_open(const String& p_path, int p_mode_flags) { return OK; } void FileAccessEncrypted::close() { if (!file) return; if (writing) { Vector compressed; size_t len = data.size(); if (len % 16) { len+=16-(len % 16); } MD5_CTX md5; MD5Init(&md5); MD5Update(&md5,data.ptr(),data.size()); MD5Final(&md5); compressed.resize(len); zeromem( compressed.ptr(), len ); for(int i=0;istore_32(COMP_MAGIC); file->store_32(mode); file->store_buffer(md5.digest,16); file->store_64(data.size()); file->store_buffer(compressed.ptr(),compressed.size()); file->close(); memdelete(file); file=NULL; data.clear(); } else { file->close(); memdelete(file); data.clear(); file=NULL; } } bool FileAccessEncrypted::is_open() const{ return file!=NULL; } void FileAccessEncrypted::seek(size_t p_position){ if (p_position > (size_t)data.size()) p_position=data.size(); pos=p_position; eofed=false; } void FileAccessEncrypted::seek_end(int64_t p_position){ seek( data.size() + p_position ); } size_t FileAccessEncrypted::get_pos() const{ return pos; } size_t FileAccessEncrypted::get_len() const{ return data.size(); } bool FileAccessEncrypted::eof_reached() const{ return eofed; } uint8_t FileAccessEncrypted::get_8() const{ ERR_FAIL_COND_V(writing,0); if (pos>=data.size()) { eofed=true; return 0; } uint8_t b = data[pos]; pos++; return b; } int FileAccessEncrypted::get_buffer(uint8_t *p_dst, int p_length) const{ ERR_FAIL_COND_V(writing,0); int to_copy=MIN(p_length,data.size()-pos); for(int i=0;i