Encryption Plugin for Firebird 3.0

IBPhoenix have developed an encyption plugin for Firebird 3.0 that is compatible with AES128 or AES256, AES128 is considered to be a "business-grade security", whilst AES256 is "military". Note that AES256 has a performance cost v's AES128.

The plugin is available for Windows (32/64bit), Linux (32/64bit) and MacOSX (32/64bit) currently. The plugin is currently in use at a number of sites and shows no problems with performance or reliability. However if you would like to test it, please contact us directly and an appropriate download will be made available.

Note

To use this plugin you need to have CPU that supports the SSE2 instruction set. The AES instruction set is desirable, but optional. For Linux also make sure that the libtommath libraries are installed. Also GLIBC_2.14+ is required.

To install

Unzip the encryption libraries and conf files into $(root_dir)/plugins

create a keyfile somewhere e.g:

C:\MyKey.txt or on Posix /opt/firebird/MyKey.txt

Now insert your key into it e.g. TestKey

Then in the file plugins KeyFile.conf you can set a server wide key using the parameter:

KeyFile = C:\MyKey.txt or /opt/firebird/MyKey.txt.

Alternatively entries for database dedicated key files can be specified for each database individually using the format <key name> = <key file>. For example suppose you have two databases testa.fdb and testb.fdb that you want to encrypt and decrypt with a separate key. Make a name up for each key and point each key name to the file holding the relevant key:

Key4TestA = C:\Key4TestA.jpg
Key4TestB = C:\Key4TestB.txt

If dedicated key names are configured the name of the key must be supplied in the optional KEY parameter of the encrypt and decrypt statements.

Another alternative is to configure the keyfile so the plugin will send a request to the user application for the file path (Keyfile = ?).

You also need to set the following in Keyfile conf when using a known key file, set DisableCallback to "true". (Make sure you remove the # signs when setting conf parameters):

DisableCallback = true

Perhaps the securest and simplest way to manage this is to put the key file onto a secure USB stick inserted into database server)

In databases.conf (or firebird.conf) set the following parameter for the appropriate database:

KeyHolderPlugin = KeyFile

Restart the Firebird Server.

Then:

isql> connect 'C:\test\firebird\test.fdb' user 'SYSDBA' password 'whatever';
isql> alter database encrypt with AES128;
isql> commit;

or on Posix:

isql>connect 'localhost:/opt/firebird/test.fdb' user 'SYSDBA' password 'whatever';
isql>alter database encrypt with AES128;
isql>commit;

If using individual keys:

isql> connect 'C:\test\firebird\test.fdb' user 'SYSDBA' password 'whatever';
isql> alter database encrypt with AES128 key TestKey;
isql> commit;

On Posix:

isql>connect 'localhost:/opt/firebird/test.fdb' user 'SYSDBA' password 'whatever';
isql>alter database encrypt with AES128 key TestKey;
isql>commit;

Note

Use AES256 if you are using the AE256 key.

If the encryption library fails to load then this error will be seen:

Statement failed, SQLSTATE = HY024
unsuccessful metadata update
-ALTER DATABASE failed
-Crypt plugin AES256/128 failed to load

There are three ways to verify encryption.

Via isql show db:

SHOW DB;
Database: test
Owner: SYSDBA
[...]
Database encrypted, crypt thread not complete

By querying the monitoring tables:

select MON$CRYPT_PAGE * 100 / MON$PAGES as ENCRYPTED_PAGES from mon$database;

ENCRYPTED_PAGES
=====================
0

If ZERO is returned then encryption has completed. Otherwise the value represents the percentage of total pages encrypted.

Or by using gstat (you can use shell to run gstat from isql), With the default -h option the Attributes field and the Key Hash fields will indicate encryption.

Or you can use:

/opt/firebird3/bin/gstat -e test.fdb

Database "/data_store/ssd/ods120/test.fdb"
Database header page information:
        Flags                   0
        Generation              2990307
        System Change Number    0
        Page size               16384
        ODS version             12.0
     [...]
        Creation date           May 24, 2016 12:18:12
        Attributes              force write, encrypted, plugin AES128

    Variable header data:
       Key hash:       X2ZorqRShODg1mhSg5yQhpFxtjk=
       Sweep interval:         0
       *END*
     Data pages: total 159004, encrypted 159004, non-crypted 0
     Index pages: total 16409, encrypted 16409, non-crypted 0
     Blob pages: total 0, encrypted 0, non-crypted 0

