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