4.3 Interactions
4.3.4 Runtime Authorization
Jif programs can increase their authority at runtime with actsfor statements, as de-scribed in Chapter 2. TEP implements actsfor statements by translating them into calls to a TepRuntime object. The TepRuntime class encapsulates the code required for checking authorization between two principals and contains data required by other privileged TEP classes. Its API is given in Table 4.3.
Each application running on TEP has a reference to its own instance of the Tep-Runtimeclass. Each instance contains a reference to TEP’s public and private keys, a reference to the Environment Checker, a connection to the Environment Prover. This connection is used to issue requests for authorization proofs at runtime. TepRuntime objects share a cache so they can take advantage of common authorization results.
Jif actsfor statements are translated into calls to the actsfor method on the application’sTepRuntimeobject. The block following anactsforstatement is executed
public class TepRuntime {
// public methods accessible by Jif classes public static TepRuntime get();
public boolean actsFor(JifPrincipal actor, JifPrincipal actee);
// package-private methods accessible only by TEP’s classes static void set(TepRuntime runtime);
PublicKey getPublicKey();
PrivateKey getPrivateKey();
boolean sameAs(PublicKey key, JifPrincipal principal);
}
Table 4.3: TEP’s Runtime API
if the check succeeds, otherwise, the optional else block is executed. An example of this translation is given in Figure 4-4.
TepRuntime’s static get routine returns the instance of the runtime associated with the current application thread. If get is called by a thread that is not running on TEP, it throws the unchecked exception JifFatalError and forces the calling Jif application to abort. JifFatalError is translated from Jif’s only unchecked exception, FatalError.
The actsFor routine returnstrue if the “actor” (the first principal) is authorized by the “actee” (the second principal). This routine is implemented by calling the appropriate actsfor routine on the Environment Checker (Section 4.1.4).
The JifPrincipal class is an abstract superclass of the two classes JifName and JifKey. These classes represent principal names (strings) and runtime principals (public keys), respectively. These classes are invisible to the Jif programmer, who uses principal names and variables directly.
The remaining TepRuntime routines are privileged and only accessible by TEP’s classes. The set routine allows TEP to set the TepRuntime object for the current application thread. The getPublicKey and getPrivateKey routines return TEP’s public and private keys respectively, for use in establishing secure channels.
The sameAs routine returns true if the given key corresponds to the given Jif-Principal. If the principal is a JifName, the routine checks whether the name is bound to the given key using the Environment Checker’s hasName routine. If the principal is a JifKey, this routine simply compares the keys directly. The sameAs routine is used in channel creation to determine if the remote principal is one of the readers in the channel label, as described in the next section.
4.3.5 Channels
Jif is designed to allow multiple parties to share data in computation, so Jif programs must be able to exchange data with external principals. This functionality is provided
// Given Bob’s authority, actsfor(Bob, Alice) {
// use Alice’s authority } else {
throw new AccessDenied("Bob must act for Alice");
}
// translates to...
if (TepRuntime.get().actsFor(new JifName("Bob"), new JifName("Alice"))) { // use Alice’s authority
} else {
throw new AccessDenied("Bob must act for Alice");
}
Figure 4-4: Translating Jif’s actsfor statement
by the TepChannel class.
The TepChannel class implements a bi-directional, secure network channel that supports different privacy labels on the input and output streams. Although some channels are implicitly uni-directional, TEP requires that channels be bi-directional to support the secure session protocol presented in Section 4.3.2. We expect that input and output devices such as keyboards, mice, displays, and printers will communicate with applications on TEP through these secure network connections.
Jif Channel API
The Jif API for TepChannel is given in Table 4.4. The TepChannel class is parame-terized over two labels, IN and OUT. Data read from the channel’s input stream may only be assigned to variables whose labels are equal to or more restrictive than IN.
This label protects the privacy of data written by the remote principal to the pro-gram. Data written to the channel’s output stream may only come from variables whose label is equal to or less restrictive than OUT. This label protects the privacy of data written by the program to the remote principal.
The TepChannel constructor requires that the given host and port have the label {}, because the host and port must be exposed to the untrusted network. This means that any code that creates a channel must remove all privacy policies from the host and port using declassification. Channel creation itself is a publically-visible event and can leak data through an implicit flow (Section 2.1.5). To prevent this, we could require that the begin label of the constructor be {}. This would ensure that no information is leaked when the channel is created, but it may be too restrictive for
class TepChannel[label IN, label OUT] {
TepChannel[IN, OUT](String{} host, int{} port)
throws (AccessControlException, // illegal reader GeneralSecurityException, // cryptography error IOException); // input/output error jif.io.InputStream[IN] getInputStream();
jif.io.OutputStream[OUT] getOutputStream();
}
Table 4.4: Jif’s Channel API
some programs.
After creating a connection, theTepChannelconstructor runs the channel creation protocol described in the next section. The constructor throws an AccessControl-Exception if the remote principal does not belong to the reader set of the label OUT.
This protects programs from revealing classified data to unauthorized principals. The constructor throws a GeneralSecurityException if there is an error with the secure session protocol and throws anIOException if there is an error communicating with the network. The constructor may also throw an unchecked JifFatalError if it cannotgetan instance of TepRuntime. The parentheses around the checked exception list are required by Jif to disambiguate its syntax.
The getInputStream and getOutputStream routines provide access to the input and output streams of the channel. We chose to build channels around the standard Java InputStream and OutputStream classes so that programmers can use familiar library classes for stream manipulation and object serialization. Jif programmers will need to use Jif versions of the stream classes that restrict the labels of data that can be read from or written to a stream. In this thesis, we assume these classes are available in the jif.io package.
TEP Channel API
When the Jif API is translated into Java for TEP, the IN and OUT labels must be preserved for use at runtime. Table 4.5 gives theTepChannel API in Java. The con-structor accepts theINandOUT labels as two additional arguments of typeJifLabel.
The JifLabel class is a runtime representation of a Jif label. Each JifLabel contains a set of objects of typeJifPolicy. EachJifPolicy has an owner and a set of readers of type JifPrincipal. The reader set for aJifLabel is calculated as the intersection of the reader sets for each JifPolicy. JifLabel also has a relabelsTo method that returns true if the label is less restrictive than its argument.
Channel Creation Protocol
Figure 4-5 gives a graphical representation of the channel creation protocol. The first
class TepChannel {
TepChannel(JifLabel in, JifLabel out, String host, int port) throws AccessControlException,
GeneralSecurityException, IOException;
InputStream getInputStream();
OutputStream getOutputStream();
}
Table 4.5: TEP’s Channel API
TEP then checks whether the remote principal is one of the readers in the channel’s OUT label.
This check implements the semantics of a trusted reader, since the reader need not enforce the policies on data sent over the channel. For example, data labelled {Bob: Alice} can be written to a channel connected to Alice, but Alice can then disseminate the data arbitrarily. Bob must trust that Alice will honor his policy. We discuss alternate output channel semantics in Section 6.2.1.
For each reader in the channel’s OUT label, TEP calls TepRuntime’s sameAs rou-tine on the peer’s public key, KP, and the reader. The sameAs routine uses the Environment Checker’s hasName routine to determine if the reader’s name is bound to KP. If the peer is not an allowed reader, the protocol aborts and throws an AccessControlException.
If the reader check succeeds, TEP sends the channel’s IN label and OUT label to the remote principal. The IN label is provided to allow the peer to check the privacy policies on data TEP reads from the channel. The OUT label is provided to allow the peer to preserve the privacy policies on data it reads from the channel.
If the remote principal does not agree that the IN label adequately protects its privacy, it closes the channel and TEP aborts the protocol with an IOException. If the remote principal approves theIN label, both parties may start using the channel.
Protecting Privacy and Integrity
The channel protects privacy by encrypting and decrypting data using the RC4 stream cipher. The channel protects integrity by calculating MACs for data sent over the streams. Since MACs must be calculated for individual messages, rather than stream, we automatically break the stream data into blocks and insert a MAC for each block.
On output, we create a new block whenever the stream is flushed or the stream buffer reaches a maximum size. Each block is prefixed by its length, appended with its MAC, and encrypted with the output session key. On input, data is decrypted with the session input key, read into blocks, and checked against the accompanying MACs. If a MAC check fails, anIOException is thrown. These mechanisms protect
classified data
TEP (Kt)
for each reader R in OUT label,
Peer (Kp) Checker
hasName(Kp, R)
return true iff proof checks Prover
proof sequence or null true or false
hasName(Kp, R)
if true, break from loop if all false, abort
if peer disconnects, abort channel IN and OUT label
authenticate and encrypt session
Figure 4-5: Channel Creation Protocol
both the privacy and the integrity of data sent over channels while providing the programmer with the standard Java stream abstractions.