Security/Tizen 3.X Key Manager initial value setting

From Tizen Wiki
Jump to: navigation, search

Requirements

  • Required to import keys, certs, and data from an external world to a device at the first boot time.
    • The device manufacturer can inject a key into a device. Applications and modules within the device can use it.
    • The imported key values should not be exposed.
  • Required to generate keys at the first boot time
    • A device can have its own platform key which are randomly generated at the first boot time and applications encrypt/decrypt data using this key. The key value is not exposed to applications but the application can use the key.
  • Support for data sharing of data imported or generated at the first boot time
    • Data imported/generated by system process must be available to user applications

High Level Design

Overview

The purpose of this feature is to load initial values from predefined location, store them in key-manager and remove them from filesystem.

Initial values.png

File format

The file format is XML. Document structure will be validated with the following schema: initial_values.xsd

Initial value files should be placed at:

/opt/data/ckm/initial_values/

Initial values file example: example.xml

XML validation and parsing will be implemented using libxml2.

System database

All initial values will be stored in system database. That is a database reserved for and accessible only by system daemons with UID<5000 (according to [1]). We don't want to identify system processes by smack label (System) because non-system users are already identified by uid. To support system database key-manager will need the following changes:

  • Most of system daemons run with root privileges, uid=0 and label="System". We can't rely on anything except process uid. Therefore such processes will be identified only by uid (not by smack label/pkg id).
  • System users won't log in so database can't be protected with user password.
    • Key-manager can derive the domain key encryption key (Domain KEK) from some hardcoded password and use it to encrypt/decrypt the database data encryption key (DB DEK) on-demand. This way the database would remain decrypted in the memory after first use.
    • Domain KEK can be used as usual to derive an application data encryption key (App DEK). However, there would be only one common App DEK for all system daemons (there won't be any actual applications and we have to share system database contents between all system daemons).
    • System daemon can also provide a custom hardcoded password to additionally encrypt a single row in database.
    • It won't be safe unless hardware assisted encryption/decryption/key wrapping is used.
  • Processes with system uids will have to be redirected to the common system database.
  • The database must not be removed when a system user is removed.
  • It won't be possible to change the key-manager password for system user.
  • If for some reason a system user logs in/out key-manager should ignore it.

Access rights

The system database will be populated by a privileged user (probably root) but objects must be accessible to ordinary users (Web_App_Encryption_Support). We don't want to populate user's databases because:

  • Newly created user's wouldn't get initial values.
  • Values would be duplicated in every user database.
  • User should not be able to remove such "global" objects.

Instead, the system user will be able to grant read-only permissions to specific application running as an ordinary user (any user).

Process identification

There will be 3 types of processes:

  • System processes running with uid < 5000 and System label. They will be mapped to system database. System processes should be able to use control API.
  • Applications running as an ordinary user with App* label. This is untrusted software and will be mapped to a proper database depending on uid and to a proper owner/application namespace depending on it's identifier. On tizen.org the process Smack label will be converted to pkg_id. The conversion will be performed by security-manager. Applications should not be able to use control API.
  • Preinstalled software running as an ordinary user with User label. This is trusted software usually running separately for each user. Such processes will be mapped to a proper database depending on uid. Because it's not an application it will not be possible to get it's pkg_id. Instead such process will be mapped to a default namespace "-". Such processes should not be able to use control API.

Integration with installer (use case)

Preloaded application example (based on Web_App_Encryption_Support):

  1. Wrt-installer running as root during image creation installs preloaded a application PKG1.
    1. It generates APP_DEK and stores it in initial values file as an AES key under a name APP_DEK_PKG1.
    2. It encrypts the application with specific AES algorithm with specific configuration.
    3. It stores the algorithm type and configuration (like initialization vector) by itself.
    4. It gives PKG1 permission to access APP_DEK_PKG1.
  2. Wrt-launcher running as an ordinary logged in user during normal system operation launches the application PKG1.
    1. Webappenc gets AES key APP_DEK_PKG1 from system database.
    2. Webappenc uses the key and previously stored decryption parameters to decrypt the web application in runtime.

Detailed Design

System database permissions

The following assumptions are made:

  • There will be only one system-like database in key-manager.
  • System database is not password protected and therefore key-manager service can access it at any time.
  • There's no such thing as application in system database. All objects exist in a common namespace. Therefore, the label column in NAMES table will be hardcoded and common for all system database objects.
  • By default no system users will have no access to system database (objects will be invisible to the client)
  • It's not possible to share objects between ordinary users.
  • Object names interpretation will be handled differently
    • pkg1 object1 will refer to an object in users database owned by pkg1 named object1 as before.
    • / object2 will refer to an object in system database in common namespace "/" named object2 ("/" is used to not clutter the app identifier namespace)
    • Non-system user can use the second format to perform read-only operations using system database objects via API: <source lang="c">ckmc_get_key(“/ key1”, NULL, &key);</source>
  • Object permissions will be handled differently for system database:
    • System daemons (uid < 5000) have full access rights to the system database. No permission rules are required for system daemons (there are no apps and no accessor label).
    • System user can grant read-only permissions to specific application running as an ordinary user: <source lang="c">ckmc_set_permission(“/ data1”, “pkg1”, “r”);</source>
    • In case of system database permissionLabel column in PERMISSIONS table will identify accessing application label of any non-system user.
    • Exportable flag works as usual.

Required changes:

System database

  • Modify object name validation to allow special owner "/".
  • Support system database unlock with first access attempt.
  • Introduce hardcoded app namespace in system database. All system database objects should be encrypted with common app DEK derived from Domain KEK
  • Provide method responsible for system database access logic:
    • Map uid < 5000 to database uid 0.
    • Map "/" owner name to database uid 0.
    • Database uid should be used to locate appropriate database but real uid should be used for permission check.
  • Introduce separate permission logic for system database (AccessControl).
    • Write operations on system database should be disallowed for ordinary users.
    • Non-system user must be logged in to access system database (that is his DomainKEK should be unlocked).
  • Handle system user login/logout (Ignore it but log warning).
  • Prepare system database tests.

System database.png


Initial value support

The whole operation of initial value parsing and saving should take place in key-manager server. Specifically in CKM service which is responsible for DB access. Initial values should be processed before any other requests to the service. Subtasks:

  • Xml validation. If validation fails the XML file should be removed. Appropriate log should be produced.
  • Xml parsing.
    • Parser types:
      • SAX - Low memory consumption, fast, harder to implement, RO access. [RECOMMENDED]
      • DOM - High memory consumption (loads entire tree into memory), slower, easy to implement, RW access.
      • XPath - Similar to DOM (loads tree into memory), easy to implement. Allows accessing individual elements by path.
    • Error handling:
      • Detecting version different than the current -> Log + remove file
      • Receiving error callback from parser -> Log + remove file
      • Logical error during parsing (incorrect parameters) -> Log + ignore current element
  • Storing initial values in system database.
  • Xml removal.
  • Prepare initial values tests.


Class diagram

Parser classes.png

  • Parser - a generic class wrapping a SAX XML interface. Allows XML validation and parsing. Custom objects can be registered as listeners for specific events.
  • ElementHandler - a base class for custom xml element handlers. The object is notified when an element starts, ends or some characters appear within it.
  • InitialValuesFile - a class responsible for processing of single XML file with initial values. The class registers itself for document events and holds InitialValueLogic.
  • InitialValuesLogic - a class providing different element handlers. It is registered in Parser. When new element starts, the InitialValuesLogic is asked to provide a handler object. It then returns custom ElementHandler derived class, which is again notified about XML events. Upon element end, after ElementHandler is notified the InitialValuesLogic is notified so that it can set the release the element handler. The class holds a connection to Database and passes it to current InitialValueHandler upon creation.
  • InitialValueHandler - base class for key, cert and data elements. It holds the buffer and permissions handlers.
  • KeyHandler - class for handling keys. When key element is finished an object of this class has all required information to save the key and permissions in database.
  • CertHandler - class for handling certificates. When certificate element is finished an object of this class has all required information to save the certificate and permissions in database.
  • DataHandler - class for handling data. When data element is finished an object of this class has all required information to save the data and permissions in database.
  • BufferHandler - class for handling actual data.
  • PermissionHandler - class for handling permissions to objects.

[NOTE] Diagram does not include a handler for main InitialValues element for clarity.

Sequence diagram

Example sequence for following initial values document: <source lang="xml"> <InitialValues version="0">

 <Key name="key1" type="RSA_PRV" password="123">
   <PEM>
     -----BEGIN PUBLIC KEY-----
     MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2b1bXDa+S8/MGWnMkru4
     T4tUddtZNi0NVjQn9RFH1NMa220GsRhRO56F77FlSVFKfSfVZKIiWg6C+DVCkcLf
     zXJ/Z0pvwOQYBAqVMFjV6efQGN0JzJ1Unu7pPRiZl7RKGEI+cyzzrcDyrLLrQ2W7
     0ZySkNEOv6Frx9JgC5NExuYY4lk2fQQa38JXiZkfyzif2em0px7mXbyf5LjccsKq
     v1e+XLtMsL0ZefRcqsP++NzQAI8fKX7WBT+qK0HJDLiHrKOTWYzx6CwJ66LD/vvf
     j55xtsKDLVDbsotvf8/m6VLMab+vqKk11TP4tq6yo0mwyTADvgl1zowQEO9I1W6o
     zQIDAQAB
     -----END PUBLIC KEY-----
   </PEM>
 </Key>

</InitialValues> </source> [NOTE] For clarity, the diagram does not include a InitialValues element parsing sequence.

Parser sequence.png

Encrypted Initial Values enhancement

Requirements

  • keys in initial values file encrypted using the device key
  • encryption: RSA OAEP
  • new requirement: encryption of certificates and data items

High Level Design

Key problem with RSA OAEP encryption is the limitation on encrypted block size. It is 86[B] for 1024-bit key, 214[B] for 2048-bit key and 470[B] for 4096-bit key. This is far too low to encrypt any certificate or asymmetric key, but fair enough to encrypt an AES key.

This leads to a hybrid solution: values are encrypted using an AES-CBC encryption, while only the AES key is encrypted using the device key. Initial values file contains encrypted AES key and plain or AES-CBC encrypted values.

On startup, Key Manager would try to decrypt the AES key using device key (coming from hardware or a special, preloaded file storing just the RSA private, device key). If succeeds, Key Manager decrypts the items and proceed as in the original Initial Values solution.

Detailed Design

Schema changes

initial_values.xsd has to be enhanced to support new elements. New items are:

  • <EncryptionKey> element storing encrypted AES key in Base64 format. This element can appear only once.
  • keys and certificates can provide the data using <EncryptedDer> tag, which contains item DER after AES-CBC encryption in Base64 format.
  • data items can provide the data using following tags:
    • <EncryptedASCII>: AES-CBC encrypted ASCII data (encoded with Base64)
    • <EncryptedBinary>: AES-CBC encrypted binary data (encoded with Base64)
  • all <EncryptedDer>, <EncryptedASCII> and <EncryptedBinary> tags require providing IV attribute containing 16[B] IV for it's item. IV must differ between items for security reasons!

Example file contents: <source lang="xml"> <InitialValues version="1">

 <EncryptionKey>
     QL/5RW1VfS1uya04CWkVy1eykdhnRaTFiQ6Lcv0XFYhqgUKp6+PxxT1xjaz8TCVp
     UcKorZayMPCuStRAylViZfxHFhXKR3awH+FcnGMZrhV6kORy39YCba0NGc5eAk3s
     CBPYdRRiV7ejJSOI8n3zFjituVhHLcLuZB6xHvQQpQFFYV0BuF3BXfx6roP4+Olj
     bZ1fYDrj8QIzqi3RV/ORGbl1BqHVRoMN/5XB+8oVKVn/EMRZPao4hnkV3pTI01Ss
     Wid4fIHzBpi8rkkxr80/ym2BkeA/piaPNGOQtKjVfBOn/SuR2LQJreG6QbI6MYXC
     ZVOanzc0euaenw1q9b+yEQ==
 </EncryptionKey>
 
   <EncryptedASCII IV="__another_IV_2__">zuBDjp8ptFthrU69Ua5cfg==</EncryptedASCII>
 

</InitialValues> </source>

Note the data above can be decrypted only when having access to original RSA device private key! Check the XSD and example.xml details: Gerrit link - in example.xml note please no size limit on encrypted items.

Parser changes

  • implement schema changes.
  • SW device key requires providing additional sw_key.xsd and appropriate key XML file.
  • initial values parser must:
    • obtain the device key:
      • parse the SW device key if TZ not present; or
      • ask TZ to provide device key alias; then
    • parse the initial value file:
      • if encrypted AES key present, use RSA-OAEP decryption using SW or TZ mechanism.
      • if any encrypted item found, use AES-CBC decryption using SW or TZ mechanism.

SW or TZ decryption

Device may or may not support TZ. Key Manager provides convenient Crypto::Decider class that decides if requested functionality should be performed using SW or TZ.

Key Manager TZ backend required changes:

  • make Crypto::Decider select TZ on the very specific platform that supports TZ.;
  • implement mechanism to obtain the device private key alias from TZ. This alias will be provided to crypto/tz-backend/store.hpp::getKey();
  • implement RSA-OAEP decryption (manager/crypto/tz-backend/key.cpp).;
  • implement AES-CBC decryption (manager/crypto/tz-backend/key.cpp).;

Encrypted file preparation

  • [general] to Base64 encode any data: <source lang="bash">openssl enc -base64 -in binary.encrypted -out binary.encrypted.base64</source>
  • to RSA-OAEP encrypt AES key:
    • encrypt AES key: <source lang="bash">openssl rsautl -encrypt -oaep -pubin -inkey device.pub -in encryption_AES_key -out encryption_AES_key.encrypted</source>
    • Base64 encode encrypted AES key: <source lang="bash">openssl enc -base64 -in encryption_AES_key.encrypted -out encryption_AES_key.encrypted.base64</source>
    • put contents of encryption_AES_key.encrypted.base64 to the initial values file <EncryptionKey> tag.
  • to AES-CBC an item:
    • put your 16B IV to encryption_AES_IV
    • encrypt your data: <source lang="bash">openssl aes-256-cbc -K `xxd -p -c 64 encryption_AES_key` -iv `xxd -p -c 64 encryption_AES_IV` -e -in data_to_crypt -out data_to_crypt.encrypted</source>
    • Base64 encode encrypted item: <source lang="bash">openssl enc -base64 -in data_to_crypt.encrypted -out data_to_crypt.encrypted.base64</source>
    • put contents of data_to_crypt.encrypted.base64 to the initial values file under your Key, Cert or Data item
    • put IV from encryption_AES_IV into the IV attribute


See also

Basic Discussion for key-manager Architecture Design