Capability-based Active Invocation Certificates

From Erights

Revision as of 17:33, 9 February 2011 by 15.243.233.68 (Talk)
(diff) ←Older revision | Current revision (diff) | Newer revision→ (diff)
Jump to: navigation, search

Contents

Highlights

CapCert is a cryptographic object-capability system relying on signed certificates rather than transmitted secrets. Were all these signed certs transmitted in the clear, confidentiality of the messages would of course be lost. But no integrity would be lost. The basic philosophy, imprecisely stated:

  • Use signing key pairs to represent object identity, where the (public) signature verification key designates the object and the (secret) signing key represents the permission to be the object.
  • Designation is not permission, but rather, permission is represented by a tree of signed messages, to be validated as conforming to ocap message rules.
  • Each message is signed by its sender.
  • For the receiver and each argument in the message, the message carries its designation and the prior messages received by this sender, demonstrating that this sender has been permitted to invoke that receiver and those arguments.
  • The sender is implicitly permitted to invoke itself without further demonstration.
  • Initial non-self connectivity is by distinct "initial certs" issued by the designated object to a recipient and conveyed to the recipient by out-of-band means, i.e., not by CapCert invocations.
  • The arguments of a message may instead be code expressing an attenuation of a directly permitted designator. The sender thus grants the recipient only the ability to invoke that attenuation of the sender's permission.
  • Attenuations thus compose along delegation chains. Attenuators are instantiated by the server (vat) of the resource to be attenuated.

The main difference between the idea presented above and the concrete CapCert proposal presented below is that below, the signing keys are per vat. A signing key and an SwissHash (an authority-free designator which is a cryptohash of an object's SwissNumber) together designate an object in a vat.

It is a bizarre side effect of this system that the validatability of messages (that need to be checked by receivers) implies auditability. The auditability here is similar to that provided by Horton but different in at least the following ways:

  • CapCert auditing info is non-repudiable (in a technical, not a legal sense), whereas Horton auditing info is normally repudiable. (A non-repudiable variation of Horton is possible. A repudiable variation of CapCert may not be.)
  • In CapCert, the auditing info is revealed to the target of an invocation, including the chain of prior messages. In Horton, each delegated resource receives info about "who" delegated it to "whom", but only receives the message by which it is directly invoked.

We are unaware of any theory of composable auditability, or of reconciling confidentiality with auditability, so it is not yet clear which form of auditability to prefer, or what the other salient differences might be.


Material taken from stuff linked from capcert.org to the archives of the E-lang mailing list:

First message

Mark S. Miller wrote Tue, 17 Oct 2000 14:55:48 -0700 in 1:

While Alan Kay was heaping criticism on the early Macintosh, 
he also quipped that the Mac was "the first computer good enough to 
criticize".  Such reminders are important, when one singles out the 
best of a field for intense criticism, while ignoring its crappy cousins.

Similarly, SPKI is the only PKI/Certificate system I know of that's good 
enough to criticize.  As explained in the Ode:

>The enforceable subset of SPKI can be seen as an off-line, auditable, 
>heavyweight, non-confinable, semi-capability system, as opposed to E's 
>on-line, repudiatable-by-default, lightweight, confinable, full-capability 
>system. Perhaps, by comparing these, we may figure out how to build systems 
>with some of the best of both.

SPKI-like certificate technology and real capabilities clearly should be 
able to get along, but until now it wasn't clear how.  The following 
proposal is inspired by Nikita Borisov's "Active Certificates" 
http://www.cs.berkeley.edu/~nikitab/papers/acert-retreat.ppt , although 
Nikita wasn't explicitly thinking in capability terms either, he 
nevertheless provided the bridge.

Development note: I plan to complete hash chaining proposal #1, and its 
application to simplify persistence and Pluribus, for the next release of E. 
Indeed, the reconstruction of Pluribus is the gating item for this next 
release.  The proposal in this note (#2) is more long term.  Neither E nor 
E's current users currently require it, though it would add significant 
value.  So don't expect it anytime soon.  However, because it makes a second 
use of hash chaining to represent cryptographic capabilities, 
it would be good to know early whether it can co-exist with our 
other cryptographic representations of capabilities.  I want to leave the 
door open to implement this proposal later as an upward compatible extension 
of E.  If you see any possible problems on this horizon, please fire away.

Before we get to the "active" stuff, let's strip from SPKI everything that 
isn't capability logic.  It's ok if the result isn't usable at this stage, 
as long as we get back to a usable result once we put the "active" stuff in.


                                        Deconstructing SPKI


After signature checking and expansion, we see from Section 6 of 
http://www.ietf.org/rfc/rfc2693.txt that there are only two kinds of SPKI 
certificates: Authorization Certificates (or 5-tuples) and Name Certificates 
(4-tuples).  Although the SPKI perspective on names is more capability-like 
than the other PKIs, it is still not the true capability perspective on 
names, so we get rid of the Name Certificate.

We state in the Ode that a SPKI Authorization Certificate corresponds to a 
capability message, but this isn't quite right.  A capability message not 
only authorizes Bob to access Carol, but it packages this authorization 
with information that should communicate to Bob why he's being given the 
argument authorizations (the label "foo"), and in which each individual 
authorization occupies a distinct argument position, corresponding to its 
role in the "why".

So a SPKI Authorization certificate corresponds to an argument in a 
capability message.  An argument in a capability message is normally 
understood to simply be a capability, so what distinction am I drawing?  At 
the capability layer of abstraction, there are no certificates, and the 
arguments of capability messages are simply capabilities.  While at the 
crypto-implementation layer of abstraction, SPKI is a non-bearer protocol.  

An individual SPKI Authorization Certificate implements a capability as 
passed specifically from Alice to Bob.  If Bob then further authorizes Dana, 
this next authorization is the same capability but a different certificate.  
If E's current SturdyRefs are off-line bearer capabilities, we might say 
that authorization certificates are SturdyArguments -- off-line per-message 
capabilities.

So now let's examine the parts of a SPKI Authorization Certificate with 
regard to representing an argument in a capability message.

1) Issuer:  Fingerprint of the public key corresponding to the private 
signing key of the party sending the message.  The tuple as a whole is also 
signed with the Issuer's signing key.  Great.  We'd keep this.  For us, the 
Issuer would be the Vat, and this fingerprint is the VatID.  In the standard 
example, this is VatID(A).  It's not yet clear whether this field needs to 
be expanded to uniquely designate Alice within VatA.

2) Subject: Fingerprint of the public signature key of the party the message 
is being sent to.  In the standard example, this is VatID(B).  It's not yet 
clear whether this field needs to be expanded to uniquely designate Bob 
within VatB.

