chiark / gitweb /
cryptop.list: New tool for listing keys.
[distorted-keys] / keys.reveal
1 #! /bin/sh
2 ###
3 ### Reveal shares of a secret distributed among keepers
4 ###
5 ### (c) 2011 Mark Wooding
6 ###
7
8 ###----- Licensing notice ---------------------------------------------------
9 ###
10 ### This file is part of the distorted.org.uk key management suite.
11 ###
12 ### distorted-keys is free software; you can redistribute it and/or modify
13 ### it under the terms of the GNU General Public License as published by
14 ### the Free Software Foundation; either version 2 of the License, or
15 ### (at your option) any later version.
16 ###
17 ### distorted-keys is distributed in the hope that it will be useful,
18 ### but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 ### GNU General Public License for more details.
21 ###
22 ### You should have received a copy of the GNU General Public License
23 ### along with distorted-keys; if not, write to the Free Software Foundation,
24 ### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25
26 set -e
27 case "${KEYSLIB+t}" in t) ;; *) echo >&2 "$0: KEYSLIB unset"; exit 1 ;; esac
28 . "$KEYSLIB"/keyfunc.sh
29
30 defhelp <<HELP
31 RECOV KEEPER [NUB]
32 Reveal a share of a recovery key distributed among keepers.
33
34 If enough shares have been revealed, reconstruct the recovery private key.
35 The keeper nub is read from NUB, or stdin if NUB is omitted or \`-'.
36 HELP
37
38 ## Parse the command line.
39 case $# in
40   2) if [ -t 0 ]; then echo >&2 "$quis: stdin is a terminal"; exit 1; fi ;;
41   3) ;;
42   *) usage_err ;;
43 esac
44 recov=$1 keeper=$2; shift 2
45 checklabel "recovery key" "$recov"
46 case "$recov" in
47   */*) ;;
48   *) recov=$recov/current ;;
49 esac
50 checkword "keeper set label" "$keeper"
51
52 ## Check that this is a sensible thing to do.
53 if [ ! -f $KEYS/keeper/$keeper/meta ]; then
54   echo >&2 "$quis: unknown keeper set \`$keeper'"
55   exit 1
56 fi
57 if [ ! -d $KEYS/recov/$recov ]; then
58   echo >&2 "$quis: unknown recovery key \`$recov'"
59   exit 1
60 fi
61 if [ ! -f $KEYS/recov/$recov/$keeper.param ]; then
62   echo >&2 "$quis: recovery key \`$recov' not kept by keeper set \`$keeper'"
63   exit 1
64 fi
65
66 ## Grab the key, because we'll need to read it several times.
67 mktmp
68 cat -- "$@" >$tmp/secret
69
70 ## Read the threshold from the recovery metadata.
71 read param <$KEYS/recov/$recov/$keeper.param
72 case "$param" in
73   shamir-params:*) ;;
74   *)
75     echo >&2 "$quis: secret sharing parameter file damaged (wrong header)"
76     exit 1
77     ;;
78 esac
79 t=";${param#*:}"
80 case "$t" in
81   *";t="*) ;;
82   *)
83     echo >&2 "$quis: secret sharing parameter file damaged (missing t)"
84     exit 1
85     ;;
86 esac
87 t=${t#*;t=}
88 t=${t%%;*}
89
90 ## Find out which keeper index it corresponds to.
91 read n hunoz <$KEYS/keeper/$keeper/meta
92 i=0
93 foundp=nil
94 while [ $i -lt $n ]; do
95   c_sysprepare $KEYS/keeper/$keeper/$i
96   nubbin=$(nubid <$tmp/secret)
97   nubid=$(cat $KEYS/keeper/$keeper/$i/nubid)
98   case "$nubbin" in "$nubid") foundp=t; break ;; esac
99   i=$(( $i + 1 ))
100 done
101 case $foundp in
102   nil) echo >&2 "$quis: nub doesn't match keeper \`$keeper'"; exit 1 ;;
103 esac
104
105 ## Establish the recovery staging area.  See whether we've done enough
106 ## already.
107 reqsafe
108 tag=$(echo $recov | tr / .)
109 mkdir -p -m700 $SAFE/keys.reveal
110 reveal=$SAFE/keys.reveal/$tag
111 if [ ! -d $reveal ]; then mkdir -m700 $reveal; fi
112 cd $reveal
113 if [ -f nub ]; then
114   echo >&2 "$quis: recovery key \`$recov' already revealed"
115   exit 1
116 fi
117
118 ## Decrypt the share.
119 umask 077
120 if [ -f $keeper.$i.share ]; then
121   echo >&2 "$quis: share $i already revealed"
122 else
123   c_sysdecrypt $KEYS/keeper/$keeper/$i $tmp/secret \
124     <$KEYS/recov/$recov/$keeper.$i.share \
125     >$keeper.$i.new
126   mv $keeper.$i.new $keeper.$i.share
127 fi
128
129 ## See if there's enough for a recovery.
130 n=0
131 for j in $keeper.*.share; do if [ -f "$j" ]; then n=$(( $n + 1 )); fi; done
132 if [ $n -lt $t ]; then
133   echo >&2 "$quis: share $i revealed; $(( $t - $n )) more required"
134 else
135   cat $KEYS/recov/$recov/$keeper.param $keeper.*.share >$keeper.shares
136   $bindir/shamir recover <$keeper.shares >nub.new
137   c_sysprepare $KEYS/recov/$recov/store
138   nubbin=$(nubid <nub.new)
139   nubid=$(cat $KEYS/recov/$recov/store/nubid)
140   case "$nubbin" in
141     "$nubid") ;;
142     *)
143       echo >&2 "$quis: recovered nub doesn't match stored hash"
144       exit 1
145       ;;
146   esac
147   mv nub.new nub
148   rm -f $keeper.*
149   echo >&2 "$quis: recovery key \`$recov' revealed"
150 fi
151
152 ###----- That's all, folks --------------------------------------------------