initial commit
This commit is contained in:
commit
25dddb2c8b
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
# Build artifacts
|
||||
build/
|
||||
dist/
|
||||
*.rpm
|
||||
*.src.rpm
|
||||
*.tar.gz
|
||||
ksigner.spec
|
||||
src/ksigner
|
||||
docs/ksigner.8
|
||||
|
||||
# Temporary files
|
||||
*~
|
||||
*.swp
|
||||
*.tmp
|
||||
|
||||
# RPM build artifacts
|
||||
noarch/
|
||||
x86_64/
|
||||
SOURCES/
|
||||
SPECS/
|
||||
BUILD/
|
||||
BUILDROOT/
|
||||
RPMS/
|
||||
SRPMS/
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 KSigner Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
59
Makefile
Normal file
59
Makefile
Normal file
@ -0,0 +1,59 @@
|
||||
NAME = ksigner
|
||||
VERSION = $(shell cat VERSION)
|
||||
RELEASE = $(shell cat RELEASE)
|
||||
SOURCEDIR = .
|
||||
BUILDDIR = build
|
||||
SOURCES = src/ksigner src/ksigner.conf src/ksigner-update-hook docs/ksigner.8 README.md LICENSE
|
||||
CLEANFILES = $(BUILDDIR) $(NAME).spec src/$(NAME) docs/$(NAME).8 noarch *.tar.gz *.rpm *.src.rpm
|
||||
|
||||
.PHONY: all clean dist rpm srpm install
|
||||
|
||||
all: dist
|
||||
|
||||
clean:
|
||||
rm -rf $(CLEANFILES)
|
||||
|
||||
$(BUILDDIR):
|
||||
mkdir -p $(BUILDDIR)
|
||||
|
||||
%.spec: %.spec.in VERSION RELEASE
|
||||
sed -e 's/@VERSION@/$(VERSION)/g' \
|
||||
-e 's/@RELEASE@/$(RELEASE)/g' \
|
||||
$< > $@
|
||||
|
||||
src/%: src/%.in VERSION RELEASE
|
||||
sed -e 's/@VERSION@/$(VERSION)/g' \
|
||||
$< > $@
|
||||
|
||||
docs/%: docs/%.in VERSION RELEASE
|
||||
sed -e 's/@VERSION@/$(VERSION)/g' \
|
||||
$< > $@
|
||||
|
||||
dist: $(BUILDDIR) $(NAME).spec src/$(NAME) docs/$(NAME).8
|
||||
mkdir -p $(BUILDDIR)/$(NAME)-$(VERSION)
|
||||
cp -r $(SOURCES) $(NAME).spec $(BUILDDIR)/$(NAME)-$(VERSION)/
|
||||
cd $(BUILDDIR) && tar -czf $(NAME)-$(VERSION).tar.gz $(NAME)-$(VERSION)/
|
||||
cp $(BUILDDIR)/$(NAME)-$(VERSION).tar.gz $(SOURCEDIR)
|
||||
|
||||
srpm: dist
|
||||
rpmbuild --define "_topdir $(PWD)/$(BUILDDIR)" \
|
||||
--define "_sourcedir $(PWD)" \
|
||||
--define "_srcrpmdir $(PWD)" \
|
||||
-bs $(NAME).spec
|
||||
|
||||
rpm: dist
|
||||
rpmbuild --define "_topdir $(PWD)/$(BUILDDIR)" \
|
||||
--define "_sourcedir $(PWD)" \
|
||||
--define "_rpmdir $(PWD)" \
|
||||
--define "_buildrootdir $(PWD)/$(BUILDDIR)" \
|
||||
-ba $(NAME).spec
|
||||
|
||||
install:
|
||||
install -d $(DESTDIR)/usr/bin
|
||||
install -d $(DESTDIR)/etc/ksigner
|
||||
install -d $(DESTDIR)/etc/kernel/postinst.d
|
||||
install -d $(DESTDIR)/usr/share/man/man8
|
||||
install -m 755 src/ksigner $(DESTDIR)/usr/bin/
|
||||
install -m 644 src/ksigner.conf $(DESTDIR)/etc/ksigner/
|
||||
install -m 755 src/ksigner-update-hook $(DESTDIR)/etc/kernel/postinst.d/zz-ksigner
|
||||
install -m 644 docs/ksigner.8 $(DESTDIR)/usr/share/man/man8/
|
171
README.md
Normal file
171
README.md
Normal file
@ -0,0 +1,171 @@
|
||||
```bash
|
||||
# Enable/disable automatic signing on kernel updates# Kernel Signer
|
||||
|
||||
A secure boot kernel signing utility for Red Hat based systems (RHEL, CentOS, Fedora, Rocky Linux, AlmaLinux, etc.).
|
||||
|
||||
## Overview
|
||||
|
||||
This package provides a comprehensive solution for signing Linux kernels with custom keys for Secure Boot environments. It includes:
|
||||
|
||||
- Automatic key generation and MOK enrollment
|
||||
- Support for signing individual or all kernels
|
||||
- Configurable through `/etc/ksigner/ksigner.conf`
|
||||
- Comprehensive logging and status reporting
|
||||
|
||||
## Installation
|
||||
|
||||
### Building the RPM
|
||||
|
||||
1. Install build dependencies:
|
||||
```bash
|
||||
# RHEL/CentOS/Rocky/Alma
|
||||
sudo dnf install rpm-build rpmdevtools
|
||||
|
||||
# Create build environment
|
||||
rpmdev-setuptree
|
||||
```
|
||||
|
||||
2. Build the package:
|
||||
```bash
|
||||
# Create source tarball
|
||||
make dist
|
||||
|
||||
# Build RPM
|
||||
make rpm
|
||||
|
||||
# Or build source RPM
|
||||
make srpm
|
||||
```
|
||||
|
||||
3. Install the package:
|
||||
```bash
|
||||
sudo rpm -ivh ksigner*.rpm
|
||||
```
|
||||
|
||||
### Dependencies
|
||||
|
||||
The following packages will be automatically installed as dependencies:
|
||||
- `openssl` - Key generation and certificate operations
|
||||
- `mokutil` - Machine Owner Key management
|
||||
- `sbsigntools` - Kernel signing utilities
|
||||
- `hmaccalc` - HMAC generation for signed kernels
|
||||
- `sudo` - Privilege escalation
|
||||
- `bash` (>= 4.0) - Shell scripting features
|
||||
|
||||
## Quick Start
|
||||
|
||||
1. **Install the package** (as shown above)
|
||||
|
||||
2. **Set up signing keys**:
|
||||
```bash
|
||||
sudo ksigner setup
|
||||
```
|
||||
|
||||
3. **Reboot and enroll MOK keys**:
|
||||
- Reboot your system
|
||||
- In the MOK management interface: Enroll MOK → Continue → Yes → Enter password → OK
|
||||
|
||||
4. **Sign kernels**:
|
||||
```bash
|
||||
# Sign latest kernel
|
||||
sudo ksigner sign
|
||||
|
||||
# Sign all kernels
|
||||
sudo ksigner sign-all
|
||||
|
||||
# Check status
|
||||
sudo ksigner status
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Edit `/etc/ksigner/ksigner.conf` to customize behavior:
|
||||
|
||||
```bash
|
||||
# Enable/disable automatic signing on kernel updates
|
||||
SIGN_ON_UPDATE=true
|
||||
|
||||
# Type of automatic signing (sign, sign-lts, sign-all, sign-all-lts)
|
||||
AUTO_SIGN_TYPE="sign-lts"
|
||||
|
||||
# Define which kernel versions are considered LTS
|
||||
LTS_VERSIONS=(
|
||||
"6.12"
|
||||
"6.6"
|
||||
"6.1"
|
||||
"5.15"
|
||||
"5.10"
|
||||
)
|
||||
```
|
||||
|
||||
## Commands
|
||||
|
||||
- `ksigner setup` - Create and install signing keys
|
||||
- `ksigner sign [kernel_file]` - Sign a kernel (latest if no file specified)
|
||||
- `ksigner sign-lts [kernel_file]` - Sign an LTS kernel
|
||||
- `ksigner sign-all` - Sign all available kernels
|
||||
- `ksigner sign-all-lts` - Sign all LTS kernels
|
||||
- `ksigner status` - Show signing key status
|
||||
- `ksigner version` - Show version information
|
||||
|
||||
## Automatic Kernel Signing
|
||||
|
||||
When `SIGN_ON_UPDATE=true` in the configuration, kernels are automatically signed when installed via package manager. The hook script `/etc/kernel/postinst.d/zz-ksigner` handles this process.
|
||||
|
||||
Logs are written to `/var/log/ksigner.log`.
|
||||
|
||||
## File Locations
|
||||
|
||||
- **Configuration**: `/etc/ksigner/ksigner.conf`
|
||||
- **Public Key**: `/etc/pki/sbsign/certs/MOK.pem`
|
||||
- **Private Key**: `/etc/pki/sbsign/private/MOK.priv`
|
||||
- **DER Key**: `/etc/pki/sbsign/certs/MOK.der`
|
||||
- **Log File**: `/var/log/ksigner.log`
|
||||
- **Update Hook**: `/etc/kernel/postinst.d/zz-ksigner`
|
||||
|
||||
## Security Notes
|
||||
|
||||
- Private keys are stored with restrictive permissions (600)
|
||||
- MOK enrollment requires manual confirmation to prevent unauthorized access
|
||||
- All operations require root privileges
|
||||
- HMAC files are generated for integrity verification
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Check Status
|
||||
```bash
|
||||
sudo ksigner status
|
||||
```
|
||||
|
||||
### View Logs
|
||||
```bash
|
||||
sudo tail -f /var/log/ksigner.log
|
||||
```
|
||||
|
||||
### Verify MOK Enrollment
|
||||
```bash
|
||||
sudo mokutil --list-enrolled
|
||||
```
|
||||
|
||||
### Re-enroll Keys
|
||||
If keys become corrupted or lost:
|
||||
```bash
|
||||
sudo ksigner setup
|
||||
# Then reboot and re-enroll MOK
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
This software is released under the MIT License. See LICENSE file for details.
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! Please submit pull requests or issues through the project repository.
|
||||
|
||||
## Support
|
||||
|
||||
For support, please:
|
||||
1. Check the man page: `man ksigner`
|
||||
2. Review logs in `/var/log/ksigner.log`
|
||||
3. Use the status command: `sudo ksigner status`
|
||||
4. File issues in the project repository
|
147
docs/ksigner.8.in
Normal file
147
docs/ksigner.8.in
Normal file
@ -0,0 +1,147 @@
|
||||
.TH KSIGNER 8 "September 2025" "ksigner @VERSION@" "System Administration"
|
||||
|
||||
.SH NAME
|
||||
ksigner \- Secure Boot kernel signing utility
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B ksigner
|
||||
.RI { setup | sign | sign-all | version | status }
|
||||
.RI [ vmlinuz_kernel_filepath ]
|
||||
|
||||
.SH DESCRIPTION
|
||||
.B ksigner
|
||||
is a utility for signing Linux kernels with custom keys for Secure Boot environments.
|
||||
It supports signing individual kernels or all available kernels.
|
||||
|
||||
.SH COMMANDS
|
||||
.TP
|
||||
.B setup
|
||||
Create and install signing keys. This must be run before any signing operations.
|
||||
The command generates RSA-4096 keys, converts them to appropriate formats,
|
||||
installs them in the system directories, and imports them to the Machine Owner Key (MOK) database.
|
||||
After running this command, you must reboot and enroll the keys through the MOK management interface.
|
||||
|
||||
.TP
|
||||
.B sign
|
||||
Sign a single kernel file. If no kernel filepath is provided, signs the latest available kernel.
|
||||
|
||||
.TP
|
||||
.B sign-all
|
||||
Sign all available kernels in /boot that match the pattern vmlinuz-*.
|
||||
Excludes rescue kernels.
|
||||
|
||||
.TP
|
||||
.B version
|
||||
Display version information.
|
||||
|
||||
.TP
|
||||
.B status
|
||||
Show the current status of signing keys and MOK enrollment.
|
||||
|
||||
.SH FILES
|
||||
.TP
|
||||
.I /etc/ksigner/ksigner.conf
|
||||
Main configuration file. Contains key paths, automatic signing settings, and LTS version definitions.
|
||||
|
||||
.TP
|
||||
.I /etc/pki/sbsign/certs/MOK.pem
|
||||
Public signing key in PEM format.
|
||||
|
||||
.TP
|
||||
.I /etc/pki/sbsign/private/MOK.priv
|
||||
Private signing key.
|
||||
|
||||
.TP
|
||||
.I /etc/pki/sbsign/certs/MOK.der
|
||||
Public signing key in DER format for MOK import.
|
||||
|
||||
.TP
|
||||
.I /etc/kernel/postinst.d/zz-ksigner
|
||||
Kernel update hook script for automatic signing.
|
||||
|
||||
.TP
|
||||
.I /var/log/ksigner.log
|
||||
Log file for automatic signing operations.
|
||||
|
||||
.SH CONFIGURATION
|
||||
The behavior of ksigner can be customized through the configuration file
|
||||
.IR /etc/ksigner/ksigner.conf .
|
||||
Key configuration options include:
|
||||
|
||||
.TP
|
||||
.B KEY_LIFETIME_DAYS
|
||||
Number of days the signing keys should remain valid (default: 36500, approximately 100 years).
|
||||
|
||||
.TP
|
||||
.B SIGN_ON_UPDATE
|
||||
Enable or disable automatic signing when kernels are updated (default: true).
|
||||
|
||||
.TP
|
||||
.B AUTO_SIGN_TYPE
|
||||
Type of automatic signing to perform on kernel updates.
|
||||
Valid options are: sign, sign-all (default: sign).
|
||||
|
||||
.SH AUTOMATIC KERNEL SIGNING
|
||||
When SIGN_ON_UPDATE is enabled in the configuration, new kernels are automatically signed
|
||||
when they are installed through the package manager. The kernel update hook script
|
||||
.I /etc/kernel/postinst.d/zz-ksigner
|
||||
is executed during kernel package installation and performs the configured signing operation.
|
||||
|
||||
.SH EXAMPLES
|
||||
.TP
|
||||
Set up signing keys for the first time:
|
||||
.B ksigner setup
|
||||
|
||||
.TP
|
||||
Sign the latest kernel:
|
||||
.B ksigner sign
|
||||
|
||||
.TP
|
||||
Sign a specific kernel:
|
||||
.B ksigner sign /boot/vmlinuz-6.1.0-13-amd64
|
||||
|
||||
.TP
|
||||
Sign all kernels:
|
||||
.B ksigner sign-all
|
||||
|
||||
.TP
|
||||
Check the status of signing keys:
|
||||
.B ksigner status
|
||||
|
||||
.SH REQUIREMENTS
|
||||
The following packages must be installed for ksigner to function:
|
||||
.IP \(bu 4
|
||||
openssl - for key generation and certificate operations
|
||||
.IP \(bu 4
|
||||
mokutil - for Machine Owner Key management
|
||||
.IP \(bu 4
|
||||
sbsigntools - for signing kernels (provides sbsign command)
|
||||
.IP \(bu 4
|
||||
hmaccalc - for generating kernel HMAC files
|
||||
.IP \(bu 4
|
||||
sudo - for privilege escalation
|
||||
.IP \(bu 4
|
||||
bash (version 4.0 or later) - for shell scripting features
|
||||
|
||||
.SH SECURITY CONSIDERATIONS
|
||||
.IP \(bu 4
|
||||
Private keys are stored with restrictive permissions (600) in /etc/pki/sbsign/private/
|
||||
.IP \(bu 4
|
||||
The setup process requires manual MOK enrollment to prevent unauthorized key installation
|
||||
.IP \(bu 4
|
||||
All operations require root privileges
|
||||
.IP \(bu 4
|
||||
HMAC files are generated for signed kernels to maintain integrity
|
||||
|
||||
.SH EXIT STATUS
|
||||
.B ksigner
|
||||
exits with status 0 on success, and non-zero on error.
|
||||
|
||||
.SH BUGS
|
||||
Report bugs to your distribution's bug tracking system or the project repository.
|
||||
|
||||
.SH SEE ALSO
|
||||
.BR mokutil (8),
|
||||
.BR sbsign (1),
|
||||
.BR openssl (1),
|
||||
.BR systemctl (1)
|
70
ksigner.spec.in
Normal file
70
ksigner.spec.in
Normal file
@ -0,0 +1,70 @@
|
||||
Name: ksigner
|
||||
Version: @VERSION@
|
||||
Release: @RELEASE@%{?dist}
|
||||
Summary: Secure Boot kernel signing utility
|
||||
|
||||
License: MIT
|
||||
URL: https://git.radon.win/radon/ksigner
|
||||
Source0: %{name}-%{version}.tar.gz
|
||||
|
||||
BuildArch: noarch
|
||||
|
||||
Requires: openssl
|
||||
Requires: mokutil
|
||||
Requires: sbsigntools
|
||||
Requires: hmaccalc
|
||||
Requires: sudo
|
||||
Requires: bash >= 4.0
|
||||
|
||||
%description
|
||||
A utility for signing Linux kernels with custom keys for Secure Boot.
|
||||
Supports signing individual kernels or all kernels.
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
||||
%build
|
||||
# Nothing to build - shell script
|
||||
|
||||
%install
|
||||
# Create directories
|
||||
install -d %{buildroot}%{_bindir}
|
||||
install -d %{buildroot}%{_sysconfdir}/ksigner
|
||||
install -d %{buildroot}%{_unitdir}
|
||||
install -d %{buildroot}%{_sysconfdir}/kernel/postinst.d
|
||||
install -d %{buildroot}%{_mandir}/man8
|
||||
|
||||
# Install main script
|
||||
install -m 755 ksigner %{buildroot}%{_bindir}/ksigner
|
||||
|
||||
# Install configuration file
|
||||
install -m 644 ksigner.conf %{buildroot}%{_sysconfdir}/ksigner/ksigner.conf
|
||||
|
||||
# Install kernel update hook
|
||||
install -m 755 ksigner-update-hook %{buildroot}%{_sysconfdir}/kernel/postinst.d/zz-ksigner
|
||||
|
||||
# Install man page
|
||||
install -m 644 ksigner.8 %{buildroot}%{_mandir}/man8/ksigner.8
|
||||
|
||||
%post
|
||||
echo "==========================================="
|
||||
echo "Kernel Signer has been installed."
|
||||
echo "To set up kernel signing:"
|
||||
echo " 1. Run: sudo ksigner setup"
|
||||
echo " 2. Reboot your system"
|
||||
echo " 3. In MOK Manager: Enroll MOK → Continue → Yes → Enter password"
|
||||
echo "==========================================="
|
||||
|
||||
%files
|
||||
%license LICENSE
|
||||
%doc README.md
|
||||
%{_bindir}/ksigner
|
||||
%config(noreplace) %{_sysconfdir}/ksigner/ksigner.conf
|
||||
%{_sysconfdir}/kernel/postinst.d/zz-ksigner
|
||||
%{_mandir}/man8/ksigner.8*
|
||||
|
||||
%changelog
|
||||
* Tue Sep 23 2025 RadioactivePb <radioactivepb@gmail.com> - @VERSION@-@RELEASE@
|
||||
- Initial RPM release
|
||||
- Added automatic kernel signing on updates
|
||||
- Added configuration file support
|
67
src/ksigner-update-hook
Normal file
67
src/ksigner-update-hook
Normal file
@ -0,0 +1,67 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Kernel update hook for automatic signing
|
||||
# This script is called when new kernels are installed
|
||||
|
||||
CONFIG_FILE="/etc/ksigner/ksigner.conf"
|
||||
KERNEL_SIGNER="/usr/bin/ksigner"
|
||||
LOG_FILE="/var/log/ksigner.log"
|
||||
|
||||
# Source configuration
|
||||
if [[ -f "$CONFIG_FILE" ]]; then
|
||||
source "$CONFIG_FILE"
|
||||
fi
|
||||
|
||||
# Default values
|
||||
SIGN_ON_UPDATE=${SIGN_ON_UPDATE:-true}
|
||||
AUTO_SIGN_TYPE=${AUTO_SIGN_TYPE:-sign}
|
||||
LOG_FILE=${LOG_FILE:-/var/log/ksigner.log}
|
||||
|
||||
log_message() {
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') - ksigner-update-hook: $1" >>"$LOG_FILE"
|
||||
}
|
||||
|
||||
# Exit if automatic signing is disabled
|
||||
if [[ "$SIGN_ON_UPDATE" != "true" ]]; then
|
||||
log_message "Automatic signing disabled, skipping"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check if ksigner exists and keys are set up
|
||||
if [[ ! -x "$KERNEL_SIGNER" ]]; then
|
||||
log_message "ksigner not found at $KERNEL_SIGNER"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! -f "/etc/pki/sbsign/certs/MOK.pem" ]]; then
|
||||
log_message "Signing keys not found, run 'ksigner setup' first"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the kernel version from the environment or find the latest
|
||||
if [[ -n "$KERNEL_VERSION" ]]; then
|
||||
KERNEL_FILE="/boot/vmlinuz-$KERNEL_VERSION"
|
||||
if [[ -f "$KERNEL_FILE" ]]; then
|
||||
log_message "Signing newly installed kernel: $KERNEL_VERSION"
|
||||
if "$KERNEL_SIGNER" sign "$KERNEL_FILE" >>"$LOG_FILE" 2>&1; then
|
||||
log_message "Successfully signed kernel $KERNEL_VERSION"
|
||||
else
|
||||
log_message "Failed to sign kernel $KERNEL_VERSION"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
log_message "Kernel file not found: $KERNEL_FILE"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
# Fallback to configured auto-sign type
|
||||
log_message "Running automatic signing: $AUTO_SIGN_TYPE"
|
||||
if "$KERNEL_SIGNER" "$AUTO_SIGN_TYPE" >>"$LOG_FILE" 2>&1; then
|
||||
log_message "Successfully completed $AUTO_SIGN_TYPE"
|
||||
else
|
||||
log_message "Failed to complete $AUTO_SIGN_TYPE"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
exit 0
|
25
src/ksigner.conf
Normal file
25
src/ksigner.conf
Normal file
@ -0,0 +1,25 @@
|
||||
# Configuration file for ksigner
|
||||
# This file is sourced by the ksigner script
|
||||
|
||||
# Key lifetime in days (default: 100 years)
|
||||
KEY_LIFETIME_DAYS=$((365 * 100))
|
||||
|
||||
# Directory paths for keys
|
||||
KEY_PUB_DIR="/etc/pki/sbsign/certs/"
|
||||
KEY_PRIV_DIR="/etc/pki/sbsign/private/"
|
||||
|
||||
# Key filenames
|
||||
KEY_PUB="MOK.pem"
|
||||
KEY_PRIV="MOK.priv"
|
||||
KEY_DER="MOK.der"
|
||||
|
||||
# Automatic signing on kernel updates
|
||||
# Set to true to enable automatic signing when kernels are updated
|
||||
SIGN_ON_UPDATE=true
|
||||
|
||||
# Type of automatic signing to perform
|
||||
# Options: sign, sign-all
|
||||
AUTO_SIGN_TYPE="sign"
|
||||
|
||||
# Log file for automatic signing operations
|
||||
LOG_FILE="/var/log/ksigner.log"
|
276
src/ksigner.in
Normal file
276
src/ksigner.in
Normal file
@ -0,0 +1,276 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# ksigner - Secure Boot kernel signing utility
|
||||
# Version: @VERSION@
|
||||
|
||||
# Source configuration
|
||||
CONFIG_FILE="/etc/ksigner/ksigner.conf"
|
||||
if [[ -f "$CONFIG_FILE" ]]; then
|
||||
source "$CONFIG_FILE"
|
||||
fi
|
||||
|
||||
# Default configuration values (can be overridden in config file)
|
||||
KEY_LIFETIME_DAYS=${KEY_LIFETIME_DAYS:-$((365 * 100))}
|
||||
KEY_PUB_DIR=${KEY_PUB_DIR:-/etc/pki/sbsign/certs/}
|
||||
KEY_PUB=${KEY_PUB:-MOK.pem}
|
||||
KEY_PRIV_DIR=${KEY_PRIV_DIR:-/etc/pki/sbsign/private/}
|
||||
KEY_PRIV=${KEY_PRIV:-MOK.priv}
|
||||
KEY_DER=${KEY_DER:-MOK.der}
|
||||
SIGN_ON_UPDATE=${SIGN_ON_UPDATE:-true}
|
||||
AUTO_SIGN_TYPE=${AUTO_SIGN_TYPE:-sign}
|
||||
|
||||
REQUIRED_BINARIES=(
|
||||
"openssl"
|
||||
"mokutil"
|
||||
"sbsign"
|
||||
"sha512hmac"
|
||||
)
|
||||
|
||||
panic() {
|
||||
echo "ERROR: $1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
log() {
|
||||
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >&2
|
||||
}
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 {setup|sign|sign-all|version|status} [vmlinuz_kernel_filepath]"
|
||||
echo " setup - Create and install signing keys"
|
||||
echo " sign - Sign a kernel file (optional: vmlinuz_kernel_filepath)"
|
||||
echo " sign-all - Sign all available kernels"
|
||||
echo " version - Show version information"
|
||||
echo " status - Show signing key status"
|
||||
exit 1
|
||||
}
|
||||
|
||||
version() {
|
||||
echo "ksigner version @VERSION@"
|
||||
echo "Copyright (C) 2025"
|
||||
echo "This is free software; see the source for copying conditions."
|
||||
}
|
||||
|
||||
status() {
|
||||
echo "Kernel Signer Status:"
|
||||
echo "====================="
|
||||
echo "Public key file: $KEY_PUB_DIR$KEY_PUB"
|
||||
if [[ -f "$KEY_PUB_DIR$KEY_PUB" ]]; then
|
||||
echo " Status: Found"
|
||||
echo " Details:"
|
||||
openssl x509 -in "$KEY_PUB_DIR$KEY_PUB" -noout -subject -dates 2>/dev/null || echo " Error reading certificate"
|
||||
else
|
||||
echo " Status: Not found"
|
||||
fi
|
||||
|
||||
echo "Private key file: $KEY_PRIV_DIR$KEY_PRIV"
|
||||
[[ -f "$KEY_PRIV_DIR$KEY_PRIV" ]] && echo " Status: Found" || echo " Status: Not found"
|
||||
|
||||
echo "DER key file: $KEY_PUB_DIR$KEY_DER"
|
||||
[[ -f "$KEY_PUB_DIR$KEY_DER" ]] && echo " Status: Found" || echo " Status: Not found"
|
||||
|
||||
echo "MOK keys enrolled:"
|
||||
mokutil --list-enrolled 2>/dev/null | grep -A 3 -B 1 "Kernel Signing" || echo " No custom MOK keys found"
|
||||
|
||||
echo "Configuration file: $CONFIG_FILE"
|
||||
[[ -f "$CONFIG_FILE" ]] && echo " Status: Found" || echo " Status: Using defaults"
|
||||
}
|
||||
|
||||
req_check() {
|
||||
local missing_binaries=()
|
||||
for binary in "${REQUIRED_BINARIES[@]}"; do
|
||||
if ! command -v "$binary" >/dev/null 2>&1; then
|
||||
missing_binaries+=("$binary")
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ${#missing_binaries[@]} -gt 0 ]]; then
|
||||
echo "Missing required binaries: ${missing_binaries[*]}" >&2
|
||||
echo "Please install the following packages:" >&2
|
||||
for binary in "${missing_binaries[@]}"; do
|
||||
case "$binary" in
|
||||
"openssl") echo " - openssl" >&2 ;;
|
||||
"mokutil") echo " - mokutil" >&2 ;;
|
||||
"sbsign") echo " - sbsigntools" >&2 ;;
|
||||
"sha512hmac") echo " - hmaccalc" >&2 ;;
|
||||
esac
|
||||
done
|
||||
exit 1
|
||||
fi
|
||||
log "All required binaries are present"
|
||||
}
|
||||
|
||||
version_greater() {
|
||||
local ver1="$1"
|
||||
local ver2="$2"
|
||||
[ "$ver1" = "$(printf '%s\n%s' "$ver1" "$ver2" | sort -V | tail -n1)" ]
|
||||
}
|
||||
|
||||
find_all_kernels() {
|
||||
local all_files=()
|
||||
for file in /boot/vmlinuz-*; do
|
||||
[ -f "$file" ] || continue
|
||||
if [[ "$file" == *"rescue"* ]]; then
|
||||
continue
|
||||
fi
|
||||
all_files+=("$file")
|
||||
done
|
||||
echo "${all_files[@]}"
|
||||
}
|
||||
|
||||
find_latest_kernel() {
|
||||
local latest_file=""
|
||||
local latest_version=""
|
||||
for file in /boot/vmlinuz-*; do
|
||||
[ -f "$file" ] || continue
|
||||
if [[ "$file" == *"rescue"* ]]; then
|
||||
continue
|
||||
fi
|
||||
local kver="${file#*vmlinuz-}"
|
||||
kver="${kver%%-*}"
|
||||
if [ -z "$latest_version" ] || version_greater "$kver" "$latest_version"; then
|
||||
latest_version="$kver"
|
||||
latest_file="$file"
|
||||
fi
|
||||
done
|
||||
echo "$latest_file"
|
||||
}
|
||||
|
||||
setup_signing_keys() {
|
||||
# Step 1: Create the signing keys
|
||||
log "[Step 1] Creating signing keys..."
|
||||
openssl req -new -x509 -newkey rsa:4096 \
|
||||
-keyout $KEY_PRIV \
|
||||
-outform DER -out $KEY_DER \
|
||||
-nodes -days $KEY_LIFETIME_DAYS -subj "/CN=Kernel Signing/" ||
|
||||
panic "[Step 1] Failed to create signing keys"
|
||||
|
||||
# Step 2: Convert the keys to PEM format
|
||||
log "[Step 2] Converting keys to PEM format..."
|
||||
openssl x509 -inform der -in $KEY_DER -out $KEY_PUB ||
|
||||
panic "[Step 2] Failed to convert keys to PEM format"
|
||||
|
||||
# Step 3: Create the directory for the keys
|
||||
log "[Step 3] Creating the directory for the keys..."
|
||||
mkdir -p $KEY_PUB_DIR $KEY_PRIV_DIR ||
|
||||
panic "[Step 3] Failed to create the directory for the keys"
|
||||
|
||||
# Step 4: Copy the keys to the directory
|
||||
log "[Step 4] Copying the keys to the directory..."
|
||||
mv -f $KEY_DER $KEY_PUB $KEY_PUB_DIR ||
|
||||
panic "[Step 4a] Failed to copy the keys to the directory"
|
||||
mv -f $KEY_PRIV $KEY_PRIV_DIR ||
|
||||
panic "[Step 4b] Failed to copy the keys to the directory"
|
||||
|
||||
# Step 5: Set the permissions for the keys
|
||||
log "[Step 5] Setting the permissions for the keys..."
|
||||
chmod -R 600 $KEY_PRIV_DIR ||
|
||||
panic "[Step 5] Failed to set the permissions for the keys"
|
||||
|
||||
# Step 6: Import the keys to the MOK
|
||||
log "[Step 6] Importing the keys to the MOK..."
|
||||
mokutil --import $KEY_PUB_DIR$KEY_DER ||
|
||||
panic "[Step 6] Failed to import the keys to the MOK"
|
||||
|
||||
echo
|
||||
log "Signing keys have been created and installed"
|
||||
echo
|
||||
echo "Please reboot your computer and enroll the keys with MOK"
|
||||
echo
|
||||
echo "Enroll MOK -> Continue -> Yes -> Enter password -> OK"
|
||||
echo
|
||||
}
|
||||
|
||||
sign_kernel() {
|
||||
local kern_version="$1"
|
||||
local kern_file="$2"
|
||||
|
||||
# Step 1: Sign the kernel
|
||||
log "[Step 1] Signing '$kern_version'..."
|
||||
/usr/bin/sbsign \
|
||||
--key "$KEY_PRIV_DIR$KEY_PRIV" \
|
||||
--cert "$KEY_PUB_DIR$KEY_PUB" \
|
||||
"$kern_file" \
|
||||
--output "$kern_file.signed" ||
|
||||
panic "[Step 1] Failed to sign '$kern_version'"
|
||||
|
||||
# Step 2: Verify the kernel was signed
|
||||
log "[Step 2] Verifying '$kern_file' was signed"
|
||||
[ -f "$kern_file.signed" ] ||
|
||||
panic "'$kern_file.signed' was not found"
|
||||
|
||||
# Step 3: Move the signed kernel
|
||||
log "[Step 3] Moving '$kern_file.signed' to '$kern_file'"
|
||||
mv -f "$kern_file.signed" "$kern_file" ||
|
||||
panic "Failed to move '$kern_file.signed'"
|
||||
|
||||
# Step 4: Make the kernel executable
|
||||
log "[Step 4] Setting permissions for '$kern_file'"
|
||||
chmod +x "$kern_file" ||
|
||||
panic "Failed to make '$kern_file' executable"
|
||||
|
||||
# Step 5: Create the HMAC
|
||||
log "[Step 5] Creating HMAC for '$kern_file'"
|
||||
sha512hmac "$kern_file" >"${kern_file/vmlinuz/.vmlinuz}.hmac" ||
|
||||
panic "Failed to create HMAC for '$kern_file'"
|
||||
|
||||
echo
|
||||
log "Signed '$kern_version' successfully"
|
||||
echo
|
||||
}
|
||||
|
||||
file_checks() {
|
||||
local kfile="$1"
|
||||
[ -e "$kfile" ] ||
|
||||
panic "Kernel file '$kfile' was not found"
|
||||
[ -e "$KEY_PUB_DIR$KEY_PUB" ] ||
|
||||
panic "'$KEY_PUB_DIR$KEY_PUB' was not found, please run 'setup' first"
|
||||
[ -e "$KEY_PRIV_DIR$KEY_PRIV" ] ||
|
||||
panic "'$KEY_PRIV_DIR$KEY_PRIV' was not found, please run 'setup' first"
|
||||
}
|
||||
|
||||
main() {
|
||||
case "$1" in
|
||||
"setup")
|
||||
req_check
|
||||
setup_signing_keys
|
||||
;;
|
||||
"sign")
|
||||
req_check
|
||||
shift
|
||||
[ -n "$1" ] &&
|
||||
kfile="$1" ||
|
||||
kfile="$(find_latest_kernel)"
|
||||
kver="${kfile#*vmlinuz-}"
|
||||
kver="${kver%%-*}"
|
||||
file_checks "$kfile"
|
||||
sign_kernel "$kver" "$kfile"
|
||||
;;
|
||||
"sign-all")
|
||||
req_check
|
||||
all_kernels_str=$(find_all_kernels)
|
||||
read -ra all_kernels <<<"$all_kernels_str"
|
||||
for kfile in "${all_kernels[@]}"; do
|
||||
[ -n "$kfile" ] || continue
|
||||
kver="${kfile#*vmlinuz-}"
|
||||
kver="${kver%%-*}"
|
||||
file_checks "$kfile"
|
||||
sign_kernel "$kver" "$kfile"
|
||||
done
|
||||
;;
|
||||
"version")
|
||||
version
|
||||
;;
|
||||
"status")
|
||||
status
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Ensure running as root
|
||||
[[ $EUID -eq 0 ]] || exec sudo "$0" "$@"
|
||||
|
||||
main "$@"
|
Loading…
x
Reference in New Issue
Block a user