3) The infamous do-not-delegate bit.  We need to eradicate this and then 
find a strong cleanser to remove its stench.  (For those new to this list, 
see http://www.erights.org/elib/capability/conspire.html .)

5) Validity dates -- the interval during which the certificate is considered 
valid.  It's not clear whether or not this needs to be primitive.  Also, 
it's most peculiar to include an interval start time rather than just a 
deadline.  Since the deadline corresponds to the expiration time of our 
existing SturdyRefs, I'm inclined to keep the deadline for now.

4) Authorization.  An S-expression which states what rights are being 
authorized.  Intermediaries on the delegation chain can use this 
S-expression language to express subsettings of the rights being passed on.
Complex rules compose these expressed subsettings to calculate the 
intersection of allowed rights.  This item is where the action is.  

First, we remove everything extraneous from this item.  This S-expression 
language is assumed to bottom out in human readable names, and in wildcards 
over such a names.  From a capability point of view, this name space is 
misguided, and the wildcards are therefore pointless.  The rights at the 
bottom of a subsetting expression should simply be the right to invoke a 
particular object.  With this as the right to be subsetted, the SPKI 
S-expression language is clearly useless as a means to subset it.  This will 
be where Nikita's "Active" ideas become crucial, but for now let's just drop 
all the subsetting logic.  What's left?  A unique unambiguous designator of 
Carol.  

<misplaced-motivational-aside>

Till now, when we wanted a cryptographic representation for designating 
Carol, we always used the pair <VatID(C), swissNumber(Carol)>.  However, if 
we use this representation here, we lose one of the really cool properties 
of Certificates: they can communicate authority without communicating 
secrets.  Indeed, the only information they require one to keep secret is 
one's own private signing key.  Because they rely on signature chains rather 
than secrets, distributed computation stitched together with certificates 
has very strong non-repudiation and auditing properties.  OTOH, it's vastly 
more expensive than on-line secret-based protocols like Pluribus.  Which one 
to use depends on context, so it would be good to be able to switch from 
one to the other while keeping the abstract capability semantics constant.

</misplaced-motivational-aside>

So, instead, we need the designator of Carol in the certificate to uniquely 
and unambiguously designate Carol without itself granting the authority to 
invoke Carol.  The authority to invoke Carol comes from the signature chain 
that reflects the sequence of introductions, starting with VatC, by which 
VatB came to attempt to invoke Carol.  Yes, believe it or not, I am 
advocating a kind of separation of designation and authority, but I don't 
believe that this separation has any semantics or presents any dangers.


                                 Hash Chaining Again


