Using Harmattan security features
Overview of application security
Application security refers to procedures used in the design, development, deployment, upgrade, and maintenance of an application to ensure that it functions according to the security policy used by it and the system it runs on. These procedures include, for example, secure coding. This guide concentrates in giving instructions on how to use the Harmattan platform security framework to make your application secure. If Harmattan applications need to access protected resources or the application provides protected resources, they must be defined in the Aegis manifest file.
A protected resource is a system resource or service that is not available by default for an application. Such resources are protected with the corresponding resource token or another credential. Applications are required to announce to which protected resources they request access, and to define if they provide the same kind of protected resources to other applications. For example, an application can access the cellular function, or a service can provide location services. Only the processes that have the required security credentials can access protected resources. Moreover, software from different software sources may be blocked from accessing certain resources.
When assessing the security needs of your application, consider the following questions:
- Does your application need to access protected resources?
- If it does, you need to request any relevant protected resources. If this does not happen automatically with the SDK tools, see the instructions for creating the Aegis manifest file manually for the Qt SDK and for the Platform SDK.
- Do you need to protect the data your application handles?
- Does your application provide services for other applications?
- Does your application need to access Harmattan device certificates or store private keys?
If you answer 'yes' to any of the questions, see the instructions that apply to your application.
If you have no specific needs, you still have to consider secure coding.
Providing protected resources
The following file provides an example of an Aegis manifest file for a server. The Aegis manifest file provides a number of interfaces over D-Bus. The example assumes that there is a global resource token, TestToken
, in the system. The server in the example provides the following interfaces:
com.nokia.server.datarequest
with the methods:get_data
get_raw_data
check_data_status
- For the
com.nokia.server.datarequest
interface, the server uses local resource tokens to protect theget_data
("get-data" resource token) andget_raw_data
("get-raw-data" resource token) methods. Thecheck_data_status
method should not be protected with any resource tokens.
com.nokia.server.datainfo
- For the
com.nokia.server.datainfo
interface, the server would like to use the global tokenTestToken
to protect the entire interface. - The binding to the service name is protected with a local
dbus-server-bind
token.
- For the
<aegis> <provide> <credential name="get-data" /> <credential name="get-raw-data" /> <credential name="dbus-server-bind" /> <dbus name="com.maemo.server" own="dbus-server-bind" bus="session"> <node name="/"> <interface name="server.datarequest"> <method name="get_data"> <annotation name="com.maemo.Aegis" value="get-data"/> </method> <method name="get_raw_data"> <annotation name="com.maemo.Aegis" value="get-raw-data"/> </method> <interface name="server.datainfo"> <annotation name="com.maemo.Aegis" value="TestToken"/> </interface> </node> </dbus> </provide> <request> <credential name="dbus-server-bind" /> <for path="/usr/bin/aegis-dbus-server" /> </request> </aegis>
Creating specific user accounts and groups
To create specific user accounts and groups by using the Aegis manifest file, use the optional <account>
element. The element creates users and groups when the application package is installed, even if you specify a non-existent group.
To define the name and group for the account, use the <user>
element within the <account>
element:
name
attribute is the user name (UID)group
attribute is the group name (GID)
The following is an example of an <account>
definition:
<aegis> <account> <user name="donald" group="duck"/> <user name="mickey" group="mouse"/> </account> </aegis>
Note: The users and groups created when the application package is installed are not removed if the application package itself is removed.
Requesting specific user accounts and groups
Note: You can only use an account created through an Aegis manifest file to run applications with the UID and GID defined in it. You cannot use the account, for example, to log into the device. In addition, the account does not have a home folder.
To define the requested credential, use the value of the name
attribute within a <credential>
element. The general syntax is:
[namespace "::"] name
To request the system to run your application under a specific user identifier or group identifier, use the UID::username
and GID::groupname
attribute values. The UID and GID must already exist on the device or the request fails. To create new UIDs and GIDs, see section Creating specific user accounts and groups.
The following is an example of a <credential>
definition:
<aegis> <request> <credential name="UID::myuser" /> <credential name="GID::mygroup" /> <for path="/usr/bin/myapp" /> </request> </aegis>
Requesting supplementary groups
To request to have the group included in supplementary groups, use the GRP::group
attribute value.
The following is an example of a supplementary group request:
<aegis> <request> <credential name="GRP::dial-out" /> <for path="/usr/bin/myapp" /> </request> </aegis>
Requesting POSIX capabilities
If your application needs any POSIX capabilities, the following example shows how to request POSIX capabilities for your application.
Note that POSIX capabilities are sensitive credentials. Even if you use the request, whether you get the capabilities or not depends on the software source.
<aegis> <request> <credential name="CAP::chown" /> <credential name="CAP::kill" /> <for path="/usr/bin/myapp" /> </request> </aegis>
Requesting resource tokens
The Aegis manifest file syntax depends on the token that the application package needs to request. There are two types of tokens:
- Global tokens are declared in the
aegis-global-tokens
package. You can request these tokens directly in the<request>
sections.- The following is an example of a global token request:
<aegis> <request> <credential name="Cellular" /> <for path="/usr/bin/userdatamanager" /> </request> </aegis>
The above example states that whenever /usr/bin/userdatamanager
is executed, its credential set includes the Cellular
credential.
- Internal tokens can be provided by any package. When you request an internal token, you need to add the package name as the prefix in the name attribute.
- The following is an example of an Aegis manifest file requesting an internal token:
A package called cool-tools
includes the following <provide>
section:
<aegis> <provide> <credential name="UserData" /> </provide> </aegis>
To request this resource token, a package must include the following <request>
section in its Aegis manifest file:
<aegis> <request> <credential name="cool-tools::UserData" /> <for path="/usr/bin/userdatamanager" /> </request> </aegis>
Requesting an application identifier
On the Harmattan system, the term 'application identifier' refers to a unique identifier for an application on the platform. Such a unique identifier can be used in order to keep application data secure. For more information, see Protecting the server's data store by using encryption and signing.
By default, all binaries that have even an empty request in their Aegis manifest file get an application identifier in the format AID::sw_source_name.packagename.
. To request different application identifiers for two or more binaries in the same package, add an additional id
attribute in the <for>
element of your request. The value of the id
attribute is combined with the source domain and package name, and the resulting string is the actual application identifier (AID::sw_source_name.packagename.id
).
The following is an example of an application identifier request:
<aegis> <request> <for path="/usr/bin/foo" id="foo" /> </request> </aegis>
Requesting additional credentials for a different binary from plug-in package
If you are creating a plug-in that needs some credentials in order to access protected interfaces, you may need to request these credentials for the main application binary that usually resides in another package. In order to do that, the main application binary should have at least an empty manifest request in its package:
<aegis> <request> <for path="/full/path/to/main/application" /> </request> </aegis>
In order to request credentials for the main application binary package that includes the above Aegis manifest file, create the following Aegis manifest file:
<aegis> <request> <credential name="cred_name_1" /> <credential name="cred_name_2" /> <for path="main_application_package::/full/path/to/main/application" /> </request> </aegis>
In some cases, you may want the main application to drop unnecessary credentials before loading a plug-in (a shared library). This is a good practice if you want to limit the amount of credentials that plug-in has access to.
Dropping the credentials to the level of the plug-in
In order to drop the credentials to the level needed by a certain plug-in that the main application loads, an application should use the creds_confine2()
function from the libcreds2
library. Provide a full path to the plug-in (shared library) with the function. However, in order for this function to work, the plug-in package should not only request credentials for the main application in its manifest, but also for itself:
<aegis> <request> <credential name="cred_name_1" /> <credential name="cred_name_2" /> <for path="main_application_package::/full/path/to/main/application" /> <for path="/full/path/to/the/plug-in" /> </request> </aegis>
The main application should call creds_confine2
providing the /full/path/to/the/plug-in
before loading the plug-in (shared library).
Requesting credentials for a pre-started application
If your application is pre-started with the application launcher, you need one more line in your Aegis manifest file, which grants the same set of credentials to the application launcher binary:
<aegis> <request> <credential name="cred_name_1" /> <credential name="cred_name_2" /> <for path="/usr/bin/myapp" /> <for path="applauncherd-launcher::/usr/bin/applauncherd.bin" id="" /> </request> </aegis>
This definition also makes sure that your application is started with the correct application identifier.
Everything that is requested for the application binary must be requested to the application launcher binary as well.
If you specify your own application identifier, you must also refer to the same identifier in the for
statement for the application launcher:
<aegis> <request> <credential name="cred_name_1" /> <credential name="cred_name_2" /> <for path="/usr/bin/myapp" id="myappid" /> <for path="applauncherd-launcher::/usr/bin/applauncherd.bin" id="myappid" /> </request> </aegis>
Addressing specific security needs
This section presents a simple example of server and client applications to demonstrate certain security features that applications can use. New features are gradually added to the example with references to corresponding branches in the repository. The example uses Qt APIs. Therefore, you can more easily follow the examples if you are familiar with creating Qt applications.
To evaluate which features your application needs, see the questions in Overview of application security.
Providing new resource tokens
To use the examples in the following sections, you must understand how to create new resource tokens in the Harmattan system. This is done with the <provide>
element.
Use the <provide>
element to define credential tokens specific to your application. The <provide>
element can contain one or more <credential>
elements. Each <credential>
definition defines a new application-specific token. The name you give in the <credential>
element is implicitly prefixed with the name of the application package, and cannot have a namespace definition. You cannot provide a token that belongs to another package.
The following example shows how to use the <provide>
element:
<aegis> <provide> <credential name="encrypt"> <docstring> A Token that is used for encrypting data. </docstring> </credential> </provide> </aegis>
Basic example of server and client communication
The master branch of the server and client application example contains the Qt implementation of the client and server without any additional security features. The server provides two interfaces:
com.meego.mssf
, a D-Bus interface on the system bus/tmp/mssf.socket
, a Unix domain socket interface
The only method, provided by the server over the com.meego.mssf
D-Bus interface is setState
, which enables setting the internal state of the server. The same functionality is available over the /tmp/mssf.socket
local socket interface. The client program calls the server D-Bus interface with all possible states and tries to set a state by using local socket communication. For more information, see Client::run
method.
The server also provides a standard D-Bus configuration policy, com.meego.mssf.conf
, which allows all applications to access this interface. The daemon stores its configuration settings in the /tmp/mssf-demo.storage
file and has two classes, ConfigWriter
and Configuration
, to access this storage.
Protecting the server's data store by using standard Linux permissions
In the basic example above, the server uses the configuration data from the /tmp/mssf-demo.storage
file. To protect the integrity and confidentiality of the data stored in this file, you can use the standard Linux file system permissions, which work in the same way on the device.
As a number of online tutorials on Linux file system access control are available (for example, File System Permissions), all details of suitable setups for different use cases are not covered in this topic. Instead, one possible setting is presented in the example below.
To allow only the server application to read and write in the data storage, and others only to read the storage, specify the permissions for the file in the following way:
% ls -l /tmp/mssf-demo.storage -rw-rw-r-- 1 appd appd 123 Jan 22 16:29 mssf-demo.storage
In this setting, the user and group that own the file are called appd
, and only this user and group have a right to read and write in the file. Others are only allowed to read. You must create this user and group and request the corresponding group in the Aegis manifest file of the server application.
Protecting the server's data store by using encryption and signing
Protecting the configuration data file of the application server against offline attacks is necessary because data can be modified even if the device is switched off. Linux access control permissions cannot be used for this because they are not enforced when the device is switched off.
The next branch presents a method to provide confidentiality of the daemon's configuration data by using encryption and decryption methods. This example does not guarantee the integrity of configuration data, because it does not use signing methods. To add integrity protection, use the signing and verification methods provided below.
To see how encryption and signing of data transmitted from the server to client is added to the example, see the difference between this branch and the previous one.
The main difference is the presence of a new class, AegisCrypto
, which provides methods to sign and verify, as well as encrypt and decrypt the data. The daemon program uses this class to encrypt and decrypt the configuration data in the ConfigWriter
class. For information on AegisCrypto
API, see Platform API reference.
If you take a look at the code inside the AegisCrypto
class, you see that it uses methods declared in aegis_crypto.h
(libaegis-crypto
library). This library provides a method to perform cryptographic operations by using the keys stored securely in the Trusted Execution Environment (TEE) of the device. For each cryptographic operation, a key is derived inside TEE from the device-specific symmetric key and the credential defined in the method. The credential can be either a resource token or an application identifier. (If a resource token is not specified, an application identifier is used by default.) The choice of credential defines, for example, which applications can decrypt the encrypted data. The security driver in the device ensures that the calling application possesses a credential specified in the method. The method returns the requested result only if this credential is found. In this example, only an application identifier is used, and therefore all the encryption and decryption calls succeed.
A more detailed look at the simple encryptData
method reveals that it first checks the input parameters and declares needed variables. After this, it calls the aegis_crypto_encrypt
method, where it supplies the clear text data, its length, and the credential to be used for encryption (token
), and receives the cipher text with its length. If something fails, the returned data is cleaned. If everything is successful, the data is copied and returned.
The following example illustrates the encryptData
method:
if (aegis_crypto_encrypt(clearText.data(), clearText.length(), token, &cipherText, &cipherLength) != aegis_crypto_ok) { aegis_crypto_free(cipherText); qDebug("Failed to encrypt data: %s", aegis_crypto_last_error_str()); return QByteArray(); } QByteArray encrypted((char *)cipherText, cipherLength); aegis_crypto_free(cipherText); return encrypted;
Protecting the server's data store by using the protected storage API
You can use another set of methods to store the configuration data securely and manage the file operations. These methods are defined in aegis-storage.h
provided by the libaegis-crypto
library. You can use the methods to:
- Create a protected storage (such as a virtual container) for a number of files.
- Specify the credentials needed to access the protected storage (similar to the examples presented in Protecting data store of a server with encryption and signing).
To learn how to use these methods, see the next branch of the server and client example.
The main addition compared to the previous branch is a new class, AegisStorage
, which operates with the protected storage content directly. It contains methods for reading and writing data into the files stored in the protected storage, and for cleaning the protected storage and listing the files.
The most important functionality is in the aegisStorageWrite
function:
QSharedPointer<storage> aegisStorage(new storage(storageName, token, storage::vis_private, storage::prot_encrypted)); if (aegisStorage->put_file(storagePath, (void *)data.data(), data.length()) != 0) { qDebug("Failed To create or retrieve an Aegis-Storage location: %s", aegis_crypto_last_error_str()); return false; } aegisStorage->commit();
This function creates a new encrypted storage with a specified storage name. Because the function includes the flags vis_private
and prot_encrypted
, only the current application can read and write into the storage. The function also adds a new file into the storage with specified data and commits the storage. For more information about the different flags, see lines 304-337 in the aegis-storage.h
file.
Protecting the server's data by storing it in /home/user/private
AegisFS is a cryptographic userspace file system that enables mounting protected stores or zip files as directories anywhere in the file system. It starts automatically at boot time and mounts the directories defined in its configuration files. Applications can use these directories as any other directories in the system, provided that they have the necessary credentials. Almost all POSIX file system calls are supported including managing sub-directories, symbolic links and hard links, file locking, random access, regular file attributes and discretionary access control.
AegisFS supports two types of directories. Signed directories are implemented by help of signed protected stores to guarantee data integrity. Typically anyone is free to read the files in them but modification is allowed only for processes that have a speficic resource token. Encrypted directories store their data in encrypted protected stores and both reading and writing require an access token.
A number of platform packages define mountpoints for their own use by adding configuration files in the /etc/aegisfs.d
directory. Each configuration file needs to be registered by command aegisfs --install <configuration-file>
, which requires credential aegisfs::AegisFSMountAdd
. Non-platform packages cannot register new mountpoints.
The encrypted /home/user/private
directory is available for all applications for storing sensitive information. Anything written to this directory will be automatically encrypted and available only to the package that created it.
How does this work? Each binary mentioned in a security manifest is automatically assigned a special resource token called the application ID. It is of form AID::<source-id>.<package-name>.[<binary-id>], for instance AID::com.nokia.maemo.aegis-crypto-tools.apscli. Processes that have not been assigned an application ID use the default AID::unknown.unknown..
When the aegisfs process that serves /home/user/private
receives requests it checks what is the application ID of the caller and selects a private protected store for the directory contents accordingly. If the application ID has not been seen earlier, a new protected store is created and an empty directory is shown. To illustrate how this works.
A remote developer shell through SSH connection does not have identity
$ accli -qI Credentials: UID::user GID::users GRP::adm GRP::dialout GRP::video GRP::pulse-access GRP::users
...so everything it does in /home/user/private
goes into the unknown store.
$ date > /home/user/private/edate $ cat /home/user/private/edate Sat Jan 1 03:15:49 EET 2000 $ ls -l /home/user/private/ total 1 -rw-r--r-- 1 user users 29 Jan 1 03:15 edate
A local terminal on the other hand inherits its identity from the Home Screen application:
$ accli -qI Credentials: UID::user GID::users SRC::com.nokia.maemo AID::com.nokia.maemo.meegotouchhome-nokia. meegotouchhome-nokia::meegotouchhome-nokia
So it has its own idea of what /home/user/private
contains:
$ ls -l /home/user/private/ total 0 $ date > /home/user/private/edate $ cat /home/user/private/edate Sat Jan 1 03:19:55 EET 2000
Even if both clients created a file called /home/user/private/edate they are two physically different files encrypted by different keys and stored in two different protected stores:
$ apscli -lu | grep ^private private@com.nokia.maemo.meegotouchhome-nokia.:Pe private@unknown.unknown.:Pe
To get identity a binary needs to be mentioned in a for-tag of a manifest. This is a minimal security manifest required to create a new application id:
<aegis> <request policy="add"> <for path="/opt/coolapp/mainbin" /> </request> </aegis>
By default all binaries from the same package get the same application id, so they have the same view to /home/user/private
. If the data must be accessible only by a single binary it can be given an optional binary ID in the manifest as <for path="/opt/coolapp/mainbin" id="mainbin"/>
.
Securing the communication between the server and client by using data signing and encryption
To learn how to secure communication between the server and client, see the next branch.
In this example, the server sends an encrypted reply over the Unix domain socket to the client:
- QByteArray encrypted = AegisCrypto::encryptData(data, Mssf::tokenName);
The server uses the methods from the AegisCrypto
class again, but this time it specifies a credential. This credential is the Mssf::tokenName
variable, which contains the mssf-demo::encrypt
internal resource token used to derive the key for the encryption. The server application also has an Aegis manifest file where it provides this new credential, and requests it and a number of other credentials.
The client application also requests the new resource token in its Aegis manifest file, and uses the AegisCrypto
class to decrypt the server reply:
- QDataStream byteStream(AegisCrypto::decryptData(data, Mssf::tokenName));
Protecting the server's D-Bus interface by using resource tokens
The master branch includes a D-Bus configuration file, which specifies that all applications can send messages and bind to this interface. To protect the D-Bus interface provided by the server, you must create a more restricted policy by using an Aegis manifest file, as shown in the next branch.
The main difference to the master branch is that the com.meego.mssf.conf
file is removed and the server Aegis manifest file is extended. The Aegis manifest file provides two new resource tokens: MssfDBusServiceOwn
and StateSetter
. MssfDBusServiceOwn
is used to define which application can own the specified interface on a system bus:
- <dbus name="com.meego.mssf" own="MssfDBusServiceOwn" bus="system">
StateSetter
is used to specify the credential required to call a setState
method:
<node name="/"> <interface name="com.meego.mssf"> <annotation name="com.maemo.Aegis" value=""/> <method name="setState"> <annotation name="com.maemo.Aegis" value="StateSetter"/> </method> </interface> </node>
The server also requests both new credentials in addition to the ones in the original Aegis manifest file.
If you compile and start the client and server in this branch, you see that the client receives the message "Access denied" from the D-Bus daemon when trying to call the setState
method. This happens because the client does not possess the required mssf-demo::StateSetter
credential.
To learn how to request the missing credential for the client, see the next branch. One line is added into the client Aegis manifest file, enabling the client to call the setState
method from the com.meego.mssf
interface.
Protecting the server's interfaces by using server-enforced access control
Some cases demand a more secure or fine-grained solution than specifying a credential to call a particular method. This means that access control decisions cannot be delegated to the D-Bus daemon, but the server must make the access decisions itself. In this example, the server makes access control decisions itself using a special user space library, libcreds2
.
See the changes that are needed to the daemon part.
You can use the libcreds2
library through two APIs:
- C API
- Qt wrapper
mssf-qt
for the main methods
This example uses the Qt wrapper.
In the example code, you can see that the daemon defines two new resource tokens: Stop_State
and Clean_State
. These are required to perform calls to setState
method to change the daemon state to stop
or clean
, respectively. (As presented in the previous section, you also need the resource token required to invoke the setState
method itself.) Other state changes do not require a token.
The first daemon sets the credential value based on the requested state:
switch ((Mssf::State)state) { case Mssf::Clean: credential = QLatin1String("mssf-demo::Clean_State"); break; case Mssf::Stopped: credential = QLatin1String("mssf-demo::Stop_State"); break; default: break; }
Then, if a credential is needed to change the state, the daemon checks it in the following call:
if (!DBusContextAccessManager::hasClientCredential(*this, credential, &errorString)) { qDebug() << "Failed to validate credential: " << errorString; sendErrorReply(QDBusError::AccessDenied, "Caller does not possess the correct credentials"); return false; }
If the client does not possess the necessary credential, the daemon sends an error as a reply and does not change the state. If you compile and run this branch, you see that the client cannot set the Clean
and Stop
states because it does not have the necessary credentials. The next branch adds credentials to the client, enabling the client to set all possible states for the daemon.
Protecting the application's UNIX socket interface
After protecting the D-Bus socket interface of the server, you must also protect the Unix local socket interface. Because there is no D-Bus daemon between the server and client, the server must use libcreds2
library, as in the previous example.
To learn how to protect the Unix local socket interface, see the changes required for the server. In the Aegis manifest file, the server provides an additional resource token, SocketSetter
, which is checked for all clients connecting over a Unix socket to the server.
The server checks the client credentials in the following call:
if (!CredentialsManager::hasSocketCredential(sockClient->socketDescriptor(), Mssf::SocketSetter, &errorString)) { qDebug() << "Failed to validate credential: " << errorString; }
If the client does not have the required mssf-demo::SocketSetter
credential, the error is printed and the state is not set. As in the previous example, if you compile and run this branch, you see that the client cannot set the state of the server through a Unix local socket interface. To succeed, the client must request the mssf-demo::SocketSetter
token in its Aegis manifest file.
Managing certificates with Certificate Manager
When communicating and authenticating with servers using the secure SSL/TLS protocol, take care of the integrity of the related X.509 certificates and the privacy of their private keys. For this purpose, the Harmattan platform provides a protected certificate store which is based on the protected storage implementation mentioned above.
The integrity of the certificates must be protected because the authenticity of the remote servers is verified by using them. The device comes with a pre-installed set of root Certificate Authority (CA) certificates, which cannot be verified by any other means but just have to be trusted. An attacker that is able to inject malicious root CA certificates in the system can spoof SSL/TLS servers and perform a man-in-the-middle attack, for example, against secure connection to banking sites.
When user certificates are used to log in to remote services, the security is based on the privacy of the private keys which are used to sign a challenge sent by a server. If private keys can be extracted from the system, they can be used to log in as the device owner and fake the owner's identity.
On the other hand, it must be possible to install new CA certificates in the system to authenticate servers that are signed, for example, with a corporate key. To limit the damage a fake CA certificate can cause, they are divided into certificate domains according to the intended use:
- Each device comes with a pre-installed
common-ca
root certificate store, which cannot be modified by any means other than by an authorized software update from trusted source. These root certificates can be used for all purposes.
- The domains
ssl-ca
,ssl-user
,wifi-ca
andwifi-user
contain the signing CA and user certificates for authenticating and logging in to SSL/TLS servers and WiFi access points. These domains can be modified by the Certificate management applet available in the settings, which allows adding and removing new CA and user certificates. The purpose of a certificate can be selected by the user at installation time.
- There are also the domains,
smime-ca
,smime-user
,codesign-ca
andcodesign-user
, for certificates used from S/MIME e-mail and code signing purposes. Currently there are no applications that would use these domains, so they are typically empty.
Applications can use the secure certificate stores in one of three ways:
- Using the proprietary
aegis_certman.h
API.- This is a low-level C-API that has been designed as an extension to the OpenSSL crypto and communication library. The function call,
aegis_certman_collect
, can be used to retrieve a populated certificate store of typeX509_STORE
that contains the certificates from one or more domains and used in the SSL handshake for authenticating the peer. An application that uses this function can rely on the integrity of the certificate set.
- This is a low-level C-API that has been designed as an extension to the OpenSSL crypto and communication library. The function call,
- Using the PKCS#11 interface.
- Applications that use the Network Security Services (NSS) crypto and communication library can configure
libaegis_certman.so.0
as a loadable security module and access the certificate stores in a secure way through it by using the NSS library's functions in the normal way. Only reading of certificates is currently supported through the PKCS#11 module.
- Applications that use the Network Security Services (NSS) crypto and communication library can configure
- Reading certificates from the OpenSSL's default directory
/etc/ssl/certs
.- This method is also secure because the directory is served by the secure file system which maps the contents of the directory to the combined contents of the
common-ca
andssl-ca
certificate stores.
- This method is also secure because the directory is served by the secure file system which maps the contents of the directory to the combined contents of the
The last method is usually the easiest way to ensure the integrity of the root CA set. Since QNetwork uses this directory by default, all Qt applications that do not change the default settings use it with no further effort.
If your application requires implementing secure authentication using the stored user certificates and private keys, it should use the functions of aegis_certman.h
to iterate through the certificates stored for a purpose and to access their private keys, which are stored as encrypted PKCS#8 envelope files.
Modifying the modifiable CA domains requires having one of resource tokens CertCASSLAdd
, CertCAWifiAdd
, CertCASMIMEAdd
or CertCACodeSignAdd
, depending on which certificate store is being modified. Using the private keys requires one of tokens CertUserSSLUse
, CertUserWifiUse
, CertUserSMIMEUse
or CertUserCodeSignUse
in the same way. All these resource tokens are declared in package aegis-certman-common-ca
and must be prefixed by the package name. An application that requires modifying CA domains or getting access to the private keys must claim the respective resource tokens in its package manifest.
Further information
For more information on security, see the following:
- Secure coding
- Aegis manifest syntax
- Aegis Manifest Schema
- Harmattan Security FAQ: Includes frequently asked questions about security components and how they affect applications.
- Aegis manifest file generation tool
- Creating the Aegis manifest file manually with Qt SDK
- Creating the Aegis manifest file manually with Platform SDK
- ITU-T Recommendation X.509: Public-key and attribute certificate frameworks, International Telecommunications Union
- Public-Key Cryptography Standards (PKCS) PKCS#11, RSA Laboratories
- Private-Key Information Syntax Standard PKCS#8, RSA Laboratories
- OpenSSL
- Network Security Services (NSS), Mozilla