This post is by Philippe Bertrand, staff software developer working on UltraLiteJ, and answers several questions we have had about database security on BlackBerry.
Introduction
In this article I present an overview of security issues on BlackBerry devices and discuss how an UltraLiteJ application developer may address them based on their security needs. I cover databases residing in the Persistent Store (Persistent Object Store), on-board flash memory (accessed as file:///store/ and hence referred to as flash file store), and media cards.
This article is based on the SQL Anywhere 11.0.1 release on a BlackBerry Device OS 4.2 – 5.0, although it applies to all known versions of UltraLiteJ at the time of writing. No knowledge of cryptography is required, nor is a developer background. However, to make use of the included code sample the reader should be familiar with the UltraLiteJ API and BlackBerry development.
Basic Security
The most basic level of security prevents theft of information by nosey individuals, such as those who can’t resist peeking at an open pay stub that a co-worker has left out in the open. We could also consider the value of the data: data that has little value to a prospective thief requires only minimal security. All data should at least be protected from accidental damage, such as when your six year old gets hold of your BlackBerry and starts playing with it. In addition, in a synchronization environment where an UltraLiteJ database is synchronized with a MobiLink server, you should also consider the risk of bad data being uploaded to the consolidated database.
For this kind of data, the BlackBerry device should be protected with a device password and the UltraLiteJ database should also be protected with a non-default password. The database password prevents other UltraLiteJ applications from accidently accessing a database. Databases in the BlackBerry Persistent Store are protected from non-UltraLiteJ applications using the type-checking mechanism, however files in the flash file store or on a media card can be viewed by other applications.
Protecting Sensitive Data
The next level of security protects data from malware and opportunistic thieves (stealing the device or media card then seeing if there is anything of value on it). While the basic security (device password) of the BlackBerry device is quite effective and will deter most thieves from accessing the persistent store (attempts to re-install the OS or too many attempts to guess the password will result in a security wipe of the Persistent Store), there is increased risk for data on flash file storage and data on media cards is completely unprotected (with the basic level of security). The value of the data determines how much effort the thief may take to acquire it – for instance, credit card and information used in identity theft is highly valued. You should also consider legislative privacy requirements (for personal health information for instance) and how embarrassing it could be to your company if customer or corporate data were leaked.
UltraLiteJ applications provide several options with respect to protecting this kind of data.
1. Encrypting just the sensitive data
Sensitive data such as credit card numbers, social security numbers, driver’s license numbers, etc. can be directly encrypted before they are placed in the database. While this approach may be the least CPU-intensive, it is more problematic to program, and such values may not be used in indexes in any order-preserving way (lookups can still be performed using the encrypted value). Access to column values is achieved through a simple accessor class (code not included) very similar to the Encryptor class described below, the only challenging part being to make sure to access all values through such a class.
2. Encrypting the entire database
An easier and more encompassing approach is to define a class that implements the UltraLiteJ EncryptionControl interface (sample below). This class is passed to an UltraLiteJ configuration object to create the database and is used for all subsequent connections that open the database. UltraLiteJ will use it to encrypt and decrypt all database pages.
Update: this code has been updated to show that you need to loop through the array of bytes you want to encrypt, passing them a chunk at a time to the encrypt or decrypt methods.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
| /** Class to implement encryption/decryption of the database.
*/
class Encryptor
implements EncryptionControl
{
private BlockEncryptorEngine _encryptor;
private BlockDecryptorEngine _decryptor;
private int block_length;
/** Encrypt a page stored in the Database.
* @param page_no the number of the page being encrypted
* @param src the encrypted source page which was read from the Database
* @param tgt the unencrypted page (filled in by method)
*/
public void decrypt( int page_no, byte[] src, byte[] tgt )
throws ULjException
{
try {
for( int i = 0; i < src.length; i += _block_length ) {
_decryptor.decrypt( src, i, tgt, i );
}
} catch( Exception e ) {
throw new EncryptionError();
}
}
/** Encrypt a page stored in the Database.
* @param page_no the number of the page being encrypted
* @param src the unencrypted source
* @param tgt the encrypted target page which will be written to the Database (filled in by method)
*/
public void encrypt( int page_no, byte[] src, byte[] tgt )
throws ULjException
{
try {
for( int i = 0; i < src.length; i += _block_length ) {
_encryptor.encrypt( src, i, tgt, i );
}
} catch( Exception e ) {
throw new EncryptionError();
}
}
/** Initialize the encryption control with a password.
* @param password the password
*/
public void initialize( String password )
throws ULjException
{
try {
byte[] bytes = password.getBytes( "UTF8" );
SHA256Digest sha = new SHA256Digest();
sha.reset();
sha.update( bytes, 0, bytes.length );
byte[] key_bytes = new byte[32];
sha.getDigest( key_bytes, 0, false );
AESKey key = new AESKey( key_bytes );
_encryptor = new AESEncryptorEngine( key );
_decryptor = new AESDecryptorEngine( key );
_block_length = _encryptor.getBlockLength();
} catch( Exception e ) {
throw new EncryptionError();
}
}
}
/** Error class for encryption errors.
*/
class EncryptionError
extends ULjException
{
/** Constructor.
*/
EncryptionError()
{
super( "Encryption Error" );
}
/**
* Get the error code, associated with this exception.
* @return the error code (from the list at the top of this class) associated
* with this exception
*/
public int getErrorCode()
{
return ULjException.SQLE_ERROR;
}
/** Get exception causing this exception, if it exists.
* @return null, if there is no causing exception; otherwise, the exception causing this exception
*/
public ULjException getCausingException()
{
return null;
}
/** Get offset of error within a SQL string.
* @return (-1) when there is no SQL string associated with the error message;
* otherwise, the (base 0) offset within that string where the error occurred.
*/
public int getSqlOffset()
{
return -1;
}
} |
Benefits
Both of these methods provide good security while providing excellent flexibility. Databases can be created and pre-loaded onto media cards for distribution or copied into the flash file store using the BlackBerry USB mass media mode while still providing data security. This option also allows for applications to run background synchronizations.
3. Using BlackBerry encryption mode for flash file store and media cards
A final approach (for flash file store and media card databases only) is to rely on the BlackBerry Device Options > Memory > Encryption Mode (or equivalent IT Policy) setting to specify the level of security for the database that is stored on either the flash file store or the media card. This approach requires the device to be unlocked whenever the application requires access to the database. Some values for this setting require the database to be created on the BlackBerry it will be used on, and a database cannot be imported with this security enabled, either through media card distribution or by the USB mass storage mode. While the Security Password encryption mode is more portable (between BlackBerry devices), the algorithm is not public, nor are there any desktop tools to create compatible encrypted files (Media Manager only handles media files and USB mass storage mode does not encrypt and decrypt files going to or from the device). For all enabled security modes, applications must implement a PersistentContentListener with a persistentContentStateChanged() method that closes all connections to the database when the device locks (strong references to the listener may cause memory leaks and other problems should the application fail and not clean up properly). After locking completes and the device key is released by the operating system, no database access, including background synchronization with a MobiLink server, is possible until the device is unlocked.
There is a risk if the user somehow installs malware on their device. When the device is unlocked, any application on the device can read or copy the database file.
Encryption is easily turned off
It should be noted that if a database is created without any encryption, changes to the Encryption Mode (or equivalent IT Policy) setting will have no effect on the security level of the database. If the database is created with any kind of encryption and the Encryption Mode is changed to None (while the card is still in the device), the database will become viewable by any BlackBerry even though it is still wrapped in an encrypted wrapper!
Critical Data and Determined Thieves
There is a select group of thieves that, given a locked device, can break into it and find the encryption keys that are in memory. This is a sophisticated attack known as a cold boot attack (http://en.wikipedia.org/wiki/Cold_boot_attack), which involves breaking into a device without removing power to the memory to get the device’s encryption key and then having access to everything stored in persistent store and other forms of memory. BlackBerry OS applications are protected by disabling access to the device encryption key when the device locks or is connected to the desktop.
An UltraLiteJ application would protect itself by implementing a MemoryCleanerListener, which drops all connections to the database and destroys all references to configuration objects used to connect to the database. The memory cleaner can be configured to run after a specified amount of time after the device is locked. A fully secure solution which does not require a user to re-enter a database password after the device is unlocked would do the following:
• Application implements an EncryptionControl for encrypting the UltraLiteJ database
• When first run, the application prompts for a database password
• The password is securely stored in the Persistent Store using PersistentContent.encode()
• On connect, the application uses the password and the EncryptionControl to create a connection to the database (do not keep extra references to the configuration object or password)
• When the MemoryCleanerListener is invoked, the application drops all connections to the database, destroys all configurations, EncryptionControl objects, and all copies of the password (not the one in Persistent Store)
• Once the user unlocks the device, the application can retrieve the password from the Persistent Store and reconnect to the database.
One interesting opportunity that arises when you implement a MemoryCleanerListener and a PersistentContentListener is that they define the time between when a device is locked and when it should be completely secure – an ideal time for a background synchronization!
If you use the preceding security solution, ensure either that the device Options > Memory > Encryption Mode (and associated IT Policy) are turned off, or that the database has first been created on the desktop to maintain the full features and functionality described above.
It should be noted that even RIM’s solution has one weakness since applications may hold onto a “ticket,” keeping the device key in memory until they release the ticket. A single bad application may keep the device in a vulnerable state. Users should pay attention to the little padlock icon on the locked screen. It only ”locks” when the key is cleaned up.
Persistent Store Security Options
The device Options > Security Options > General Settings > Content Protection (and the associated IT Policy setting) affects only the Persistent and Runtime Store of the device. Content protection is not automatic but requires applications to do the right thing with respect to their data. At this time, UltraLiteJ does not provide any support for this setting.
Please note that the device Options > Memory > Encryption Mode is independent of the Options > Security Options > General Settings > Content Protection setting. Encryption Mode controls the security of the flash file store and media card.
IT Policy Versus User Settings
All device options mentioned in this article may be overwritten by the IT policies of the BlackBerry Enterprise Server (BES) a device is paired with, in which case the most restrictive setting (user or IT) takes precedence. Thus, a user may not choose a less restrictive Encryption Mode than what is mandated by the corresponding IT Policy setting.