Difference between revisions of "Symbian OS Platform Security/07. Sharing Data Safely"

From Franklin Heath Ltd Wiki
Jump to: navigation, search
m (Getting the Right Balance)
m (removed category, added copyright template)
 
(10 intermediate revisions by 5 users not shown)
Line 1: Line 1:
 +
{| width="100%"
 +
|'''by Will Palmer'''||align="center"|Reproduced by kind permission of John Wiley & Sons.||align="right"|'''[[Symbian OS Platform Security/06. How to Write Secure Plug-ins|Prev.]]   [[Symbian OS Platform Security|Contents]]   [[Symbian OS Platform Security/08. Native Software Installer|Next]]'''
 +
|}
 +
 
=Introduction to Sharing Data=
 
=Introduction to Sharing Data=
 
This chapter presents the key questions you need to ask – and some
 
This chapter presents the key questions you need to ask – and some
Line 27: Line 31:
 
key questions to consider. These will all be developed in further sections.
 
key questions to consider. These will all be developed in further sections.
  
'''Do you need to protect the integrity of your data?'''
+
'''''Do you need to protect the integrity of your data?'''''
  
 
You may need to guard against abnormal behavior of your application
 
You may need to guard against abnormal behavior of your application
Line 36: Line 40:
 
secure URL.
 
secure URL.
  
'''Do you need to protect the confidentiality of your data?'''
+
'''''Do you need to protect the confidentiality of your data?'''''
  
 
Your data may need to be guarded against ‘prying eyes’ – for example, if
 
Your data may need to be guarded against ‘prying eyes’ – for example, if
Line 43: Line 47:
 
password to be retrieved only if the user supplies a PIN.
 
password to be retrieved only if the user supplies a PIN.
  
'''What attacks should you care about?'''
+
'''''What attacks should you care about?'''''
  
 
There are several types of attack on data, both on its confidentiality and
 
There are several types of attack on data, both on its confidentiality and
Line 50: Line 54:
 
provided to protect against all of them.
 
provided to protect against all of them.
  
'''When should your data be available?'''
+
'''''When should your data be available?'''''
  
 
Do you want to share your data synchronously or asynchronously? You
 
Do you want to share your data synchronously or asynchronously? You
Line 56: Line 60:
 
You usually do this by making use of Symbian OS system services.
 
You usually do this by making use of Symbian OS system services.
  
'''How much data should you share?'''
+
'''''How much data should you share?'''''
  
 
You should examine the granularity of your data below the file level.
 
You should examine the granularity of your data below the file level.
Line 89: Line 93:
 
It is worth briefly touching on this topic, in order to clearly understand
 
It is worth briefly touching on this topic, in order to clearly understand
 
where the boundaries are. This is important to enable us to look at the
 
where the boundaries are. This is important to enable us to look at the
‘end-to-end’ security of our data.We have alreadymentioned in Chapter 1
+
‘end-to-end’ security of our data. We have already mentioned in Chapter 1
 
how controls at the network boundary are becoming inadequate because
 
how controls at the network boundary are becoming inadequate because
 
of the trend towards seamless information flow between networks. There
 
of the trend towards seamless information flow between networks. There
Line 107: Line 111:
 
can send from the mobile phone – for example, address book contact
 
can send from the mobile phone – for example, address book contact
 
information that is synchronized to the PC. The synchronization process
 
information that is synchronized to the PC. The synchronization process
has capabilities ReadUserData and LocalServices, and we trust it
+
has capabilities {{Icode|ReadUserData}} and {{Icode|LocalServices}}, and we trust it
 
to send on request only the subset of data that is policed by this capability.
 
to send on request only the subset of data that is policed by this capability.
 +
 
We also cannot control how the data is used once it is received by
 
We also cannot control how the data is used once it is received by
 
an external entity. There can be no guarantee that the external entity will
 
an external entity. There can be no guarantee that the external entity will
Line 171: Line 176:
 
may simply be achieved at the user interface level; an example of this is a
 
may simply be achieved at the user interface level; an example of this is a
 
calendar entry that might be a public holiday or a medical appointment.
 
calendar entry that might be a public holiday or a medical appointment.
 +
 
User data capabilities are usually policed symmetrically – that is, both
 
User data capabilities are usually policed symmetrically – that is, both
 
reading and writing the data requires a capability. User data does not
 
reading and writing the data requires a capability. User data does not
Line 187: Line 193:
 
(persistent and constant value). The hardware abstraction layer (HAL) in
 
(persistent and constant value). The hardware abstraction layer (HAL) in
 
the OS kernel contains system data, some of which has a constant value
 
the OS kernel contains system data, some of which has a constant value
(ECPUSpeed), and some of which is variable (EBacklightState).
+
({{Icode|ECPUSpeed}}), and some of which is variable ({{Icode|EBacklightState}}).
  
 
Here though, the type of data does not automatically determine the
 
Here though, the type of data does not automatically determine the
Line 200: Line 206:
 
this is network signal strength or current call status. In the small number
 
this is network signal strength or current call status. In the small number
 
of cases where confidentiality is required in addition to integrity, read
 
of cases where confidentiality is required in addition to integrity, read
access is policed with ReadDeviceData and we term this ‘device data’
+
access is policed with {{Icode|ReadDeviceData}} and we term this ‘device data’
 
since the policy is then symmetrical. An example of this would be an
 
since the policy is then symmetrical. An example of this would be an
 
IMAP server address.
 
IMAP server address.
Line 214: Line 220:
 
has no bearing on the policy.
 
has no bearing on the policy.
  
{| Border="1"
+
{| Border="1" cellspacing="0" cellpadding="6"
 +
|+'''Table 7.1''' Data Access Capabilities
 
!Type of Data !! Confidentiality Required: access policy !! Integrity Required: access policy
 
!Type of Data !! Confidentiality Required: access policy !! Integrity Required: access policy
 
|-  
 
|-  
| User data||  ReadUserData or none || WriteUserData
+
| User data||  {{Icode|ReadUserData}} or none || {{Icode|WriteUserData}}
 
|-
 
|-
| System data|| None|| WriteDeviceData, SID of process that modifies the value
+
| System data|| None|| {{Icode|WriteDeviceData}}, SID of process that modifies the value
 
|-
 
|-
| Device data|| ReadDeviceData|| WriteDeviceData
+
| Device data|| {{Icode|ReadDeviceData}}|| {{Icode|WriteDeviceData}}
 
|}
 
|}
  
Line 240: Line 247:
 
‘noise’ but deleting entries as removing an audit trail.
 
‘noise’ but deleting entries as removing an audit trail.
  
It is sometimes easier to apply an inverse test and ask, ‘Who do I not
+
It is sometimes easier to apply an inverse test and ask, ‘Who do I ''not''
 
want to share my data with?’. This might help you to decide how much
 
want to share my data with?’. This might help you to decide how much
 
you would care if the data was corrupted or deleted, either intentionally
 
you would care if the data was corrupted or deleted, either intentionally
Line 251: Line 258:
 
Bear in mind that when we asked users what security they expect from
 
Bear in mind that when we asked users what security they expect from
 
a mobile phone, one answer repeatedly made was ‘I want my private
 
a mobile phone, one answer repeatedly made was ‘I want my private
data to stay private’ (as reported in Symbian OS Internals [Sales 2005]).
+
data to stay private’ (as reported in ''Symbian OS Internals'' [Sales 2005]).
  
 
==Identification for Authorization==
 
==Identification for Authorization==
Line 258: Line 265:
 
authorization model. You may choose to mediate access using the SID or
 
authorization model. You may choose to mediate access using the SID or
 
the VID of the process because you are only concerned with identity.
 
the VID of the process because you are only concerned with identity.
 +
 
Policing your data using the VID may be considered less secure
 
Policing your data using the VID may be considered less secure
 
than using the SID, as the scope of processes with a particular VID is
 
than using the SID, as the scope of processes with a particular VID is
Line 288: Line 296:
 
Having created a threat model you will have a good idea of the kind of
 
Having created a threat model you will have a good idea of the kind of
 
attacks that could occur on your data. We categorize the most common
 
attacks that could occur on your data. We categorize the most common
forms of attack below, and focus primarily on intentional attacks directed
+
forms of attack below, and focus primarily on ''intentional'' attacks directed
 
against our data assets. Unintentional compromises, however, can be just
 
against our data assets. Unintentional compromises, however, can be just
 
as damaging unless we implement robust behavior.
 
as damaging unless we implement robust behavior.
Line 295: Line 303:
 
services, since many problems occur as a result of concurrency
 
services, since many problems occur as a result of concurrency
 
issues – multiple clients accessing data at the same time [Anderson 2001].
 
issues – multiple clients accessing data at the same time [Anderson 2001].
 +
 
We also discuss specific countermeasures for each type of attack. The
 
We also discuss specific countermeasures for each type of attack. The
 
platform security architecture gives you the primary countermeasures
 
platform security architecture gives you the primary countermeasures
Line 300: Line 309:
 
protection, through process isolation, are integral countermeasure tools
 
protection, through process isolation, are integral countermeasure tools
 
that you get ‘for free’. However there are two things that you must do:
 
that you get ‘for free’. However there are two things that you must do:
*Implement the countermeasures, made available through the platform
+
*Implement the countermeasures, made available through the platform security architecture that you have decided on to harden your software against attack.
security architecture that you have decided on to harden your software
+
*Apply ‘best practices’ as a complement to platform security, to make your software robust in the face of unexpected data. These are critical elements of security engineering in diminishing the threat of attack.
against attack.
+
*Apply ‘best practices’ as a complement to platform security, to make
+
your software robust in the face of unexpected data. These are critical
+
elements of security engineering in diminishing the threat of attack.
+
  
 
Unfortunately, many instances of compromised data occur as a result
 
Unfortunately, many instances of compromised data occur as a result
Line 317: Line 322:
  
 
==Data Capture==
 
==Data Capture==
This is an attack on confidentiality and is the most commonly considered
+
This is an attack on ''confidentiality'' and is the most commonly considered
 
attack on data. Here are some ways in which it can occur:
 
attack on data. Here are some ways in which it can occur:
 
*Malware tricking a process into giving it data – for example, by
 
*Malware tricking a process into giving it data – for example, by
Line 323: Line 328:
 
from any output. Alternatively it could use brute force – for example,
 
from any output. Alternatively it could use brute force – for example,
 
by cracking a password.
 
by cracking a password.
*Snooping on data passed between two legitimate entities (man-inthe-
+
*Snooping on data passed between two legitimate entities (man-inthe- middle). Temporary files and public memory spaces are common attack vectors.
middle). Temporary files and public memory spaces are common
+
*Unintentionally giving access to files, or data within them, that should not be shared. Often data is part of a collection of information. It may be a set of elements in a table, lines in a file, a typed list of elements, or a set of properties of a class. Sharing more data than you need to leaves that data vulnerable to attack. Log files are an obvious example here, especially if they are recorded to a public location.
attack vectors.
+
*Unintentionally giving access to files, or data within them, that should
+
not be shared. Often data is part of a collection of information. It may
+
be a set of elements in a table, lines in a file, a typed list of elements,
+
or a set of properties of a class. Sharing more data than you need to
+
leaves that data vulnerable to attack. Log files are an obvious example
+
here, especially if they are recorded to a public location.
+
  
