in deutsch IMMD IV Home Page Back Up Next Help Rie - Jan. 14, 1997

AKBP-II 1997: Group 4


The Crypt Filesystem

Basic Functionality

The Crypt Filesystem is a special kind of loopback filesystem which enables the user to store data in encrypted form.

The simplest way to use the Crypt Filesystem is to mount a directory on the local hard disk (e.g., "/crypt"), which contains encrypted files, to a mount point (e.g., "/mnt"). After setting a key, the encrypted files in "/crypt" will be visible (decrypted) in "/mnt". The key can be set by the user-level program "cryptfs_setkey": this program creates a new shell and attaches the key to it. Whenever this shell accesses files of the Crypt Filesystem (i.e. in /mnt), all data transferred to/retrieved from disk will be automatically encrypted/decrypted. This special shell passes on its ability to access the key to its child processes which are created by the Unix process creation mechanism, i.e. commands which are typed in the shell will be able to access files of the Crypt Filesystem. The fact that the key is bound to processes rather than, for example, login names, provides better protection for the encrypted data: Even if a hacker manages to break into the Unix system, it is difficult to compromise the Crypt Filesystem as well. This seems possible only if an attacker manages to gain root privileges, which will be discussed in more detail when the use of NFS in combination with the Crypt Filesystem will be described.

Encryption and decryption of the files is transparent to the user: Once the key is set, all Unix programs work as used, because the Crypt Filesystem takes care of encryption/decryption automatically.

Using NFS in Combination with the Crypt Filesystem

As described above, the Crypt Filesystem can be used to protect sensitive data stored on a local hard disk. However, it is often desirable to access data which is kept on a remote file server rather than on a local workstation. For this purpose, NFS (Network File System) is in widespread use, although NFS has serious disadvantages in regard to data security when used in the traditional way. Problems can arise due to security flaws of the client, of the server, and - perhaps most important - of the network inbetween. Especially if server and client do not use the same local network, transmitted data can be seen by any person having access to one of the routers between client and server. To prevent this, the Crypt Filesystem can be used to make sure that only encrypted data is transmitted via network. This can be done in two different ways, depending on the circumstances and security requirements. These two ways are described in the following paragraphs.

First, the files can be stored on the server in encrypted form and made accessible to the client using NFS. The corresponding directory can then be mounted using the Crypt Filesystem to obtain a directory on the client which contains the files in decrypted form. The mount operation is done the same way as if the NFS-directory was a directory on the local hard disk of the client which contains encrypted files. Using this method, no encrypt- and decrypt-operations have to be performed on the server, which also means that the key is not needed on the server. As the data encrypted on the server, it is safe even if an attacker manages to break into it. As the key is not present at the server, the best possible security is achieved on the server side. ``Best possible'' means that the only way of compromising the system is to break the encryption system (i.e., DES) itself. Even the knowledge of the root password for the server is no use for an attacker if the key for encryption is not known. There is also no need to worry about someone gaining access to the data on its way through the network, because only encrypted data is transmitted, so on the net, the same level of security is achieved as on the server. On the client side, the Crypt Filesystem takes care of decrypting the files which are imported via NFS and makes them transparently accessible the same way as if the files were stored in encrypted form on the local hard disk. As the key has to be stored somewhere in the client's operating system (i.e., within the kernel data structures), care has to be taken in order to prevent an attacker from acquiring superuser privileges. In this case, it cannot be prevented that the attacker finds a way to sneak the key out of the kernel's data structures or to read the uncrypted data directly out of the user adress space of a process which was provided with the key. Therefore, the root password has to be chosen carefully according to well-known rules for Unix passwords, and it has to be kept as secret as the key for the encryption system.

The second method to use NFS in combination with the Crypt Filesystem makes it possible to protect data which is not encrypted on the file server. One way to make sure that only encrypted data is sent over the net to the client would be to make an encrypted copy of every file which is to be exported. With these encrypted copies, the first method (described above) can be used to make the data accessible to the client. To avoid the inconvenience of having to create a copy of the whole directory tree, it is possible to create a "virtual encrypted copy" of the directory tree which is to be exported with the Crypt Filesystem. This is done by mounting the corresponding directory in "inverse mode", creating a directory which is identical to the mounted directory, except that all the files are encrypted. This directory can be exported via NFS and decrypted again on the client to get files which are identical to the ones stored on the server.

Although this method is convenient in order to export files without having to create encrypted files on the server's hard disk, it should be pointed out that there are two major disadvantages: First, the server is vulnerable for an attacker who manages to break into the Unix system, as the files are stored on the hard disk. To compare the situation of an attacker with root privileges on the client (no matter whether the first or the second method is used) to the situation of an attacker with the same privileges on the server when the second method is used, it can be stated that it is still tricky for a "superuser" on the client to find out the key or gain access to the data directly, whereas it is obviously trivial to read the files which are stored without encryption on the server. Especially, to compromise the Crypt Filesystem on the client is only possible while there exist processes which "know" the key. (Therefore, it is recommended to have these "privileged processes" only as long as they are really needed.)

