chiark / gitweb /
e4981f0fc9fee70ef4da03c234fb758ffc7cfb07
[distorted-keys] / new-recov
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 --------------------------------------------------