File: blockdev-keygen

package info (click to toggle)
partman-crypto 57
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 2,664 kB
  • sloc: sh: 1,956; ansic: 172; makefile: 33
file content (268 lines) | stat: -rwxr-xr-x 5,344 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
#!/bin/sh
#
# usage: $0 description keytype keyfile [keybits]
#
# This handles sensitive data that must not be swapped out
# or written out to disk unencrypted.
#
# Important: before running this script the caller has
# to check for unsafe swap partitions. This is done in
# choose_method/encrypt/do_options.
#
# Assumption: This runs as part of d-i. Therefore, temp
# files outside of /target reside in a ramdisk. Process
# information (think [ "$pass" ]) is not exposed to anyone
# but the installing user.
#
# Released under the GNU GPL.
# Copyright 2005, Max Vozeler <xam@debian.org>
#

. /usr/share/debconf/confmodule

umask 077

# When changing minlen care must be taken about the
# consequences for translations, see #326482
minlen=8

passphrase_is_weak () {
	test $(printf %s "$1" | wc -c) -lt $minlen
}

get_passphrase () {
	local pass_ok

	pass_ok=0
	while [ $pass_ok -eq 0 ]; do
		templ="partman-crypto/passphrase"
		db_set $templ ""
		db_fset $templ seen false
		db_subst $templ DEVICE "$description"
		db_input critical $templ

		templ="partman-crypto/passphrase-again"
		db_set $templ ""
		db_fset $templ seen false
		db_input critical $templ

		db_go || return 1

		db_get partman-crypto/passphrase || RET=''
		pass=$RET
		if [ -z "$pass" ]; then
			templ="partman-crypto/passphrase-empty"
			db_fset $templ seen false
			db_input critical $templ
			continue
		fi

		db_get partman-crypto/passphrase-again || RET=''
		if [ "$pass" != "$RET" ]; then
			templ="partman-crypto/passphrase-mismatch"
			db_fset $templ seen false
			db_input critical $templ
			continue
		fi

		if passphrase_is_weak "$pass"; then
			templ="partman-crypto/weak_passphrase"
			db_set $templ false
			db_fset $templ seen false
			db_subst $templ MINIMUM $minlen
			db_input critical $templ || true
			db_go || true
			db_get $templ || RET=''

			if [ "$RET" != true ]; then
				# user doesn't want to force weak passphrase
				continue
			fi
		fi

		pass_ok=1
	done

	db_set partman-crypto/passphrase ""
	db_set partman-crypto/passphrase-again ""

	if [ $pass_ok -eq 1 ]; then
		echo "$pass"
	fi
}

have_entropy_plugin () {
	db_capb
	set -- $RET
	for cap; do
		if [ "$cap" = plugin-entropy ]; then
			return 0
		fi
	done
	return 1
}

# Fifo provided by cdebconf-entropy plugins
randfifo=/var/run/random.fifo

call_entropy_plugin () {
	local keybytes
	keybytes=$1

	db_capb backup align

	templ=partman-crypto/entropy
	db_fset $templ seen false
	db_subst $templ DEVICE "$description"
	db_subst $templ FIFO $randfifo
	db_subst $templ KEYSIZE "$keybytes"
	db_subst $templ SUCCESS partman-crypto/entropy-success
	db_input critical $templ
	db_go || return 1

	return 0
}

gnupg_encrypt () {
	local keyfile passfifo gpgopts
	keyfile=$1
	passfifo=$2
	gpgopts="--batch --no-options --no-random-seed-file --no-default-keyring --keyring /dev/null --passphrase-fd 3 --symmetric -a"

	while [ ! -p $randfifo ]; do
		sleep 1
	done

	base64 < $randfifo | gpg $gpgopts 3< $passfifo > $keyfile
}

# Create a GnuPG keyfile for use by loop-AES.
# (v3 key format: 2925 bytes in base64)
create_gnupg_keyfile () {
	local keyfile pass passfifo pid
	keyfile=$1
	pass=$2

	passfifo=$keyfile.pass
	if [ ! -p $passfifo ]; then
		mknod $passfifo p
		chmod 0600 $passfifo
	fi

	# Fork off gnupg encrypting pipe
	printf %s "$pass" > $passfifo &
	gnupg_encrypt $keyfile $passfifo &
	gpg_pid=$!

	# Call plugin to feed randfifo
	call_entropy_plugin 2925
	if [ $? -ne 0 ] || ! wait $gpg_pid; then
		rm $keyfile
		kill $gpg_pid
		return 1
	fi

	# for use by init.d/crypto
	printf %s "$pass" > $passfifo &
	return 0
}

# Create a one-time random keyfile for use during install
create_random_keyfile() {
	local keyfile keybytes
	keyfile=$1
	keybytes=$2

	# Fork off file writer
	(while [ ! -p $randfifo ]; do
		 sleep 1
	 done
	 cat $randfifo > $keyfile
	) &
	writer_pid=$!

	# Call plugin to feed randfifo
	call_entropy_plugin $keybytes
	if [ $? -ne 0 ] || ! wait $writer_pid; then
		rm $keyfile
		kill $writer_pid
		return 1
	fi

	return 0
}

problem_dialog () {
	db_fset partman-crypto/keyfile-problem seen false
	db_input critical partman-crypto/keyfile-problem
	db_go || true
}

description=$1
keytype=$2
keyfile=$3
keybits=$4

if ! ([ "$description" ] && [ "$keytype" ] && [ "$keyfile" ]); then
	# bad options
	problem_dialog
	exit 1
fi

# Log available entropy
logger -t partman-crypto "kernel entropy_avail: $(cat /proc/sys/kernel/random/entropy_avail) bits"

if [ "$keytype" = random ] || [ "$keytype" = keyfile ]; then
	if ! have_entropy_plugin; then
		db_fset partman-crypto/tools_missing seen false
		db_input critical partman-crypto/tools_missing
		db_go || true
		exit 1
	fi
fi

case $keytype in
	keyfile)
		pass=$(get_passphrase)
		if [ -z "$pass" ]; then
			problem_dialog
			exit 1
		fi
		if ! create_gnupg_keyfile $keyfile "$pass"; then
			problem_dialog
			exit 1
		fi
		;;

	passphrase)
		pass=$(get_passphrase)
		if [ -z "$pass" ]; then
			problem_dialog
			exit 1
		fi
		printf %s "$pass" > $keyfile
		;;

	random)
		if [ -z "$keybits" ]; then
			problem_dialog
			exit 1
		fi
		# Round keybits up to closest byte
		keybytes=$(( (keybits + 7)/8 ))
		if [ $keybytes -lt 1 ]; then
			# key size invalid
			problem_dialog
			exit 1
		fi
		if ! create_random_keyfile $keyfile $keybytes; then
			problem_dialog
			exit 1
		fi
		;;

	*)
		problem_dialog
		exit 1
		;;
esac