github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/tao/proto/attestation.proto (about) 1 // Copyright (c) 2014, Kevin Walsh. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 syntax = "proto2"; 15 16 package tao; 17 18 // Statements: 19 // 20 // A statement conveys: 21 // issuer from time until exp says message 22 // In Go, a statement is represented in Go using cloudproxy/tao/auth.Says. By 23 // itself, a statement can't be verified as it does not include a signature. 24 // 25 // Delegation Statements: 26 // 27 // Tao uses simple delegation statements internally. This is the only kind of 28 // statement that Tao generates or interprets. A simple delegation statement is 29 // a statement conveying a particular message: 30 // issuer ... says (delegate speaksfor issuer) 31 // Here, delegate is the name of some principal, usually a (non-tpm) Tao key 32 // principal, i.e. key("...") where "..." is a hashed, serialized public key as 33 // produced by Signer.ToPrincipal() or Verifier.ToPrincipal(). If time 34 // restrictions are met, from a delegation statement we can derive: 35 // issuer says (delegate speaksfor issuer) 36 // and further: 37 // delegate speaksfor issuer 38 // That is to say, a delegation statement conveys a speaks-for relationship. 39 // 40 // Delegation Statement Example: 41 // 42 // Suppose some program Prog(...), running on some OS PCRs(...), running on some 43 // TPM K_aik where H_aik = Hash(K_aik), generates a key and wants to arrange for 44 // that key to speak for itself. It can express as much with this statement: 45 // H_aik.PCRs(...).Prog(...) says (H_prog speaksfor H_aik.PCRs(...).Prog(...)) 46 // 47 // Other Statements: 48 // 49 // Statements can convey a variety of other messages beyond just a delegation. 50 // For example: 51 // issuer says Pred(arg_1, ..., arg_n) 52 // Here, 'Pred' is the name of some predicate that is meaningful to the issuer 53 // (and to other principals that trust the issuer), and the arg_i are values 54 // such as strings, integers, or names of principals or subprincipals. 55 // 56 // Other Statement Examples: 57 // 58 // Following the above delegation example, the policy key might want to express 59 // that the TPM identified by H_aik = H(K_aik) is a trusted platform, and the OS 60 // identified by PCRs(...) is a trusted OS. It can do so with these statements: 61 // H_policy says IsTrustedPlatform(H_aik) 62 // H_policy says IsTrustedOS("PCRs(...)") 63 64 // An Attestation is a key, a signature, and a statement, and it conveys: 65 // signer says statement 66 // i.e. 67 // signer says (issuer from time until exp says message) 68 // A valid Attestation encodes a public key, and it carries a signature that 69 // anyone can verify to (eventually) conclude: 70 // issuer from time' until exp' says message 71 // Note: Because of time restrictions within attached delegations, restrictions 72 // time' and exp' here do not necessarily exactly match the restrictions time 73 // and exp on the original serialized statement. 74 // If the modified time restriction is met, then we can derive the same 75 // conclusion as we would for the included statement, e.g.: 76 // delegate speaksfor issuer (for a delegation statement) 77 // or: 78 // issuer says Pred(arg_1, ..., arg_n) (for a predicate statement) 79 // That is to say, a valid Attestation that meets its time restriction conveys 80 // exactly the same meaning as conveyed by the included statement. 81 // 82 // There are two categories of valid Attestations: 83 // 84 // (1) In cases where issuer is a subprincipal of (or identical to) signer, no 85 // delegation will be present. In these cases, signer speaksfor issuer, so from 86 // the attestation: 87 // signer says (issuer says ...) 88 // we can derive: 89 // issuer says (issuer says ...) 90 // and further: 91 // issuer says ... 92 // 93 // Example of a category (1) attestation: 94 // Attestation = { 95 // statement = "H_aik.PCRs(...) says (H_os speaksfor H_aik.PCRs(...))" 96 // signer = K_aik 97 // signature = ... 98 // delegation = nil 99 // } 100 // Here, an OS has published a delegation statement establishing that key K_os 101 // speaks for the OS, and this statement was signed by the TPM K_aik on behalf 102 // of the OS. Note that the OS is a subprincipal of the TPM, so the TPM speaks 103 // for the OS. 104 // 105 // (2) In all other cases, a delegation will be present that, if valid, conveys: 106 // issuer0 from time0 until exp0 says (delegate speaksfor issuer0) 107 // where issuer is a subprincipal of (or identical to) issuer0 and delegate is a 108 // subprincipal of (or identical to) signer. Such a valid 109 // delegation can be combined with: 110 // signer says (issuer from time until exp says ...) 111 // to derive: 112 // issuer0 from time0 until exp0 says (issuer from time until exp says ...) 113 // And because issuer0 speaks for issuer, we can further derive: 114 // issuer from time' until exp' says ... 115 // where time' = max(time, time0) and exp = min(exp, exp0). 116 // 117 // Example of a category (2) attestation: 118 // Attestation = { 119 // statement = "H_aik.PCRs(...).Prog(...) says H_app speaksfor H_aik.PCRs(...).Prog(...)" 120 // signer = K_os 121 // signature = ... 122 // delegation = { 123 // statement = H_aik.PCRs(...) says H_os speaksfor H_aik.PCRs(...) 124 // signer = K_aik 125 // signature = ... 126 // delegation = nil 127 // } 128 // } 129 // Here, the OS identified by H_aik.PCRs(...) has signed, using a 130 // seemingly unrelated key K_os, a statement on behalf of one of its hosted 131 // programs, H_aik.PCRs(...).Prog(...). The embedded delegation statement, 132 // signed by K_aik, binds that seemingly unrelated key K_os to the OS's actual 133 // identity, H_aik.PCRs(...). 134 // 135 // Verifying an attestation signature requires knowing how the signature was 136 // produced. We currently define two signature schemes: 137 // 138 // TODO(kwalsh): add tpm2 signature scheme here and in attestation.go 139 // 140 // (a) Some signatures are produced by the TPM, so here we are bound by the 141 // mechanisms implemented by the TPM. In this case, we encode the signer name as 142 // tpm("..H..") where "..H.." is the hashed, serialized public half 143 // of the TPM's RSA key K. The TPM only ever signs things on behalf of its 144 // hosted programs, so the issuer used in the serialized statement will always 145 // have the form: 146 // tpm("..H..").PCRs("..i..", "..h..")... 147 // where "..i.." is a sorted, comma-separated list of PCR numbers, and "..h.." 148 // is the corresponding, comma-separated list of hex-encoded PCR values. The 149 // signature is computed roughly as: 150 // sig = rsa_sign(K, H( H(message) | pcrbuf(i, h) )) 151 // Here, we first hash the statement in a tpm-specific way, then sign the 152 // hash with RSA key K. To obtain the statement hash, first hash the serialized 153 // statement, including issuer, time, expiration and other information. This 154 // intermediate hash is then re-hashed with a tpm-specific encoding of the PCR 155 // numbers ("..i..") and values ("..h..") extracted from issuer. 156 // 157 // Note: The PCR values are effectively hashed twice, once as part of statement, 158 // and separately as part of the pcrbuf datastructure. See optimization note 159 // below. 160 // 161 // (b) Other signatures are produced in software, and here we have flexibility 162 // to use simpler signature schemes. In this case, we encode the signer name as 163 // key("..H..") where "..H.." is the hashed, serialized public half 164 // of a DSA key K. The issuer used in the serialized statement can have any 165 // form. The signature is roughly: 166 // sig = dsa_sign(K, H(context|message)) 167 // Here, we simply hash the serialized statement, along with some context, then 168 // sign it with the private DSA key K. The context used for attestations is 169 // defined in Tao.AttestationSigningContext. 170 // 171 // Together, this results in four possible combinations: 172 // 173 // (1a) No delegation, Tao signature. 174 // Historical note: This is the old "ROOT" attestation type. 175 // Typically exaample: signer is the "domain policy" key. 176 // The signer is always key("..H.."). 177 // (1b) No delegation, TPM signature. 178 // This is produced by tpm_tao. 179 // The signer is always tpm("..H..") and the statement issuer is 180 // always a tpm("..H..").PCRs("..i..", "..h..")... principal. 181 // (2a) Delegation, Tao signature. 182 // Historical note: This is the old "INTERMEDIATE" attestation type. 183 // The signer is always key("..H.."). 184 // The delegation is the head of a chain that eventually terminates in a 185 // type (1a) or (1b) attestation. 186 // (2b) Delegation, TPM signature. 187 // Historical note: This is the old "TPM_1_2_QUOTE" attestation type. 188 // This combination is no longer used. If it were, the signer would be 189 // tpm("..H..") and the statement issuer would be something like 190 // H_policy.TrustedPlatform. The delegation would be the head of a chain 191 // that eventually terminates in a type (1a) or (1b) attestation. The 192 // issuer at the head of the chain would always be a 193 // tpm("..H..").PCRs("..i..", "..h..") principal. 194 message Attestation { 195 // A serialized statement. This is serialized to avoid canonicalization issues 196 // when signing and verifying signatures. In Go, this is obtained using 197 // cloudproxy/tao/auth.Marshal(). 198 required bytes serialized_statement = 1; 199 200 // The signature type, either "tpm", "tpm2", or "key". This must match 201 // the type of the signer key, and it is also used to determine how to verify 202 // signatures. 203 required string signer_type = 2; 204 205 // The signer's public key, i.e. the un-hashed key material used within 206 // cloudproxy/tao/auth.New*Prin(). 207 required bytes signer_key = 3; 208 209 // Signature over the serialized statement using TPM or Tao signing. 210 required bytes signature = 4; 211 212 // A delegation attestation that conveys (eventually) that signer speaks for 213 // the issuer in the serialized statement. If this is empty, then it must be 214 // self evident that signer speaks for the issuer in the serialized statement. 215 // This can be added, removed, or replaced without changing the attestation 216 // signature, but verification may fail if a required delegation is missing. 217 optional bytes serialized_delegation = 5; 218 219 // An optional set of further attestations that may pertain, in some way, to 220 // the the issuer or signer of this attestation. These can be added or removed 221 // without changing the attestation signature. This allows attestations to be 222 // piggy-backed, e.g. when an authorization guard requires multiple 223 // attestations to check a policy. 224 repeated bytes serialized_endorsements = 6; 225 226 // This is the quote structure actually signed by the tpm 2.0. 227 // TODO(kwalsh) remove this -- as for tpm1.2, the quote structure should be 228 // recoverable from the principal names in the serialized statement. 229 optional bytes tpm2_quote_structure = 7; 230 231 // This is a DER encoded X509 certificate certifying the key signing the 232 // attestation. This is included in attestations signed by a root Tao 233 // i.e. a TPM (1.2 or 2.0) Tao or a soft Tao, and forms the root of the 234 // attestation chain. This certificate is signed by the policy key. 235 // TODO(kwalsh) remove this -- endorsements, and especially x509 certificates, 236 // do not belong in attestations; an x509 "endorsement" in fact *is* a kind of 237 // attestation. 238 optional bytes root_endorsement = 8; 239 } 240 241 // TODO(kwalsh) Consider moving issuer (and expiration times) out of serialized 242 // statement and into Attestation. Non-tpm signature scheme would just hash the 243 // issuer separately. This would eliminate the double-hashing of PCR values, and 244 // it would let us do some trivial space optimizations: if issuer is empty, then 245 // issuer = signer, if issuer key is empty (i.e. starts with "."), then signer 246 // gets prepended to issuer, etc. 247 248 // TODO(kwalsh) Previously, names were not always included in statements and 249 // attestations, nor did names always include serialized public keys. That makes 250 // signed statements more compact. Now, the same public key might appear several 251 // times within a single attestation. The problem arises because each 252 // attestation is really a collection of statements and nested attestations. We 253 // should revisit how to efficiently encode these structures.