github.com/transparency-dev/armored-witness-os@v0.1.3-0.20240514084412-27eef7325168/trusted_os/main.go (about)

     1  // Copyright 2022 The Armored Witness OS authors. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package main
    16  
    17  import (
    18  	"bytes"
    19  	"crypto/sha256"
    20  	_ "embed"
    21  	"encoding/gob"
    22  	"fmt"
    23  	"log"
    24  	"os"
    25  	"runtime"
    26  	"strings"
    27  	"time"
    28  
    29  	"github.com/coreos/go-semver/semver"
    30  	usbarmory "github.com/usbarmory/tamago/board/usbarmory/mk2"
    31  	"github.com/usbarmory/tamago/soc/nxp/enet"
    32  	"github.com/usbarmory/tamago/soc/nxp/imx6ul"
    33  	"github.com/usbarmory/tamago/soc/nxp/usb"
    34  	"golang.org/x/mod/sumdb/note"
    35  
    36  	// for now just test compilation of these
    37  	"github.com/transparency-dev/armored-witness-common/release/firmware"
    38  	_ "github.com/transparency-dev/armored-witness-os/internal/hab"
    39  	_ "github.com/transparency-dev/armored-witness-os/rpmb"
    40  )
    41  
    42  const (
    43  	Build = ""
    44  )
    45  
    46  // initialized at compile time (see Makefile)
    47  var (
    48  	Revision               string
    49  	Version                string
    50  	SRKHash                string
    51  	LogVerifier            string
    52  	LogOrigin              string
    53  	AppletManifestVerifier string
    54  	OSManifestVerifier1    string
    55  	OSManifestVerifier2    string
    56  )
    57  
    58  var (
    59  	Control *usb.USB
    60  
    61  	// USB armory Mk II (rev. β) - UA-MKII-β
    62  	// USB armory Mk II (rev. γ) - UA-MKII-γ
    63  	USB *usb.USB
    64  
    65  	// USB armory Mk II LAN - UA-MKII-LAN
    66  	LAN *enet.ENET
    67  
    68  	// osVersion is the semver parsed representation of the Version string above.
    69  	osVersion semver.Version
    70  	// loadedAppletVersion is taken from the manifest used to verify the
    71  	// applet.
    72  	loadedAppletVersion semver.Version
    73  
    74  	AppletBundleVerifier firmware.BundleVerifier
    75  	OSBundleVerifier     firmware.BundleVerifier
    76  )
    77  
    78  // A Trusted Applet can be embedded for testing purposes with QEMU.
    79  var (
    80  	//go:embed assets/trusted_applet.elf
    81  	taELF []byte
    82  
    83  	//go:embed assets/trusted_applet.proofbundle
    84  	taProofBundle []byte
    85  )
    86  
    87  func init() {
    88  	log.SetFlags(log.Ltime)
    89  	log.SetOutput(os.Stdout)
    90  
    91  	if imx6ul.Native {
    92  		imx6ul.SetARMFreq(imx6ul.Freq528)
    93  
    94  		if imx6ul.DCP != nil {
    95  			imx6ul.DCP.Init()
    96  		}
    97  
    98  		model, _ := usbarmory.Model()
    99  
   100  		switch model {
   101  		case usbarmory.BETA, usbarmory.GAMMA:
   102  			USB = usbarmory.USB1
   103  			USB.Init()
   104  
   105  			Control = usbarmory.USB2
   106  			Control.Init()
   107  
   108  			if debug {
   109  				debugConsole, _ := usbarmory.DetectDebugAccessory(250 * time.Millisecond)
   110  				<-debugConsole
   111  			}
   112  		case usbarmory.LAN:
   113  			LAN = usbarmory.ENET2
   114  			LAN.RingSize = 512
   115  			LAN.Init()
   116  
   117  			Control = usbarmory.USB1
   118  			Control.Init()
   119  		}
   120  	} else {
   121  		LAN = imx6ul.ENET1
   122  		LAN.RingSize = 512
   123  		LAN.Init()
   124  	}
   125  
   126  	imx6ul.GIC.Init(true, false)
   127  
   128  	log.Printf("%s/%s (%s) • TEE security monitor (Secure World system/monitor) • %s %s",
   129  		runtime.GOOS, runtime.GOARCH, runtime.Version(),
   130  		Revision, Build)
   131  }
   132  
   133  func main() {
   134  	// Increase default fuse-blowing timeout
   135  	if imx6ul.Native && imx6ul.OCOTP != nil {
   136  		imx6ul.OCOTP.Timeout = 100 * time.Millisecond
   137  	}
   138  	// Strip off v from GitTag so we can semver parse it.
   139  	Version = strings.TrimPrefix(Version, "v")
   140  
   141  	var err error
   142  
   143  	usbarmory.LED("blue", false)
   144  	usbarmory.LED("white", false)
   145  
   146  	Storage := storage()
   147  	if Storage != nil {
   148  		if err = Storage.Detect(); err != nil {
   149  			log.Fatalf("SM failed to detect storage, %v", err)
   150  		}
   151  	}
   152  
   153  	rpmb, err := newRPMB(Storage)
   154  	if err != nil {
   155  		log.Fatalf("SM could not initialize rollback protection, %v", err)
   156  	}
   157  
   158  	rpc := &RPC{
   159  		RPMB:        rpmb,
   160  		Storage:     Storage,
   161  		Diversifier: sha256.Sum256([]byte(AppletManifestVerifier)),
   162  	}
   163  
   164  	ctl := &controlInterface{
   165  		RPC:     rpc,
   166  		SRKHash: SRKHash,
   167  	}
   168  
   169  	if imx6ul.Native && imx6ul.SNVS.Available() {
   170  		log.Printf("SM version verification (%s)", Version)
   171  
   172  		if err = rpmb.init(); err != nil {
   173  			log.Fatalf("SM could not initialize rollback protection, %v", err)
   174  		}
   175  
   176  		if err = rpmb.checkVersion(osVersionSector, Version); err != nil {
   177  			log.Fatalf("SM firmware rollback check failure, %v", err)
   178  		}
   179  	}
   180  
   181  	if err := determineLoadedOSBlock(Storage); err != nil {
   182  		log.Printf("Failed to determine OS MMC block (no OS installed?): %v", err)
   183  	}
   184  
   185  	log.Printf("SM log verification pub: %s", LogVerifier)
   186  	logVerifier, err := note.NewVerifier(LogVerifier)
   187  	if err != nil {
   188  		log.Fatalf("SM invalid AppletLogVerifier: %v", err)
   189  	}
   190  	log.Printf("SM applet verification pub: %s", AppletManifestVerifier)
   191  	AppletBundleVerifier, err = createBundleVerifier(LogOrigin, logVerifier, []string{AppletManifestVerifier})
   192  	if err != nil {
   193  		log.Fatalf("SM failed to create applet bundle verifier: %v", err)
   194  	}
   195  	OSBundleVerifier, err = createBundleVerifier(LogOrigin, logVerifier, []string{OSManifestVerifier1, OSManifestVerifier2})
   196  	if err != nil {
   197  		log.Fatalf("SM failed to create OS bundle verifier: %v", err)
   198  	}
   199  
   200  	if v, err := semver.NewVersion(Version); err != nil {
   201  		log.Printf("Failed to parse OS version %q: %v", Version, err)
   202  	} else {
   203  		osVersion = *v
   204  	}
   205  
   206  	var ta *firmware.Bundle
   207  	if len(taELF) > 0 && len(taProofBundle) > 0 {
   208  		// Handle embedded applet & proof.
   209  		dec := gob.NewDecoder(bytes.NewBuffer(taProofBundle))
   210  		ta = &firmware.Bundle{}
   211  		if err := dec.Decode(ta); err != nil {
   212  			log.Printf("SM invalid embedded proof bundle: %v", err)
   213  		}
   214  		ta.Firmware = taELF
   215  	} else {
   216  		if ta, err = read(Storage); err != nil {
   217  			log.Printf("SM could not load applet, %v", err)
   218  		}
   219  	}
   220  
   221  	if ta != nil {
   222  		go func() {
   223  			for {
   224  				log.Print("SM Verifying applet bundle")
   225  				manifest, err := AppletBundleVerifier.Verify(*ta)
   226  				if err != nil {
   227  					log.Printf("SM applet verification error, %v", err)
   228  				}
   229  				loadedAppletVersion = manifest.Git.TagName
   230  				log.Printf("SM Loaded applet version %s", loadedAppletVersion.String())
   231  
   232  				usbarmory.LED("white", true)
   233  
   234  				appletCtx, err := loadApplet(ta.Firmware, ctl)
   235  				if err != nil {
   236  					log.Printf("SM applet execution error, %v", err)
   237  				}
   238  
   239  				<-appletCtx.Done()
   240  				if err := storeAppletCrashLog(Storage, getConsoleLogs()); err != nil {
   241  					log.Printf("Failed to store ringbuffer logs: %v", err)
   242  				}
   243  			}
   244  		}()
   245  	}
   246  
   247  	go func() {
   248  		l := true
   249  		for {
   250  			usbarmory.LED("white", l)
   251  			l = !l
   252  			time.Sleep(500 * time.Millisecond)
   253  		}
   254  	}()
   255  
   256  	if imx6ul.Native {
   257  		// start USB control interface
   258  		ctl.Start()
   259  	}
   260  
   261  	// never returns
   262  	handleInterrupts()
   263  }
   264  
   265  func createBundleVerifier(logOrigin string, logVerifier note.Verifier, manifestVerifiers []string) (firmware.BundleVerifier, error) {
   266  	vs := []note.Verifier{}
   267  	for _, v := range manifestVerifiers {
   268  		nv, err := note.NewVerifier(v)
   269  		if err != nil {
   270  			return firmware.BundleVerifier{}, fmt.Errorf("invalid manifest verifier %q: %v", v, err)
   271  		}
   272  		vs = append(vs, nv)
   273  	}
   274  	bv := firmware.BundleVerifier{
   275  		LogOrigin:         logOrigin,
   276  		LogVerifer:        logVerifier,
   277  		ManifestVerifiers: vs,
   278  	}
   279  	return bv, nil
   280  }