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.