Hi, First, I want to say that you project seems really cool. Standardizing encrypted disk setup is an important step towards information confidentiality. Have you thought about adding the possibility to enter the passphrase remotely when the system boots ? It would be very useful for servers for which physical access is not easy. I have done an implementation of this a few years ago. It uses a first non encrypted base system that sets up the network interface and runs ssh. Then, when booted, it waits for the administrator to start a script that asks for the passphrase, mount the crypted disks (including the new root) and calls a pivot_root to switch to the new system. If you ever think of distributing this, I suggest to implement this as an initrd (which I haven't done). Some scripts should be made to update the content of the initrd (ssh, root password, ssh keys) easily. Here is the code. There are probably bugs and security issues, so please consider it alpha. The first program is written in C and should be used instead of /bin/init. The following are helper scripts that runs in the base unencrypted root. The "startsys" program should probably be written in C so we can be sure that the KEY variable is wiped from memory. Mathieu ---- /* cryptwait.c * * Daemon that takes PID 1, fork and start a script, and wait for a signal to * execute init. * * Copyright 2005 - Mathieu Desnoyers * * Licensed under GPLv2. */ #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <stdio.h> #include <signal.h> /* signal handler */ void handler(int signo) { printf("received signal killing all \n"); kill(-1, SIGKILL); wait(NULL); printf("all killed exec /sbin/init\n "); execl("/sbin/init","init",(char*)NULL); } void sigchild_handler(int signo) { wait(NULL); } int main(int argc, char ** argv) { pid_t pid; static struct sigaction act, child_act; pid = fork(); if(pid == 0) { /* child : executes script */ execl("/bin/sh","sh","/root/waitssh",(char*)NULL); } else if( pid > 0) { /* parent : wait for signal. */ act.sa_handler = handler; sigemptyset(&(act.sa_mask)); sigaddset(&(act.sa_mask), SIGUSR1); sigaction(SIGUSR1, &act, NULL); child_act.sa_handler = sigchild_handler; sigemptyset(&(child_act.sa_mask)); sigaddset(&(child_act.sa_mask), SIGCHLD); sigaction(SIGCHLD, &child_act, NULL); // Wait for signals.. forever... while(1) pause(); } else { /* error : exec init directly */ execl("/sbin/init","init",(char*)NULL); } return 0; } ---- #!/bin/sh # # waitssh # # Script ran in the unencrypted root : starts the network interfaces, ssh and a # local tty, waits for someone to log in. # # Mathieu Desnoyers 11/5/2005 - GPLv2 mount / -o remount,rw mount /proc /etc/init.d/hostname.sh # don't care about /etc/network/ifstate /etc/init.d/fullduplex ifup eth0 --force ifup eth1 --force /etc/init.d/ssh start while ((1)); do /sbin/getty 38400 tty1; done ---- #!/bin/sh # # startsys # # Script that asks from the passphrase, maps the dm-crypt partitions, mounts # them, kills all the running processes, pivots / to the crypted root and # signals the PID 1 (cryptwait) that the system is ready to execute /bin/init. # # Mathieu Desnoyers 11/5/2005 - GPLv2 MAPFROM=/dev/sda4 MAPNAME=_dev_sda4 MAPDEV=/dev/mapper/${MAPNAME} MAPFROM1=/dev/sda3 MAPNAME1=_dev_sda3 MAPDEV1=/dev/mapper/${MAPNAME1} #this is the VFS point where the new root must be mounted before the pivot CRYPTROOT=/mnt/cryptroot #this is the new VFS location of the old root in the VFS (as seen after pivot) BASEROOT=/mnt/baseroot #ask for all passphrases echo "Please enter the passphrase for all the filesystems" KEY=`/usr/sbin/hashalot sha256` #ask for / passphrase echo "Creating ${MAPFROM} mapping... " echo "${KEY}" | cryptsetup -c aes-cbc-essiv:sha256 -d /dev/stdin create ${MAPNAME} ${MAPFROM} echo -n "Mounting ${MAPDEV} filesystem... " mount ${MAPDEV} ${CRYPTROOT} if (( $? != 0 )); then cryptsetup remove ${MAPNAME} echo failed. exit -1 else echo success. fi #setting swap echo "Setting up swap.. " cryptsetup -c aes-cbc-essiv:sha256 -d /dev/urandom create ${MAPNAME1} ${MAPFROM1} mkswap ${MAPDEV1} #will remount it later... #umount ${CRYPTROOT} # stopping all services #for script in /etc/rc0.d/* #do # if ( [ x"${script}" != x"/etc/rc0.d/S90halt" ] && [ x"${script}" != x"/etc/rc0.d/S50mdadm-raid" ] && [ x"${script}" != x"/etc/rc0.d/S48cryptdisks" ] ) # then # #echo $script # $script stop # fi #done # #umount everything but / #umount /dev/pts #umount /sys ifdown eth0 ifdown eth1 umount /proc mount / -o remount,ro #/bin/bash #testing... #echo -n "Mounting ${MAPDEV} filesystem... " #mount ${MAPDEV} ${CRYPTROOT} #if (( $? != 0 )); then # echo -n "failed. rebooting..." # reboot #else # echo success. #fi echo -n "pivot_root to new root filesystem... " cd ${CRYPTROOT} pivot_root . ${CRYPTROOT}${BASEROOT} #remount baseroot rw for depmod -a mount / -o remount,rw echo finish. # starting services #echo -n "Starting services..." #for script in /etc/rcS.d/* #do # $script start #done # #for script in /etc/rc2.d/* #do # $script start #done #echo "Unmounting ${BASEROOT}" #exec chroot . sh -c "umount ${BASEROOT}; exec /sbin/init"\ # < /dev/console >/dev/console 2>&1 #S11remountbase will remount in rcS.d umount -l ${BASEROOT} #reset memory for KEY (256 bits) KEY=0000000000000000000000000000000000000000000000000000000000000000 echo -n "Sending signal to cryptwait" kill -s USR1 1 ---- #!/bin/sh # mountdrv # # Mounts the encrypted drives so they can be accessed from within the running # base unencrypted system. # # Mathieu Desnoyers 11/5/2005 - GPLv2 MAPFROM=/dev/sda4 MAPNAME=_dev_sda4 MAPDEV=/dev/mapper/${MAPNAME} #this is the VFS point where the new root must be mounted before the pivot CRYPTROOT=/mnt/cryptroot #this is the new VFS location of the old root in the VFS (as seen after pivot) BASEROOT=/mnt/baseroot #ask for all passphrases echo "Please enter the passphrase for all the filesystems" KEY=`/usr/sbin/hashalot sha256` #ask for / passphrase echo "Creating ${MAPFROM} mapping... " echo "${KEY}" | cryptsetup -c aes-cbc-essiv:sha256 -d /dev/stdin create ${MAPNAME} ${MAPFROM} echo -n "Mounting ${MAPDEV} filesystem... " mount ${MAPDEV} ${CRYPTROOT} if (( $? != 0 )); then cryptsetup remove ${MAPNAME} echo failed. exit -1 else echo success. fi ---- -- OpenPGP public key: http://krystal.dyndns.org:8080/key/compudj.gpg Key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68 --------------------------------------------------------------------- dm-crypt mailing list - http://www.saout.de/misc/dm-crypt/ To unsubscribe, e-mail: dm-crypt-unsubscribe@xxxxxxxx For additional commands, e-mail: dm-crypt-help@xxxxxxxx