From 03c3f61ba33e009dd692ba9d934e7bcb5cb30756 Mon Sep 17 00:00:00 2001 From: bunnie Date: Mon, 8 Apr 2024 23:54:36 +0800 Subject: [PATCH] fixes to encrypt/decrypt routines to adjust offsets etc. --- loader/src/platform/cramium/swap.rs | 19 +++++++++++++--- loader/src/platform/precursor/swap.rs | 31 +++++++++++++++++++++------ 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/loader/src/platform/cramium/swap.rs b/loader/src/platform/cramium/swap.rs index fa7012b8d..319756bd0 100644 --- a/loader/src/platform/cramium/swap.rs +++ b/loader/src/platform/cramium/swap.rs @@ -14,6 +14,7 @@ use crate::platform::{SPIM_FLASH_IFRAM_ADDR, SPIM_RAM_IFRAM_ADDR}; use crate::println; use crate::swap::*; use crate::PAGE_SIZE; +use crate::SDBG; /// hard coded at offset 0 of SPI FLASH for now, until we figure out if and how to move this around. const SWAP_IMG_START: usize = 0; @@ -232,8 +233,17 @@ impl SwapHal { // compute offsets for swap let mac_size = (swap.ram_size as usize / 4096) * size_of::(); - let mac_size_to_page = (mac_size + (PAGE_SIZE - 1)) / PAGE_SIZE; + let mac_size_to_page = (mac_size + (PAGE_SIZE - 1)) & !(PAGE_SIZE - 1); let ram_size_actual = (swap.ram_size as usize & !(PAGE_SIZE - 1)) - mac_size_to_page; + if SDBG { + println!( + "mac area size: {:x}, ram_size_actual: {:x}, swap.ram_size: {:x}, mac offset: {:x}", + mac_size, + ram_size_actual, + swap.ram_size, + swap.ram_offset as usize + ram_size_actual + ); + } // generate a random key for swap let mut trng = sce::trng::Trng::new(utralib::generated::HW_TRNG_BASE as usize); @@ -291,6 +301,9 @@ impl SwapHal { pub fn decrypt_src_page_at(&mut self, offset: usize) -> &[u8] { assert!((offset & 0xFFF) == 0, "offset is not page-aligned"); + assert!(offset >= 0x1000); + // compensate for the unencrypted header that is not included in the `src_data_area` slice + let offset = offset - 0x1000; self.buf_addr = offset; self.flash_spim.mem_read((self.image_start + offset) as u32, &mut self.buf.data); let mut nonce = [0u8; size_of::()]; @@ -334,7 +347,7 @@ impl SwapHal { let vpage_masked = src_vaddr & !(PAGE_SIZE - 1); nonce[9..12].copy_from_slice(&(vpage_masked as u32).to_be_bytes()[..3]); let aad: &[u8] = &[]; - match self.src_cipher.encrypt_in_place_detached(Nonce::from_slice(&nonce), aad, buf) { + match self.dst_cipher.encrypt_in_place_detached(Nonce::from_slice(&nonce), aad, buf) { Ok(tag) => { self.ram_spim.mem_ram_write(dest_offset as u32, buf); self.ram_spim.mem_ram_write( @@ -362,7 +375,7 @@ impl SwapHal { self.ram_spim .mem_read((self.swap_mac_start + (src_offset / PAGE_SIZE) * size_of::()) as u32, &mut tag); self.ram_spim.mem_read(src_offset as u32, &mut self.buf.data); - match self.src_cipher.decrypt_in_place_detached( + match self.dst_cipher.decrypt_in_place_detached( Nonce::from_slice(&nonce), aad, &mut self.buf.data, diff --git a/loader/src/platform/precursor/swap.rs b/loader/src/platform/precursor/swap.rs index d5f744f1b..6c0279f53 100644 --- a/loader/src/platform/precursor/swap.rs +++ b/loader/src/platform/precursor/swap.rs @@ -7,6 +7,7 @@ use crate::bootconfig::BootConfig; use crate::println; use crate::swap::*; use crate::PAGE_SIZE; +use crate::SDBG; pub struct SwapHal { src_data_area: &'static [u8], @@ -33,8 +34,17 @@ impl SwapHal { // compute the MAC area needed for the total RAM size. This is a slight over-estimate // because once we remove the MAC area, we need even less storage, but it's a small error. let mac_size = (swap.ram_size as usize / 4096) * size_of::(); - let mac_size_to_page = (mac_size + (PAGE_SIZE - 1)) / PAGE_SIZE; + let mac_size_to_page = (mac_size + (PAGE_SIZE - 1)) & !(PAGE_SIZE - 1); let ram_size_actual = (swap.ram_size as usize & !(PAGE_SIZE - 1)) - mac_size_to_page; + if SDBG { + println!( + "mac area size: {:x}, ram_size_actual: {:x}, swap.ram_size: {:x}, mac offset: {:x}", + mac_size, + ram_size_actual, + swap.ram_size, + swap.ram_offset as usize + ram_size_actual + ); + } // access the hardware TRNG manually to generate a per-boot random key for RAM swap let trng = CSR::new(utra::trng_kernel::HW_TRNG_KERNEL_BASE as *mut u32); @@ -92,6 +102,9 @@ impl SwapHal { pub fn decrypt_src_page_at(&mut self, offset: usize) -> &[u8] { assert!((offset & 0xFFF) == 0, "offset is not page-aligned"); + assert!(offset >= 0x1000); + // compensate for the unencrypted header that is not included in the `src_data_area` slice + let offset = offset - 0x1000; self.buf_addr = offset; // println!("data area: {:x?}", &self.src_data_area[..4]); // println!("offset: {:x}", offset); @@ -125,7 +138,7 @@ impl SwapHal { /// Swap count is fixed at 0 by this routine. The data to be encrypted is provided in /// `buf`, and is replaced with part of the encrypted data upon completion of the routine. pub fn encrypt_swap_to(&mut self, buf: &mut [u8], dest_offset: usize, src_vaddr: usize, src_pid: u8) { - println!("enc_to: pid: {}, src_vaddr: {:x} dest_offset: {:x}", src_pid, src_vaddr, dest_offset); + // println!("enc_to: pid: {}, src_vaddr: {:x} dest_offset: {:x}", src_pid, src_vaddr, dest_offset); assert!(buf.len() == PAGE_SIZE); assert!(dest_offset & (PAGE_SIZE - 1) == 0); let mut nonce = [0u8; size_of::()]; @@ -136,19 +149,23 @@ impl SwapHal { let vpage_masked = src_vaddr & !(PAGE_SIZE - 1); nonce[9..12].copy_from_slice(&(vpage_masked as u32).to_be_bytes()[..3]); let aad: &[u8] = &[]; - match self.src_cipher.encrypt_in_place_detached(Nonce::from_slice(&nonce), aad, buf) { + match self.dst_cipher.encrypt_in_place_detached(Nonce::from_slice(&nonce), aad, buf) { Ok(tag) => { self.dst_data_area[dest_offset..dest_offset + PAGE_SIZE].copy_from_slice(buf); let mac_offset = (dest_offset / PAGE_SIZE) * size_of::(); self.dst_mac_area[mac_offset..mac_offset + size_of::()].copy_from_slice(tag.as_slice()); + // println!("Nonce: {:x?}, tag: {:x?}", &nonce, tag.as_slice()); + // println!("dst_mac_area: {:x?}", &self.dst_mac_area[..32]); } Err(e) => panic!("Encryption error to swap ram: {:?}", e), } } - /// Swap count is fixed at 0 by this routine. The data to be encrypted is - /// assumed to already be in `self.buf` + /// Used to examine contents of swap RAM. Swap count is fixed at 0 by this routine. Decrypted data is + /// returned as a slice. pub fn decrypt_swap_from(&mut self, src_offset: usize, dst_vaddr: usize, dst_pid: u8) -> &[u8] { + // println!("Decrypt swap:"); + // println!(" offset: {:x}, vaddr: {:x}, pid: {}", src_offset, dst_vaddr, dst_pid); assert!(src_offset & (PAGE_SIZE - 1) == 0); let mut nonce = [0u8; size_of::()]; nonce[0..4].copy_from_slice(&[0u8; 4]); // this is the `swap_count` field @@ -161,8 +178,10 @@ impl SwapHal { let mut tag = [0u8; size_of::()]; let mac_offset = (src_offset / PAGE_SIZE) * size_of::(); tag.copy_from_slice(&self.dst_mac_area[mac_offset..mac_offset + size_of::()]); + // println!("dst_mac_area: {:x?}", &self.dst_mac_area[..32]); self.buf.data.copy_from_slice(&self.dst_data_area[src_offset..src_offset + PAGE_SIZE]); - match self.src_cipher.decrypt_in_place_detached( + // println!("Nonce: {:x?}, tag: {:x?}", &nonce, &tag); + match self.dst_cipher.decrypt_in_place_detached( Nonce::from_slice(&nonce), aad, &mut self.buf.data,