Countermeasures
+
===Countermeasures===
  
 
#Place your sensitive persistent data in the private data cage of your process, and keep your sensitive transient data within its private memory space.
 
#Place your sensitive persistent data in the private data cage of your process, and keep your sensitive transient data within its private memory space.
Line 341: Line 339:
 
#Identify and implement different read policies, where necessary, for collections of data. Consider the individual elements of the collection and only share what is necessary.
 
#Identify and implement different read policies, where necessary, for collections of data. Consider the individual elements of the collection and only share what is necessary.
  
Best practices
+
===Best practices===
  
 
Some best practices to help keep data secure from prying eyes are:
 
Some best practices to help keep data secure from prying eyes are:
Line 352: Line 350:
  
 
==Tampering==
 
==Tampering==
This is an attack on the integrity of data and, where system or device data
+
This is an attack on the ''integrity'' of data and, where system or device data
 
is involved, on the integrity of the mobile phone itself. Here are some
 
is involved, on the integrity of the mobile phone itself. Here are some
 
ways in which it can occur, some reasons and some effects:
 
ways in which it can occur, some reasons and some effects:
*Most importantly, the attack could be launched to cause instability
+
*Most importantly, the attack could be launched to cause instability through corrupted data. This might result in a process crash, or stopping the mobile phone from booting.
through corrupted data. This might result in a process crash, or
+
*It may be launched to coerce the owner into undertaking an alternative path of action.
stopping the mobile phone from booting.
+
*It may lead to service denial – for example, if dialup connection information is altered.
*It may be launched to coerce the owner into undertaking an alternative
+
*It may cause the user to unwittingly spend money – for example, by altering a phone number to a premium rate one.
path of action.
+
*It may lead to service denial – for example, if dialup connection
+
information is altered.
+
*It may cause the user to unwittingly spend money – for example, by
+
altering a phone number to a premium rate one.
+
 
*It may lead to data capture, if connection information is altered.
 
*It may lead to data capture, if connection information is altered.
*Data on removable media is at high risk from this kind of attack – as
+
*Data on removable media is at high risk from this kind of attack – as we have already noted, this is out of our control when the media is removed from the mobile phone.
we have already noted, this is out of our control when the media is
+
*Some attacks of this kind are specific to server processes that allow concurrency of access. These occur when inconsistent updates are performed on dependent compound data. There is a risk of being left in an unknown state unless atomic updates are executed.
removed from the mobile phone.
+
*Some attacks of this kind are specific to server processes that allow
+
concurrency of access. These occur when inconsistent updates are
+
performed on dependent compound data. There is a risk of being left
+
in an unknown state unless atomic updates are executed.
+
  
'''Countermeasures'''
+
===Countermeasures===
  
 
#Place your sensitive persistent data in the private data cage of your process, and keep your sensitive transient data within its private memory space.
 
#Place your sensitive persistent data in the private data cage of your process, and keep your sensitive transient data within its private memory space.
Line 379: Line 367:
 
#Use a system service to mediate write access on your behalf, and register a write policy with it for your data. Your data is hidden within the system service’s data cage or process memory space.
 
#Use a system service to mediate write access on your behalf, and register a write policy with it for your data. Your data is hidden within the system service’s data cage or process memory space.
 
#Share individual files from your data cage with trusted processes using shared handles.
 
#Share individual files from your data cage with trusted processes using shared handles.
#Take advantage of the static access policy that is applied to the special directory \resource for your resource files. This directory allows you to share your resources publicly but without compromising their integrity. Essentially it is a read-only directory for non-TCB processes. Examples of data you might install here are bitmaps, fonts, RSC and help files.
+
#Take advantage of the static access policy that is applied to the special directory \resource for your resource files. This directory allows you to share your resources publicly but without compromising their integrity. Essentially it is a read-only directory for non-TCB processes. Examples of data you might install here are bitmaps, fonts, {{Icode|RSC}} and help files.
  
'''Best practices'''
+
===Best practices===
  
#Make your process fault tolerant – that is, resistant to corrupted or unexpected data. Create a recovery strategy for all the situations you have identified in your threat model. This may be as simple as resetting the data back to a ‘default’ configuration for corrupted backup data. Choose a resilience strategy that is both simple and effective for your process, and also right for the type of data in question. If you are implementing a media player, you are likely to be accepting data from off the mobile phone (OTA or removable
+
#Make your process fault tolerant – that is, resistant to corrupted or unexpected data. Create a recovery strategy for all the situations you have identified in your threat model. This may be as simple as resetting the data back to a ‘default’ configuration for corrupted backup data. Choose a resilience strategy that is both simple and effective for your process, and also right for the type of data in question. If you are implementing a media player, you are likely to be accepting data from off the mobile phone (OTA or removable media). If such a file were corrupt you would simply not play it.
media). If such a file were corrupt you would simply not play it.
+
#You may refuse unsolicited data but instead only use data that has been installed through the Software Install process. You can do this by not implementing support for a {{Icode|\import}} directory in your private data cage – see Chapter 8 for more information on import directories.
#You may refuse unsolicited data but instead only use data that has been installed through the Software Install process. You can do this by not implementing support for a \import directory in your private data cage – see Chapter 8 for more information on import directories.
+
#Return errors to clients of your data in a timely fashion, but make sure that a client can process the error. For example, you must not return an error for a method such as {{Icode|CancelTransaction()}}.
#Return errors to clients of your data in a timely fashion, but make sure that a client can process the error. For example, you must not return an error for a method such as CancelTransaction().
+
#Threats to server processes associated with inconsistent updates can be mitigated by using a locking transaction model. However, we do not recommend this – instead build this into your recovery strategy. For example, the use of client-side caching of data is advocated in ''Symbian OS C++ for Mobile Phones'' [Harrison 2003] – this could be used to roll back to a consistent state.
#Threats to server processes associated with inconsistent updates can be mitigated by using a locking transaction model. However, we do not recommend this – instead build this into your recovery strategy. For example, the use of client-side caching of data is advocated in Symbian OS C++ for Mobile Phones [Harrison 2003] – this could be used to roll back to a consistent state.
+
  
 
==Denial of Service==
 
==Denial of Service==
This is an attack on availability of data and is especially important to
+
This is an attack on ''availability'' of data and is especially important to
 
address for the system services presented next in this chapter. Here are
 
address for the system services presented next in this chapter. Here are
 
some ways in which it can occur:
 
some ways in which it can occur:
Line 398: Line 385:
 
*Causing a priority inversion – an attack on a server process – where a high-priority thread waiting on that service fails to run because a low-priority thread has locked the resource it wishes to access. A resource can be locked for an extended period of time, for example, if a large transaction takes place (or indeed if a locking transaction never completes), or if frequent and extensive searches through the data are made.
 
*Causing a priority inversion – an attack on a server process – where a high-priority thread waiting on that service fails to run because a low-priority thread has locked the resource it wishes to access. A resource can be locked for an extended period of time, for example, if a large transaction takes place (or indeed if a locking transaction never completes), or if frequent and extensive searches through the data are made.
  
'''Countermeasures'''
+
===Countermeasures===
  
#Place your sensitive persistent data in the private data cage of your process and keep your sensitive transient data within its private
+
#Place your sensitive persistent data in the private data cage of your process and keep your sensitive transient data within its private memory space.
memory space.
+
 
#Police the transaction APIs correctly on your server process to guard against denial of service through locking.
 
#Police the transaction APIs correctly on your server process to guard against denial of service through locking.
  
'''Best practices'''
+
===Best practices===
  
 
#Make your process fault tolerant and create a good recovery strategy.
 
#Make your process fault tolerant and create a good recovery strategy.
Line 414: Line 400:
 
breaking a mobile phone.
 
breaking a mobile phone.
  
Best practices
+
===Best practices===
  
 
Recovery of lost data can be achieved if processes back up their data.
 
Recovery of lost data can be achieved if processes back up their data.
Line 429: Line 415:
 
data capture (DC), tampering (TA), and denial of service (DoS).
 
data capture (DC), tampering (TA), and denial of service (DoS).
  
Threat scenario and type Countermeasure
+
{| border="1" cellspacing="0" cellpadding="6"
 
+
|+'''Table 7.2''' Threats and Countermeasures
Tricking of APIs by malware
+
!Threat scenario and type !! Countermeasure
(DC)
+
|-
Data cage all sensitive data, or keep in
+
| Tricking of APIs by malware (DC)||  Data cage all sensitive data, or keep in private memory space
private memory space
+
|-
Snooping (DC) Data cage and implement API read
+
| Snooping (DC)|| Data cage and implement API read policy (use system service if practical) Use shared file handles
policy (use system service if practical)
+
|-
Use shared file handles
+
| Unintentionally allowing access (DC)|| Implement read policies at the right level of granularity
Unintentionally allowing
+
|-
access (DC)
+
|Modification of data to cause unexpected behavior, including failing to execute (TA, DoS)||Data cage and implement API write policy (use system service if practical)
Implement read policies at the right
+
level of granularity
+
Threat scenario and type Countermeasure
+
Modification of data to cause
+
unintended or unexpected
+
behavior, including failing to
+
execute (TA, DoS)
+
Data cage and implement API write
+
policy (use system service if practical)
+
 
Use shared file handles
 
Use shared file handles
 
Use \resource directory for your
 
Use \resource directory for your
 
resources
 
resources
Altering dial-up information
+
|-
(TA, DoS, DC)
+
| Altering dial-up information (TA, DoS, DC)|| Data cage and implement API write policy
Data cage and implement API write
+
|-
policy
+
| Inconsistent update made (TA, DoS)|| Police transactional APIs accordingly
Inconsistent update made (TA,
+
|-
DoS)
+
| Causing a buffer overflow (DoS)|| Implement fault tolerance (best practice only)
Police transactional APIs accordingly
+
|-
Causing a buffer overflow
+
| Causing a priority inversion or locking of a resource (DoS)|| Police (transactional) APIs accordingly
(DoS)
+
|}
Implement fault tolerance (best
+
practice only)
+
Causing a priority inversion or
+
locking of a resource (DoS)
+
Police (transactional) APIs accordingly
+
  
 
=Using System Services=
 
=Using System Services=
Line 496: Line 468:
 
Publish and subscribe is a state-oriented service for asynchronous distribution
 
Publish and subscribe is a state-oriented service for asynchronous distribution
 
of information where the latest value of a setting is the only
 
of information where the latest value of a setting is the only
one relevant. We term each setting held in this service a property. Key
+
one relevant. We term each setting held in this service a ''property''. Key
 
functional points are:
 
functional points are:
*It provides a means to store and broadcast transient data at run time.
+
*It provides a means to store and broadcast ''transient'' data at run time.
 
