Friday, January 15, 2016

Linux Security Topic : Key Management/Service

The below text explains the basics of key service and relevant terms. It discusses in length the role of kernel in key service management. The Key service is an kernel's abstraction of creation of cryptographic keys, the actual interface for crypto hardware drivers  to the service is not covered here.

The Master References :- https://www.kernel.org/doc/Documentation/security/


===============================================================
HOW TO ENABLE KEY MANAGEMENT/SERVICE IN THE KERNEL/USERSPACE
===============================================================

The key service can be configured on by enabling: "Security options"/"Enable access key retention support" (CONFIG_KEYS) in the arch/../../defconfig or dynamacally using make menuconfig.

This service allows cryptographic keys, authentication tokens, cross-domain user mappings, and similar to be cached in the kernel for the use of filesystems and other kernel services

In the USERSPACE, the keyutils - In-kernel key management utilities is needed to support it. Refer :- http://man7.org/linux/man-pages/man7/keyutils.7.html for more details.


============
KEY BASICS
============

KEYS represent units of cryptographic data, authenticationtokens, keyrings, etc.. These are represented in the kernel by struct key.

Each key has a number of attributes:

A serial number :- Each key is issued a serial number of type key_serial_t that is unique for
the lifetime of that key. All serial numbers are positive non-zero 32-bit integers.

A type :- Each key is of a defined "type". Types must be registered inside the kernel by a kernel service (such as a filesystem) before keys of that type can be added or used. Userspace programs cannot define new types directly. Key types are represented in the kernel by struct key_type. This defines a number of operations that can be performed on a key of that type. Note that if a type be removed from the system, all the keys of that type will be invalidated.

A description (for matching a key in a search) : Each key has a description. This should be a printable string. The key type provides an operation to perform a match between the description on a key and a criterion string.

Access control information : Each key has an owner user ID, a group ID and a permissions mask. These are used to control what a process may do to a key from userspace, and whether a kernel service will  be able to find the key. 

An expiry time : Each key can be set to expire at a specific time by the key type's instantiation function. Keys can also be immortal.

A payload : This is a quantity of data that represent the actual "key".  In the case of a keyring, this is a list of keys to which the keyring links; In the case of a user-defined key, it's an arbitrary blob of data.


State :

 Each key can be in one of a number of basic states:

(a) Un-instantiated. The key exists, but does not have any data attached. Keys being requested from userspace will be in this state.

  (b) Instantiated. This is the normal state. The key is fully formed, and  has data attached.

  (c) Negative. This is a relatively short-lived state. The key acts as a
note saying that a previous call out to userspace failed, and acts as
a throttle on key lookups. A negative key can be updated to a normal
state.

  (d) Expired. Keys can have lifetimes set. If their lifetime is exceeded,
they traverse to this state. An expired key can be updated back to a
normal state.

  (e) Revoked. A key is put in this state by userspace action. It can't be
 found or operated upon (apart from by unlinking it).

  (f) Dead. The key's type was unregistered, and so the key is now useless.

 
Important Points : 

(a) A payload is not mandatory; and the payload can, in fact, just be a value stored in the struct key itself.

(b) When a key is instantiated, the key type's instantiation function is called with a blob of data, and that then creates the key's payload in  the kernel.

(c) when userspace wants to read back the contents of the key, if  permitted, another key type operation will be called to convert the key's attached payload back into a blob of data.

(d) Userspace programs can use a key's serial numbers as a way to gain access to it, subject to permission checking.

(e) Userspace programs cannot define new types directly. Key types are represented 
in the kernel by struct key_type.For further information on key_type refer :- https://www.kernel.org/doc/Documentation/security/keys.txt

(f) Kernel maintains all datastructures for key managemnent. Userspace can make system calls to use/update keys. We will discuss this in detail in the later part of the document.


=========
KEYRINGS
=========

These are a special type of key that can hold links to other keys. Processes each have three standard keyring subscriptions that a kernel service can search for relevant keys.


==================================================
USERSPACE SYSTEM CALL INTERFACE WITH THE KERNEL
==================================================

Userspace can manipulate keys directly through three new syscalls: add_key, request_key and keyctl. It is important to note here that mostly the key created and added by the kernel and user space just sees it and authenticates it.

