diff --git a/panda/src/express/encrypt_string.cxx b/panda/src/express/encrypt_string.cxx index a15107cb7c..7b5fa19224 100644 --- a/panda/src/express/encrypt_string.cxx +++ b/panda/src/express/encrypt_string.cxx @@ -20,7 +20,8 @@ // Function: encrypt_string // Access: Published // Description: Encrypts the indicated source string using the given -// password. Returns the encrypted string. +// password, and the algorithm specified by +// encryption-algorithm. Returns the encrypted string. //////////////////////////////////////////////////////////////////// string encrypt_string(const string &source, const string &password) { diff --git a/panda/src/express/multifile.I b/panda/src/express/multifile.I index fb0d1cd504..287a7e0e2f 100644 --- a/panda/src/express/multifile.I +++ b/panda/src/express/multifile.I @@ -145,9 +145,8 @@ get_scale_factor() const { // When true, subfiles will be encrypted with the // password specified by set_encryption_password(). It // is possible to apply a different password to -// different files, but you must call flush() or -// repack() before changing these properties, and the -// resulting file can't be mounted via VFS. +// different files, but the resulting file can't be +// mounted via VFS. //////////////////////////////////////////////////////////////////// INLINE void Multifile:: set_encryption_flag(bool flag) { @@ -181,10 +180,20 @@ get_encryption_flag() const { // subfiles subsequently added to the multifile, if the // encryption flag is also set true (see // set_encryption_flag()). +// +// It is possible to apply a different password to +// different files, but the resulting file can't be +// mounted via VFS. Changing this value may cause an +// implicit call to flush(). //////////////////////////////////////////////////////////////////// INLINE void Multifile:: -set_encryption_password(const string &password) { - _encryption_password = password; +set_encryption_password(const string &encryption_password) { + if (_encryption_password != encryption_password) { + if (!_new_subfiles.empty()) { + flush(); + } + _encryption_password = encryption_password; + } } //////////////////////////////////////////////////////////////////// @@ -199,6 +208,126 @@ get_encryption_password() const { return _encryption_password; } +//////////////////////////////////////////////////////////////////// +// Function: Multifile::set_encryption_algorithm +// Access: Public +// Description: Specifies the encryption algorithm that should be +// used for future calls to add_subfile(). The default +// is whatever is specified by the encryption-algorithm +// config variable. The complete set of available +// algorithms is defined by the current version of +// OpenSSL. +// +// If an invalid algorithm is specified, there is no +// immediate error return code, but flush() will fail +// and the file will be invalid. +// +// It is possible to apply a different encryption +// algorithm to different files, and unlike the +// password, this does not interfere with mounting the +// multifile via VFS. Changing this value may cause an +// implicit call to flush(). +//////////////////////////////////////////////////////////////////// +INLINE void Multifile:: +set_encryption_algorithm(const string &encryption_algorithm) { + if (_encryption_algorithm != encryption_algorithm) { + if (!_new_subfiles.empty()) { + flush(); + } + _encryption_algorithm = encryption_algorithm; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: Multifile::get_encryption_algorithm +// Access: Public +// Description: Returns the encryption algorithm that was specified +// by set_encryption_algorithm(). +//////////////////////////////////////////////////////////////////// +INLINE const string &Multifile:: +get_encryption_algorithm() const { + return _encryption_algorithm; +} + +//////////////////////////////////////////////////////////////////// +// Function: Multifile::set_encryption_key_length +// Access: Public +// Description: Specifies the length of the key, in bits, that should +// be used to encrypt the stream in future calls to +// add_subfile(). The default is whatever is specified +// by the encryption-key-length config variable. +// +// If an invalid key_length for the chosen algorithm is +// specified, there is no immediate error return code, +// but flush() will fail and the file will be invalid. +// +// It is possible to apply a different key length to +// different files, and unlike the password, this does +// not interfere with mounting the multifile via VFS. +// Changing this value may cause an implicit call to +// flush(). +//////////////////////////////////////////////////////////////////// +INLINE void Multifile:: +set_encryption_key_length(int encryption_key_length) { + if (_encryption_key_length != encryption_key_length) { + if (!_new_subfiles.empty()) { + flush(); + } + _encryption_key_length = encryption_key_length; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: Multifile::get_encryption_key_length +// Access: Public +// Description: Returns the encryption key length, in bits, that was +// specified by set_encryption_key_length(). +//////////////////////////////////////////////////////////////////// +INLINE int Multifile:: +get_encryption_key_length() const { + return _encryption_key_length; +} + +//////////////////////////////////////////////////////////////////// +// Function: Multifile::set_encryption_iteration_count +// Access: Public +// Description: Specifies the number of times to repeatedly hash the +// key before writing it to the stream in future calls +// to add_subfile(). Its purpose is to make it +// computationally more expensive for an attacker to +// search the key space exhaustively. This should be a +// multiple of 1,000 and should not exceed about 65 +// million; the value 0 indicates just one application +// of the hashing algorithm. +// +// The default is whatever is specified by the +// multifile-encryption-iteration-count config variable. +// +// It is possible to apply a different iteration count +// to different files, and unlike the password, this +// does not interfere with mounting the multifile via +// VFS. Changing this value causes an implicit call to +// flush(). +//////////////////////////////////////////////////////////////////// +INLINE void Multifile:: +set_encryption_iteration_count(int encryption_iteration_count) { + if (_encryption_iteration_count != encryption_iteration_count) { + flush(); + _encryption_iteration_count = encryption_iteration_count; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: Multifile::get_encryption_iteration_count +// Access: Public +// Description: Returns the value that was specified by +// set_encryption_iteration_count(). +//////////////////////////////////////////////////////////////////// +INLINE int Multifile:: +get_encryption_iteration_count() const { + return _encryption_iteration_count; +} + //////////////////////////////////////////////////////////////////// // Function: Multifile::read_subfile // Access: Published diff --git a/panda/src/express/multifile.cxx b/panda/src/express/multifile.cxx index a21361c7f0..4f601608c3 100644 --- a/panda/src/express/multifile.cxx +++ b/panda/src/express/multifile.cxx @@ -115,8 +115,14 @@ Multifile() : _scale_factor = 1; _new_scale_factor = 1; _encryption_flag = false; + _encryption_iteration_count = multifile_encryption_iteration_count; _file_major_ver = 0; _file_minor_ver = 0; + + // Get these values from the config file via an EncryptStreamBuf. + EncryptStreamBuf tbuf; + _encryption_algorithm = tbuf.get_algorithm(); + _encryption_key_length = tbuf.get_key_length(); } //////////////////////////////////////////////////////////////////// @@ -1853,7 +1859,7 @@ write_data(ostream &write, istream *read, streampos fpos, if ((_flags & SF_encrypted) != 0) { // Write it encrypted. OEncryptStream *encrypt = new OEncryptStream; - encrypt->set_iteration_count(multifile_encryption_iteration_count); + encrypt->set_iteration_count(multifile->_encryption_iteration_count); encrypt->open(putter, delete_putter, multifile->_encryption_password); putter = encrypt; diff --git a/panda/src/express/multifile.h b/panda/src/express/multifile.h index d28cc084a4..89824a9d55 100644 --- a/panda/src/express/multifile.h +++ b/panda/src/express/multifile.h @@ -65,9 +65,16 @@ PUBLISHED: INLINE void set_encryption_flag(bool flag); INLINE bool get_encryption_flag() const; - INLINE void set_encryption_password(const string &password); + INLINE void set_encryption_password(const string &encryption_password); INLINE const string &get_encryption_password() const; + INLINE void set_encryption_algorithm(const string &encryption_algorithm); + INLINE const string &get_encryption_algorithm() const; + INLINE void set_encryption_key_length(int encryption_key_length); + INLINE int get_encryption_key_length() const; + INLINE void set_encryption_iteration_count(int encryption_iteration_count); + INLINE int get_encryption_iteration_count() const; + string add_subfile(const string &subfile_name, const Filename &filename, int compression_level); string add_subfile(const string &subfile_name, istream *subfile_data, @@ -180,6 +187,9 @@ private: bool _encryption_flag; string _encryption_password; + string _encryption_algorithm; + int _encryption_key_length; + int _encryption_iteration_count; pifstream _read_file; IStreamWrapper _read_filew;