chiark / gitweb /
keys.delete-keeper: Only do one pass through the file system.
[distorted-keys] / 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
c47f2aba 31[-p PROFILE] RECOV [KEEPER:K ...] [-- OPTION=VALUE ...]
53263601
MW
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
53263601
MW
46
47## Parse the command line.
c47f2aba
MW
48profile=${recov_profile-recovery}
49while getopts "p:" opt; do
50 case "$opt" in
51 p) profile=$OPTARG ;;
52 *) usage_err ;;
53 esac
54done
55shift $(( $OPTIND - 1 ))
56case $# in 0) usage_err ;; esac
53263601
MW
57recov=$1; shift
58checkword "recovery key label" "$recov"
c47f2aba
MW
59checkword "profile label" "$profile"
60nkeep=0
53263601
MW
61for k in "$@"; do
62 case "$k" in
c47f2aba 63 --) break ;;
53263601
MW
64 *:*) ;;
65 *) echo >&2 "$quis: bad keeper spec \`$k'"; exit 1 ;;
66 esac
c47f2aba 67 keeper=${k%:*} t=${k#*:} nkeep=$(( $nkeep + 1 ))
53263601
MW
68 checkword "keeper set label" "$keeper"
69 checknumber "keeper quorum" "$t"
70done
71
72## Establish the keeper parameters.
73rdir=$KEYS/recov/$recov
74if [ ! -d $rdir ]; then mkdir -m755 -p $rdir; fi
c47f2aba 75case $nkeep in
53263601
MW
76 0)
77 kparam=$rdir/keepers
78 ;;
79 *)
80 for k in "$@"; do
c47f2aba 81 case "$k" in --) break ;; esac
53263601
MW
82 keeper=${k%:*} t=${k#*:}
83 echo $keeper $t
84 done >$rdir/keepers.new
85 kparam=$rdir/keepers.new
86 ;;
87esac
88if [ ! -f $kparam ]; then echo >&2 "$quis: no keepers specified"; exit 1; fi
89
90## Make the new key and issue the shares.
c47f2aba 91mktmp
53263601
MW
92rm -rf $rdir/new
93mkdir -m755 $rdir/new
94cd $tmp
c3b148fb
MW
95while :; do
96 case "$#,$1" in
c47f2aba
MW
97 0,) break ;;
98 *,*,*) ;;
99 *,--) break ;;
100 esac
101 shift
102done
6aef0cfe 103c_gensyskey $profile $rdir/new/store secret recov="$recov" "$@"
53263601
MW
104while read keeper k; do
105 read n hunoz <$KEYS/keeper/$keeper/meta
5c30c6e6 106 $bindir/shamir issue $k/$n secret | {
53263601
MW
107 read param
108 echo "$param" >$rdir/new/$keeper.param
109 i=0
110 while read share; do
c47f2aba
MW
111 c_sysencrypt $KEYS/keeper/$keeper/$i >$rdir/new/$keeper.$i.share <<EOF
112$share
113EOF
114 i=$(( $i + 1 ))
53263601
MW
115 done
116 }
117done <$kparam
118rm -f secret
119
120## If there's an existing instance of this key, transfer the recovery blobs.
121if [ ! -d $rdir/current ]; then
122 seq=0
123else
124 seq=$(readlink $rdir/current)
c47f2aba
MW
125 reqsafe
126 reveal=$SAFE/keys.reveal/$recov.current/secret
53263601
MW
127 if [ ! -f $reveal ]; then
128 echo >&2 "$quis: current $recov key not revealed"
129 exit 1
130 fi
599c8f75
MW
131
132 find $rdir/current/ -type f -name '*.recov' -print | while read name; do
53263601
MW
133 name=${name#$rdir/current/}
134 case "$name" in */*) mkdir -p -m755 $rdir/new/${name%/*} ;; esac
c47f2aba
MW
135 c_sysdecrypt $rdir/current/store $reveal <$rdir/current/$name >tmp
136 c_sysencrypt $rdir/new/store <tmp >$rdir/new/$name
137 rm tmp
53263601 138 done
c47f2aba 139 rm -r $SAFE/keys.reveal/$recov.current
53263601
MW
140fi
141
599c8f75
MW
142## Tidy up and commit. Repointing the symlink is grim because, according to
143## POSIX rules, `mv foo bar' should rename `foo' to `bar/foo' is `bar' is a
144## symlink to a directory -- and there's no way of turning this behaviour
145## off. The subterfuge here is due to Colin Watson.
53263601 146cd $rdir
c47f2aba 147while [ -d $seq ]; do seq=$(( $seq + 1 )); done
53263601
MW
148case $kparam in *.new) mv keepers.new keepers ;; esac
149rm -f next
150ln -s $seq next
151mv new $seq
599c8f75 152mkdir hack; mv next hack/current; mv hack/current .; rmdir hack
53263601
MW
153
154###----- That's all, folks --------------------------------------------------