SQLCipher for Android FIPS

Introduction

This document describes the steps that differ from the standard SQLCipher for Android integration instructions when using the FIPS package. Follow the base documentation for project setup, license code application, and general API usage, and apply the changes below.

SQLCipher for Android FIPS uses an embedded FIPS validated cryptographic module per FIPS Implementation Guidance.

Library installation

Extract the sqlcipher-android-fips-4.16.0.zip package and copy the sqlcipher-android-fips-4.16.0.aar file into the app/libs directory of your application.

Update build.gradle

In the application module build.gradle, reference the FIPS AAR instead of the standard AAR:

dependencies {
  implementation fileTree(dir: 'libs', include: ['sqlcipher-android-fips-4.16.0.aar'])
  implementation 'androidx.sqlite:sqlite:2.6.2'
}

Next, add the keepDebugSymbols and useLegacyPackaging options inside the android block. These are required for the FIPS module to operate correctly:

android {
  packagingOptions {
    jniLibs {
      keepDebugSymbols += ['*/*/libfips.so', '*/*/libfipscnf.so']
      useLegacyPackaging = true
    }
  }
}
  1. keepDebugSymbols ensures the FIPS module libraries are not stripped during packaging, which would modify the files and invalidate the Power On Self Test signatures.
  2. useLegacyPackaging ensures .so files are extracted on install so that Power On Self Test signature verification runs on the libraries.

Apply License Code

License code application is identical to the non-FIPS integration; see the License Code Integration section of the base documentation. As a reminder, the license code must be applied via SQLiteDatabaseHook.preKey before any other database operation:

SQLiteDatabaseHook hook = new SQLiteDatabaseHook() {
  public void preKey(SQLiteConnection connection) {
    connection.executeRaw("PRAGMA cipher_license = 'OmNpZD...';", null, null);
  }
  public void postKey(SQLiteConnection connection) {}
};

SQLiteDatabase database =
  SQLiteDatabase.openOrCreateDatabase(databasePath.getAbsolutePath(), password, null, null, hook);

If the license code is not properly applied your application will receive not authorized or SQLITE_AUTH (23) errors.

Check FIPS Mode

Applications using a FIPS 140 validated cryptographic module should, as a matter of practice, check that the library is operating in FIPS mode early in the application lifecycle. This ensures that the FIPS-enabled library has been integrated into the application, loaded properly at runtime, that all Power On Self Tests have completed successfully, and that the library is running in FIPS mode.

Cursor cursor = database.query("PRAGMA cipher_fips_status;", new String[]{});

String value = "";
if(cursor != null){
  cursor.moveToFirst();
  value = cursor.getString(0);
  cursor.close();
}
if("1".equals(value)) {
  // operating in FIPS mode
} else {
  // not operating in FIPS mode - throw error
}

Reference Application

A complete reference application is available under examples/SQLCipherAndroid/ in the sqlcipher-android-fips-4.16.0.zip package. It incorporates all of the configurations described above and can be used for testing or comparison purposes.

Troubleshooting

  1. SQLiteOutOfMemoryException or unknown error (code 7): the Power On Self Test failed to verify the FIPS library. Check the build.gradle to ensure the packagingOptions settings above are properly applied.
  2. not authorized or SQLITE_AUTH (23): the License Code was not supplied, is not valid, or has expired. Check that the application is applying the license code in the preKey hook.
  3. UnsatisfiedLinkError: or library "libsqlcipher.so" not found: the SQLCipher library is not available for the given architecture. SQLCipher for Android FIPS does not support x86 emulators; use a 64-bit x86_64 emulator or an ARM device. Also check abiFilters to ensure platform-specific libraries are not being excluded.

Please contact support@zetetic.net with any questions or to receive private support.