chiark / gitweb /
cryptop.list: Fix column width calculation.
[distorted-keys] / keys.new-recov
... / ...
CommitLineData
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 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
31[-p PROFILE] RECOV [KEEPER:K ...] [-- OPTION=VALUE ...]
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
46
47## Parse the command line.
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
57recov=$1; shift
58checkword "recovery key label" "$recov"
59checkword "profile label" "$profile"
60nkeep=0
61for k in "$@"; do
62 case "$k" in
63 --) break ;;
64 *:*) ;;
65 *) echo >&2 "$quis: bad keeper spec \`$k'"; exit 1 ;;
66 esac
67 keeper=${k%:*} t=${k#*:} nkeep=$(( $nkeep + 1 ))
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
75case $nkeep in
76 0)
77 kparam=$rdir/keepers
78 ;;
79 *)
80 for k in "$@"; do
81 case "$k" in --) break ;; esac
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.
91mktmp
92rm -rf $rdir/new
93mkdir -m755 $rdir/new
94cd $tmp
95while :; do case "$#,$1" in
96 0,) break ;;
97 *,*,*) ;;
98 *,--) break ;;
99 esac
100 shift
101done
102c_gensyskey $profile $rdir/new/store secret recov="$recov"
103while read keeper k; do
104 read n hunoz <$KEYS/keeper/$keeper/meta
105 $bindir/shamir issue $k/$n secret | {
106 read param
107 echo "$param" >$rdir/new/$keeper.param
108 i=0
109 while read share; do
110 c_sysencrypt $KEYS/keeper/$keeper/$i >$rdir/new/$keeper.$i.share <<EOF
111$share
112EOF
113 i=$(( $i + 1 ))
114 done
115 }
116done <$kparam
117rm -f secret
118
119## If there's an existing instance of this key, transfer the recovery blobs.
120if [ ! -d $rdir/current ]; then
121 seq=0
122else
123 seq=$(readlink $rdir/current)
124 reqsafe
125 reveal=$SAFE/keys.reveal/$recov.current/secret
126 if [ ! -f $reveal ]; then
127 echo >&2 "$quis: current $recov key not revealed"
128 exit 1
129 fi
130
131 find $rdir/current/ -type f -name '*.recov' -print | while read name; do
132 name=${name#$rdir/current/}
133 case "$name" in */*) mkdir -p -m755 $rdir/new/${name%/*} ;; esac
134 c_sysdecrypt $rdir/current/store $reveal <$rdir/current/$name >tmp
135 c_sysencrypt $rdir/new/store <tmp >$rdir/new/$name
136 rm tmp
137 done
138 rm -r $SAFE/keys.reveal/$recov.current
139fi
140
141## Tidy up and commit. Repointing the symlink is grim because, according to
142## POSIX rules, `mv foo bar' should rename `foo' to `bar/foo' is `bar' is a
143## symlink to a directory -- and there's no way of turning this behaviour
144## off. The subterfuge here is due to Colin Watson.
145cd $rdir
146while [ -d $seq ]; do seq=$(( $seq + 1 )); done
147case $kparam in *.new) mv keepers.new keepers ;; esac
148rm -f next
149ln -s $seq next
150mv new $seq
151mkdir hack; mv next hack/current; mv hack/current .; rmdir hack
152
153###----- That's all, folks --------------------------------------------------