*It can provide a run-time data cage into which each process can publish its properties, providing protection from spoofing or denial of service.
 
*It can provide a run-time data cage into which each process can publish its properties, providing protection from spoofing or denial of service.
 
*Under certain circumstances it provides bounded execution time for critical tasks that require real-time guarantees. Guarantees are made for:
 
*Under certain circumstances it provides bounded execution time for critical tasks that require real-time guarantees. Guarantees are made for:
Line 508: Line 480:
 
Here is the prototype for defining a property:
 
Here is the prototype for defining a property:
  
IMPORT_C static TInt Define(TUint aKey, TInt aAttr,
+
<code>
const TSecurityPolicy& aReadPolicy,
+
IMPORT_C static TInt Define(TUint aKey, TInt aAttr,
const TSecurityPolicy& aWritePolicy,
+
                const TSecurityPolicy& aReadPolicy,
TInt aPreallocated=0);
+
                const TSecurityPolicy& aWritePolicy,
 +
                              TInt aPreallocated=0);</code>
  
 
When a process defines a property it is stored in a category with a value
 
When a process defines a property it is stored in a category with a value
Line 536: Line 509:
 
friend event’:
 
friend event’:
  
static const TInt32 KIMServerSID = 0x89ABCDEF;
+
<code>
static _LIT_SECURITY_POLICY_S0 (KFriendsListChangePolicy,
+
static const TInt32 KIMServerSID = 0x89ABCDEF;
KIMServerSID);
+
static _LIT_SECURITY_POLICY_S0 (KFriendsListChangePolicy,
void CIMServer::ConstructL()
+
                                KIMServerSID);
{
+
...
+
void CIMServer::ConstructL()
User::LeaveIfError(
+
  {
RProperty::Define(KKeyFriendsListHasChanged,
+
  ...
RProperty::EInt,
+
  User::LeaveIfError(
KAlwaysPassPolicy,
+
              RProperty::Define(KKeyFriendsListHasChanged,
KFriendsListChangePolicy));
+
                                          RProperty::EInt,
...
+
                                        KAlwaysPassPolicy,
}
+
                              KFriendsListChangePolicy));
 +
  ...
 +
  }</code>
  
 
There are a couple of interesting points that come out of this. Firstly,
 
There are a couple of interesting points that come out of this. Firstly,
Line 562: Line 537:
 
property when a friend’s online status changes:
 
property when a friend’s online status changes:
  
void CIMServer::OnCommunicationEventL(TEvent aEvent,
+
<code>
TEventData aBuf, TInt aError)
+
void CIMServer::OnCommunicationEventL(TEvent aEvent,
{
+
                        TEventData aBuf, TInt aError)
144 SHARING DATA SAFELY
+
  {
switch (aEvent)
+
  switch (aEvent)
{
+
    {
case EFriendOnline:
+
    case EFriendOnline:
case EFriendOffline:
+
    case EFriendOffline:
{
+
      {
UpdateFriendsListL(aBuf);
+
      UpdateFriendsListL(aBuf);
User::LeaveIfError (RProperty::Set(KIMServerSID,
+
      User::LeaveIfError (RProperty::Set(KIMServerSID,
KKeyFriendsListHasChanged,
+
                            KKeyFriendsListHasChanged,
iFriendsList.Count()));
+
                                iFriendsList.Count()));
}
+
      }
...
+
    ...
}
+
    }
}
+
  }</code>
  
Consider the client code for the UI application. First, in its ConstructL()
+
Consider the client code for the UI application. First, in its {{Icode|ConstructL()}}
 
the application creates an instance of an active object
 
the application creates an instance of an active object
 
that tracks ‘friends online change’ events from the server:
 
that tracks ‘friends online change’ events from the server:
void CIMApplicationUI::ConstructL()
+
 
{
+
<code>
// connect to the server
+
void CIMApplicationUI::ConstructL()
User::LeaveIfError(iIMSvr.Connect());
+
{
// create the active object that tracks events
+
// connect to the server
iWatcher = CFriendEventWatcher::NewL(*this);
+
User::LeaveIfError(iIMSvr.Connect());
...
+
// create the active object that tracks events
}
+
iWatcher = CFriendEventWatcher::NewL(*this);
 +
...
 +
}</code>
 +
 
 
The following code shows how the active object handles and acts on
 
The following code shows how the active object handles and acts on
 
these server events:
 
these server events:
void CFriendEventWatcher::ConstructL()
+
 
{
+
<code>
// attach to the property
+
void CFriendEventWatcher::ConstructL()
User::LeaveIfError(iProperty.Attach(KIMServerSID,
+
  {
KKeyFriendsListHasChanged));
+
  // attach to the property
CActiveScheduler::Add(this)
+
  User::LeaveIfError(iProperty.Attach(KIMServerSID,
// initial subscription and process current property value
+
                        KKeyFriendsListHasChanged));
RunL();
+
  CActiveScheduler::Add(this)
}
+
  // initial subscription and process current property value
void CFriendEventWatcher::RunL()
+
  RunL();
{
+
  }
// re-subscribe to help prevent missing notification of updates
+
iProperty.Subscribe(iStatus);
+
void CFriendEventWatcher::RunL()
SetActive();
+
  {
// test availability of property
+
  // re-subscribe to help prevent missing notification of updates
TInt numfriends;
+
  iProperty.Subscribe(iStatus);
TInt err = iProperty.Get(numfriends);
+
  SetActive();
if (KErrNotFound == err)
+
 
{
+
  // test availability of property
// server is not running
+
  TInt numfriends;
User::Leave(KErrIMServerNotRunning);
+
  TInt err = iProperty.Get(numfriends);
}
+
  if (KErrNotFound == err)
USING SYSTEM SERVICES 145
+
    {
else if (KErrNone == err)
+
    // server is not running
{
+
    User::Leave(KErrIMServerNotRunning);
if (numfriends)
+
    }
{
+
  else if (KErrNone == err)
// enable friends online icon
+
    {
}
+
    if (numfriends)
else
+
      {
{
+
      // enable friends online icon
// disable friends online icon
+
      }
}
+
    else
}
+
      {
...
+
      // disable friends online icon
}
+
      }
 +
    }
 +
  ...
 +
  }</code>
  
 
Here we are checking the latest value in order to enable or disable a
 
Here we are checking the latest value in order to enable or disable a
Line 649: Line 630:
 
value to it. This is an example of non-symmetrical policing.
 
value to it. This is an example of non-symmetrical policing.
  
'''Good practices'''
+
===Good practices===
  
 
Multiple publishers of values to a property are generally discouraged.
 
Multiple publishers of values to a property are generally discouraged.
Line 682: Line 663:
 
factory reset and data backup of the mobile phone. Key functional
 
factory reset and data backup of the mobile phone. Key functional
 
points are:
 
points are:
*It uses simple partitioning of data using a UID-pair to create a two-tier structure: up to 232 top-level ‘keyspaces’ or repositories, within which up to 232 settings of any simple type, may be defined.
+
*It uses simple partitioning of data using a UID-pair to create a two-tier structure: up to 2<sup>32</sup> top-level ‘keyspaces’ or repositories, within which up to 2<sup>32</sup> settings of any simple type, may be defined.
 
*It provides the ability to define separate read and write access policies to settings within a keyspace at three levels: a default policy for the whole keyspace, a policy for a range of settings and a policy for individual settings.
 
*It provides the ability to define separate read and write access policies to settings within a keyspace at three levels: a default policy for the whole keyspace, a policy for a range of settings and a policy for individual settings.
 
*It provides the means to change the read and write access policy of a setting at run time.
 
*It provides the means to change the read and write access policy of a setting at run time.
Line 694: Line 675:
 
deleting keyspaces that are no longer used.
 
deleting keyspaces that are no longer used.
  
It is important to note that the central repository is not generally
+
{|border="1" cellspacing="0" cellpadding="8"
available for use as a storage mechanism at the time of writing. Third
+
|It is important to note that the central repository is not generally available for use as a storage mechanism at the time of writing. Third parties with sufficient capabilities can find and read from settings, and be notified of any changes, but cannot write their own changes. This restriction is likely to be lifted in the future.
parties with sufficient capabilities can find and read from settings, and
+
|}
be notified of any changes, but cannot write their own changes. This
+
restriction is likely to be lifted in the future.
+
  
 
The INI file may also contain settings and default values for that keyspace.
 
The INI file may also contain settings and default values for that keyspace.
 
Here is a simple example, an instant messaging server’s initialization file:
 
Here is a simple example, an instant messaging server’s initialization file:
  
# 89ABCDEF.cre
+
<code>
# Instant Messaging Server keyspace
+
# 89ABCDEF.cre
cenrep
+
# Instant Messaging Server keyspace
version 1
+
[platsec]
+
cenrep
# default capabilities for this keyspace
+
version 1
cap_rd=ReadUserData cap_wr=WriteUserData
+
# define a range for server private data
+
[platsec]
0x100 0x200 sid_rd=0x89ABCDEF sid_wr=0x89ABCDEF
+
# default capabilities for this keyspace
# define a range for public data
+
cap_rd=ReadUserData cap_wr=WriteUserData
0x1000 0x1100 cap_rd=AlwaysPass cap_wr=AlwaysPass
+
# define a range for server private data
[defaultMeta]
+
0x100 0x200 sid_rd=0x89ABCDEF sid_wr=0x89ABCDEF
0x1000000
+
# define a range for public data
[main]
+
0x1000 0x1100 cap_rd=AlwaysPass cap_wr=AlwaysPass
# protected by default capabilities
+
# autologin: specifies whether to login on startup of application
+
[defaultMeta]
0x1 int 1
+
0x1000000
# usesslport: specifies whether to use SSL
+
0x2 int 0
+
[main]
# anonsearch: specifies whether to undertake anonymous searches
+
# protected by default capabilities
0x3 int
+
# autologin: specifies whether to login on startup of application
# server private data
+
0x1 int 1
# imhostname: host address of server
+
# usesslport: specifies whether to use SSL
0x100 string “host1.imserver”
+
0x2 int 0
# defport: default port number
+
# anonsearch: specifies whether to undertake anonymous searches
0x101 int 5269
+
0x3 int
# sslport: ssl port number
+
0x102 int 5223
+
# server private data
# account data (device data) - using individual policy
+
# imhostname: host address of server
# username
+
0x100 string “host1.imserver”
0x200 string “username” cap_rd=ReadDeviceData
+
# defport: default port number
cap_wr=WriteDeviceData
+
0x101 int 5269
# password
+
# sslport: ssl port number
0x201 string “password” cap_rd=ReadDeviceData
+
0x102 int 5223
cap_wr=WriteDeviceData
+
# public data
+
# account data (device data) - using individual policy
# onlineicon: user profile icon
+
# username
0x1000 string “defUser.gif”
+
0x200 string “username” cap_rd=ReadDeviceData
# displayfont
+
cap_wr=WriteDeviceData
0x1001 string “swissA”
+
# password
# fontsize
+
0x201 string “password” cap_rd=ReadDeviceData
0x1002 int 10
+
cap_wr=WriteDeviceData
#timeout: timeout value (min) for inactive chat sessions
+
0x1003 int 10
+
# public data
 +
