Using eCryptfs on the B3
There are several file encryption tools for Linux available. The one I like most currently is eCryptfs. Unlike other methods it works on top of an existing file system encrypting each file separately. This has many advantages:
- you don't need to reserve space for encryption (like with creating a partition or a container file)
- you can access the encrypted files and backup them to an untrusted location (like a cheap webhost)
- if something breaks (think bitflip) only a single file is affected, not all your files (not sure if this is true for other systems too)
It also has some disadvantages:
- eCryptfs systems can't be exported via NFS currently
- if you have many small files, you have some space overhead as each file has an encryption header.
- maybe more
Anyway, I wanted to use it on my new B3 server. Here is how.
Installing the Kernel Module
The B3 does not have the needed Kernel module, so we need to compile it ourselves. You could probably setup some cross-compile environment for that, but I found it much easier to just compile it on the B3 itself. It takes a while though .
Login via SSH and become root, then install the build tools first:
#aptitude install devscripts build-essential lsb-release libncurses-dev
Now you need to fetch the kernel sources matching your running kernel.
# uname -a Linux b3 2.6.35.4 #5 Tue Sep 7 16:06:15 CEST 2010 armv5tel GNU/Linux # wget http://download.excito.net/kernel/Excito_B3/2.6.35.4/linux-2.6.35.4-excito.tar.bz2
Unpack it and get the current Kernel config from /proc
:
# tar -xjvf linux-2.6.35.4-excito.tar.bz2 # cd linux* # cat /proc/config.gz |gunzip >.config
Now run the config tool
# make menuconfig
The thing we're missing is
File systems ---> Miscellaneous filesystems ---> <M> eCrypt filesystem layer support (EXPERIMENTAL)
Be sure to select module (M), we don't want to build a completely new kernel here.
Now get a coffee and compile the modules.
# make modules
Once the compile succeeds you can copy the new module to the right place and load it:
# cp -r fs/ecryptfs /lib/modules/2.6.35.4/kernel/fs/ # depmod -a # modprobe ecryptfs
Now you just need to add the user space utilities:
# aptitude install ecryptfs-utils
Setting up the Mountpoints
To have an encrypted directory, you specify a directory where the encrypted files should be stored (called lower directory) and then mount a virtual directory to where you want to access the decrypted files (the mount point).
Let's assume we want to encrypt the /home/storage/pictures
directory (our mount point) and use /home/storage/.pictures
as the lower directory. You have to decide if you want eCryptfs to encrypt the file names as well or just the file contents. Let's say we want the file names encrypted as well.
So let's start with creating the lower directory:
# mkdir /home/storage/.pictures
To actually setup the encryption you simply mount the directories using the ecryptfs
file system type. The mount helper will ask you for the needed options:
# mount -t ecryptfs /home/storage/.pictures /home/storage/pictures Passphrase: My secret passphrase! Select cipher: 1) aes: blocksize = 16; min keysize = 16; max keysize = 32 (loaded) 2) blowfish: blocksize = 16; min keysize = 16; max keysize = 56 (not loaded) 3) des3_ede: blocksize = 8; min keysize = 24; max keysize = 24 (loaded) 4) twofish: blocksize = 16; min keysize = 16; max keysize = 32 (not loaded) 5) cast6: blocksize = 16; min keysize = 16; max keysize = 32 (not loaded) 6) cast5: blocksize = 8; min keysize = 5; max keysize = 16 (not loaded) Selection [aes]: 1 Select key bytes: 1) 16 2) 32 3) 24 Selection [16]: 1 Enable plaintext passthrough (y/n) [n]: n Enable filename encryption (y/n) [n]: y Filename Encryption Key (FNEK) Signature [0123456789abcdef]: Attempting to mount with the following options: ecryptfs_unlink_sigs ecryptfs_fnek_sig=0123456789abcdef ecryptfs_key_bytes=16 ecryptfs_cipher=aes ecryptfs_sig=0123456789abcdef Mounted eCryptfs WARNING: Based on the contents of [/root/.ecryptfs/sig-cache.txt], it looks like you have never mounted with this key before. This could mean that you have typed your passphrase wrong. Would you like to proceed with the mount (yes/no)? : yes Would you like to append sig [0123456789abcdef] to [/root/.ecryptfs/sig-cache.txt] in order to avoid this warning in the future (yes/no)? : yes Successfully appended new sig to user sig cache file Mounted eCryptfs
If you don't want filename encryption, just say no when asked.
You now have setup the encryption and can start putting files in /home/storage/pictures
.
To be able to easily remount the directories later, you should adjust your /etc/fstab
:
- /etc/fstab
/home/.crypt/hard /home/crypt/hard ecryptfs noauto,rw,ecryptfs_sig=0123456789abcdef,ecryptfs_cipher=aes,ecryptfs_key_bytes=16,ecryptfs_fnek_sig=0123456789abcdef,ecryptfs_unlink_sigs,ecryptfs_passthrough=n 0 0
The needed signatures in these lines were displayed after your mount command above, but can also be seen by just calling mount
on the command line. If you said no to filename encryption just skip the ecryptfs_fnek_sig
parameter.
Be sure to add the noauto option or your B3 will not boot anymore (because it will wait for a passphrase)!
The directories can now be unmounted and mounted again by simply calling
# umount /home/storage/pictures # mount /home/storage/pictures
Webinterface for Mounting
To have an easy way for mounting your encrypted directories, I wrote a PHP script that can be integrated into the B3 web interface. Install it to /usr/share/web-admin/admin/controllers/ecryptfs.php
.
- /usr/share/web-admin/admin/controllers/ecryptfs.php
<?php class Ecryptfs extends Controller{ function __construct(){ parent::Controller(); require_once(APPPATH."/legacy/defines.php"); require_once(ADMINFUNCS); $this->Auth_model->enforce_policy('web_admin','administer', 'admin'); load_lang("bubba",THEME.'/i18n/'.LANGUAGE); } function _renderfull($content, $head = '/disk/disk_head_view', $data = ''){ $navdata["menu"] = $this->menu->retrieve($this->session->userdata('user'),$this->uri->uri_string()); $mdata["navbar"]=$this->load->view(THEME.'/nav_view',$navdata,true); $mdata["dialog_menu"] = $this->load->view(THEME.'/menu_view',$this->menu->get_dialog_menu(),true); $mdata["head"] = $this->load->view(THEME.$head,$data,true); $mdata["content"]=$content; $this->load->view(THEME.'/main_view',$mdata); } function _list_mounts($haspass){ $fstab = file('/etc/fstab'); $fstab = preg_grep ('/^\s*#/',$fstab,PREG_GREP_INVERT); $fstab = preg_grep ('/\secryptfs\s/',$fstab); sort($fstab); $mtab = file('/etc/mtab'); $mtab = preg_grep ('/^\s*#/',$mtab,PREG_GREP_INVERT); $mtab = preg_grep ('/\secryptfs\s/',$mtab); sort($mtab); echo '<table class="ui-table-outline">'; echo '<thead>'; echo '<tr>'; echo '<th colspan="3" class="ui-state-default ui-widget-header">eCryptfs Mount Points</th>'; echo '</tr>'; echo '<tr class="ui-header">'; echo '<th width="50%">Mountpoint</th>'; echo '<th width="50%">Mounted</th>'; echo '</tr>'; echo '</thead>'; echo '<tbody>'; foreach($fstab as $num => $line){ $fields = preg_split('/\s+/',$line); $ck = preg_quote($fields[0],'/'); $is_mounted = count(preg_grep("/^$ck\s/",$mtab)); echo '<tr>'; echo '<td>'.htmlspecialchars($fields[1]).'</td>'; if($is_mounted){ echo '<td style="color: green">mounted</td>'; }else{ if($haspass && $this->_mount($fields[1])){ echo '<td style="color: green">now mounted</td>'; }else{ echo '<td style="color: red">not mounted</td>'; } } echo '</tr>'; } echo '<tbody>'; echo '</table>'; echo '<form action="" method="POST">'; echo '<fieldset>'; echo '<legend>Provide passphrase</legend>'; echo '<input type="password" name="pass" style="display:inline" />'; echo '<input type="submit" value="mount" style="display:inline" />'; echo '</fieldset>'; echo '</form>'; } function _passadd($pass){ $fstab = file('/etc/fstab'); $fstab = preg_grep ('/^\s*#/',$fstab,PREG_GREP_INVERT); $fstab = preg_grep ('/\secryptfs\s/',$fstab); sort($fstab); $mtab = file('/etc/mtab'); $mtab = preg_grep ('/^\s*#/',$mtab,PREG_GREP_INVERT); $mtab = preg_grep ('/\secryptfs\s/',$mtab); sort($mtab); $fh = popen('/usr/bin/ecryptfs-add-passphrase --fnek -','w'); if(!$fh) { echo '<p class="err">Failed to run the <code>ecryptfs-add-passphrase</code> command.</p>'; return false; } fwrite($fh,$pass); $ok = pclose($fh); if($ok !== 0){ echo '<p class="err">Something went wrong during passphrase add.</p>'; return false; } echo '<p class="err">Passphrase added to kernel keyring.</p>'; return true; } function _mount($mp){ $ok = 0; $out = array(); exec('/bin/mount -i '.escapeshellarg($mp),$out,$ok); if($ok == 0){ return true; }else{ return false; } } function index(){ ob_start(); if(!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] != 'on'){ echo '<p class="err">Please access this page via <a href="https://'.$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI'].'">HTTPS</a> only</p>'; }else{ $haspass = false; if(isset($_POST['pass']) && $_POST['pass']){ $haspass = $this->_passadd($_POST['pass']); } $this->_list_mounts($haspass); } $content = ob_get_contents(); ob_end_clean(); $this->_renderfull($content); } }
Once installed, you can access it at https://b3/admin/ecryptfs.php 1). It lists all eCryptfs mount points from /etc/fstab
and lets you mount them by providing the needed passphrase. If all your mounts use the same passphrase they will be mounted all at once. If you used different passphrases you need to supply them one by one.