chiark / gitweb /
.gitignore: Ignore `INSTALL'.
[distorted-keys] / keys.reveal
CommitLineData
53263601
MW
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###
599c8f75
MW
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
53263601
MW
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###
599c8f75 17### distorted-keys is distributed in the hope that it will be useful,
53263601
MW
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
599c8f75 23### along with distorted-keys; if not, write to the Free Software Foundation,
53263601
MW
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
ae0eb898 31[-i INST] RECOV KEEPER
53263601
MW
32Reveal a share of a recovery key distributed among keepers.
33
34If enough shares have been revealed, reconstruct the recovery private key.
d516ebd0 35The keeper nub is read from stdin.
53263601 36HELP
53263601
MW
37
38## Parse the command line.
ae0eb898
MW
39inst=current
40while getopts "i:" opt; do
41 case "$opt" in
42 i) inst=$OPTARG ;;
43 *) usage_err ;;
44 esac
45done
46shift $(( $OPTIND - 1 ))
d516ebd0 47case $# in 2) ;; *) usage_err ;; esac
53263601 48recov=$1 keeper=$2; shift 2
ae0eb898
MW
49checkword "recovery instance" "$inst"
50checkword "recovery key" "$recov"
53263601
MW
51checkword "keeper set label" "$keeper"
52
c47f2aba 53## Check that this is a sensible thing to do.
bdc4cfb4
MW
54keepdir=$KEYS/keeper/$keeper
55if [ ! -f $keepdir/meta ]; then
c47f2aba
MW
56 echo >&2 "$quis: unknown keeper set \`$keeper'"
57 exit 1
58fi
bdc4cfb4 59if [ ! -h $KEYS/recov/$recov/current ]; then
c47f2aba
MW
60 echo >&2 "$quis: unknown recovery key \`$recov'"
61 exit 1
62fi
ae0eb898
MW
63rdir=$KEYS/recov/$recov/$inst
64if [ ! -f $rdir/$keeper.param ]; then
c47f2aba
MW
65 echo >&2 "$quis: recovery key \`$recov' not kept by keeper set \`$keeper'"
66 exit 1
67fi
68
53263601 69## Grab the key, because we'll need to read it several times.
c47f2aba 70mktmp
d516ebd0 71cat >$tmp/secret
53263601
MW
72
73## Read the threshold from the recovery metadata.
ae0eb898 74t=$(sharethresh $rdir/$keeper.param)
53263601
MW
75
76## Find out which keeper index it corresponds to.
bdc4cfb4 77read n hunoz <$keepdir/meta
53263601 78i=0
bdc4cfb4 79foundnubp=nil
53263601 80while [ $i -lt $n ]; do
bdc4cfb4 81 c_sysprepare $keepdir/$i
c47f2aba 82 nubbin=$(nubid <$tmp/secret)
bdc4cfb4
MW
83 nubid=$(cat $keepdir/$i/nubid)
84 case "$nubbin" in "$nubid") foundnubp=t; break ;; esac
c47f2aba 85 i=$(( $i + 1 ))
53263601 86done
bdc4cfb4 87case $foundnubp in
c47f2aba 88 nil) echo >&2 "$quis: nub doesn't match keeper \`$keeper'"; exit 1 ;;
53263601
MW
89esac
90
91## Establish the recovery staging area. See whether we've done enough
92## already.
c47f2aba 93reqsafe
ae0eb898 94tag=$recov.$inst
c47f2aba
MW
95mkdir -p -m700 $SAFE/keys.reveal
96reveal=$SAFE/keys.reveal/$tag
599c8f75
MW
97if [ ! -d $reveal ]; then mkdir -m700 $reveal; fi
98cd $reveal
c47f2aba 99if [ -f nub ]; then
ae0eb898 100 echo >&2 "$quis: recovery key \`$recov/$inst' already revealed"
53263601
MW
101 exit 1
102fi
103
104## Decrypt the share.
599c8f75 105umask 077
c47f2aba
MW
106if [ -f $keeper.$i.share ]; then
107 echo >&2 "$quis: share $i already revealed"
108else
bdc4cfb4 109 c_sysdecrypt $keepdir/$i $tmp/secret \
ae0eb898 110 <$rdir/$keeper.$i.share \
c47f2aba
MW
111 >$keeper.$i.new
112 mv $keeper.$i.new $keeper.$i.share
113fi
53263601
MW
114
115## See if there's enough for a recovery.
116n=0
c47f2aba 117for j in $keeper.*.share; do if [ -f "$j" ]; then n=$(( $n + 1 )); fi; done
53263601 118if [ $n -lt $t ]; then
c47f2aba 119 echo >&2 "$quis: share $i revealed; $(( $t - $n )) more required"
53263601 120else
ae0eb898 121 cat $rdir/$keeper.param $keeper.*.share >$keeper.shares
5c30c6e6 122 $bindir/shamir recover <$keeper.shares >nub.new
ae0eb898 123 c_sysprepare $rdir/store
c47f2aba 124 nubbin=$(nubid <nub.new)
ae0eb898 125 nubid=$(cat $rdir/store/nubid)
c47f2aba
MW
126 case "$nubbin" in
127 "$nubid") ;;
53263601 128 *)
c47f2aba 129 echo >&2 "$quis: recovered nub doesn't match stored hash"
53263601
MW
130 exit 1
131 ;;
132 esac
c47f2aba
MW
133 mv nub.new nub
134 rm -f $keeper.*
ae0eb898 135 echo >&2 "$quis: recovery key \`$recov/$inst' revealed"
53263601
MW
136fi
137
138###----- That's all, folks --------------------------------------------------