fw: Add checksum to partition table

Refuse to boot if blake2s digest over the partition table does not match
digest stored on flash
This commit is contained in:
Mikael Ågren 2025-04-03 15:48:51 +02:00
parent 75dd726998
commit f24c7ea515
No known key found for this signature in database
GPG key ID: E02DA3D397792C46
11 changed files with 207 additions and 73 deletions

View file

@ -7,29 +7,40 @@ import (
"fmt"
"io"
"os"
"golang.org/x/crypto/blake2s"
)
type PreLoadedAppData struct {
Size uint32
Digest [32]uint8
Signature [64]uint8
}
type Auth struct {
Nonce [16]uint8
AuthDigest [16]uint8
}
type AppStorage struct {
Status uint8
Auth Auth
}
type PartTable struct {
Header struct {
Version uint8
}
PreLoadedAppData [2]struct {
Size uint32
Digest [32]uint8
Signature [64]uint8
}
AppStorage [4]struct {
Status uint8
Auth struct {
Nonce [16]uint8
AuthDigest [16]uint8
}
}
Version uint8
PreLoadedAppData [2]PreLoadedAppData
AppStorage [4]AppStorage
}
type PartTableStorage struct {
PartTable PartTable
Digest [16]uint8
}
type Flash struct {
Bitstream [0x20000]uint8
PartitionTable PartTable
PartitionTableStorage PartTableStorage
PartitionTablePadding [64*1024 - 365]uint8
PreLoadedApp0 [0x20000]uint8
PreLoadedApp1 [0x20000]uint8
@ -37,6 +48,24 @@ type Flash struct {
EndPadding [0x10000]uint8
}
func readPartTableStorage(filename string) PartTableStorage {
var storage PartTableStorage
tblFile, err := os.Open(filename)
if err != nil {
panic(err)
}
if err := binary.Read(tblFile, binary.LittleEndian, &storage); err != nil {
fmt.Println("binary.Read failed:", err)
}
tblStructLen, _ := tblFile.Seek(0, io.SeekCurrent)
fmt.Fprintf(os.Stderr, "INFO: Go partition table struct is %d byte long\n", tblStructLen)
return storage
}
func readPartTable(filename string) PartTable {
var tbl PartTable
@ -73,6 +102,14 @@ func readFlashDump(filename string) Flash {
return flash
}
func printPartTableStorageJson(storage PartTableStorage) {
json, err := json.MarshalIndent(storage, "", " ")
if err != nil {
panic(err)
}
fmt.Printf("%s\n", string(json))
}
func printPartTableJson(tbl PartTable) {
partTableJSON, err := json.MarshalIndent(tbl, "", " ")
if err != nil {
@ -81,11 +118,11 @@ func printPartTableJson(tbl PartTable) {
fmt.Printf("%s\n", string(partTableJSON))
}
func printPartTableCondensed(tbl PartTable) {
func printPartTableCondensed(storage PartTableStorage) {
fmt.Printf("Header\n")
fmt.Printf(" Version : %d\n", tbl.Header.Version)
fmt.Printf(" Version : %d\n", storage.PartTable.Version)
for i, appData := range tbl.PreLoadedAppData {
for i, appData := range storage.PartTable.PreLoadedAppData {
fmt.Printf("Preloaded App %d\n", i)
fmt.Printf(" Size : %d\n", appData.Size)
fmt.Printf(" Digest : %x\n", appData.Digest[:16])
@ -97,6 +134,49 @@ func printPartTableCondensed(tbl PartTable) {
}
}
func printPartTableStorageCondensed(storage PartTableStorage) {
}
func calculateStorageDigest(data []byte) []byte {
key := [16]byte{}
hash, err := blake2s.New128(key[:])
if err != nil {
panic(err)
}
hash.Write(data)
digest := hash.Sum([]byte{})
return digest
}
func generatePartTableStorage(filename string) {
storage := PartTableStorage{
PartTable: PartTable{
Version: 1,
PreLoadedAppData: [2]PreLoadedAppData{},
AppStorage: [4]AppStorage{},
},
}
buf := make([]byte, 4096, 4096)
len, err := binary.Encode(buf, binary.LittleEndian, storage.PartTable)
if err != nil {
panic(err)
}
digest := calculateStorageDigest(buf[:len])
copy(storage.Digest[:], digest)
storageFile, err := os.Create(filename)
if err != nil {
panic(err)
}
if err := binary.Write(storageFile, binary.LittleEndian, storage); err != nil {
fmt.Println("binary.Write failed:", err)
}
}
func main() {
filename := ""
json := false
@ -112,17 +192,20 @@ func main() {
os.Exit(1)
}
var tbl PartTable
generatePartTableStorage(filename)
return
if flash {
tbl = readFlashDump(filename).PartitionTable
} else {
tbl = readPartTable(filename)
}
// var tbl PartTable
if json {
printPartTableJson(tbl)
} else {
printPartTableCondensed(tbl)
}
// if flash {
// tbl = readFlashDump(filename).PartitionTable
// } else {
// tbl = readPartTable(filename)
// }
// if json {
// printPartTableJson(tbl)
// } else {
// printPartTableCondensed(tbl)
// }
}