So let's say that the Certificate's Authorization field contains, not 
<VatID(C), swissNumber(Carol)>, but <VatID(C), hash(swissNumber(Carol))>.  
Since we assume hashes are strongly irreversible, knowledge of 
hash(swissNumber(Carol)) provides no knowledge of swissNumber(Carol), and 
only the latter is a secret that provides authority.  This representation 
also makes it easier to see how to interface between the bearer and the 
certificate worlds:

Given a live (a bearer on-line) reference to Carol (and given another 
capability on VatC (the function sturdyRef() that grant the authority to 
burden VatC with a storage obligation), Alice may currently ask VatC for a 
corresponding SturdyRef to Carol that's good until the requested expiration 
date.  A SturdyRef is a bearer off-line reference, so Alice can pass to Bob 
in an on-line message either a live reference or a SturdyRef designating 
Carol.  When Bob wants to invoke Carol, in he hold a SturdyRef, he first 
obtains a live reference from his SturdyReference, and then invokes on it.

Similarly, given a live reference to Carol, we can enable Alice to ask VatC 
for a corresponding Authorization certificate, signed by VatC, authorizing 
VatA to invoke Carol.  Alice, being within VatA, may later use this 
certificate to obtain a live reference to Carol, which she can then invoke on 
directly.  If Alice passes to Bob a derived certificate, signed by VatA 
authorizing VatB to access Carol, and including the previous certificate, 
then Bob may likewise use this certificate chain to obtain from VatC a live 
reference to Carol, which he can then invoke.

The combination of the two hash chaining proposals together look surprising 
natural.  The three numbers correspond to a three level hierarchy of 
authority to a capability:

1) arcHash(swissNumber) provides the authority to be the object, and 
  therefore receive invocations.
2) swissNumber corresponds provides the authority to invoke the object.
3) hash(swissNumber) uniquely and unambiguously designates an invokable 
  object, but does not provide the authority to invoke it.  Curiously, it does 
  provide the ability to compare two of these for equality.

It seems fine that each authority implies the ones after it, but not the 
ones before it.


                       Why we need off-line Messages, 
                             not just off-line Arguments


More later...

Second message

Mark S. Miller wrote Wed, 18 Oct 2000 14:23:17 -0700 in [1]:

                                    Message vs Invocation:
                                  A Terminology Correction.  


In the previous note, when I referred to "Message" I usually should have 
said "Invocation".  An invocation is a pair of a Message and a reference to 
the object that will receive the Message -- the Recipient.  In the 
Granovetter diagram, the fat arrow is a Message containing a reference to 
Carol as an argument.  The fat Message arrow combined with the thin reference 
arrow on which it rides -- the reference to Bob -- together constitute an 
Invocation.  With these definitions, it is clear that an authorization 
certificate represents an Invocation Argument rather than a Message 
Argument, since it authorizes only the Recipient.

The canonical example is a certificate from Alice authorizing Bob to invoke 
Carol.  If it were a Message Argument, then it would authorize whoever the 
Message were sent to, without that having been determined yet.



           Why we need off-line Invocations, not just off-line Arguments:
                     Another Lesson from the Confused Deputy



The punch line we all know from the Confused Deputy paper is "Don't separate 
designation from authority."  But this paper has enough punch lines to last 
a conventional lifetime.  Here's another.

Let's define authorization as the granting of authority.  One may conclude 
from the same tale that, even if designation and authority are kept 
together, "one must not separate authorization from invocation".  Why?  In a 
normal message-based capability system, the deputy only receives new 
authority as arguments of messages he receives asking him to do something.  
Each new authority has a separate position in the request, which represents 
its intended role in this request.  Only this context information gives the 
Deputy enough information to know what to do and what NOT to do with the new 
authority he's just been granted.

When authorization is communicated without such context, it's like receiving 
a key in the mail with no hint about what to do with it.  Or it's like an 
object system in which objects respond to the message

    hereIsSomethingYouMayFindUseful(arg)

After an object receives this message, she can invoke arg if she chooses, 
but why would she ever choose to do so?  Were the separation of 
authorization from invocation truly this silly, no one would have thought to 
separate them.  Instead, no one seems to question separating them.  Why?  I 
can think of two reasons, both derived from the ACL paradigm:

1) Ambient Authority.  The following chain of reasoning seems very 
plausible, especially if it's not articulated or examined closely:  If 
object A attempts to perform action X, and object A has enough authority to 
perform action X, then object A's attempt to perform action X should be be 
permitted.  The implicit assumption is that, if A attempts X, then A must 
want to perform X.  If it wants to and it's allow to, clearly it should be 
permitted to.  In such a system, a hereIsSomethingYouMayFindUseful() message 
could simply add arg to the object's ambient authority.

