chiark / gitweb /
Allow explicit selection of recovery instances.
authorMark Wooding <mdw@distorted.org.uk>
Tue, 18 Sep 2012 19:29:26 +0000 (20:29 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Tue, 18 Sep 2012 19:29:26 +0000 (20:29 +0100)
Also improve reporting of recovery instances.

cryptop.recover
keyfunc.sh.in
keys.list-keepers
keys.list-recov
keys.recover
keys.reveal

index 26142e9..c4b1e7f 100755 (executable)
@@ -28,15 +28,24 @@ case "${KEYSLIB+t}" in t) ;; *) echo >&2 "$0: KEYSLIB unset"; exit 1 ;; esac
 . "$KEYSLIB"/keyfunc.sh
 
 defhelp <<HELP
-KEY RECOV
+[-i INST] KEY RECOV
 Recover the named user KEY using a blob protected using the recovery key
 RECOV; it is an error if RECOV is not currently revealed.
 HELP
 
+inst=current
+while getopts "i:" opt; do
+  case "$opt" in
+    i) inst=$OPTARG ;;
+    *) usage_err ;;
+  esac
+done
+shift $(( $OPTIND - 1 ))
 case $# in 2) ;; *) usage_err ;; esac
 key=$1 recov=$2
 parse_keylabel "$key"
 if [ ! -d $kdir ]; then echo >&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") ;;
index 02bc10d..6cba169 100644 (file)
@@ -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
index 399d765..297c83e 100755 (executable)
@@ -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
index 38ab00f..24978aa 100755 (executable)
@@ -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#./}
index 2c48be8..cb4c816 100755 (executable)
@@ -28,19 +28,28 @@ case "${KEYSLIB+t}" in t) ;; *) echo >&2 "$0: KEYSLIB unset"; exit 1 ;; esac
 . "$KEYSLIB"/keyfunc.sh
 
 defhelp <<HELP
-RECOV LABEL
+[-i INST] RECOV LABEL
 Recover the secret LABEL using recovery key RECOV.
 
 The recovery key must be revealed.  The secret is written to stdout.
 HELP
 
 ## Parse the command line.
+inst=current
+while getopts "i:" opt; do
+  case "$opt" in
+    i) inst=$OPTARG ;;
+    *) usage_err ;;
+  esac
+done
+shift $(( $OPTIND - 1 ))
 case $# in 2) ;; *) usage_err ;; esac
 recov=$1 label=$2
-checklabel "recovery key label" "$recov"
+checkword "recovery instance" "$inst"
+checkword "recovery key label" "$recov"
 checklabel "secret" "$label"
 
 ## Do the recovery.
-recover $recov $label
+recover $recov $inst $label
 
 ###----- That's all, folks --------------------------------------------------
index 9e18879..9270b55 100755 (executable)
@@ -28,7 +28,7 @@ case "${KEYSLIB+t}" in t) ;; *) echo >&2 "$0: KEYSLIB unset"; exit 1 ;; esac
 . "$KEYSLIB"/keyfunc.sh
 
 defhelp <<HELP
-RECOV KEEPER
+[-i INST] RECOV KEEPER
 Reveal a share of a recovery key distributed among keepers.
 
 If enough shares have been revealed, reconstruct the recovery private key.
@@ -36,25 +36,32 @@ The keeper nub is read from stdin.
 HELP
 
 ## Parse the command line.
+inst=current
+while getopts "i:" opt; do
+  case "$opt" in
+    i) inst=$OPTARG ;;
+    *) usage_err ;;
+  esac
+done
+shift $(( $OPTIND - 1 ))
 case $# in 2) ;; *) usage_err ;; esac
 recov=$1 keeper=$2; shift 2
-checklabel "recovery key" "$recov"
-case "$recov" in
-  */*) ;;
-  *) recov=$recov/current ;;
-esac
+checkword "recovery instance" "$inst"
+checkword "recovery key" "$recov"
 checkword "keeper set label" "$keeper"
 
 ## Check that this is a sensible thing to do.
-if [ ! -f $KEYS/keeper/$keeper/meta ]; then
+kdir=$KEYS/keeper/$keeper
+if [ ! -f $kdir/meta ]; then
   echo >&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 <nub.new)
-  nubid=$(cat $KEYS/recov/$recov/store/nubid)
+  nubid=$(cat $rdir/store/nubid)
   case "$nubbin" in
     "$nubid") ;;
     *)
@@ -125,7 +132,7 @@ else
   esac
   mv nub.new nub
   rm -f $keeper.*
-  echo >&2 "$quis: recovery key \`$recov' revealed"
+  echo >&2 "$quis: recovery key \`$recov/$inst' revealed"
 fi
 
 ###----- That's all, folks --------------------------------------------------