panthema / 2009 / cryptote / cryptote-0.5.390 / libenctain / enctain.h (Download File)
// $Id: enctain.h 384 2009-08-03 20:29:06Z tb $

/*
 * CryptoTE LibEnctain v0.5.390
 * Copyright (C) 2008-2009 Timo Bingmann
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#ifndef ENCTAIN_H
#define ENCTAIN_H

#include <string>
#include <exception>
#include <stdint.h>

/// Holds all public declarations and classes of Enctain.
namespace Enctain {

/**
 * Enumeration of different error return codes. They can be resolved into
 * English strings using GetErrorString().
 */
enum error_type
{
    /// No Error occured.
    ETE_SUCCESS = 0,

    /// Exception with unknown error code, see plain text message.
    ETE_TEXT = 1,
    
    ETE_OUTPUT_ERROR = 1000,
    ETE_INPUT_ERROR,

    ETE_SAVE_NO_KEYSLOTS,

    ETE_LOAD_HEADER1,
    ETE_LOAD_HEADER1_SIGNATURE,
    ETE_LOAD_HEADER1_VERSION,
    ETE_LOAD_HEADER1_METADATA,
    ETE_LOAD_HEADER1_METADATA_PARSE,

    ETE_LOAD_HEADER2,
    ETE_LOAD_HEADER2_NO_KEYSLOTS,
    ETE_LOAD_HEADER2_KEYSLOTS,
    ETE_LOAD_HEADER2_INVALID_KEY,

    ETE_LOAD_HEADER3,
    ETE_LOAD_HEADER3_ENCRYPTION,
    ETE_LOAD_HEADER3_METADATA,
    ETE_LOAD_HEADER3_METADATA_CHECKSUM,
    ETE_LOAD_HEADER3_METADATA_PARSE,

    ETE_LOAD_SUBFILE,

    ETE_LOAD_CHECKSUM,

    ETE_KEYSLOT_INVALID_INDEX,

    ETE_SUBFILE_INVALID_INDEX,
    ETE_SUBFILE_CHECKSUM,
    ETE_SUBFILE_INVALID_COMPRESSION,
    ETE_SUBFILE_INVALID_ENCRYPTION,

    ETE_Z_UNKNOWN = 2000,
    ETE_Z_OK,
    ETE_Z_NEED_DICT,
    ETE_Z_STREAM_END,
    ETE_Z_ERRNO,
    ETE_Z_STREAM_ERROR,
    ETE_Z_DATA_ERROR,
    ETE_Z_MEM_ERROR,
    ETE_Z_BUF_ERROR,
    ETE_Z_VERSION_ERROR,
};

/**
 * Enumeration of different supported encryption algorithms which can be
 * applied to individual files.
 */
enum encryption_type
{
    ENCRYPTION_NONE = 0,
    ENCRYPTION_SERPENT256 = 1
};

/**
 * Enumeration of different supported compression algorithms which can be
 * applied to individual files.
 */
enum compression_type
{
    COMPRESSION_NONE = 0,
    COMPRESSION_ZLIB = 1,
    COMPRESSION_BZIP2 = 2
};

/**
 * Enumeration of progress indicator (text) descriptions. Used instead of the
 * text string for localization.
 */
enum progress_indicator_type {
    PI_GENERIC = 0,
    PI_SAVE_CONTAINER,
    PI_LOAD_CONTAINER,
    PI_REENCRYPT,
    PI_SAVE_SUBFILE,
    PI_LOAD_SUBFILE
};

/**
 * Top-Level Exception Class for all exceptions thrown from Enctain. The
 * additional error_type code can be used for better translation of error
 * strings.
 */
class Exception : public std::exception
{
protected:
    /// Error code which can be used for translation.
    error_type		m_ecode;

    /// Error message in English plain text.
    std::string		m_msg;

public:
    /// Initializing constructor.
    Exception(error_type ec, const std::string& m);

    /// Required for virtual functions.
    virtual ~Exception() throw()
    { }

    /// Return the English error message
    virtual const char* what() const throw()
    { return m_msg.c_str(); }

    /// Return Enctain error message string
    virtual const std::string& str() const throw()
    { return m_msg; }

    /// Return Enctain error code
    virtual error_type code() const throw()
    { return m_ecode; }
};

/**
 * Second-Level Exception Class for all exceptions which indicate a transient
 * run-time like entering an invalid decryption key.
 */
class RuntimeError : public Exception
{
public:
    /// Initializing constructor.
    RuntimeError(error_type ec, const std::string& m);

    /// Initializing constructor with automatic message text.
    RuntimeError(error_type ec);
};

/**
 * Second-Level Exception Class for all exceptions which indicate a permanent
 * program error, like specifying wrong parameters or calling functions in an
 * invalid order.
 */
class ProgramError : public Exception
{
public:
    /// Initializing constructor.
    ProgramError(error_type ec, const std::string& m);

    /// Initializing constructor with automatic message text.
    ProgramError(error_type ec);
};