For e.g. Trusted and Encrypted Keys are two new key types added to the existing kernel key ring service.  Both of these new types are variable length symmetric keys, and in both cases all keys are created in the kernel, and user space sees, stores, and loads only encrypted blobs.

1.Create a new key and add it to the nominated keyring:

key_serial_t add_key(const char *type, const char *desc,
    const void *payload, size_t plen,
    key_serial_t keyring);

2. When referring to a key directly, userspace programs should use the key's serial number to directly get the key. Search the process's keyrings for a key, potentially calling out to userspace to create it. It is important to note that this API is similar to the other API provided to kernel services(e.g Filesystem) to search or request a key.

key_serial_t request_key(const char *type, const char *description,
const char *callout_info,
key_serial_t dest_keyring); 

For more description of this API and its relavent usage related to processes , 
refer :-https://www.kernel.org/doc/Documentation/security/keys-request-key.txt


3. Read the payload data from a key - one of the important usage of keyctl.This function attempts to read the payload data  from the specified key into the buffer. The process must have read permission on the key to succeed.  

long keyctl(KEYCTL_READ, key_serial_t keyring, char *buffer, size_t buflen);

For all other types of keyctl,  please refer :- http://man7.org/linux/man-pages/man7/keyutils.7.html

The application of keyctl is brought out when a key is created for Filesystem and the filesystem is then mounted using the key.

Refer :- https://www.kernel.org/doc/Documentation/security/keys-ecryptfs.txt


============================================
USAGE OF KEYCTL for Filesystem key authentication
============================================

important commands for keyctl :-

keyctl add encrypted name "new ecryptfs key-type:master-key-name keylen" ring
keyctl add encrypted name "load hex_blob" ring
keyctl update keyid "update key-type:master-key-name"

Example of encrypted key usage with the eCryptfs filesystem:

Create an encrypted key "1000100010001000" of length 64 bytes with format
'ecryptfs' and save it using a previously loaded user key "test":

    $ keyctl add encrypted 1000100010001000 "new ecryptfs user:test 64" @u
    19184530

    $ keyctl print 19184530
    ecryptfs user:test 64 490045d4bfe48c99f0d465fbbbb79e7500da954178e2de0697
    dd85091f5450a0511219e9f7cd70dcd498038181466f78ac8d4c19504fcc72402bfc41c2
    f253a41b7507ccaa4b2b03fff19a69d1cc0b16e71746473f023a95488b6edfd86f7fdd40
    9d292e4bacded1258880122dd553a661

    $ keyctl pipe 19184530 > ecryptfs.blob

Mount an eCryptfs filesystem using the created encrypted key "1000100010001000"
into the '/secret' directory:

    $ mount -i -t ecryptfs -oecryptfs_sig=1000100010001000,\
      ecryptfs_cipher=aes,ecryptfs_key_bytes=32 /secret /secret


=====================================
KERNEL SERVICES FOR KEY MANAGEMENT
=====================================

The kernel services for key management can be broken down into two areas: keys and key types.

Firstly, the kernel service registers its type, then it searches for a key of that type. It should retain the key as long as it has need of it, and then it should release it. 

E.g. For a filesystem or device file, a search would probably be performed during the open call, and the key released upon close. 

To access the key manager, the following header must be included:
#include

Some of the important kernel functions are described below, for complete list you can refer : - https://www.kernel.org/doc/Documentation/security/keys.txt

1. A keyring can be created by:

struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
const struct cred *cred,
key_perm_t perm,
unsigned long flags,
struct key *dest);

2. A kernel service may want to define its own key type. For instance, an AFS filesystem might want to define a key type. To do this, it author fills in  a key_type struct and registers it with the system.

(a)To register a key type, the following function should be called:

int register_key_type(struct key_type *type);

(b) To unregister a key type, call:

void unregister_key_type(struct key_type *type);


3. To get the Key, following are the functions to be called by Kernel service.

struct key *__key_get(struct key *key);
struct key *key_get(struct key *key);

4. A key's serial number can be obtained by calling:

key_serial_t key_serial(struct key *key);

5. To search for a key, call:

struct key *request_key(const struct key_type *type,
const char *description,
const char *callout_info);

References :- https://www.kernel.org/doc/Documentation/security/

No comments:

Post a Comment