-
Notifications
You must be signed in to change notification settings - Fork 789
/
dif_keymgr.h
583 lines (548 loc) · 19.2 KB
/
dif_keymgr.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#ifndef OPENTITAN_SW_DEVICE_LIB_DIF_DIF_KEYMGR_H_
#define OPENTITAN_SW_DEVICE_LIB_DIF_DIF_KEYMGR_H_
/**
* @file
* @brief <a href="/hw/ip/keymgr/doc/">Key Manager</a> Device Interface
* Functions
*/
#include <stdint.h>
#include "sw/device/lib/base/macros.h"
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/dif/dif_base.h"
#include "keymgr_regs.h"
#include "sw/device/lib/dif/autogen/dif_keymgr_autogen.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
/**
* A typical usage of this library during different secure boot
* stages is as follows:
*
* - In ROM:
* - Create a new handle: `dif_keymgr_init()`.
* - Configure hardware: `dif_keymgr_configure()`.
* - Initialize state: `dif_keymgr_advance_state()`,
* `dif_keymgr_get_status_codes()`, `dif_keymgr_get_state()`.
* - Advance state: `dif_keymgr_advance_state()`,
* `dif_keymgr_get_status_codes()`, `dif_keymgr_get_state()`.
* - In subsequent boot stages, i.e. ROM_EXT, BL0, kernel:
* - Create a new handle: `dif_keymgr_init()`.
* - Generate keys and/or identity seeds:
* `dif_keymgr_generate_versioned_key()`,
* `dif_keymgr_generate_identity_seed()`, `dif_keymgr_get_status_codes()`.
* - Read output (if applicable): `dif_keymgr_read_output()`.
* - Advance state: `dif_keymgr_advance_state()`,
* `dif_keymgr_get_status_codes()`, `dif_keymgr_get_state()`.
*/
/**
* Enumeration for side load slot clearing.
*/
typedef enum dif_keymgr_sideload_clr {
kDifKeyMgrSideLoadClearNone = 0,
kDifKeyMgrSideLoadClearAes = 1,
kDifKeyMgrSideLoadClearKmac = 2,
kDifKeyMgrSideLoadClearOtbn = 3,
// Using different value than those enumerated above should clear all slots,
// so we can use the mask value of this field to denote ALL case. This was
// we can statically assert this value on the .c side of this DIF.
kDifKeyMgrSideLoadClearAll = 7,
} dif_keymgr_sideload_clr_t;
/**
* Runtime configuration for key manager.
*
* This struct describes runtime information for one-time configuration of the
* hardware.
*/
typedef struct dif_keymgr_config {
/**
* Number of key manager cycles before the entropy is reseeded.
*
* Key manager uses random values generated by the entropy source for
* initializing its state and clearing sideload keys. This value determines
* the frequency at which this random value is updated.
*/
uint16_t entropy_reseed_interval;
} dif_keymgr_config_t;
/**
* Key manager states.
*
* Key manager has seven states that control its operation. During secure boot,
* key manager transitions between these states sequentially and these
* transitions are irreversible until a power cycle.
*
* The secret value of key manager changes at each state transition in a
* well-defined manner, thus its meaning is tied to the current state of key
* manager.
*
* The functionality of key manager is directly tied to the life cycle
* controller peripheral and it is explicitly disabled during specific life
* cycle stages. If key manager has not been initialized, it cannot be
* initialized until it is enabled by life cycle controller. If key manager is
* disabled by life cycle controller while it is in an operational state, it
* immediately wipes its contents and transitions to Disabled state.
*/
typedef enum dif_keymgr_state {
/**
* Reset state.
*
* This is the initial state of key manager after PoR. At this state, the
* secret value of key manager is non-deterministic, i.e. some value based on
* the physical characteristics of the device and environment conditions.
*/
kDifKeymgrStateReset,
/**
* Initialized state.
*
* Secret value of key manager is initialized with random values generated by
* the entropy source. This is not an operational state and the key manager
* state must be advanced one more time before keys or identity seeds can be
* generated.
*/
kDifKeymgrStateInitialized,
/**
* CreatorRootKey state.
*
* This is the first operational state of key manager. At this state, key
* manager can generate a versioned creator key or a creator identity seed
* that can be used to generate a creator identity using an asymmetric KDF.
*/
kDifKeymgrStateCreatorRootKey,
/**
* OwnerIntermediateKey state.
*
* This is the second operational state of key manager. At this state, key
* manager can generate a versioned intermediate owner key or an intermediate
* owner identity seed that can be used to generate an intermediate owner
* identity using an asymmetric KDF.
*/
kDifKeymgrStateOwnerIntermediateKey,
/**
* OwnerRootKey state.
*
* This is the last operational state of key manager. At this state, key
* manager can generate a versioned owner key or an owner identity seed that
* can be used to generate an owner identity using an asymmetric KDF.
*/
kDifKeymgrStateOwnerRootKey,
/**
* Disabled state.
*
* This is a terminal state where key manager is no longer operational. At
* this state, the secret value of key manager is a random value.
*/
kDifKeymgrStateDisabled,
/**
* Invalid state.
*
* Keymgr is in an invalid state and must be reset.
*/
kDifKeymgrStateInvalid,
} dif_keymgr_state_t;
/**
* Compound Device Identifier type.
*
* The key manager supports the DICE open profile consisting of two Compound
* Device Identifiers (CDI):
*
* - Sealing
* - Attestation
*
* In every operational state of the key manager, it is possible to derive
* either sealing or attestation identifiers, software or hardware keys by
* setting the `CDI_SEL` bit in the `CONTROL_SHADOWED` register.
*/
typedef enum dif_keymgr_cdi_type {
/**
* Sealing CDI.
*
* This is the default configuration, corresponding to an unset bit.
*/
kDifKeymgrSealingCdi = KEYMGR_CONTROL_SHADOWED_CDI_SEL_VALUE_SEALING_CDI,
/**
* Attestation CDI.
*/
kDifKeymgrAttestationCdi =
KEYMGR_CONTROL_SHADOWED_CDI_SEL_VALUE_ATTESTATION_CDI
} dif_keymgr_cdi_type_t;
/**
* Configures key manager with runtime information.
*
* This function should need to be called once for the lifetime of `keymgr`.
*
* @param keymgr A key manager handle.
* @param config Runtime configuration parameters.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_keymgr_configure(const dif_keymgr_t *keymgr,
dif_keymgr_config_t config);
/**
* Parameters for a key manager state.
*/
typedef struct dif_keymgr_state_params {
/**
* This value is used by key manager to derive secret values and can be either
* a value that represents the contents of a boot stage, e.g. a (truncated)
* hash, or a tag.
*
* If it is a hash, changes in a boot stage will change the secret value, and
* consequently the versioned keys and identity seeds generated at subsequent
* boot stages. If it is a tag, those secret values, versioned keys, and
* identity seeds will be preserved across updates of the boot stage as long
* as the tag remains the same.
*/
uint32_t binding_value[8];
/**
* Maximum allowed version for keys generated at a state.
*/
uint32_t max_key_version;
} dif_keymgr_state_params_t;
/**
* Advances key manager state.
*
* This function instructs key manager to transition to the next state, i.e.
* Reset -> Initialized -> CreatorRootKey -> OwnerIntermediateKey ->
* OwnerRootKey -> Disabled. Once a state transition starts, key manager locks
* the control register until the transition is complete. State transitions are
* irreversible until a power cycle.
*
* The entropy source must be initialized before this function is called. After
* PoR, key manager is in Reset state with a non-deterministic secret value. The
* first call to this function after PoR causes key manager to initialize its
* secret value using the random values generated by the entropy source and
* transition to Initialized state.
*
* `params` is required when the next state is an operational state,
* i.e. `CreatorRootKey`, `OwnerIntermediateKey`, or `OwnerRootKey`. It must be
* `NULL` for all other cases.
*
* This is an asynchronous function because key manager state transitions
* involve KMAC operations that can take some time to complete. Clients must
* check the status of key manager using `dif_keymgr_get_status_codes()` before
* calling other functions in this library.
*
* @param keymgr A key manager handle.
* @param params The binding and max key version value for the next state.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_keymgr_advance_state(const dif_keymgr_t *keymgr,
const dif_keymgr_state_params_t *params);
/**
* Advances key manager state without setting any of the required inputs.
*
* This function instructs key manager to transition to the next state, i.e.
* Reset -> Initialized -> CreatorRootKey -> OwnerIntermediateKey ->
* OwnerRootKey -> Disabled. Once a state transition starts, key manager locks
* the control register until the transition is complete. State transitions are
* irreversible until a power cycle.
*
* This function does not have a `dif_keymgr_state_params_t` parameter since
* these inputs are expected to be set before this function is called, e.g. when
* the chip is using `rom` as opposed to `test_rom`. See
* `dif_keymgr_advance_state()` if you need to set the binding value and max key
* version before advancing the state.
*
* The entropy source must be initialized before this function is called. After
* PoR, key manager is in Reset state with a non-deterministic secret value. The
* first call to this function after PoR causes key manager to initialize its
* secret value using the random values generated by the entropy source and
* transition to Initialized state.
*
* This is an asynchronous function because key manager state transitions
* involve KMAC operations that can take some time to complete. Clients must
* check the status of key manager using `dif_keymgr_get_status_codes()` before
* calling other functions in this library.
*
* @param keymgr A key manager handle.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_keymgr_advance_state_raw(const dif_keymgr_t *keymgr);
/**
* Disables key manager.
*
* This function disables key manager until the next power cycle by making it
* transition to Disabled state. Disabled state is a terminal state where key
* manager is no longer operational and its secret value is a random value.
*
* @param keymgr A key manager handle.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_keymgr_disable(const dif_keymgr_t *keymgr);
/**
* Status code bit flags.
*
* See also: `dif_keymgr_status_codes_t`.
*/
typedef enum dif_keymgr_status_code {
/**
* Key manager is idle.
*/
kDifKeymgrStatusCodeIdle = 1 << 0,
/**
* Software invoked an invalid operation.
*/
kDifKeymgrStatusCodeInvalidOperation = 1 << 1,
/**
* Key manager issued invalid data to KMAC interface.
*/
kDifKeymgrStatusCodeInvalidKmacInput = 1 << 2,
/**
* Software performed an invalid shadow update.
*/
kDifKeymgrStatusCodeInvalidKmacOutput = 1 << 3,
/**
* Key manager encountered invalid state
*/
kDifKeymgrStatusCodeInvalidState = 1 << 4,
} dif_keymgr_status_code_t;
/**
* A bit vector of status codes.
*
* The following snippet can be used to check if key manager is idle:
*
* `bool is_idle = (status_codes & kDifKeymgrStatusCodeIdle);`
*
* The following snippet can be used to check if key manager is idle and
* error-free:
*
* `bool is_idle_and_ok = (status_codes == kDifKeymgrStatusCodeIdle);`
*
* See also: `dif_keymgr_status_code_t`.
*/
typedef uint8_t dif_keymgr_status_codes_t;
/**
* Gets the operational status of key manager.
*
* This function also clears OP_STATUS and ERR_CODE registers after reading
* them.
*
* @param keymgr A key manager handle.
* @param[out] status_codes Out-param for key manager status codes.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_keymgr_get_status_codes(
const dif_keymgr_t *keymgr, dif_keymgr_status_codes_t *status_codes);
/**
* Gets the current state of key manager.
*
* @param keymgr A key manager handle.
* @param[out] state Out-param for current key manager state.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_keymgr_get_state(const dif_keymgr_t *keymgr,
dif_keymgr_state_t *state);
/**
* Parameters for generating an identity seed.
*/
typedef struct dif_keymgr_identity_seed_params {
/**
* Compound Device Identifier type (sealing or attestation).
*/
dif_keymgr_cdi_type_t cdi_type;
} dif_keymgr_identity_seed_params_t;
/**
* Generates an identity seed.
*
* This function requests key manager to generate an identity seed using its
* current secret value. Clients must first verify that the operation was
* successful using `dif_keymgr_get_status_codes()` before reading the generated
* identity seed using `dif_keymgr_read_output()`.
*
* The generated seed can be used to generate an identity using an asymmetric
* KDF.
*
* @param keymgr A key manager handle.
* @param params Identity seed generation params.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_keymgr_generate_identity_seed(
const dif_keymgr_t *keymgr, dif_keymgr_identity_seed_params_t params);
/**
* Destination of a versioned key generation operation.
*
* Key manager can make the output of a versioned key generation operation
* available to software or sideload it directly to a peripheral device. When
* the destination is a peripheral device, the output of the operation is not
* visible to software and a different derivation constant is used for each
* peripheral.
*/
typedef enum dif_keymgr_versioned_key_dest {
/**
* Store the generated versioned key in software visible registers.
*
* The generated versioned key can be read by calling
* `dif_keymgr_read_output()` after verifying that the operation was
* successful using `dif_keymgr_get_status_codes()`.
*/
kDifKeymgrVersionedKeyDestSw,
/**
* Sideload the generated versioned key to AES device.
*/
kDifKeymgrVersionedKeyDestAes,
/**
* Sideload the generated versioned key to KMAC device.
*/
kDifKeymgrVersionedKeyDestKmac,
/**
* Sideload the generated versioned key to Otbn device.
*/
kDifKeymgrVersionedKeyDestOtbn,
/**
* \internal Last key destination.
*/
kDifKeymgrVersionedKeyDestLast = kDifKeymgrVersionedKeyDestOtbn,
} dif_keymgr_versioned_key_dest_t;
/**
* Parameters for generating a versioned key.
*/
typedef struct dif_keymgr_versioned_key_params {
/**
* Destination of the generated versioned key.
*
* See also: `dif_keymgr_versioned_key_dest_t`.
*/
dif_keymgr_versioned_key_dest_t dest;
/**
* Salt value to use for key generation.
*/
uint32_t salt[8];
/**
* Version value to use for key generation.
*/
uint32_t version;
/**
* Coumpund Device Identifier type (sealing or attestation).
*/
dif_keymgr_cdi_type_t cdi_type;
} dif_keymgr_versioned_key_params_t;
/**
* Generates a versioned key.
*
* This function requests key manager to generate a versioned key using its
* current secret value and the provided parameters. The generated key can be
* sideloaded directly to a peripheral device or made visible to software using
* `params.dest`. If the destination is software, clients must first verify that
* the operation was successful using `dif_keymgr_get_status_codes()` before
* reading the generated key using `dif_keymgr_read_output()`.
*
* @param keymgr A key manager handle.
* @param params Key generation parameters.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_keymgr_generate_versioned_key(
const dif_keymgr_t *keymgr, dif_keymgr_versioned_key_params_t params);
/**
* Starts or stops clearing of sideload keys.
*
* When a key is generated to be sideloaded to a hardware peripheral, key
* manager stores it in a set of storage registers. Calling this function with
* `state` set to `kDifKeymgrToggleEnabled` causes key manager to clear sideload
* keys continously using random values from the entropty source. Callers must
* disable clearing of sideload keys to resume normal sideload operation.
*
* @param keymgr A key manager handle.
* @param state The new toggle state for sideload clear.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_keymgr_sideload_clear_set_enabled(const dif_keymgr_t *keymgr,
dif_toggle_t state);
/**
* Checks whether clearing of sideload keys is enabled or not.
*
* @param keymgr A key manager handle.
* @param[out] Out-param for the current toggle state of sideload clear.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_keymgr_sideload_clear_get_enabled(const dif_keymgr_t *keymgr,
dif_toggle_t *state);
/**
* Output of a key manager operation.
*
* Key manager outputs are in two-shares.
*/
typedef struct dif_keymgr_output {
uint32_t value[2][8];
} dif_keymgr_output_t;
/**
* Reads the output of the last key manager operation.
*
* After starting a key manager operation, clients must verify that the
* operation was successful using `dif_keymgr_get_status_codes()` before calling
* this function.
*
* When key manager is used for versioned key generation, the output of this
* function is valid only if the destination of the operation was
* `kDifKeymgrVersionedKeyDestSw`.
*
* See also: `dif_keymgr_output_t`.
*
* @param keymgr A key manager handle.
* @param[out] output Out-param for key manager output.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_keymgr_read_output(const dif_keymgr_t *keymgr,
dif_keymgr_output_t *output);
/**
* Attestation and sealing binding value.
*/
typedef struct dif_keymgr_binding_value {
/**
* Sealing binding value.
*/
uint32_t sealing[8];
/**
* Attestation binding value.
*/
uint32_t attestation[8];
} dif_keymgr_binding_value_t;
/**
* Reads both the attestation or the binding value set.
*
* @param keymgr A key manager handle.
* @param[out] output Value read.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_keymgr_read_binding(const dif_keymgr_t *keymgr,
dif_keymgr_binding_value_t *output);
typedef struct dif_keymgr_max_key_version {
/**
* Max creator key version.
*/
uint32_t creator_max_key_version;
/**
* Max owner intermediate key version.
*/
uint32_t owner_int_max_key_version;
/**
* Max owner key version.
*/
uint32_t owner_max_key_version;
} dif_keymgr_max_key_version_t;
/**
* Reads the max key version of each stage.
*
* @param keymgr A key manager handle.
* @param version Struct with the max versions set.
* @return dif_result_t
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_keymgr_read_max_key_version(
const dif_keymgr_t *keymgr, dif_keymgr_max_key_version_t *versions);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // OPENTITAN_SW_DEVICE_LIB_DIF_DIF_KEYMGR_H_