/**
 * Second-Level Exception Class for all exceptions which indicate an internal
 * error which should never occur.
 */
class InternalError : public Exception
{
public:
    /// Initializing constructor.
    InternalError(error_type ec, const std::string& m);

    /// Initializing constructor with automatic message text.
    InternalError(error_type ec);
};

/**
 * Library Initialization and Shutdown Object. Create it in the main() function
 * or object. Loads and initializes the ciphers (in the Botan library).
 */
class LibraryInitializer
{
public:
    static void initialize(const std::string& args = "");
    static void deinitialize();

    LibraryInitializer(const std::string& args = "") { initialize(args); }
    ~LibraryInitializer() { deinitialize(); }
};

/**
 * Random number generator interface based on Botan
 */

class RNG
{
public:
    static void 		randomize(unsigned char* out, unsigned int len);

    static unsigned char	random_byte();
    static unsigned int		random_uint();
};

/**
 * Abstract interface class which receives data during container saving or
 * subfile decompression/decryption operations. It is a generic data receiver.
 */
class DataOutput
{
public:

    /// Required.
    virtual ~DataOutput() {};

    /// Pure virtual function which gets data block-wise. If it returns true
    /// the output process continues, on false it will abort.
    virtual bool	Output(const void* data, size_t datalen) = 0;
};

/**
 * Abstract interface class which requests data during container loading. It is
 * a generic stream interface and only have one function.
 */
class DataInput
{
public:

    /// Required.
    virtual ~DataInput() {};

    /// Pure virtual function which requests data block-wise. The function must
    /// return maxlen byte at once, if they are available (this is different
    /// from read()'s semantics). Must return the number of bytes retrieved.
    virtual unsigned int Input(void* data, size_t maxlen) = 0;
};

/**
 * Abstract interface class which can be used to accept progress information
 * during longer operations.
 */

class ProgressIndicator
{
public:

    /// Required.
    virtual ~ProgressIndicator() {};

    /// Pure virtual function called when the progress indicator should
    /// start. The current value and range is given in this call. This call may
    /// be repeated to adjust the text or range during a running process.
    virtual void	ProgressStart(const char* pitext,
				      progress_indicator_type pitype,
				      size_t value, size_t limit) = 0;

    /// Pure virtual function called when the progress indicator should be
    /// updated.
    virtual void	ProgressUpdate(size_t value) = 0;

    /// Pure virtual function called when the progress indicator should be
    /// hidden.
    virtual void	ProgressStop() = 0;
};

/// Hold internal declarations implementing the encrypted container class.
namespace internal {
// Forward declaration for internal implementation class.
class ContainerImpl;
}

/**
 * Class holding all data loaded from an encrypted container. The classes uses
 * a reference-counted pointer implementation. This means you can safely assign
 * and copy objects, where a copy does not create a new object.
 */
class Container
{
protected:

    class internal::ContainerImpl*	m_pimpl;

public:
    // *** Constructors, Destructor, Assignment ***

    /// Default construction: creates a new empty container object and holds a
    /// reference to it.
    Container();

    /// Decreases the reference counter and eventually deletes the container
    /// object.
    ~Container();

    /// Copy-Constructor: create another reference to the same container
    /// object.
    Container(const Container &cnt);

    /// Assignment-Operator: copy reference to the same container object.
    Container& operator=(const Container &cnt);

    // *** Settings and Error Strings ***

    /// Change the signature used by Enctain which defaults to "CryptoTE". The
    /// signature is always 8 characters long and will be truncated or padded
    /// with zeros. The signature is shared between all instances.
    static void		SetSignature(const char* sign);

    /// Return a one-line English description of the error code.
    static const char*	GetErrorString(error_type e);

    // *** Load/Save/Clear Operations ***

    /// Save the current container by outputting all data to the data sink.
    void		Save(DataOutput& dataout);

    /// Load a new container from an input stream and parse the subfile index.
    void		Load(DataInput& datain, const std::string& userkey);

    /// Reset all structures in the container
    void		Clear();


    // *** Container Info Operations ***

    /// Return whether the subfiles or properties were changed since the last load/save.
    bool		GetModified() const;

    /// Return number of bytes written to data sink during last Save()
    /// operation.
    size_t		GetLastWritten() const;

    /// Set the Progress Indicator object which receives progress notifications
    void		SetProgressIndicator(ProgressIndicator* pi);


    // *** Container User KeySlots Operations ***

    /// Return number of user key slots used.
    unsigned int	CountKeySlots() const;
    
    /// Add a new user key string. The string will be hashed and used to store
    /// a copy of the master key. SubFiles do not need to be
    /// reencrypted. Returns number of new key slot.
    unsigned int	AddKeySlot(const std::string& key);

    /// Replace a key slot with a new key string. Requires that the container
    /// was opened using one of the previously existing user key slots.
    void		ChangeKeySlot(unsigned int slot, const std::string& newkey);