Should show that the database has been encrypted

To decrypt use:

isql> alter database decrypt;

or:

isql> alter database decrypt key TestKey;

Note

You can also use the fb_info_crypt_state item for the isc_database_info() API call to check the encryption status of the database too.

Application Key

Rather than providing the decryption key in a file, it is possible to provide the decryption key directly within your application using the relevant Firebird API calls. To do this, change the declaration of KeyHolderPlugin in databases.conf (or Firebird.conf) from KeyFile to Callback. This will allow you to provide the crypt key directly from the application.

To check if the configuration is correct, you can look at the data, received by the application callback in the first two parameters. The data will be "AES128.<something>" for old versions of plugin and "AES256/128" for version 1.2+ If you can see that, then the configuration is correct and the application can send the crypt key. If you still see "KeyFile.<something>", the configured key holder is still KeyFile and that is a file name, not the key itself.

Currently we have examples for Delphi, C++ and .NET.

This code works using Delphi XE6 or XE7, However there does seem to be a problem with earlier versions of Delphi e.g. Delphi XE3.

Note

The Firebird referred to in the "uses" section is the Firebird.pas that can be found in the include Firebird directory of the Firebird installation.

Another Delphi example.

C/C++ Code C example of how to use the encryption plugin and pass the key from a client application.

Or alternatively you can use the following new function in ibase.h:

/*******************************************/
/* Set callback for database crypt plugins */
/*******************************************/
ISC_STATUS ISC_EXPORT fb_database_crypt_callback(ISC_STATUS*,
    FB_NAMESPACE_USE(Firebird, ICryptKeyCallback*));
#ifdef __cplusplus
}    /* extern "C" */
#endif

Note

The second parameter is declared as void*, because of the use of namespace Firebird (where the interfaces live) breaks the old-style ibase.h. This can cause problems when passing some implementations of ICallback due to incorrect type casts.

To avoid it one should first cast the pointer to the implementation of ICallback* like this:

CryptKey key;
ICryptKeyCallback* cb = &key;
fb_database_crypt_callback(status, cb);

Doing the following directly:

CryptKey key;
fb_database_crypt_callback(status, &key);

may cause a segmentation fault.

Example of a Visual C++ Class that uses fb_database_crypt_callback.

.NET needs the ADO.NET provider 5.11.0.0, and then you can use this code.

Note

In the configuration files Callback.conf and KeyFile.conf it is now possible to use the parameter ShareKey, where a key received from a client application will be shared between connections in SuperServer mode. When set to false (default is true) it will then require a key for each database attachment:

ShareKey=false

Backup and Restore

The crypt plugin also supports the backup and restore of an encrypted Firebird database using either the Firebird Service Manager or Gbak

Examples:

a typical backup command using gbak:

gbak -b -user sysdba -pas masterkey -keyholder KeyFile -crypt AES128 -verify empcrypt /path/to/backupdir/empcrypt.fbk

a typical restore command:

gbak -v -c -user sysdba -pas masterkey -keyholder KeyFile -crypt AES128 /path/to/backupdir/empcrypt.fbk /path/to/databases/empcrypt_new.fdb

fbsvcmgr typical commands would be like this:

fbsvcmgr localhost:service_mgr key_holder KeyFile action_backup \
         dbname empcrypt128 bkp_file /srv/data/backup/ods120/empcrypt128.fbkz \
         bkp_keyholder KeyFile bkp_keyname ServerKeyAES128 bkp_crypt AES128 bkp_zip


fbsvcmgr localhost:service_mgr key_holder KeyFile action_restore \
         dbname /srv/data/ods120/empcrypt128-restored.fdb \
         res_keyholder KeyFile bkp_file /srv/data/backup/ods120/empcrypt128.fbkz

Licensing

On purchase of an appropriate server license a download of the software will be made available. A server license costs $250.00 and will allow you to encrypt multiple databases on that server. Should you wish to use the encryption plugin with an embedded application or for deployment to multiple servers you can purchase an unlimited use license for $2499.00.

buy