1 /*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #pragma once
18
19 #include <lk/compiler.h>
20 #include <stdbool.h>
21 #include <stdint.h>
22
23 #define HWKEY_PORT "com.android.trusty.hwkey"
24
25 #define HWKEY_KDF_VERSION_BEST 0
26 #define HWKEY_KDF_VERSION_1 1
27
28 /**
29 * HWKEY_OPAQUE_HANDLE_MAX_SIZE: The maximum size of an opaque handle returned
30 * by the hwkey service.
31 */
32 #define HWKEY_OPAQUE_HANDLE_MAX_SIZE 128
33
34 /* Maximum valid size of a hwkey message, including context or key material. */
35 #define HWKEY_MAX_MSG_SIZE 2048
36
37 /**
38 * enum hwkey_cmd - command identifiers for hwkey functions
39 */
40 enum hwkey_cmd {
41 HWKEY_RESP_BIT = 1,
42 HWKEY_REQ_SHIFT = 1,
43
44 HWKEY_GET_KEYSLOT = (0 << HWKEY_REQ_SHIFT),
45 HWKEY_DERIVE = (1 << HWKEY_REQ_SHIFT),
46
47 /*
48 * commands for &struct hwkey_derive_versioned_msg
49 */
50 HWKEY_DERIVE_VERSIONED = (2 << HWKEY_REQ_SHIFT),
51 };
52
53 /**
54 * enum hwkey_err - error codes for hwkey protocol
55 * @HWKEY_NO_ERROR: all OK
56 * @HWKEY_ERR_GENERIC: unknown error. Can occur when there's an
57 * internal server error, e.g. the server runs out
58 * of memory or is in a bad state.
59 * @HWKEY_ERR_NOT_VALID: input not valid. May occur if the non-buffer
60 * arguments passed into the command are not valid,
61 * for example if the KDF version passed to derive
62 * is not any supported version.
63 * @HWKEY_ERR_BAD_LEN: buffer is unexpected or unaccepted length.
64 * May occur if received message is not at least
65 * the length of the header, or if the payload
66 * length does not meet constraints for the
67 * function.
68 * @HWKEY_ERR_NOT_IMPLEMENTED: requested command not implemented
69 * @HWKEY_ERR_NOT_FOUND: requested keyslot not found
70 * @HWKEY_ERR_ALREADY_EXISTS: requested opaque handle has already been
71 * retrieved. Close the connection and reconnect
72 * to clear this handle and retrieve a new handle.
73 */
74 enum hwkey_err {
75 HWKEY_NO_ERROR = 0,
76 HWKEY_ERR_GENERIC = 1,
77 HWKEY_ERR_NOT_VALID = 2,
78 HWKEY_ERR_BAD_LEN = 3,
79 HWKEY_ERR_NOT_IMPLEMENTED = 4,
80 HWKEY_ERR_NOT_FOUND = 5,
81 HWKEY_ERR_ALREADY_EXISTS = 6,
82 };
83
84 /**
85 * struct hwkey_msg_header - common header for hwkey messages
86 * @cmd: command identifier
87 * @op_id: operation identifier, set by client and echoed by server.
88 * Used to identify a single operation. Only used if required
89 * by the client.
90 * @status: operation result. Should be set to 0 by client, set to
91 * a enum hwkey_err value by server.
92 *
93 * Common header shared between &struct hwkey_msg and &struct
94 * hwkey_derive_versioned_msg. Which message struct is used depends on the
95 * &struct hwkey_msg_header.cmd field, see each message struct for details.
96 */
97 struct hwkey_msg_header {
98 uint32_t cmd;
99 uint32_t op_id;
100 uint32_t status;
101 } __PACKED;
102
103 /**
104 * DOC: hwkey protocol
105 * - Client opens channel to the server, then sends one or more
106 * requests and receives replies.
107 *
108 * - Client is allowed to keep the channel opened for the duration
109 * of the session.
110 *
111 * - Client is allowed to open multiple channels, all such channels
112 * should be treated independently.
113 *
114 * - Client is allowed to issue multiple requests over the same channel
115 * and may receive responses in any order. Client must check op_id
116 * to determine corresponding request.
117 *
118 * - The request and response structure is shared among all API calls.
119 * The data required for each call is as follows:
120 *
121 * hwkey_get_keyslot:
122 *
123 * Request:
124 * @cmd: HWKEY_REQ_GET_KEYSLOT
125 * @op_id: client specified operation identifier. Echoed
126 * in response.
127 * @status: must be 0.
128 * @arg1: unused
129 * @arg2: unused
130 * @payload: string identifier of requested keyslot, not null-terminated
131 *
132 * Response:
133 * @cmd: HWKEY_RESP_GET_KEYSLOT
134 * @op_id: echoed from request
135 * @status: operation result, one of enum hwkey_err
136 * @arg1: unused
137 * @arg2: unused
138 * @payload: unencrypted keyslot data, or empty on error
139 *
140 * hwkey_derive:
141 *
142 * Request:
143 * @cmd: HWKEY_REQ_DERIVE
144 * @op_id: client specified operation identifier. Echoed
145 * in response.
146 * @status: must be 0.
147 * @arg1: requested key derivation function (KDF) version.
148 * Use HWKEY_KDF_VERSION_BEST for best version.
149 * @arg2: unused
150 * @payload: seed data for key derivation. Size must be equal
151 * to size of requested key.
152 *
153 * Response:
154 * @cmd: HWKEY_RESP_DERIVE
155 * @op_id: echoed from request
156 * @status: operation result, one of enum hwkey_err.
157 * @arg1: KDF version used. Always different from request if
158 * request contained HWKEY_KDF_VERSION_BEST.
159 * @arg2: unused
160 * @payload: derived key
161 */
162
163 /**
164 * struct hwkey_msg - common request/response structure for hwkey
165 * @header: message header. @header.cmd must be either %HWKEY_GET_KEYSLOT or
166 * %HWKEY_DERIVE (optionally ORed with %HWKEY_RESP_BIT).
167 * @arg1: first argument, meaning determined by command issued.
168 * Must be set to 0 if unused.
169 * @arg2: second argument, meaning determined by command issued
170 * Must be set to 0 if unused.
171 * @payload: payload buffer, meaning determined by command issued
172 */
173 struct hwkey_msg {
174 struct hwkey_msg_header header;
175 uint32_t arg1;
176 uint32_t arg2;
177 uint8_t payload[0];
178 };
179 STATIC_ASSERT(sizeof(struct hwkey_msg) == 20);
180
181 /**
182 * enum hwkey_rollback_version_source - Trusty rollback version source.
183 * @HWKEY_ROLLBACK_COMMITTED_VERSION:
184 * Gate the derived key based on the anti-rollback counter that has been
185 * committed to fuses or stored. A version of Trusty with a version smaller
186 * than this value should never run on the device again. The latest key may
187 * not be available the first few times a new version of Trusty runs on the
188 * device, because the counter may not be committed immediately. This
189 * version source may not allow versions > 0 on some devices (i.e. rollback
190 * versions cannot be committed).
191 * @HWKEY_ROLLBACK_RUNNING_VERSION:
192 * Gate the derived key based on the anti-rollback version in the signed
193 * image of Trusty that is currently running. The latest key should be
194 * available immediately, but the Trusty image may be rolled back on a
195 * future boot. Care should be taken that Trusty still works if the image is
196 * rolled back and access to this key is lost. Care should also be taken
197 * that Trusty cannot infer this key if it rolls back to a previous version.
198 * For example, storing the latest version of this key in Trusty’s storage
199 * would allow it to be retrieved after rollback.
200 */
201 enum hwkey_rollback_version_source {
202 HWKEY_ROLLBACK_COMMITTED_VERSION = 0,
203 HWKEY_ROLLBACK_RUNNING_VERSION = 1,
204 };
205
206 #define HWKEY_ROLLBACK_VERSION_CURRENT (-1)
207
208 /**
209 * enum hwkey_derived_key_options - Options for derived versioned keys
210 * @HWKEY_DEVICE_UNIQUE_KEY_TYPE: A key unique to the device it was derived on.
211 * This key should never be available outside of
212 * this device. This key type is the default.
213 * @HWKEY_SHARED_KEY_TYPE: A key shared across a family of devices. May not be
214 * supported on all device families. This derived key
215 * should be identical on all devices of a particular
216 * family given identical inputs, if supported.
217 *
218 * @HWKEY_DEVICE_UNIQUE_KEY_TYPE and @HWKEY_SHARED_KEY_TYPE conflict and cannot
219 * both be used at the same time.
220 */
221 enum hwkey_derived_key_options {
222 HWKEY_DEVICE_UNIQUE_KEY_TYPE = 0,
223 HWKEY_SHARED_KEY_TYPE = 1,
224 };
225
226 /**
227 * enum hwkey_rollback_version_indices - Index descriptions for &struct
228 * hwkey_derive_versioned_msg.rollback_versions
229 * @HWKEY_ROLLBACK_VERSION_OS_INDEX: Index for the Trusty OS rollback version
230 *
231 * This interface allows up to %HWKEY_ROLLBACK_VERSION_INDEX_COUNT distinct
232 * versions, not all of which are currently used. Allowed version types have an
233 * allocation index in this enum. We may add additional version gates, e.g., app
234 * version.
235 */
236 enum hwkey_rollback_version_indices {
237 HWKEY_ROLLBACK_VERSION_OS_INDEX = 0,
238
239 HWKEY_ROLLBACK_VERSION_INDEX_COUNT = 8,
240 };
241
242 /**
243 * struct hwkey_derive_versioned_msg - request/response structure for versioned
244 * hwkey
245 * @header: message header. @header.cmd must be %HWKEY_DERIVE_VERSIONED
246 * @kdf_version: version of the KDF algorithm to use. Use
247 * %HWKEY_KDF_VERSION_BEST for the current best version. Set to
248 * the actual KDF version used in the server response.
249 * @rollback_version_source: one of &enum hwkey_kdf_version_source, echoed back
250 * in the server response.
251 * @rollback_versions: versions of the key requested. The version at
252 * %HWKEY_ROLLBACK_VERSION_OS_INDEX must be less than or
253 * equal to the current Trusty rollback version. Use
254 * %HWKEY_ROLLBACK_VERSION_CURRENT for the most recent
255 * version. Each element set to
256 * %HWKEY_ROLLBACK_VERSION_CURRENT will be replaced with the
257 * actual rollback version used for the generated key in the
258 * server response.
259 * @key_options: indicates whether the key should be device-unique or the same
260 * across a family of devices. See &enum hwkey_derived_key_options
261 * for details.
262 * @key_len: number of bytes of key material requested, set to the length of
263 * payload in the server response.
264 *
265 * If @key_options includes %HWKEY_DEVICE_UNIQUE_KEY_TYPE and
266 * @rollback_versions[HWKEY_ROLLBACK_VERSION_OS_INDEX] is 0, the service will be
267 * backwards compatible and use the same key derivation function as for
268 * %HWKEY_DERIVE. This allows a client to migrate away from the old
269 * hwkey_derive() API without changing the derived key output. When backwards
270 * compatibility is required, @rollback_version_source is ignored and the same
271 * key is generated regardless of source, since that parameter is not available
272 * in the hwkey_derive() API.
273 *
274 * If %HWKEY_ROLLBACK_VERSION_CURRENT is provided for the OS rollback version
275 * and the current version is 0, compatibility will be provided as if 0 was
276 * passed explicitly.
277 *
278 * We plan to deprecate and remove %HWKEY_DERIVE; on devices that never
279 * supported %HWKEY_DERIVE, the versioned derive will not support backwards
280 * compatibility.
281 *
282 * This message header should (optionally) be followed by user-provided context
283 * input in requests and will be followed by the derived key material in the
284 * response packet.
285 */
286 struct hwkey_derive_versioned_msg {
287 struct hwkey_msg_header header;
288 uint32_t kdf_version;
289 uint32_t rollback_version_source;
290 int32_t rollback_versions[HWKEY_ROLLBACK_VERSION_INDEX_COUNT];
291 uint32_t key_options;
292 uint32_t key_len;
293 };
294
295 /**
296 * hwkey_derive_versioned_msg_compatible_with_unversioned() - Should this derive
297 * request be handled as if it was a %HWKEY_DERIVE command?
298 * @msg: request message
299 *
300 * Determines if a versioned key derivation request should be implemented to be
301 * compatible with the older, unversioned %HWKEY_DERIVE request type.
302 *
303 * Return: true if this message must return identical key material as the
304 * unversioned API.
305 */
hwkey_derive_versioned_msg_compatible_with_unversioned(const struct hwkey_derive_versioned_msg * msg)306 static inline bool hwkey_derive_versioned_msg_compatible_with_unversioned(
307 const struct hwkey_derive_versioned_msg* msg) {
308 return msg->rollback_versions[HWKEY_ROLLBACK_VERSION_OS_INDEX] == 0 &&
309 (msg->key_options & HWKEY_SHARED_KEY_TYPE) == 0;
310 }
311