chiark / gitweb /
more progress. recovery seems to be working now.
[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###
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
31RECOV [KEEPER:K ...]
32Generate a new recovery secret, and split it among the available keepers.
33
34The new secret will be called RECOV. For each KEEPER set, the private key
35wil be split into shares, and encrypted with the KEEPER's public keys; any K
36of these shares can be used to reveal the original key.
37
38If there is already a recovery key called RECOV then it will be rolled over.
39The previous key must already be revealed. If KEEPERs are listed, these
40replace the existing keeper sets; otherwise the same keepers as before are
41used.
42
43If there is not a recovery key called RECOV then at least one keeper set must
44be specified.
45HELP
46dohelp
47
48## Parse the command line.
49case $# in 0) echo >&2 "$usage"; exit 1 ;; esac
50recov=$1; shift
51checkword "recovery key label" "$recov"
52for k in "$@"; do
53 case "$k" in
54 *:*) ;;
55 *) echo >&2 "$quis: bad keeper spec \`$k'"; exit 1 ;;
56 esac
57 keeper=${k%:*} t=${k#*:}
58 checkword "keeper set label" "$keeper"
59 checknumber "keeper quorum" "$t"
60done
61
62## Establish the keeper parameters.
63rdir=$KEYS/recov/$recov
64if [ ! -d $rdir ]; then mkdir -m755 -p $rdir; fi
65case $# in
66 0)
67 kparam=$rdir/keepers
68 ;;
69 *)
70 for k in "$@"; do
71 keeper=${k%:*} t=${k#*:}
72 echo $keeper $t
73 done >$rdir/keepers.new
74 kparam=$rdir/keepers.new
75 ;;
76esac
77if [ ! -f $kparam ]; then echo >&2 "$quis: no keepers specified"; exit 1; fi
78
79## Make the new key and issue the shares.
80tmp=$(mktmp); cleanup rmtmp
81rm -rf $rdir/new
82mkdir -m755 $rdir/new
83cd $tmp
84ec_keygen secret $rdir/new/pub
85while read keeper k; do
86 read n hunoz <$KEYS/keeper/$keeper/meta
87 shamir issue $k/$n secret | {
88 read param
89 echo "$param" >$rdir/new/$keeper.param
90 i=0
91 while read share; do
92 echo $share |
93 ec_encrypt $KEYS/keeper/$keeper/$i.pub -o$rdir/new/$keeper.$i.share
94 i=$(( i + 1 ))
95 done
96 }
97done <$kparam
98rm -f secret
99
100## If there's an existing instance of this key, transfer the recovery blobs.
101if [ ! -d $rdir/current ]; then
102 seq=0
103else
104 seq=$(readlink $rdir/current)
599c8f75
MW
105 mem=$(userv root claim-mem-dir </dev/null)
106 reveal=$mem/keys.reveal/$recov.current/secret
53263601
MW
107 if [ ! -f $reveal ]; then
108 echo >&2 "$quis: current $recov key not revealed"
109 exit 1
110 fi
599c8f75
MW
111
112 find $rdir/current/ -type f -name '*.recov' -print | while read name; do
53263601
MW
113 name=${name#$rdir/current/}
114 case "$name" in */*) mkdir -p -m755 $rdir/new/${name%/*} ;; esac
115 ec_decrypt $reveal -i$rdir/current/$name |
116 ec_encrypt $rdir/new/pub -o$rdir/new/$name
117 done
599c8f75 118 rm -r $mem/keys.reveal/$recov.current
53263601
MW
119fi
120
599c8f75
MW
121## Tidy up and commit. Repointing the symlink is grim because, according to
122## POSIX rules, `mv foo bar' should rename `foo' to `bar/foo' is `bar' is a
123## symlink to a directory -- and there's no way of turning this behaviour
124## off. The subterfuge here is due to Colin Watson.
53263601
MW
125cd $rdir
126while [ -d $seq ]; do seq=$(( seq + 1 )); done
127case $kparam in *.new) mv keepers.new keepers ;; esac
128rm -f next
129ln -s $seq next
130mv new $seq
599c8f75 131mkdir hack; mv next hack/current; mv hack/current .; rmdir hack
53263601
MW
132
133###----- That's all, folks --------------------------------------------------