trefactoring of the way password and keys are handled internally - tomb - the crypto undertaker
 (HTM) git clone git://parazyd.org/tomb.git
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 5158c380fefa46396ce3f2ec6ca6b994384de7d2
 (DIR) parent 534476a84988dc08ac1c7678d74651b880306aba
 (HTM) Author: Jaromil <jaromil@dyne.org>
       Date:   Wed,  6 Aug 2014 07:43:25 +0200
       
       refactoring of the way password and keys are handled internally
       
       tthis change uses an hidden global variable within tomb to store the
       decrypted key material, avoiding using one tempfile in RAM, avoiding
       running the decryption more than once (which means sanity for KDF
       usage) and overall simplifying the code also avoiding duplicates.
       
       Diffstat:
         M extras/test/runtests                |      19 ++++++++++++++++++-
         M tomb                                |     117 +++++++++----------------------
       
       2 files changed, 51 insertions(+), 85 deletions(-)
       ---
 (DIR) diff --git a/extras/test/runtests b/extras/test/runtests
       t@@ -39,7 +39,7 @@ typeset -A results
        tests=(dig forge lock badpass open close passwd chksum bind setkey)
        { test $RESIZER = 1 } && { tests+=(resize) }
        { test $KDF = 1 } && { tests+=(kdforge kdfpass kdflock kdfopen) }
       -{ test $STEGHIDE = 1 } && { tests+=(stgin stgout stgopen) }
       +{ test $STEGHIDE = 1 } && { tests+=(stgin stgout stgopen stgpipe stgimpl) }
        { test $QRENCODE = 1 } && { tests+=(qrenc) }
        
        sudo rm -f /tmp/test.tomb{,.key}
       t@@ -225,10 +225,27 @@ fi
            { test $? = 0 } && { results+=(stgopen SUCCESS) }
        
            ${T} close test
       +
       +    # test piping keys using -k -
       +    tkey=`tt --unsecure-dev-mode --tomb-pwd ${dummypass} exhume /tmp/tomb.jpg`
       +    print "$tkey" | tt --unsecure-dev-mode --tomb-pwd ${dummypass} open -k - /tmp/test.tomb
       +    { test $? = 0 } && { results+=(stgpipe SUCCESS) }
       +
       +    ${T} close test
       +
       +
       +    notice "test using open -k image.jpeg"
       +
       +    tt --unsecure-dev-mode --tomb-pwd ${dummypass} open -k /tmp/tomb.jpg /tmp/test.tomb 
       +    { test $? = 0 } && { results+=(stgimpl SUCCESS) }
       +
       +    ${T} close test
        }
        
        { test $QRENCODE = 1 } && {
        
       +    notice "test rendering a QR printable key backup"
       +
            tt engrave -k /tmp/test.tomb.key
        
            { test $? = 0 } && { results+=(qrenc SUCCESS) }
 (DIR) diff --git a/tomb b/tomb
       t@@ -64,6 +64,8 @@ typeset -h _uid
        typeset -h _gid
        typeset -h _tty
        
       +typeset -H tomb_secret
       +
        # Make sure sbin is in PATH
        PATH+=:/sbin:/usr/sbin
        
       t@@ -469,6 +471,8 @@ function _warning  no() {
        function _failure die() {
            typeset -i exitcode=${2:-1}
            option_is_set -q || _msg failure "$1"
       +    # be sure we forget the secrets we were told
       +    unset tomb_secret
            exit $exitcode
        }
        
       t@@ -603,9 +607,9 @@ gpg_decrypt() {
            if [ "$gpgver" = "1.4.11" ]; then
                _verbose "GnuPG is version 1.4.11 - adopting status fix."
        
       -        print "$lukspass" | \
       +        tomb_secret=`print "$lukspass" | \
                    gpg --batch --passphrase-fd 0 --no-tty --no-options \
       -            -d "${keyfile}"
       +            -d "${keyfile}"`
                ret=$?
                unset lukspass
        
       t@@ -616,10 +620,10 @@ gpg_decrypt() {
                    unset lukspass;
                    _failure "Fatal error creating temp file." }
        
       -        print "$lukspass" | \
       +        tomb_secret=`print "$lukspass" | \
                    gpg --batch --passphrase-fd 0 --no-tty --no-options \
                    --status-fd 2 --no-mdc-warning --no-permission-warning \
       -            --no-secmem-warning -d "${keyfile}" 2> $res
       +            --no-secmem-warning -d "${keyfile}" 2> $res`
        
                unset lukspass
                grep 'DECRYPTION_OKAY' $res > /dev/null
       t@@ -651,7 +655,7 @@ ask_key_password() {
                        return 1
                    fi
        
       -            check_lukskey "$tombpass" "$tombkey"
       +            get_lukskey "$tombpass" "$tombkey"
        
                    if [ $? = 0 ]; then
                        passok=1; _message "Password OK."
       t@@ -664,16 +668,16 @@ ask_key_password() {
                tombpass="$2"
                _verbose "ask_key_password with tombpass: $tombpass"
        
       -        check_lukskey "$tombpass" "$tombkey"
       +        get_lukskey "$tombpass" "$tombkey"
        
                if [ $? = 0 ]; then
                    passok=1; _message "Password OK."; fi
        
            fi
       -
       -    { test "$passok" = "1" } || { return 1 }
       +    # print the password out in case caller needs to know it
            print "$tombpass"
            unset tombpass
       +    { test "$passok" = "1" } || { return 1 }
            return 0
        }
        
       t@@ -695,9 +699,9 @@ change_passwd() {
            if option_is_set --tomb-old-pwd; then
                tomb_old_pwd="`option_value --tomb-old-pwd`"
                _verbose "--tomb-old-pwd = $tomb_old_pwd"
       -        tombpass=`ask_key_password "$keyfile" "$tomb_old_pwd"`
       +        ask_key_password "$keyfile" "$tomb_old_pwd" > /dev/null
            else
       -        tombpass=`ask_key_password "$keyfile"`
       +        ask_key_password "$keyfile" > /dev/null
            fi
        
            { test $? = 0 } || {
       t@@ -705,7 +709,7 @@ change_passwd() {
        
            # danger zone in which the key is written in clear
        
       -    get_lukskey "$tombpass" "$keyfile" > "$lukskey"
       +    print "$tomb_secret"> "$lukskey"
        
            drop_key
        
       t@@ -789,54 +793,6 @@ print "-----END PGP MESSAGE-----"
        }
        
        
       -# This function checks if the password effectively works to decrypt
       -# the key. It is used by the password prompt to verify validity and
       -# it resembles get_lukskey(). 1st arg the password, 2nd the keyfile
       -check_lukskey() {
       -    local lukspass="$1"
       -    local keyfile="$2"
       -    local exhumedkey
       -
       -    firstline=`head -n1 $keyfile`
       -    _verbose "check_lukskey XXX $keyfile"
       -
       -
       -    # key is KDF encoded
       -    if [[ $firstline =~ '^_KDF_' ]]; then
       -        _verbose "KDF: `cut -d_ -f 3 <<<$firstline`"
       -        case `cut -d_ -f 3 <<<$firstline` in
       -            pbkdf2sha1)
       -                pbkdf2_param=`cut -d_ -f 4- <<<$firstline | tr '_' ' '`
       -                lukspass=$(tomb-kdb-pbkdf2 ${=pbkdf2_param} 2> /dev/null <<<$lukspass)
       -                ;;
       -            *)
       -                _failure "No suitable program for KDF `cut -f 3 <<<$firstline`."
       -                unset lukspass
       -                return 1
       -                ;;
       -        esac
       -
       -    # key needs to be exhumed from an image
       -    elif [[ `file "$keyfile"` =~ "JP.G" ]]; then
       -        exhumedkey="`safe_filename exhumedkey`"
       -        _verbose "lukspass in check_lukskey: $lukspass"
       -
       -        exhume_key "$keyfile" "$lukspass" "$exhumedkey"
       -        keyfile="$exhumedkey"
       -    fi
       -    _verbose "lukspass in check_lukskey: $lukspass"
       -
       -    # check validity, eventually repair adding headers
       -    is_valid_key "$keyfile" || {
       -        _failure "This key is unusable: $keyfile" }
       -
       -    # prints out decrypted content to stdout
       -    gpg_decrypt "$lukspass" "$keyfile" > /dev/null
       -    ret="$?"
       -    _verbose "check_lukskey returns $ret"
       -    return $ret
       -}
       -
        
        # Gets a key file and a password, prints out the decoded contents to
        # be used directly by Luks as a cryptographic key
       t@@ -879,7 +835,7 @@ get_lukskey() {
            is_valid_key "$keyfile" || {
                _failure "This key is unusable: $keyfile" }
        
       -    # prints out decrypted content to stdout
       +    # saves decrypted content into $tomb_secret
            gpg_decrypt "$lukspass" "$keyfile"
        
            ret="$?"
       t@@ -1365,9 +1321,9 @@ lock_tomb_with_key() {
            if option_is_set --tomb-pwd; then
                tomb_pwd="`option_value --tomb-pwd`"
                _verbose "--tomb-pwd = $tomb_pwd"
       -        tombpass=`ask_key_password "$tombkey" "$tomb_pwd"`
       +        ask_key_password "$tombkey" "$tomb_pwd" > /dev/null
            else
       -        tombpass=`ask_key_password "$tombkey"`
       +        ask_key_password "$tombkey" > /dev/null
            fi
            { test $? = 0 } || {
                losetup -d ${nstloop}
       t@@ -1376,29 +1332,26 @@ lock_tomb_with_key() {
            _success "Locking ${tombfile} with ${tombkey}"
        
            _message "Formatting Luks mapped device."
       -    get_lukskey "${tombpass}" ${tombkey} | \
       +    print "$tomb_secret" | \
                cryptsetup --key-file -   --batch-mode \
                --cipher ${cipher} --key-size 256 --key-slot 0 \
                luksFormat ${nstloop}
            if ! [ $? = 0 ]; then
                _warning "cryptsetup luksFormat returned an error."
       -        unset tombpass
                losetup -d $nstloop
                _failure "Operation aborted."
            fi
        
       -    get_lukskey "${tombpass}" ${tombkey} | \
       +    print "$tomb_secret" | \
                cryptsetup --key-file - \
                --cipher ${cipher} luksOpen ${nstloop} tomb.tmp
            if ! [ $? = 0 ]; then
                _warning "cryptsetup luksOpen returned an error."
       -        unset tombpass
                losetup -d $nstloop
                _failure "Operation aborted."
            fi
        
            # cleanup tombs
       -    unset tombpass
            drop_key # make sure all temp files are out
        
            _message "Formatting your Tomb with Ext3/Ext4 filesystem."
       t@@ -1459,35 +1412,35 @@ change_tomb_key() {
            if option_is_set --tomb-pwd; then
                tomb_new_pwd="`option_value --tomb-pwd`"
                _verbose "--tomb-pwd = $tomb_new_pwd"
       -        newkeypass=`ask_key_password "$newkey" "$tomb_new_pwd"`
       +        ask_key_password "$newkey" "$tomb_new_pwd" > /dev/null 
            else
       -        newkeypass=`ask_key_password "$newkey"`
       +        ask_key_password "$newkey" > /dev/null
            fi
            { test $? = 0 } || {
                _failure "No valid password supplied for the new key." }
            newkeyfile="`safe_filename newkey`"
       -    get_lukskey "$newkeypass" "$newkey" > $newkeyfile
       +    print "$tomb_secret" > $newkeyfile
        
        
            # load the old key
            if option_is_set --tomb-old-pwd; then
                tomb_old_pwd="`option_value --tomb-old-pwd`"
                _verbose "--tomb-old-pwd = $tomb_old_pwd"
       -        oldkeypass=`ask_key_password "$oldkey" "$tomb_old_pwd"`
       +        ask_key_password "$oldkey" "$tomb_old_pwd" > /dev/null
            else
       -        oldkeypass=`ask_key_password "$oldkey"`
       +        ask_key_password "$oldkey" > /dev/null
            fi
            { test $? = 0 } || {
                _failure "No valid password supplied for the old key." }
        
            # luksOpen the tomb (not really mounting, just on the loopback)
       -    get_lukskey "$oldkeypass" "$oldkey" | \
       +    print "$tomb_secret" | \
                cryptsetup --key-file - luksOpen ${nstloop} ${mapper}
            { test $? = 0 } || {
                losetup -d "$nstloop"
                _failure "Unexpected error in luksOpen." }
        
       -    get_lukskey "$oldkeypass" "$oldkey" | \
       +    print "$tomb_secret"| \
                cryptsetup --key-file - luksChangeKey "$nstloop" "$newkeyfile"
            { test $? = 0 } || {
                losetup -d "$nstloop"
       t@@ -1501,8 +1454,6 @@ change_tomb_key() {
                _failure "Unexpected error in luksClose." }
        
            drop_key
       -    unset oldkeypass
       -    unset newkeypass
            losetup -d ${nstloop}
        
            _success "Succesfully changed key for tomb: $2"
       t@@ -1645,20 +1596,19 @@ mount_tomb() {
            if option_is_set --tomb-pwd; then
                tomb_pwd="`option_value --tomb-pwd`"
                _verbose "--tomb-pwd = $tomb_pwd"
       -        tombpass=`ask_key_password "$tombkey" "$tomb_pwd"`
       +        ask_key_password "$tombkey" "$tomb_pwd" > /dev/null
            else
       -        tombpass=`ask_key_password "$tombkey"`
       +        ask_key_password "$tombkey" > /dev/null
            fi
            { test $? = 0 } || {
                losetup -d ${nstloop}
                _failure "No valid password supplied." }
        
       -    get_lukskey "${tombpass}" ${tombkey} | \
       +    print "$tomb_secret" | \
                cryptsetup --key-file - luksOpen ${nstloop} ${mapper}
        
            # key dropped here
            drop_key
       -    unset tombpass
        
            if ! [ -r /dev/mapper/${mapper} ]; then
                losetup -d ${nstloop}
       t@@ -2173,9 +2123,9 @@ resize_tomb() {
            if option_is_set --tomb-pwd; then
                tomb_pwd="`option_value --tomb-pwd`"
                _verbose "--tomb-pwd = $tomb_pwd"
       -        tombpass=`ask_key_password "$tombkey" "$tomb_pwd"`
       +        ask_key_password "$tombkey" "$tomb_pwd" > /dev/null
            else
       -        tombpass=`ask_key_password "$tombkey"`
       +        ask_key_password "$tombkey" > /dev/null
            fi
            { test $? = 0 } || {
                _failure "No valid password supplied." }
       t@@ -2190,11 +2140,10 @@ resize_tomb() {
            local mapdate=`date +%s`
            local mapper="tomb.${tombname}.${mapdate}.`basename $nstloop`"
        
       -    get_lukskey "${tombpass}" ${tombkey} | \
       +    print "$tomb_secret" | \
                cryptsetup --key-file - luksOpen ${nstloop} ${mapper}
        
            drop_key # cleanup after load_key
       -    unset tombpass
        
            if ! [ -r /dev/mapper/${mapper} ]; then
                losetup -d ${nstloop}