summaryrefslogtreecommitdiffstats
path: root/scripts/signall.sh
blob: 3bea7be1e4de51d5ade657ac7a944b6f59a1b925 (plain)
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
#!/usr/bin/env bash

tarball="$1"
branch="$2"

tmpdir="signall.$$"
tarball="$(readlink -f "$tarball")"

finish() { rm -rf "$tmpdir"; exit $1; }

iniget() {
	local file="$1" section="$2" option="$3"

	sed -rne '
		/\['"$section"'\]/,$ {
			/^[ \t]*'"$option"'[ \t]*=[ \t]*/ {
				s/^[^=]+=[ \t]*//; h;
				:c; n;
				/^([ \t]|$)/ {
					s/^[ \t]+//; H;
					b c
				};
				x; p; q
			}
		}
	' "$file" | sed -e :a -e '/^\n*$/{$d;N;ba' -e '}'
}

trap "finish 255" HUP INT TERM

if [ ! -f "$tarball" ] || [ ! -f "${CONFIG_INI:-config.ini}" ]; then
	echo "Usage: [CONFIG_INI=...] $0 <tarball>" >&2
	finish 1
fi

[ ! -e "$tmpdir" ] || {
	echo "Temporary directory $tmpdir already exists!" >&2
	finish 2
}

umask 077
mkdir "$tmpdir" "$tmpdir/tar" "$tmpdir/gpg" "$tmpdir/gpg/private-keys-v1.d" || finish 2

umask 022
chmod 0755 "$tmpdir/tar"
tar -C "$tmpdir/tar/" -xzf "$tarball" || finish 3

loopback=""

case "$(gpg --version | head -n1)" in
	*\ 2.*) loopback=1 ;;
esac

if [ -z "$branch" ]; then
GPGKEY="$(iniget "${CONFIG_INI:-config.ini}" gpg key)"
GPGKEYID="$(iniget "${CONFIG_INI:-config.ini}" gpg keyid)"
GPGPASS="$(iniget "${CONFIG_INI:-config.ini}" gpg passphrase)"
GPGCOMMENT="$(iniget "${CONFIG_INI:-config.ini}" gpg comment)"

USIGNKEY="$(iniget "${CONFIG_INI:-config.ini}" usign key)"
USIGNCOMMENT="$(iniget "${CONFIG_INI:-config.ini}" usign comment)"

APKSIGNKEY="$(iniget "${CONFIG_INI:-config.ini}" apk key)"
else
GPGKEY="$(iniget "${CONFIG_INI:-config.ini}" "branch $branch" "gpg_key")"
GPGKEYID="$(iniget "${CONFIG_INI:-config.ini}" "branch $branch" "gpg_keyid")"
GPGPASS="$(iniget "${CONFIG_INI:-config.ini}" "branch $branch" "gpg_passphrase")"
GPGCOMMENT="$(iniget "${CONFIG_INI:-config.ini}" "branch $branch" "gpg_comment")"

USIGNKEY="$(iniget "${CONFIG_INI:-config.ini}" "branch $branch" "usign_key")"
USIGNCOMMENT="$(iniget "${CONFIG_INI:-config.ini}" "branch $branch" "usign_comment")"

APKSIGNKEY="$(iniget "${CONFIG_INI:-config.ini}" "branch $branch" "apk_key")"
fi

if [ -n "$APKSIGNKEY" ]; then
	umask 077
	echo "$APKSIGNKEY" > "$tmpdir/apk.pem"

	umask 022
	find "$tmpdir/tar/" -type f -name "packages.adb" -print0 | while IFS= read -r -d '' file; do
		if ! "${APK_BIN:-apk}" adbsign --allow-untrusted --sign-key "$(readlink -f "$tmpdir/apk.pem")" "$file"; then
			finish 3
		fi
	done

	find "$tmpdir/tar/" -type f -name sha256sums | while read -r file; do
		dir=$(dirname "$file")
		pushd "$dir" > /dev/null || finish 3

		grep 'packages\.adb' sha256sums | while IFS= read -r line; do
			filename="${line#*' *'}"
			# Skip updating hash of previous kmods/ if not found in sign tar (already signed)
			[ ! -f "$filename" ] && [[ "$filename" == kmods/* ]] && continue
			escaped_filename="${filename//\//\\\/}"
			escaped_filename="${escaped_filename//&/\\&}"
			checksum_output=$(sha256sum --binary -- "$filename")
			new_checksum_line="${checksum_output%% *} *${checksum_output#*' *'}"
			sed -i "s#.*[[:space:]]\*$escaped_filename\$#$new_checksum_line#" sha256sums
		done

		popd > /dev/null || finish 3
	done
fi

if echo "$GPGKEY" | grep -q "BEGIN PGP PRIVATE KEY BLOCK" && [ -z "$GPGKEYID" ]; then
	umask 077
	echo "$GPGPASS" > "$tmpdir/gpg.pass"
	echo "$GPGKEY" | gpg --batch --homedir "$tmpdir/gpg" \
		${loopback:+--pinentry-mode loopback --no-tty --passphrase-fd 0} \
		${GPGPASS:+--passphrase-file "$tmpdir/gpg.pass"} \
		--import - || finish 4

	umask 022
	find "$tmpdir/tar/" -type f -not -name "*.asc" -and -not -name "*.sig" -exec \
		gpg --no-version --batch --yes -a -b \
			--homedir "$(readlink -f "$tmpdir/gpg")" \
			${loopback:+--pinentry-mode loopback --no-tty --passphrase-fd 0} \
			${GPGPASS:+--passphrase-file "$(readlink -f "$tmpdir/gpg.pass")"} \
			${GPGCOMMENT:+--comment="$GPGCOMMENT"} \
			-o "{}.asc" "{}" \; || finish 4
fi

if [ -n "$GPGKEYID" ]; then
	find "$tmpdir/tar/" -type f -not -name "*.asc" -and -not -name "*.sig" -print0 | while IFS= read -r -d '' file; do
		if ! gpg --no-version --batch --detach-sign --armor \
			--local-user "${GPGKEYID}" \
			${GPGCOMMENT:+--comment="$GPGCOMMENT"} \
			--homedir /home/buildbot/.gnupg "${file}.asc" "$file"; then
			finish 4
		fi
	done
fi

if [ -n "$USIGNKEY" ]; then
	USIGNID="$(echo "$USIGNKEY" | base64 -d -i | dd bs=1 skip=32 count=8 2>/dev/null | od -v -t x1 | sed -rne 's/^0+ //p' | tr -d ' ')"

	if ! echo "$USIGNID" | grep -qxE "[0-9a-f]{16}"; then
		echo "Invalid usign key specified" >&2
		finish 5
	fi

	umask 077
	printf "untrusted comment: %s\n%s\n" "${USIGNCOMMENT:-key ID $USIGNID}" "$USIGNKEY" > "$tmpdir/usign.sec"

	umask 022
	find "$tmpdir/tar/" -type f -not -name "*.asc" -and -not -name "*.sig" -exec \
		signify-openbsd -S -s "$(readlink -f "$tmpdir/usign.sec")" -m "{}" \; || finish 5
fi

tar -C "$tmpdir/tar/" -czf "$tarball" . || finish 6

finish 0