TCFS: Transparent Cryptographic File System
Current network technology makes it cheap and convenient to share resources over a network. Typically, a computer network consists of one server with direct access to a resource (file system, printers, CPU time). The server then allows several clients to access the resource. A file system is a typical resource which can be shared over a network, and Sun's NFS is the most widespread protocol for file system sharing. An important feature of NFS is its complete transparency to the application using it. The application has no need to know whether it is accessing a file on a local file system or from a file system shared over a network.
NFS, designed by Sun several years ago, does not address the security issues arising in this context. NFS is simple in structure and assumes a strong trust model: that is, the user trusts the remote file system server and the network with his data. This poses several risks. The data on the server are available to the server superuser; also, users on the network may assume other identities by changing their IP numbers or their user IDs, allowing data to be read while it travels on the network. Because of this, it is necessary to address the security issues by protecting the data while stored on a remote server and during network transfers.
TCFS (Transparent Cryptographic File System) has been developed at the Dipartimento di Informatica ed Applicazione of the Universita' di Salerno (Italy) and is currently available for Linux. You can look at TCFS as an extended NFS. It acts just like NFS, but allows a user to protect his/her files using encryption.
TCFS requires an NFS server running Linux with the EXT2 file system. It must be used with 2.0.x kernels, since it is based on Olaf Kirch's NFS module. TCFS can be used as a kernel module (and inserted using the insmod utility) or can be compiled into the kernel. When you start the TCFS module or when you boot (if TCFS is statically linked), you will find four copies of the tcfsiod daemon running.
TCFS works as a layer under the VFS (Virtual File system Switch) layer, making it completely transparent to the applications. The security is guaranteed by means of the DES (data encryption standard) algorithm. Keys are kept in a special database (/etc/tcfspasswd) which stores keys encrypted with the user's login password. To maximize the level of security, it is best to keep to a minimum number of trusted entities. A TCFS user needs to trust only the kernel and the superuser of the client machine accessing the data. We stress that this minimal level of trust is necessary, since you cannot protect your data from the kernel and the superuser. Both can access memory any time that they want. Our trust model fits perfectly the typical scenario in which TCFS is used: a network of workstations with limited disk space, each used almost exclusively by a limited number of users (you can even think of each user as the superuser of his/her own workstation) and a remote file server sharing files with all the workstations.
In designing TCFS we were interested in providing a robust security mechanism at the lowest possible cost to the user. The security mechanism must guarantee that secure files are not readable:
by any user other than the legitimate owner,
by tapping the communication lines between the user and the remote file system server,
by the superuser of the file system server.
We also protect sensitive meta data—for each file; not only the content but also the filename is encrypted. We hide internal file data dependencies using a DES in the chaining block cipher.
In TCFS, security acts in a transparent way. Secure files can be accessed in the same way as local files—the user has only to authenticate himself to TCFS before starting to work. A special flag, which looks like an EXT2 extended attribute, marks encrypted files to make them distinguishable from unencrypted ones. Thus, TCFS is able to store both secure and unsecure files on the same file system depending on whether or not this flag is set.
We give special attention to making TCFS completely transparent to the file server. Transparency allows the superuser on a server to perform all administration duties in that we don't change the data structures of the file system itself. Special work is needed for a directory with the secure flag enabled. Files in a secure directory are stored with encrypted filenames, and new files inherit the secure flag, so that they too are secure. Since TCFS acts like a file system in a VFS (virtual file system) layer, standard system calls can be used to access files on the TCFS. No special flags are needed by the open() or create() system calls. For this reason, all applications can use the new features without being recompiled.
To explain the mechanics of TCFS we will first review the working of NFS. NFS is a simple distributed file system that allows a file system server to export its file systems to several clients. Applications, running on a client, access the remote file system via the usual system calls. The client kernel checks to see whether the requested data is on a local file system or an NFS file system. In the latter case, the kernel issues a request to the server; for example, if the application needs to read a block from a file on a remote file system, the client operating system issues a read request to the server. The server, upon receiving a read request, reads the data from its local file system and sends it to the client, which then passes the data to the application. It is important to remember that NFS provides a minimal form of user authentication. The server receives from the client the uid of the user requesting the data and checks if that user is allowed to access the file containing the data. Thus, it is possible for a user to change his uid on the client (for example, the superuser of the client machine can use the command su to become any user) or to modify the NFS client so that a different uid is provided with the request.
When using TCFS, files can be stored in encrypted form on the server file system with a different encryption key for each user. The encryption key is provided by the user to the TCFS client through the tcfslogin utility. (A detailed description of the TCFS utilities appears below.) Reading a block of data from the server is achieved following the NFS protocol, with one important exception: once the requested block is received by the TCFS client, it is decrypted before being passed to the application. Similarly, a block of data written by an application is encrypted with the user's key before being passed to the TCFS server. During a read or write operation the user's encryption key never leaves the TCFS client, and data travels between server and client only in encrypted form. Moreover, this approach addresses the problems related to user authentication. While it is still possible for a user to impersonate the legitimate owner of a file, he will receive only encrypted data.
Set up your TCFS server just as you would an NFS server—by exporting the file system you wish to share with your clients. Usually this is done by editing the /etc/exports file and restarting the NFS daemons (rpc.mountd, rpc.nfsd).
Retrieve xattrd from the TCFS package. It can be found in the linux/fs/tcfs/contrib/xattrd directory of the TCFS distribution. Copy xattrd to the daemon directory, usually /usr/sbin, and add it to your rc files. For the Slackware distribution, edit the /etc/rc.d/rc.inet2 file to look like Listing 1. rc.inet2 File.
For Red Hat or any other distribution using the System V init script model, create a file in the rc directory (/etc/rc.d/init.d in Red Hat 4) for starting and stopping the xattrd daemon and make symbolic links in the rc\#.d directories to start it. In Red Hat you can do this using the tksysv script. For an example of building the xattrd rc scripts, see Listing 2. File for Building xattrd Script.
Now, reboot the system or run xattrd as root to prepare the server for TCFS. Notice that xattrd reads /etc/exports at startup and so if you change /etc/exports, you must restart xattrd. xattrd adds functionality to the NFS server and is not meant to be a replacement; therefore, it is possible to use the same server as both a TCFS server and an NFS server.
Installing TCFS on the client is somewhat more complex, since most of the work is performed by the client—the kernel must be rebuilt to support TCFS.
The TCFS distribution provides a tar file to be unpacked in the /usr/src directory. We assume that the kernel sources are in the /usr/src/linux directory (this is the standard for most Linux distributions). Install TCFS with the following steps:
Untar TCFS to create the directory /usr/src/linux/fs/tcfs which contains the code for TCFS and its related utilities.
Apply the tcfs.diff patch found in /usr/src/linux/fs/tcfs/patches to the kernel. Do this by changing directories to /usr/src and then typing patch < linux/fs/tcfs/patches/tcfs.diff.
Recompile the kernel. In the FileSystem section you will be asked about TCFS. It is possible to install tcfs as a module or built-in. In both cases it is necessary to recompile the kernel following the usual procedure.
Install the utilities. Once a kernel with TCFS support has been installed, change directory to /usr/src/linux/fs/tcfs/contrib/binaries where you will find the binaries for the TCFS utilities, and type make<\!s>install. It is also possible to compile the source code for the TCFS utilities located in /usr/src/linux/fs/tcfs/contrib/src.
Enable use of TCFS. The superuser of the client must generate a key for each user using the tcfsgenkey utility. This requires the user's password, so it must be done with the help of the user. The utility tcfsgenkey builds a database (/etc/tcfspasswd) where the keys used to encrypt files are stored. These are kept encrypted using the user's login password as key. In future releases of TCFS we are planning to provide support for smart cards, thus dispensing with the need of keeping the key (albeit in encrypted form) on the client.
TCFS utilities. The command mount provided by TCFS is capable of handling TCFS mount operations. We encourage you to use our version of mount in place of the standard mount command, since TCFS needs some information that the standard mount doesn't provide. To mount a file system with TCFS, type:
mount -t tcfs server:/remotepath /localpath
TCFS also supplies the passwd command which is used to update the encryption key database. It acts like the standard passwd command, but also updates the tcfspasswd file after changing the password. Changing your password with the old passwd command will result in the wrong encryption key being extracted from /etc/tcfspasswd, and thus, in a complete loss of data.
After login, each user has to execute tcfslogin. Utility tcfslogin requests the user's login password to decrypt the encryption key and pushes the cipher key in the kernel module. To remove the key, the user must execute the utility tcfslogout, which needs a TCFS file system mounted to work. In future releases we plan to include support for PAM (Pluggable Authentication Module), making it unnecessary to input the login password twice.
The lsattr and chattr commands act just as they do in EXT2. The TCFS versions support a new flag, X, to enable encryption of files. You can change status of a file (encrypt or decrypt) by typing:
chattr $ <+|-> $X
Suppose you have a server named foo and a client named bar and suppose you export the directory tree named /exports from server foo to client bar. For this to be true foo must have the following line in /etc/exports:
Now, login as root on bar and mount /exports by typing:
mount -t tcfs foo:/exports /mnt/tcfsThis command causes the remote file system, /exports@foo, to be mounted on the local file system, /mnt/tcfs@localhost, via a TCFS layer.
Now, suppose your login is usdm1, and you own a directory named /mnt/tcfs/usdm1. Login as usdm1 on bar and execute tcfslogin; doing so enables you to use encryption in your directory /mnt/tcfs/usdml. If tcfslogin is not issued, a permission denied error will be issued when attempting to access files with the X flag set.
In order to evaluate the overhead introduced by encryption of the data sent over the network, we performed a set of tests. We ran the test in the following framework:
The client machine running TCFS on the Linux 2.0.23 kernel is a Cyrix x686 166MHz processor
The server machine running as the NFS+xattrd file server is an Intel Pentium 133MHz processor with a 2GB fast SCSI disk.
Since encryption/decryption is a CPU-bound task, having a fast client to perform encryption results in better performance. TCFS makes use of standard VFS caches—no special caching is needed.
time dd bs=xxx if=file of=/dev/null count=n
and for the write operations:
time dd bs=xxx if=/dev/zero of=file count=n
The tables show the following results:
The overall performance of TCFS for write operations is close to NFS performances plus DES overhead. In the write, we suffer due to the lack of a cache system, since data are written directly to the server file system.
The performance of TCFS for read operations seems to hide part of the DES time, since VFS caches reduce server I/O.
Some extra cost is paid by TCFS for I/O of unencrypted files due to handling of extended attributes. In NFS several getattr calls are needed to update inode caching. In TCFS we need a getattr and a geteattr to update inode caching. This causes some extra overhead in TCFS I/O.
Use of other ciphers will result in different performances. We are planning to use IDEA, RC5 and other ciphers as optional modules for TCFS.
Ermelindo Mauriello (firstname.lastname@example.org) was born in Avellino, Italy on December 10, 1972. He is a computer science student at the Dipartimento di Informatica ed Applicazioni “Renato M. Capocelli” of the Universita' di Salerno in Italy. He has been working on the TCFS project since 1995.