]> git.decadent.org.uk Git - dak.git/blob - scripts/debian/byhand-code-sign
byhand-code-sign: Put signature tarballs for security uploads in .../updates
[dak.git] / scripts / debian / byhand-code-sign
1 #!/bin/bash
2
3 set -u
4 set -e
5 set -o pipefail
6
7 if [ $# -lt 5 ]; then
8         echo "Usage: $0 filename version arch changes_file suite"
9         exit 1
10 fi
11
12 IN_TARBALL="$1" # Tarball to read, compressed with xz
13 VERSION="$2"
14 ARCH="$3"
15 CHANGES="$4"    # Changes file for the upload
16 SUITE="$5"
17
18 error() {
19         echo >&2 "E: $*"
20         exit 1
21 }
22
23 export OPENSSL_CONF=/dev/null
24
25 # Read dak configuration for security or main archive.
26 # Also determine subdirectory for the suite.
27 case "$0" in
28     /srv/security-master.debian.org/*)
29         configdir="/srv/security-master.debian.org/dak/config/debian-security"
30         suitedir="$SUITE/updates"
31         ;;
32     /srv/ftp-master.debian.org/*)
33         configdir="/srv/ftp-master.debian.org/dak/config/debian"
34         suitedir="$SUITE"
35         ;;
36     *)
37         error "$0: Can't tell if security or not"
38         ;;
39 esac
40 . "$configdir/vars"
41
42 # Read and trivially validate our configuration
43 . "$configdir/byhand-code-sign.conf"
44 for var in EFI_BINARY_PRIVKEY EFI_BINARY_CERT \
45            LINUX_SIGNFILE LINUX_MODULE_PRIVKEY LINUX_MODULE_CERT; do
46         test -v $var || error "$var is not defined in configuration"
47         test -n "${!var}" || error "$var is empty in configuration"
48 done
49
50 TARGET="$ftpdir/dists/$suitedir/main/code-sign/"
51 OUT_TARBALL="$TARGET/${IN_TARBALL##*/}"
52 OUT_TARBALL="${OUT_TARBALL%.tar.xz}_sigs.tar.xz"
53
54 # Check that this source/arch/version hasn't already been signed
55 if [ -e "$OUT_TARBALL" ]; then
56         error "Signature tarball already exists: $OUT_TARBALL"
57 fi
58
59 # If we fail somewhere, cleanup the temporary directories
60 IN_DIR=
61 OUT_DIR=
62 CERT_DIR=
63 cleanup() {
64         for dir in "$IN_DIR" "$OUT_DIR" "$CERT_DIR"; do
65                 test -z "$dir" || rm -rf "$dir"
66         done
67 }
68 trap cleanup EXIT
69
70 # Extract the data into the input directory
71 IN_DIR="$(mktemp -td byhand-code-sign-in.XXXXXX)"
72 tar xaf "$IN_TARBALL" --directory="$IN_DIR"
73
74 case "$EFI_BINARY_PRIVKEY" in
75     pkcs11:*)
76         # Translate from OpenSSL PKCS#11 enigne syntax to pesign parameters
77         # See: https://sources.debian.net/src/engine-pkcs11/0.2.2-1/src/engine_pkcs11.c
78         pkcs11_pin_value=
79         old_IFS="$IFS"
80         IFS=';'
81         for kv in ${EFI_BINARY_PRIVKEY#pkcs11:}; do
82                 case "$kv" in
83                     token=*)
84                         pkcs11_token="${kv#*=}"
85                         ;;
86                     object=*)
87                         pkcs11_object="${kv#*=}"
88                         ;;
89                     pin-value=*)
90                         pkcs11_pin_value="${kv#*=}"
91                         ;;
92                 esac
93         done
94         IFS="$old_IFS"
95         unset old_IFS
96         # TODO: unlock it
97         PESIGN_PARAMS=(-t "$pkcs11_token" -c "$pkcs11_object")
98         ;;
99     *)
100         # Create certificate store for pesign
101         CERT_DIR="$(mktemp -td byhand-code-sign-cert.XXXXXX)"
102         chmod 700 "$CERT_DIR"
103         mkdir "$CERT_DIR/store"
104         certutil -N --empty-password -d "$CERT_DIR/store"
105         openssl pkcs12 -export \
106                 -inkey "$EFI_BINARY_PRIVKEY" -in "$EFI_BINARY_CERT" \
107                 -out "$CERT_DIR/efi-image.p12" -passout pass: \
108                 -name efi-image
109         pk12util -i "$CERT_DIR/efi-image.p12" -d "$CERT_DIR/store" -K '' -W ''
110         PESIGN_PARAMS=(-n "$CERT_DIR/store" -c efi-image)
111         ;;
112 esac
113
114 # Create hierarchy of detached signatures in parallel to the uploaded files
115 OUT_DIR="$(mktemp -td byhand-code-sign-out.XXXXXX)"
116 while read filename; do
117         mkdir -p "$OUT_DIR/${filename%/*}"
118         case "${filename##*/}" in
119             *.efi | vmlinuz-*)
120                 pesign -i "$IN_DIR/$filename" \
121                        --export-signature "$OUT_DIR/$filename.sig" --sign \
122                        -d sha256 "${PESIGN_PARAMS[@]}"
123                 ;;
124             *.ko)
125                 "$LINUX_SIGNFILE" -d sha256 "$LINUX_MODULE_PRIVKEY" \
126                         "$LINUX_MODULE_CERT" "$IN_DIR/$filename"
127                 mv "$IN_DIR/$filename.p7s" "$OUT_DIR/$filename.sig"
128                 ;;
129             *)
130                 echo >&2 "W: Not signing unrecognised file: $filename"
131                 continue
132                 ;;
133         esac
134         if [ ${#filename} -gt 60 ]; then
135                 filename_trunc="...${filename:$((${#filename} - 57)):57}"
136         else
137                 filename_trunc="$filename"
138         fi
139         printf 'I: Signed %-60s\r' "$filename_trunc"
140 done < <(find "$IN_DIR" -type f -printf '%P\n')
141
142 # Clear last progress message
143 printf '%-70s\r' ''
144
145 # Build tarball of signatures
146 chmod -R a+rX "$OUT_DIR"
147 mkdir -p "$TARGET"
148 tar caf "$OUT_TARBALL" --directory="$OUT_DIR" .
149 echo "I: Created $OUT_TARBALL"
150
151 trap - EXIT
152 cleanup
153
154 exit 0