blob: d394a5cd69930ac7fd4274258e4ef116f08aa27b [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <lk/compiler.h>
#include <stdbool.h>
#include <stdint.h>
#define HWKEY_PORT "com.android.trusty.hwkey"
#define HWKEY_KDF_VERSION_BEST 0
#define HWKEY_KDF_VERSION_1 1
/**
* HWKEY_OPAQUE_HANDLE_MAX_SIZE: The maximum size of an opaque handle returned
* by the hwkey service.
*/
#define HWKEY_OPAQUE_HANDLE_MAX_SIZE 128
/* Maximum valid size of a hwkey message, including context or key material. */
#define HWKEY_MAX_MSG_SIZE 2048
/**
* enum hwkey_cmd - command identifiers for hwkey functions
*/
enum hwkey_cmd {
HWKEY_RESP_BIT = 1,
HWKEY_REQ_SHIFT = 1,
HWKEY_GET_KEYSLOT = (0 << HWKEY_REQ_SHIFT),
HWKEY_DERIVE = (1 << HWKEY_REQ_SHIFT),
/*
* commands for &struct hwkey_derive_versioned_msg
*/
HWKEY_DERIVE_VERSIONED = (2 << HWKEY_REQ_SHIFT),
};
/**
* enum hwkey_err - error codes for hwkey protocol
* @HWKEY_NO_ERROR: all OK
* @HWKEY_ERR_GENERIC: unknown error. Can occur when there's an
* internal server error, e.g. the server runs out
* of memory or is in a bad state.
* @HWKEY_ERR_NOT_VALID: input not valid. May occur if the non-buffer
* arguments passed into the command are not valid,
* for example if the KDF version passed to derive
* is not any supported version.
* @HWKEY_ERR_BAD_LEN: buffer is unexpected or unaccepted length.
* May occur if received message is not at least
* the length of the header, or if the payload
* length does not meet constraints for the
* function.
* @HWKEY_ERR_NOT_IMPLEMENTED: requested command not implemented
* @HWKEY_ERR_NOT_FOUND: requested keyslot not found
* @HWKEY_ERR_ALREADY_EXISTS: requested opaque handle has already been
* retrieved. Close the connection and reconnect
* to clear this handle and retrieve a new handle.
*/
enum hwkey_err {
HWKEY_NO_ERROR = 0,
HWKEY_ERR_GENERIC = 1,
HWKEY_ERR_NOT_VALID = 2,
HWKEY_ERR_BAD_LEN = 3,
HWKEY_ERR_NOT_IMPLEMENTED = 4,
HWKEY_ERR_NOT_FOUND = 5,
HWKEY_ERR_ALREADY_EXISTS = 6,
};
/**
* struct hwkey_msg_header - common header for hwkey messages
* @cmd: command identifier
* @op_id: operation identifier, set by client and echoed by server.
* Used to identify a single operation. Only used if required
* by the client.
* @status: operation result. Should be set to 0 by client, set to
* a enum hwkey_err value by server.
*
* Common header shared between &struct hwkey_msg and &struct
* hwkey_derive_versioned_msg. Which message struct is used depends on the
* &struct hwkey_msg_header.cmd field, see each message struct for details.
*/
struct hwkey_msg_header {
uint32_t cmd;
uint32_t op_id;
uint32_t status;
} __PACKED;
/**
* DOC: hwkey protocol
* - Client opens channel to the server, then sends one or more
* requests and receives replies.
*
* - Client is allowed to keep the channel opened for the duration
* of the session.
*
* - Client is allowed to open multiple channels, all such channels
* should be treated independently.
*
* - Client is allowed to issue multiple requests over the same channel
* and may receive responses in any order. Client must check op_id
* to determine corresponding request.
*
* - The request and response structure is shared among all API calls.
* The data required for each call is as follows:
*
* hwkey_get_keyslot:
*
* Request:
* @cmd: HWKEY_REQ_GET_KEYSLOT
* @op_id: client specified operation identifier. Echoed
* in response.
* @status: must be 0.
* @arg1: unused
* @arg2: unused
* @payload: string identifier of requested keyslot, not null-terminated
*
* Response:
* @cmd: HWKEY_RESP_GET_KEYSLOT
* @op_id: echoed from request
* @status: operation result, one of enum hwkey_err
* @arg1: unused
* @arg2: unused
* @payload: unencrypted keyslot data, or empty on error
*
* hwkey_derive:
*
* Request:
* @cmd: HWKEY_REQ_DERIVE
* @op_id: client specified operation identifier. Echoed
* in response.
* @status: must be 0.
* @arg1: requested key derivation function (KDF) version.
* Use HWKEY_KDF_VERSION_BEST for best version.
* @arg2: unused
* @payload: seed data for key derivation. Size must be equal
* to size of requested key.
*
* Response:
* @cmd: HWKEY_RESP_DERIVE
* @op_id: echoed from request
* @status: operation result, one of enum hwkey_err.
* @arg1: KDF version used. Always different from request if
* request contained HWKEY_KDF_VERSION_BEST.
* @arg2: unused
* @payload: derived key
*/
/**
* struct hwkey_msg - common request/response structure for hwkey
* @header: message header. @header.cmd must be either %HWKEY_GET_KEYSLOT or
* %HWKEY_DERIVE (optionally ORed with %HWKEY_RESP_BIT).
* @arg1: first argument, meaning determined by command issued.
* Must be set to 0 if unused.
* @arg2: second argument, meaning determined by command issued
* Must be set to 0 if unused.
* @payload: payload buffer, meaning determined by command issued
*/
struct hwkey_msg {
struct hwkey_msg_header header;
uint32_t arg1;
uint32_t arg2;
uint8_t payload[0];
};
STATIC_ASSERT(sizeof(struct hwkey_msg) == 20);
/**
* enum hwkey_rollback_version_source - Trusty rollback version source.
* @HWKEY_ROLLBACK_COMMITTED_VERSION:
* Gate the derived key based on the anti-rollback counter that has been
* committed to fuses or stored. A version of Trusty with a version smaller
* than this value should never run on the device again. The latest key may
* not be available the first few times a new version of Trusty runs on the
* device, because the counter may not be committed immediately. This
* version source may not allow versions > 0 on some devices (i.e. rollback
* versions cannot be committed).
* @HWKEY_ROLLBACK_RUNNING_VERSION:
* Gate the derived key based on the anti-rollback version in the signed
* image of Trusty that is currently running. The latest key should be
* available immediately, but the Trusty image may be rolled back on a
* future boot. Care should be taken that Trusty still works if the image is
* rolled back and access to this key is lost. Care should also be taken
* that Trusty cannot infer this key if it rolls back to a previous version.
* For example, storing the latest version of this key in Trusty’s storage
* would allow it to be retrieved after rollback.
*/
enum hwkey_rollback_version_source {
HWKEY_ROLLBACK_COMMITTED_VERSION = 0,
HWKEY_ROLLBACK_RUNNING_VERSION = 1,
};
#define HWKEY_ROLLBACK_VERSION_CURRENT (-1)
/**
* enum hwkey_derived_key_options - Options for derived versioned keys
* @HWKEY_DEVICE_UNIQUE_KEY_TYPE: A key unique to the device it was derived on.
* This key should never be available outside of
* this device. This key type is the default.
* @HWKEY_SHARED_KEY_TYPE: A key shared across a family of devices. May not be
* supported on all device families. This derived key
* should be identical on all devices of a particular
* family given identical inputs, if supported.
*
* @HWKEY_DEVICE_UNIQUE_KEY_TYPE and @HWKEY_SHARED_KEY_TYPE conflict and cannot
* both be used at the same time.
*/
enum hwkey_derived_key_options {
HWKEY_DEVICE_UNIQUE_KEY_TYPE = 0,
HWKEY_SHARED_KEY_TYPE = 1,
};
/**
* enum hwkey_rollback_version_indices - Index descriptions for &struct
* hwkey_derive_versioned_msg.rollback_versions
* @HWKEY_ROLLBACK_VERSION_OS_INDEX: Index for the Trusty OS rollback version
*
* This interface allows up to %HWKEY_ROLLBACK_VERSION_INDEX_COUNT distinct
* versions, not all of which are currently used. Allowed version types have an
* allocation index in this enum. We may add additional version gates, e.g., app
* version.
*/
enum hwkey_rollback_version_indices {
HWKEY_ROLLBACK_VERSION_OS_INDEX = 0,
HWKEY_ROLLBACK_VERSION_INDEX_COUNT = 8,
};
/**
* struct hwkey_derive_versioned_msg - request/response structure for versioned
* hwkey
* @header: message header. @header.cmd must be %HWKEY_DERIVE_VERSIONED
* @kdf_version: version of the KDF algorithm to use. Use
* %HWKEY_KDF_VERSION_BEST for the current best version. Set to
* the actual KDF version used in the server response.
* @rollback_version_source: one of &enum hwkey_kdf_version_source, echoed back
* in the server response.
* @rollback_versions: versions of the key requested. The version at
* %HWKEY_ROLLBACK_VERSION_OS_INDEX must be less than or
* equal to the current Trusty rollback version. Use
* %HWKEY_ROLLBACK_VERSION_CURRENT for the most recent
* version. Each element set to
* %HWKEY_ROLLBACK_VERSION_CURRENT will be replaced with the
* actual rollback version used for the generated key in the
* server response.
* @key_options: indicates whether the key should be device-unique or the same
* across a family of devices. See &enum hwkey_derived_key_options
* for details.
* @key_len: number of bytes of key material requested, set to the length of
* payload in the server response.
*
* If @key_options includes %HWKEY_DEVICE_UNIQUE_KEY_TYPE and
* @rollback_versions[HWKEY_ROLLBACK_VERSION_OS_INDEX] is 0, the service will be
* backwards compatible and use the same key derivation function as for
* %HWKEY_DERIVE. This allows a client to migrate away from the old
* hwkey_derive() API without changing the derived key output. When backwards
* compatibility is required, @rollback_version_source is ignored and the same
* key is generated regardless of source, since that parameter is not available
* in the hwkey_derive() API.
*
* If %HWKEY_ROLLBACK_VERSION_CURRENT is provided for the OS rollback version
* and the current version is 0, compatibility will be provided as if 0 was
* passed explicitly.
*
* We plan to deprecate and remove %HWKEY_DERIVE; on devices that never
* supported %HWKEY_DERIVE, the versioned derive will not support backwards
* compatibility.
*
* This message header should (optionally) be followed by user-provided context
* input in requests and will be followed by the derived key material in the
* response packet.
*/
struct hwkey_derive_versioned_msg {
struct hwkey_msg_header header;
uint32_t kdf_version;
uint32_t rollback_version_source;
int32_t rollback_versions[HWKEY_ROLLBACK_VERSION_INDEX_COUNT];
uint32_t key_options;
uint32_t key_len;
};
/**
* hwkey_derive_versioned_msg_compatible_with_unversioned() - Should this derive
* request be handled as if it was a %HWKEY_DERIVE command?
* @msg: request message
*
* Determines if a versioned key derivation request should be implemented to be
* compatible with the older, unversioned %HWKEY_DERIVE request type.
*
* Return: true if this message must return identical key material as the
* unversioned API.
*/
static inline bool hwkey_derive_versioned_msg_compatible_with_unversioned(
const struct hwkey_derive_versioned_msg* msg) {
return msg->rollback_versions[HWKEY_ROLLBACK_VERSION_OS_INDEX] == 0 &&
(msg->key_options & HWKEY_SHARED_KEY_TYPE) == 0;
}