# onlineicon: user profile icon
 +
0x1000 string “defUser.gif”
 +
# displayfont
 +
0x1001 string “swissA”
 +
# fontsize
 +
0x1002 int 10
 +
#timeout: timeout value (min) for inactive chat sessions
 +
0x1003 int 10</code>
  
 
The ability to define access policies at different levels makes this service
 
The ability to define access policies at different levels makes this service
very flexible. This is particularly important as you can store up to 232
+
very flexible. This is particularly important as you can store up to 2<sup>32</sup>
 
settings in a single keyspace. Note that the policies are governed by
 
settings in a single keyspace. Note that the policies are governed by
the standard rules applied by the TSecurityPolicy class. The policies
+
the standard rules applied by the {{Icode|TSecurityPolicy}} class. The policies
 
at successive levels supersede any more general policy defined,
 
at successive levels supersede any more general policy defined,
 
and these cannot be applied or changed dynamically. This does not
 
and these cannot be applied or changed dynamically. This does not
Line 776: Line 763:
 
high concurrency – a number of transactions are allowed to be opened
 
high concurrency – a number of transactions are allowed to be opened
 
on a keyspace, however, the first to commit causes all others to fail
 
on a keyspace, however, the first to commit causes all others to fail
with KErrLocked. Consequently, clients are rewarded for keeping their
+
with {{Icode|KErrLocked}}. Consequently, clients are rewarded for keeping their
 
transactions short since they are less likely to fail. Clients that must
 
transactions short since they are less likely to fail. Clients that must
guarantee success place their transaction in a do-while KErrLocked
+
guarantee success place their transaction in a {{Icode|do-while KErrLocked}}
 
loop. Concurrency is further guarded by checking that the capabilities
 
loop. Concurrency is further guarded by checking that the capabilities
 
of the requesting client were at least equal to the default policy for the
 
of the requesting client were at least equal to the default policy for the
Line 792: Line 779:
 
and provides you with a way to share your data asynchronously. Key
 
and provides you with a way to share your data asynchronously. Key
 
functional points are:
 
functional points are:
*It provides the ability to define cumulative separate read and write access and schema manipulation policies on two levels: a default policy for the database and a policy for individual tables.
+
*It provides the ability to define ''cumulative'' separate read and write access and schema manipulation policies on two levels: a default policy for the database and a policy for individual tables.
 
*It provides a lightweight client-side implementation, enabling processes to store data in their own data cage, and police it accordingly.
 
*It provides a lightweight client-side implementation, enabling processes to store data in their own data cage, and police it accordingly.
  
Line 809: Line 796:
 
to apply to a database and it can be used to add capabilities for accessing
 
to apply to a database and it can be used to add capabilities for accessing
 
tables. Note that the policies are governed by the standard rules applied
 
tables. Note that the policies are governed by the standard rules applied
by the TSecurityPolicy class and that this table-level security can
+
by the {{Icode|TSecurityPolicy}} class and that this table-level security can
only strengthen the database policy, rather than override it. Here is an
+
only ''strengthen'' the database policy, rather than override it. Here is an
 
example policy file that an instant messaging server might register to be
 
example policy file that an instant messaging server might register to be
 
used to police access to an IM ‘friends’ database:
 
used to police access to an IM ‘friends’ database:
  
; dbms policy file for Instant Messaging ‘friends’ database
+
<code>
; 87654321.spd
+
; dbms policy file for Instant Messaging ‘friends’ database
[database]
+
; 87654321.spd
; friends are considered to be user data. The tables containing
+
; contact information will be policed on these default policies
+
[database]
read
+
; friends are considered to be user data. The tables containing
capability = ReadUserData
+
; contact information will be policed on these default policies
write
+
read
capability = WriteUserData
+
capability = ReadUserData
schema
+
write
; only the server process can change the schema
+
capability = WriteUserData
SID = 89ABCDEF
+
schema
[table]
+
; only the server process can change the schema
; this is a table relating to friends, and contains data
+
SID = 89ABCDEF
; private to the server process, for example, local UIDs etc
+
; the policies below strengthen the default policies
+
[table]
name = metadata
+
; this is a table relating to friends, and contains data
; only server process can read or write metadata
+
; private to the server process, for example, local UIDs etc
read
+
; the policies below strengthen the default policies
SID = 89ABCDEF
+
name = metadata
write
+
; only server process can read or write metadata
SID = 89ABCDEF
+
read
 +
SID = 89ABCDEF
 +
write
 +
SID = 89ABCDEF</code>
  
 
There is no concept of ownership in the context of a policy file, and
 
There is no concept of ownership in the context of a policy file, and
Line 843: Line 833:
 
separate corporate directory.
 
separate corporate directory.
  
It is important to note here that access policies are only read from
+
{|border="1" cellspacing="0" cellpadding="8"
ROM at the time of writing. This restriction is likely to be lifted in
+
|It is important to note here that access policies are only read from ROM at the time of writing. This restriction is likely to be lifted in the future.
the future.
+
|}
  
In order tomake the creation and manipulation of secure shared databases
+
In order to make the creation and manipulation of secure shared databases
 
available to third parties, a mobile phone manufacturer could choose
 
available to third parties, a mobile phone manufacturer could choose
 
to embed a ‘default’ policy file in ROM that polices access on user
 
to embed a ‘default’ policy file in ROM that polices access on user
 
capabilities:
 
capabilities:
  
; default security policy file for third party use
+
<code>
; 12345678.spd
+
; default security policy file for third party use
[database]
+
; 12345678.spd
read
+
capability = ReadUserData
+
[database]
write
+
read
capability = WriteUserData
+
capability = ReadUserData
schema
+
write
capability = WriteUserData
+
capability = WriteUserData
 +
schema
 +
capability = WriteUserData</code>
 +
 
 
Given that the UID for the policy file is published, third parties could
 
Given that the UID for the policy file is published, third parties could
 
then use the DBMS secure shared database extension API to create their
 
then use the DBMS secure shared database extension API to create their
 
own database with a policy based on this file:
 
own database with a policy based on this file:
RDbs dbms;
+
 
User::LeaveIfError(dbms.Connect());
+
<code>
CleanupClosePushL(dbms);
+
RDbs dbms;
RDbNamedDatabase file;
+
User::LeaveIfError(dbms.Connect());
file.Create(dbms, _LIT(“c:myDb.db”), _L(“secure[12345678]”));
+
CleanupClosePushL(dbms);
CleanupClosePushL(file);
+
RDbNamedDatabase file;
...
+
file.Create(dbms, _LIT(“c:myDb.db”), _L(“secure[12345678]”));
 +
CleanupClosePushL(file);
 +
...</code>
  
 
Obviously a table-level policy is not possible in this case, since you must
 
Obviously a table-level policy is not possible in this case, since you must
Line 891: Line 886:
  
 
Files can be shared in this way using the following family of methods
 
Files can be shared in this way using the following family of methods
published on the RFile API:
+
published on the {{Icode|RFile}} API:
  
RFile::TransferToClient() and RFile::AdoptFromClient()
+
<code>
RFile::TransferToServer() and RFile::AdoptFromServer()
+
RFile::TransferToClient() and RFile::AdoptFromClient()
RFile::TransferToProcess() and RFile::AdoptFromProcess()
+
RFile::TransferToServer() and RFile::AdoptFromServer()
 +
RFile::TransferToProcess() and RFile::AdoptFromProcess()</code>
  
 
These methods allow transfer of a file handle using the client server IPC
 
These methods allow transfer of a file handle using the client server IPC
Line 901: Line 897:
  
 
We said that the mode of a file cannot normally be changed. The only
 
We said that the mode of a file cannot normally be changed. The only
change allowed is to toggle between the modes EFileShareExclusive
+
change allowed is to toggle between the modes {{Icode|EFileShareExclusive}}
and EFileShareReadersOnly, and this is only allowed under
+
and {{Icode|EFileShareReadersOnly}}, and this is only allowed under
 
limited circumstances that would not compromise the use of the file by
 
limited circumstances that would not compromise the use of the file by
 
the other process you are sharing with.
 
the other process you are sharing with.
Line 911: Line 907:
 
to share that file and no other. The IM server code might look as follows:
 
to share that file and no other. The IM server code might look as follows:
  