    /// Remove a user key slot. When all user key slots are removed and a new
    /// key is added, a new master key is also generated.
    void		DeleteKeySlot(unsigned int slot);

    /// Return the number of the key slot which matched while loading the
    /// file. Returns -1 if it was deleted.
    int			GetUsedKeySlot() const;


    // *** Container Unencrypted Global Properties ***

    /// Set (overwrite) an unencrypted global property.
    void		SetGlobalUnencryptedProperty(const std::string& key, const std::string& value);
    
    /// Get an unencrypted  global property by key.
    const std::string&	GetGlobalUnencryptedProperty(const std::string& key) const;

    /// Delete an unencrypted  global property key.
    bool		DeleteGlobalUnencryptedProperty(const std::string& key);
    
    /// Get an unencrypted global property (key and value) by index. Returns
    /// false if the index is beyond the last property
    bool		GetGlobalUnencryptedPropertyIndex(unsigned int propindex,
							  std::string& key, std::string& value) const;


    // *** Container Encrypted Global Properties ***

    /// Set (overwrite) an encrypted global property.
    void		SetGlobalEncryptedProperty(const std::string& key, const std::string& value);
    
    /// Get an encrypted global property by key.
    const std::string&	GetGlobalEncryptedProperty(const std::string& key) const;

    /// Delete an encrypted global property key.
    bool		DeleteGlobalEncryptedProperty(const std::string& key);
    
    /// Get an encrypted global property (key and value) by index. Returns
    /// false if the index is beyond the last property
    bool		GetGlobalEncryptedPropertyIndex(unsigned int propindex,
							std::string& key, std::string& value) const;


    // *** Container SubFiles ***


    // * Subfile array management *

    /// Return number of subfiles in the container.
    unsigned int 	CountSubFile() const;

    /// Append an empty uninitialized subfile at the end of the list. Returns
    /// the new subfile's index.
    unsigned int 	AppendSubFile();

    /// Insert an empty uninitialized subfile at the given position in the
    /// list. Returns the new subfile's index.
    unsigned int 	InsertSubFile(unsigned int subfileindex);

    /// Delete a subfile in the array. Returns true if it existed.
    bool		DeleteSubFile(unsigned int subfileindex);


    // * Subfile user-defined properties *

    /// Set (overwrite) a subfile's property.
    void		SetSubFileProperty(unsigned int subfileindex, const std::string& key, const std::string& value);

    /// Get a subfile's property by key. Returns an empty string if it is not set.
    const std::string&	GetSubFileProperty(unsigned int subfileindex, const std::string& key) const;

    /// Delete a subfile's property key.
    bool		DeleteSubFileProperty(unsigned int subfileindex, const std::string& key);
    
    /// Get a subfile's property (key and value) by index. Returns false if the
    /// index is beyond the last property
    bool		GetSubFilePropertyIndex(unsigned int subfileindex, unsigned int propindex,
						std::string& key, std::string& value) const;


    // * Get operations of subfile header fields *
    
    /// Return number of bytes the subfile requires on disk, after compression
    /// and encryption.
    uint32_t		GetSubFileStorageSize(unsigned int subfileindex) const;

    /// Return number of bytes the subfile requires when decrypted and
    /// decompressed.
    uint32_t		GetSubFileSize(unsigned int subfileindex) const;

    /// Return encryption cipher of the subfile.
    encryption_type	GetSubFileEncryption(unsigned int subfileindex) const;

    /// Return compression method of the subfile.
    compression_type	GetSubFileCompression(unsigned int subfileindex) const;


    // * Set operations of subfile header fields *

    /// Set data encryption flag of a subfile. This can be an expensive
    /// operation as the memory buffer may need to be decrypted/encrypted.
    void		SetSubFileEncryption(unsigned int subfileindex,
					     encryption_type c);

    /// Set data compression flag of a subfile. This can be an expensive
    /// operation as the memory buffer may need to be decompressed/compressed.
    void		SetSubFileCompression(unsigned int subfileindex,
					      compression_type c);

    /// Set both data compression and encryption flags of a subfile. This can
    /// be an expensive operation as the memory buffer may need to be
    /// decompressed/compressed and reencrypted.
    void		SetSubFileCompressionEncryption(unsigned int subfileindex,
							compression_type comp,
							encryption_type enc);


    // * Subfile data operations *

    /// Return the data of a subfile: decrypt and uncompress it. The data is
    /// sent block-wise to the DataOutput object.
    void		GetSubFileData(unsigned int subfileindex, class DataOutput& dataout) const;

    /// Return the data of a subfile: decrypt and uncompress it. Return
    /// complete data in a memory string.
    void		GetSubFileData(unsigned int subfileindex, std::string& data) const;

    /// Set/change the data of a subfile, it will be compressed and encrypted
    /// but not written to disk, yet.
    void 		SetSubFileData(unsigned int subfileindex, const void* data, unsigned int datalen);
};

} // namespace Enctain

#endif // ENCTAIN_H