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)]
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
#[clap(required_if_eq("mode", "Partition::Manual"), parse(try_from_str = parse_partitions))]
pub partitions: Vec<Partition>,
@ -147,6 +155,9 @@ pub enum BootloaderSubcommand {
GrubEfi {
/// The directory to install the EFI bootloader to
efidir: PathBuf,
/// Wether the install destination is encrypted
encrypted: bool,
},
/// Install GRUB in legacy (BIOS) mode
@ -154,6 +165,9 @@ pub enum BootloaderSubcommand {
GrubLegacy {
/// The device to install the bootloader to
device: PathBuf,
/// Wether the install destination is encrypted
encrypted: bool,
},
}

@ -1,5 +1,5 @@
use crate::internal::exec::*;
use crate::internal::files::append_file;
use crate::internal::files::{append_file, sed_file};
use crate::internal::*;
use log::warn;
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![
"grub",
"efibootmgr",
@ -114,6 +114,9 @@ pub fn install_bootloader_efi(efidir: PathBuf) {
if !std::path::Path::new(&format!("/mnt{efi_str}")).exists() {
crash(format!("The efidir {efidir:?} doesn't exist"), 1);
}
if encrypt {
install_bootloader_encryption(true);
}
exec_eval(
exec_chroot(
"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![
"grub",
"crystal-grub-theme",
@ -164,6 +167,9 @@ pub fn install_bootloader_legacy(device: PathBuf) {
crash(format!("The device {device:?} does not exist"), 1);
}
let device = device.to_string_lossy().to_string();
if encrypt {
install_bootloader_encryption(false);
}
exec_eval(
exec_chroot(
"grub-install",
@ -185,6 +191,18 @@ pub fn install_bootloader_legacy(device: PathBuf) {
),
"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() {
@ -223,3 +241,54 @@ pub fn install_zram() {
"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,
mode: PartitionMode,
efi: bool,
encrypted: bool,
password: String,
partitions: &mut Vec<args::Partition>,
) {
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 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")
{
part1 = format!("{}p1", device.to_string_lossy());
part2 = format!("{}p2", device.to_string_lossy());
vec![part1.as_str(), part2.as_str()]
if efi {
part1 = format!("{}p1", 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()]
}
} else {
part1 = format!("{}1", device.to_string_lossy());
part2 = format!("{}2", device.to_string_lossy());
vec![part1.as_str(), part2.as_str()]
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 {
part1 = format!("{}1", device.to_string_lossy());
part2 = format!("{}2", device.to_string_lossy());
vec![part1.as_str(), part2.as_str()]
}
};
auto_format(partitions);
mount_disks(efi);
let parts: Vec<String>;
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 => {
log::debug!("Manual partitioning");
@ -134,7 +156,7 @@ pub fn partition(
}
}
fn create_partitions(device: &Path, efi: bool) {
fn create_partitions(device: &Path, efi: bool){
let device = device.to_string_lossy().to_string();
exec_eval(
exec(
@ -162,12 +184,27 @@ fn create_partitions(device: &Path, efi: bool) {
String::from(&device),
String::from("mkpart"),
String::from("fat32"),
String::from("0"),
String::from("300"),
String::from("1MiB"),
String::from("125MiB"),
],
),
"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 {
exec_eval(
exec(
@ -194,7 +231,7 @@ fn create_partitions(device: &Path, efi: bool) {
String::from("mkpart"),
String::from("primary"),
String::from("btrfs"),
String::from("512MIB"),
String::from(if efi { "637MiB" } else { "512MIB" } ),
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(
"mkfs.vfat",
"cryptsetup",
vec![
"-F32".to_string(),
"-n".to_string(),
"CYRSTAL_EFI".to_string(),
partitions[0].to_string(),
String::from("close"),
String::from("root"),
],
),
format!("format {} as fat32 with label CRYSTAL_EFI", partitions[0]).as_str(),
format!("LUKS close {}", if efi { partitions[2] } else { partitions[1] }).as_str(),
);
exec_eval(
exec(
"mkfs.btfrs",
"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(
"mkfs.vfat",
vec![
"-F32".to_string(),
"-n".to_string(),
"crystal-efi".to_string(),
partitions[0].to_string(),
],
),
format!("format {} as fat32 with label crystal-efi", partitions[0]).as_str(),
);
exec_eval(
exec(
"mkfs.ext4",
vec![
"-F".to_string(),
"-L".to_string(),
"crystal-boot".to_string(),
partitions[1].to_string(),
],
),
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(),
partitions[1].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", partitions[1]).as_str(),
format!("format {} as btrfs with label crystal-root", if efi { partitions[2] } else { partitions[1] }).as_str(),
);
}
fn mount_disks(efi: bool) {
mount("/dev/disk/by-label/CRYSTAL_ROOT", "/mnt", "");
fn mount_disks(efi: bool, encrypted: bool) {
let root = if encrypted { "/dev/mapper/root" } else { "/dev/disk/by-label/crystal-root" };
mount(root, "/mnt", "");
exec_eval(
exec_workdir(
"btrfs",
@ -256,22 +400,21 @@ fn mount_disks(efi: bool) {
"create btrfs subvolume @home",
);
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");
mount(
"/dev/disk/by-label/CRYSTAL_ROOT",
root,
"/mnt/home",
"subvol=@home",
);
files_eval(create_directory("/mnt/boot"), "create directory /mnt/boot");
mount("/dev/disk/by-label/crystal-boot", "/mnt/boot", "");
if efi {
files_eval(
create_directory("/mnt/boot/efi"),
"create directory /mnt/boot/efi",
);
mount("/dev/disk/by-label/CRYSTAL_EFI", "/mnt/boot/efi", "");
} else {
mount("/dev/disk/by-label/CRYSTAL_BOOT", "/mnt/boot", "");
mount("/dev/disk/by-label/crystal-efi", "/mnt/boot/efi", "");
}
}

@ -26,6 +26,8 @@ struct Partition {
device: String,
mode: PartitionMode,
efi: bool,
encrypted: bool,
password: String,
partitions: Vec<String>,
}
@ -96,6 +98,8 @@ pub fn read_config(configpath: PathBuf) {
device,
config.partition.mode,
config.partition.efi,
config.partition.encrypted,
config.partition.password,
&mut partitions,
);
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 to : {}", config.bootloader.location);
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" {
base::install_bootloader_legacy(PathBuf::from(config.bootloader.location));
base::install_bootloader_legacy(PathBuf::from(config.bootloader.location), config.partition.encrypted);
}
println!();
log::info!("Adding Locales : {:?}", config.locale.locale);

@ -14,7 +14,7 @@ fn main() {
match opt.command {
Command::Partition(args) => {
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) => {
base::install_base_packages(args.kernel);
@ -24,11 +24,11 @@ fn main() {
}
Command::SetupTimeshift => base::setup_timeshift(),
Command::Bootloader { subcommand } => match subcommand {
BootloaderSubcommand::GrubEfi { efidir } => {
base::install_bootloader_efi(efidir);
BootloaderSubcommand::GrubEfi { efidir, encrypted } => {
base::install_bootloader_efi(efidir, encrypted);
}
BootloaderSubcommand::GrubLegacy { device } => {
base::install_bootloader_legacy(device);
BootloaderSubcommand::GrubLegacy { device, encrypted } => {
base::install_bootloader_legacy(device, encrypted);
}
},
Command::Locale(args) => {

Loading…
Cancel
Save