I am the person who remembers.
I remember happiness.
A new threat from quantum computers now challenges this foundation. At scale, it will be able to erase or forge the cryptographic records that shape our digital lives.
To protect the integrity of collective memory and prevent future attackers from stealing identities, I have left previous cryptographic standards behind and implemented the highest security level available today, post-quantum technology. The double threat: Shor and Grover
Quantum computing poses two distinct mathematical threats to modern cryptography. To understand the transition to post-quantum standards, it is essential to know both.
Shor's algorithm represents the existential threat. It efficiently solves the integer factorization and discrete logarithm problems that underpin nearly all classical public-key cryptography, including RSA, Diffie-Hellman, and elliptic curve systems (ECC). This is not a degradation but a complete break. A sufficiently powerful quantum computer can derive a private key from a public key, thereby fundamentally undermining classical identity systems.
Grover's algorithm targets symmetric cryptography and hash functions. It provides a quadratic speedup for brute-force searches, effectively halving the security strength of a key. This is why AES-256 is so crucial: even after Grover's reduction, it still offers 128 bits of effective security, which is computationally practically unbreakable.
The most immediate danger is the SNDL attack (Store Now, Decrypt Later). Encrypted traffic, identity proofs, certificates, and signatures can be intercepted today, while classical cryptography is still valid, and stored indefinitely. Once quantum technology matures, these archives can be decrypted or forged retroactively. If our cryptographic foundations fail, we also lose the ability to document our own digital history.
For years, elliptic curve cryptography, particularly P-384 (ECDSA), was the gold standard in high-security environments. While P-384 offers about 192 bits of classical security, it has no resistance whatsoever to Shor's algorithm. It was designed for a classical world, and that world is coming to an end.
This is why I have implemented ML-DSA-87 for Root CA and signing operations. ML-DSA-87 is the highest security level defined by modern lattice-based standards, offering Category 5 security, which is computationally equivalent to AES-256. Choosing this level instead of the more common ML-DSA-65 ensures that my network's identity is built with the greatest possible security margin available today.
Post-quantum cryptography is no longer theoretical. It is deployable now, even on routers and mobile-class hardware. I am running a custom OpenSSL 3.5.0 build on an AArch64 MediaTek Filogic 830/880 platform. This SoC is unusually well-suited for post-quantum workloads.
ML-KEM and ML-DSA rely heavily on polynomial arithmetic. ARM NEON vector instructions allow these operations to be executed in parallel, significantly reducing TLS handshake latency even with large PQ key material.
Post-quantum keys are large. A public ML-KEM-1024 key is 1568 bytes, compared to 49 bytes for P-384. The 64-bit address space of AArch64 allows for clean management of these buffers, avoiding fragmentation and pressure issues seen on older architectures.
After installing the custom toolchain on the AArch64 target system, the post-quantum stack can be verified directly.
openssl list -kem-algorithms
ml-kem-1024
secp384r1mlkem1024 (high-security hybrid)
openssl list -signature-algorithms | grep -i ml
ml-dsa-87 (256-bit security)
The presence of these algorithms confirms that the platform supports both post-quantum key exchange (ML-KEM-1024) and quantum-resistant signatures (ML-DSA-87).
By moving directly to ML-KEM-1024 and ML-DSA-87, I have bypassed the outdated bottlenecks of the last decade. My network is no longer preparing for the quantum transition; it has already completed it. The rest of the industry will follow suit in time.
```The RK3588 SoC features a quad-core Arm Cortex-A76/A55 CPU, a Mali-G610 GPU, and a highly flexible I/O architecture that makes it ideal for embedded Linux SBCs like the Radxa Rock 5B+.
I’ve been exploring and documenting board bring-up for this platform, including u-boot and Linux kernel contributions, device-tree development, and tooling for reproducible builds and signal-integrity validation. Most of this work is still in active development and early upstream preparation.
I’m publishing my notes, measurements, and bring-up artifacts here as the work progresses, while active u-boot and kernel development including patch iteration, test builds, and branch history are maintained in separate working repositories:
Signal Analysis / Bring-Up Repo: https://github.com/brhinton/signal-analysis
The repository currently includes (with more being added):
Additional U-Boot and Linux kernel work, including mainline test builds, feature development, rebases, and patch series in progress, is maintained in separate working repositories. This repo serves as the central location for measurements, documentation, and board-level bring-up notes.
This is ongoing, work-in-progress engineering effort, and I’ll be updating the repositories as additional measurements, boards, and upstream-ready changes are prepared.
Arch Linux is known for its high level of customization, and configuring LUKS2 and LVM is a straightforward process. This guide provides a set of instructions for setting up an Arch Linux system with the following features:
/dev/nvme0n1).Boot your system from the Arch Linux installation media.
# timedatectl set-ntp true
/dev/nvme0n1). Use lsblk to confirm.# wipefs --all /dev/nvme0n1
# sgdisk /dev/nvme0n1 -n 1::+512MiB -t 1:EF00
# sgdisk /dev/nvme0n1 -n 2 -t 2:8300
Encrypt the second partition using LUKS2. This example uses aes-xts-plain64 and serpent-xts-plain ciphers, and SHA512 for the hash. Adjust as needed.
# cryptsetup luksFormat --cipher aes-xts-plain64 \
--keyslot-cipher serpent-xts-plain --keyslot-key-size 512 \
--use-random -S 0 -h sha512 -i 4000 /dev/nvme0n1p2
--cipher: Specifies the cipher for data encryption.--keyslot-cipher: Specifies the cipher used to encrypt the key.--keyslot-key-size: Specifies the size of the key slot.-S 0: Disables sparse headers.-h: Specifies the hash function.-i: Specifies the number of iterations.Open the encrypted partition:
# cryptsetup open /dev/nvme0n1p2 root
Create an ext4 file system on the decrypted volume:
# mkfs.ext4 /dev/mapper/root
Mount the root file system:
# mount /dev/mapper/root /mnt
Create and mount the EFI System Partition:
# mkfs.fat -F32 /dev/nvme0n1p1
# mount --mkdir /dev/nvme0n1p1 /mnt/efi
Create and enable a swap file:
# dd if=/dev/zero of=/mnt/swapfile bs=1M count=8000 status=progress
# chmod 600 /mnt/swapfile
# mkswap /mnt/swapfile
# swapon /mnt/swapfile
Use pacstrap to install the necessary packages:
# pacstrap -K /mnt base base-devel linux linux-hardened \
linux-hardened-headers linux-firmware apparmor mesa \
xf86-video-intel vulkan-intel git vi vim ukify
# genfstab -U /mnt >> /mnt/etc/fstab
# arch-chroot /mnt
Set the timezone:
# ln -sf /usr/share/zoneinfo/UTC /etc/localtime
# hwclock --systohc
Uncomment en_US.UTF-8 UTF-8 in /etc/locale.gen and generate the locale:
# sed -i 's/#'"en_US.UTF-8"' UTF-8/'"en_US.UTF-8"' UTF-8/g' /etc/locale.gen
# locale-gen
# echo 'LANG=en_US.UTF-8' > /etc/locale.conf
# echo "KEYMAP=us" > /etc/vconsole.conf
Set the hostname:
# echo myhostname > /etc/hostname
# cat <<EOT >> /etc/hosts
127.0.0.1 myhostname
::1 localhost
127.0.1.1 myhostname.localdomain myhostname
EOT
Configure mkinitcpio.conf to include the encrypt hook:
# sed -i 's/HOOKS.*/HOOKS=(base udev autodetect modconf kms \
keyboard keymap consolefont block encrypt filesystems resume fsck)/' \
/etc/mkinitcpio.conf
Create the initial ramdisk:
# mkinitcpio -P
Install the bootloader:
# bootctl install
Set the root password:
# passwd
Install microcode and efibootmgr:
# pacman -S intel-ucode efibootmgr
Get the swap offset:
# swapoffset=`filefrag -v /swapfile | awk '/\s+0:/ {print $4}' | \
sed -e 's/\.\.$//'`
Get the UUID of the encrypted partition:
# blkid -s UUID -o value /dev/nvme0n1p2
Create the EFI boot entry. Replace <UUID OF CRYPTDEVICE> with the actual UUID:
# efibootmgr --disk /dev/nvme0n1p1 --part 1 --create --label "Linux" \
--loader /vmlinuz-linux --unicode "cryptdevice=UUID=<UUID OF CRYPTDEVICE>:root \
root=/dev/mapper/root resume=/dev/mapper/root resume_offset=$swapoffset \
rw initrd=\intel-ucode.img initrd=\initramfs-linux.img" --verbose
Configure the UKI presets:
# cat <<EOT >> /etc/mkinitcpio.d/linux.preset
ALL_kver="/boot/vmlinuz-linux"
ALL_microcode=(/boot/*-ucode.img)
PRESETS=('default' 'fallback')
default_uki="/efi/EFI/Linux/arch-linux.efi"
default_options="--splash /usr/share/systemd/bootctl/splash-arch.bmp"
fallback_uki="/efi/EFI/Linux/arch-linux-fallback.efi"
fallback_options="-S autodetect"
EOT
Create the UKI directory:
# mkdir -p /efi/EFI/Linux
Configure the kernel command line:
# cat <<EOT >> /etc/kernel/cmdline
cryptdevice=UUID=<UUID OF CRYPTDEVICE>:root root=/dev/mapper/root \
resume=/dev/mapper/root resume_offset=51347456 rw
EOT
Build the UKIs:
# mkinitcpio -p linux
Configure the kernel install layout:
# echo "layout=uki" >> /etc/kernel/install.conf
Create a systemd-networkd network configuration file:
# cat <<EOT >> /etc/systemd/network/nic0.network
[Match]
Name=nic0
[Network]
DHCP=yes
EOT
Install Xorg, Xfce, LightDM, and related packages:
# pacman -Syu
# pacman -S xorg xfce4 xfce4-goodies lightdm lightdm-gtk-greeter \
libva-intel-driver mesa xorg-server xorg-xinit sudo
# systemctl enable lightdm
# systemctl start lightdm
# systemctl enable systemd-resolved.service
# systemctl enable systemd-networkd.service
# systemctl start systemd-resolved.service
# systemctl start systemd-networkd.service
Create a user account and add it to the wheel group:
# useradd -m -g wheel -s /bin/bash myusername
Exit the chroot environment and reboot your system:
# exit
# umount -R /mnt
# reboot
Parallelism on a time-sliced, preemptive operating system means the simultaneous execution of multiple schedulable entities over a time quantum. Both processes and threads can execute in parallel across multiple cores or processors. Concurrency and parallelism are at play on a multi-user system with preemptive time-slicing and multiple processor cores. Affinity scheduling refers to scheduling processes and threads across multiple cores so that their concurrent and parallel execution is close to optimal.
It's worth noting that affinity scheduling refers to the practice of assigning processes or threads to specific processors or cores to optimize their execution and minimize unnecessary context switching. This can improve overall system performance by reducing cache misses and increasing cache hits, among other benefits. In contrast, non-affinity scheduling allows processes and threads to be executed on any available processor or core, which can result in more frequent context switching and lower performance.As the switches are moved or the buttons are pressed, the seven-segment display is updated to reflect the numeric output frequency, and the output pin(s) are driven at the desired frequency. The onboard clock runs at 50MHz, and the signal on the output pins is set on the rising edge of the clock input signal (positive edge-triggered). At 50MHz, the output pins can be toggled at a maximum rate of 50 million cycles per second or 25 million rising edges of the clock per second. An LED attached to one of the output pins would blink 25 million times per second, not recognizable to the human eye. The persistence of vision, which is the time the human eye retains an image after it disappears from view, is approximately 1/16th of a second. Therefore, an LED blinking at 25 million times per second would appear as a continuous light to the human eye.
scaler <= compute_prescaler((to_integer(unsigned( SW )))*scaler_mlt);
gpiopulse_process : process(CLOCK_50, KEY(0))
begin
if (KEY(0) = '0') then -- async reset
count <= 0;
elsif rising_edge(CLOCK_50) then
if (count = scaler - 1) then
state <= not state;
count <= 0;
elsif (count = clk50divider) then -- auto reset
count <= 0;
else
count <= count + 1;
end if;
end if;
end process gpiopulse_process;The scaler signal is calculated using the compute_prescaler function, which takes the value of a switch (SW) as an input, multiplies it with a multiplier (scaler_mlt), and then converts it to an integer using to_integer. This scaler signal is used to control the frequency of the pulse signal generated on the output pin.