The
MIDP security system is clearly described in the MIDP specification and
should behave similarly on all devices. In the real world, many phones
and carriers do behave slightly differently, and this is one of the
primary challenges of JME development.
Each application is granted a
set of permissions that allows the application to use sensitive phone
functionality (for example, GPS or the cellular network). The
permissions are defined using fully qualified package names. Earlier in
the sample JAD file, you saw the permission
javax.microedition.io.Connector.http. Many of these permissions are
defined in the MIDP JSR, but Optional JSRs may define permissions as
well. The Location Services JSR, for example, defines permissions that
are required in order to access location data. Applications are isolated
from each other almost completely, with small exceptions made for
applications signed with the same signature.
Not all applications may be
authorized to use all permissions because not all applications are
equally trusted. JME applications trust is determined by examining the
application’s origin and integrity. Most devices use X.509 certificates
and rely on the certificate’s common name (CN) and issuing CA as proof
of origin. The signature in the JAD file binds the origin to the
application and ensures that the application’s code has not been
tampered with since it was signed.
After
its identity is verified, the JVM assigns the application to a
protection domain. These are groups of permissions that allow access to
certain classes and functionality. A MIDlet suite may only be allowed to
access one protection domain at a time, although MIDP 3.0 may change
this. Frankly, having more than one set of permissions applying to an
application at one time may be confusing. It will be interesting to see
how that problem is resolved.
The protection domains are
not standard across manufacturers and carriers, but with MIDP 2.1 there
was an effort to standardize protection domains for GSM/UMTS phones.
This effort produced the following domains, as detailed in the MIDP 2.1
specification:
Unidentified Third Party protection domain (a.k.a. untrusted)
All unsigned code is placed in this domain. Irrespective of the MIDP
2.1 specification, all phones must have an untrusted domain and support
running unsigned code.
Identified Third Party protection domain
Code that has been signed with a certificate issued by a CA that the
operator or manufacturer trusts. Code in this domain may be able to use
the network or advanced phone functionality without user prompting.
Operator protection domain
A highly trusted domain restricted to code signed by an operator-owned
certificate. Generally allowed to do anything on the device.
Manufacturer protection domain
A highly trusted domain restricted to code signed by a
manufacturer-owned certificate. Generally allowed to do anything on the
device.
Not all carriers follow
these specifications exactly, but any changes tend to err on the more
restrictive side. T-Mobile North America, for example, doesn’t include
an Identified Third Party domain. Therefore, applications signed with
popular JME signing certificates aren’t allowed to run on T-Mobile’s
phones.
The untrusted protection
domain is a special case and must exist on all MIDP phones. Applications
without signatures are automatically placed in this domain, and for
many applications that arrangement works perfectly well. Games, for
example, don’t need to access much of the phones functionality, and the
MIDP API set is intentionally designed to allow them to run without
requiring signatures or special permissions. This means there are a lot
of unsigned JME applications out there.
Interestingly, if an application
has a signature that is either unknown or corrupted, the application
will not be placed into the untrusted zone. Instead, the application
will simply be rejected. This causes problems for developers with
applications signed with a certificate that is recognized on one network
but not on another. Just like getting into an exclusive night club,
getting into the desired domain on certain carriers can be a combination
of luck and skill.
The
JVM enforces all permissions at runtime, and if an application attempts
to access an API without permission, a dialog will be shown to the user
asking for permission (see Figure 1
for an example of this). Alternatively, the device could fail the API
call by throwing a java.lang.SecurityException. The MIDP specification
contains a list of which APIs require prompting, but manufacturers can
always choose to completely block access. Two sample APIs that require
prompting are javax.microedition.io.HttpConnection and
javax.microedition.io.HttpsConnection. These APIs are considered
sensitive because they allow access to the network.
Devices
may adopt different prompting modes that control how often the user is
asked for permission. The MIDP specification outlines three models:
oneshot, session, and blanket. These models are respectively valid for
one API use, one execution lifetime of an application, and for the
entire lifetime of an application. Most devices use the oneshot mode
because it is the most annoying and will force the developer to sign
their code. Granting a permission is granting the application access to
an entire API. Permissions are not necessarily provided on a per-item
basis. For example, MIDP is asking “Do you want this application to be
able to manipulate contacts?” It is not asking, “Do you want this
application to be able to manipulate Nancy Jones’s contact?”
Overall, the MIDP
permission system does well at controlling how applications are allowed
to interact with each other and with the system, and there have been few
reports of JME malware. The system is not without its downsides—the
prompts can be confusing to users, and getting code signed properly can
be difficult due to the way each carrier handles security.
Data Access
Mobile devices are
nothing without the ability to access data from different sources.
Normally, the Java.io and Java.net packages contain Java’s data access
functionality. However, including all of these classes in JME would
require too much memory. So JME uses the CLDC generic connector API,
which is a framework for defining read/write operations on arbitrary
stream data. By having one API, the number of classes in the standard
API is kept down.
The connector API references data sources using standard URIs—for example, www.isecpartners.com
for accessing the iSEC Partners website and “comm:0; baudrate=9600” for
using the serial port. There are also connectors for accessing sockets,
Bluetooth, and HTTPS. Not all connector exist on all devices, because
not all devices support the same hardware. Three permission modes are
defined when using the connector API: READ_ONLY, WRITE_ONLY, and
READ_WRITE. The semantics of these modes change depending on the
connector being used.
Network Access
All MIDP 2.1 platforms must
support HTTP, HTTPS, Socket, and Secure Socket connectors. By default,
untrusted applications are not allowed to use the network without
prompting. On some carriers (but not all), signed applications can use
the network silently. To learn more about the connector API, review the
CLDC 1.1 specification and the javax.microedition.io.Connector
documentation. Both describe the reasoning behind the generic connection
framework and how to use it.
Record Stores
JME
devices are normally resource constrained and may not have file
systems. However, every device supports MIDP2 Record Management Store
(RMS) databases. These can be used for persistently storing arbitrary
blobs of binary data. For example, a geo-caching application may store
the last location it recorded. Because they persist data, they are
particularly interesting to security review. Thankfully, MIDP does the
right thing—RMS databases are, by default, only accessible to the MIDlet
suite that creates them. (Note that I said “by default.”)
RMS databases can be shared
between applications if the AUTHMODE_ANY flag is specified at RMS
creation time. This publicizes the database to any other application
that knows the package and RMS database name (for example,
com.isecpartners.testapp.RMS_STORE). The sharing is limited to the named
record store and does not affect any of the application’s private
record stores.
Sharing is not recommended for
both privacy and security reasons, because users aren’t able to control
which applications can access shared RMS databases. Even untrusted
MIDlets can read or update shared RMS databases. Additionally, RMS
doesn’t synchronize access to RMS records, so corruption is highly
likely. If you’re planning on sharing any data, make sure the user is
properly informed before doing so and be aware that sharing does not
work on all phones. BlackBerry, for example, requires applications to
use a more secure proprietary sharing mechanism.
Cryptography
By default, JME storage
is not encrypted, and robust cryptographic classes are not included with
the default SDK. To perform in-depth encryption, use the Legion of the
Bouncy Castle’s JME cryptographic provider, available for free from http://www.bouncycastle.org/.