void CIMServer::HandleNewAttachmentL(const TDesC& aName)
+
<code>
{
+
void CIMServer::HandleNewAttachmentL(const TDesC& aName)
// create a new session to the file server specifically for
+
  {
// sharing just the attachment
+
  // create a new session to the file server specifically for
RFs fs;
+
  // sharing just the attachment
User::LeaveIfError(fs.Connect());
+
  RFs fs;
CleanupClosePushL(fs);
+
  User::LeaveIfError(fs.Connect());
// allow session to be shared by receiving process
+
  CleanupClosePushL(fs);
User::LeaveIfError(fs.ShareProtected());
+
  // allow session to be shared by receiving process
// open file where data has been previously stored
+
  User::LeaveIfError(fs.ShareProtected());
RFile attachment;
+
User::LeaveIfError(attachment.Open(fs, aName, EFileRead));
+
  // open file where data has been previously stored
CleanupClosePushL(attachment);
+
  RFile attachment;
RProcess handler;
+
  User::LeaveIfError(attachment.Open(fs, aName, EFileRead));
User::LeaveIfError(handler.Create(_LIT(“Handler.exe”),
+
  CleanupClosePushL(attachment);
KNullDesC));
+
  RProcess handler;
CleanupClosePushL(handler);
+
  User::LeaveIfError(handler.Create(_LIT(“Handler.exe”),
// transfer file to process
+
                                            KNullDesC));
152 SHARING DATA SAFELY
+
  CleanupClosePushL(handler);
User::LeaveIfError(attachment.TransferToProcess(handler, 1, 2);
+
TRequestStatus status;
+
  // transfer file to process
handler.Rendezvous(status);
+
  User::LeaveIfError(attachment.TransferToProcess(handler, 1, 2);
if (KRequestPending != status.Int())
+
  TRequestStatus status;
{
+
  handler.Rendezvous(status);
handler.RendezvousCancel(status);
+
  if (KRequestPending != status.Int())
handler.Kill(0);
+
    {
User::Leave(status.Int());
+
    handler.RendezvousCancel(status);
}
+
    handler.Kill(0);
handler.Resume();
+
    User::Leave(status.Int());
User::WaitForRequest(status);
+
    }
User::LeaveIfError(status.Int());
+
  handler.Resume();
// safe to close all handles including shared session
+
  User::WaitForRequest(status);
CleanupStack::PopAndDestroy(3, fs);
+
  User::LeaveIfError(status.Int());
}
+
 +
  // safe to close all handles including shared session
 +
  CleanupStack::PopAndDestroy(3, fs);
 +
  }</code>
  
 
Notice that the IM server opens the attachment in read-only mode
 
Notice that the IM server opens the attachment in read-only mode
Line 955: Line 954:
 
number, for instance. Finally, we see that the session is open only for as
 
number, for instance. Finally, we see that the session is open only for as
 
long as required for the handler process to receive the handle, and no
 
long as required for the handler process to receive the handle, and no
longer. This is achieved with the Rendezvous code, which allows the
+
longer. This is achieved with the {{Icode|Rendezvous}} code, which allows the
 
IM server to be notified when the handler has received the attachment.
 
IM server to be notified when the handler has received the attachment.
 
Here is the corresponding code in the handler process:
 
Here is the corresponding code in the handler process:
  
LOCAL_C void MainL()
+
<code>
{
+
LOCAL_C void MainL()
// adopt the file
+
  {
RFile attachment;
+
  // adopt the file
User::LeaveIfError(attachment.AdoptFromCreator(1, 2));
+
  RFile attachment;
CleanupClosePushL(attachment);
+
  User::LeaveIfError(attachment.AdoptFromCreator(1, 2));
//signal transfer complete
+
  CleanupClosePushL(attachment);
RProcess::Rendezvous(KErrNone);
+
// use the file
+
  //signal transfer complete
...
+
  RProcess::Rendezvous(KErrNone);
// close the file
+
CleanupStack::PopAndDestroy(&attachment);
+
  // use the file
}
+
  ...
GLDEF_C TInt E32Main()
+
  // close the file
{
+
  CleanupStack::PopAndDestroy(&attachment);
__UHEAP_MARK;
+
  }
CTrapCleanup* cleanup = CTrapCleanup::New();
+
CActiveScheduler* scheduler = new CActiveScheduler;
+
GLDEF_C TInt E32Main()
TInt ret = KErrNoMemory;
+
  {
if (cleanup && scheduler)
+
  __UHEAP_MARK;
SUMMARY 153
+
  CTrapCleanup* cleanup = CTrapCleanup::New();
{
+
  CActiveScheduler* scheduler = new CActiveScheduler;
CActiveScheduler::Install(scheduler);
+
  TInt ret = KErrNoMemory;
}
+
  if (cleanup && scheduler)
delete scheduler;
+
    {
delete cleanup;
+
    CActiveScheduler::Install(scheduler);
__UHEAP_MARKEND;
+
    }
return ret;
+
  delete scheduler;
}
+
  delete cleanup;
 +
  __UHEAP_MARKEND;
 +
  return ret;
 +
  }</code>
  
 
The client can use the file through a hidden shared file server session
 
The client can use the file through a hidden shared file server session
inside the RFile object, removing the need for a separate RFs
+
inside the {{Icode|RFile}} object, removing the need for a separate {{Icode|RFs}}
 
object to be maintained. This session is automatically closed when
 
object to be maintained. This session is automatically closed when
RFile::Close() is called on the attachment.
+
{{Icode|RFile::Close()}} is called on the attachment.
  
 
The trust relationship between the two processes is evident here once
 
The trust relationship between the two processes is evident here once
Line 1,006: Line 1,008:
 
the data.
 
the data.
  
Characteristic Persistency Volatility Size Exchange
+
{| border="1" cellspacing="0" cellpadding="6"
Service
+
|+'''Table 7.3''' System Data Services Characteristics
Publish and
+
!rowspan="2"|Service!!colspan="4"|Characteristic
subscribe
+
|-
Transient Any Prefer <512
+
! Persistency !! Volatility !! Size !! Exchange
bytes
+
|-
Asynchronous
+
|'''Publish and subscribe'''|| Transient|| Any|| Prefer <512 bytes|| Asynchronous
Central
+
|-
repository
+
|'''Central repository'''|| Persistent|| Non-volatile|| <2 KB|| Asynchronous
Persistent Non-volatile <2 KB Asynchronous
+
|-
DBMS Persistent Non-volatile Any Asynchronous
+
|'''DBMS'''|| Persistent || Non-volatile|| Any|| Asynchronous
File handles Transient Non-volatile Any Synchronous
+
|-
Custom server Any Any Any Synchronous
+
|'''File handles'''||  Persistent|| Non-volatile|| Any|| Synchronous
 +
|-
 +
|'''Custom server'''|| Any || Any|| Any || Synchronous
 +
|}
  
 
=Summary=
 
=Summary=
Line 1,044: Line 1,049:
 
mediated access to your data for trusted clients is paramount.
 
mediated access to your data for trusted clients is paramount.
  
[[Category: book]]
+
{{SymbianOSPlatformSecurity_Copyright}}

Latest revision as of 12:53, 17 January 2011

by Will Palmer Reproduced by kind permission of John Wiley & Sons. Prev.   Contents   Next

Introduction to Sharing Data

This chapter presents the key questions you need to ask – and some possible answers – to share your data in a secure way with Symbian OS platform security. It also shows you techniques you can use to implement data sharing in the Symbian operating system. Files and other resources were previously freely accessible to all running processes; this has led in some cases to bad modeling and design, to shortcuts, and, of course, to the creation of malware. With the advent of platform security this is no longer the case – access to files and other resources is now strictly controlled and managed, so developers need to consider how to share and access data securely.

We will consider all data that is accessed by more than one process. Although sharing data might involve, for example, several messaging applications accessing data from a message server, it also includes participating in a backup operation, or data being remotely provisioned through a device-provisioning server.

You should be sure of your need to share data. If your application’s data does not need to be shared, then it is safest to hide it by default. You do this by putting it into your process’s private directory, without implementing any accessor methods – and then you’ll have no need for this chapter.

Considerations in Sharing Data

When sharing your data with more than one process, there are a number of key questions to consider. These will all be developed in further sections.

Do you need to protect the integrity of your data?

You may need to guard against abnormal behavior of your application or of other applications that are a client of your data. Although you should always make your application robust in the face of unexpected or corrupted data, you may have data whose integrity is relied upon by a client to perform a sensitive action – for example, a certificate or secure URL.

Do you need to protect the confidentiality of your data?

Your data may need to be guarded against ‘prying eyes’ – for example, if you are storing a password to use for remote access. You might choose never to reveal the plain text of that password, or perhaps to allow the password to be retrieved only if the user supplies a PIN.

What attacks should you care about?

There are several types of attack on data, both on its confidentiality and its integrity. Some of these we have seen exploited in releases of Symbian OS prior to the enhancement of platform security, but new measures are provided to protect against all of them.

When should your data be available?

Do you want to share your data synchronously or asynchronously? You may want your data to be accessible even if your process is not running. You usually do this by making use of Symbian OS system services.

How much data should you share?

You should examine the granularity of your data below the file level. Often data is a collection of information, and you may want to police the elements separately.

There are other important considerations that are more implementation specific, and relate to ‘best practice’ when developing your application. For example, if you are implementing a server, what are the consequences of allowing concurrency of access to your data and how do you permit this to occur; what are the consequences of too weak or too strong an access policy? We will also cover best practice in more detail in our discussion about levels of trust.

Categories of Data

What’s Out of Scope

Data is a very general term, and encompasses anything from messages (signals, semaphores, datagrams) to settings (persistent configuration, transient property) to files (databases, resources, media ‘BLOBs’).

We restrict discussion in this chapter to settings and files. The primary mechanism for inter-process message passing is the Symbian OS client–server mechanism, discussed in Chapter 5. Other mechanisms for communicating information between processes, such as shared memory, semaphores and message queues, are also touched on in that chapter. Similarly, getting other processes to undertake tasks on your behalf – for example, the Task Scheduler and SendAs server – is outside the scope of what we discuss here.

What’s Out of the Platform’s Control

It is worth briefly touching on this topic, in order to clearly understand where the boundaries are. This is important to enable us to look at the ‘end-to-end’ security of our data. We have already mentioned in Chapter 1 how controls at the network boundary are becoming inadequate because of the trend towards seamless information flow between networks. There is, therefore, a need for a mobile phone to protect the information on it in a robust way, and also to protect any networks that it connects to.

A secure platform allows you to protect your data according to a policy that you choose. Capabilities that allow the use of local and remote network services are carefully assigned to trusted processes to control whether an application can communicate sensitive data across a network, but platform security does not control where a process sends data to or receives data from. We must rely on other technologies to provide end-to-end communications security – for example, a secure data channel protocol such as TLS/SSL, with authentication at each end of the link using digital certificates. By assigning a level of trust to a particular process, we have determined the policy for the type of information it can send from the mobile phone – for example, address book contact information that is synchronized to the PC. The synchronization process has capabilities ReadUserData and LocalServices, and we trust it to send on request only the subset of data that is policed by this capability.

We also cannot control how the data is used once it is received by an external entity. There can be no guarantee that the external entity will respect, or even understand, the security policy applied to the data. Once the data is off the Symbian OS mobile phone, we have no control over the level of privacy applied to the data.

Consider the ramifications of providing a backup mechanism in Symbian OS. Once the backup data is on the remote device – the PC, for example – it is the responsibility of the owner of the device to ensure that the backup data is not tampered with. On restore, Symbian OS can, of course, detect any evidence of tampering using hashing, but cannot prevent it. This is similar to the way it deals with removable media (see Chapter 8). Additionally, the backup architecture provides hooks that mobile phone manufacturers can use, at their discretion, to implement encryption of the backup data to assist with confidentiality. The story remains the same though – once data is off the mobile phone it is out of our control.

Persistency

Persistency of data describes the length of time for which data exists on the mobile phone. Data may either be transient – held in temporary memory and not surviving a reboot – or persistent – written to disk and, therefore, surviving a reboot. As examples of these different types, consider an instant messaging (IM) application. This application might have transient data (friends who are currently online, location information) that exists, at most, for the lifetime of the application, and persistent data (a list of friends, the configuration of the user interface) that is written to disk for use when the application restarts.

Once created, persistent and transient data may have a constant value – for example, mobile phone attributes such as manufacturer and firmware version. Resource files, such as fonts and branding elements (bitmaps, ring tones, wallpapers, etc.), are also in this category. Data may also be dynamic (i.e. changing in value), such as a setting indicating whether the Bluetooth service is available, or indicating the currently active window.

Data Added by the User

Perhaps the most common use of the term ‘data’ on a mobile phone is when it is applied to persistent information that a user stores. We refine this by defining ‘user data’ as that which is personal information stored by a user. Address book contacts and calendar entries are examples of user data and Symbian OS defines capabilities for protecting exactly this type of data. Contrast this with data such as downloaded ring tones – this is a type of data that a user might add to the mobile phone, but it is not regarded in platform security terms as user data.

Data added by the user may be considered as two types – public, which the user has no problem with any person reading, and private, which the user does not want any unauthorized person or process reading. Symbian OS platform security does not differentiate between these, since it is content-dependent – data added by the user may be either public or private user data.

As a result of this, it may be necessary to employ other protection techniques in the case of private user data. A piece of text in a notebook application, for example, might be something as innocuous as a scribbled note to oneself or it might be a debit card PIN. In this case it is the responsibility of the application managing this data to enable protection mechanisms such as encryption and password protection. This protection may simply be achieved at the user interface level; an example of this is a calendar entry that might be a public holiday or a medical appointment.

User data capabilities are usually policed symmetrically – that is, both reading and writing the data requires a capability. User data does not have to be policed symmetrically though; a media server is an example of this, where the server might be quite happy for anyone to read files in order to play them, but it certainly doesn’t want anybody writing to them, potentially corrupting the files. Note also that, in this example, the policing of an application wishing to add files would probably be applied differently too, but this would depend on the content of the data.

Data Resident as Part of the Mobile Phone

We describe this as ‘system data’ – data that is vital to the integrity of the system, and that, if compromised, could cause a network or device service to fail. Examples of this type of data are network availability (a transient property), network access point (persistent) and IMEI number (persistent and constant value). The hardware abstraction layer (HAL) in the OS kernel contains system data, some of which has a constant value (ECPUSpeed), and some of which is variable (EBacklightState).

Here though, the type of data does not automatically determine the capabilities it will be policed on – system data capabilities are often non-symmetrical. Write access might be policed by the SID of a system process, in the case where there should only be one process updating the value. (This is generally preferable as it reduces the need for more processes to possess a system capability – this is discussed further in the next section). Read access, in many cases, does not require any capability – anyone can read the data – because confidentiality is not the prime issue, as the description of this type of data shows. An example of this is network signal strength or current call status. In the small number of cases where confidentiality is required in addition to integrity, read access is policed with ReadDeviceData and we term this ‘device data’ since the policy is then symmetrical. An example of this would be an IMAP server address.

Compound data often has both user and system parts – for example, a user account for a SyncML server. The server’s address is clearly system data, as changing it would cause the service to fail; however the display name for the account is considered public data.

Capability Summary

Here we summarize the policy that you would apply to the different types of data that we have discussed in this section. The storage mechanism has no bearing on the policy.

Table 7.1 Data Access Capabilities
Type of Data Confidentiality Required: access policy Integrity Required: access policy
User data ReadUserData or none WriteUserData
System data None WriteDeviceData, SID of process that modifies the value
Device data ReadDeviceData WriteDeviceData

Deciding the Level of Trust

So you have some data that you want to share – how do you share it safely? You must decide the level of trust to apply. Thismeans undertaking a threat analysis. Analyze the value of your assets (the data), identify the attack surface, consider the threats to those assets, and then decide on an appropriate measure.

Symbian’s platform security architecture is designed to empower the developer to decide the level of trust to apply. In practical terms this means the capabilities to assign to the policy for sharing your data. Note that the ability to write data can encompass creating, adding and deleting data as well. It may well be that you need to police access to these differently, depending on the content of your data. For example, a process that wishes to log events may treat adding entries simply as ‘noise’ but deleting entries as removing an audit trail.

It is sometimes easier to apply an inverse test and ask, ‘Who do I not want to share my data with?’. This might help you to decide how much you would care if the data was corrupted or deleted, either intentionally or unintentionally, or stolen by an unauthorized entity. If you applied the wrong capability policy, could a phone number be modified to a premium rate number, for example? You must also think about the consequences to subscribers of your data – what is at stake for them? In fact, who are the clients of your data?

Bear in mind that when we asked users what security they expect from a mobile phone, one answer repeatedly made was ‘I want my private data to stay private’ (as reported in Symbian OS Internals [Sales 2005]).

Identification for Authorization

There are sometimes practical requirements for access control based on identity, and so we have chosen to support this as a complement to the authorization model. You may choose to mediate access using the SID or the VID of the process because you are only concerned with identity.

Policing your data using the VID may be considered less secure than using the SID, as the scope of processes with a particular VID is ‘open-ended’ – new software may be installed that has that VID, which may introduce new security problems. By contrast, only one EXE on the mobile phone can possess a particular SID, so the access control is more precisely defined. When using the VID, it may be useful to combine it with a capability check, in order to constrain further the potential scope of access being granted. The best approach, in this case, is to keep it simple. In many cases policing by the SID or the VID can be considered overengineering, and by restricting access you could reduce the mass-appeal of your software.

Getting the Right Balance

In defining the policy for your data, you should consider that too strong a policy could be as bad as too weak a policy. The authorization model relies on the correct use of capabilities to be effective.

If you don’t protect your data sufficiently you are at greater risk of an attack. If you protect your data too much you may create side effects:

  • You limit the number of applications that can use your service, so you decrease its potential market value. Clients will have to pass more stringent tests to obtain this level of trust.
  • You weaken the protection of other data policed by this capability by increasing the number of processes requiring it. We call this ‘dilution of capabilities’.

Think of it in terms of ‘communities’ of services and data. The level of trust required to get access to the community protected by a capability is in practice likely to be reduced to that required for the least sensitive service or piece of data.

Attacks on Data and Countermeasures

Having created a threat model you will have a good idea of the kind of attacks that could occur on your data. We categorize the most common forms of attack below, and focus primarily on intentional attacks directed against our data assets. Unintentional compromises, however, can be just as damaging unless we implement robust behavior.

We include some common threats to data storage and management services, since many problems occur as a result of concurrency issues – multiple clients accessing data at the same time [Anderson 2001].

We also discuss specific countermeasures for each type of attack. The platform security architecture gives you the primary countermeasures to threats against your data. In particular, data caging and memory protection, through process isolation, are integral countermeasure tools that you get ‘for free’. However there are two things that you must do:

  • Implement the countermeasures, made available through the platform security architecture that you have decided on to harden your software against attack.
  • Apply ‘best practices’ as a complement to platform security, to make your software robust in the face of unexpected data. These are critical elements of security engineering in diminishing the threat of attack.

Unfortunately, many instances of compromised data occur as a result of the unintentional behavior of the clients of that data. As a client of shared data, you have responsibilities too. Capability implies trust – trust not to leak data that you have privileged access to. This means that you must ensure that you do not pass this information on to any other process without first checking that it has the appropriate capabilities. In accepting responsibility for privileged access, you must also accept responsibility for policing access.

Data Capture

This is an attack on confidentiality and is the most commonly considered attack on data. Here are some ways in which it can occur:

  • Malware tricking a process into giving it data – for example, by

intentionally passing inappropriate data to glean sensitive information from any output. Alternatively it could use brute force – for example, by cracking a password.

  • Snooping on data passed between two legitimate entities (man-inthe- middle). Temporary files and public memory spaces are common attack vectors.
  • Unintentionally giving access to files, or data within them, that should not be shared. Often data is part of a collection of information. It may be a set of elements in a table, lines in a file, a typed list of elements, or a set of properties of a class. Sharing more data than you need to leaves that data vulnerable to attack. Log files are an obvious example here, especially if they are recorded to a public location.

Countermeasures

  1. Place your sensitive persistent data in the private data cage of your process, and keep your sensitive transient data within its private memory space.
  2. Mediate read access to your data by policing APIs exported by your process.
  3. Use a system service to mediate read access on your behalf, and register a read policy with it for your data. Your data is hidden within the system service’s data cage or process memory space.
  4. Share individual files from your data cage with trusted processes using shared handles.
  5. Identify and implement different read policies, where necessary, for collections of data. Consider the individual elements of the collection and only share what is necessary.

Best practices

Some best practices to help keep data secure from prying eyes are:

  1. Temporary files are often a loophole in security – don’t use a public store to temporarily hold sensitive data derived from the original.
  2. Don’t write data belonging to your own process to a public log.
  3. Don’t write another application’s data to a public log.
  4. Protect user-added data with sensitive content with passwords or encrypt the data.
  5. When sharing files from your data cage, open only the files you wish to share and no others. Any files that are open may be accessible by the receiving process through the shared file session. Close the session at the first opportunity after the file handle has been received by the process you are sharing with.
  6. Where possible, minimize the amount of time for which data is shared.

Tampering

This is an attack on the integrity of data and, where system or device data is involved, on the integrity of the mobile phone itself. Here are some ways in which it can occur, some reasons and some effects:

  • Most importantly, the attack could be launched to cause instability through corrupted data. This might result in a process crash, or stopping the mobile phone from booting.
  • It may be launched to coerce the owner into undertaking an alternative path of action.
  • It may lead to service denial – for example, if dialup connection information is altered.
  • It may cause the user to unwittingly spend money – for example, by altering a phone number to a premium rate one.
  • It may lead to data capture, if connection information is altered.
  • Data on removable media is at high risk from this kind of attack – as we have already noted, this is out of our control when the media is removed from the mobile phone.
  • Some attacks of this kind are specific to server processes that allow concurrency of access. These occur when inconsistent updates are performed on dependent compound data. There is a risk of being left in an unknown state unless atomic updates are executed.

Countermeasures

  1. Place your sensitive persistent data in the private data cage of your process, and keep your sensitive transient data within its private memory space.
  2. Mediate write access to your data by policing APIs exported by your process.
  3. Use a system service to mediate write access on your behalf, and register a write policy with it for your data. Your data is hidden within the system service’s data cage or process memory space.
  4. Share individual files from your data cage with trusted processes using shared handles.
  5. Take advantage of the static access policy that is applied to the special directory \resource for your resource files. This directory allows you to share your resources publicly but without compromising their integrity. Essentially it is a read-only directory for non-TCB processes. Examples of data you might install here are bitmaps, fonts, RSC and help files.

Best practices

  1. Make your process fault tolerant – that is, resistant to corrupted or unexpected data. Create a recovery strategy for all the situations you have identified in your threat model. This may be as simple as resetting the data back to a ‘default’ configuration for corrupted backup data. Choose a resilience strategy that is both simple and effective for your process, and also right for the type of data in question. If you are implementing a media player, you are likely to be accepting data from off the mobile phone (OTA or removable media). If such a file were corrupt you would simply not play it.
  2. You may refuse unsolicited data but instead only use data that has been installed through the Software Install process. You can do this by not implementing support for a \import directory in your private data cage – see Chapter 8 for more information on import directories.
  3. Return errors to clients of your data in a timely fashion, but make sure that a client can process the error. For example, you must not return an error for a method such as CancelTransaction().
  4. Threats to server processes associated with inconsistent updates can be mitigated by using a locking transaction model. However, we do not recommend this – instead build this into your recovery strategy. For example, the use of client-side caching of data is advocated in Symbian OS C++ for Mobile Phones [Harrison 2003] – this could be used to roll back to a consistent state.

Denial of Service

This is an attack on availability of data and is especially important to address for the system services presented next in this chapter. Here are some ways in which it can occur:

  • Changing a setting, resulting in the user being deprived of a service, such as a setting on a POP account stopping a user from picking up email.
  • Removal of an application’s data file resulting in an application not running.
  • Sending data too large to be handled by the receiving process – resulting in buffer overflow.
  • Causing a priority inversion – an attack on a server process – where a high-priority thread waiting on that service fails to run because a low-priority thread has locked the resource it wishes to access. A resource can be locked for an extended period of time, for example, if a large transaction takes place (or indeed if a locking transaction never completes), or if frequent and extensive searches through the data are made.

Countermeasures

  1. Place your sensitive persistent data in the private data cage of your process and keep your sensitive transient data within its private memory space.
  2. Police the transaction APIs correctly on your server process to guard against denial of service through locking.

Best practices

  1. Make your process fault tolerant and create a good recovery strategy.
  2. Implement a ‘non-serialized optimistic’ transaction model on your server process in order to achieve high concurrency of access. This model allows any number of clients to start a transaction (optimistic) at any time (non-serialized), which eliminates the threat of blocking access to shared data.

Physical Loss and Damage

Lastly, there is, of course, what we might consider as the biggest threat against data by users themselves – data being lost through losing or breaking a mobile phone.

Best practices

Recovery of lost data can be achieved if processes back up their data. You should consider using the Symbian OS secure backup service – being robust in this way will certainly make your application more attractive to the user. Another way of backing up data is through synchronization (for example, SyncML), although this has the added complication of the remote software (server) needing to understand the MIME type of your data.

Threats and Countermeasures Summary

Here we summarize the threats and their countermeasures that we have discussed in this section. Abbreviations used in the table are as follows: data capture (DC), tampering (TA), and denial of service (DoS).

Table 7.2 Threats and Countermeasures
Threat scenario and type Countermeasure
Tricking of APIs by malware (DC) Data cage all sensitive data, or keep in private memory space
Snooping (DC) Data cage and implement API read policy (use system service if practical) Use shared file handles
Unintentionally allowing access (DC) Implement read policies at the right level of granularity
Modification of data to cause unexpected behavior, including failing to execute (TA, DoS) Data cage and implement API write policy (use system service if practical)

Use shared file handles Use \resource directory for your resources

Altering dial-up information (TA, DoS, DC) Data cage and implement API write policy
Inconsistent update made (TA, DoS) Police transactional APIs accordingly
Causing a buffer overflow (DoS) Implement fault tolerance (best practice only)
Causing a priority inversion or locking of a resource (DoS) Police (transactional) APIs accordingly

Using System Services

We now look at how you choose the right mechanism for sharing your data. We recommend that you use existing system services where possible, unless:

  • your security policy does not fit these services
  • your data should only be accessible when your process is running
  • your data type is not supported.

In this case you should implement a custom server to tailor the shared service to your needs (see Chapter 5). This may be appropriate for BLOBs, for example, such as media files, for which there is no system service at the time of writing.

System services that are currently available for you to share your data safely are:

  • publish and subscribe
  • DBMS
  • file handles.

We will discuss the security features of these services and show how to use them. Additionally, we will look at security in the central repository – a system service that has restrictions on who can use it, but we will look at how you can make use of it. Lastly, we will touch on a few other mechanisms that are pertinent to this topic, and review the implications of their use.

Publish and Subscribe

Publish and subscribe is a state-oriented service for asynchronous distribution of information where the latest value of a setting is the only one relevant. We term each setting held in this service a property. Key functional points are:

  • It provides a means to store and broadcast transient data at run time.
  • It can provide a run-time data cage into which each process can publish its properties, providing protection from spoofing or denial of service.
  • Under certain circumstances it provides bounded execution time for critical tasks that require real-time guarantees. Guarantees are made for:
    • publishing a property of up to 512 bytes in length via a handle, if the new data length does not exceed a buffer size that you can pre-allocate
    • reading the value of a property of up to 512 bytes in length using a handle to the property.

The run-time data cage is the point of interest in platform security terms.

Here is the prototype for defining a property:

IMPORT_C static TInt Define(TUint aKey, TInt aAttr,
                const TSecurityPolicy& aReadPolicy,
               const TSecurityPolicy& aWritePolicy,
                             TInt aPreallocated=0);

When a process defines a property it is stored in a category with a value equal to the SID of the process. No other processes can define a property in this keyspace, so the property can’t be spoofed – the net effect being a run-time data cage. At the point of definition, the process must also supply a read and write policy, which allows the service to limit access to trusted clients you have specified.

Note that the lifetime of the property defined in the service is not necessarily linked to the lifetime of the defining process. The property will exist until either the mobile phone is switched off or the defining process deletes it. This provides flexibility in how long your shared data is available. It could be:

  • for the length of time that your process is running (for example, a state flag during a task execution phase)
  • for the lifetime of your process (for example a ‘friend online’ Instant Message signal)
  • or, from the point that it is defined to when the mobile phone is switched off (for example, system properties such as network signal availability and battery strength).

Consider an example from an instant messaging application, whose design is split between a server and a UI application (see [Harrison 2003]) to allow, among other things, different UI applications to be built. A function of this application might be to notify a user when a ‘friend’ goes online or offline. This could be achieved by the server defining a property ‘new friend event’:

static const TInt32 KIMServerSID = 0x89ABCDEF;
static _LIT_SECURITY_POLICY_S0 (KFriendsListChangePolicy,
                                KIMServerSID);

void CIMServer::ConstructL()
  {
  ...
  User::LeaveIfError(
             RProperty::Define(KKeyFriendsListHasChanged,
                                         RProperty::EInt,
                                       KAlwaysPassPolicy,
                              KFriendsListChangePolicy));
  ...
  }

There are a couple of interesting points that come out of this. Firstly, we simply define a property to publish the fact that the friends list has changed, rather than trying to say ‘you have a new friend’. If you look back to our definition of ‘Publish and Subscribe’ you can see why – we state that ‘the latest value of a setting is the only one relevant’. This is because it cannot be guaranteed that every event will be received by a subscriber. Consequently your behavior as a subscriber should always be to react based on the current value, not a change in state.

The following code snippet shows how the server publishes to the property when a friend’s online status changes:

void CIMServer::OnCommunicationEventL(TEvent aEvent,
                       TEventData aBuf, TInt aError)
  {
  switch (aEvent)
    {
    case EFriendOnline:
    case EFriendOffline:
      {
      UpdateFriendsListL(aBuf);
      User::LeaveIfError (RProperty::Set(KIMServerSID,
                            KKeyFriendsListHasChanged,
                               iFriendsList.Count()));
      }
    ...
    }
  }

Consider the client code for the UI application. First, in its ConstructL() the application creates an instance of an active object that tracks ‘friends online change’ events from the server:

void CIMApplicationUI::ConstructL()
{
// connect to the server
User::LeaveIfError(iIMSvr.Connect());
// create the active object that tracks events
iWatcher = CFriendEventWatcher::NewL(*this);
...
}

The following code shows how the active object handles and acts on these server events:

void CFriendEventWatcher::ConstructL()
  {
  // attach to the property
  User::LeaveIfError(iProperty.Attach(KIMServerSID,
                       KKeyFriendsListHasChanged));
  CActiveScheduler::Add(this)
  // initial subscription and process current property value
  RunL();
  }

void CFriendEventWatcher::RunL()
  {
  // re-subscribe to help prevent missing notification of updates
  iProperty.Subscribe(iStatus);
  SetActive();
  
  // test availability of property
  TInt numfriends;
  TInt err = iProperty.Get(numfriends);
  if (KErrNotFound == err)
    {
    // server is not running
    User::Leave(KErrIMServerNotRunning);
    }
  else if (KErrNone == err)
    {
    if (numfriends)
      {
      // enable friends online icon
      }
    else
      {
      // disable friends online icon
      }
    }
  ...
  }

Here we are checking the latest value in order to enable or disable a ‘you have friends online’ icon. If a friend came online at the same time as another went offline, there would be two published events – however, the UI application might only receive one. This is why the event could not be an increment (‘new friend online’) in its own right. Imagine a toggle switch property – if a subscriber missed one event and didn’t check the value, it would have its logic reversed.

The second interesting point is with regard to the ‘friends online’ icon. This is a good technique for avoiding polling overhead – an application could ask the server for the complete list of friends each time it is notified, however, if it only does this in response to a ‘show friends’ command, processing is minimized.

Finally, note that the UI application does not need any capabilities to read this property as we consider it public information – we only protect what needs to be protected – however, only the IM server can write a value to it. This is an example of non-symmetrical policing.

Good practices

Multiple publishers of values to a property are generally discouraged. There are two reasons for this. Firstly, it encourages the, potentially unnecessary, proliferation of ‘write policy’ capabilities. Secondly, it could give rise to race conditions, especially with respect to Booleans or bit masks. An exception to this might be publishing to properties that represent events where the subsequent processing of subscribers is simply in response to the event.

Client code should not perform substantial processing on each notification for properties that change value frequently. Publishing to a property could potentially lead to multiple clients servicing the notification – if this property’s value has a high frequency of change, it can lead to a large amount of processing. It is, therefore, a good idea to document the expected update frequency of your property.

Sometimes data represents the current state of part of a mobile phone. An example might be the current volume level of the speaker, the value of which may be highly volatile while it is being changed through the user interface. The publish and subscribe service should be used for just such transient data. Note that once the target volume is reached (it’s final state), the property ceases to be volatile. In this case the value is written to disk in order to save the initial state of the volume should the mobile phone be rebooted or media application restarted.

Central Repository

The central repository provides a centralized service for safe, secure persistence of shared settings. It is implemented in the OS to enhance ease of programming through a unified settings API, to promote a common policy for platform security, and to allow simpler customization, factory reset and data backup of the mobile phone. Key functional points are:

  • It uses simple partitioning of data using a UID-pair to create a two-tier structure: up to 232 top-level ‘keyspaces’ or repositories, within which up to 232 settings of any simple type, may be defined.
  • It provides the ability to define separate read and write access policies to settings within a keyspace at three levels: a default policy for the whole keyspace, a policy for a range of settings and a policy for individual settings.
  • It provides the means to change the read and write access policy of a setting at run time.
  • It provides non-serialized optimistic transactional support for reading and writing multiple settings – ensuring consistency between multiple values within a keyspace.

Policies are defined in a keyspace initialization file held in the data cage of the central repository server, and these may reside in ROM, or be installed via a SIS package. A new keyspace may only be created through software install; it cannot be created at run time, which prevents the potential problem of unchecked bloat through badly behaved applications not deleting keyspaces that are no longer used.

It is important to note that the central repository is not generally available for use as a storage mechanism at the time of writing. Third parties with sufficient capabilities can find and read from settings, and be notified of any changes, but cannot write their own changes. This restriction is likely to be lifted in the future.

The INI file may also contain settings and default values for that keyspace. Here is a simple example, an instant messaging server’s initialization file:

# 89ABCDEF.cre
# Instant Messaging Server keyspace

cenrep
version 1

[platsec]
# default capabilities for this keyspace
cap_rd=ReadUserData cap_wr=WriteUserData
# define a range for server private data
0x100 0x200 sid_rd=0x89ABCDEF sid_wr=0x89ABCDEF
# define a range for public data
0x1000 0x1100 cap_rd=AlwaysPass cap_wr=AlwaysPass

[defaultMeta]
0x1000000

[main]
# protected by default capabilities
# autologin: specifies whether to login on startup of application
0x1 int 1
# usesslport: specifies whether to use SSL
0x2 int 0
# anonsearch: specifies whether to undertake anonymous searches
0x3 int

# server private data
# imhostname: host address of server
0x100 string “host1.imserver”
# defport: default port number
0x101 int 5269
# sslport: ssl port number
0x102 int 5223

# account data (device data) - using individual policy
# username
0x200 string “username” cap_rd=ReadDeviceData
cap_wr=WriteDeviceData
# password
0x201 string “password” cap_rd=ReadDeviceData
cap_wr=WriteDeviceData

# public data
# onlineicon: user profile icon
0x1000 string “defUser.gif”
# displayfont
0x1001 string “swissA”
# fontsize
0x1002 int 10
#timeout: timeout value (min) for inactive chat sessions
0x1003 int 10

The ability to define access policies at different levels makes this service very flexible. This is particularly important as you can store up to 232 settings in a single keyspace. Note that the policies are governed by the standard rules applied by the TSecurityPolicy class. The policies at successive levels supersede any more general policy defined, and these cannot be applied or changed dynamically. This does not prevent the policy applied to the setting being changed at run time, as we stated.

In the previous example we defined a range of keys with a read and write access policy equal to the owning process’s SID. The central repository supports the ability to move settings within a keyspace, given that the process that moves the settings has the write capabilities applying to both the source and target keys. In this example, settings could be moved into this key range, effectively hiding them from all but the owning process. This can be used to achieve temporary sharing (or hiding) of data. There is a potential drawback to this mechanism – the potential to ‘downgrade’ the policy on a setting. So, for instance, a client may have added what was considered as user data, and another client makes it available to anyone. Also, the clients of some shared settings may not be robust enough to deal with data they expect to be available suddenly disappearing. The trust relationship between processes sharing settings is evident here, as well as the need for resilience to unexpected events.

The transaction model implemented in the central repository achieves high concurrency – a number of transactions are allowed to be opened on a keyspace, however, the first to commit causes all others to fail with KErrLocked. Consequently, clients are rewarded for keeping their transactions short since they are less likely to fail. Clients that must guarantee success place their transaction in a do-while KErrLocked loop. Concurrency is further guarded by checking that the capabilities of the requesting client were at least equal to the default policy for the keyspace – making sure that people without the ability to read and write settings cannot start a transaction.

DBMS

DBMS is a service that provides a general interface for access to relational databases. The service provides two different implementations: a clientside service and a client–server service. The former gives you DBMS functionality to use within your own data cage and you would police access through your own API. The latter is of more interest in this context, and provides you with a way to share your data asynchronously. Key functional points are:

  • It provides the ability to define cumulative separate read and write access and schema manipulation policies on two levels: a default policy for the database and a policy for individual tables.
  • It provides a lightweight client-side implementation, enabling processes to store data in their own data cage, and police it accordingly.

Databases may be manipulated either through a subset of SQL or through a Symbian OS C++ API. This API has been extended to support creation and manipulation of secure, shared databases and also allows a thread to query the policy applied to a database or table. This can be useful for a middleware server, for example, that provides querying functionality on top of DBMS, and which polices this API according to the data it is acting on in DBMS. However, this will not be a very common pattern – most clients would use the DBMS API directly.

Access to secure DBMS databases is controlled through pre-registered policy files, each of which has a UID, and is applied to the database by its creator. The policy file states the read, write and ‘modify schema’ policies to apply to a database and it can be used to add capabilities for accessing tables. Note that the policies are governed by the standard rules applied by the TSecurityPolicy class and that this table-level security can only strengthen the database policy, rather than override it. Here is an example policy file that an instant messaging server might register to be used to police access to an IM ‘friends’ database:

; dbms policy file for Instant Messaging ‘friends’ database
; 87654321.spd

[database]
; friends are considered to be user data. The tables containing
; contact information will be policed on these default policies
read
capability = ReadUserData
write
capability = WriteUserData
schema
; only the server process can change the schema
SID = 89ABCDEF

[table]
; this is a table relating to friends, and contains data
; private to the server process, for example, local UIDs etc
; the policies below strengthen the default policies
name = metadata
; only server process can read or write metadata
read
SID = 89ABCDEF
write
SID = 89ABCDEF

There is no concept of ownership in the context of a policy file, and hence there is no limit to the number of databases that can use one. This is certainly the case for the Contacts Model, which allows a user to create more than one database – for instance, one for personal contacts and a separate corporate directory.

It is important to note here that access policies are only read from ROM at the time of writing. This restriction is likely to be lifted in the future.

In order to make the creation and manipulation of secure shared databases available to third parties, a mobile phone manufacturer could choose to embed a ‘default’ policy file in ROM that polices access on user capabilities:

; default security policy file for third party use
; 12345678.spd

[database]
read
capability = ReadUserData
write
capability = WriteUserData
schema
capability = WriteUserData

Given that the UID for the policy file is published, third parties could then use the DBMS secure shared database extension API to create their own database with a policy based on this file:

RDbs dbms;
User::LeaveIfError(dbms.Connect());
CleanupClosePushL(dbms);
RDbNamedDatabase file;
file.Create(dbms, _LIT(“c:myDb.db”), _L(“secure[12345678]”));
CleanupClosePushL(file);
...

Obviously a table-level policy is not possible in this case, since you must write the name of the table in the policy file.

File Handles

Symbian OS supports the means for a process to temporarily share a file with another process under controlled conditions. The kernel provides the basic support for handle-sharing across the process boundary, and the file server builds on this to provide specific support for sharing file handles. Some key points to note:

  • The owning process opens a file in a mode that cannot be changed by the receiving process under normal circumstances.
  • The receiving process accesses the file through the shared handle it receives, but does not get access to the shared file’s private directory.
  • The owning process shares a file server session with the receiving process.
  • Revocation of sharing a file is not possible.

Note that file handles are not handles in the sense of a reference to a kernel object, but, instead, they are a unique identifier of an open file within a file server session.

Files can be shared in this way using the following family of methods published on the RFile API:

RFile::TransferToClient() and RFile::AdoptFromClient()
RFile::TransferToServer() and RFile::AdoptFromServer()
RFile::TransferToProcess() and RFile::AdoptFromProcess()

These methods allow transfer of a file handle using the client server IPC mechanism, and also from one process to another.

We said that the mode of a file cannot normally be changed. The only change allowed is to toggle between the modes EFileShareExclusive and EFileShareReadersOnly, and this is only allowed under limited circumstances that would not compromise the use of the file by the other process you are sharing with.

Our example IM server could make good use of file sharing if it receives a file as an attachment during a chat session and needs to hand the file on to an appropriate application or recognizer. The server needs to share that file and no other. The IM server code might look as follows:

void CIMServer::HandleNewAttachmentL(const TDesC& aName)
  {
  // create a new session to the file server specifically for
  // sharing just the attachment
  RFs fs;
  User::LeaveIfError(fs.Connect());
  CleanupClosePushL(fs);
  // allow session to be shared by receiving process
  User::LeaveIfError(fs.ShareProtected());

  // open file where data has been previously stored
  RFile attachment;
  User::LeaveIfError(attachment.Open(fs, aName, EFileRead));
  CleanupClosePushL(attachment);
  RProcess handler;
  User::LeaveIfError(handler.Create(_LIT(“Handler.exe”),
                                            KNullDesC));
  CleanupClosePushL(handler);

  // transfer file to process
  User::LeaveIfError(attachment.TransferToProcess(handler, 1, 2);
  TRequestStatus status;
  handler.Rendezvous(status);
  if (KRequestPending != status.Int())
    {
    handler.RendezvousCancel(status);
    handler.Kill(0);
    User::Leave(status.Int());
    }
  handler.Resume();
  User::WaitForRequest(status);
  User::LeaveIfError(status.Int());

  // safe to close all handles including shared session
  CleanupStack::PopAndDestroy(3, fs);
  }

Notice that the IM server opens the attachment in read-only mode for sharing. Notice also that the file server session is open specifically for sharing, and the only file opened using this shared session is the attachment. This ensures that the handler process only has access to that file and no others in the IM server’s private directory. If any other files were opened using this session there is a possibility that the receiving process could also open it – by speculatively incrementing the handle number, for instance. Finally, we see that the session is open only for as long as required for the handler process to receive the handle, and no longer. This is achieved with the Rendezvous code, which allows the IM server to be notified when the handler has received the attachment. Here is the corresponding code in the handler process:

LOCAL_C void MainL()
  {
  // adopt the file
  RFile attachment;
  User::LeaveIfError(attachment.AdoptFromCreator(1, 2));
  CleanupClosePushL(attachment);

  //signal transfer complete
  RProcess::Rendezvous(KErrNone);

  // use the file
  ...
  // close the file
  CleanupStack::PopAndDestroy(&attachment);
  }

GLDEF_C TInt E32Main()
  {
  __UHEAP_MARK;
  CTrapCleanup* cleanup = CTrapCleanup::New();
  CActiveScheduler* scheduler = new CActiveScheduler;
  TInt ret = KErrNoMemory;
  if (cleanup && scheduler)
    {
    CActiveScheduler::Install(scheduler);
    }
  delete scheduler;
  delete cleanup;
  __UHEAP_MARKEND;
  return ret;
  }

The client can use the file through a hidden shared file server session inside the RFile object, removing the need for a separate RFs object to be maintained. This session is automatically closed when RFile::Close() is called on the attachment.

The trust relationship between the two processes is evident here once again; there is no chance of revocation on the part of the sharing process. Similarly, the receiving process has a duty to protect the file it has received (note, though, that there is no technical reason why this process cannot pass the file on to another process).

Services Summary

The table below summarizes the system services and the categories of data with which they are best used. ‘Custom server’ in the table denotes the implementation of your own dedicated server to manage access to the data.

Table 7.3 System Data Services Characteristics
Service Characteristic
Persistency Volatility Size Exchange
Publish and subscribe Transient Any Prefer <512 bytes Asynchronous
Central repository Persistent Non-volatile <2 KB Asynchronous
DBMS Persistent Non-volatile Any Asynchronous
File handles Persistent Non-volatile Any Synchronous
Custom server Any Any Any Synchronous

Summary

Getting the level of trust correct for your data is essential in order to ensure it is secure enough, and to maintain a strong and balanced capability model on the mobile phone. Creating a threat model is crucial in achieving this outcome.

We have looked at different categories of data, and shown how confidentiality and integrity should be treated, with respect to each of these categories. As a client of shared data, the granting of a capability should be seen as bestowing privileged access. With privileges come responsibilities – once access has been granted, the responsibility for policing access has to be accepted also.

Your decision on how to implement secure sharing of your data will depend on its type and the characteristics of that data. We noted that system services should be used where possible, in preference to duplicating their functionality.

The benefits of sharing data safely are clear: in a world where more and more information is stored electronically, and where much of it may reside on or pass through a mobile phone and where the abuse of electronic communications to perpetrate fraud is rapidly increasing, mediated access to your data for trusted clients is paramount.


Copyright © 2006, Symbian Ltd.