From: Mark Wooding Date: Tue, 18 Sep 2012 19:29:26 +0000 (+0100) Subject: Allow explicit selection of recovery instances. X-Git-Tag: 0.99.2~17 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~mdw/git/distorted-keys/commitdiff_plain/ae0eb8989b3100de7b410f0cbffbee48495b9591 Allow explicit selection of recovery instances. Also improve reporting of recovery instances. --- diff --git a/cryptop.recover b/cryptop.recover index 26142e9..c4b1e7f 100755 --- a/cryptop.recover +++ b/cryptop.recover @@ -28,15 +28,24 @@ case "${KEYSLIB+t}" in t) ;; *) echo >&2 "$0: KEYSLIB unset"; exit 1 ;; esac . "$KEYSLIB"/keyfunc.sh defhelp <&2 "$quis: unknown key \`$key'"; exit 1; fi +checkword "recovery instance" "$inst" checkword "recovery key label" "$recov" case $kowner in $USERV_USER) ;; @@ -58,7 +67,7 @@ if [ -f $knub ]; then fi umask 077 -recover $recov $kowner/$klabel >$knub.new +recover $recov $inst $kowner/$klabel >$knub.new nubbin=$(nubid <$knub.new) case "$nubbin" in "$nubid") ;; diff --git a/keyfunc.sh.in b/keyfunc.sh.in index 02bc10d..6cba169 100644 --- a/keyfunc.sh.in +++ b/keyfunc.sh.in @@ -612,21 +612,23 @@ stash () { } recover () { - recov=$1 label=$2 + recov=$1 inst=$2 label=$3 ## Recover a stashed secret, protected by RECOV and stored as LABEL, and ## write it to stdout. checkword "recovery key label" "$recov" + checkword "recovery instance" "$inst" checklabel "secret" "$label" - rdir=$KEYS/recov/$recov/current + rdir=$KEYS/recov/$recov/$inst if [ ! -f $rdir/$label.recov ]; then - echo >&2 "$quis: no blob for \`$label' under recovery key \`$recov'" + echo >&2 "$quis: no blob for \`$label' under recovery key \`$recov/$inst'" exit 1 fi reqsafe - nub=$SAFE/keys.reveal/$recov.current/nub + tag=$recov.$inst + nub=$SAFE/keys.reveal/$tag/nub if [ ! -f $nub ]; then - echo >&2 "$quis: current recovery key \`$recov' not revealed" + echo >&2 "$quis: current recovery key \`$recov/$inst' not revealed" exit 1; fi mktmp diff --git a/keys.list-keepers b/keys.list-keepers index 399d765..297c83e 100755 --- a/keys.list-keepers +++ b/keys.list-keepers @@ -34,53 +34,91 @@ HELP case $# in 0) ;; *) usage_err ;; esac +## Collect information about available recovery keys. if [ -d $KEYS/recov ]; then cd $KEYS/recov + + ## No keeper sets encountered yet. kk=: - for r in $(find . -type l -name current -print); do - r=${r#./}; r=${r%/current} - if ! expr >/dev/null "Q$r" : "Q$R_LABEL"; then continue; fi - set _ $(echo $r | md5sum); rh=$2 - eval rcur_$rh=$(readlink $r/current) r_$rh=\$r + + ## Iterate over recovery keys. + for r in *; do + if [ ! -d $r ]; then continue; fi + + ## Now work through the instances of this recovery key. for ri in $r/*; do + + ## Get the instance number. i=${ri##*/} case "$i" in *[!0-9]*) continue ;; esac + + ## Read the keeper sharing parameters. for kp in $ri/*.param; do + + ## Find the keeper name. k=${kp##*/}; k=${k%.param} + + ## Add this keeper to the list if we haven't already, and clear the + ## list of associated recovery keys. case $kk in *:$k:*) ;; *) kk=$kk$k:; unset rr_$k ;; esac - eval t_$k_$rh_$i='$(sharethresh $kp)' - eval "rr_$k=\${rr_$k+\$rr_$k }$rh/$i" + + ## Associate this recovery key instance with the keeper set, and + ## store information about the sharing. + eval t_$k_$r_$i='$(sharethresh $kp)' + eval "rr_$k=\${rr_$k+\$rr_$k }$r/$i" done done done fi +## Now work through the keeper sets. if [ ! -d $KEYS/keeper ]; then echo >&2 "$quis: no keepers" else cd $KEYS/keeper + + ## Iterate over the keeper sets. + firstp=t for k in *; do + + ## Make sure that this really looks like a keeper set. checkword "keeper set label" "$k" if [ ! -r $k/meta ]; then continue; fi + + ## Read the keeper metadata, and print basic stuff about it. read n hunoz <$k/meta readmeta $k/0 + case $firstp in t) firstp=nil ;; nil) echo ;; esac echo "$k profile=$profile n=$n" + + ## Print the sharing information, including the keeper nubids. echo " share" i=0; while [ $i -lt $n ]; do nubid=$(cat $k/$i/nubid) echo " $i nubid=$nubid" i=$(( $i + 1 )) done + + ## Print the associated recovery keys. echo " recov" eval rr=\$rr_$k for ri in $rr; do - rh=${ri%/*} i=${ri##*/} - eval r=\$r_$rh - eval t=\$t_$k_$rh_$i + + ## Pick out the hash and instance number, and extract the rest of the + ## data from this recovery key. + r=${ri%/*} i=${ri##*/} + eval t=\$t_$k_$r_$i + + ## Start assembling an information line. info="$r/$i t=$t" - set $(echo $r/$i | tr / .) revealed - eval rcur=\$rcur_$rh - case $rcur in $i) set "$@" $(echo $r/current | tr / .) current ;; esac + + ## Determine the revelation status of the recovery key. There are + ## maybe things to check: the revelation of the key by explicit + ## instance, or, if applicable, as the current instance. Build in the + ## positional parameters a sequence of DIR WHAT pairs to process. + set $r.$i revealed + eval rcur=\$rcur_$r + case $rcur in $i) set "$@" $r.current current ;; esac while [ $# -gt 0 ]; do rd=$SAFE/keys.reveal/$1 attr=$2; shift 2 if [ ! -d $rd ]; then @@ -96,6 +134,8 @@ else info="$info $attr=$ss" fi done + + ## Print this information. echo " $info" done done diff --git a/keys.list-recov b/keys.list-recov index 38ab00f..24978aa 100755 --- a/keys.list-recov +++ b/keys.list-recov @@ -34,32 +34,47 @@ HELP case $# in 0) ;; *) usage_err ;; esac +## Work through the recovery keys. if [ ! -d $KEYS/recov ]; then echo 2>&1 "$quis: no recovery keys" else cd $KEYS/recov firstp=t - for r in $(find . -type l -name current -print); do - r=${r#./}; r=${r%/current} - if ! expr >/dev/null "Q$r" : "Q$R_LABEL"; then continue; fi - unset ri + for r in *; do + if [ ! -d $r ]; then continue; fi + + ## Start printing a record for this key. case $firstp in t) firstp=nil ;; nil) echo ;; esac echo "$r" + + ## Print information about the configured keeper set. echo " keepers" while read k t; do read n hunoz <$KEYS/keeper/$k/meta echo " $k t=$t n=$n" done <$r/keepers + + ## Print information about the various instances. rcur=$(readlink $r/current) for ri in $r/*; do + + ## Extract and check the instance number. i=${ri##*/} case "$i" in *[!0-9]*) continue ;; esac + + ## Start printing a subrecord. echo " instance $i" + + ## If this is the current instance, mention this. case "$rcur" in $i) echo " current" ;; esac + + ## Print basic facts about the instance. readmeta $ri/store nubid=$(cat $ri/store/nubid) echo " profile $profile" echo " nubid $nubid" + + ## Print information about the keepers, including sharing stuff. echo " keepers" for kp in $ri/*.param; do k=${kp##*/}; k=${k%.param} @@ -67,6 +82,9 @@ else t=$(sharethresh $kp) echo " $k t=$t n=$n" done + + ## Print information about secrets protected by this recovery key + ## instance. anyp=nil for sf in $(cd $ri; find . -type f -name '*.recov' -print); do s=${sf#./} diff --git a/keys.recover b/keys.recover index 2c48be8..cb4c816 100755 --- a/keys.recover +++ b/keys.recover @@ -28,19 +28,28 @@ case "${KEYSLIB+t}" in t) ;; *) echo >&2 "$0: KEYSLIB unset"; exit 1 ;; esac . "$KEYSLIB"/keyfunc.sh defhelp <&2 "$0: KEYSLIB unset"; exit 1 ;; esac . "$KEYSLIB"/keyfunc.sh defhelp <&2 "$quis: unknown keeper set \`$keeper'" exit 1 fi -if [ ! -d $KEYS/recov/$recov ]; then +if [ ! -l $KEYS/recov/$recov/current ]; then echo >&2 "$quis: unknown recovery key \`$recov'" exit 1 fi -if [ ! -f $KEYS/recov/$recov/$keeper.param ]; then +rdir=$KEYS/recov/$recov/$inst +if [ ! -f $rdir/$keeper.param ]; then echo >&2 "$quis: recovery key \`$recov' not kept by keeper set \`$keeper'" exit 1 fi @@ -64,16 +71,16 @@ mktmp cat >$tmp/secret ## Read the threshold from the recovery metadata. -t=$(sharethresh $KEYS/recov/$recov/$keeper.param) +t=$(sharethresh $rdir/$keeper.param) ## Find out which keeper index it corresponds to. -read n hunoz <$KEYS/keeper/$keeper/meta +read n hunoz <$kdir/meta i=0 foundp=nil while [ $i -lt $n ]; do - c_sysprepare $KEYS/keeper/$keeper/$i + c_sysprepare $kdir/$i nubbin=$(nubid <$tmp/secret) - nubid=$(cat $KEYS/keeper/$keeper/$i/nubid) + nubid=$(cat $kdir/$i/nubid) case "$nubbin" in "$nubid") foundp=t; break ;; esac i=$(( $i + 1 )) done @@ -84,13 +91,13 @@ esac ## Establish the recovery staging area. See whether we've done enough ## already. reqsafe -tag=$(echo $recov | tr / .) +tag=$recov.$inst mkdir -p -m700 $SAFE/keys.reveal reveal=$SAFE/keys.reveal/$tag if [ ! -d $reveal ]; then mkdir -m700 $reveal; fi cd $reveal if [ -f nub ]; then - echo >&2 "$quis: recovery key \`$recov' already revealed" + echo >&2 "$quis: recovery key \`$recov/$inst' already revealed" exit 1 fi @@ -99,8 +106,8 @@ umask 077 if [ -f $keeper.$i.share ]; then echo >&2 "$quis: share $i already revealed" else - c_sysdecrypt $KEYS/keeper/$keeper/$i $tmp/secret \ - <$KEYS/recov/$recov/$keeper.$i.share \ + c_sysdecrypt $kdir/$i $tmp/secret \ + <$rdir/$keeper.$i.share \ >$keeper.$i.new mv $keeper.$i.new $keeper.$i.share fi @@ -111,11 +118,11 @@ for j in $keeper.*.share; do if [ -f "$j" ]; then n=$(( $n + 1 )); fi; done if [ $n -lt $t ]; then echo >&2 "$quis: share $i revealed; $(( $t - $n )) more required" else - cat $KEYS/recov/$recov/$keeper.param $keeper.*.share >$keeper.shares + cat $rdir/$keeper.param $keeper.*.share >$keeper.shares $bindir/shamir recover <$keeper.shares >nub.new - c_sysprepare $KEYS/recov/$recov/store + c_sysprepare $rdir/store nubbin=$(nubid &2 "$quis: recovery key \`$recov' revealed" + echo >&2 "$quis: recovery key \`$recov/$inst' revealed" fi ###----- That's all, folks --------------------------------------------------