The second disadvantage is that the server has to do the encryption/decryption of the data for every read or write access. As these are cpu intensive operations, performance of the server might decrease. In general, computations should be shifted from the central servers to the local clients whenever possible in order to optimize average response time, because several people contribute to the load of a single file server, whereas there is usually only one person logged on to a client workstation. This general goal is not respected by the method in question. Therefore, it should be evaluated if the convenience of the second method is worth the risk that the work of all those who are dependent on the file server is slowed down. In the long term, it might pay off to generate crypted versions of the files on the server and to export them directly.

The modules "cryptfs" and "crypt"

In order to use the Crypt-Filesystem, two modules must be present: The module "cryptfs", which provides the filesystem itself, i.e. it includes the filesystem and vnode/key-vnode operations (this is described further in the "Implementation Details" section below), and the module "crypt", which contains the encryption/decryption routines and a function to construct the key in the format that is necessary for the particular crypt method out of a passphrase. When a Crypt-FS mount operation is done and these two modules are not yet present in the kernel, they are loaded automatically, provided they are found in the appropriate module directories. These directories are "/kernel/fs" for the module "cryptfs" and "/kernel/misc" for "crypt".

The reason why a separate module is used for the crypt routines is that this makes it possible to have a choice of several different crypt methods by providing different versions of the "crypt" module. For example, different users might have different requirements in regard to the level of security that is necessary and the loss in performance of the file system that is acceptable. Usually, an encryption method which provides better security takes also longer to compute for a given amount of data.

The different "crypt" modules must have a common interface, as their routines are all called by the same "cryptfs" module. This interface is given in the header file "crypt.h". It should be feasible to adapt other encryption algorithms which are suitable for the Crypt-FS to this interface and compiling "crypt" modules for these algorithms, being flexible in regard to encryption algorithms which may evolve in the future. Being "suitable" means that the method has to use a symmetric key and that it must be possible to encrypt/decrypt a part of a file without the need to know or to change certain parts of the rest of the file.

Implementation Details

The Crypt Filesystem consists of the three logic parts filesystem-, vnode- and key-management.

Filesystem / Vnodes

The Crypt Filesystem management hardly differs from a "normal" loopback-filesystem. The main difference - apart from the encryption/decryption - is the fact that not only a linked list of vnodes has to be kept, but also of key-vnodes which are needed to store the key.

The main part of the work is done by the vnode-operations. All operations which have nothing to do with encryption/decryption are passed to the underlying filesystem. Decryption/Encryption is performed by the read- and the write-operations.

As the crypt-routines operate on data blocks of a fixed length (eight bytes), encrypted files are enlarged by one block length. This makes it possible to deal with the last bytes of a file, which do not fill a whole block, and provides a solution to the problem of getting the "real" length of the uncrypted file. Of course, this change in the length of the files has to be taken into account in certain operations (read(), write(), getattr()) to avoid inconsistencies. Furthermore, the operations read and write have to make sure that whole blocks are being used even if this is not the case for the user request, as parts of blocks cannot by decrypted/encrypted.

The key management

The encryption system

For the crypt routines the symmetric system DES is used, i.e. there is only one key for both en- and decryption. The current version uses a key of 8 bytes; it is specified by the user within the user-level-program "cryptfs_setkey" in hex format. The following paragraph describes how the key is stored within the Unix kernel in order to make it possible to have a key which is bound to processes and which is passed on to child processes automatically when the ordinary Unix system calls for process creation are called (i.e. "fork" and the calls of the "exec"-family).

Where the key is stored

To enable inheritance, the key must be stored in a per-process data structure which survives calls of "fork()" and "exec()". The file descriptors have these properties: The file descriptor table entries are copied when a child process is created and they remain when "exec()" is called. Therefore, a special file descriptor (number 63) was chosen to point to a special vnode (called key-vnode) which holds the key in its private data structure. If there is no entry on place 63 of the file descriptor table or the entry does not point to a key-vnode, the corresponding process is not able to read or write any files of the Crypt Filesystem. "Access denied" (EACCES) will be returned by the called vnode operations in this case. If the key-vnode is present, the key will be extracted and is used for the call of the routines which handle encryption/decryption.

How the key is set

To simplify generation of key-vnodes, a key-vnode is created by the lookup-operation of the Crypt Filesystem, if a call with the file-name ".keytab" is made. Therefore, the program "cryptfs_setkey" does an "open()" on this file. This system call will return a file descriptor which points to a key-vnode if "cryptfs_setkey" was called in a directory of the Crypt Filesystem, as the open-call results in a call of the lookup-operation of the Crypt Filesystem. This key-vnode will be uninitialized at this point, i.e. no key is stored in its private data structure. As the key-vnode has to be accessible through file-descriptor 63, "cryptfs_setkey" performs a call to "dup2()". To initialize the key-vnode, "write()" is called with the key the user provides. The key is copied into the private data area of the key-vnode where it can be accessed through the 63th file descriptor table entry on subsequent read- and write-operations.


About our Server | Mail to Webmaster | Navigational Hints | Search