Mobile Device Management
 
Native SDK
ddar::abstract_crypto Class Reference

Base class for dual-dar crypto implementation. More...

#include <ddar.h>

List of all members.

Public Member Functions

virtual bool prepare (context *context, metadata *md)=0
 Callback to initialize ephemeral cache.
virtual bool encrypt (metadata *md, void *pt, void *ct, unsigned long page_offset, int page_len)=0
 Callback when a file is currently being written to the disk.
virtual bool decrypt (metadata *md, void *ct, unsigned long page_offset, int page_len)=0
 Callback when a file is currently being read from the disk.

Detailed Description

Base class for dual-dar crypto implementation.

A derived class must override all the public virtual functions. Crypto module must have an entry symbol DDAR_ABSTRACT_CRYPTO_SYM with a type of abstract_crypto then the system daemon can dynamically load the derived class at device boot up

 MyTestCrypto.cpp
 MyTestCrypto DDAR_ABSTRACT_CRYPTO_SYM;
 

When abstract_crypto callbacks are invoked?

  • First encrypt/decrypt after inode object allocation When inode object is allocated in the kernel, ephemeral cache is empty. Then the next encrypt or decrypt operation requested to dualdar daemon, it invoke abstract_crypto::prepare(). In the prepare function, all the initialization logic should be performed that should happen only once for the inode object's lifetime (until inode invalidation). For example, an implementation of prepare might derive file encryption key (FEK) from the master key in secret object and store the FEK in ephemeral cache to further use it within encrypt/decrypt callbacks
  • Writeback (delayed disk I/O): abstract_crypto::encrypt() is called while (right before) dirty pages are written out to disk dirty page writeback occurs in three situations:
    • Memory pressure. when free memory shrinks below a specific threshold (dirty_background_ratio)
    • Timer. When dirty grows older than a specific period (to avoid remain dirty indefinitely). Flusher threads periodically wake up (unrelated to low-memory condition) and writes out old dirty pages
    • sync() and fsync() system-calls when user process invokes them, the kernel performs write-back on demand. Some of c++/Java methods internally call fsync()
  • Readahead: abstract_crypto::decrypt() is called by a user process' read() system call and the file content is not yet loaded in memory

Data lock state: When Android framework decides to trigger user state transition into data lock state, it executes as follows

  • Clear all secret object associated with the user. The memory space for each secret object is cleared by overwritting with zeros (NIAP, FCS_CKM_EXT.4, Cryptographic Key Destruction)
  • Secure inode object invalidation:
    • Immediately flush dirty pages into disk blocks
    • Free page caches connected to each inode object. Data contents in each page is cleared from memory by overwritting with zeros
    • Ephemeral cache page is cleared by overwritting with zeros and freed to memory pool
    • Free inode object
  • inode invalidation is triggered in following cases:
    • In data lock state, all the inode object within the user are invalidated
    • File deletion
    • Memory pressue (page frame reclamation), the kernel select old pages (based on Least-Recently Used list) which can freed for new uses before physical memory is exhausted

Declaring library version: Crypto library shall declare library version by defining a symbol DDAR_ABSTRACT_CRYPTO_VERSION This version string is exposed to Java interface DualDARPlatformInfo.clientLibVersion.

 MyTestCrypto.cpp
 const unsigned char *DDAR_ABSTRACT_CRYPTO_VERSION = "1.0.1";  // <major>.<minor>.<patch>
 

Member Function Documentation

virtual bool ddar::abstract_crypto::decrypt ( metadata md,
void *  ct,
unsigned long  page_offset,
int  page_len 
) [pure virtual]

Callback when a file is currently being read from the disk.

The source and destination pages are same, sub classes are expected to implement an inplace decryption

 bool MyTestCrypto::decrypt(ddar::metadata *md, void *ct, unsigned long page_offset, int page_len) {
  struct my_metadata *my_md = (struct my_metadata *) md->ephemeral_addr;
  if(mSSL.decrypt((unsigned char *)ct, page_len,
          (unsigned char *)my_md->fek, NULL,
          (unsigned char *)ct) > 0)  // implement crypto inplace
      return true;
  return false;
 }
 
Parameters:
ctsource and destination page of kernel memory that contains cipher text from the disk
virtual bool ddar::abstract_crypto::encrypt ( metadata md,
void *  pt,
void *  ct,
unsigned long  page_offset,
int  page_len 
) [pure virtual]

Callback when a file is currently being written to the disk.

 bool MyTestCrypto::encrypt(ddar::metadata *md, void *pt, void *ct, unsigned long page_offset, int page_len) {
  struct my_metadata *my_md = (struct my_metadata *) md->ephemeral_addr;
  if(mSSL.encrypt((unsigned char *)pt, page_len,
          (unsigned char *)my_md->fek, NULL,
          (unsigned char *)ct) > 0)
      return true;
  return false;
 }
 
Parameters:
ptsource filesystem page cache that contains plain text from user program
ctdestination page of kernel memory that is being written to the disk
page_offsetpage into the associated file
virtual bool ddar::abstract_crypto::prepare ( context context,
metadata md 
) [pure virtual]

Callback to initialize ephemeral cache.

This is called when first encryption/decryption after inode object allocation

 bool MyTestCrypto::prepare(ddar::context *context, ddar::metadata *md) {
  ddar::secret *sec = context->get_secret("my_master_key_alias");  # vendor client app defined
  struct my_metadata *my_md = (struct my_metadata *) md->ephemeral_addr;
  char *iv = NULL;
  char efek[FEK_KEYLEN];
  int rc = md->persistent_get(ALIAS_EFEK, efek);
  if (rc <= 0) {
      // No FEK associate with the file, create new
      mSSL.rand_bytes(my_md->fek, FEK_KEYLEN);
      rc = mSSL.encrypt((unsigned char *)my_md->fek, FEK_KEYLEN,
              (unsigned char *)sec->data, (unsigned char *)iv, (unsigned char *)efek);
      if (rc < 0)
          return false;  // failed to encrypt efek
      md->persistent_set(ALIAS_EFEK, efek, FEK_KEYLEN);  // store efek
  } else {
      mSSL.decrypt((unsigned char *)efek, rc,
          (unsigned char *)sec->data, (unsigned char *)iv, (unsigned char *)my_md->fek);
  }
  
Parameters:
contextaccess user-wide global info
mdmetadata to access per-file info

The documentation for this class was generated from the following file:
 All Classes Namespaces Functions Variables Enumerations