initial checkin: still somewhat sketchy
[distorted-keys] / new-recov
CommitLineData
53263601
MW
1#! /bin/sh
2###
3### Generate a new recovery key and split it among keepers
4###
5### (c) 2011 Mark Wooding
6###
7
8###----- Licensing notice ---------------------------------------------------
9###
10### This program is free software; you can redistribute it and/or modify
11### it under the terms of the GNU General Public License as published by
12### the Free Software Foundation; either version 2 of the License, or
13### (at your option) any later version.
14###
15### This program is distributed in the hope that it will be useful,
16### but WITHOUT ANY WARRANTY; without even the implied warranty of
17### MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18### GNU General Public License for more details.
19###
20### You should have received a copy of the GNU General Public License
21### along with this program; if not, write to the Free Software Foundation,
22### Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24set -e
25case "${KEYSLIB+t}" in t) ;; *) echo >&2 "$0: KEYSLIB unset"; exit 1 ;; esac
26. "$KEYSLIB"/keyfunc.sh
27
28defhelp <<HELP
29RECOV [KEEPER:K ...]
30Generate a new recovery secret, and split it among the available keepers.
31
32The new secret will be called RECOV. For each KEEPER set, the private key
33wil be split into shares, and encrypted with the KEEPER's public keys; any K
34of these shares can be used to reveal the original key.
35
36If there is already a recovery key called RECOV then it will be rolled over.
37The previous key must already be revealed. If KEEPERs are listed, these
38replace the existing keeper sets; otherwise the same keepers as before are
39used.
40
41If there is not a recovery key called RECOV then at least one keeper set must
42be specified.
43HELP
44dohelp
45
46## Parse the command line.
47case $# in 0) echo >&2 "$usage"; exit 1 ;; esac
48recov=$1; shift
49checkword "recovery key label" "$recov"
50for k in "$@"; do
51 case "$k" in
52 *:*) ;;
53 *) echo >&2 "$quis: bad keeper spec \`$k'"; exit 1 ;;
54 esac
55 keeper=${k%:*} t=${k#*:}
56 checkword "keeper set label" "$keeper"
57 checknumber "keeper quorum" "$t"
58done
59
60## Establish the keeper parameters.
61rdir=$KEYS/recov/$recov
62if [ ! -d $rdir ]; then mkdir -m755 -p $rdir; fi
63case $# in
64 0)
65 kparam=$rdir/keepers
66 ;;
67 *)
68 for k in "$@"; do
69 keeper=${k%:*} t=${k#*:}
70 echo $keeper $t
71 done >$rdir/keepers.new
72 kparam=$rdir/keepers.new
73 ;;
74esac
75if [ ! -f $kparam ]; then echo >&2 "$quis: no keepers specified"; exit 1; fi
76
77## Make the new key and issue the shares.
78tmp=$(mktmp); cleanup rmtmp
79rm -rf $rdir/new
80mkdir -m755 $rdir/new
81cd $tmp
82ec_keygen secret $rdir/new/pub
83while read keeper k; do
84 read n hunoz <$KEYS/keeper/$keeper/meta
85 shamir issue $k/$n secret | {
86 read param
87 echo "$param" >$rdir/new/$keeper.param
88 i=0
89 while read share; do
90 echo $share |
91 ec_encrypt $KEYS/keeper/$keeper/$i.pub -o$rdir/new/$keeper.$i.share
92 i=$(( i + 1 ))
93 done
94 }
95done <$kparam
96rm -f secret
97
98## If there's an existing instance of this key, transfer the recovery blobs.
99if [ ! -d $rdir/current ]; then
100 seq=0
101else
102 seq=$(readlink $rdir/current)
103 mem=$(userv root claim-mem-dir)
104 reveal=$mem/keys.reveal.$recov.current/secret
105 if [ ! -f $reveal ]; then
106 echo >&2 "$quis: current $recov key not revealed"
107 exit 1
108 fi
109 find $rdir/current -type f -name '*.recov' -print | while read name; do
110 name=${name#$rdir/current/}
111 case "$name" in */*) mkdir -p -m755 $rdir/new/${name%/*} ;; esac
112 ec_decrypt $reveal -i$rdir/current/$name |
113 ec_encrypt $rdir/new/pub -o$rdir/new/$name
114 done
115fi
116
117## Tidy up and commit.
118cd $rdir
119while [ -d $seq ]; do seq=$(( seq + 1 )); done
120case $kparam in *.new) mv keepers.new keepers ;; esac
121rm -f next
122ln -s $seq next
123mv new $seq
124mv next current
125
126###----- That's all, folks --------------------------------------------------