Commit | Line | Data |
---|---|---|
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 | ||
24 | set -e | |
25 | case "${KEYSLIB+t}" in t) ;; *) echo >&2 "$0: KEYSLIB unset"; exit 1 ;; esac | |
26 | . "$KEYSLIB"/keyfunc.sh | |
27 | ||
28 | defhelp <<HELP | |
29 | RECOV [KEEPER:K ...] | |
30 | Generate a new recovery secret, and split it among the available keepers. | |
31 | ||
32 | The new secret will be called RECOV. For each KEEPER set, the private key | |
33 | wil be split into shares, and encrypted with the KEEPER's public keys; any K | |
34 | of these shares can be used to reveal the original key. | |
35 | ||
36 | If there is already a recovery key called RECOV then it will be rolled over. | |
37 | The previous key must already be revealed. If KEEPERs are listed, these | |
38 | replace the existing keeper sets; otherwise the same keepers as before are | |
39 | used. | |
40 | ||
41 | If there is not a recovery key called RECOV then at least one keeper set must | |
42 | be specified. | |
43 | HELP | |
44 | dohelp | |
45 | ||
46 | ## Parse the command line. | |
47 | case $# in 0) echo >&2 "$usage"; exit 1 ;; esac | |
48 | recov=$1; shift | |
49 | checkword "recovery key label" "$recov" | |
50 | for 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" | |
58 | done | |
59 | ||
60 | ## Establish the keeper parameters. | |
61 | rdir=$KEYS/recov/$recov | |
62 | if [ ! -d $rdir ]; then mkdir -m755 -p $rdir; fi | |
63 | case $# 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 | ;; | |
74 | esac | |
75 | if [ ! -f $kparam ]; then echo >&2 "$quis: no keepers specified"; exit 1; fi | |
76 | ||
77 | ## Make the new key and issue the shares. | |
78 | tmp=$(mktmp); cleanup rmtmp | |
79 | rm -rf $rdir/new | |
80 | mkdir -m755 $rdir/new | |
81 | cd $tmp | |
82 | ec_keygen secret $rdir/new/pub | |
83 | while 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 | } | |
95 | done <$kparam | |
96 | rm -f secret | |
97 | ||
98 | ## If there's an existing instance of this key, transfer the recovery blobs. | |
99 | if [ ! -d $rdir/current ]; then | |
100 | seq=0 | |
101 | else | |
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 | |
115 | fi | |
116 | ||
117 | ## Tidy up and commit. | |
118 | cd $rdir | |
119 | while [ -d $seq ]; do seq=$(( seq + 1 )); done | |
120 | case $kparam in *.new) mv keepers.new keepers ;; esac | |
121 | rm -f next | |
122 | ln -s $seq next | |
123 | mv new $seq | |
124 | mv next current | |
125 | ||
126 | ###----- That's all, folks -------------------------------------------------- |