chiark / gitweb /
debian: About time, really.
[distorted-keys] / keys.reveal
... / ...
CommitLineData
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
26set -e
27case "${KEYSLIB+t}" in t) ;; *) echo >&2 "$0: KEYSLIB unset"; exit 1 ;; esac
28. "$KEYSLIB"/keyfunc.sh
29
30defhelp <<HELP
31RECOV KEEPER [NUB]
32Reveal a share of a recovery key distributed among keepers.
33
34If enough shares have been revealed, reconstruct the recovery private key.
35The keeper nub is read from NUB, or stdin if NUB is omitted or \`-'.
36HELP
37
38## Parse the command line.
39case $# in
40 2) if [ -t 0 ]; then echo >&2 "$quis: stdin is a terminal"; exit 1; fi ;;
41 3) ;;
42 *) usage_err ;;
43esac
44recov=$1 keeper=$2; shift 2
45checklabel "recovery key" "$recov"
46case "$recov" in
47 */*) ;;
48 *) recov=$recov/current ;;
49esac
50checkword "keeper set label" "$keeper"
51
52## Check that this is a sensible thing to do.
53if [ ! -f $KEYS/keeper/$keeper/meta ]; then
54 echo >&2 "$quis: unknown keeper set \`$keeper'"
55 exit 1
56fi
57if [ ! -d $KEYS/recov/$recov ]; then
58 echo >&2 "$quis: unknown recovery key \`$recov'"
59 exit 1
60fi
61if [ ! -f $KEYS/recov/$recov/$keeper.param ]; then
62 echo >&2 "$quis: recovery key \`$recov' not kept by keeper set \`$keeper'"
63 exit 1
64fi
65
66## Grab the key, because we'll need to read it several times.
67mktmp
68cat -- "$@" >$tmp/secret
69
70## Read the threshold from the recovery metadata.
71read param <$KEYS/recov/$recov/$keeper.param
72case "$param" in
73 shamir-params:*) ;;
74 *)
75 echo >&2 "$quis: secret sharing parameter file damaged (wrong header)"
76 exit 1
77 ;;
78esac
79t=";${param#*:}"
80case "$t" in
81 *";t="*) ;;
82 *)
83 echo >&2 "$quis: secret sharing parameter file damaged (missing t)"
84 exit 1
85 ;;
86esac
87t=${t#*;t=}
88t=${t%%;*}
89
90## Find out which keeper index it corresponds to.
91read n hunoz <$KEYS/keeper/$keeper/meta
92i=0
93foundp=nil
94while [ $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 ))
100done
101case $foundp in
102 nil) echo >&2 "$quis: nub doesn't match keeper \`$keeper'"; exit 1 ;;
103esac
104
105## Establish the recovery staging area. See whether we've done enough
106## already.
107reqsafe
108tag=$(echo $recov | tr / .)
109mkdir -p -m700 $SAFE/keys.reveal
110reveal=$SAFE/keys.reveal/$tag
111if [ ! -d $reveal ]; then mkdir -m700 $reveal; fi
112cd $reveal
113if [ -f nub ]; then
114 echo >&2 "$quis: recovery key \`$recov' already revealed"
115 exit 1
116fi
117
118## Decrypt the share.
119umask 077
120if [ -f $keeper.$i.share ]; then
121 echo >&2 "$quis: share $i already revealed"
122else
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
127fi
128
129## See if there's enough for a recovery.
130n=0
131for j in $keeper.*.share; do if [ -f "$j" ]; then n=$(( $n + 1 )); fi; done
132if [ $n -lt $t ]; then
133 echo >&2 "$quis: share $i revealed; $(( $t - $n )) more required"
134else
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"
150fi
151
152###----- That's all, folks --------------------------------------------------