Assignment #3: Cryptographic Filesystem
Due Date: April 12, 2006
Total Points: 100

Introduction

Many people and corporations would like to use encryption to protect the confidentiality of their data. However, the difficult of using common encryption programs like PGP (see Why Johnny can't Encrypt: A Usability Evaluation of PGP 5.0) prevents most users from encrypting their data. Yet the threat of information leakage is a very real one, as shown by incidents where thousands of people's confidential data is stolen along with a company laptop. File encryption could be made transparent to the user by moving it into the filesystem. Applications can function unchanged while all of their files are encrypted. For this assignment, you'll implement a cryptographic filesystem to solve this problem.

Assignment

Starting with the stackable filesystem wrapfs, implement an encrypting filesystem. Encryption should be based on the Blowfish algorithm with 128-bit keys. This algorithm is provided as part of the kernel's CryptoAPI. For help on using the CryptoAPI, see crypto/tcrypt.c, which contains the kernel's cryptographic test functions. The test_cipher() and test_hash() functions will show you how to use Blowfish encryption and MD5/SHA hashing respectively.

Blowfish is a block cipher with a 64-bit block size. This means that all reads and writes must be aligned on 8-byte boundaries within a file. Your read and write routines will need to read beyond the requested set of bytes to reach proper alignment in order to fulfill some requests. As a result, all files must be a multiple of 8 bytes in length. You can pad files with zeroes to meet alignment requirements. In order to show the user the correct file size, add 8 to the stored file size if it's not a multiple of 8 already. When the file size is read, substract 8 from it if the read size is not a multiple of 8.

I recommend that you begin the assignment by creating a filesystem that encrypts with Blowfish using a fixed key that's used for the entire filesystem. Test that filesystem carefully, then implement ioctl(3) calls to set and delete the cryptographic key (see the debugging ioctl examples in file.c in wrapfs for help on creating those.) For security, in the key deletion ioctl zero out the memory used by the key before freeing it. The key can either be stored in the superblock or in a hidden file (you'll need to choose a name and use wrapfs to hide the file.)

Write user-level programs, setkey and delkey, that call the set and delete ioctl functions. The programs must take the cryptographic filesystem's mount point as an argument (i.e., /mnt/cryptfs and should use the user's UID as the associated key UID. The user must enter a passphrase to use setkey. The passphrase will be need to be hashed to produce the cryptographic key (the kernel cryptoAPI has hash functions that will produce 128-bit values from any string given.)

Your ioctl functions need to handle common user errors like trying to set a key multiple times and deleting a non-existent key. Document your design choices and error handling in a README file.

Submission

Submit the contents of your cryptfs directory as a gzipped tar file (.tar.gz suffix). Comment all modifications to the source with your name and include a README file that summarizes your design decisions and the modifications you made to implement them. Submit the file by e-mail to me. You'll also demo your code in class in the lab session on the due date.

References

  1. Erek Zadok and Ion Badulescu, A Stackable File System Interface for Linux, 1999.
  2. Erek Zadok, Ion Badulescu, Alex Shender, Cryptfs: A Stackable Vnode Level Encryption File System, 1998.
 

©2006 James Walden, Ph.D.