github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/Doc/KeysAndTrust.txt (about)

     1  April 20, 2014 - Kevin Walsh
     2  
     3  == Status quo (in Tom's implementation) ==
     4  
     5  Each Tao layer has its own public key pair and its own symmetric key.
     6  - The public key pair is used to make signed attestations.
     7  - The symmetric key is used to seal things on behalf of its "hosted" children.
     8  
     9  Ignoring C++isms, the Tao layer provides this interface to its hosted children:
    10  - Init() and Destroy()
    11    These are just C++-isms, and I'll ignore them.
    12  - (success, identifier) = StartHostedProgram(name, arglist)
    13    Starts a hosted program, returns status and a unique identifier.
    14    For the LinuxTao, "name" is a path to an executable in the local filesystem,
    15    and args are passed to main's argv.
    16    For KvmTao, name is a unique ID of some sort, and args contains a path to a
    17    "vm spec" template, a path to a kernel file, a path to an initrd file, a path
    18    to a disk image file, and some encoded channel parameters.
    19    The TPM doesn't implement this at all.
    20  - RemoveHostedProgram(child_hash)
    21    Unregisters (but probably doesn't kill) a hosted program. Maybe "disown" would
    22    be a better name.
    23    The TPM doesn't implement this at all.
    24  - bytes = GetRandomBytes(size)
    25    Get strong random bytes. The root Tao has a way to generate strong random
    26    numbers (i.e. the presumed special hardware in the TPM). And a hosted Tao can
    27    either us use its own special technique or just pass the call down to its
    28    parent Tao.
    29  JLM: Or, more likely, seed a psuedo random nubmer generator using hardware entropy or
    30  random numbers collected from it's host Tao.
    31  - blob = Seal(data)
    32    Seal the data into a blob that can be unsealed later.
    33  - data = Unseal(blob)
    34    Unseal a blob that was previously sealed. The blob must have been created via
    35    a Seal request to this same Tao by the same hosted program. Here, "same hosted
    36    program" means a program with the same child hash. And "same Tao" means "has
    37    the same symmetric key", which in practice means the Tao and all its parent
    38    Tao parents down to the root all have the same has as they did when the seal
    39    operation happened, and they are all running on the same physical TPM. 
    40  - attestation = Attest(data)
    41    Produce a signed attestation that essentially conveys "Tao says (child says
    42    data)", where "Tao" is really the Tao's public key, and "child" is the hash of
    43    the hosted program making the request. Ideally, a hosted program would make a
    44    call where data conveys "(time<T) implies MyKeyIs(K)" for some values of T and
    45    K, so the resulting attestation would convey "Tao says (child says ((time<T)
    46    implies MyKeyIs(K)))". Actually, the it is the host Tao that puts in the
    47    expiration, so the meaning is "Tao says ((time < T) implies (child says
    48    MyKeyIs(K)))". The TPM implements this, sort of (see below).
    49  
    50  Observation: GetRandomBytes seems out of place. Presumably, the TPM is a "good"
    51  source of strong randomness (maybe?), so we want to provide a way for hosted
    52  programs, regardless of how deep in the Tao stack, to access this randomness.
    53  JLM:  The TPM is an OK source of RNG's but its quite slow.  Always asking for fresh
    54  random numbers from your host is very expensive and more likely you'd use a PRNG
    55  seeded occasionally by host entropy.  Some Tao layers have direct access to very
    56  fast hardware RNG's like RDRAND in the new Haswell chip.  GetRandomBytes is not
    57  out of place though since, absent special knowledge, the host is the only GUARANTEED
    58  RNG source.
    59  
    60  Observation: There is no uniform semantics or mechanism for "starting' a hosted
    61  child. And why is there a remove operation but no kill? Every Tao is embedded in
    62  some other entity (Linux, KVM, hypervisor) which has some mechanism for starting
    63  and stopping children. In the C++ Tao implementation, we will of course have
    64  some "register/unregister child" hooks that are hopefully generic enough to make
    65  the Tao embedding trivial. But let's not pretend the Tao is providing much here
    66  beyond whatever Linux (or KVM or hypervisor) already provides.
    67  
    68  == Is the TPM a Tao? ==
    69  
    70  There are 5 essential Tao operations.
    71  - The TPM implements 2 (Seal and Unseal) operations with normal semantics.
    72  - The TPM does not implement 2 (StartHostedProgram, RemoveHostedProgram) at all.
    73  JLM: Yes it does, in conjuction with the chipset it boots the trusted hypervisor
    74  or OS and, in fact, a TPM owner can set policy on which initial programs it is
    75  willint to boot.  So it does do this.  It only has one hosted system however and
    76  in that way it may differ from Tao's higher in the stack.
    77  - The TPM implements 1 (Attest) with basically the right semantics, but in a way
    78    such that causes anyone that uses the result to have special TPM-specific
    79    code.
    80  JLM: Yes, this is unfortunate.  It will be better with TPM2.0.
    81    
    82  This is because the format of the resulting attestation is completely different
    83  than the format of attestations produced by all other Taos. For the TPM, "child"
    84  is a weird TPM-specific PCR datastructure, and the signature is over a messy
    85  struct involving the data (and the expiration) and those PCRs. For all other
    86  Taos, "child" is a simple hash, the attestation is a straight signature over a
    87  simple data structure (defined in attestation.proto) that includes an expiration
    88  time, the data, a hash algorithm ID, and the child hash.
    89  
    90  == Trust among Taos ==
    91  
    92  It may not be obvious, but every hosted program (or hosted Tao) necessarily
    93  trusts its host (or parent) Tao completely. Normally, a hosted program gives all
    94  of its private keys, which are among its most important secrets, to the host Tao
    95  for safe keeping via the Seal operation. So the Tao, if corrupt, could directly
    96  impersonate any hosted program below it, or leak the keys and allow other
    97  principals to do the same.
    98  
    99  Even if the hosted program did not use Seal (perhaps it instead uses ephemeral
   100  keys generated on each execution), the way the hosted program authenticates to
   101  other principals is by way of an attestation from the host Tao. If the host tao
   102  were corrupt, the host Tao could lie about the hash for some second (real or
   103  imaginary) hosted program, and this second hosted program could then impersonate
   104  the first hosted program for all remote authentication.
   105  
   106  Suppose a hosted program does not use keys at all, has no long-term secrets, and
   107  does not do remote authentication, Does this hosted program, which does not use
   108  Seal or Attest, still trust the Tao completely?  One might be tempted to say no,
   109  because (in some situations and in the current implementation) the Tao service
   110  doesn't have full kernel privileges, but instead runs as a separate user-level
   111  linux process. However, we rely on the host Tao to start hosted programs. So a
   112  corrupt host tao could covertly inject vulnerabilities into the hosted program
   113  before the hosted program starts. Moreover, as the parent process, the host Tao
   114  process has a lot of direct control over a hosted process. 
   115  
   116  To summarize: in practice, a hosted process necessarily and fully trusts its
   117  host Tao, and this trust extends all the way down the stack of Tao hosts.
   118  JLM: Yes,  in fact this is VERY explicit which is why the policy key owner
   119  may need to know the entire hosted path to make a signing decision over
   120  Tao Keys.  The most difficult job of the Tao Host is provide isolation between
   121  its hosted programs.  Hoe is does this varies depending on the Tao level.
   122  
   123  == Trust for the TaoCA ==
   124  
   125  It has been said that every hosted program has one (and only one?) embed ed
   126  policy key, and the hosted program trusts that policy key completely. Or at
   127  least, for all authorization and authentication decisions.
   128  
   129  This clearly doesn't include the root Taos, i.e. the TPMs, since they don't have
   130  a policy key. And it may or may not include the FakeTaos (actually, at one point
   131  I had code that could configure FakeTao to run as a pseudo-TPM, i.e. without an
   132  attestation, or as a pseudo-hosted-Tao with an attestation but no parent).
   133  JLM: The sort of do have an implicit policy key, namely the EK which must be 
   134  certified by a "trusted provider".  Absent even the "key" paradigm, TPMs
   135  have owner set policy which corresponds to the policy generally delegated by a key.
   136  
   137  Do hosted programs actually fully trust the policy key? It is not clear that
   138  this is necessary or even desirable.
   139  
   140  If a hosted program gets an attestation chain from the policy key, and it uses
   141  that attestation chain as its only means for authentication, then yes, the
   142  hosted program necessarily fully trusts the policy key. This is the same
   143  situation as described above for the parent Tao. Essentially, once the hosted
   144  program takes on the new identity, it "becomes" the principal named by that
   145  identity.
   146  
   147  But I see no reason that a hosted program could not use multiple identities
   148  (i.e. multiple attestation chains) for different purposes. In this case, the
   149  hosted program merely "speaks for" the principals named by those identities. And
   150  if anything, this is the opposite of trusting the policy server -- the policy
   151  server is trusting the hosted program to not abuse the privileges associated
   152  with that identity.
   153  JLM:  This idea of code identity is that it is immutable (i.e.-represents
   154  ultimately the exact same code (and possibly critical data).  You should NOT
   155  have multiple code identities although you certainly could participate in multiple
   156  security domains either by explicity having multiple policy keys or letting the
   157  master policy key delegate to others.
   158  
   159  Here is a concrete example: Suppose we build a secure write-only logging
   160  service, and the policy server (TaoCA) wants to use this service. The TaoCA can
   161  provide the logging program with an attestation, and the logging program can use
   162  that attestation to gain access to certain resources (say, confidential old
   163  logs). But the logging service might have other secrets, e.g. keys that it uses
   164  to ensure the write-only property of the logs, and there is no reason that the
   165  logging program should trust the policy server on these matters. In fact, the
   166  point is that we explicitly do not trust the policy server to do its own
   167  logging, but we do trust the logging server to do it.
   168  JLM:  This is an example of limited delegate trust to perform a service but it
   169  is not the same kind of "trust" you have to have in your hosts (and their hosts)
   170  which is basically unrestricted at least on a designated stack.
   171  
   172  Are there compelling examples of hosted programs that should necessarily and
   173  fully trust the policy server?
   174  JLM:  Yes in practice, I think there is.  Ultimately this becomes a 
   175  "policy distribution" problem analogous to a "symmetric key distribution" problem 
   176  without asymmetric ciphers and an n^2 policy problem is probably unmanageable for n>2.  
   177  As you point out, we may have constrained trust in a program operating elsewhere, written
   178  by another entity with a different policy key (or no policy key) but this is always constrained.
   179  Further, absent a "central" policy key, each program must maintain a list of things they trust,
   180  which is stateful and presents distribution problems (just like CRLs).  It becomes worse as
   181  some Tao element underneath get compromised.  For example, how does the program know
   182  other programs have been determined to be flawed?  Basically, the authority tells them and
   183  they recover.  I'm convinced that the notion of a policy key representing a well defined policy
   184  domain is basic.  Without it, I really have no overall sense of end-to-end security for an
   185  "activity" as a practical matter.  Finally, there is an (implicit) single root of policy in
   186  practice anyway for the program: the person who wrote the final version of the program (and embedded
   187  the key); whether he embedded a key or not we trust the program in this model.
   188  
   189  == Key Rotation ==
   190  
   191  NIST suggests (a) all keys should be rotated about every year, and (b) all data
   192  should be re-keyed every every one to three years.
   193  
   194  In the current implementation, there are a lot of keys to keep secret: every Tao
   195  layer has two (a private key and a symmetric key), and most of the "leaf" hosted
   196  processes at least two as well.
   197  
   198  The public key pairs used for authentication can be easily rotated. With two
   199  exceptions (below), a principal can unilaterally discard its authentication key
   200  pair at any time, generate a new key pair, then obtain a new attestation for the
   201  new key from its host Tao. The process can discard the old key pair immediately.
   202  For each processes with attestation chains involving the old public key, the
   203  process can either (a) simply retain the old pubic key and attestation chain
   204  until it expires, or (b) request a new attestation chain using the new public
   205  key. Processes can make this choice independently.
   206  
   207  The policy CA (aka TaoCA aka "key nego server?") can't unilaterally discard its
   208  authentication key, since lots of other principals rely on it for authentication
   209  and have copies of the policy CA's public key. The key must must be known by all
   210  Tao layers and hosted programs so that they can validate attestation chains
   211  rooted in the policy key or create authenticated network channels to the policy
   212  CA and other principals. Currently, the policy key is given to each participant
   213  through a (presumably) secure, offline channel at "setup time", and there is no
   214  rollover mechanism. Since authenticated network connections rely on attestation
   215  chains rooted in the policy key for that domain, an online key rollover would be
   216  required: the new policy public key would be sent to all participants over a
   217  channel authenticated using the old policy key. Any recipients could begin using
   218  the new key immediately, but all would need to to keep the old policy public key
   219  alongside the new one until all existing chains that might use the old key have
   220  expired. 
   221  
   222  A root Tao (i.e. the TPM) similarly can't unilaterally discard its
   223  authentication key (the TPM EK). In practice, of course, the TPM EK is permanent
   224  and can not be changed. But even if it could, rotation would be difficult for
   225  the same reasons as for the policy CA.
   226  
   227  The symmetric keys are difficult to rotate. A "leaf" hosted process can normally
   228  unilaterally select a new symmetric key at any time. Before it discards the old
   229  key, it must re-encrypt all of its data using the new key. So long as the hosted
   230  process manages and stores all of this encrypted data locally, this might be
   231  plausible.
   232  
   233  A host Tao (and some leaf hosted processes) can not easily rotate its symmetric
   234  key because the encrypted data is held and manged by child hosted processes. We
   235  might include an expiration and a "rollover" period in the seal operation. When
   236  the rollover period starts, the host Tao can pick a new key. During the rollover
   237  period, all hosted processes would be required to exchange all of their sealed
   238  secrets for newly encrypted copies, or simply re-seal the original data. At
   239  expiration (the end of the rollover period), the host Tao can discard the old
   240  symmetric key. The TPM probably does not support this.
   241  
   242  If symmetric keys are not ever rotated, and private keys are sealed using the
   243  symmetric keys, is there a reason to rotate the asymmetric keys? Presumably yes:
   244  the symmetric keys are used only (or mostly?) locally, but the asymmetric keys
   245  are used on the network.
   246  JLM:  You're right with respect to the "hardware" key.  To rotate it, you throw away
   247  the hardware (or in some cases, you solder something to the board).  In practice,
   248  at every other lever keys can rotate; if only by distributing new versions of the
   249  program with new policy keys.
   250  
   251  == Alternative designs ==
   252  
   253  I see no reason for Tao to closely follow the abstractions presented by the TPM
   254  interface, since nearly everything that talks to the TPM or deals with output
   255  from the TPM has to use special-purpose TPM-specific code. So long as the Tao
   256  API can be implemented on top of the TPM API, then nothing is lost in
   257  implementation "elegance". There is some extra conceptual overhead for those
   258  trying to understand the internals of how Tao is implemented, but users of Tao
   259  need only understand the Tao API, not the TPM API.
   260  JLM: yes, I agree.
   261  
   262  With that in mind, here are some API suggestions.
   263  
   264  == Tao generates keys for hosted program (idea #0) ==
   265  
   266  On balance, this is probably not worth implementing.
   267  
   268  Currently, every hosted program needs a symmetric key pair, attested to by its
   269  JLM: DO you mean asymmetric key pair?
   270  parent Tao. This is done in three steps: call GetRandomBytes() from the parent
   271  Tao, then generate the key locally in the hosted program, followed by calling
   272  Attest() from the parent Tao. We could condense this into a single Tao call:
   273  - (keypair, cert) = GenerateAuthenticationKey(suggested_expiration, other key details)
   274  The host Tao (or one of its parent Taos) would generate a fresh key pair and a
   275  matching signed attestation that the child can use for remote authentication. 
   276  
   277  Currently, GetRandomBytes() is used only for generating keys, but there are
   278  plenty of other possible uses for GetRandomBytes(). So this proposal does not
   279  eliminate getRandomBytes.
   280  
   281  Currently, Attest() is used only for attesting to keys. If that remains the
   282  case, then GetAuthenticationKey would obviate the need for Attest(). On the
   283  
   284  JLM: GetAuthenticationKey has to have a mechanism to verify the identity of
   285  the thing (program) it is giving its key to.  I think this is morally equivalent
   286  to Attest.  Of course, for some hosts, you could have a different mechanism
   287  to do this but since the bottom layer in a distributed system is stuck with a
   288  public key based attest and since there are no performance or flexibility problems
   289  with this, I don't know that we want another mechanism to worry about.
   290  
   291  other hand, we can't eliminate Attest() if it evolves into a general-purpose
   292  "says" operation that allows, for example, a hosted program without its own key
   293  to get a signed credential to the effect of "Tao says child says stmt" for some
   294  arbitrary statement. 
   295  
   296  Pros: 
   297  - Slightly more efficient.
   298  - Maybe eliminate the Attest operation, whose semantics are currently hazy.
   299  JLM: I'm not quite sure what you mean by hazy.  Attest means "The signed data (usually
   300  a key as you point out) came from the program with the following identity (the hash) which
   301  was isolated by me (the host)."  This seems like a very clear (and useful) assertion.
   302  
   303  Cons:
   304  - If we don't eliminate Attest(), then it makes the Tao API larger.
   305  JLM: Why does it become larger?   You argue above that we need Attest somewhere
   306  (maybe only in HW) so it seems an alternate mechanism adds surface area.  I'm not
   307  sure I understand this comment.
   308  - Functionality easily implemented in the hosted program using the existing API.
   309  
   310  == A minimalist API (idea #1) ==
   311  
   312  I don't think we should do this, but I think it is a useful point of comparison.
   313  
   314  Tao layers and other hosted programs form a tree. But currently, except for
   315  GetRandomBytes(), there is no interaction between layers except during startup.
   316  Upon startup, a hosted Tao does either a single Seal() and a single Attest(), if
   317  this is the first execution and keys need to be generated, or it does a single
   318  Unseal() to recover its previously-generated keys. From then on it has its own
   319  set of keys, which it uses to implement Seal(), Unseal(), and Attest() for
   320  hosted child processes. 
   321  JLM: There is continued interaction for StartHostedPrograms as new hosted systems
   322  start and, of course, the hosted program can use the Generate/Attest/Seal/Unseal
   323  dance to rotate keys (although this presumably doesn't happen too often.
   324  
   325  If this is the case, why not simplify the API and eliminate the channels between
   326  layers entirely? When a hosted program is about to be started, the host Tao
   327  checks if sealed keys and an attestation exist for that program. If so, Tao
   328  unseals the keys, and passes the keys and attestation as parameters to the
   329  hosted program. If not, Tao generates a set of keys, seals them, makes an
   330  attestation for them, then passes the keys and attestations as parameters to the
   331  hosted program. There is no API for hosted programs to communicate with the host
   332  Tao (except maybe GetRandomBytes). If a hosted program wants to keep secrets, it
   333  can encrypt them itself using its own key. If it wants to do remote
   334  authentication, it has a suitable key and matching attestation.
   335  
   336  All of this applies to "leaf" hosted programs and to hosted Taos alike. The TPM
   337  would be a special case (as it is now). In order to launch the first real Tao
   338  layer, sitting directly above the TPM, someone (either that Tao or some helper
   339  program) would need to open a connection to the TPM and make the necessary
   340  seal/unseal/attest requests. This special-case code is really implementing the
   341  TPM's missing StartHostedProgram() call.
   342  
   343  Pros:
   344  - Simpler (trivial) API and implementation.
   345  JLM: Again, to my mind this seems more complicated.  Since you need the Tao at the lowest level
   346  adding additional mechanism just adds to surface area.  Of course, you could package the basic
   347  dance so that layers that don't care about it make simpler calls but you've added complication
   348  (as measured by mechanisms and code).  Packaging the mechanisms is fine and represents a saving
   349  in terms of how many people implement what but it doesn't save, and in fact increases, the "minimal"
   350  implmentation footprint.
   351  - Efficiency: no need to keep secure channels (pipes) open.
   352  - Hosted programs don't need generate or rotate their own keys.
   353  JLM: They still may need to rotate their keys.  The hosts are not necessarily in the same
   354  trust domain as the children.  Policy only requires that host adhere with their contract not
   355  that they be able to carry out all security related domain actions.  In fact, the idea is to
   356  let lower Tao levels be as simple as possible to avoid security issues that will necessarily affect
   357  their hosted programs.  By contrast, two hosted programs in the same security domain can
   358  actually segregate duties, thus preventing a single program from causing universal damage.
   359  
   360  Cons:
   361  - Hosted programs don't control their own key generation or rotation.
   362  - Hosted program keys are in memory during the entire program execution, with no
   363    flexibility to do seal-then-reseal for shorter intervals.
   364  - Hosted programs can't easily have multiple keys (say, with different
   365    expirations or strengths), multiple attestations (say, from different policy
   366    servers), etc.
   367  
   368  == Sealing with expirations (idea #2) ==
   369  
   370  I think we should at least do option (b) below. It is simple but it adds some
   371  nice functionality that is currently missing.
   372  
   373  To facilitate rotating the symmetric keys, seal/unseal should really have an
   374  expiration. When a hosted program seals data, the hosted program and the host
   375  Tao agree on some expiration date. The host Tao promises to keep the sealing key
   376  available until that expiration, but no longer. The sealed bundle is only
   377  guaranteed to be unsealable until the expiration, and it is up to the hosted
   378  program to ask for the sealed bundle to be rekeyed with a new expiration date
   379  before the original expires.
   380  
   381  There are choices: 
   382  
   383  (a) The Tao keeps a set of one or two sealing keys, one active, one old, both
   384  with expirations. When the old key expires, it is discarded. When the active key
   385  nears expiration, it becomes the old key and a new active key is generated. Tao
   386  uses the active key for sealing, and refuses to seal data with an expiration
   387  past the active key's expiration. For unsealing, Tao uses whichever key is
   388  needed.
   389  
   390  Pros:
   391  - Easy to implement host Tao (small delta from current implementation).
   392  
   393  Cons:
   394  - Painful for hosted programs, which must re-seal according to host Tao's
   395    schedule.
   396  - Hard to chose expiration for host Tao key -- too short forces repeated
   397    re-sealing, too long adds unnecessary risk.
   398  
   399  (b) Same as (a), but Tao could instead keep multiple key sets with different
   400  expiration schedules. So there might be five key sets that rotate every hour,
   401  week, day, year, and decade. When a hosted program requests to seal data with
   402  some expiration time, Tao just uses the active key for the shortest appropriate
   403  set. 
   404  
   405  Pros:
   406  - Simpler semantics for hosted programs: they can chose any reasonable
   407    expiration.
   408  
   409  Cons:
   410  - More state for Tao, but not significant and could be made constant.
   411  - Expirations of sealing key will not exactly match expiration for data. So a
   412    2-year sealed bundle might have been signed with a key that is kept for a
   413    decade.
   414  
   415  (c) Tao could use a unique symmetric key for every seal operation, with the key
   416  expiration chosen to match the requested expiration of the data. During seal,
   417  Tao generates the key, sets its expiration, and returns the encrypted data to
   418  the hosted program. Tao manages the sealing key just like it manages its other
   419  secret data, i.e. by asking its parent Tao to seal it or by encrypting it and
   420  having its parent Tao seal the encryption key. 
   421  
   422  Pros:
   423  - Simple semantics for hosted programs: they can chose any expiration.
   424  - Expiration of sealing key exactly matches expiration of data.
   425  - Amortization of costs and extra state management adds complexity to host Tao.
   426  
   427  Cons:
   428  - Expensive: potentially multiple key generations and encryptions (as
   429    many as one for each Tao layer, including one for the TPM) for every Seal()
   430    operation. Similar for Unseal.
   431  - Cost for recursive calls might be amortized across Seal/Unseal operations:
   432    host Tao could wait some time or until it has generated N sealing keys, then ask
   433    its parent Tao to seal them all together or use its own symmetric key to encrypt
   434    them.
   435  - More state for each Tao layer, grows with number of Seal() operations.
   436  - Because of state growth, may want way to reclaim keys that are not expired but
   437    no longer needed.
   438  
   439  (d) Same as (c), but the host Tao doesn't manage the sealing key. Instead, it
   440  generates a per-bundle sealing key, then asks its own parent Tao (or the TPM) to
   441  seal that sealing key. Then encrypted data and encrypted key make up the sealed
   442  bundle. During unseal, Tao asks its parent to unseal the key, then uses the key
   443  to decrypt the data. This is recursive, with each layer generating a key then
   444  asking its parent to seal that key. Alternatively, the same effect can be
   445  achieved by just having Tao append the child name to the data, then pass this to
   446  its parent Tao for sealing. The parent will in turn append a name and pass it to
   447  its own parent. During unseal, each layer asks the parent to unseal, then checks
   448  the name at the end (as it currently does), then passes the result back to the
   449  requester.
   450  
   451  Pros:
   452  - Simple semantics for hosted programs: they can chose any expiration.
   453  - Expiration of sealing key exactly matches expiration of data.
   454  - Simple implementation: no extra state stored by host Tao.
   455  
   456  Cons:
   457  - Expensive: always multiple key generations and multiple encryptions (one for
   458    each Tao layer, including one for the TPM) for every Seal() operation.
   459    Unseal() is similarly expensive.
   460  
   461  == TaoCA is a Tao (idea #3) ==
   462  
   463  Though I haven't digested this idea completely yet, I don't like it.
   464  
   465  I argued above that hosted programs should not normally fully trust the TaoCA
   466  server (aka policy server). But if we are going to go with the idea that each
   467  hosted program has an embed ed policy key that it fully trusts for all important
   468  decisions... then why not consider TaoCA to be a Tao?
   469  
   470  The requirement for being a parent (i.e. a Tao) are:
   471  - There is a secure authenticated channel from parent to each child (or one can
   472    be created when needed).
   473  - The parent can recognize and identify its children.
   474  - The parent can provide the Tao API operations for its children.
   475  
   476  TaoCA can easily generate keys sufficient to implement the Tao operations
   477  (except getRandomBytes and start/remove hosted program). It basically implements
   478  Attest() already. And even though it doesn't implement start/remove hosted
   479  program, it has enough information that it can recognize its own children, e.g.
   480  its list of approved TPM EKs. It can create authenticated TLS channels to its
   481  children because it happens that every one of its children either (a) possesses a
   482  TPM EK the TaoCA knows about or (b) possesses an attestation chain from a TPM EK
   483  that the TaoCA knows about.
   484  
   485  Here, a hosted Tao can have more than one parent Tao. LinuxTao might have the
   486  TPM as one parent and a TaoCA as a second parent. Other layers hosted on that
   487  Tao might have additional (or the same) TaoCAs as parents. Even a "leaf" hosted
   488  program may have multiple Tao ancestors, because its host Tao and/or other
   489  ancestor Taos have multiple parent Taos. So some Tao operations may require
   490  extra parameters to specify which line of ancestry to follow for that call. For
   491  example, Attest() would need to specify a complete path from some root Tao,
   492  among all the possible root ancestor Taos, all the way down to itself.
   493  
   494  JLM:  While I don't think of the TaoCA as a Tao, it could and probably should
   495  be able to negotiate and shared keys within a domain.  For me, multiple Tao hosts
   496  makes end-to-end evaluation of hosted programs too complicated and error prone
   497  and given the distributed policy, I just don't see the need.
   498  
   499  Pros:
   500  - Formalizes the role of the TaoCA and its (trust) relationship with hosted
   501  programs, hosted Taos, etc.
   502  
   503  Cons:
   504  - I think hosted programs do not really (and should not) full trust any policy
   505  server under normal circumstances.
   506  
   507  == Use symmetric keys within a machine (idea #4) ==
   508  
   509  I think we should do this.
   510  
   511  We should add functionality to the Tao API to support the creation of
   512  authenticated channels between Tao-relatives, i.e. between two hosted programs
   513  that share a common Tao ancestor. The processes are necessarily on the same
   514  machine since they are all under the same TPM, and fully trust their common
   515  ancestors, so there isn't much reason to be doing expensive public key
   516  encryption.
   517  
   518  Every hosted program is already assumed to have a authenticated private channel
   519  to its host Tao and, indirectly, to every ancestor Tao as well. A call to
   520  GetRandomBytes, for example, might be passed down to some distant ancestor. 
   521  
   522  For any given pair of Tao hosted programs (or hosted Taos) running on the same
   523  machine, there is one or more common ancestor Taos that is necessarily trusted
   524  by both. We can use a common ancestor Tao to distribute a shared symmetric key
   525  to the pair of hosted programs. The two programs can then use TLS-PSK to
   526  communicate.
   527  
   528  Elsewhere [Cryptography.txt, AuthenticationImplementation.txt] I explore some
   529  possibilities. To summarize the options:
   530  * (a) Currently we use TLS and policy-attested (or Tao-attested) public keys for
   531    all authentication between local programs, even if they share a common
   532    ancestor.
   533  * (b) We could instead rely instead on channels implemented by the OS or vm,
   534    with no TLS at all. Basically, pipes. 
   535  * (c) This proposal.
   536  
   537  Option (a) is slow/expensive, and you have to worry about exposure of long-lived
   538  keys (the policy key, the public keys of each hosted program and each Tao).
   539  
   540  Option (b) is fast/cheap, but it would make the Tao implementation and API much
   541  more complex. And there is no common mechanism that could be written just once:
   542  every Tao (for linux, kvm, evmm, etc.) would need separate mechanisms for
   543  managing the channels. Implementing this would be like implementing
   544  StartHostedProgram, but worse.
   545  
   546  Option (c), this proposal, has moderate speed and expense, and the
   547  implementation and API is fairly simple. Once a pair of hosted programs has a
   548  shared symmetric key, they can use TLS-PSK to communicate, which relies only on
   549  symmetric cryptography and avoids the use of asymmetric keys. 
   550  
   551  As with sealing, the symmetric keys should have an expiration negotiated between
   552  the requesting hosted program and the common ancestor Tao. Basically, each of
   553  the two hosted programs can independently ask their parents for a suitable
   554  symmetric key to talk to the other, using an API like this:
   555  - shared_key = GenerateSharedKey(my_name, peer_name, requested_expiration)
   556  Just like GetRandomBytes, the call can traverse down the chain of parent Taos,
   557  stopping when it reaches a common ancestor. If the common ancestor can use a
   558  key-generation key (KGK) to deterministically generate the shared key as a
   559  function of the two peer names and its actual expiration. As long as that Tao
   560  keeps and uses the same KGK until after the expiration, and the generation
   561  function is deterministic, then both hosted programs will get the same key.
   562  
   563  The my_name parameter is only needed if hosted programs can be identified by
   564  more than a single name. Currently, every hosted program is identified by a hash
   565  of the program binary and the command-line arguments. But we could have other
   566  identifiers that mix in the process id, time of process creation, etc., yielding
   567  identifiers with various levels of detail. The my_name parameter would let the
   568  caller chose which granularity to use.
   569  
   570  Note: the hosted programs do not need to store (or seal) the shared keys,
   571  because the key generation is deterministic. At any time, if they simply
   572  re-request the a key with the same expiration, they should receive the same
   573  shared_key result from the ancestor Tao. Just like for sealing, the ancestor Tao
   574  needs to keep the key-generation keys available, and might have multiple
   575  key-generation keys to use with different expirations.
   576  
   577  Note: The TPM doesn't support this directly. The first real Tao, sitting
   578  directly above the TPM, would need to implement this feature using a combination
   579  of TPM Seal/Unseal/Random operations.
   580  
   581  == Use symmetric keys with a cloud, after bootstrapping (idea #5) ==
   582  
   583  I don't think we should implement this yet: the benefit isn't obvious enough.
   584  
   585  The idea above for using symmetric keys and TLS-PSK for communication between
   586  two hosted programs works when we have an already-established secure
   587  authenticated channel from each of the two hosted programs to some trusted third
   588  party. There, two hosted programs within the same machine used an ancestor Tao
   589  as the trusted third party, and the channels to it went through the stack of
   590  parent Taos. 
   591  
   592  For two hosted programs executing on different machines but in the same cloud
   593  (aka "Cloud-relative", i.e. programs executing in the same Tao domain, i.e.
   594  governed by the same policy key), the policy server can serve as a trusted third
   595  party to distributed shared keys. We just to "bootstrap" this by creating an
   596  authenticated, secure channel from the hosted programs to the policy server. 
   597  
   598  When a hosted program wants to communicate with some Cloud-relative program, the
   599  hosted program establishes a TLS channel to the policy server as usual,
   600  authenticated using its parent-Tao attested asymmetric key. The hosted program
   601  then does a GenerateSharedKey() RPC to obtain a shared key that it can use to
   602  communicate with the specified Cloud-relative. As before, both peers make this
   603  call independently, so the policy server will need to generate they shared keys
   604  deterministically.
   605  
   606  Note: It might be the case that the hosted program's parent Tao will be governed
   607  by the same policy server as the hosted program itself, but I don't think this
   608  is always the case. If it were the case, then the hosted program could ask its
   609  parent Tao (or, indirectly, its ancestor Tao) to contact the policy server on
   610  its behalf, saving the cost of the TLS setup for each hosted program.
   611  
   612  The cost for avoiding asymmetric operations with the peer is the asymmetric-key
   613  TLS setup for the channel to the policy server. But this cost is amortized over
   614  all connections to the peer during the same execution. And once we have a shared
   615  symmetric key, we can seal it on the peer to avoid the need to talk to the
   616  policy server during subsequent executions (assuming the hosted program identity
   617  doesn't change between executions). The cost can also be amortized over multiple
   618  operations with the policy server: once the channel is open to the policy
   619  server, the hosted program can obtain shared symmetric keys for many peers. 
   620  
   621  To summarize:
   622  * (a) Currently we use TLS and policy-attested (or Tao-attested) public keys for
   623    all authentication between remote programs, even if they share a common
   624    trusted policy server.
   625  * (b) We could simply use the TLS session-resume feature.
   626    This just uses asymmetric-key TLS on the first TLS connection to a peer, then
   627    uses that session to establish a shared symmetric key to be used for
   628    subsequent TLS connections. 
   629  * (c) This proposal.
   630  
   631  Option (a) requires expensive asymmetric-key operations once per connection, and
   632  you have to worry about exposure of long-lived public keys (the policy key, the
   633  public keys of each hosted program and each Tao).
   634  
   635  Option (b) amortizes expensive asymmetric-key operations to once per pair of
   636  communicating hosted programs, at best. But it simple to implement, and requires
   637  no Tao infrastructure. You still have to worry about exposure of long-lived keys
   638  because of the initial TLS session to the peer.
   639  
   640  Option (c) amortizes expensive asymmetric-key operations to once per hosted
   641  program, at best. It seems a bit complex to implement (managing the amortization
   642  across executions), and it requires Tao infrastructure (generating shared keys
   643  at the policy server). It's also not clear that the extra amortization beyond
   644  option (b) is significant. And you still have to worry about exposure of
   645  long-lived public keys because of the initial TLS session to the policy server.
   646  
   647  On the other hand, with option (c), there is no longer any need for
   648  policy-attested public keys, since all communication between hosted programs
   649  would use parent-Tao attested keys to create the connection to the policy
   650  server, then shared keys to communicate with each other.
   651  
   652  == Eliminate seal and unseal, use hosted program keys instead (idea #6) ==
   653  
   654  I like this idea, and I think we should implement it. 
   655  
   656  If we can outfit each hosted program with a symmetric key that is available only
   657  to that hosted program (and, of course, its necessarily-trusted parent and
   658  ancestor Taos), then a hosted program can implement Seal and Unseal operations
   659  without further help from its parent Tao. Seal and Unseal instead become
   660  convenience library functions, executed entirely locally within each hosted
   661  program or hosted Tao: The hosted program uses its symmetric key to used to
   662  encrypt program data, creating a sealed bundle, then later during the same or
   663  subsequent executions, it uses the same key to decrypt the sealed bundle and
   664  recover the data. 
   665  
   666  Idea #4 above provides a way for any hosted program to obtain a program-specific
   667  symmetric key by making a request to its parent Tao. Essentially, a program
   668  would ask to obtain a key that is shared with future versions of itself, by
   669  calling:
   670  - shared_key = GenerateSharedKey(my_name, my_future_name, requested_expiration)
   671  
   672  == Summary of revised Tao API ==
   673  
   674  I will outline a revised Tao API using these decisions:
   675  . Reject idea #0 - Tao generates keys for hosted program
   676  . Reject idea #1 - A minimalist API
   677  ~ Accept idea #2 - Sealing with expirations, option (b), sort of
   678  . Reject idea #3 - TaoCA is a Tao 
   679  * Accept idea #4 - Use symmetric keys within a machine
   680  . Reject idea #5 - Use symmetric keys with a cloud, after bootstrapping
   681  * Accept idea #6 - Eliminate seal and unseal, use hosted program keys instead
   682  
   683  Ignoring C++-isms, the revised tao API would look like this:
   684  - Unspecified: implementation/context-specific hooks for managing the lifecycle
   685    of hosted programs and the Tao service itself.
   686  - bytes = GetRandomBytes(size)
   687    Same as current API. 
   688  - attestation = Attest(statement)
   689    Same as current API, but with a statement in some logic not a blob of opaque
   690    data. The returned attestation conveys "Tao says (child says statement)",
   691    where "Tao" is really the Tao's public key, and "child" is the hash of the
   692    hosted program making the request. 
   693  - shared_key = GenerateSharedKey(my_name, peer_name, requested_expiration)
   694    Generate a shared symmetric key that is available only to hosted programs with
   695    name my_name or peer_name. The call is only successful if my_name is one of
   696    the caller's identities. Otherwise, exchanging my_name and peer_name doesn't
   697    affect the result. The call is only successful if the expiration has not past.
   698  
   699  Convenience/library methods implemented locally in hosted programs:
   700  - (keypair, cert) = GenerateAuthenticationKey(suggested_expiration, other key details)
   701    Calls GetRandomBytes(), then generates a key pair, then calls Attest() with an
   702    appropriate statement describing the public key, its expiration, and possibly
   703    other key details (e.g. key usage?). This just packages up what all of the
   704    current hosted programs already do.
   705  - sealing_key = GenerateSealingKey(my_name, requested_expiration)
   706    Calls GenerateSharedKey(my_name, my_name, requested_expiration).
   707  - blob = Seal(my_name, data, requested_expiration)
   708    Calls GenerateSealingKey(my_name, requested_expiration), then uses the
   709    resulting key to encrypt the data. Maybe attach requested_expiration to the
   710    blob. Maybe also attach my_name.
   711  - data = Unseal(my_name, requested_expiration, blob)
   712    Calls GenerateSealingKey(my_name, requested_expiration), then uses the
   713    resulting key to decrypt blob and recover the data. If we attach my_name and
   714    requested_expiration to the blob during Seal(), then we don't need to pass
   715    them as parameters here. As with the current Seal() implementation, the blob
   716    must have been created via a Seal request to by the same hosted program
   717    running on the same parent Tao. 
   718  
   719  Observation: There is nothing here about authentication between hosted programs
   720  and the outside world. That already requires different mechanisms, e.g. using
   721  x509 certificates and https (and there is no simple way to convey all the
   722  information in a Tao attestation chain, since those chains are rooted in the TPM
   723  which does not generate x509-compatible certificates. Currently,
   724  https-compatible x509 chains are produced by the policy server.  Aside from
   725  this, there isn't much of a role for the policy server.
   726  
   727  == Groups and Sub-principals ==
   728  
   729  It is tempting to use subprincipals and delegation instead of groups and
   730  membership. For example, K_policy::TrustedPlatform could be the name for some
   731  group of TPM-based platforms. K_policy can issue delegations that effectively
   732  convey group membership, e.g.
   733    K_policy says (K_tpm speaksfor K_policy::TrustedPlatform)
   734  from which we can derive:
   735    K_tpm speaksfor K_policy::TrustedPlatform
   736  From here, K_tpm can speak for the group.
   737  
   738  But things get complicated quickly. Each time the TPM speaks, we must decide
   739  whether it should speak as K_tpm or as K_policy::TrustedPlatform. And for a
   740  program OS hosted on this TPM, we must decide if the program should be identified
   741  as a subprincipal of K_tpm or as a subprincipal of K_policy::TrustedPlatform.
   742  The latter, e.g. K_policy::TrustedPlatform::TrustedOS, is tempting because
   743  K_policy is likely to be a well known name (whereas K_tpm and its subprincipals are
   744  possibly known only locally and to K_policy). So we are effectively creating a
   745  "sub-group", K_policy::TrustedPlatform::TrustedOS, containing all instances of
   746  certain programs hosted on some platform in the K_policy::TrustedPlatform group.
   747  This makes the job of writing policies somewhat easy. For example,
   748  K_policy::TrustedPlatform::TrustedOS can be put on an ACL, and that will cover
   749  all of the instances of OS. Or, we can arrange for OS to have its own key, K_os,
   750  and create delegations K_os speaksfor K_policy::TrustedPlatform::TrustedOS. Or
   751  create a chain of delegations, e.g. K_os speaksfor
   752  K_policy::TrustedPlatform::PCRs(...), K_policy::TrustedPlatform::PCRs(...)
   753  speaksfor K_policy::TrustedPlatform::TrustedOS. Or maybe keep the names shorter
   754  with a chain K_os speaksfor K_policy::TrustedPlatform::PCRs(...),
   755  K_policy::TrustedPlatform::PCRs(...) speaksfor K_policy::TrustedOS. The
   756  variations are seemginly endless.
   757  
   758  But notice that according to the logic, if mutually inconsistent statements are
   759  made by any of the platforms, the entire group is compromised. When we make a
   760  group in this way, we are essentially taking all the statements of the members
   761  and taking the closure. Also, a lot of policy-relevant decision making has to be
   762  done at the time statements and delegations are issued and when naming
   763  principals. Ideally, every Tao has some well defined name or names, and uses
   764  those names in simple, clear, and consistent ways that do not depend on the
   765  vagaries of higher-level policy.
   766  
   767  So it seems that when a Tao obtains and makes use of some policy attestation,
   768  this is treating K_policy as if it were a "parent" Tao, and ionly leads to
   769  trouble and confusion. 
   770  
   771  One alternative to using a subprincipal as groups is to use an intensional group
   772  defined by a characteristic predicate.  Here, we would put on the ACL something
   773  like:
   774     { p : (exists t, o :
   775  			   p speaksfor o::Prog(h) and K_policy says isTrustedProgram(h) and
   776                     o speaksfor t::PCRS(r) and K_policy says isTrustedOS(r) and
   777  						K_policy says isTrustedPlatform(t) ) }
   778  And we arrange for K_policy to define each predicate, e.g.
   779    K_policy says isTrustedPlatform(K_tpm)
   780    K_policy says isTrustedOS("...pcrs...")
   781    K_policy says isTrustedProgram("...hash...");
   782  
   783  Notice that here, the TPM always speaks using its single identity, K_tpm. A
   784  hosted Tao always speaks as a subprincipal, e.g. K_tpm::PCRs(...). For
   785  performance reasons, a hosted Tao can create its own key K_os, and then obtain
   786  from its parent a delegation K_os speaksfor K_tpm::PCRs(...). This allowing it
   787  to speak as K_tpm::PCRs(...) while actually doing cryptography using the local
   788  key K_os. A child of this hosted Tao would always speak as
   789  K_tpm::PCRs(...)::Prog(...), and so on, and these too could make similar
   790  performance optimizations using their own local keys.
   791  
   792  A second alternative way to implement groups is to make use of predicates
   793  directly, and not use groups at all. So we might say that a principal P
   794  is authorized perform some operation "op" if
   795    K_policy says Authorized(P, "op")
   796  And we arrange for K_policy to define this predicate, e.g.
   797    K_policy says Authorized(K_tpm::PCRs(...)::Prog(...), "op")
   798  or:
   799    K_policy says
   800        ((exists t, o :
   801  			   P speaksfor o::Prog(h) and K_policy says isTrustedProgram(h) and
   802                     o speaksfor t::PCRS(r) and K_policy says isTrustedOS(r) and
   803  						K_policy says isTrustedPlatform(t) )
   804  	   implies (K_policy says Authorized("op", P)))
   805  The latter would be coupled with the same kinds of predicate definitions we saw
   806  above, e.g.:
   807    K_policy says isTrustedPlatform(K_tpm)
   808    K_policy says isTrustedOS("...pcrs...")
   809    K_policy says isTrustedProgram("...hash...");
   810  
   811  Let's take this second alternative and try it out.