summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2022-06-30 14:57:54 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2022-06-30 14:57:54 +0000
commitadc95b436be192fbe7910deb3b593d0daf9f5add (patch)
tree00f2c65624705862fecc496644b2ab29bca27e19
parentReleasing progress-linux version 2022.04.08-1~progress6+u1. (diff)
downloadwireless-regdb-adc95b436be192fbe7910deb3b593d0daf9f5add.tar.xz
wireless-regdb-adc95b436be192fbe7910deb3b593d0daf9f5add.zip
Merging debian version 2022.04.08-2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
-rw-r--r--debian/changelog8
-rwxr-xr-xdebian/tests/check-signatures136
-rw-r--r--debian/tests/control2
-rw-r--r--debian/wireless-regdb.postinst13
4 files changed, 159 insertions, 0 deletions
diff --git a/debian/changelog b/debian/changelog
index 638ee5b..47cf92c 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
+wireless-regdb (2022.04.08-2) unstable; urgency=medium
+
+ * debian/tests: Add check that regulatory.db signatures are valid
+ * d/wireless-regdb.postinst: Remove regular files installed by d-i
+ (Closes: #1012601)
+
+ -- Ben Hutchings <benh@debian.org> Thu, 30 Jun 2022 00:01:25 +0200
+
wireless-regdb (2022.04.08-1~progress6+u1) fuchur-backports; urgency=medium
* Uploading to fuchur-backports, remaining changes:
diff --git a/debian/tests/check-signatures b/debian/tests/check-signatures
new file mode 100755
index 0000000..1845f71
--- /dev/null
+++ b/debian/tests/check-signatures
@@ -0,0 +1,136 @@
+#!/usr/bin/python3
+
+# Check that signatures on regulatory.db are valid and made by keys
+# trusted by the current kernel in the target suite
+
+import glob
+import io
+import os
+import os.path
+import re
+import subprocess
+import sys
+
+
+tmp_dir = os.getenv('AUTOPKGTEST_TMP')
+
+
+# Find current major/minor kernel version
+def get_linux_source_name():
+ proc = subprocess.Popen(['dpkg', '-s', 'linux-source'],
+ stdout=subprocess.PIPE)
+ with io.open(proc.stdout.fileno(), encoding='utf-8') as pipe:
+ for line in pipe:
+ match = re.match(r'^Depends:.*\b(linux-source-[0-9.]*)\b', line)
+ if match:
+ return match.group(1)
+ return None
+
+
+# Extract wireless regdb certificate sources
+def extract_certs_source(source_name):
+ certs_subdir = f'{source_name}/net/wireless/certs'
+ subprocess.check_call(['tar', '-C', tmp_dir, '-xa',
+ '-f', f'/usr/src/{source_name}.tar.xz',
+ certs_subdir])
+ return os.path.join(tmp_dir, certs_subdir)
+
+
+c_comment_re = re.compile(r'/\*.*?\*/')
+c_hex_byte_re = re.compile(r'\s*0x([0-9A-Fa-f]{2})\s*')
+
+
+# Convert from a C hex literal array to bytes
+def convert_c_hex_to_bytes(hex):
+ decoded = []
+ hex = c_comment_re.sub(' ', hex)
+ for word in hex.split(','):
+ match = c_hex_byte_re.fullmatch(word)
+ if match:
+ decoded.append(int(match.group(1), 16))
+ elif word.isspace():
+ pass
+ else:
+ raise ValueError()
+ return bytes(decoded)
+
+
+# Convert an X.509 certificate from DER to PEM format
+def convert_cert_der_to_pem(der):
+ proc = subprocess.Popen(['openssl', 'x509', '-inform', 'der',
+ '-outform' 'pem'],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE)
+ pem, _ = proc.communicate(der)
+ proc.wait()
+ return pem
+
+
+# Return an array of (cert, is_upstream] pairs. Each cert is in PEM
+# format. The is_upstream flag is false for certificates found in
+# "debian.hex" and otherwise true.
+def convert_certs(certs_source_dir):
+ certs = []
+
+ for hex_name in glob.glob(f'{certs_source_dir}/*.hex'):
+ is_upstream = os.path.basename(hex_name) != 'debian.hex'
+ decoded = convert_c_hex_to_bytes(open(hex_name).read())
+
+ # Split into certificates and convert one at a time, as the
+ # openssl command line doesn't seem to support this
+ start = 0
+ while start < len(decoded):
+ end = decoded.find(b'\x30\x82\x02', start + 3)
+ if end < 0:
+ end = len(decoded)
+ certs.append((convert_cert_der_to_pem(decoded[start:end]),
+ is_upstream))
+ start = end
+
+ return certs
+
+
+# Verify a PKCS#7 signature where the signer must exactly match
+# one of the given PEM-format X.509 certificates
+def verify_signature(payload_name, signature_name, certs):
+ cert_name = os.path.join(tmp_dir, 'certificate.pem')
+ with open(cert_name, 'wb') as cert_file:
+ for cert in certs:
+ cert_file.write(cert)
+
+ # The certificates used here are self-signed and not CAs. This
+ # means we need to turn off vertification of the certificates
+ # (-noverify). We then to ignore the certificate in the signature
+ # (-nointern), so that the signature is required to have been made
+ # by one of the certificates we pass in (I hope).
+ # The payload is printed to stdout by default, so disable that.
+ # Successful verification is reported to stderr, which autopkgtest
+ # counts as a failure, so redirect that to our stdout.
+ subprocess.check_call(['openssl', 'smime', '-verify', '-noverify',
+ '-certfile', cert_name, '-nointern',
+ '-no_check_time',
+ '-content', payload_name,
+ '-in', signature_name, '-inform', 'der'],
+ stdout=subprocess.DEVNULL,
+ stderr=1)
+
+
+def main():
+ source_name = get_linux_source_name()
+ certs_source_dir = extract_certs_source(source_name)
+ certs = convert_certs(certs_source_dir)
+ certs_upstream = [cert
+ for cert, is_upstream in certs
+ if is_upstream]
+ certs_debian = [cert for cert, is_upstream in certs]
+
+ verify_signature('/lib/firmware/regulatory.db-upstream',
+ '/lib/firmware/regulatory.db.p7s-upstream',
+ certs_upstream)
+ verify_signature('/lib/firmware/regulatory.db-debian',
+ '/lib/firmware/regulatory.db.p7s-debian',
+ certs_debian)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/debian/tests/control b/debian/tests/control
new file mode 100644
index 0000000..8e72cc8
--- /dev/null
+++ b/debian/tests/control
@@ -0,0 +1,2 @@
+Tests: check-signatures
+Depends: wireless-regdb, linux-source, openssl, python3
diff --git a/debian/wireless-regdb.postinst b/debian/wireless-regdb.postinst
index 9cdbcb8..8432e70 100644
--- a/debian/wireless-regdb.postinst
+++ b/debian/wireless-regdb.postinst
@@ -3,6 +3,19 @@
set -e
if [ "$1" = "configure" ]; then
+ # d-i currently installs its copies of regulatory.db{,.p7s} as
+ # regular files, which we need to remove before running
+ # update-alternatives
+ if dpkg --compare-versions "$2" lt 2022.04.08-2~; then
+ for file in regulatory.db regulatory.db.p7s; do
+ if [ ! -L /lib/firmware/"$file" ] || \
+ [ "$(readlink /lib/firmware/"$file")" != \
+ /etc/alternatives/"$file" ]; then
+ rm -f /lib/firmware/"$file"
+ fi
+ done
+ fi
+
update-alternatives --install \
/lib/firmware/regulatory.db regulatory.db /lib/firmware/regulatory.db-debian 100 \
--slave /lib/firmware/regulatory.db.p7s regulatory.db.p7s /lib/firmware/regulatory.db.p7s-debian