The flaw is the assumption that it wants its attempt to succeed.  A deputy 
only brings to bear on an action those authorities that should be applied to 
the action, because it wishes the action to fail if these authorities are 
inadequate -- even if the deputy itself has further authority.  How does a 
deputy determine which authorities to apply to an action?  In a capability 
system, only according to how the deputy came to hold these authorities -- 
by initial endowment and by receiving them as invocation arguments.

2) Labelling.  In SPKI, an authorization certificate not only authorizes, it 
names the resources that it authorizes access to.  It's like receiving a key 
in the mail that's labelled with the name of the thing it opens.  This 
presumes a namespace that's meaningful among the various parties, 
necessitating that we solve a harder problem before we can solve the easier 
problem.  Our invocation perspective is much like the labelling perspective: 
the message carries a message name (in E, the verb) used by the receiver to 
understand why he's receiving the arguments.  However, the verb labels the 
reason for interacting, not the resource being authorized.  The latter needs 
no name -- the capability is all the designation we need, and all the 
designation we can trust.

Of course, once Alice is invoking Bob rather than just authorizing Bob, now 
Bob, like Carol, is something to be invoked.  Just as Alice or Bob must be 
authorized in order to invoke Carol, so must Alice be authorized to invoke 
Bob.  If invoking is the only means of authorizing, then Alice must be 
authorized to invoke Bob in order for Alice to be able to authorize Bob.  In 
situations where this is enforceable, this both provides the reference arrow 
missing from http://www.erights.org/elib/capability/ode/images/spki.gif and 
removes the asymmetry between Subject and Resource.  Both would simply be 
objects, and shown as circles.  The full Granovetter diagram would be restored.


                          The Parts of an Invocation in E



So let's examine and give names to all the parts of an inter-vat Invocation 
in E.  Inter-vat Invocations in E may only be asynchronous, so we examine 
only the eventual ("<-") send expression:

       recipient <- verb(args...)

which acts like two different expressions depending on context:

a)    define result := recipient <- verb(args...)
b)    recipient <- verb(args...); null

Both of these asks the recipient to eventually perform the verb-named action 
using the provided arguments.  The request is queued on the vat of the 
recipient to be performed to completion when that vat is done with all prior 
requests.  

#a is the general case: When the send expression occurs in a static context 
where its value is needed (evaluated for value), the send expression 
immediately returns a promise for the outcome of performing the request.  
This is a tail of a reference arrow whose head is encapsulated in the 
Message.  (This head serves a role much like a lambda continuation, expect 
that it normally provides only data-flow, not control-flow.)  We call this 
arrowhead the Resolver.

#b is an important optimization: When the send expression occurs in a static 
context where the value is not needed (evaluated for effect only), then we 
can avoid creating the promise for the return result.  In both cases, these 
messages are one-way in a control flow sense.  #b is also one-way in a 
data-flow sense.

So, putting it all together, an E on-line Invocation consists of

Invocation
    Recipient (arrowtail)
    Message
        Verb (usually a String.  Always passed by copy.)
        Args (List of arrowtails conceptually, but may use any passing mode)
        Resolver (optional.  arrowhead for reporting outcome)

For off-line invocation certificates, let's tentatively make four semantic
changes.

1) Let's drop the optional Resolver.  It's hard to see any motivation for 
message pipelining in the off-line case.  In the absence of pipelining, most 
of the effects of the encapsulated Resolver can instead be provided with an 
explicit Resolver argument.  This decision does make it awkward to interface 
between the on-line and off-line worlds, so we may revisit it later.

2) Drop the requirement of order-preserving fail-stop at-most-once message 
delivery.  An on-line protocol can provide such guarantees cheaply.  For an 
off-line protocol, the expense would be too great to put at the foundations. 
Instead, we leave it up to the objects interacting via off-line invocations 
to deal with the problems resulting from the absence of these guarantees.  
I'm quite queasy with this, but it corresponds to the burden placed on the 
programmer by any of the other certificate systems.  Of course, this make it 
yet more awkward to interface the off-line and on-line worlds.

3) Do not provide built-in secrecy.  As with the other PKIs, invocation 
certificates are signed but not encrypted.  If their users wish to 
separately encrypt them, fine.

4) Provide built-in non-repudiation and some measure of auditability, at the 
price of a further loss of privacy.  Indeed, I believe this to be *the* 
tradeoff that should determine whether to use a certificate system or a 
bearer system.  Clearly, both have their place.


                Proposed Contents of an E Invocation Certificate


