1# DICE chain policies 2 3DICE policy is the mechanism for specifying constraints on a DICE chain. A DICE chain policy 4verifier takes a policy and a DICE chain, and returns whether the DICE chain meets the constraints 5set out in the policy. 6 7## Navigating this project 8 9This directory exports Rust crates for matching Dice Chains against Dice Policies as well building 10Dice Policies. 11 121. [./building/](https://cs.android.com/android/platform/superproject/main/+/main:system/secretkeeper/dice_policy/building/src/lib.rs): 13 Supports constructing Dice Policies on a Dice chains, enabling various ways to specify the 14 constraints. 151. [./src/](https://cs.android.com/android/platform/superproject/main/+/main:system/secretkeeper/dice_policy/src/lib.rs): 16 Supports matching Dice Chains against Dice Policies. 17 18## DICE chain 19 20[Open Profile for DICE][open_dice_spec] is designed to be layered. The certificate generated by the 21next DICE layer can chain to the certificate generated by the previous DICE layer. This chain of 22certificates has been termed as DICE chain in context of this documentation. 23 24Note that the libraries in this directory are implemented to work with DICE chains following tighter 25constraints of [Android Profile for DICE chains][android_dice_spec], although the concept is 26applicable to any DICE chain profiles. 27 28## Rollback protection and DICE 29 30Each component in a DICE chain receives a secret, the “attestation CDI”, which depends on all of the 31information in the chain up to that point; this secret is used to protect a signing keypair that the 32component uses to sign DICE assertions. This secret isn’t useful for protecting component data, 33since it changes whenever the component or any part of the boot chain is updated. Some DICE 34implementations provide a “sealing CDI” which depends only on stable information such as component 35names and the public keys used to sign components. However, this provides no protection against 36attacks based on version rollback because it doesn't include any version information. 37 38To resolve this, we change the sealing operation to take an additional input called a “policy”. 39Unsealing is only permitted if the DICE chain for the component requesting unsealing complies with 40the policy given when the message was sealed. A typical policy will assert things like: 41 421. UDS_Public must have a specific value 431. The DICE chain must be exactly five certificates long 441. authorityHash in the third certificate must have this value 451. securityVersion in the fourth certificate must be an integer greater than 8 46 47At sealing time, the component performing the sealing must compose a policy that meets its needs: 48specific enough that its secrets are protected from attackers, but general enough that future 49versions of the component can unseal them. 50 51Projects such as [Secretkeeper][sk_project] use policy-based protection; they are the foundation to 52providing rollback-secure identities and secrets to VMs and Authgraph participants. 53 54## Example DICE policy 55 56Below is a highly simplified DICE policy on DICE chains specifying (among other things) that a 57particular DiceChainEntry need to have auth_hash value exactly equal to specified one and 58security_version >= 5. 59 60``` 61 DicePolicy { 62 version: 1, 63 node_constraint_list: 64 <!-- ExplicitKeyDiceCertChain version --> 65 NodeConstraints [ 66 Constraint { 67 type=ExactMatch, 68 path=[] 69 value="1", 70 }, 71 ] 72 node_constraint_list: 73 <!-- Constraints on the DiceCertChainInitialPayload --> 74 NodeConstraints [ 75 Constraint { 76 type=ExactMatch, 77 path=[] 78 value="a50101032704810220062158203e85e5727555e51ee7f335948ebbbd741e1dca499c97397706d3c86e8bd733f9", 79 }, 80 ] 81 node_constraint_list: 82 <!-- Constraints on a DiceChainEntry --> 83 NodeConstraints [ 84 Constraint { 85 type=ExactMatch, 86 path=[authority_hash] 87 value="04255d605f5c450df29a6e993003b8d6e199711bf844fab531791c37684e1dc0247468f880203e44b143d29cfc129e770ade2924ff2efac710d573d4c6df629f", 88 }, 89 Constraint { 90 type=ExactMatch, 91 path=[mode] 92 value="01", 93 }, 94 Constraint { 95 type=GreaterOrEqual, 96 path=[config_desc,security_version] 97 value="5", 98 }, 99 ] 100 } 101``` 102 103## CBOR representation 104 105### Explicit-key DiceCertChain format 106 107In the [Android Profile for DICE][android_dice_spec] `DiceCertChain` format specification, the 108`subjectPublicKey` in a certificate which describes the signing key of the next party in the chain 109is specified as a `.bstr cbor`: a binary string containing CBOR data. This makes it very easy to 110define eg “the hash of the public key” or compare two keys for identity. 111 112However, this is not true of the first public key in the chain, UDS_Public, derived from the Unique 113Device Secret (UDS). For example, it means that the DICE chain verifiers have to resort custom look ups 114look up to converted from COSE_Key form to an algorithm-specific non-COSE format for lookup. 115 116The policy comparison code should stay as simple and predictable as possible, algorithm specific 117lookups should be avoided. So instead we specify a new DICE chain format which is slightly different 118to the DiceCertChain format and addresses this issue. 119 120We don’t anticipate that devices will switch to using this new chain from the moment they boot - 121that would be a disruptive change. Instead, we anticipate that components will receive their DICE 122chain in DiceCertChain format, and convert it to “ExplicitKeyDiceCertChain” format before presenting 123it to any other party in any context where policy comparisons are relevant. This conversion must be 124deterministic so that the UDS_Public bstr presented on the device never changes, or policy comparisons 125will fail; CBOR canonicalization can be used to this end. 126 127``` 128ExplicitKeyDiceCertChain = [ 129 1, ; version, hopefully will never change 130 DiceCertChainInitialPayload, 131 * DiceChainEntry 132] 133 134; Encoded in accordance with Core Deterministic Encoding Requirements [RFC 8949 s4.2.1] 135DiceCertChainInitialPayload = bstr .cbor PubKeyEd25519 136 / bstr .cbor PubKeyECDSA256 137 / bstr .cbor PubKeyECDSA384 ; subjectPublicKey 138``` 139 140## DICE policy specification 141 142The spec is extracted from [DicePolicy.cddl][dicepolicycddl] 143 144``` 145dicePolicy = [ 146 1, ; version, hopefully will never change 147 + nodeConstraintList 148] 149 150nodeConstraintList = [ 151 * nodeConstraint 152] 153 154; We may add a hashConstraint item later 155nodeConstraint = exactMatchConstraint / geConstraint 156 157exactMatchConstraint = [1, keySpec, value] 158geConstraint = [2, keySpec, int] 159 160keySpec = [value+] 161 162value = bool / int / tstr / bstr 163``` 164 165[android_dice_spec]: https://cs.android.com/android/platform/superproject/main/+/main:hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/generateCertificateRequestV2.cddl 166[dicepolicycddl]: https://cs.android.com/android/platform/superproject/main/+/main:hardware/interfaces/security/authgraph/aidl/android/hardware/security/authgraph/DicePolicy.cddl 167[open_dice_spec]: https://pigweed.googlesource.com/open-dice/+/refs/heads/main/docs/specification.md#Layering-Details 168[sk_project]: https://android.git.corp.google.com/platform/system/secretkeeper/ 169