github.com/google/trillian-examples@v0.0.0-20240520080811-0d40d35cef0e/binary_transparency/firmware/devices/usbarmory/bootloader/conf.go (about)

     1  // https://github.com/usbarmory/armory-boot
     2  //
     3  // Copyright (c) F-Secure Corporation
     4  // https://foundry.f-secure.com
     5  //
     6  // Use of this source code is governed by the license
     7  // that can be found in the LICENSE file.
     8  
     9  //go:build armory
    10  // +build armory
    11  
    12  package main
    13  
    14  import (
    15  	"encoding/json"
    16  	"errors"
    17  	"fmt"
    18  	"log"
    19  )
    20  
    21  const defaultConfigPath = "/boot/armory-boot.conf"
    22  const signatureSuffix = ".sig"
    23  
    24  var conf Config
    25  
    26  type Config struct {
    27  	// Kernel is the path to a Linux kernel image.
    28  	Kernel []string `json:"kernel"`
    29  
    30  	// DeviceTreeBlob is the path to a Linux DTB file.
    31  	DeviceTreeBlob []string `json:"dtb"`
    32  
    33  	// CmdLine is the Linux kernel command-line parameters.
    34  	CmdLine string `json:"cmdline"`
    35  
    36  	// Unikernel is the path to an ELF unikernel image.
    37  	Unikernel []string `json:"unikernel"`
    38  
    39  	partition *Partition
    40  	conf      []byte
    41  
    42  	kernel     []byte
    43  	kernelHash string
    44  
    45  	params     []byte
    46  	paramsHash string
    47  
    48  	elf bool
    49  }
    50  
    51  func (c *Config) Init(p *Partition, configPath string) (err error) {
    52  	log.Printf("armory-boot: reading configuration at %s\n", configPath)
    53  
    54  	c.partition = p
    55  	c.conf, err = p.ReadAll(configPath)
    56  
    57  	return
    58  }
    59  
    60  func (c *Config) Verify(sigPath string, pubKey string) (err error) {
    61  	sig, err := c.partition.ReadAll(sigPath)
    62  
    63  	if err != nil {
    64  		return fmt.Errorf("invalid signature path, %v", err)
    65  	}
    66  
    67  	return verifySignature(c.conf, sig, pubKey)
    68  }
    69  
    70  func (c *Config) Load() (err error) {
    71  	err = json.Unmarshal(c.conf, &c)
    72  
    73  	if err != nil {
    74  		return
    75  	}
    76  
    77  	ul, kl := len(conf.Unikernel), len(conf.Kernel)
    78  	isUnikernel, isKernel := ul > 0, kl > 0
    79  
    80  	if isUnikernel == isKernel {
    81  		return errors.New("must specify either unikernel or kernel")
    82  	}
    83  
    84  	var kernelPath string
    85  
    86  	switch {
    87  	case isKernel:
    88  		if kl != 2 {
    89  			return errors.New("invalid kernel parameter size")
    90  		}
    91  
    92  		if len(conf.DeviceTreeBlob) != 2 {
    93  			return errors.New("invalid dtb parameter size")
    94  		}
    95  
    96  		kernelPath = conf.Kernel[0]
    97  		c.kernelHash = conf.Kernel[1]
    98  	case isUnikernel:
    99  		if ul != 2 {
   100  			return errors.New("invalid unikernel parameter size")
   101  		}
   102  
   103  		kernelPath = conf.Unikernel[0]
   104  		c.kernelHash = conf.Unikernel[1]
   105  	}
   106  
   107  	c.Print()
   108  
   109  	c.kernel, err = c.partition.ReadAll(kernelPath)
   110  
   111  	if err != nil {
   112  		return fmt.Errorf("invalid path %s, %v\n", kernelPath, err)
   113  	}
   114  
   115  	if isUnikernel {
   116  		c.elf = true
   117  		return
   118  	}
   119  
   120  	c.paramsHash = conf.DeviceTreeBlob[1]
   121  	c.params, err = c.partition.ReadAll(conf.DeviceTreeBlob[0])
   122  
   123  	if err != nil {
   124  		return fmt.Errorf("invalid path %s, %v\n", conf.DeviceTreeBlob[0], err)
   125  	}
   126  
   127  	return
   128  }
   129  
   130  func (c *Config) Print() {
   131  	j, _ := json.MarshalIndent(c, "", "\t")
   132  	log.Printf("\n%s", string(j))
   133  }