Since we've already got a notation for describing E invocations -- E -- I'll 
use it in the certificate proposal below.  A more politically acceptable 
proposal may use the XML representation of Kernel-E parse trees 
http://www.erights.org/elang/kernel/index.html , since this would be less 
readable and more verbose.  If you wish, consider all the E notation in what 
follows to be syntactic sugar for such XML.

As with any lambda language, E expressions are evaluated within a lexical 
scope.  *.emaker files are evaluated in the E "universal scope" -- a 
immutable scope containing only transitively immutable objects that provide 
no authority -- such as the binding of "true" to the appropriate boolean.  
The expression in our invocation certificate can be evaluated (for effect 
only) within this scope, but we needs more.  The authorization certificates 
provide further capabilities, but only in this context.  We need a form of 
expression available within this context that wraps the authorization 
certificate data and effectively evaluates to the corresponding object 
reference.  

Let's use E's syntactic sugar for URI expressions, and introduce a binding 
for "auth__uriGetter".  The expression <auth:...>, with an authorization 
certificate in place of the "...", evaluates to a capability to the 
authorized object.  Ignoring for a moment the issue of whether it evaluates 
to an on-line or an off-line reference, our standard example would now look 
like:

   def bob := <auth:...Alice's authorization (from somewhere) to invoke Bob...>
   def carol := <auth:...Bob's authorization from Alice to invoke Carol...>
   bob <- foo(carol)

The first authorization would be signed by whoever enabled Alice to invoke Bob.

The second authorization would be signed by Alice, and would include Alice's 
authorization to invoke Carol.

The expression as a whole would be signed by Alice.


                           An Aside: Enabling Stronger Auditing


Should Alice really sign the authorization for Bob to invoke Carol, given 
that she's signing the message as a whole?  Interestingly, we get much 
stronger auditability if the answer is no.  If the answer is yes, then this 
authorization by itself is what Bob would present when invoking Carol, or 
when authorizing someone else to invoke Carol.  If the answer is no, then 
only this invocation as a whole demonstrates Bob's authorization to Carol.

Likewise, one level back on the chain, Alice's inclusion of the 
demonstration that she is authorized to invoke Carol (necessary for her 
authorization of Bob to be valid) would not be an authorization certificate, 
but rather the entire invocation certificate showing why she came to have 
that authority.  

If the argument authorizations aren't signed, and therefore don't need to be 
standalone, then they also don't need to list the "Subject", since this must 
always be the Recipient (Bob).  They all must also have the same Issuer 
(Alice), so we could list this once rather than per-argument.  All that's 
left or SPKI's 5-tuple is the Carol designation: <vatID(C), 
hash(swissNumber(Carol))>.  The authorization data would consist of this 
plus a chain of earlier Invocation certificates.

The authorization chains are now more like stack tracebacks, whose utility 
for debugging is well known.  Auditing and debugging may be more similar 
than we think.  However, the space overhead may be unreasonable for many uses.



Next Message:  I finally get to the "Active" stuff


Third message

Mark S. Miller wrote Tue, 24 Oct 2000 13:52:34 -0700 in [2]:

Sorry for teasing, but I realized that there was one other major chunk to 
explain before I could tie this thread together into a proposal for Off-Line 
Active Invocation Certificates (as inspired by Nikita's Active 
(Authorization) Certificates).  

