# Key Manager

The Key Manager (KM) provides JavaScript applications with key management and cryptographic functionality. It makes this available on the device's public bus via a number of API calls. The Key Manager implements a key store , allowing apps a place to safely keep keys where they are readily available for cryptographic operations.

The Key Manager is designed to do the following:

- Provide apps and services easy access to cryptographic functions they need to perform local tasks safely, comply with standards, and interact with external services.

- Protect user secrets (keys, passwords, etc.) in the event of loss or theft. Even if the device is in Developer Mode, possession alone should not provide access to secrets.

- Protect application secrets (keys, tokens, etc.) from disclosure to the user or other applications.

- Provide apps and services access, via a flexible and easy-to-use interface, to commonly used encryption algorithms such as AES, 3DES, and HMAC, and digest functions such as SHA-1.

Keys are stored encrypted in a database. They have both an app name (i.e., `"com.someone.appname"`) and a key name. The latter is not necessarily unique—two different apps can both have a key with the same name. However, the Key Manager service obtains the app name from the protocol, making it almost impossible for apps to use the same keys.

An app can use the KM service to store or generate a key while specifying its encryption algorithm type, length, and an option to hide the key and never return it to the application, though it remains available for cryptographic operations.

In this section:

- Supported Key Types
- Supported Block Cipher Modes
- Supported Block Cipher Padding Modes
- Methods

## Supported Key Types

In cryptography, a key is a piece of information (a parameter) that determines the functional output of a cryptographic algorithm or cipher. Without a key, the algorithm would have no result. In encryption, a key specifies the particular transformation of plaintext (unencrypted text) into ciphertext (encrypted text), or vice-versa during decryption. Keys are also used in other cryptographic algorithms, such as digital signature schemes and message authentication codes.

Key Manager supports the following key encryption algorithm types:

- AES—Advanced Encryption Standard. AES-128, AES-192, and AES-256 are supported.

- 3DES (3 key outer CBC)—The size includes the padding.

- HMAC — SHA1 —Hash-based Message Authentication Code - Secure Hash Algorithm-1 . Any size from 16 bytes up is supported.

- BLOB—For storing any type of data, up to 4k bytes.

- ASCIIBLOB—An ascii (non-base64 encoded) BLOB. The data must be in valid JSON format with no unescaped JSON formatting characters.

## Supported Block Cipher Modes

A block cipher is a type of symmetric-key encryption algorithm that transforms a fixed-length block of plaintext data into a block of ciphertext data of the same length. This transformation takes place with the aid of a user-provided secret key. Decryption is performed by applying the reverse transformation to the ciphertext block using the same secret key. The fixed length is called the block size, and for many block ciphers, the block size is 64 bits or 128 bits.

AES and 3DES are the supported block ciphers.

Key Manager supports the following block cipher modes:

- CBC—Cipher Block Chaining.
- ECB—Electronic CodeBook.
- CFB—Cipher FeedBack Mode.

## Supported Block Cipher Padding Modes

Because a block cipher works on units of a fixed size, but messages come in a variety of lengths, some modes (mainly CBC) require that the final block be padded before encryption.

Key Manager supports the following block cipher padding modes:

- None—Data must be a multiple of the block size.
- PKCS1—Public Key Cryptography Standards #1.

## Methods

You can asynchronously call Key Manager methods through the `serviceRequest` function which takes 2 parameters:

- The Key Manager URI (Uniform Resource Identifier).
- A JSON (JavaScript Object Notation) object containing parameters, callback functions, and other data.

Depending on outcome, the API returns a JSON result to either the success or failure callback function. These functions can then parse the result. Your app needs to take into account the call's asynchronous nature (results may be delayed) and not block user interaction while awaiting results.

### About JSON

For more information on calling services such as Key Manager, see the Services Overview.

JSON is a lightweight data-interchange text format based on a subset of the JavaScript programming language that is easy for humans to read and write and for machines to parse and generate. Like XML, JSON contains name/value pair collections and ordered list of values (i.e., arrays).

