The best way to realise software integrity is through hardware-based trust anchors in the form of a Trusted Platform Module (TPM) or an HSM. An HSM / TPM is a dedicated trusted hardware or software module, which provides secure cryptographic key management, encryption and signature operations as well as secure storage.
During the secure boot process, only signed software components (boot loader, kernel, rfs etc.) are loaded. This is a highly recommended first step to ensure the security of the device. This procedure is relatively easy to implement, but may involve some restrictions with regard to the licensing obligations of open source software. The result is a tamper-proof device.
Using a Measured Boot Process standardised by the Trusted Computing Group, the integrity of all operating system components is verified when the system is started and the hash values of the individual software components are stored in the so-called PCR registers. These values can be used locally or also for remote attestation to prove the integrity of the software stack. This procedure ensures that all licence obligations can be fulfilled.
Disk and Application Encryption
The HSM/TPM module is also used to securely store the keys for the encryption of data and programmes on the device. This effectively prevents unauthorised duplication of the application (i.e. the know-how) and (or) the data. And in the case of IoT devices, it enables device identification and authentication (see also Secure Device Onboarding).
Instead of the hardware modules, a combination of TrustZone and TEE can also be used in the case of an ARM architecture. Another possibility is the use of TZ and an eMMC with RPMB (replay protect memory block) functionality.
User Land Security
User space integrity - secure boot, dm-verity, white listing (combination of IMA, Linux Security Module such as apparmor, SELinux etc.), control flow integrity (CFI) - largely feasible with the help of LSM by defining which programmes may be started by which processes, and refined with seccomp filters that define which syscalls the programmes may call [unfortunately this does not apply to the kernel].