Add initial luks encryption support

This has to be the worst code I've ever written 💀
axtloss/rework-partitioning
axtloss 2 years ago
parent 8cd714f537
commit e2a8735bee
No known key found for this signature in database
GPG Key ID: DD6D66939396C90E

@ -95,6 +95,14 @@ pub struct PartitionArgs {
#[clap(long)] #[clap(long)]
pub efi: bool, pub efi: bool,
/// If the install destination should be encrypted
#[clap(long)]
pub encrypted: bool,
/// The password to use for the encrypted partition
#[clap(long, required_if("encrypted", "true"))]
pub password: String,
/// The partitions to use for manual partitioning /// The partitions to use for manual partitioning
#[clap(required_if_eq("mode", "Partition::Manual"), parse(try_from_str = parse_partitions))] #[clap(required_if_eq("mode", "Partition::Manual"), parse(try_from_str = parse_partitions))]
pub partitions: Vec<Partition>, pub partitions: Vec<Partition>,
@ -147,6 +155,9 @@ pub enum BootloaderSubcommand {
GrubEfi { GrubEfi {
/// The directory to install the EFI bootloader to /// The directory to install the EFI bootloader to
efidir: PathBuf, efidir: PathBuf,
/// Wether the install destination is encrypted
encrypted: bool,
}, },
/// Install GRUB in legacy (BIOS) mode /// Install GRUB in legacy (BIOS) mode
@ -154,6 +165,9 @@ pub enum BootloaderSubcommand {
GrubLegacy { GrubLegacy {
/// The device to install the bootloader to /// The device to install the bootloader to
device: PathBuf, device: PathBuf,
/// Wether the install destination is encrypted
encrypted: bool,
}, },
} }

@ -1,5 +1,5 @@
use crate::internal::exec::*; use crate::internal::exec::*;
use crate::internal::files::append_file; use crate::internal::files::{append_file, sed_file};
use crate::internal::*; use crate::internal::*;
use log::warn; use log::warn;
use std::path::PathBuf; use std::path::PathBuf;
@ -101,7 +101,7 @@ pub fn genfstab() {
); );
} }
pub fn install_bootloader_efi(efidir: PathBuf) { pub fn install_bootloader_efi(efidir: PathBuf, encrypt: bool) {
install::install(vec![ install::install(vec![
"grub", "grub",
"efibootmgr", "efibootmgr",
@ -114,6 +114,9 @@ pub fn install_bootloader_efi(efidir: PathBuf) {
if !std::path::Path::new(&format!("/mnt{efi_str}")).exists() { if !std::path::Path::new(&format!("/mnt{efi_str}")).exists() {
crash(format!("The efidir {efidir:?} doesn't exist"), 1); crash(format!("The efidir {efidir:?} doesn't exist"), 1);
} }
if encrypt {
install_bootloader_encryption(true);
}
exec_eval( exec_eval(
exec_chroot( exec_chroot(
"grub-install", "grub-install",
@ -153,7 +156,7 @@ pub fn install_bootloader_efi(efidir: PathBuf) {
); );
} }
pub fn install_bootloader_legacy(device: PathBuf) { pub fn install_bootloader_legacy(device: PathBuf, encrypt: bool) {
install::install(vec![ install::install(vec![
"grub", "grub",
"crystal-grub-theme", "crystal-grub-theme",
@ -164,6 +167,9 @@ pub fn install_bootloader_legacy(device: PathBuf) {
crash(format!("The device {device:?} does not exist"), 1); crash(format!("The device {device:?} does not exist"), 1);
} }
let device = device.to_string_lossy().to_string(); let device = device.to_string_lossy().to_string();
if encrypt {
install_bootloader_encryption(false);
}
exec_eval( exec_eval(
exec_chroot( exec_chroot(
"grub-install", "grub-install",
@ -185,6 +191,18 @@ pub fn install_bootloader_legacy(device: PathBuf) {
), ),
"create grub.cfg", "create grub.cfg",
); );
if encrypt {
exec_eval(
exec(
"bash",
vec![
String::from("-c"),
String::from("sed -i 's/root=UUID=[^ ]* rw/rw/g' /mnt/boot/grub/grub.cfg"),
],
),
"remove root=UUID from grub",
);
}
} }
pub fn setup_timeshift() { pub fn setup_timeshift() {
@ -223,3 +241,54 @@ pub fn install_zram() {
"Write zram-generator config", "Write zram-generator config",
); );
} }
pub fn install_bootloader_encryption(efi: bool) {
files_eval(
sed_file(
"/mnt/etc/mkinitcpio.conf",
"HOOKS=(base udev autodetect modconf kms keyboard keymap consolefont block filesystems fsck)",
"HOOKS=(base udev autodetect modconf kms keyboard keymap consolefont block encrypt filesystems fsck)"
),
"enable encryption in mkinitcpio",
);
files_eval(
sed_file(
"/mnt/etc/default/grub",
"GRUB_CMDLINE_LINUX_DEFAULT=\"loglevel=3 quiet\"",
"GRUB_CMDLINE_LINUX_DEFAULT=\"loglevel=3 quiet cryptdevice=UUID=:crystal_root root=/dev/mapper/crystal_root\""
),
"enable encryption in grub",
);
exec_eval(
exec(
"chmod",
vec![
String::from("-x"),
String::from("/tmp/encryption.sh"),
],
),
"Make encryption script executable",
);
exec_eval(
exec(
"bash",
vec![
String::from("/tmp/encryption.sh"),
],
),
"Run encryption script",
);
exec_eval(
exec_chroot(
"mkinitcpio",
vec![
String::from("-P"),
],
),
"Regenerate initramfs",
);
}

@ -88,6 +88,8 @@ pub fn partition(
device: PathBuf, device: PathBuf,
mode: PartitionMode, mode: PartitionMode,
efi: bool, efi: bool,
encrypted: bool,
password: String,
partitions: &mut Vec<args::Partition>, partitions: &mut Vec<args::Partition>,
) { ) {
println!("{:?}", mode); println!("{:?}", mode);
@ -101,19 +103,39 @@ pub fn partition(
let part1: String; // This is probably a horrible way of doing this, but the borrow checker is annoying let part1: String; // This is probably a horrible way of doing this, but the borrow checker is annoying
let part2: String; let part2: String;
let partitions: Vec<&str> = if device.to_string_lossy().contains("nvme") let part3: String;
let mut partitions: Vec<&str> = if device.to_string_lossy().contains("nvme")
|| device.to_string_lossy().contains("mmcblk") || device.to_string_lossy().contains("mmcblk")
{ {
if efi {
part1 = format!("{}p1", device.to_string_lossy()); part1 = format!("{}p1", device.to_string_lossy());
part2 = format!("{}p2", device.to_string_lossy()); part2 = format!("{}p2", device.to_string_lossy());
part3 = format!("{}p3", device.to_string_lossy());
vec![part1.as_str(), part2.as_str(), part3.as_str()]
} else {
part1 = format!("{}1", device.to_string_lossy());
part2 = format!("{}2", device.to_string_lossy());
vec![part1.as_str(), part2.as_str()] vec![part1.as_str(), part2.as_str()]
}
} else {
if efi {
part1 = format!("{}1", device.to_string_lossy());
part2 = format!("{}2", device.to_string_lossy());
part3 = format!("{}3", device.to_string_lossy());
vec![part1.as_str(), part2.as_str(), part3.as_str()]
} else { } else {
part1 = format!("{}1", device.to_string_lossy()); part1 = format!("{}1", device.to_string_lossy());
part2 = format!("{}2", device.to_string_lossy()); part2 = format!("{}2", device.to_string_lossy());
vec![part1.as_str(), part2.as_str()] vec![part1.as_str(), part2.as_str()]
}
}; };
auto_format(partitions); let parts: Vec<String>;
mount_disks(efi); if encrypted {
parts = encrypt_partition(partitions, &password, efi);
partitions = parts.iter().map(|s| &**s).collect();
}
auto_format(efi, partitions);
mount_disks(efi, encrypted);
} }
PartitionMode::Manual => { PartitionMode::Manual => {
log::debug!("Manual partitioning"); log::debug!("Manual partitioning");
@ -162,12 +184,27 @@ fn create_partitions(device: &Path, efi: bool) {
String::from(&device), String::from(&device),
String::from("mkpart"), String::from("mkpart"),
String::from("fat32"), String::from("fat32"),
String::from("0"), String::from("1MiB"),
String::from("300"), String::from("125MiB"),
], ],
), ),
"create EFI partition", "create EFI partition",
); );
exec_eval(
exec(
"parted",
vec![
String::from("-s"),
String::from(&device),
String::from("mkpart"),
String::from("primary"),
String::from("ext4"),
String::from("125MIB"),
String::from("637MIB"),
],
),
"create boot partition",
);
} else { } else {
exec_eval( exec_eval(
exec( exec(
@ -194,7 +231,7 @@ fn create_partitions(device: &Path, efi: bool) {
String::from("mkpart"), String::from("mkpart"),
String::from("primary"), String::from("primary"),
String::from("btrfs"), String::from("btrfs"),
String::from("512MIB"), String::from(if efi { "637MiB" } else { "512MIB" } ),
String::from("100%"), String::from("100%"),
], ],
), ),
@ -202,35 +239,142 @@ fn create_partitions(device: &Path, efi: bool) {
); );
} }
fn auto_format(partitions: Vec<&str>) { fn encrypt_partition(partitions: Vec<&str>, passphrase: &str, efi: bool) -> Vec<String> {
exec_eval(
exec(
"bash",
vec![
String::from("-c"),
format!(
"echo {} | cryptsetup luksFormat {}",
passphrase, if efi { partitions[2] } else { partitions[1] }
),
],
),
format!("LUKS encrypt {}", if efi { partitions[2] } else { partitions[1] }).as_str(),
);
exec_eval(
exec(
"bash",
vec![
String::from("-c"),
format!(
"echo {} | cryptsetup luksOpen {} root",
passphrase, if efi { partitions[2] } else { partitions[1] }
),
],
),
format!("LUKS open {}", if efi { partitions[2] } else { partitions[1] }).as_str(),
);
exec_eval(
exec(
"cryptsetup",
vec![
String::from("close"),
String::from("root"),
],
),
format!("LUKS close {}", if efi { partitions[2] } else { partitions[1] }).as_str(),
);
exec_eval(
exec(
"bash",
vec![
String::from("-c"),
format!(
"echo {} | cryptsetup luksOpen {} root",
passphrase, if efi { partitions[2] } else { partitions[1] }
),
],
),
format!("LUKS open {}", if efi { partitions[2] } else { partitions[1] }).as_str(),
);
files::create_file("/tmp/encryption.sh");
files_eval(
files::append_file("/tmp/encryption.sh", "#!/bin/bash"),
"Write encryption script",
);
files_eval(
files::append_file("/tmp/encryption.sh", format!("UUID=$(lsblk -pdfo UUID {} | grep -v UUID)", if efi { partitions[2] } else { partitions[1] }).as_str()),
"Write encryption script",
);
files_eval(
files::append_file("/tmp/encryption.sh", "sed -i \"s/UUID=/UUID=${UUID}/g\" /mnt/etc/default/grub"),
"Write encryption script",
);
if efi {
return vec![
partitions[0].to_string(),
partitions[1].to_string(),
"/dev/mapper/root".to_string(),
];
} else {
return vec![
partitions[0].to_string(),
"/dev/mapper/root".to_string(),
];
}
}
fn auto_format(efi: bool, partitions: Vec<&str>) {
println!("{:?}", partitions);
if efi {
exec_eval( exec_eval(
exec( exec(
"mkfs.vfat", "mkfs.vfat",
vec![ vec![
"-F32".to_string(), "-F32".to_string(),
"-n".to_string(), "-n".to_string(),
"CYRSTAL_EFI".to_string(), "crystal-efi".to_string(),
partitions[0].to_string(), partitions[0].to_string(),
], ],
), ),
format!("format {} as fat32 with label CRYSTAL_EFI", partitions[0]).as_str(), format!("format {} as fat32 with label crystal-efi", partitions[0]).as_str(),
); );
exec_eval( exec_eval(
exec( exec(
"mkfs.btfrs", "mkfs.ext4",
vec![ vec![
"-f".to_string(), "-F".to_string(),
"-L".to_string(), "-L".to_string(),
"CRYSTAL_ROOT".to_string(), "crystal-boot".to_string(),
partitions[1].to_string(), partitions[1].to_string(),
], ],
), ),
format!("format {} as btrfs with label CRYSTAL_ROOT", partitions[1]).as_str(), format!("format {} as ext4 with label crystal-boot", partitions[1]).as_str(),
);
} else {
exec_eval(
exec(
"mkfs.ext4",
vec![
"-F".to_string(),
"-L".to_string(),
"crystal-boot".to_string(),
partitions[0].to_string(),
],
),
format!("format {} as ext4 with label crystal-boot", partitions[0]).as_str(),
)
}
exec_eval(
exec(
"mkfs.btrfs",
vec![
"-f".to_string(),
"-L".to_string(),
"crystal-root".to_string(),
if efi { partitions[2].to_string() } else { partitions[1].to_string() },
],
),
format!("format {} as btrfs with label crystal-root", if efi { partitions[2] } else { partitions[1] }).as_str(),
); );
} }
fn mount_disks(efi: bool) { fn mount_disks(efi: bool, encrypted: bool) {
mount("/dev/disk/by-label/CRYSTAL_ROOT", "/mnt", ""); let root = if encrypted { "/dev/mapper/root" } else { "/dev/disk/by-label/crystal-root" };
mount(root, "/mnt", "");
exec_eval( exec_eval(
exec_workdir( exec_workdir(
"btrfs", "btrfs",
@ -256,22 +400,21 @@ fn mount_disks(efi: bool) {
"create btrfs subvolume @home", "create btrfs subvolume @home",
); );
umount("/mnt"); umount("/mnt");
mount("/dev/disk/by-label/CRYSTAL_ROOT", "/mnt", "subvol=@"); mount(root, "/mnt", "subvol=@");
files_eval(create_directory("/mnt/home"), "create directory /mnt/home"); files_eval(create_directory("/mnt/home"), "create directory /mnt/home");
mount( mount(
"/dev/disk/by-label/CRYSTAL_ROOT", root,
"/mnt/home", "/mnt/home",
"subvol=@home", "subvol=@home",
); );
files_eval(create_directory("/mnt/boot"), "create directory /mnt/boot"); files_eval(create_directory("/mnt/boot"), "create directory /mnt/boot");
mount("/dev/disk/by-label/crystal-boot", "/mnt/boot", "");
if efi { if efi {
files_eval( files_eval(
create_directory("/mnt/boot/efi"), create_directory("/mnt/boot/efi"),
"create directory /mnt/boot/efi", "create directory /mnt/boot/efi",
); );
mount("/dev/disk/by-label/CRYSTAL_EFI", "/mnt/boot/efi", ""); mount("/dev/disk/by-label/crystal-efi", "/mnt/boot/efi", "");
} else {
mount("/dev/disk/by-label/CRYSTAL_BOOT", "/mnt/boot", "");
} }
} }

@ -26,6 +26,8 @@ struct Partition {
device: String, device: String,
mode: PartitionMode, mode: PartitionMode,
efi: bool, efi: bool,
encrypted: bool,
password: String,
partitions: Vec<String>, partitions: Vec<String>,
} }
@ -96,6 +98,8 @@ pub fn read_config(configpath: PathBuf) {
device, device,
config.partition.mode, config.partition.mode,
config.partition.efi, config.partition.efi,
config.partition.encrypted,
config.partition.password,
&mut partitions, &mut partitions,
); );
base::install_base_packages(config.kernel); base::install_base_packages(config.kernel);
@ -104,9 +108,9 @@ pub fn read_config(configpath: PathBuf) {
log::info!("Installing bootloader : {}", config.bootloader.r#type); log::info!("Installing bootloader : {}", config.bootloader.r#type);
log::info!("Installing bootloader to : {}", config.bootloader.location); log::info!("Installing bootloader to : {}", config.bootloader.location);
if config.bootloader.r#type == "grub-efi" { if config.bootloader.r#type == "grub-efi" {
base::install_bootloader_efi(PathBuf::from(config.bootloader.location)); base::install_bootloader_efi(PathBuf::from(config.bootloader.location), config.partition.encrypted);
} else if config.bootloader.r#type == "grub-legacy" { } else if config.bootloader.r#type == "grub-legacy" {
base::install_bootloader_legacy(PathBuf::from(config.bootloader.location)); base::install_bootloader_legacy(PathBuf::from(config.bootloader.location), config.partition.encrypted);
} }
println!(); println!();
log::info!("Adding Locales : {:?}", config.locale.locale); log::info!("Adding Locales : {:?}", config.locale.locale);

@ -14,7 +14,7 @@ fn main() {
match opt.command { match opt.command {
Command::Partition(args) => { Command::Partition(args) => {
let mut partitions = args.partitions; let mut partitions = args.partitions;
partition::partition(args.device, args.mode, args.efi, &mut partitions); partition::partition(args.device, args.mode, args.efi, args.encrypted, args.password, &mut partitions);
} }
Command::InstallBase(args) => { Command::InstallBase(args) => {
base::install_base_packages(args.kernel); base::install_base_packages(args.kernel);
@ -24,11 +24,11 @@ fn main() {
} }
Command::SetupTimeshift => base::setup_timeshift(), Command::SetupTimeshift => base::setup_timeshift(),
Command::Bootloader { subcommand } => match subcommand { Command::Bootloader { subcommand } => match subcommand {
BootloaderSubcommand::GrubEfi { efidir } => { BootloaderSubcommand::GrubEfi { efidir, encrypted } => {
base::install_bootloader_efi(efidir); base::install_bootloader_efi(efidir, encrypted);
} }
BootloaderSubcommand::GrubLegacy { device } => { BootloaderSubcommand::GrubLegacy { device, encrypted } => {
base::install_bootloader_legacy(device); base::install_bootloader_legacy(device, encrypted);
} }
}, },
Command::Locale(args) => { Command::Locale(args) => {

Loading…
Cancel
Save