The SDSC Encryption / Authentication (SEA) System
Wayne Schroeder
December, 1997
This document is available at http://www.sdsc.edu/~schroede/sea.html .
Introduction
The SDSC Encryption / Authentication (SEA) System was developed as
part of the DOCT project to
provide authentication and encryption capabilities between two running
processes communicating via TCP/IP sockets. In particular, it is
being used as part of the SDSC Storage Resource Broker (SRB) client
and server in support of the DOCT storage, replication, and
communication infrastructure and in other SRB applications.
Features
The SEA system has many features that, in combination, are unavailable
in other authentication / encryption systems:
-
Provides secure user authentication capabilities
for distributed processes.
- Provides encrypted communications capabilities for distributed processes.
Encryption can be be utilized as either independent from authentication or in
conjunction with it.
-
Provides authentication for arbitrary processes (names). Authenticated
users can create authentication keys for use by processes.
- Simple API. Integration into existing distributed
applications is straightforward.
-
Suitable for a batch queuing environment on trusted hosts.
Passwords can be provided beforehand (eliminating the security risk
of placing passwords
in batch scripts), and tickets will not expire over a long period (days or
or even weeks).
-
Multiple trust models for the initial registration of users:
- Password
- Trusted Host
- Self-introduction
-
A simple user interface for registration and key management.
-
Suitable for distributed, independent, computer systems (separate
administrative domains).
-
Default configuration is moderately strong and fairly quick (512-bit
RSA keys, 14-round RC5 with added Cipher Block Chaining). Can be configured
with stronger encryption (longer RSA keys and/or more RC5 rounds).
-
Available on a wide variety of Unix systems:
the Cray C90 and T3E, SunOS, Solaris, IRIX, DEC OSF1, AIX, and
the Sun/Cray CS6400 system. Porting to additional architectures
would be relatively straightforward.
Why Another Authentication System Was Needed
There are many secure authentication systems in use today. Kerberos,
the Kerberos-related DCE Security system, and SSL with X.509
Certificates are major systems that are in many ways competing with
each other. There are also related subsystems, such as SSH and PGP,
that augment system security using similar encryption building blocks.
GSSAPI (Generic Security Service API) is an attempt to simplify the
application of security services by providing a common interface for
various underlying security systems. But one still needs to run one
of the services, Kerberos or DCE Security, for example, and the GSSAPI
has additional complexity to allow it to function in either
environment. Thus GSSAPI is a helpful work-around, but not a direct
solution to the problem.
One reason for developing our own is precisely this profusion of
solutions. If one system were preeminent, then its use would be
preferable, even with substantial limitations. The goal in this case
would be to find work-arounds to meet our requirements. As it is,
though, the industry is struggling with this field, and the
sophisticated and involved solutions that exist require substantial
commitment from both supporting and installing/utilizing
organizations. The ideal of the "universal" Single Sign-On capability
has not yet arrived for the vast majority of computer users and
appears to be particularly remote to organizations, such as ourselves,
with a significantly heterogeneous computing environment.
Kerberos is gaining strength, particularly with the recent release of
Kerberos 5 release 1.0, but still lacks features, particularly for an
HPC environment. Similarly, SSL is gaining in usage but lacks HPC
features and would require a major effort for porting to Cray
architecture.
The high-level reasons for developing SEA include:
- There is no single dominant secure authentication solution.
- Existing solutions are lacking is some specific capabilities needed
for DOCT/HPC, including:
- Support for batch processing and semi-permanent certificates.
- Support for Cray supercomputers (in some cases).
- A flexible set of "trust models" for initial registration.
The lack of Cray and batch support are common problems in High
Performance Computing since 1) HPC (essentially by definition) is a
small niche, 2) the Cray vector architecture has unique features that
make it difficult and expensive to port software to,*
and 3) the batch
environment, very important for long-running HPC applications, has
long ago been replaced with interactive and real-time paradigms for
most systems. These reasons, in combination, often make leading-edge
mainstream solutions unavailable to the HPC environment.
*The lack of a 32-bit addressable unit is often a significant
problem when porting systems-related software to the Cray PVP architecture.
In HPC systems environments, we often need to port software to HPC
platforms, develop software as subset solutions or gateways, and/or
develop unique interim solutions ourselves. Choices are difficult,
particularly as we try to guess the future of the very dynamic computing
industry. Often our software is only short-lived, but it serves the
purposes of meeting our immediate and specific needs, being highly
tailorable, illuminating requirements, and focusing our vision for
the future.
The SEA system was developed to provide simple, easily utilized
solutions for immediate uses. By utilizing standards like RSA and
RC5, we were able to build an effective solution with the exact
features we need. For use within a DOCT meta-computing
infrastructure, the easy additions of strongly encrypted inter-process
communications and long-term process and user secure authentication
are particularly valuable. For DOCT, SEA became a supplemental
research and analysis project, is being utilized as part of the
infrastructure, and provides an alternative solution for various
components in possible future security development. Eventually, an
industry standard may emerge which may be preferable to use, but for
now SEA addresses a host of specific requirements in an effective
manner.
See the SEA software design document and the
Authentication Mechanisms paper (written
primarily by Markus Jakobsson) for additional discussions of the
shortcomings of existing security systems for the DOCT environment
and the reasoning behind various choices made.
Components
The SEA System is built upon RSAREF 2.0 and RC5. As is often done in
similar systems, RSA is used to exchange a random session key, which
is then used with a more efficient symmetric key algorithm, in this
case RC5. Other building blocks include an SDSC-developed random
number generator and middle-level routines.
RC5
Sample source code from "Applied Cryptography" by Bruce Schneier was
used as the basis for our RC5 implementation. To this we added two
important features: porting the software to the C90, and Cipher Block
Chaining.
Porting the RC5 code to the Cray C90 required a number of changes to
deal with longer word size. Since 32-bit integers are not available
on the C90, 32-bit masks were needed in many operations to return the
64-bit computed quantities to 32-bits as needed in the algorithm.
As acquired, the RC5 algorithm would encrypt any 8 byte block of
plain-text to the same cipher-text, regardless of its location in the
input stream, presenting a weakness that could be exploited. To
harden the implementation, a Cipher Block Chaining (CBC) algorithm was
implemented. In CBC, the cipher stream is mixed (typically XORed)
with the plain-text as it is encrypted, ensuring variation in the
cipher-text even with recurring plain-text patterns.
RSAREF 2.0
RSAREF 2.0 was downloaded from RSA Data Security Inc. This was ported
to the C90, which involved numerous changes in various modules to deal
with the 64-bit word size. This is the only known port of RSAREF 2.0
to the C90 and is also being used in SDSC's Legion C90/T90 porting
effort.
It was found that the MD5 implementation within RSAREF 2.0 conflicted
with that available in libnsl on Solaris systems, so names of the key
MD5 routines were changed to keep them separate.
Random number generation
Random numbers are needed for various purposes: a seed for RSA
Encryption, the RC5 session key, padding for seaWrite buffers (for
RC5, buffers must be a multiple of 8 bytes long, so libsea pads them),
and challenge values for authentication.
The implemented getRandomNoise() routine generates pseudo-random
numbers for use in libsea by generating an MD5 hash of a series of
buffers. The MD5 hash provides a chaos-producing effect; that is,
small variations in the input values produce radically differing MD5
output. Although not cryptographically analyzed, it is believed that
this provides sufficiently random values, particularly since the
algorithms being used are not widely known (i.e., obscurity creates a
slight degree of additional safety).
The input to the MD5 hash includes the output of an fstat call on
stdin, an fstat on stdout, a stat on "/",
a gettimeofday, and an
internal floating point number that is incremented on each call. For
calls made in rapid sequence, tv_usec and the counter will vary each
time. And for many calls, all five MD5 input buffers will vary
considerably.
Middle layer
Various middle-level routines were developed as the interface between
the API routines and the lower-level encryption routines. This
included various key management routines to read and write encrypted
and semi-encrypted public and private RSA keys. These, like the
encryption routines, were developed such that they would function
identically on all architectures, so that encrypted keys could be
accessed from each architecture.
Utilities/Daemons
Four programs were developed, themselves layered on the SEA library,
to handle the management of the RSA keys. They are: 1) a key
generation and registration utility, seaauth, 2) a key management
daemon for accepting and storing registered public keys, 3) a
'trusted agent', and 4) a separate key generation utility. These are
described in later sections.
The two functions, encryption and authentication, are provided by
separate APIs. An application can utilize either the encryption or
authentication functions, both, or neither.
SEA Encryption
Application client and servers first establish communication via a
TCP/IP socket. The following routines can then be called to establish
encryption:
- seaBeginEncryptionServer(fd)
- seaBeginEncryptionClient(fd)
The fd is a socket connecting a client and server. The client calls
seaBeginEncryptionClient, and the server calls
seaBeginEncryptionServer. The routines perform a handshake, using RSA
to exchange a random key for use with this session. Upon success,
each returns 0. If an error occurs, a message is printed to standard out,
and a negative value is returned.
The following two routines are called instead of write and read to
send and receive encrypted data on a socket:
- seaWrite(fd,buf,len)
- seaRead(fd,buf,len)
All arguments and return values are equivalent to read and write.
This includes the return value, which is the positive length for a
successful read or write, 0 when disconnected, and negative upon
error.
The application can establish encryption at any point in the session.
Both sides just need to know to call the seaBeginEncryption routine at
the same time. Once encryption is established, the application calls
seaRead and seaWrite just like read and write to exchange information
that is encrypted. If data does not need to be encrypted, the
application can use read and write instead of seaRead and seaWrite,
even after encryption is established on the socket. Multiple sockets
can be encrypted via multiple calls to
seaBeginEncryptionServer/Client.
RC5 encryption requires a buffer that is an integer multiple of 8
bytes in length. If the user passes a buffer to seaWrite that is not
a multiple of 8 bytes, the SEA routines will pad the buffer with
random data, saving and restoring the contents of the 0 to 7 bytes of
storage following the data. This means, however, that a call to such
as seaWrite(fd,"hi",2), will fail, since the storage area for constants
is not writable. Application programs must copy the data to a buffer
instead: char buf[20]; strcpy(buf,"Hi"); seaWrite(fd,buf,2);
Also, the buffer passed to seaRead and seaWrite must be aligned on a
4-byte boundary so that the encryption routines can perform the
integer arithmetic on 4-byte items. If this is not the case, a "bus
error" will occur. With some compilers for a character array, this
means that it needs to be defined to be a multiple of 4 bytes in
length (i.e., char buf[10000]; , not char[10002]).
Normally, authentication (described below) will be performed on
sockets that are being encrypted, but this is not necessary. The
authentication exchange uses RSA to securely identify users without
exchanging any plain-text passwords. However, first encrypting and
then authenticating is the preferred method, as it does provide a
little more security.
seaWrite and seaRead will transfer data without encryption if the
seaBeginEncryptionClient/Server routines have not been called. We may also add a
seaEndEncryption routine at some point.
The following is a brief description of the Encryption protocol:
The client and server processes first establish a communications
socket. Then the client calls seaBeginEncryptionClient(fd) (where fd
is the file descriptor for the socket), and the server calls
seaBeginEncryptionServer(fd).
- seaBeginEncryptionServer reads the public key file (or alternative,
see below) and sends this
data to the client.
- seaBeginEncryptionClient reads the message, randomly generates a
64 bit session key, encrypts it with the public key,
and sends it to the server.
- seaBeginEncryptionServer reads the message, reads the private key file,
and decrypts the data.
If an error occurs, an error message is first exchanged. This
provides information and also prevents one side from waiting
indefinitely for the next message in the sequence. Also with errors, a
message is displayed, and the function returns with a negative
value.
At this point, both sides have a secret random key for use in the rc5
encryption that has been exchanged securely.
The Server-side of this exchange needs access to a public/private RSA
key pair. There are three methods of providing these:
-
The location of these key pair files is defined in the sea.h file
at compile time (see sea.h comments for details). These keys can be
generated with the SEA genkey utility.
-
If these keys are not available, the SEA library recognizes this and will
perform encryption setup using a key-pair that is built into the source.
The SEA script mkinit.pl can be used to install a new pair of built-in
keys.
-
The third method for providing the RSA key pair is via a call to
seaMakeEncryptionKey(). This will generate a new pair of RSA keys,
hold them in memory, and set the SEA library to use them. It usually
takes 15 to 30 seconds to generate keys. If seaMakeEncryptionKey()
is called and succeeds, the generated keys will be used instead of the
file or built-in key pairs. This should be used in long-running
daemons as it provides very secure and changing RSA keys.
seaMakeEncryptionKey returns 0 on success, -1 on failure.
See the source, elib.c in particular, for additional information.
Encryption Performance
Any secure encryption algorithm will reduce communications performance
considerably. Instead of primarily just moving buffers (or, usually,
pointers) and orchestrating I/O, substantial logical and arithmetic
operations must be performed on each data item.
The RC5 implementation in SEA, however, is quite efficient and is
comparable to SSH's encryption mechanisms (using rough timing
estimates, using the default settings of 512-bit RSA keys 14 RC5
rounds and SSH's IDEA algorithm).
In cases in which security constraints are less severe, the SEA system
can be configured with milder encryption. If the SEA library is
configured to use 7 RC5 rounds, SEA encryption is almost twice as
fast.
In addition to this, RC5 rounds could be adjusted downward, and back
up to the initialized value, on the fly. With a simple extension of
the SEA-level protocol, the number of rounds used to encrypt the data
can be transferred, allowing this dynamic (or, at least,
per-connection) adjustment. Thus users could request strong, medium,
or mild encryption. This is a planned enhancement to SEA for the near
future.
SEA Authentication
The following two routines are called to authenticate a user or
process. As with the Encryption routines, they are called after a
TCP/IP socket connection has been established.
- seaAuthServer(fd,userid)
performs the server-side authentication protocol.
If successful, it returns the authenticated user identifying
string in the userid argument and a 0 return value. If an error
occurs, a message is printed on standard error, and a negative value
is returned. The userid string is the name that the client has
authenticated as, that is, the user or id on the other side of the socket.
- seaAuthClient(fd, objectname, password)
performs the client-side authentication protocol. If objectname
is a NULL pointer or contains a NULL string (default), the library
will generate and use the user's id (of the form username@domain).
If non-NULL, this is the name that the client will attempt to
authenticate. (In either case the Server-side must have a public
key matching that string, and the client must have the private key
that goes with it.)
Similarly, if the password contains a NULL pointer or a NULL string,
the library will attempt to use the 'semi-encrypted' private
key (created by seaauth auto). If password is non-NULL, the SEA
library will still first attempt to use the 'semi-encrypted' private
key, but if not available, it will attempt to use the encrypted private
key and decrypt it with the password/phrase.
There are also two support functions which can be used by the
application to determine if it needs to prompt for a password:
- seaCheckUserPrivateKeyUnencrypted(name)
Returns true if an Unencrypted private key exists for the user,
or (if name is non-NULL), for the named process.
- seaCheckUserPrivateKeyEncrypted(name)
Returns true if an Encrypted private key exists for the user,
or (if name is non-NULL), for the named process.
See the "User private key files" section below for a related
description.
The following is a brief description of the Authentication protocol:
The client and server processes first establish a communications
socket. Then the client calls seaAuthClient and the server calls
seaAuthServer.
- seaAuthClient sends the id string which is to be authenticated
(e.g., 'schroede@sdsc') to the Server.
- seaAuthServer
receives the id string and attempts to load the corresponded public
key from the defined directory. It then generates a random challenge
8-byte quantity, encrypts this with the public RSA key, and sends the
cipher-text to the Client.
- seaAuthClient receives the challenge, loads the local private key
(decrypting it in the process), decrypts the challenge, and sends the
decrypted challenge back to the Server.
- The Server receives the challenge response (or error message) and
compares it to the original challenge pattern. If they match, the
Authentication is successful, as the Client has proven that it has
access to the private key that corresponds to the registered public key.
Introduction Trust Models
There are multiple distinct authentication environments.
In the DOCT environment, we may wish to allow users to introduce
themselves to the system, and from then on it is sufficient that the
system knows that the same person is communicating with the system
(i.e., they have the private key). In this case, we can simply have
the software generate public/private keys, and send the public key to
the key manager (see below) in effect saying, "here's my public key,
from now on you can identify me with it."
In the NPACI/SDSC environment, a preferred method is to confirm that
the user is actually running on one of our trusted hosts. Like
passwordless access to HPSS from the C90, the SEA system just needs to
confirm that the user is logged onto the C90 as a particular user to
acquire the access privileges of that user. Since that host is well
secured, further authentication is not needed, and the benefits of
simplified registration outweigh the risks. So for the introduction
function (when initial user public/private keys are established), the
system has to confirm that the user is actually logged in on a trusted
host (e.g., the c90) and running as that user. Once that is done, the
SEA authentication system can be confident that a user registered as
user@sdsc actually is that SDSC user. This is accomplished by the SEA
'Trusted Agent.'
In a third environment, positive control is required, but the hosts
involved may not be well-secured trusted hosts. In this case, a
password is required to confirm user identity during registration.
For an initial introduction/registration, the seaauth utility
generates a pair of RSA keys, stores the private key locally
(encrypted), and sends the public key to the key manager to be
recorded for future use. Once this is done, the user can authenticate
to the programs using SEA (the SEA library accesses these keys to
securely authenticate).
The SEA system provides for three "Trust Models" for the initial
introduction/registration.
- Password - The administrator sets up a password for each user's
initial introduction and provides this to the user via a secure
mechanism (e.g., phone or mail). The SEA key manager daemon will
verify this password before allowing a new RSA key to be registered.
This password is encrypted as it crosses the network via the normal
SEA encryption functions.
- Trusted Host - A 'Trusted Agent' process runs on each system that
has a unique user home directory. This agent communicates with the
key manager daemon to verify that the public key being provided is
indeed the key owned by the stated user. This agent program authenticates
itself to the key manager at startup. When authenticating a user,
the agent reads a copy of the user's public key that seaauth
has stored in the user's home directory and provides it to the key
daemon.
For systems that share user
home directories (most SDSC workstations, for example), only one
trusted agent needs to run on one system to handle the whole
collection of computers. The security of this trust model is relying
on the security of the hosts involved and is appropriate for a
centrally managed, security-aware, administrative environment.
- Self-introduction - The system allows
the introduction of new RSA keys as long as the name does not match
an existing key (this uniqueness is required in the Password and
Trusted Host models too). This could be appropriate in an environment
where one is only concerned in verifying the continued identity of
the user; i.e., once introduced, they are the same individual.
Higher-level functions
Two utilities (seaauth, keygen) and daemons (keyd, and ta (trusted
agent)) provide the key generation and management functions. These make use of
the SEA library routines for encryption and authentication themselves
and also make use of various SEA library routines for key file access
and management and other common functions.
The one user utility is seaauth, with the following man-page-style
description:
SEAAUTH .................. December 5, 1997 ................ SEAAUTH
- NAME
-
SEAAUTH - set up and modify authentication with the SDSC
Encryption/Authentication (SEA) system.
- SYNOPSIS
-
seaauth reg | auto | noauto | passwd | rereg | unreg [objectname]
-
reg ---
register as a new user with the SDSC Encryption/Authentication
system. This will create an RSA key pair for you to use,
registering the public key with the SEA system and
storing your private key locally (the combination of these
keys is used to authenticate you in SEA applications such as
the SRB). Normally, the encrypted
private key is stored in your home directory. You will need
to provide a password for encrypting this private key.
-
unreg --- unregister from the SEA system. You will need to
authenticate using your private key and password to
do this. This is not normally needed.
-
auto --- allow automatic authentication from the current host.
This will create an unencrypted copy of your private key
in a local file system. You will need to supply your
private key password to do this. You should run auto
before you run batch jobs, or before an interactive
session in which multiple authentications will be needed.
To increase security, you should run noauto when you
are finished.
-
noauto - disallow automatic authentication from the current host.
This will remove the unencrypted private key.
-
passwd - change the password used to encrypt your private key.
You will be prompted for your old private key password
and for a new one.
-
rereg - go through the registration process again, generating a
new key pair. You will be prompted for your old private
key password to authenticate before this will be allowed.
It is a good idea to reregister occasionally in case
someone else has gained access to your private key.
- DESCRIPTION
-
By default, all of the above operate on your SEA user id, which
is username@domain, where username is your Unix login name and
domain is predefined; for example 'schroede@sdsc'.
Other entities can also be authenticated. In this case, the object
name is specified on the command line.
At SDSC, your encrypted private keys are stored in your Home
directory. For most SDSC workstations, home directories are shared
(NFS mounted) but when they are not (e.g., the C90), you will need
to move your encrypted private key between hosts.
Do NOT attempt to move your unencrypted private keys. They will
not function on another host (they are designed to be host-specific),
and the transfer could expose your private key information on the
network. Your unencrypted private keys are stored on local disk
(/tmp) so as to not transverse the network (i.e., via NFS). (These
private keys are actually encrypted, but only using determinate
values such as hostname.
It is your responsibility to keep your private key private.
As configured at SDSC, your private key file is HOME/.SEAusername@domain,
for example, /users/sy/schroede/.SEAschroeder@sdsc. Your unencrypted
private key will be stored as /tmp/.SEAusername@domain.hostname,
for example, /tmp/.SEAschroeder@sdsc.c90. Both of these files
will be owned by your user id and stored without group or other
access (mode 600). Please do not alter these file modes.
The applications that utilize the SEA system will access your
keys to authenticate you. If you have no unencrypted private key,
they will prompt for your private key password.
In addition to these, seaauth also contains some test and debug
options. This includes -n to display the network messages, -d to
display the network messages and the unencrypted messages, and
test1, test2, test3, and a -mmessage to be used in conjunction
with the tests. These test and demonstrate libsea capabilities.
test1 connects to the key daemon, establishes encryption, performs
authentication, and optionally sends the -mmessage. test2 does the
same except without establishing encryption. And test3 does the
same except without authentication. See the source code for more
information.
seaauth connects to the key daemon (keyd) to register the public key
(and also for the tests). This is an encrypted session, using the
normal libsea encryption functions (although encryption would not be
required). keyd receives the public key from seaauth and stores it
in the public key directory via libsea routines. The directory is
defined in sea.h. The request to store a new key will be rejected if
it already exists (for that user or process name).
Write access to the public key directory must be carefully controlled.
Read access to the public key data is not a concern, and the
seaAuthServer routine, in fact, requires read access. The key daemon
carefully manages this area. The administrator must assure that only
a trusted users can update this directory. Normally, this is only the
administrator who is running the SEA system and perhaps root. The
login password for this account should be well protected, as the SEA
trust hierarchy rests on the security of the Unix file permissions on
the keyd host. So the plain-text password for this login account
should not be sent across the network (e.g., via telnet) but secure
mechanisms (such as SSH or kerberos telnet/rlogin) should be used.
User Private Key Files
User private key files have to be available to the authentication
library on the Client side. For batch jobs, they can not be encrypted
in a way such that passwords are needed to make use of them.
At SDSC, we've configured SEA to store user-password-encrypted private
keys in the users' home directories (e.g., NFS-mounted), and
unencrypted private keys in a local file system (so they won't cross a
network). Users are able to create unencrypted private keys from
their encrypted private keys via the seaauth auto command. These
can be used for batch jobs or interactive sessions (i.e., the library
is able to automatically authenticate using them).
The "unencrypted" private keys are encrypted but only in a
"semi-secure" manner. The SEA routines encrypt and decrypt the user
private key data as it is being written and read from the private key
files. This algorithm takes constant information (such as UID and
host), generates a key (via MD5), and uses this key to encrypt. This
provides a little additional security, but only because the algorithm
is not widely known. Other than this, as with Kerberos, DCE, and
other systems, we are relying on the security of the Operating System
to protect the
secrecy of these key files.
The private key storage location is a configurable option defined in the
sea.h file. A file system that is local (e.g., not NFS-mounted) could
be used for the unencrypted private keys. On the C90, for example,
the home directories could used for the unencrypted private keys, as
they are not NFS-mounted. On SDSC workstations, we store them in
/tmp, since that file system is local and home directories are not.
User Public Keys Files
Each computer system which supports the SEA Server-side authentication
needs access to the public key files. If the public key file
directory is NFS-mounted, they are readily available in a secure
manner (their contents need not be kept private). If that is not
available, a second function of the Trusted Agent can be utilized.
The SEA Trusted Agent (TA), in addition to its function of confirming
user logins and public keys, also synchronizes a replica public key
directory. These two functions work well together, as both are needed
for each independent file system.
The Key Daemon periodically sends a summary of the key file directory to
each TA. This is a blank-delimited list of each key file name with a
checksum value. The TA compares this with a summary of its local
copy. If a local file does not exist in the master list, it is
removed. If a file is missing, or has a differing checksum (has
changed), the TA requests the file from the Key Daemon and receives
and stores it. The Key Daemon repeats this process quickly if the TA
requests a file, and when an update (registration, unregistration, or
reregistration) occurs. Since these files seldom change and are
quite small, this works very well and should scale well to fairly
large directories.
Beyond this, it may be feasible to provide a daemon to return the
public key data instead of accessing files. Since it would be
critical to authenticate this daemon reliably, we could use SEA for
this, storing the Public Key Daemon's key locally, connecting and
authenticating it, and receiving the desired public key. This adds
additional overhead/delay (up to two authentications to achieve one)
as well as some complexity (the existing type of authentication plus
the daemon logic). So, at least for now, the synchronization of public
key files is preferable.
Web of Trust
The SEA system implements a chaining of trust that begins with the SEA
administrator, extends via the Trusted Agent (run by the
administrator), then to Users and Processes. Users can register with
the SEA system (via the TA or password and Key Daemon) and can in turn
register new keys as arbitrary names.
Administrator
/ | \
TA TA TA
/ \ / \ / \
Users Users Users
/ \ / \ / \ / \ / \ / \
Processes and Alternative Names
Each new registration is logged, along with the authenticating agent.
This authenticating agent is first authenticated as part of the
registration process and is either a Trusted Agent or a User. Thus
a chain of trust is created, providing secure authenticating
functionality distributed to a wide set of people.
Integration of SEA with SRB
In the previous versions of the SRB, a plain-text ASCII string within
the connect message was utilized to identify the client user. This
was adequate for testing and prototype purposes, but was not secure.
SEA has been integrated into the SRB to provide secure authentication
and optional encryption.
SRB User Access Control
Once a user is identified, access is controlled to data via that id.
Access Control Lists are maintained in the MCAT catalog specifying who
has what type of access to each particular dataset.
Communication Changes
The modification of the SRB communication routines to allow for
encryption was more involved than expected. The SRB communication
routines, based on code available from elsewhere, was using file
stream I/O and doing this via multiple subroutine packages. The use
of file stream I/O was a reasonable design choice but prevented the
access to buffers that is needed for any add-on encryption scheme.
The sets of communication routines were modified to use sockets and
new buffering routines. For example, calls to putc were changed to
calls to commPutc, which stores data into a small buffer and calls
seaWrite when full (similarly, calls to fflush were changed to a new
routine that calls seaWrite).
The read system call and seaRead behave differently than stream file
I/O reads in that they will return data that is currently available
rather than waiting for the buffer to fill. To present the same
stream-like interface to the higher-level communications routines, the
mid-level routines loop on reads until the buffer fills or the connection
ends.
SRB Encryption
With these communications changes in place, a call to
seaBeginEncryptionClient and seaBeginEncryptionServer causes libsea to
encrypt communications data. In the SRB communication scheme, both
control information and data are transferred on the same socket, so
when encryption is enabled, it is performed on both.
There is a new flag in the SRB connect message that requests
encryption. The client user can control this with the SEA_OPT
environment variable. When the flag is set, the client side calls
seaBeginEncryptionClient, and the server side calls
seaBeginEncryptionServer to establish encryption.
If a SRB client has requested encryption and the SRB Server connects
to another SRB for a proxy function, encryption is requested on this
second (or subsequent) connection, thus extending the protection of
data. When the SRB Server calls another SRB for a proxy function, it
does so via the SRB client routines, so adding encryption is simply a
matter of propagating the flag. However, this does mean that the SRB
in the middle has to decrypt and reencrypt (in a different key) as it
is transferring data.
SRB Authentication
In a manner similar to the SRB SEA encryption, a new flag in the
SRB connect message specifies that SEA authentication is to be used.
Eventually, this will be phased out and SEA authentication required
by default.
The server and client make the SEA authentication calls to confirm
the identity of the client.
SRB to SRB Authentication
In various situations, a SRB will make client calls to another SRB on
behalf of a client. This can occur when a particular storage type (an
Illustra DB, for example), is available through a second SRB but not
the first. In fact, much of the SRB functionality is this
transparency of access.
The SRB to SRB authentication has been implemented by using the SEA
user authentication capabilities and a list of privileged user ids,
for example "srb@sdsc". It would also be possible to authenticate
with an alternative process or object name but, for now,
authenticating to the SRB userid is sufficient. If the
SEA-authenticated user is privileged, then the username as passed by
the connect message is used. In this way, the SRB to SRB connections
can proxy for the original user.
The list of SRB names (users with privileges) is maintained in the
MCAT Catalog and retrieved by each SRB at startup. This provides
substantial flexibility in the configuration of multiple SRBs and
meshes well with the MCAT core functions as the SRB data and metadata
repository.
We decided to modify the connect message to contain two fields, the
clientUser and the proxyUser, to clarify the use of two types of user
ids. This is similar to the Unix's model of Real and Effective User
IDs. SEA is used to confirm the identity of the proxyUser field (real
UID). (An initial integration of SRB and SEA kept the format of the
SRB connect message unchanged, except for the addition of new flags,
and used SEA to confirm the user id.)
With SEA authentication from SRB clients, the proxyUser field is
compared with the SEA-authenticated name as determined by
seaAuthServer routine. If the proxyUser matches an entry in the
privileged user list, then the clientUser field is allowed to vary
from the proxyUser name. For non-privileged users, the clientUser
field must match the proxyUser. It is the clientUser name that is
used for access control.
A second (or later) SRB in a chain of SRBs (for a particular
connection) trusts the information passed to it when that connection
has been identified as from a privileged user. The user of the
original SRB client is authenticated to the first SRB, and the second
SRB then "knows" that the user has authenticated. This provides a
secure, flexible, and simple authentication mechanism that meets the
needs of the SRB infrastructure.
Server Identification
For the SRB, there is little need to confirm that a client is
actually talking to the SDSC SRB. If it is not, it will not be
able to access data. SEA could be used for this type of
authentication, but some method of reliably providing the SRB public
key to the clients would be needed.
How To Install For Encryption
- Build RSAREF 2.0. For most Unix systems, SEA is using a slightly
modified version of the standard reference implementation from RSA
Laboratories, rsaref2.tar (the names of a few routines were changed to
avoid a conflict with libnsl on Solaris systems: MD5Init to MD5SInit,
MD5Update to MD5SUpdate, and MD5Final to MD5SFinal). For the Cray C90
and Cray T3E, SDSC modified versions are available.
- Unpack the SEA distribution tar file and edit the Makefile and
sea.h files for site-specific options. See sea.h for details.
- Run gmake (gnu make). This will create libsea.a, keyc, keyd,
ta, genkey, and some test utilities. If gnu make is not available, the
Makefile can be edited to remove the host-type checks and to set
host-specific values.
- For the encryption functions, the process calling the
seaBeginEncryptionServer function (the server process), should
have access to an RSA public/private key pair in files defined in
sea.h (#defines PUB_KEY_FILE and PRIV_KEY_FILE). These can be
generated with the SEA administrative utility genkey.
If these files are not available, the SEA library will use a key pair
that are built into the source. This is somewhat less secure,
however. (The built-in keys can be changed using genkey and the
mkinit.pl script. See comments in the script for more information.
But even if the source is changed, key files are generally more secure.)
- Applications linking with the SEA library
will need access to the following:
- libsea.a (the Makefile file merges both the RSAREF library and the
SEA library into libsea.a)
- Some applications may need access to sea.h
By default, the libsea RSA keys are 512 bits long, providing
reasonably strong security. Longer keys can be used if desired. The
512-bit keys take about 15 seconds to a minute or so to generate
(using libseas RSAREF2.0), and about 1 second in use. Generation is
done infrequently (i.e., when one uses genkey to set up the keys for
encryption) and use is done each time encryption is established.
To use longer keys, provide a longer key length to the genkey
utility. The format of the command line is genkey
outputfiles_basename [keylen] [passwd]', for example, genkey
sea_key 712.
How To Install For Authentication
- Perform the installation for Encryption.
- Install keyc (key client, also known as seaauth) where you would
like it, accessible to users (e.g., cp keyc /usr/local/bin/seaauth).
No privileges are needed (no setuid or setgid).
- Install keyd (key daemon (the key manager)). The user under which
keyd runs must have write access to the directory that holds the user
public keys (defined in sea.h). Processes that will be using
seaAuthServer routine will need read access to this directory. No other
user should have write access to the directory.
- If you are running the Trusted Agent (ta), install it where
you want, generate a key for it (seaauth reg ta_name)
and start it. The execute line is ta ta_name. If
seaauth auto ta_name has been run, no password will be
needed to authenticate the TA to the key manager daemon. You may want
to set up a cron job to periodically start it (if a ta by this
name is already connected to the key manager, it will exit; if it
can't connect to the key manager, or an error occurs, it will also
exit.)
Licensing Restrictions
Even without using PGP, the use of RSA and RC5 may eventually require
some attention to licensing. However, the use of RSA by
U.S. Universities for non-commercial purposes is allowed without a
direct license from the patent holder (RSA Data Security). As we
move into a more production mode, this may require more attention.
Other Web Pages Of Interest
RSA
Kerberos Users' Frequently Asked Questions
International PGP Home Page
SSH Home Page
SSH at SDSC
International Cryptography Pages
Other Important Sources
For RC5, we started with sample source code from "Applied Cryptography"
by Bruce Schneier, via associated diskettes.