The previous message (#2b) proposes Off-Line Invocation Certificates as an 
off-line derivative of on-line invocation. The addition of "Active" means 
the certificate additionally carries mobile code, as a more flexible 
replacement of the SPKI subsetting language.  Following our methodology, 
support for off-line mobile code should be derived from support for on-line 
mobile code.  While E was always designed for mobile code, we're not there 
yet, so the ideas weren't in concrete form.

This has now been repaired.  
http://www.erights.org/javadoc/org/erights/e/elang/evm/Evaluator.html is my 
proposal for a remote evaluation service, and syntactic sugar to support it.
Fire away.  If this proposal survives the initial volley, the off-line 
proposal will be built on it.

Fourth message

Mark S. Miller wrote Sat, 11 Nov 2000 08:44:55 -0800 in [3]:

Here is the long delayed next step in this proposal for Capability-based 
Active Invocation Certificates.  For an indefinitely postponed hypothetical 
piece of engineering, this thread is taking up a distressing amount of 
paper.  *If* off-line certificates are indeed useful in an increasingly 
on-line world (a questionable assumption), then I believe this thread will 
prove important.  Thanks for your indulgence.

(Alan and Bill, you guys are the most qualified to address this 
questionable assumption, as you've both been heavily involved in engineering 
efforts with similar goals on both sides of this coin.  (E-Speak 2.2 vs 
E-Speak 3.0/SPKI; Indra & Pluribus vs SPKI).  Is there a compelling 
need for off-line certificates?  Do they address a real problem?)

Previous messages in this thread have already established a strong 
correspondence between Invocation Certificates and E/Pluribus messages -- 
they are simply the off-line and on-line embodiments, respectively, of a 
Granovetter/capability message.  The semantic differences are only due to 
the differences between our notions off-line and on-line (significantly 
clarified in answer to Bill's question), plus that we only define off-line 
certificates to be the equivalent of sendOnly messages -- messages without a 
continuation 
http://www.erights.org/elib/concurrency/msg-passing.html#sendOnly .

The remaining element, and the element that motivated this whole thread in 
the first place, is the not-yet-explained "Active" feature of our 
certificate proposal.  Rather than explain Active certificates directly, 
this message will show the on-line equivalent of this feature: 
Deputizing Remote Vats with Mobile Code.  That's why we introduced the 
Evaluator earlier.

Let's construct the standard deputy scenario 
http://www.erights.org/elib/capability/deputy.html .  Let's say that Alice 
had a prior reference to Mallet and the power, P, and that Alice constructs 
Bob in order to provide Mallet with reduced authority over the power.  For 
example, let's say P is a mutable slot with getValue() and 
setValue(newValue) messages, and that Alice wishes to provide Mallet only 
the authority to see the current value, but not to set it.  As a contrived 
embellishment whose purpose will be clear later, let's say Alice constructs 
Bob to accept but ignore the setValue message.  Alice might define Bob thus:

    define BobMaker new(P) :any {
        define Bob {
            to getValue :any { P getValue }
            to setValue(newValue) {}
        }
    }

Alice would then give Mallet

    Mallet foo(BobMaker new(P))

However, now let's say Alice, P, and Mallet are all in three separate vats:
VatA, VatP, and VatM.  The code would then read

    define BobMaker new(P) :any {
        define Bob {
            # returns a promise for the value
            to getValue :any { P <- getValue }
            to setValue(newValue) {}
        }
    }

    Mallet <- foo(BobMaker new(P))

>From a security point of view, this is ideal.  Bob is Alice's deputy, and 
Bob runs on VatA, and therefore Alice's TCB.  Alice necessarily 
"trusts" her own TCB, not because she necessarily has higher confidence in 
its trustworthiness, but because she can't help but be fully vulnerable to 
it, so she may as well stop worrying.  Since she already has this 
vulnerability, she does not acquire any new vulnerability by trusting the 
same TCB to run Bob.

Unfortunately, depending on the particulars of the situation, this choice 
may not be ideal from a distributed systems point of view.  Any time Mallet 
wishes to exercise his reduced power, the request has to go through Bob 
(necessary) and therefore through VatA (unfortunate).  Besides the obvious 
performance cost, Alice may be expecting VatA to go off-line soon, or become 
otherwise inaccessible to VatM and VatP.  Let's say Alice also expects VatM 
and VatP to remain accessible to each other.  If Alice were introducing 
Mallet to all of P, our standard Granovetter introduction protocol would put 
VatM and VatP in direct contact, and Alice could drop out of the picture 
without disrupting their further communication.  How can Alice introduce 
Mallet to the "some of P" represented by Bob, and still be able to drop out?

I'm sure you can all see what's coming: there are only two other Vats in the 
picture.  Alice's only two sensible choices are to instantiate Bob on VatM 
or on VatP.  Both subject Alice to greater security risk that Bob on VatA.

Bob on VatM:

If Alice trusts VatM more than Mallet, this can be a sensible choice 
(depending on the nature of trust in VatM).  Alice cannot rationally trust 
VatM less than Mallet.  If she trusts them the same, then this is a bad 
choice, since VatM is being given direct access to P.

Bob on VatP:

P is necessarily vulnerable to VatP, so any dishonest execution of Bob 
that's equivalent to corruption of P creates no loss of security.  What 
greater damage can a corrupt VatP cause?  Alice's intended Bob behavior 
prevents Mallet from sending capabilities to P as argument of setValue 
message.  Is this a form of distributed capability confinement 
http://www.erights.org/elib/capability/dist-confine.html ?  With Bob on 
VatA, it might seem that Mallet and P cannot arrange for Mallet to send 
capabilities to P.  Unfortunately, the getValue message, as currently 
defined, allows P to "send" (reveal, as the outcome of a prior send) an 
arbitrary capability, which is enough to work around the restriction.  
However, Bob might be more constraining.  A Bob that only allowed integers 
to be gotten from P would prevent Mallet from sending a capability to P.

If we run Bob on VatP and VatP is corrupt (and in cahoots with Mallet and 
P), then it can give to P capabilities from Mallet that Alice coded Bob to 
prevent.  But wait a second, if VatP is corrupt, can't it separately 
establish a channel between Mallet and P?  Only with VatM's cooperation.  So 
we're back to relying on trust in VatM.

When the location question comes up, I suspect capability confinement will 
rarely be a concern (though it's good to check!).  Therefore, when 
non-security issues argue against putting Bob on VatA, security issues will 
typically argue for putting it on VatP.  Note that the non-security issues 
are almost perfectly indifferent between VatP and VatM.

Ok, so how does Alice instantiate Bob on VatP, and give Mallet access to 
that Bob.  An economist turned programmer might say "Assume an Evaluator" 
http://www.erights.org/javadoc/org/erights/e/elang/evm/Evaluator.html .  
Specifically, an Evaluator on VatP (exported by VatP's TCB), let's say 
called evalP in Alice's scope.  Alice only needs to change her code to:

    meta <- eval(evalP, define BobMaker new(P) :any {
        define Bob {
            # returns a promise for the value
            to getValue :any { P <- getValue }
            to setValue(newValue) {}
        }
    })

    Mallet <- foo(BobMaker <- new(P))

This asks the Evaluator on VatP to evaluate the expression defining 
"BobMaker".  It also defines "BobMaker" in this (Alice's) scope to be a 
promise for that remote BobMaker.  We then send a remote request on this 
BobMaker-promise to create a new Bob (BobMaker <- new(P)).  The value of 
this expression is a promise for Bob, which is then sent to Mallet.

(Just to show off message pipelining 
http://www.erights.org/elib/concurrency/pipeline.html , all three of these 
messages go out immediately, without VatA waiting to hear anything back.)

The analogy with the SPKI subsetting language should be clear: Bob expresses 
a subsetting of the authority of P.  Alice, who has authority P, is giving 
Mallet only that subset, but is handing over the interpretation of her 
subsetting intentions to VatP.  When Mallet goes to exercise his authority, 
the subsetting is enforced by VatP, hopefully according to Alice's 
instructions.

The main difference, due to Nikita, is that we're expressing the subsetting 
in a general purpose programming language.  This allows abstraction as well 
as subsetting-by-thinning.  For example, a covered call option is a deputy 
subsetting-by-abstraction the underlying instrument, such as stock.  One could 
never express this kind of subsetting in a data-language such as SPKI provides.

Complete concrete syntax

Zarutians notes:

following is in bnf like form:

invocation_cert := issuer recipient verb args signature
issuer := principal
recipient := SturdyArg | SturdyRef | initcert
verb := string
args := arg*
arg := SturdyArg | passByConstruction
signature := <crypto signature of the whole cert (issuer, recipient, verb and args)>
SturdyArg := subject [ invocation_cert ]
  cert is omitted if VatID of subject is the issuer of this invocation_cert
VatID := principal
principal := public-key | cryptohash(public-key)
swissNr := [swiss Number]
initcert := issuer subject granted initcert_signature  -- gives subject an license to use granted as recipiant in an invocation_cert
subject := VatId hash(swissNr) 
granted := hash(swissNr)  -- points to an object on issuers vat
initcert_signature := <crypto signature of the whole cert (issuer subject granted)>

Mark S. Miller: hmm... this only supports certs that invoke an object on the recipient vat directly. So if one wants to build an attenuator via the cert on must direct the invocation at an object that makes the object pointed to by an SturdyArg available to the unserialized representation of the attenuator. (Which itself is an passByConstruction arg in that invocation.

How then to make SturdyArg possible exit in serialized object graph carried in passByConstruction arg in the cert?

Zarutian: One kludge is to have an publicly aviable deserializer on the subject vat that gets invoked by the capcert. The deserialier would be of the form: deserialize(passByConstructionDepiction, exit1, exit2, ..., exitn)

But above is rather nasty kludge. The only otherway to solve this is to make capcert aviable to the deserialization surgeon or, heck, the E evaluator (as an uriGetter).

I havent gotten to the point of how to bridge the online and offline world, that is make it possible for vatConnections to invoke capcerts (which could be solved by an capcert uriGetter as above) and vice versa (other than inducing the subject vat to issue an initcert).

Zarutian later: The proplem in above paragraph can be solved by making hash(swissNr) in the subject form optional. In those cases the VatId much match the one of the vatp connection and refers to the invoking object.

The kludge that markm pointed out can be solved by adding "universal_builder" to the reciepiant form.

Zarutian: I am trying to get at the proplem from an different direction:

active_cert := issuer script signiture
issuer := prinicpal
siginiture := publickey_sign(concat(issuer script), issuer.privatekey)
  
script := string containing code in E

def principal_seal(thing :any, recipiant :principal) :sealed_box {}
def principal_unseal(box :sealed_box) :any {}
def rootbase_get(swissHash :string) :any {}

def do_active_cert(cert :String) :any {
  // 1. check if the signiture is valid
  // 2. make a new scope that has
  //     do_active_cert (this procedure),
  //     principal_seal,
  //     principal_unseal that only unseals sealed_boxes ment for the cert issuer
  //     all the other stuff a safeScope has
  // 3. run the script in that scope
  // 4. return any results
}

one issuer is special, the one who is also the VatID.
active_certs issued by that issuer can invoke (call or eventual send) rootbase_get().
why? so an tree of active_certs can get the source authority.

Second attempt

Zarutian my second attempt at if from that direction:

# E syntax 0.9
pragma.syntax("0.9")


def makeBrandPair := <elib:sealing.makeBrand>
def makePrinicipalsSealerRegister () :any {
  # make an FlexMap, does there exists any better way to do so?
  var register := [].asMap().diverge()
  def shared_internal(principal :any, i :int(0..1)) :any {
    if (not(register.maps(principal))) {
      register.put(principal, makeBrandPair(principal), true)
    }
    return register.get(principal).get(i)
  }
  def getSealer(principal)   { return shared_internal(principal, 0) }
  def getUnsealer(principal) { return shared_internal(principal, 1) }
  return [getSealer, getUnsealer]
}
def [getSealer, getUnsealer] := makePrincipalsSealerRegister()
def swissHash__uriGetter {
  # to be implemented
  # used by active certs issued by this vats public key.
  to get(str :String) :any {
    throw("Not yet implemented")
  }
}
def vatId := <<get the public key of this vat>>
def ActiveCapCertPrincipal {
  to coerce(specimen, optEjector) :near {
    # for now nothing passes this guard
    throw.eject(optEjector, "guard not yet implimented") 
  }
}
def ActiveCapCert__uriGetter
def ActiveCapCertMaker {
  to makeFrom(cert :String) :any {
    def issuer := null   # will be filled in by th cert parsing code
    def code :EExpr := e`$code` # ditto
    # check here if signed by issuer as it is pretty expensive.
    def unsealer(box :any) :any {
      return getUnsealer(issuer).unseal(box)
    }
    def ActiveCapCert {
      to run(parameters :any) :any {
        def env := safeScope
        env with= ("parameters", parameters)
        env with= ("my_unsealer", unsealer)
        env with= ("get_sealerFor", getSealer)
        env with= ("ActiveCapCert__uriGetter", ActiveCapCert__uriGetter)
        if (issuer == vatId) {
          env with= ("swissHash__uriGetter", swissHash__uriGetter)
        }
        return code.eval(env)
      }  
      to getSigner() :ActiveCapCertPrincipal {
        return issuer
      }
      to getCode() :EExpr {
        return code
      }
      to __optUncall() :Portrayal {
        return [ActiveCapCert__uriGetter, "get", [cert]]
      }
    }
    return ActiveCapCert
  }
  to makeCert(code :EExpr) :String {
    # prepend this vats pubkey to the code
    # and sign it
  } 
}
bind ActiveCapCert__uriGetter {
  to get(str :String) :any { return ActiveCapCertMaker(str) }
}

Possible usages:

1. On a CapTP connection (the messages from the sending vat are treated like they were signed by that vat).

2. A chain of simple authorization certs.

3. A tree of embedded such chains.

4. A symbolon style of authorizations. (Alice gets an authroization/active cert from Bob that can only be used if Carol gives Alice an authroization/active cert that gives the former cert authority which is given (and possibly attenuated) onward to Alice)

5. In a PostalRef scenario. (PostalRefs are offline like SturdyRefs but you can send it eventual sends which will then be written out as authroization/active cert(s))

6. In an authenticated save style (Like in Blizzards Diablo I Battle.net only that any tampering with the save file invalidates it) ( perhaps usefull in scenarious where elib.serial is used).

Relationship to using SAML authorization assertions

We did similar work using SAML authorization assertions as capabilities. The only major difference that I see is that the active invocation certificates include trees of authorization assertion assertions. Our work has been adopted by the State of California Health and Human Services Privacy Board as the means to authorize consulting physicians. Go to http://ca.gov and search for ZBAC. -- Alan Karp

Personal tools
more tools