Kernel Key Retention Service — The Linux Kernel documentation


  • Map a special key ID to a real key ID for this process:

    key_serial_t keyctl(KEYCTL_GET_KEYRING_ID, key_serial_t id,
                        int create);
    

    The special key specified by “id” is looked up (with the key being created
    if necessary) and the ID of the key or keyring thus found is returned if
    it exists.

    If the key does not yet exist, the key will be created if “create” is
    non-zero; and the error ENOKEY will be returned if “create” is zero.

  • Replace the session keyring this process subscribes to with a new one:

    key_serial_t keyctl(KEYCTL_JOIN_SESSION_KEYRING, const char *name);
    

    If name is NULL, an anonymous keyring is created attached to the process
    as its session keyring, displacing the old session keyring.

    If name is not NULL, if a keyring of that name exists, the process
    attempts to attach it as the session keyring, returning an error if that
    is not permitted; otherwise a new keyring of that name is created and
    attached as the session keyring.

    To attach to a named keyring, the keyring must have search permission for
    the process’s ownership.

    The ID of the new session keyring is returned if successful.

  • Update the specified key:

    long keyctl(KEYCTL_UPDATE, key_serial_t key, const void *payload,
                size_t plen);
    

    This will try to update the specified key with the given payload, or it
    will return error EOPNOTSUPP if that function is not supported by the key
    type. The process must also have permission to write to the key to be able
    to update it.

    The payload is of length plen, and may be absent or empty as for
    add_key().

  • Revoke a key:

    long keyctl(KEYCTL_REVOKE, key_serial_t key);
    

    This makes a key unavailable for further operations. Further attempts to
    use the key will be met with error EKEYREVOKED, and the key will no longer
    be findable.

  • Change the ownership of a key:

    long keyctl(KEYCTL_CHOWN, key_serial_t key, uid_t uid, gid_t gid);
    

    This function permits a key’s owner and group ID to be changed. Either one
    of uid or gid can be set to -1 to suppress that change.

    Only the superuser can change a key’s owner to something other than the
    key’s current owner. Similarly, only the superuser can change a key’s
    group ID to something other than the calling process’s group ID or one of
    its group list members.

  • Change the permissions mask on a key:

    long keyctl(KEYCTL_SETPERM, key_serial_t key, key_perm_t perm);
    

    This function permits the owner of a key or the superuser to change the
    permissions mask on a key.

    Only bits the available bits are permitted; if any other bits are set,
    error EINVAL will be returned.

  • Describe a key:

    long keyctl(KEYCTL_DESCRIBE, key_serial_t key, char *buffer,
                size_t buflen);
    

    This function returns a summary of the key’s attributes (but not its
    payload data) as a string in the buffer provided.

    Unless there’s an error, it always returns the amount of data it could
    produce, even if that’s too big for the buffer, but it won’t copy more
    than requested to userspace. If the buffer pointer is NULL then no copy
    will take place.

    A process must have view permission on the key for this function to be
    successful.

    If successful, a string is placed in the buffer in the following format:

    Where type and description are strings, uid and gid are decimal, and perm
    is hexadecimal. A NUL character is included at the end of the string if
    the buffer is sufficiently big.

    This can be parsed with:

    sscanf(buffer, "%[^;];%d;%d;%o;%s", type, &uid, &gid, &mode, desc);
    
  • Clear out a keyring:

    long keyctl(KEYCTL_CLEAR, key_serial_t keyring);
    

    This function clears the list of keys attached to a keyring. The calling
    process must have write permission on the keyring, and it must be a
    keyring (or else error ENOTDIR will result).

    This function can also be used to clear special kernel keyrings if they
    are appropriately marked if the user has CAP_SYS_ADMIN capability. The
    DNS resolver cache keyring is an example of this.

  • Link a key into a keyring:

    long keyctl(KEYCTL_LINK, key_serial_t keyring, key_serial_t key);
    

    This function creates a link from the keyring to the key. The process must
    have write permission on the keyring and must have link permission on the
    key.

    Should the keyring not be a keyring, error ENOTDIR will result; and if the
    keyring is full, error ENFILE will result.

    The link procedure checks the nesting of the keyrings, returning ELOOP if
    it appears too deep or EDEADLK if the link would introduce a cycle.

    Any links within the keyring to keys that match the new key in terms of
    type and description will be discarded from the keyring as the new one is
    added.

  • Move a key from one keyring to another:

    long keyctl(KEYCTL_MOVE,
                key_serial_t id,
                key_serial_t from_ring_id,
                key_serial_t to_ring_id,
                unsigned int flags);
    

    Move the key specified by “id” from the keyring specified by
    “from_ring_id” to the keyring specified by “to_ring_id”. If the two
    keyrings are the same, nothing is done.

    “flags” can have KEYCTL_MOVE_EXCL set in it to cause the operation to fail
    with EEXIST if a matching key exists in the destination keyring, otherwise
    such a key will be replaced.

    A process must have link permission on the key for this function to be
    successful and write permission on both keyrings. Any errors that can
    occur from KEYCTL_LINK also apply on the destination keyring here.

  • Unlink a key or keyring from another keyring:

    long keyctl(KEYCTL_UNLINK, key_serial_t keyring, key_serial_t key);
    

    This function looks through the keyring for the first link to the
    specified key, and removes it if found. Subsequent links to that key are
    ignored. The process must have write permission on the keyring.

    If the keyring is not a keyring, error ENOTDIR will result; and if the key
    is not present, error ENOENT will be the result.

  • Search a keyring tree for a key:

    key_serial_t keyctl(KEYCTL_SEARCH, key_serial_t keyring,
                        const char *type, const char *description,
                        key_serial_t dest_keyring);
    

    This searches the keyring tree headed by the specified keyring until a key
    is found that matches the type and description criteria. Each keyring is
    checked for keys before recursion into its children occurs.

    The process must have search permission on the top level keyring, or else
    error EACCES will result. Only keyrings that the process has search
    permission on will be recursed into, and only keys and keyrings for which
    a process has search permission can be matched. If the specified keyring
    is not a keyring, ENOTDIR will result.

    If the search succeeds, the function will attempt to link the found key
    into the destination keyring if one is supplied (non-zero ID). All the
    constraints applicable to KEYCTL_LINK apply in this case too.

    Error ENOKEY, EKEYREVOKED or EKEYEXPIRED will be returned if the search
    fails. On success, the resulting key ID will be returned.

  • Read the payload data from a key:

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

    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.

    The returned data will be processed for presentation by the key type. For
    instance, a keyring will return an array of key_serial_t entries
    representing the IDs of all the keys to which it is subscribed. The user
    defined key type will return its data as is. If a key type does not
    implement this function, error EOPNOTSUPP will result.

    If the specified buffer is too small, then the size of the buffer required
    will be returned. Note that in this case, the contents of the buffer may
    have been overwritten in some undefined way.

    Otherwise, on success, the function will return the amount of data copied
    into the buffer.

  • Instantiate a partially constructed key:

    long keyctl(KEYCTL_INSTANTIATE, key_serial_t key,
                const void *payload, size_t plen,
                key_serial_t keyring);
    long keyctl(KEYCTL_INSTANTIATE_IOV, key_serial_t key,
                const struct iovec *payload_iov, unsigned ioc,
                key_serial_t keyring);
    

    If the kernel calls back to userspace to complete the instantiation of a
    key, userspace should use this call to supply data for the key before the
    invoked process returns, or else the key will be marked negative
    automatically.

    The process must have write access on the key to be able to instantiate
    it, and the key must be uninstantiated.

    If a keyring is specified (non-zero), the key will also be linked into
    that keyring, however all the constraints applying in KEYCTL_LINK apply in
    this case too.

    The payload and plen arguments describe the payload data as for add_key().

    The payload_iov and ioc arguments describe the payload data in an iovec
    array instead of a single buffer.

  • Negatively instantiate a partially constructed key:

    long keyctl(KEYCTL_NEGATE, key_serial_t key,
                unsigned timeout, key_serial_t keyring);
    long keyctl(KEYCTL_REJECT, key_serial_t key,
                unsigned timeout, unsigned error, key_serial_t keyring);
    

    If the kernel calls back to userspace to complete the instantiation of a
    key, userspace should use this call mark the key as negative before the
    invoked process returns if it is unable to fulfill the request.

    The process must have write access on the key to be able to instantiate
    it, and the key must be uninstantiated.

    If a keyring is specified (non-zero), the key will also be linked into
    that keyring, however all the constraints applying in KEYCTL_LINK apply in
    this case too.

    If the key is rejected, future searches for it will return the specified
    error code until the rejected key expires. Negating the key is the same
    as rejecting the key with ENOKEY as the error code.

  • Set the default request-key destination keyring:

    long keyctl(KEYCTL_SET_REQKEY_KEYRING, int reqkey_defl);
    

    This sets the default keyring to which implicitly requested keys will be
    attached for this thread. reqkey_defl should be one of these constants:

    CONSTANT                                VALUE   NEW DEFAULT KEYRING
    ======================================  ======  =======================
    KEY_REQKEY_DEFL_NO_CHANGE               -1      No change
    KEY_REQKEY_DEFL_DEFAULT                 0       Default[1]
    KEY_REQKEY_DEFL_THREAD_KEYRING          1       Thread keyring
    KEY_REQKEY_DEFL_PROCESS_KEYRING         2       Process keyring
    KEY_REQKEY_DEFL_SESSION_KEYRING         3       Session keyring
    KEY_REQKEY_DEFL_USER_KEYRING            4       User keyring
    KEY_REQKEY_DEFL_USER_SESSION_KEYRING    5       User session keyring
    KEY_REQKEY_DEFL_GROUP_KEYRING           6       Group keyring
    

    The old default will be returned if successful and error EINVAL will be
    returned if reqkey_defl is not one of the above values.

    The default keyring can be overridden by the keyring indicated to the
    request_key() system call.

    Note that this setting is inherited across fork/exec.

    [1] The default is: the thread keyring if there is one, otherwise
    the process keyring if there is one, otherwise the session keyring if
    there is one, otherwise the user default session keyring.

  • Set the timeout on a key:

    long keyctl(KEYCTL_SET_TIMEOUT, key_serial_t key, unsigned timeout);
    

    This sets or clears the timeout on a key. The timeout can be 0 to clear
    the timeout or a number of seconds to set the expiry time that far into
    the future.

    The process must have attribute modification access on a key to set its
    timeout. Timeouts may not be set with this function on negative, revoked
    or expired keys.

  • Assume the authority granted to instantiate a key:

    long keyctl(KEYCTL_ASSUME_AUTHORITY, key_serial_t key);
    

    This assumes or divests the authority required to instantiate the
    specified key. Authority can only be assumed if the thread has the
    authorisation key associated with the specified key in its keyrings
    somewhere.

    Once authority is assumed, searches for keys will also search the
    requester’s keyrings using the requester’s security label, UID, GID and
    groups.

    If the requested authority is unavailable, error EPERM will be returned,
    likewise if the authority has been revoked because the target key is
    already instantiated.

    If the specified key is 0, then any assumed authority will be divested.

    The assumed authoritative key is inherited across fork and exec.

  • Get the LSM security context attached to a key:

    long keyctl(KEYCTL_GET_SECURITY, key_serial_t key, char *buffer,
                size_t buflen)
    

    This function returns a string that represents the LSM security context
    attached to a key in the buffer provided.

    Unless there’s an error, it always returns the amount of data it could
    produce, even if that’s too big for the buffer, but it won’t copy more
    than requested to userspace. If the buffer pointer is NULL then no copy
    will take place.

    A NUL character is included at the end of the string if the buffer is
    sufficiently big. This is included in the returned count. If no LSM is
    in force then an empty string will be returned.

    A process must have view permission on the key for this function to be
    successful.

  • Install the calling process’s session keyring on its parent:

    long keyctl(KEYCTL_SESSION_TO_PARENT);
    

    This functions attempts to install the calling process’s session keyring
    on to the calling process’s parent, replacing the parent’s current session
    keyring.

    The calling process must have the same ownership as its parent, the
    keyring must have the same ownership as the calling process, the calling
    process must have LINK permission on the keyring and the active LSM module
    mustn’t deny permission, otherwise error EPERM will be returned.

    Error ENOMEM will be returned if there was insufficient memory to complete
    the operation, otherwise 0 will be returned to indicate success.

    The keyring will be replaced next time the parent process leaves the
    kernel and resumes executing userspace.

  • Invalidate a key:

    long keyctl(KEYCTL_INVALIDATE, key_serial_t key);
    

    This function marks a key as being invalidated and then wakes up the
    garbage collector. The garbage collector immediately removes invalidated
    keys from all keyrings and deletes the key when its reference count
    reaches zero.

    Keys that are marked invalidated become invisible to normal key operations
    immediately, though they are still visible in /proc/keys until deleted
    (they’re marked with an ‘i’ flag).

    A process must have search permission on the key for this function to be
    successful.

  • Compute a Diffie-Hellman shared secret or public key:

    long keyctl(KEYCTL_DH_COMPUTE, struct keyctl_dh_params *params,
                char *buffer, size_t buflen, struct keyctl_kdf_params *kdf);
    

    The params struct contains serial numbers for three keys:

    - The prime, p, known to both parties
    - The local private key
    - The base integer, which is either a shared generator or the
      remote public key
    

    The value computed is:

    result = base ^ private (mod prime)
    

    If the base is the shared generator, the result is the local
    public key. If the base is the remote public key, the result is
    the shared secret.

    If the parameter kdf is NULL, the following applies:

    • The buffer length must be at least the length of the prime, or zero.

    • If the buffer length is nonzero, the length of the result is
      returned when it is successfully calculated and copied in to the
      buffer. When the buffer length is zero, the minimum required
      buffer length is returned.

    The kdf parameter allows the caller to apply a key derivation function
    (KDF) on the Diffie-Hellman computation where only the result
    of the KDF is returned to the caller. The KDF is characterized with
    struct keyctl_kdf_params as follows:

    • char *hashname specifies the NUL terminated string identifying
      the hash used from the kernel crypto API and applied for the KDF
      operation. The KDF implementation complies with SP800-56A as well
      as with SP800-108 (the counter KDF).

    • char *otherinfo specifies the OtherInfo data as documented in
      SP800-56A section 5.8.1.2. The length of the buffer is given with
      otherinfolen. The format of OtherInfo is defined by the caller.
      The otherinfo pointer may be NULL if no OtherInfo shall be used.

    This function will return error EOPNOTSUPP if the key type is not
    supported, error ENOKEY if the key could not be found, or error
    EACCES if the key is not readable by the caller. In addition, the
    function will return EMSGSIZE when the parameter kdf is non-NULL
    and either the buffer length or the OtherInfo length exceeds the
    allowed length.

  • Restrict keyring linkage:

    long keyctl(KEYCTL_RESTRICT_KEYRING, key_serial_t keyring,
                const char *type, const char *restriction);
    

    An existing keyring can restrict linkage of additional keys by evaluating
    the contents of the key according to a restriction scheme.

    “keyring” is the key ID for an existing keyring to apply a restriction
    to. It may be empty or may already have keys linked. Existing linked keys
    will remain in the keyring even if the new restriction would reject them.

    “type” is a registered key type.

    “restriction” is a string describing how key linkage is to be restricted.
    The format varies depending on the key type, and the string is passed to
    the lookup_restriction() function for the requested type. It may specify
    a method and relevant data for the restriction such as signature
    verification or constraints on key payload. If the requested key type is
    later unregistered, no keys may be added to the keyring after the key type
    is removed.

    To apply a keyring restriction the process must have Set Attribute
    permission and the keyring must not be previously restricted.

    One application of restricted keyrings is to verify X.509 certificate
    chains or individual certificate signatures using the asymmetric key type.
    See Asymmetric / Public-key Cryptography Key Type for specific restrictions
    applicable to the asymmetric key type.

  • Query an asymmetric key:

    long keyctl(KEYCTL_PKEY_QUERY,
                key_serial_t key_id, unsigned long reserved,
                const char *params,
                struct keyctl_pkey_query *info);
    

    Get information about an asymmetric key. Specific algorithms and
    encodings may be queried by using the params argument. This is a
    string containing a space- or tab-separated string of key-value pairs.
    Currently supported keys include enc and hash. The information
    is returned in the keyctl_pkey_query struct:

    __u32   supported_ops;
    __u32   key_size;
    __u16   max_data_size;
    __u16   max_sig_size;
    __u16   max_enc_size;
    __u16   max_dec_size;
    __u32   __spare[10];
    

    supported_ops contains a bit mask of flags indicating which ops are
    supported. This is constructed from a bitwise-OR of:

    KEYCTL_SUPPORTS_{ENCRYPT,DECRYPT,SIGN,VERIFY}
    

    key_size indicated the size of the key in bits.

    max_*_size indicate the maximum sizes in bytes of a blob of data to be
    signed, a signature blob, a blob to be encrypted and a blob to be
    decrypted.

    __spare[] must be set to 0. This is intended for future use to hand
    over one or more passphrases needed unlock a key.

    If successful, 0 is returned. If the key is not an asymmetric key,
    EOPNOTSUPP is returned.

  • Encrypt, decrypt, sign or verify a blob using an asymmetric key:

    long keyctl(KEYCTL_PKEY_ENCRYPT,
                const struct keyctl_pkey_params *params,
                const char *info,
                const void *in,
                void *out);
    
    long keyctl(KEYCTL_PKEY_DECRYPT,
                const struct keyctl_pkey_params *params,
                const char *info,
                const void *in,
                void *out);
    
    long keyctl(KEYCTL_PKEY_SIGN,
                const struct keyctl_pkey_params *params,
                const char *info,
                const void *in,
                void *out);
    
    long keyctl(KEYCTL_PKEY_VERIFY,
                const struct keyctl_pkey_params *params,
                const char *info,
                const void *in,
                const void *in2);
    

    Use an asymmetric key to perform a public-key cryptographic operation a
    blob of data. For encryption and verification, the asymmetric key may
    only need the public parts to be available, but for decryption and signing
    the private parts are required also.

    The parameter block pointed to by params contains a number of integer
    values:

    __s32           key_id;
    __u32           in_len;
    __u32           out_len;
    __u32           in2_len;
    

    key_id is the ID of the asymmetric key to be used. in_len and
    in2_len indicate the amount of data in the in and in2 buffers and
    out_len indicates the size of the out buffer as appropriate for the
    above operations.

    For a given operation, the in and out buffers are used as follows:

    Operation ID            in,in_len       out,out_len     in2,in2_len
    ======================= =============== =============== ===============
    KEYCTL_PKEY_ENCRYPT     Raw data        Encrypted data  -
    KEYCTL_PKEY_DECRYPT     Encrypted data  Raw data        -
    KEYCTL_PKEY_SIGN        Raw data        Signature       -
    KEYCTL_PKEY_VERIFY      Raw data        -               Signature
    

    info is a string of key=value pairs that supply supplementary
    information. These include:

    enc= The encoding of the encrypted/signature blob. This

    can be “pkcs1” for RSASSA-PKCS1-v1.5 or
    RSAES-PKCS1-v1.5; “pss” for “RSASSA-PSS”; “oaep” for
    “RSAES-OAEP”. If omitted or is “raw”, the raw output
    of the encryption function is specified.

    hash= If the data buffer contains the output of a hash

    function and the encoding includes some indication of
    which hash function was used, the hash function can be
    specified with this, eg. “hash=sha256”.

    The __spare[] space in the parameter block must be set to 0. This is
    intended, amongst other things, to allow the passing of passphrases
    required to unlock a key.

    If successful, encrypt, decrypt and sign all return the amount of data
    written into the output buffer. Verification returns 0 on success.

  • Watch a key or keyring for changes:

    long keyctl(KEYCTL_WATCH_KEY, key_serial_t key, int queue_fd,
                const struct watch_notification_filter *filter);
    

    This will set or remove a watch for changes on the specified key or
    keyring.

    “key” is the ID of the key to be watched.

    “queue_fd” is a file descriptor referring to an open pipe which
    manages the buffer into which notifications will be delivered.

    “filter” is either NULL to remove a watch or a filter specification to
    indicate what events are required from the key.

    See General notification mechanism for more information.

    Note that only one watch may be emplaced for any particular { key,
    queue_fd } combination.

    Notification records look like:

    struct key_notification {
            struct watch_notification watch;
            __u32   key_id;
            __u32   aux;
    };
    

    In this, watch::type will be “WATCH_TYPE_KEY_NOTIFY” and subtype will be
    one of:

    NOTIFY_KEY_INSTANTIATED
    NOTIFY_KEY_UPDATED
    NOTIFY_KEY_LINKED
    NOTIFY_KEY_UNLINKED
    NOTIFY_KEY_CLEARED
    NOTIFY_KEY_REVOKED
    NOTIFY_KEY_INVALIDATED
    NOTIFY_KEY_SETATTR
    

    Where these indicate a key being instantiated/rejected, updated, a link
    being made in a keyring, a link being removed from a keyring, a keyring
    being cleared, a key being revoked, a key being invalidated or a key
    having one of its attributes changed (user, group, perm, timeout,
    restriction).

    If a watched key is deleted, a basic watch_notification will be issued
    with “type” set to WATCH_TYPE_META and “subtype” set to
    watch_meta_removal_notification. The watchpoint ID will be set in the
    “info” field.

    This needs to be configured by enabling:

    “Provide key/keyring change notifications” (KEY_NOTIFICATIONS)



  • Source link

    Leave a Reply

    Your email address will not be published. Required fields are marked *