For more information on JSON, see the following websites:

- JSON objects, values and format—http://www.json.org/
- JSON schemas—http://tools.ietf.org/html/draft-zyp-json-schema-02

A primer on how JSON data objects are formatted is beyond the scope of this document—consult the two links above for more information. However, in brief:

- Curly brackets ('{', '}') are used to enclose objects.
- Angle brackets ('[', ']') are used to enclose arrays.
- Colons (':') are used as delimiters in name/value pairs.
- Quotes (") are used for string values. Numeric values are not quoted.

### Data Formatting

Since JSON objects are composed and formatted with ascii (UTF-8) text, data to and from the Key Manager service needs to be base64 encoded to avoid having it interpreted as JSON formatting instructions. This includes key data, data to be encrypted or decrypted, and IVs (Initialization Vectors). The webOS JavaScript foundation libraries provide the following base64 encoding and decoding functions: TBD

### Key Manager Public Methods

- crypt—Encrypts or decrypts data.
- export—Wraps a key using a specified wrapping key.
- fetchKey—Returns key metadata and key data.
- generate—Generates a key.
- import—Takes a wrapped key and imports it.
- keyInfo—Returns key metadata but not the key data.
- remove—Deletes a key from the database.
- store—Stores a key in the database.

### crypt

You can use this API to encrypt or decrypt data. The key encryption algorithm specified (AES, 3DES, or HMACSHA1) must be the same as the one used to create the key.

Key data needs to be base64 encoded. Since JSON objects are composed and formatted with ascii (UTF-8) text, data needs to be base64 encoded to avoid having it interpreted as JSON formatting instructions. The webOS JavaScript foundation libraries provide the following base64 encoding/decoding functions: TBD

#### Schema

>     {
>       "keyname"   : string,
>       "algorithm" : string,
>       "pad"       : string,
>       "mode"      : string,
>       "iv"        : string,
>       "decrypt"   : boolean,
>       "data"      : string
>     }

#### Parameters

Argument | Required | Type | Description
--- | --- | --- | ---
keyname | Yes | string | Key name.
algorithm | Yes | string | Possible values: `"AES", "3DES", or "HMACSHA1"`.
pad | No | string | Possible values: `"PKCS1"`, or `"none"`. Required for block ciphers.
mode | No | string | Possible values: `"CBC", "CFB", "ECB", or "none"`. This is only appropriate for block ciphers. `none` is not valid for block ciphers.
iv | No | string | Initialization Vector—a block of bits that is required to allow a stream cipher or a block cipher to to produce a unique stream independent from other streams produced by the same encryption key without having to go through a re-keying process. Only required for CBC and CFB modes. 16 bytes for AES, 8 bytes for 3DES.
decrypt | Yes | boolean | `false` to encrypt, `true` to decrypt.
data | Yes | string | Data to encrypt or decrypt.

#### Returns

>     {
>       "returnValue" : boolean,
>       "errorText"   : string, |
>       "data"        : string
>     }

Argument | Required | Type | Description
--- | --- | --- | ---
returnValue | Yes | boolean | `true` (success) or `false` (failure)
errorText | No | string | Error message returned on failure.
data | No | string | Encrypted data.

Example

>     this.controller.serviceRequest("palm://com.palm.keymanager/", {
>       method: "crypt",
>       parameters: {
>           "keyname"   : "myKey",
>           "algorithm" : "AES",
>           "decrypt"   : false,
>           "data"      : "Here is my secret, secret credit card number: 3456-8720-8735=0678"
>       },
>       onSuccess: function(e){ Mojo.Log.info("Crypt success, data="+e.data); },
>       onFailure: function(e){ Mojo.Log.info("Crypt failure, err="+e.errorText); }
>     });

### export

Wraps a key using a specified wrapping key. Both keys must belong to the same owner. A key can not wrap itself.

#### Schema

>     {
>       "keyname"        : string,
>       "wrappingkeyname": string
>     }

#### Parameters

Argument | Type | Description
--- | --- | ---
keyname | string | Key name.
wrappingkeyname | string | Wrapping key name.

#### Returns

>     {
>       "returnValue" : boolean,
>       "errorText"   : string, |
>       "wrappedkey"  : string
>     }

Argument | Required | Type | Description
--- | --- | --- | ---
returnValue | Yes | boolean | `true` (success) or `false` (failure)
errorText | No | string | Error message returned on failure.
wrappedkey | No | string | Wrapped key returned on success.

Example

>     this.controller.serviceRequest("palm://com.palm.keymanager/", {
>       method: "export",
>       parameters: {
>           "keyname": "MyKey",
>           "wrappingkeyname": "MyWrappingKey"
>       },
>       onSuccess: function(e) {Mojo.Log.info("KeyManager: export success="+JSON.stringify(e));},
>       onFailure: function(e) {Mojo.Log.info("KeyManager: export failure="+JSON.stringify(e));}
>     });

### fetchKey

Returns key metadata and key data. Key data is returned if the key had been originally stored or generated with nohide = `true`. Otherwise, the call fails and a "key is not exportable" error message is returned.

#### Schema

>     {
>       "keyname" : string
>     }

#### Parameters

Argument | Required | Type | Description
--- | --- | --- | ---
keyname | Yes | string | Key name.

#### Returns

>     {
>       "returnValue" : boolean,
>       "errorText"   : string, |
>       "keyname"     : string,
>       "type"        : string,
>       "keydata"     : string
>       "nohide"      : boolean
>     }

Argument | Required | Type | Description
--- | --- | --- | ---
returnValue | Yes | boolean | `true` (success) or `false` (failure).
errorText | No | string | Error message returned on failure.
keyname | No | string | Key name. Returned on success.
type | No | string | Key type. One of the following—`"AES", "3DES", "HMACSHA1", "BLOB", or "ASCIIBLOB"`. Returned on success.
keydata | No | string | Optional key data string. Returned if `nohide` is `true`. Returned on success.
nohide | No | boolean | If `true`, it means key data can be returned with this call. Returned on success.

Example

>     this.controller.serviceRequest("palm://com.palm.keymanager/", {
>       method: "fetchKey",
>       parameters: {
>           "keyname" :"MyKey"
>       },
>       onSuccess: function(e){
>           var MyKeyB64 = Base64.decode(e.keydata);
>           Mojo.Log.info("KeyManager: fetchKey Success: keydata= "+MyKeyB64+ ", keyname="+e.keyname);
>       },
>       onFailure: function(e){ Mojo.Log.info("fetchKey Failure, err="+e.errorText); }
>     });

### generate

Generates a key with the name specified. If `nohide = true`, the key data can be accessed with `fetchKey`.

Types and their size requirements:

- AES—16 (default), 24 or 32 bytes. These sizes correspond to AES 128, 192 or 256 bit.
- 3DES—24 bytes.
- HMACSHA1—16 bytes or up.
- BLOB—Up to 4096 bytes. The BLOB type is used for safely storing data of any kind.
- ASCIIBLOB—Same as BLOB but for storing ascii, JSON formatted text that is not base64 encoded.

#### Schema

>     {
>       "keyname": string,
>       "size"   : integer,
>       "type"   : string,
>       "nohide" : boolean
>     }

#### Parameters

Argument | Required | Type | Description
--- | --- | --- | ---
keyname | Yes | string | Name of key to generate.
size | Yes | integer | Key size in bytes.
type | Yes | string | Key type. Must be one of the following—`"AES", "3DES", "HMACSHA1", "BLOB", or "ASCIIBLOB"`.
nohide | No | boolean | If `false` (default), the key data can not be exported with `fetchKey`.

#### Returns

>     {
>       "returnValue" : boolean,
>       "errorText"   : string
>     }

Argument | Required | Type | Description
--- | --- | --- | ---
returnValue | Yes | boolean | `true` (success) or `false` (failure).
errorText | No | string | Error message returned on failure.

Example

>     this.controller.serviceRequest("palm://com.palm.keymanager/", {
>       method: "generate",
>       parameters: {
>           "keyname" : "MyGenKey",
>           "size"    : 16,
>           "type"    : "HMACSHA1",
>           "nohide"  : true
>       },
>       onSuccess: function(e){ Mojo.Log.info("KeyManager: Generate MyGenKey success, e="+JSON.stringify(e)); },
>       onFailure: function(e){ Mojo.Log.info("KeyManager: Generate MyGenKey failure, e="+JSON.stringify(e)); }
>     });

### import

Import takes a wrapped key and imports it. If the wrapping key is not present, the key is not installed and an error is returned. If successful, the unwrapped key's name is returned. A wrapped key can not replace an existing key with the same owner and name.

#### Schema

>     {
>       "wrappedKey": string
>     }

#### Parameters

Argument | Type | Description
--- | --- | ---
wrappedKey | string | Wrapped key.

#### Returns

>     {
>       "returnValue" : boolean,
>       "errorText"   : string, |
>       "keyname"     : string
>     }

Argument | Required | Type | Description
--- | --- | --- | ---
returnValue | Yes | boolean | `true` (success) or `false` (failure).
errorText | No | string | Error message returned on failure. Returned on success.
keyname | No | string | Key name.

Example

>     this.controller.serviceRequest("palm://com.palm.keymanager/", {
>       method: "import",
>       parameters: {
>           "wrappedKey": "MyWrappedKey"
>       },
>       onSuccess: function(e){ Mojo.Log.info("Import success, e="+JSON.stringify(e)); },
>       onFailure: function(e){ Mojo.Log.info("Import failure, e="+JSON.stringify(e)); }
>     });

### keyInfo

Returns the key's metadata but not the key data.

#### Schema

>     {
>       "keyname" : string
>     }

#### Parameters

Argument | Required | Type | Description
--- | --- | --- | ---
keyname | Yes | string | Key name

#### Returns

>     {
>       "returnValue" : boolean,
>       "errorText"   : string, |
>       "keyname"     : string,
>       "type"        : string,
>       "nohide"      : boolean,
>       "backup"      : boolean,
>       "noexport"    : boolean,
>       "cloud"       : boolean,
>       "unwrap_only" : boolean,
>       "shared"      : boolean
>     }

Argument | Required | Type | Description
--- | --- | --- | ---
returnValue | Yes | boolean | `true` (success) or `false` (failure).
errorText | No | string | Error message returned on failure.
keyname | No | string | Key name. Returned on success.
type | No | string | One of the following—`"AES", "3DES", "HMACSHA1", "BLOB", or "ASCIIBLOB"`. Returned on success.
nohide | No | boolean | Indicates if key data is accessible via fetchKey (`true`), or can only be used for operations (`false`). Returned on success.
backup | No | boolean | Is this key backed up in the cloud with the device backup? Returned on success.
noexport | No | boolean | Key can be exported flag. Returned on success.
cloud | No | boolean | Is this key stored in the cloud and used for backups? Returned on success.
unwrap_only | No | boolean | If `true`, key can only be used to unwrap wrapped keys and no other operation. Returned on success.
shared | No | boolean | Can other apps access the key flag. Returned on success.

Example

>     this.controller.serviceRequest("palm://com.palm.keymanager/", {
>       method: "keyInfo",
>       parameters: {
>           "keyname" :"MyKey"
>       },
>       onSuccess: function(e){ Mojo.Log.info("keyInfo Success: type= "+e.type); },
>       onFailure: function(e){ Mojo.Log.info("keyInfo Failure err="+JSON.stringify(e)); }
>     });

### remove

Given a key name, removes a key from the key store.

#### Schema

>     {
>       "keyname" : string
>     }

#### Parameters

Argument | Required | Type | Description
--- | --- | --- | ---
keyname | Yes | string | Key name.

#### Returns

>     {
>       "returnValue" : boolean,
>       "errorText"   : string
>     }

Argument | Required | Type | Description
--- | --- | --- | ---
returnValue | Yes | boolean | `true` (success) or `false` (failure).
errorText | No | string | Error message on failure.

Example

>     this.controller.serviceRequest("palm://com.palm.keymanager/", {
>       method: "remove",
>       parameters: {
>           "keyname" : "MyKey4"
>       },
>       onSuccess: function(e){ Mojo.Log.info("Remove key success"); },
>       onFailure: function(e){ Mojo.Log.info("Remove key failure, err="+JSON.stringify(e)); }
>     });

### store

Stores a key in the database given a key name, data, key encryption algorithm type, and other optional parameters.

Key data needs to be base64 encoded unless its `type` is `ASCIIBLOB`. Since JSON objects are composed and formatted with ascii (UTF-8) text, data needs to be base64 encoded to avoid having it interpreted as JSON formatting instructions. The webOS JavaScript foundation libraries provide the following base64 encoding/decoding functions: TBD

`Type` must be one of the supported key types—`AES, 3DES, HMACSHA1, BLOB, or ASCIIBLOB.` `BLOB` is not actually a key type, but can be used to safely store data (up to 4096 bytes) of any kind. `ASCIIBLOB` is the same as `BLOB`, but for storing ascii, JSON formatted text.

If `nohide` is set to `false` (default), the key data can not be exported with fetchKey. `BLOB` types should not have `nohide` set, as that makes them useless.

The `backup` flag (keys backed up in the cloud with the device backup) is `false` by default.

The `cloud` flag indicates a key which is stored in the cloud and is a special key for backups. If `true`, The type should be `ASCIIBLOB` and the keydata contains the backup-specific part of the URL for fetching the key.

#### Schema

>     {
>       "keyname" : string,
>       "keydata" : string,
>       "type"    : string,
>       "nohide"  : boolean,
>       "backup"  : boolean,
>       "cloud"   : boolean
>     }

#### Parameters

Argument | Required | Type | Description
--- | --- | --- | ---
keyname | Yes | string | Key name.
keydata | Yes | string | Key data.
type | Yes | string | Key algroithm encryption type. Must be one of the following—AES, 3DES, HMACSHA1, BLOB, or ASCIIBLOB. 3DES keys must be properly formed with DES parity bits and weak key checking already done.
nohide | No | boolean | If `false` (default), the key data can not be exported with `fetchKey`.
backup | No | boolean | If `true`, this key is backed up in the cloud with the device backup. This field is `false` by default.
cloud | No | boolean | Indicates a key which is stored in the cloud and is a special key for backups. The type should be `ASCIIBLOB` and the `keydata` contains the backup-specific part of the URL for fetching the key.

#### Returns

>     {
>       "returnValue" : boolean,
>       "errorText"   : string
>     }

Argument | Required | Type | Description
--- | --- | --- | ---
returnValue | Yes | boolean | `true` (success) or `false` (failure).
errorText | No | string | Error message returned on failure.

Example

>     // The following base64 encoding functionality is something YOU need to provide
>     var KeyDataB64 = Base64.encode("123456");
>     this.controller.serviceRequest("palm://com.palm.keymanager/", {
>       method: "store",
>       parameters: {
>           "keyname" : "MyKey",
>           "keydata" : KeyDataB64,
>           "type"    : "AES",
>           "nohide"  : true
>       },
>       onSuccess: function(e){ Mojo.Log.info("Store key success"); },
>       onFailure: function(e){ Mojo.Log.info("Store key failure, err="+JSON.stringify(e)); }
>     });