├── trusted_os_sifive_u ├── bios │ ├── README.md │ ├── build.sh │ ├── bios.s │ └── bios.ld ├── cmd │ ├── gotee.go │ ├── iopmp.go │ ├── common.go │ ├── pmp.go │ ├── mem.go │ └── handler.go ├── internal │ ├── rpc.go │ ├── exec.go │ ├── handler.go │ ├── pmp.go │ └── load.go └── main.go ├── internal └── semihosting │ ├── exit_stub.go │ ├── exit.go │ ├── exit_arm.s │ └── exit_riscv64.s ├── util ├── rpc.go ├── log.go ├── debug.go └── ssh.go ├── AUTHORS ├── nonsecure_os_go ├── api.go ├── api_arm.s ├── api_riscv64.s ├── main_riscv64.go └── main_arm.go ├── trusted_applet_go ├── mem_riscv64.go ├── mem_arm.go └── main.go ├── trusted_os_usbarmory ├── internal │ ├── rpc.go │ ├── handler.go │ ├── exec.go │ ├── tz.go │ └── load.go ├── cmd │ ├── arm.go │ ├── gotee.go │ ├── common.go │ ├── mem.go │ ├── csu.go │ ├── handler.go │ └── debug.go └── main.go ├── mem ├── util.go ├── layout_riscv64.go └── layout_arm.go ├── go.mod ├── LICENSE ├── trusted_applet_rust ├── main_riscv64.rs └── main_arm.rs ├── go.sum ├── Makefile └── README.md /trusted_os_sifive_u/bios/README.md: -------------------------------------------------------------------------------- 1 | This is a bios helper to launch tamago/riscv64 binaries under qemu. 2 | -------------------------------------------------------------------------------- /trusted_os_sifive_u/bios/build.sh: -------------------------------------------------------------------------------- 1 | riscv64-linux-gnu-gcc -march=rv64g -mabi=lp64 -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles -Tbios.ld bios.s -o bios.bin 2 | -------------------------------------------------------------------------------- /trusted_os_sifive_u/bios/bios.s: -------------------------------------------------------------------------------- 1 | .align 2 2 | .include "cfg.inc" 3 | 4 | .section .text 5 | .globl _start 6 | 7 | _start: 8 | li t0, RT0_RISCV64_TAMAGO 9 | jr t0 10 | -------------------------------------------------------------------------------- /internal/semihosting/exit_stub.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | //go:build !semihosting 7 | // +build !semihosting 8 | 9 | package semihosting 10 | 11 | func Exit() {} 12 | -------------------------------------------------------------------------------- /util/rpc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package util 7 | 8 | // LEDStatus represents an RPC LED state request. 9 | type LEDStatus struct { 10 | // Name is the LED name 11 | Name string 12 | // On is the LED state 13 | On bool 14 | } 15 | -------------------------------------------------------------------------------- /internal/semihosting/exit.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | //go:build semihosting 7 | // +build semihosting 8 | 9 | package semihosting 10 | 11 | // defined in exit_$GOARCH.s 12 | func sys_exit() 13 | 14 | func Exit() { 15 | sys_exit() 16 | } 17 | -------------------------------------------------------------------------------- /internal/semihosting/exit_arm.s: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | // func sys_exit() 7 | TEXT ·sys_exit(SB), $0 8 | MOVW $0x18, R0 // TARGET_SYS_EXIT 9 | MOVW $0x20026, R1 // ADP_Stopped_ApplicationExit 10 | WORD $0xef123456 // svc 0x00123456 11 | RET 12 | -------------------------------------------------------------------------------- /trusted_os_sifive_u/bios/bios.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_ARCH( "riscv" ) 2 | OUTPUT_FORMAT("elf64-littleriscv") 3 | ENTRY( _start ) 4 | SECTIONS 5 | { 6 | . = 0x80000000; 7 | .text : { *(.text) } 8 | .gnu_build_id : { *(.note.gnu.build-id) } 9 | .data : { *(.data) } 10 | .rodata : { *(.rodata) } 11 | .sdata : { *(.sdata) } 12 | .debug : { *(.debug) } 13 | . += 0x8000; 14 | stack_top = .; 15 | _end = .; 16 | } 17 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the list of GoTEE significant contributors. 2 | # 3 | # This does not necessarily list everyone who has contributed code, 4 | # especially since many employees of one corporation may be contributing. 5 | # To see the full list of contributors, see the revision history in 6 | # source control. 7 | Andrea Barisani 8 | Andrej Rosano 9 | -------------------------------------------------------------------------------- /nonsecure_os_go/api.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package main 7 | 8 | import ( 9 | "github.com/usbarmory/GoTEE/syscall" 10 | ) 11 | 12 | const ( 13 | SYS_WRITE = syscall.SYS_WRITE 14 | SYS_EXIT = syscall.SYS_EXIT 15 | ) 16 | 17 | // defined in api_*.s 18 | func printSecure(byte) 19 | func exit() 20 | -------------------------------------------------------------------------------- /internal/semihosting/exit_riscv64.s: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | // func sys_exit() 7 | TEXT ·sys_exit(SB), $0 8 | MOV $0x18, A0 // TARGET_SYS_EXIT 9 | MOV $0x20026, T1 // ADP_Stopped_ApplicationExit 10 | 11 | MOV -2*8(SP), A1 12 | MOV T1, (A1) 13 | 14 | SLLI $0x1f, X0, X0 15 | EBREAK 16 | SRAI $0x07, X0, X0 17 | RET 18 | -------------------------------------------------------------------------------- /nonsecure_os_go/api_arm.s: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | #include "go_asm.h" 7 | 8 | // func printSecure(c byte) 9 | TEXT ·printSecure(SB),$0-1 10 | MOVW $const_SYS_WRITE, R0 11 | MOVB c+0(FP), R1 12 | 13 | WORD $0xe1600070 // smc 0 14 | 15 | RET 16 | 17 | // func exit() 18 | TEXT ·exit(SB),$0 19 | MOVW $const_SYS_EXIT, R0 20 | 21 | WORD $0xe1600070 // smc 0 22 | 23 | RET 24 | -------------------------------------------------------------------------------- /nonsecure_os_go/api_riscv64.s: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | #include "go_asm.h" 7 | 8 | // A7 must be set to 0 to avoid interference with SBI 9 | 10 | // func printSecure(c byte) 11 | TEXT ·printSecure(SB),$0-1 12 | MOV $const_SYS_WRITE, A0 13 | MOV c+0(FP), A1 14 | 15 | MOV $0, A7 16 | ECALL 17 | 18 | RET 19 | 20 | // func exit() 21 | TEXT ·exit(SB),$0 22 | MOV $const_SYS_EXIT, A0 23 | 24 | MOV $0, A7 25 | ECALL 26 | 27 | RET 28 | -------------------------------------------------------------------------------- /trusted_applet_go/mem_riscv64.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package main 7 | 8 | import ( 9 | _ "unsafe" 10 | 11 | "github.com/usbarmory/GoTEE-example/mem" 12 | ) 13 | 14 | //go:linkname ramStart runtime.ramStart 15 | var ramStart uint64 = mem.AppletStart 16 | 17 | //go:linkname ramSize runtime.ramSize 18 | var ramSize uint64 = mem.AppletSize 19 | 20 | //go:linkname ramStackOffset runtime.ramStackOffset 21 | var ramStackOffset uint64 = 0x100 22 | -------------------------------------------------------------------------------- /trusted_applet_go/mem_arm.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package main 7 | 8 | import ( 9 | _ "unsafe" 10 | 11 | "github.com/usbarmory/GoTEE-example/mem" 12 | ) 13 | 14 | //go:linkname ramStart runtime.ramStart 15 | var ramStart uint32 = mem.AppletVirtualStart 16 | 17 | //go:linkname ramSize runtime.ramSize 18 | var ramSize uint32 = mem.AppletSize 19 | 20 | //go:linkname ramStackOffset runtime.ramStackOffset 21 | var ramStackOffset uint32 = 0x100 22 | -------------------------------------------------------------------------------- /trusted_os_sifive_u/cmd/gotee.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package cmd 7 | 8 | import ( 9 | "golang.org/x/term" 10 | 11 | "github.com/usbarmory/GoTEE-example/trusted_os_sifive_u/internal" 12 | ) 13 | 14 | func init() { 15 | Add(Cmd{ 16 | Name: "gotee", 17 | Help: "TrustZone example w/ TamaGo unikernels", 18 | Fn: goteeCmd, 19 | }) 20 | } 21 | 22 | func goteeCmd(term *term.Terminal, arg []string) (res string, err error) { 23 | return "", gotee.GoTEE() 24 | } 25 | -------------------------------------------------------------------------------- /trusted_os_sifive_u/internal/rpc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package gotee 7 | 8 | import ( 9 | "errors" 10 | 11 | "github.com/usbarmory/GoTEE-example/util" 12 | ) 13 | 14 | // RPC represents an example receiver for user mode <--> system RPC over system 15 | // calls. 16 | type RPC struct{} 17 | 18 | // Echo returns a response with the input string. 19 | func (r *RPC) Echo(in string, out *string) error { 20 | *out = in 21 | return nil 22 | } 23 | 24 | // LED receives a LED state request. 25 | func (r *RPC) LED(led util.LEDStatus, _ *bool) error { 26 | switch led.Name { 27 | case "white", "White", "WHITE": 28 | return errors.New("LED is secure only") 29 | case "blue", "Blue", "BLUE": 30 | // unimplemented as the target is virtual for now 31 | default: 32 | return errors.New("invalid LED") 33 | } 34 | 35 | return nil 36 | } 37 | -------------------------------------------------------------------------------- /trusted_os_sifive_u/internal/exec.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package gotee 7 | 8 | import ( 9 | "log" 10 | "sync" 11 | 12 | _ "github.com/usbarmory/tamago/board/qemu/sifive_u" 13 | 14 | "github.com/usbarmory/GoTEE/monitor" 15 | ) 16 | 17 | func GoTEE() (err error) { 18 | var wg sync.WaitGroup 19 | var ta *monitor.ExecCtx 20 | var os *monitor.ExecCtx 21 | 22 | if ta, err = loadApplet(); err != nil { 23 | return 24 | } 25 | 26 | if os, err = loadSupervisor(); err != nil { 27 | return 28 | } 29 | 30 | // test concurrent execution of: 31 | // Security Monitor (machine mode) - secure OS (this program) 32 | // Applet (supervisor/user mode) - trusted applet 33 | // Untrusted OS (supervisor/user mode) - main OS 34 | wg.Add(2) 35 | go run(ta, &wg) 36 | go run(os, &wg) 37 | 38 | log.Printf("SM waiting for applet and kernel") 39 | wg.Wait() 40 | 41 | return 42 | } 43 | -------------------------------------------------------------------------------- /trusted_os_usbarmory/internal/rpc.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package gotee 7 | 8 | import ( 9 | "errors" 10 | 11 | usbarmory "github.com/usbarmory/tamago/board/usbarmory/mk2" 12 | 13 | "github.com/usbarmory/GoTEE-example/util" 14 | ) 15 | 16 | // RPC represents an example receiver for user mode <--> system RPC over system 17 | // calls. 18 | type RPC struct{} 19 | 20 | // Echo returns a response with the input string. 21 | func (r *RPC) Echo(in string, out *string) error { 22 | *out = in 23 | return nil 24 | } 25 | 26 | // LED receives a LED state request. 27 | func (r *RPC) LED(led util.LEDStatus, _ *bool) error { 28 | switch led.Name { 29 | case "white", "White", "WHITE": 30 | return errors.New("LED is secure only") 31 | case "blue", "Blue", "BLUE": 32 | return usbarmory.LED(led.Name, led.On) 33 | default: 34 | return errors.New("invalid LED") 35 | } 36 | 37 | return nil 38 | } 39 | -------------------------------------------------------------------------------- /mem/util.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package mem 7 | 8 | import ( 9 | "log" 10 | "sync/atomic" 11 | "unsafe" 12 | ) 13 | 14 | // TestAccess attempts to read one 32-bit word from Secure World memory. 15 | func TestAccess(tag string) { 16 | addr := SecureStart + uint32(0x10000) 17 | mem := (*uint32)(unsafe.Pointer(uintptr(addr))) 18 | 19 | log.Printf("%s is about to read secure memory at %#x", tag, addr) 20 | val := atomic.LoadUint32(mem) 21 | 22 | res := "success - *insecure configuration*" 23 | 24 | if val != textStartWord { 25 | res = "fail (expected, but you should never see this)" 26 | } 27 | 28 | log.Printf("%s read secure memory %#x: %#x (%s)", tag, addr, val, res) 29 | } 30 | 31 | // TestDataAbort abort attempts a write to unallocated memory. 32 | func TestDataAbort(tag string) { 33 | var p *byte 34 | 35 | log.Printf("%s is about to trigger a data abort", tag) 36 | *p = 0xab 37 | } 38 | -------------------------------------------------------------------------------- /mem/layout_riscv64.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package mem 7 | 8 | import ( 9 | "github.com/usbarmory/tamago/dma" 10 | ) 11 | 12 | const ( 13 | // Secure Monitor 14 | SecureStart = 0x90000000 15 | SecureSize = 0x03f00000 // 63MB 16 | 17 | // Secure Monitor DMA (relocated to avoid conflicts with Main OS) 18 | SecureDMAStart = 0x94f00000 19 | SecureDMASize = 0x00100000 // 1MB 20 | 21 | // Secure Monitor Applet 22 | AppletStart = 0x95000000 23 | AppletSize = 0x02000000 // 32MB 24 | 25 | // Main OS 26 | NonSecureStart = 0x80000000 27 | NonSecureSize = 0x10000000 // 256MB 28 | ) 29 | 30 | const textStartWord = 0x010db303 31 | 32 | var ( 33 | AppletRegion *dma.Region 34 | NonSecureRegion *dma.Region 35 | ) 36 | 37 | func Init() { 38 | AppletRegion, _ = dma.NewRegion(AppletStart, AppletSize, false) 39 | AppletRegion.Reserve(AppletSize, 0) 40 | 41 | NonSecureRegion, _ = dma.NewRegion(NonSecureStart, NonSecureSize, false) 42 | NonSecureRegion.Reserve(NonSecureSize, 0) 43 | } 44 | -------------------------------------------------------------------------------- /util/log.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package util 7 | 8 | import ( 9 | "bytes" 10 | "os" 11 | 12 | "golang.org/x/term" 13 | ) 14 | 15 | var secureOutput bytes.Buffer 16 | var nonSecureOutput bytes.Buffer 17 | 18 | const outputLimit = 1024 19 | const flushChr = 0x0a // \n 20 | 21 | func BufferedStdoutLog(c byte, secure bool) { 22 | var buf *bytes.Buffer 23 | 24 | if secure { 25 | buf = &secureOutput 26 | } else { 27 | buf = &nonSecureOutput 28 | } 29 | 30 | buf.WriteByte(c) 31 | 32 | if c == flushChr || buf.Len() > outputLimit { 33 | os.Stdout.Write(buf.Bytes()) 34 | buf.Reset() 35 | } 36 | } 37 | 38 | func BufferedTermLog(c byte, secure bool, t *term.Terminal) { 39 | var buf *bytes.Buffer 40 | var color []byte 41 | 42 | if secure { 43 | buf = &secureOutput 44 | color = t.Escape.Green 45 | } else { 46 | buf = &nonSecureOutput 47 | color = t.Escape.Red 48 | } 49 | 50 | buf.WriteByte(c) 51 | 52 | if c == flushChr || buf.Len() > outputLimit { 53 | t.Write(color) 54 | t.Write(buf.Bytes()) 55 | t.Write(t.Escape.Reset) 56 | 57 | buf.Reset() 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /nonsecure_os_go/main_riscv64.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package main 7 | 8 | import ( 9 | "log" 10 | "os" 11 | "runtime" 12 | _ "unsafe" 13 | 14 | "github.com/usbarmory/tamago/soc/sifive/fu540" 15 | 16 | "github.com/usbarmory/GoTEE-example/mem" 17 | ) 18 | 19 | //go:linkname ramStart runtime.ramStart 20 | var ramStart uint64 = mem.NonSecureStart 21 | 22 | //go:linkname ramSize runtime.ramSize 23 | var ramSize uint64 = mem.NonSecureSize 24 | 25 | //go:linkname hwinit runtime.hwinit1 26 | func hwinit() { 27 | fu540.RV64.InitSupervisor() 28 | } 29 | 30 | //go:linkname printk runtime.printk 31 | func printk(c byte) { 32 | printSecure(c) 33 | } 34 | 35 | func init() { 36 | log.SetFlags(log.Ltime) 37 | log.SetOutput(os.Stdout) 38 | } 39 | 40 | func main() { 41 | log.Printf("%s/%s (%s) • supervisor", runtime.GOOS, runtime.GOARCH, runtime.Version()) 42 | 43 | // uncomment to test memory protection 44 | // mem.TestAccess("supervisor") 45 | 46 | // yield back to secure monitor 47 | log.Printf("supervisor is about to yield back") 48 | exit() 49 | 50 | // this should be unreachable 51 | log.Printf("supervisor says goodbye") 52 | } 53 | -------------------------------------------------------------------------------- /trusted_os_sifive_u/cmd/iopmp.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | //go:build sifive_u 7 | // +build sifive_u 8 | 9 | package cmd 10 | 11 | import ( 12 | "errors" 13 | "fmt" 14 | "regexp" 15 | "strconv" 16 | 17 | "golang.org/x/term" 18 | 19 | "github.com/usbarmory/tamago/soc/sifive/physicalfilter" 20 | ) 21 | 22 | var Base uint32 23 | 24 | func init() { 25 | Add(Cmd{ 26 | Name: "iopmp", 27 | Args: 1, 28 | Pattern: regexp.MustCompile(`^iopmp (\d+)$`), 29 | Syntax: "", 30 | Help: "read Device PMP", 31 | Fn: iopmpRead, 32 | }) 33 | } 34 | 35 | func iopmpRead(_ *term.Terminal, arg []string) (res string, err error) { 36 | if Base == 0 { 37 | return "", errors.New("unavailable") 38 | } 39 | 40 | i, err := strconv.ParseUint(arg[0], 10, 8) 41 | 42 | if err != nil { 43 | return "", fmt.Errorf("invalid size, %v", err) 44 | } 45 | 46 | pf := &physicalfilter.PhysicalFilter{ 47 | Base: Base, 48 | } 49 | 50 | addr, r, w, a, lock, err := pf.ReadPMP(int(i)) 51 | 52 | if err != nil { 53 | return 54 | } 55 | 56 | return fmt.Sprintf("DevicePMP:%.2d addr:%#.16x A:%v R:%v W:%v lock:%v", i, addr, a, r, w, lock), nil 57 | } 58 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/usbarmory/GoTEE-example 2 | 3 | go 1.24.6 4 | 5 | require ( 6 | github.com/usbarmory/GoTEE v0.0.0-20250811152814-d8456103e1fc 7 | github.com/usbarmory/armory-boot v0.0.0-20250313080757-07776e494cb3 8 | github.com/usbarmory/imx-usbnet v0.0.0-20250123113617-d39929cd7171 9 | github.com/usbarmory/tamago v0.0.0-20250811152003-24ca488864f4 10 | golang.org/x/crypto v0.41.0 11 | golang.org/x/term v0.34.0 12 | ) 13 | 14 | require ( 15 | github.com/dsoprea/go-ext4 v0.0.0-20190528173430-c13b09fc0ff8 // indirect 16 | github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect 17 | github.com/dustin/go-humanize v1.0.1 // indirect 18 | github.com/go-errors/errors v1.0.2 // indirect 19 | github.com/google/btree v1.1.2 // indirect 20 | github.com/klauspost/compress v1.17.4 // indirect 21 | github.com/pierrec/lz4/v4 v4.1.14 // indirect 22 | github.com/u-root/u-root v0.14.0 // indirect 23 | github.com/u-root/uio v0.0.0-20240209044354-b3d14b93376a // indirect 24 | github.com/ulikunitz/xz v0.5.11 // indirect 25 | golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect 26 | golang.org/x/net v0.42.0 // indirect 27 | golang.org/x/sys v0.35.0 // indirect 28 | golang.org/x/time v0.5.0 // indirect 29 | gvisor.dev/gvisor v0.0.0-20240909175600-91fb8ad18db5 // indirect 30 | ) 31 | -------------------------------------------------------------------------------- /trusted_os_sifive_u/internal/handler.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package gotee 7 | 8 | import ( 9 | "github.com/usbarmory/GoTEE/monitor" 10 | "github.com/usbarmory/GoTEE/sbi" 11 | "github.com/usbarmory/GoTEE/syscall" 12 | 13 | "github.com/usbarmory/GoTEE-example/util" 14 | ) 15 | 16 | var Console *util.Console 17 | 18 | func goHandler(ctx *monitor.ExecCtx) (err error) { 19 | defaultHandler := monitor.SecureHandler 20 | 21 | if !ctx.Secure() { 22 | defaultHandler = monitor.NonSecureHandler 23 | } 24 | 25 | switch { 26 | case ctx.A0() == syscall.SYS_WRITE: 27 | // Override write syscall to avoid interleaved logs and to log 28 | // simultaneously to remote terminal and serial console. 29 | if Console.Term != nil { 30 | util.BufferedTermLog(byte(ctx.A1()), ctx.Secure(), Console.Term) 31 | } else { 32 | util.BufferedStdoutLog(byte(ctx.A1()), ctx.Secure()) 33 | } 34 | case !ctx.Secure() && ctx.A0() == syscall.SYS_EXIT: 35 | ctx.Stop() 36 | default: 37 | return defaultHandler(ctx) 38 | } 39 | 40 | return 41 | } 42 | 43 | func sbiHandler(ctx *monitor.ExecCtx) (err error) { 44 | // SBI v0.2 or higher calls are treated separately from GoTEE calls 45 | if ctx.X17 != 0 { 46 | return sbi.Handler(ctx) 47 | } else { 48 | return goHandler(ctx) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /trusted_os_sifive_u/cmd/common.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package cmd 7 | 8 | import ( 9 | "bytes" 10 | "io" 11 | "regexp" 12 | "runtime/debug" 13 | "runtime/pprof" 14 | 15 | "golang.org/x/term" 16 | ) 17 | 18 | func init() { 19 | Add(Cmd{ 20 | Name: "help", 21 | Help: "this help", 22 | Fn: helpCmd, 23 | }) 24 | 25 | Add(Cmd{ 26 | Name: "exit, quit", 27 | Args: 1, 28 | Pattern: regexp.MustCompile(`^(exit|quit)$`), 29 | Help: "close session", 30 | Fn: exitCmd, 31 | }) 32 | 33 | Add(Cmd{ 34 | Name: "stack", 35 | Help: "stack trace of current goroutine", 36 | Fn: stackCmd, 37 | }) 38 | 39 | Add(Cmd{ 40 | Name: "stackall", 41 | Help: "stack trace of all goroutines", 42 | Fn: stackallCmd, 43 | }) 44 | } 45 | 46 | func helpCmd(term *term.Terminal, _ []string) (string, error) { 47 | return Help(term), nil 48 | } 49 | 50 | func exitCmd(_ *term.Terminal, _ []string) (string, error) { 51 | return "logout", io.EOF 52 | } 53 | 54 | func stackCmd(_ *term.Terminal, _ []string) (string, error) { 55 | return string(debug.Stack()), nil 56 | } 57 | 58 | func stackallCmd(_ *term.Terminal, _ []string) (string, error) { 59 | buf := new(bytes.Buffer) 60 | pprof.Lookup("goroutine").WriteTo(buf, 1) 61 | 62 | return buf.String(), nil 63 | } 64 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) The GoTEE authors. All Rights Reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Reversec Consulting AB nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /mem/layout_arm.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package mem 7 | 8 | import ( 9 | "github.com/usbarmory/tamago/dma" 10 | "github.com/usbarmory/tamago/soc/nxp/bee" 11 | ) 12 | 13 | const ( 14 | // Secure Monitor 15 | SecureStart = 0x90000000 16 | SecureSize = 0x05f00000 // 95MB 17 | 18 | // Secure Monitor DMA (relocated to avoid conflicts with Main OS) 19 | SecureDMAStart = 0x95f00000 20 | SecureDMASize = 0x00100000 // 1MB 21 | 22 | // Secure Monitor Applet (virtual) 23 | AppletVirtualStart = bee.AliasRegion0 // memory alias 24 | AppletSize = 0x02000000 // 32MB 25 | 26 | // Secure Monitor Applet (physical) 27 | // 28 | // i.MX6ULL/i.MX6ULZ: primary and shadow areas used in soft lockstep. 29 | // i.MX6UL : primary area AES encrypted w/ BEE, no lockstep. 30 | AppletPhysicalStart = 0x96000000 31 | AppletShadowStart = 0x98000000 32 | 33 | // Main OS 34 | NonSecureStart = 0x80000000 35 | NonSecureSize = 0x10000000 // 256MB 36 | ) 37 | 38 | // BEE enables AES CTR encryption for the Applet RAM on i.MX6UL P/Ns 39 | const BEE = true 40 | 41 | const textStartWord = 0xe59a1008 42 | 43 | var ( 44 | AppletRegion *dma.Region 45 | NonSecureRegion *dma.Region 46 | ) 47 | 48 | func Init() { 49 | AppletRegion, _ = dma.NewRegion(AppletVirtualStart, AppletSize, false) 50 | AppletRegion.Reserve(AppletSize, 0) 51 | 52 | NonSecureRegion, _ = dma.NewRegion(NonSecureStart, NonSecureSize, false) 53 | NonSecureRegion.Reserve(NonSecureSize, 0) 54 | } 55 | -------------------------------------------------------------------------------- /trusted_os_usbarmory/cmd/arm.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package cmd 7 | 8 | import ( 9 | "bytes" 10 | "errors" 11 | "fmt" 12 | 13 | "golang.org/x/term" 14 | 15 | "github.com/usbarmory/tamago/bits" 16 | "github.com/usbarmory/tamago/soc/nxp/imx6ul" 17 | ) 18 | 19 | func init() { 20 | Add(Cmd{ 21 | Name: "dbg", 22 | Help: "show ARM debug permissions", 23 | Fn: dbgCmd, 24 | }) 25 | } 26 | 27 | func dbgCmd(term *term.Terminal, arg []string) (res string, err error) { 28 | var buf bytes.Buffer 29 | 30 | if !imx6ul.Native { 31 | return "", errors.New("unsupported under emulation") 32 | } 33 | 34 | dbgAuthStatus := imx6ul.ARM.DebugStatus() 35 | 36 | buf.WriteString("| type | implemented | enabled |\n") 37 | buf.WriteString("|-------------------------|-------------|---------|\n") 38 | 39 | fmt.Fprintf(&buf, "| Secure non-invasive | %d | %d |\n", 40 | bits.Get(&dbgAuthStatus, 7, 1), 41 | bits.Get(&dbgAuthStatus, 6, 1), 42 | ) 43 | 44 | fmt.Fprintf(&buf, "| Secure invasive | %d | %d |\n", 45 | bits.Get(&dbgAuthStatus, 5, 1), 46 | bits.Get(&dbgAuthStatus, 4, 1), 47 | ) 48 | 49 | fmt.Fprintf(&buf, "| Non-secure non-invasive | %d | %d |\n", 50 | bits.Get(&dbgAuthStatus, 3, 1), 51 | bits.Get(&dbgAuthStatus, 2, 1), 52 | ) 53 | 54 | fmt.Fprintf(&buf, "| Non-secure invasive | %d | %d |\n", 55 | bits.Get(&dbgAuthStatus, 1, 1), 56 | bits.Get(&dbgAuthStatus, 0, 1), 57 | ) 58 | 59 | return buf.String(), nil 60 | } 61 | -------------------------------------------------------------------------------- /trusted_os_usbarmory/cmd/gotee.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package cmd 7 | 8 | import ( 9 | "errors" 10 | "regexp" 11 | "strconv" 12 | 13 | "golang.org/x/term" 14 | 15 | "github.com/usbarmory/tamago/soc/nxp/imx6ul" 16 | 17 | "github.com/usbarmory/GoTEE-example/trusted_os_usbarmory/internal" 18 | ) 19 | 20 | func init() { 21 | Add(Cmd{ 22 | Name: "gotee", 23 | Help: "TrustZone example w/ TamaGo unikernels", 24 | Fn: goteeCmd, 25 | }) 26 | 27 | Add(Cmd{ 28 | Name: "linux", 29 | Args: 1, 30 | Pattern: regexp.MustCompile(`^linux (uSD|eMMC)$`), 31 | Syntax: "", 32 | Help: "boot NonSecure USB armory Debian base image", 33 | Fn: linuxCmd, 34 | }) 35 | 36 | Add(Cmd{ 37 | Name: "lockstep", 38 | Args: 1, 39 | Pattern: regexp.MustCompile(`^lockstep (.*)$`), 40 | Syntax: "", 41 | Help: "tandem applet example w/ fault injection", 42 | Fn: lockstepCmd, 43 | }) 44 | } 45 | 46 | func goteeCmd(term *term.Terminal, arg []string) (res string, err error) { 47 | return "", gotee.GoTEE() 48 | } 49 | 50 | func linuxCmd(term *term.Terminal, arg []string) (res string, err error) { 51 | if !imx6ul.Native { 52 | return "", errors.New("unsupported under emulation") 53 | } 54 | 55 | return "", gotee.Linux(arg[0]) 56 | } 57 | 58 | func lockstepCmd(term *term.Terminal, arg []string) (res string, err error) { 59 | faultPercentage, err := strconv.ParseFloat(arg[0], 64) 60 | 61 | if err != nil { 62 | return 63 | } 64 | 65 | return "", gotee.Lockstep(faultPercentage) 66 | } 67 | -------------------------------------------------------------------------------- /trusted_os_sifive_u/main.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package main 7 | 8 | import ( 9 | _ "embed" 10 | "fmt" 11 | "log" 12 | "os" 13 | "runtime" 14 | _ "unsafe" 15 | 16 | "github.com/usbarmory/tamago/board/qemu/sifive_u" 17 | "github.com/usbarmory/tamago/dma" 18 | 19 | "github.com/usbarmory/GoTEE-example/internal/semihosting" 20 | "github.com/usbarmory/GoTEE-example/mem" 21 | "github.com/usbarmory/GoTEE-example/trusted_os_sifive_u/cmd" 22 | "github.com/usbarmory/GoTEE-example/trusted_os_sifive_u/internal" 23 | "github.com/usbarmory/GoTEE-example/util" 24 | ) 25 | 26 | // This example embeds the Trusted Applet and Main OS ELF binaries within the 27 | // Trusted OS executable, using Go embed package. 28 | 29 | //go:embed assets/trusted_applet.elf 30 | var taELF []byte 31 | 32 | //go:embed assets/nonsecure_os_go.elf 33 | var osELF []byte 34 | 35 | //go:linkname ramStart runtime.ramStart 36 | var ramStart uint64 = mem.SecureStart 37 | 38 | //go:linkname ramSize runtime.ramSize 39 | var ramSize uint64 = mem.SecureSize 40 | 41 | func init() { 42 | log.SetFlags(log.Ltime) 43 | log.SetOutput(os.Stdout) 44 | 45 | mem.Init() 46 | dma.Init(mem.SecureDMAStart, mem.SecureDMASize) 47 | 48 | cmd.Banner = fmt.Sprintf("%s/%s (%s) • TEE Security Monitor (M-mode)", runtime.GOOS, runtime.GOARCH, runtime.Version()) 49 | 50 | gotee.TA = taELF 51 | gotee.OS = osELF 52 | } 53 | 54 | func main() { 55 | gotee.Console = util.NewScreenConsole() 56 | cmd.SerialConsole(sifive_u.UART0) 57 | 58 | log.Printf("SM says goodbye") 59 | semihosting.Exit() 60 | } 61 | -------------------------------------------------------------------------------- /trusted_os_usbarmory/cmd/common.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package cmd 7 | 8 | import ( 9 | "bytes" 10 | "io" 11 | "regexp" 12 | "runtime/debug" 13 | "runtime/pprof" 14 | 15 | "golang.org/x/term" 16 | 17 | usbarmory "github.com/usbarmory/tamago/board/usbarmory/mk2" 18 | ) 19 | 20 | func init() { 21 | Add(Cmd{ 22 | Name: "help", 23 | Help: "this help", 24 | Fn: helpCmd, 25 | }) 26 | 27 | Add(Cmd{ 28 | Name: "exit, quit", 29 | Args: 1, 30 | Pattern: regexp.MustCompile(`^(exit|quit)$`), 31 | Help: "close session", 32 | Fn: exitCmd, 33 | }) 34 | 35 | Add(Cmd{ 36 | Name: "stack", 37 | Help: "stack trace of current goroutine", 38 | Fn: stackCmd, 39 | }) 40 | 41 | Add(Cmd{ 42 | Name: "stackall", 43 | Help: "stack trace of all goroutines", 44 | Fn: stackallCmd, 45 | }) 46 | 47 | Add(Cmd{ 48 | Name: "reboot", 49 | Help: "reset device", 50 | Fn: rebootCmd, 51 | }) 52 | } 53 | 54 | func helpCmd(term *term.Terminal, _ []string) (string, error) { 55 | return Help(term), nil 56 | } 57 | 58 | func exitCmd(_ *term.Terminal, _ []string) (string, error) { 59 | return "logout", io.EOF 60 | } 61 | 62 | func stackCmd(_ *term.Terminal, _ []string) (string, error) { 63 | return string(debug.Stack()), nil 64 | } 65 | 66 | func stackallCmd(_ *term.Terminal, _ []string) (string, error) { 67 | buf := new(bytes.Buffer) 68 | pprof.Lookup("goroutine").WriteTo(buf, 1) 69 | 70 | return buf.String(), nil 71 | } 72 | 73 | func rebootCmd(_ *term.Terminal, _ []string) (_ string, _ error) { 74 | usbarmory.Reset() 75 | return 76 | } 77 | -------------------------------------------------------------------------------- /trusted_applet_go/main.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package main 7 | 8 | import ( 9 | "log" 10 | "os" 11 | "runtime" 12 | "time" 13 | 14 | "github.com/usbarmory/GoTEE/applet" 15 | "github.com/usbarmory/GoTEE/syscall" 16 | 17 | "github.com/usbarmory/GoTEE-example/mem" 18 | "github.com/usbarmory/GoTEE-example/util" 19 | ) 20 | 21 | func init() { 22 | log.SetFlags(log.Ltime) 23 | log.SetOutput(os.Stdout) 24 | 25 | // yield to monitor (w/ err != nil) on runtime panic 26 | runtime.Exit = applet.Crash 27 | } 28 | 29 | func testRNG(n int) { 30 | buf := make([]byte, n) 31 | syscall.GetRandom(buf, uint(n)) 32 | log.Printf("applet obtained %d random bytes from monitor: %x", n, buf) 33 | } 34 | 35 | func testRPC() { 36 | res := "" 37 | req := "hello" 38 | 39 | log.Printf("applet requests echo via RPC: %s", req) 40 | err := syscall.Call("RPC.Echo", req, &res) 41 | 42 | if err != nil { 43 | log.Printf("applet received RPC error: %v", err) 44 | } else { 45 | log.Printf("applet received echo via RPC: %s", res) 46 | } 47 | } 48 | 49 | func main() { 50 | log.Printf("%s/%s (%s) • TEE user applet", runtime.GOOS, runtime.GOARCH, runtime.Version()) 51 | 52 | // test syscall interface 53 | testRNG(16) 54 | 55 | // test RPC interface 56 | testRPC() 57 | 58 | log.Printf("applet will sleep for 5 seconds") 59 | 60 | ledStatus := util.LEDStatus{ 61 | Name: "blue", 62 | On: true, 63 | } 64 | 65 | // test concurrent execution of applet and supervisor/monitor 66 | for i := 0; i < 5; i++ { 67 | syscall.Call("RPC.LED", ledStatus, nil) 68 | ledStatus.On = !ledStatus.On 69 | 70 | time.Sleep(1 * time.Second) 71 | log.Printf("applet says %d mississippi", i+1) 72 | } 73 | 74 | // test memory protection 75 | mem.TestAccess("applet") 76 | 77 | // this should be unreachable 78 | 79 | // test exception handling 80 | mem.TestDataAbort("applet") 81 | 82 | // terminate applet 83 | applet.Exit() 84 | } 85 | -------------------------------------------------------------------------------- /trusted_os_sifive_u/internal/pmp.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package gotee 7 | 8 | import ( 9 | "github.com/usbarmory/tamago/riscv64" 10 | "github.com/usbarmory/tamago/soc/sifive/fu540" 11 | 12 | "github.com/usbarmory/GoTEE/monitor" 13 | 14 | "github.com/usbarmory/GoTEE-example/mem" 15 | ) 16 | 17 | const ( 18 | smStart = mem.SecureStart 19 | smEnd = mem.SecureStart + mem.SecureSize + mem.SecureDMASize 20 | ) 21 | 22 | func configurePMP(ctx *monitor.ExecCtx, i int) (err error) { 23 | // The main OS used in GoTEE-example, for the riscv64 architecture, is 24 | // a TamaGo unikernel which requires only PRCI, CLINT and UART0 access. 25 | // 26 | // On the FU540 the lack of IOPMP entails that only bus peripherals can 27 | // be given access through PMP, while bus controllers (e.g. Ethernet) 28 | // must be exposed only through the Security Monitor API, and never 29 | // directly, for secure isolation. 30 | // 31 | // The access to PRCI, CLINT and UART0 can be granted without concerns 32 | // as they they cannot act as bus controllers. 33 | 34 | // grant PRCI and UART0 access 35 | 36 | if err = fu540.RV64.WritePMP(i, fu540.PRCI_BASE, false, false, false, riscv64.PMP_A_OFF, false); err != nil { 37 | return 38 | } 39 | i += 1 40 | 41 | if err = fu540.RV64.WritePMP(i, fu540.UART1_BASE, true, true, true, riscv64.PMP_A_TOR, false); err != nil { 42 | return 43 | } 44 | i += 1 45 | 46 | // grant CLINT access 47 | 48 | if err = fu540.RV64.WritePMP(i, fu540.CLINT_BASE, false, false, false, riscv64.PMP_A_OFF, false); err != nil { 49 | return 50 | } 51 | i += 1 52 | 53 | if err = fu540.RV64.WritePMP(i, fu540.CLINT_BASE+0x10000, true, true, true, riscv64.PMP_A_TOR, false); err != nil { 54 | return 55 | } 56 | i += 1 57 | 58 | // protect Security Monitor 59 | 60 | if err = fu540.RV64.WritePMP(i, smStart, false, false, false, riscv64.PMP_A_OFF, false); err != nil { 61 | return 62 | } 63 | i += 1 64 | 65 | if err = fu540.RV64.WritePMP(i, smEnd, false, false, false, riscv64.PMP_A_TOR, false); err != nil { 66 | return 67 | } 68 | 69 | return 70 | } 71 | -------------------------------------------------------------------------------- /trusted_os_usbarmory/internal/handler.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package gotee 7 | 8 | import ( 9 | "errors" 10 | "fmt" 11 | "log" 12 | 13 | "github.com/usbarmory/tamago/arm" 14 | "github.com/usbarmory/tamago/soc/nxp/imx6ul" 15 | 16 | "github.com/usbarmory/GoTEE/monitor" 17 | "github.com/usbarmory/GoTEE/syscall" 18 | 19 | "github.com/usbarmory/GoTEE-example/util" 20 | ) 21 | 22 | var Console *util.Console 23 | 24 | func goHandler(ctx *monitor.ExecCtx) (err error) { 25 | if ctx.ExceptionVector == arm.DATA_ABORT && ctx.NonSecure() { 26 | log.Printf("SM trapped Non-secure data abort pc:%#.8x", ctx.R15-8) 27 | 28 | log.Print(ctx) 29 | ctx.Stop() 30 | 31 | return 32 | } 33 | 34 | if ctx.ExceptionVector != arm.SUPERVISOR { 35 | return fmt.Errorf("exception %x", ctx.ExceptionVector) 36 | } 37 | 38 | switch ctx.A0() { 39 | case syscall.SYS_WRITE: 40 | // Override write syscall to avoid interleaved logs and to log 41 | // simultaneously to remote terminal and serial console. 42 | if Console != nil { 43 | util.BufferedTermLog(byte(ctx.A1()), !ctx.NonSecure(), Console.Term) 44 | } else { 45 | util.BufferedStdoutLog(byte(ctx.A1()), !ctx.NonSecure()) 46 | } 47 | case syscall.SYS_EXIT: 48 | // support exit syscall on both security states 49 | ctx.Stop() 50 | default: 51 | if ctx.NonSecure() { 52 | log.Print(ctx) 53 | return errors.New("unexpected monitor call") 54 | } else { 55 | return monitor.SecureHandler(ctx) 56 | } 57 | } 58 | 59 | return 60 | } 61 | 62 | func linuxHandler(ctx *monitor.ExecCtx) (err error) { 63 | if !ctx.NonSecure() { 64 | return errors.New("unexpected processor mode") 65 | } 66 | 67 | switch ctx.ExceptionVector { 68 | case arm.FIQ: 69 | switch imx6ul.GIC.GetInterrupt(true) { 70 | case imx6ul.TZ_WDOG.IRQ: 71 | imx6ul.TZ_WDOG.Service(watchdogTimeout) 72 | log.Printf("SM serviced TrustZone Watchdog") 73 | } 74 | 75 | return 76 | case arm.SUPERVISOR: 77 | return monitor.NonSecureHandler(ctx) 78 | default: 79 | return fmt.Errorf("unhandled exception %x", ctx.ExceptionVector) 80 | } 81 | 82 | return 83 | } 84 | -------------------------------------------------------------------------------- /nonsecure_os_go/main_arm.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package main 7 | 8 | import ( 9 | "crypto/aes" 10 | "crypto/sha256" 11 | "log" 12 | "os" 13 | "runtime" 14 | _ "unsafe" 15 | 16 | "github.com/usbarmory/tamago/dma" 17 | "github.com/usbarmory/tamago/soc/nxp/imx6ul" 18 | 19 | "github.com/usbarmory/GoTEE-example/mem" 20 | ) 21 | 22 | //go:linkname ramStart runtime.ramStart 23 | var ramStart uint32 = mem.NonSecureStart 24 | 25 | //go:linkname ramSize runtime.ramSize 26 | var ramSize uint32 = mem.NonSecureSize 27 | 28 | //go:linkname hwinit runtime.hwinit1 29 | func hwinit() { 30 | imx6ul.Init() 31 | } 32 | 33 | //go:linkname printk runtime.printk 34 | func printk(c byte) { 35 | printSecure(c) 36 | } 37 | 38 | func init() { 39 | log.SetFlags(log.Ltime) 40 | log.SetOutput(os.Stdout) 41 | 42 | if !imx6ul.Native { 43 | return 44 | } 45 | 46 | switch imx6ul.Family { 47 | case imx6ul.IMX6UL: 48 | imx6ul.SetARMFreq(imx6ul.Freq528) 49 | imx6ul.CAAM.DeriveKeyMemory = dma.Default() 50 | case imx6ul.IMX6ULL: 51 | imx6ul.SetARMFreq(imx6ul.FreqMax) 52 | } 53 | } 54 | 55 | func main() { 56 | log.Printf("%s/%s (%s) • system/supervisor (Non-secure:%v)", runtime.GOOS, runtime.GOARCH, runtime.Version(), imx6ul.ARM.NonSecure()) 57 | 58 | if imx6ul.Native { 59 | var err error 60 | var k []byte 61 | 62 | log.Printf("supervisor is about to perform hardware key derivation") 63 | 64 | switch { 65 | case imx6ul.CAAM != nil: 66 | // derived key differs in non-secure 67 | k = make([]byte, sha256.Size) 68 | err = imx6ul.CAAM.DeriveKey(make([]byte, sha256.Size), k) 69 | case imx6ul.DCP != nil: 70 | // this fails after restrictions are in place (see trusted_os/tz.go) 71 | imx6ul.DCP.Init() 72 | k, err = imx6ul.DCP.DeriveKey(make([]byte, aes.BlockSize), make([]byte, aes.BlockSize), -1) 73 | } 74 | 75 | if err != nil { 76 | log.Printf("supervisor failed to derive key (%v)", err) 77 | } else { 78 | log.Printf("supervisor successfully derived key (%x)", k) 79 | } 80 | } 81 | 82 | // uncomment to test memory protection 83 | //mem.TestAccess("Non-secure OS") 84 | 85 | // yield back to secure monitor 86 | log.Printf("supervisor is about to yield back") 87 | exit() 88 | 89 | // this should be unreachable 90 | log.Printf("supervisor says goodbye") 91 | } 92 | -------------------------------------------------------------------------------- /trusted_os_sifive_u/cmd/pmp.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | //go:build sifive_u 7 | // +build sifive_u 8 | 9 | package cmd 10 | 11 | import ( 12 | "fmt" 13 | "regexp" 14 | "strconv" 15 | 16 | "golang.org/x/term" 17 | 18 | "github.com/usbarmory/tamago/soc/sifive/fu540" 19 | ) 20 | 21 | func init() { 22 | Add(Cmd{ 23 | Name: "pmp ", 24 | Args: 1, 25 | Pattern: regexp.MustCompile(`^pmp (\d+)$`), 26 | Syntax: "", 27 | Help: "read PMP CSR", 28 | Fn: pmpRead, 29 | }) 30 | 31 | Add(Cmd{ 32 | Name: "pmp", 33 | Args: 7, 34 | Pattern: regexp.MustCompile(`^pmp (\d+) ([[:xdigit:]]+) (\S+) (\S+) (\S+) (\d+) (\S+)$`), 35 | Syntax: " ", 36 | Help: "write PMP CSR", 37 | Fn: pmpWrite, 38 | }) 39 | } 40 | 41 | func pmpRead(_ *term.Terminal, arg []string) (res string, err error) { 42 | i, err := strconv.ParseUint(arg[0], 10, 8) 43 | 44 | if err != nil { 45 | return "", fmt.Errorf("invalid index, %v", err) 46 | } 47 | 48 | addr, r, w, x, a, l, err := fu540.RV64.ReadPMP(int(i)) 49 | 50 | if err != nil { 51 | return 52 | } 53 | 54 | return fmt.Sprintf("PMP:%.2d addr:%.16x A:%d R:%v W:%v X:%v l:%v", i, addr, a, r, w, x, l), nil 55 | } 56 | 57 | func pmpWrite(_ *term.Terminal, arg []string) (res string, err error) { 58 | i, err := strconv.ParseUint(arg[0], 10, 8) 59 | 60 | if err != nil { 61 | return "", fmt.Errorf("invalid index, %v", err) 62 | } 63 | 64 | addr, err := strconv.ParseUint(arg[1], 16, 64) 65 | 66 | if err != nil { 67 | return "", fmt.Errorf("invalid address, %v", err) 68 | } 69 | 70 | a, err := strconv.ParseUint(arg[2], 10, 2) 71 | 72 | if err != nil { 73 | return "", fmt.Errorf("invalid A value, %v", err) 74 | } 75 | 76 | r, err := strconv.ParseBool(arg[3]) 77 | 78 | if err != nil { 79 | return "", fmt.Errorf("invalid R boolean, %v", err) 80 | } 81 | 82 | w, err := strconv.ParseBool(arg[4]) 83 | 84 | if err != nil { 85 | return "", fmt.Errorf("invalid W boolean, %v", err) 86 | } 87 | 88 | x, err := strconv.ParseBool(arg[5]) 89 | 90 | if err != nil { 91 | return "", fmt.Errorf("invalid X boolean, %v", err) 92 | } 93 | 94 | l, err := strconv.ParseBool(arg[6]) 95 | 96 | if err != nil { 97 | return "", fmt.Errorf("invalid l boolean, %v", err) 98 | } 99 | 100 | err = fu540.RV64.WritePMP(int(i), addr, r, w, x, int(a), l) 101 | 102 | return 103 | } 104 | -------------------------------------------------------------------------------- /trusted_os_sifive_u/cmd/mem.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package cmd 7 | 8 | import ( 9 | "encoding/binary" 10 | "encoding/hex" 11 | "fmt" 12 | "regexp" 13 | "strconv" 14 | 15 | "golang.org/x/term" 16 | 17 | "github.com/usbarmory/tamago/dma" 18 | ) 19 | 20 | const maxBufferSize = 102400 21 | 22 | func init() { 23 | Add(Cmd{ 24 | Name: "peek", 25 | Args: 2, 26 | Pattern: regexp.MustCompile(`^peek ([[:xdigit:]]+) (\d+)$`), 27 | Syntax: " ", 28 | Help: "memory display (use with caution)", 29 | Fn: memReadCmd, 30 | }) 31 | 32 | Add(Cmd{ 33 | Name: "poke", 34 | Args: 2, 35 | Pattern: regexp.MustCompile(`^poke ([[:xdigit:]]+) ([[:xdigit:]]+)$`), 36 | Syntax: " ", 37 | Help: "memory write (use with caution)", 38 | Fn: memWriteCmd, 39 | }) 40 | } 41 | 42 | func memCopy(start uint, size int, w []byte) (b []byte) { 43 | mem, err := dma.NewRegion(start, size, true) 44 | 45 | if err != nil { 46 | panic("could not allocate memory copy DMA") 47 | } 48 | 49 | start, buf := mem.Reserve(size, 0) 50 | defer mem.Release(start) 51 | 52 | if len(w) > 0 { 53 | copy(buf, w) 54 | } else { 55 | b = make([]byte, size) 56 | copy(b, buf) 57 | } 58 | 59 | return 60 | } 61 | 62 | func memReadCmd(_ *term.Terminal, arg []string) (res string, err error) { 63 | addr, err := strconv.ParseUint(arg[0], 16, 32) 64 | 65 | if err != nil { 66 | return "", fmt.Errorf("invalid address, %v", err) 67 | } 68 | 69 | size, err := strconv.ParseUint(arg[1], 10, 32) 70 | 71 | if err != nil { 72 | return "", fmt.Errorf("invalid size, %v", err) 73 | } 74 | 75 | if (addr%4) != 0 || (size%4) != 0 { 76 | return "", fmt.Errorf("only 32-bit aligned accesses are supported") 77 | } 78 | 79 | if size > maxBufferSize { 80 | return "", fmt.Errorf("size argument must be <= %d", maxBufferSize) 81 | } 82 | 83 | return hex.Dump(memCopy(uint(addr), int(size), nil)), nil 84 | } 85 | 86 | func memWriteCmd(_ *term.Terminal, arg []string) (res string, err error) { 87 | addr, err := strconv.ParseUint(arg[0], 16, 32) 88 | 89 | if err != nil { 90 | return "", fmt.Errorf("invalid address, %v", err) 91 | } 92 | 93 | val, err := strconv.ParseUint(arg[1], 16, 32) 94 | 95 | if err != nil { 96 | return "", fmt.Errorf("invalid data, %v", err) 97 | } 98 | 99 | buf := make([]byte, 4) 100 | binary.BigEndian.PutUint32(buf, uint32(val)) 101 | 102 | memCopy(uint(addr), 4, buf) 103 | 104 | return 105 | } 106 | -------------------------------------------------------------------------------- /util/debug.go: -------------------------------------------------------------------------------- 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 util 16 | 17 | import ( 18 | "bytes" 19 | "debug/elf" 20 | "debug/gosym" 21 | "errors" 22 | "fmt" 23 | ) 24 | 25 | var ( 26 | target []byte 27 | symCache []elf.Symbol 28 | symTableCache *gosym.Table 29 | ) 30 | 31 | func SetDebugTarget(buf []byte) { 32 | target = buf 33 | } 34 | 35 | func LookupSym(name string) (*elf.Symbol, error) { 36 | f, err := elf.NewFile(bytes.NewReader(target)) 37 | 38 | if err != nil { 39 | return nil, err 40 | } 41 | 42 | if symCache == nil { 43 | syms, err := f.Symbols() 44 | 45 | if err != nil { 46 | return nil, err 47 | } 48 | 49 | symCache = syms 50 | } 51 | 52 | for _, sym := range symCache { 53 | if sym.Name == name { 54 | return &sym, nil 55 | } 56 | } 57 | 58 | return nil, errors.New("symbol not found") 59 | } 60 | 61 | func goSymTable() (symTable *gosym.Table, err error) { 62 | var s *elf.Section 63 | 64 | if symTableCache != nil { 65 | return symTableCache, nil 66 | } 67 | 68 | f, err := elf.NewFile(bytes.NewReader(target)) 69 | 70 | if err != nil { 71 | return 72 | } 73 | 74 | if s = f.Section(".text"); s == nil { 75 | return nil, errors.New("missing section") 76 | } 77 | 78 | addr := s.Addr 79 | 80 | if s = f.Section(".gopclntab"); s == nil { 81 | return nil, errors.New("missing section") 82 | } 83 | 84 | lineTableData, err := s.Data() 85 | 86 | if err != nil { 87 | return 88 | } 89 | 90 | lineTable := gosym.NewLineTable(lineTableData, addr) 91 | 92 | if err != nil { 93 | return 94 | } 95 | 96 | if s = f.Section(".gosymtab"); s == nil { 97 | return nil, errors.New("missing section") 98 | } 99 | 100 | symTableData, err := s.Data() 101 | 102 | if err != nil { 103 | return 104 | } 105 | 106 | symTableCache, err = gosym.NewTable(symTableData, lineTable) 107 | 108 | return symTableCache, err 109 | } 110 | 111 | func PCToLine(pc uint64) (s string, err error) { 112 | symTable, err := goSymTable() 113 | 114 | if err != nil { 115 | return 116 | } 117 | 118 | file, line, _ := symTable.PCToLine(pc) 119 | 120 | return fmt.Sprintf("%s:%d", file, line), nil 121 | } 122 | -------------------------------------------------------------------------------- /trusted_os_sifive_u/internal/load.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package gotee 7 | 8 | import ( 9 | "fmt" 10 | "log" 11 | "sync" 12 | 13 | "github.com/usbarmory/GoTEE/monitor" 14 | 15 | "github.com/usbarmory/GoTEE-example/mem" 16 | "github.com/usbarmory/GoTEE-example/util" 17 | 18 | "github.com/usbarmory/armory-boot/exec" 19 | ) 20 | 21 | var ( 22 | TA []byte 23 | OS []byte 24 | ) 25 | 26 | // loadApplet loads a TamaGo unikernel as trusted applet. 27 | func loadApplet() (ta *monitor.ExecCtx, err error) { 28 | image := &exec.ELFImage{ 29 | Region: mem.AppletRegion, 30 | ELF: TA, 31 | } 32 | 33 | if err = image.Load(); err != nil { 34 | return 35 | } 36 | 37 | if ta, err = monitor.Load(image.Entry(), image.Region, true); err != nil { 38 | return nil, fmt.Errorf("SM could not load applet, %v", err) 39 | } 40 | 41 | log.Printf("SM loaded applet addr:%#x entry:%#x size:%d", ta.Memory.Start(), ta.PC, len(TA)) 42 | 43 | // set applet as ELF debugging target 44 | util.SetDebugTarget(image.ELF) 45 | 46 | // set memory protection function 47 | ta.PMP = configurePMP 48 | 49 | // register example RPC receiver 50 | ta.Server.Register(&RPC{}) 51 | 52 | // set stack pointer to the end of available memory 53 | ta.X2 = uint64(ta.Memory.End()) 54 | 55 | // override default handler to improve logging 56 | ta.Handler = goHandler 57 | 58 | return 59 | } 60 | 61 | // loadSupervisor loads a TamaGo unikernel as main OS. 62 | func loadSupervisor() (os *monitor.ExecCtx, err error) { 63 | image := &exec.ELFImage{ 64 | Region: mem.NonSecureRegion, 65 | ELF: OS, 66 | } 67 | 68 | if err = image.Load(); err != nil { 69 | return 70 | } 71 | 72 | if os, err = monitor.Load(image.Entry(), image.Region, false); err != nil { 73 | return nil, fmt.Errorf("SM could not load kernel, %v", err) 74 | } 75 | 76 | log.Printf("SM loaded kernel addr:%#x entry:%#x size:%d", os.Memory.Start(), os.PC, len(OS)) 77 | 78 | // set memory protection function 79 | os.PMP = configurePMP 80 | 81 | // set stack pointer to the end of available memory 82 | os.X2 = uint64(os.Memory.End()) 83 | 84 | // override default handler to support SBI and improve logging 85 | os.Handler = sbiHandler 86 | 87 | return 88 | } 89 | 90 | func run(ctx *monitor.ExecCtx, wg *sync.WaitGroup) { 91 | log.Printf("SM starting sp:%#.8x pc:%#.8x secure:%v", ctx.X2, ctx.PC, ctx.Secure()) 92 | 93 | err := ctx.Run() 94 | 95 | if wg != nil { 96 | wg.Done() 97 | } 98 | 99 | log.Printf("SM stopped sp:%#.8x ra:%#.8x pc:%#.8x err:%v %s", ctx.X2, ctx.X1, ctx.PC, err, ctx) 100 | 101 | if err != nil { 102 | pcLine, _ := util.PCToLine(ctx.PC) 103 | lrLine, _ := util.PCToLine(ctx.X1) 104 | 105 | if pcLine != "" || lrLine != "" { 106 | log.Printf("stack trace:\n %s\n %s", pcLine, lrLine) 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /trusted_os_usbarmory/cmd/mem.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package cmd 7 | 8 | import ( 9 | "encoding/binary" 10 | "encoding/hex" 11 | "fmt" 12 | "regexp" 13 | "strconv" 14 | 15 | "golang.org/x/term" 16 | 17 | "github.com/usbarmory/tamago/arm" 18 | "github.com/usbarmory/tamago/dma" 19 | "github.com/usbarmory/tamago/soc/nxp/imx6ul" 20 | ) 21 | 22 | const maxBufferSize = 102400 23 | 24 | func init() { 25 | Add(Cmd{ 26 | Name: "peek", 27 | Args: 2, 28 | Pattern: regexp.MustCompile(`^peek ([[:xdigit:]]+) (\d+)$`), 29 | Syntax: " ", 30 | Help: "memory display (use with caution)", 31 | Fn: memReadCmd, 32 | }) 33 | 34 | Add(Cmd{ 35 | Name: "poke", 36 | Args: 2, 37 | Pattern: regexp.MustCompile(`^poke ([[:xdigit:]]+) ([[:xdigit:]]+)$`), 38 | Syntax: " ", 39 | Help: "memory write (use with caution)", 40 | Fn: memWriteCmd, 41 | }) 42 | } 43 | 44 | func mem(start uint, size int, w []byte) (b []byte) { 45 | // temporarily map page zero if required 46 | if z := uint32(1 << 20); uint32(start) < z { 47 | imx6ul.ARM.ConfigureMMU(0, z, 0, (arm.TTE_AP_001<<10)|arm.TTE_SECTION) 48 | defer imx6ul.ARM.ConfigureMMU(0, z, 0, 0) 49 | } 50 | 51 | return memCopy(start, size, w) 52 | } 53 | 54 | func memCopy(start uint, size int, w []byte) (b []byte) { 55 | mem, err := dma.NewRegion(start, size, true) 56 | 57 | if err != nil { 58 | panic("could not allocate memory copy DMA") 59 | } 60 | 61 | start, buf := mem.Reserve(size, 0) 62 | defer mem.Release(start) 63 | 64 | if len(w) > 0 { 65 | copy(buf, w) 66 | } else { 67 | b = make([]byte, size) 68 | copy(b, buf) 69 | } 70 | 71 | return 72 | } 73 | 74 | func memReadCmd(_ *term.Terminal, arg []string) (res string, err error) { 75 | addr, err := strconv.ParseUint(arg[0], 16, 32) 76 | 77 | if err != nil { 78 | return "", fmt.Errorf("invalid address, %v", err) 79 | } 80 | 81 | size, err := strconv.ParseUint(arg[1], 10, 32) 82 | 83 | if err != nil { 84 | return "", fmt.Errorf("invalid size, %v", err) 85 | } 86 | 87 | if (addr%4) != 0 || (size%4) != 0 { 88 | return "", fmt.Errorf("only 32-bit aligned accesses are supported") 89 | } 90 | 91 | if size > maxBufferSize { 92 | return "", fmt.Errorf("size argument must be <= %d", maxBufferSize) 93 | } 94 | 95 | return hex.Dump(mem(uint(addr), int(size), nil)), nil 96 | } 97 | 98 | func memWriteCmd(_ *term.Terminal, arg []string) (res string, err error) { 99 | addr, err := strconv.ParseUint(arg[0], 16, 32) 100 | 101 | if err != nil { 102 | return "", fmt.Errorf("invalid address, %v", err) 103 | } 104 | 105 | val, err := strconv.ParseUint(arg[1], 16, 32) 106 | 107 | if err != nil { 108 | return "", fmt.Errorf("invalid data, %v", err) 109 | } 110 | 111 | buf := make([]byte, 4) 112 | binary.BigEndian.PutUint32(buf, uint32(val)) 113 | 114 | mem(uint(addr), 4, buf) 115 | 116 | return 117 | } 118 | -------------------------------------------------------------------------------- /trusted_os_usbarmory/cmd/csu.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package cmd 7 | 8 | import ( 9 | "bytes" 10 | "errors" 11 | "fmt" 12 | "regexp" 13 | "strconv" 14 | 15 | "golang.org/x/term" 16 | 17 | "github.com/usbarmory/tamago/soc/nxp/csu" 18 | "github.com/usbarmory/tamago/soc/nxp/imx6ul" 19 | ) 20 | 21 | func init() { 22 | Add(Cmd{ 23 | Name: "csl", 24 | Help: "show config security levels (CSL)", 25 | Fn: cslCmd, 26 | }) 27 | 28 | Add(Cmd{ 29 | Name: "csl ", 30 | Args: 3, 31 | Pattern: regexp.MustCompile(`csl (\d+) (\d+) ([[:xdigit:]]+)`), 32 | Syntax: " ", 33 | Help: "set config security level (CSL)", 34 | Fn: cslCmd, 35 | }) 36 | 37 | Add(Cmd{ 38 | Name: "sa", 39 | Help: "show security access (SA)", 40 | Fn: saCmd, 41 | }) 42 | 43 | Add(Cmd{ 44 | Name: "sa ", 45 | Args: 2, 46 | Pattern: regexp.MustCompile(`sa (\d+) (secure|nonsecure)`), 47 | Syntax: " ", 48 | Help: "set security access (SA)", 49 | Fn: saCmd, 50 | }) 51 | } 52 | 53 | func cslCmd(term *term.Terminal, arg []string) (res string, err error) { 54 | if len(arg) == 0 { 55 | var buf bytes.Buffer 56 | 57 | for i := csu.CSL_MIN; i <= csu.CSL_MAX; i++ { 58 | csl, _, _ := imx6ul.CSU.GetSecurityLevel(i, 0) 59 | fmt.Fprintf(&buf, "CSL%.2d 0:%#.2x", i, csl) 60 | 61 | csl, _, _ = imx6ul.CSU.GetSecurityLevel(i, 1) 62 | fmt.Fprintf(&buf, " 1:%#.2x\n", csl) 63 | } 64 | 65 | return buf.String(), nil 66 | } 67 | 68 | if !imx6ul.Native { 69 | return "", errors.New("unsupported under emulation") 70 | } 71 | 72 | periph, err := strconv.ParseUint(arg[0], 10, 8) 73 | 74 | if err != nil { 75 | return "", fmt.Errorf("invalid peripheral index: %v", err) 76 | } 77 | 78 | slave, err := strconv.ParseUint(arg[1], 10, 8) 79 | 80 | if err != nil { 81 | return "", fmt.Errorf("invalid slave index: %v", err) 82 | } 83 | 84 | csl, err := strconv.ParseUint(arg[2], 16, 8) 85 | 86 | if err != nil { 87 | return "", fmt.Errorf("invalid csl: %v", err) 88 | } 89 | 90 | if err = imx6ul.CSU.SetSecurityLevel(int(periph), int(slave), uint8(csl), false); err != nil { 91 | return 92 | } 93 | 94 | return 95 | } 96 | 97 | func saCmd(term *term.Terminal, arg []string) (res string, err error) { 98 | if len(arg) == 0 { 99 | var buf bytes.Buffer 100 | 101 | for i := csu.SA_MIN; i <= csu.SA_MAX; i++ { 102 | if sa, _, _ := imx6ul.CSU.GetAccess(i); sa { 103 | fmt.Fprintf(&buf, "SA%.2d: secure\n", i) 104 | } else { 105 | fmt.Fprintf(&buf, "SA%.2d: nonsecure\n", i) 106 | } 107 | } 108 | 109 | return buf.String(), nil 110 | } 111 | 112 | if !imx6ul.Native { 113 | return "", errors.New("unsupported under emulation") 114 | } 115 | 116 | id, err := strconv.ParseUint(arg[0], 10, 8) 117 | 118 | if err != nil { 119 | return "", fmt.Errorf("invalid peripheral index: %v", err) 120 | } 121 | 122 | if arg[1] == "secure" { 123 | err = imx6ul.CSU.SetAccess(int(id), true, false) 124 | } else { 125 | err = imx6ul.CSU.SetAccess(int(id), false, false) 126 | } 127 | 128 | return 129 | } 130 | -------------------------------------------------------------------------------- /trusted_applet_rust/main_riscv64.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | // This is a minimal example for a GoTEE Trusted Applet written in Rust. 7 | // 8 | // For simplicity the example does not use any external crates or memory 9 | // allocator, though in a complex applet both might be desirable/required. 10 | 11 | #![no_std] 12 | #![no_main] 13 | 14 | use core::arch::asm; 15 | use core::fmt::{self, Write}; 16 | use core::panic::PanicInfo; 17 | use core::time::Duration; 18 | 19 | const SYS_EXIT: u64 = 0; 20 | const SYS_WRITE: u64 = 1; 21 | const SYS_NANOTIME: u64 = 2; 22 | const SYS_GETRANDOM: u64 = 3; 23 | 24 | struct Stdout {} 25 | 26 | macro_rules! print { 27 | ($($arg:tt)*) => { 28 | write!(&mut Stdout {}, $($arg)*).ok(); 29 | }; 30 | } 31 | 32 | macro_rules! log { 33 | ($fmt:expr) => { 34 | log_walltime(nanotime()); 35 | print!(concat!($fmt, "\r\n")) 36 | }; 37 | ($fmt:expr, $($arg:tt)*) => { 38 | log_walltime(nanotime()); 39 | print!(concat!($fmt, "\r\n"), $($arg)*) 40 | }; 41 | } 42 | 43 | #[panic_handler] 44 | fn panic(panic_info: &PanicInfo) -> ! { 45 | log!("applet panic, {:?})", panic_info); 46 | exit(); 47 | 48 | // this should be unreachable 49 | loop {} 50 | } 51 | 52 | fn log_walltime(ns: u64) { 53 | let epoch = Duration::from_nanos(ns).as_secs(); 54 | let ss = epoch % 60; 55 | let mm = (epoch / 60) % 60; 56 | let hh = (epoch / 3600) % 24; 57 | 58 | print!("{:02}:{:02}:{:02} ", hh, mm, ss); 59 | } 60 | 61 | fn exit() { 62 | unsafe { 63 | asm!( 64 | "ecall", 65 | in("a0") SYS_EXIT, 66 | ); 67 | } 68 | } 69 | 70 | impl Write for Stdout { 71 | fn write_str(&mut self, s: &str) -> fmt::Result { 72 | for c in s.bytes() { 73 | unsafe { 74 | asm!( 75 | "ecall", 76 | in("a0") SYS_WRITE, 77 | in("a1") c, 78 | in("a7") 0, 79 | ); 80 | } 81 | } 82 | Ok(()) 83 | } 84 | } 85 | 86 | fn nanotime() -> u64 { 87 | let ns: u64; 88 | 89 | unsafe { 90 | asm!( 91 | "ecall", 92 | in("a0") SYS_NANOTIME, 93 | in("a7") 0, 94 | ); 95 | 96 | asm!( 97 | "", 98 | out("a0") ns, 99 | ); 100 | } 101 | 102 | ns 103 | } 104 | 105 | fn getrandom(data: &mut [u8]) { 106 | unsafe { 107 | asm!( 108 | "ecall", 109 | in("a0") SYS_GETRANDOM, 110 | in("a1") data.as_ptr(), 111 | in("a2") data.len(), 112 | in("a7") 0, 113 | ); 114 | } 115 | } 116 | 117 | fn test_rng() { 118 | let mut rng: [u8; 16] = [0; 16]; 119 | 120 | getrandom(&mut rng); 121 | 122 | log!( 123 | "applet obtained {:} random bytes from SM: {:x?}", 124 | rng.len(), 125 | rng 126 | ); 127 | } 128 | 129 | #[no_mangle] 130 | pub extern "C" fn _start() { 131 | log!("rust • TEE user applet"); 132 | 133 | // test syscall interface 134 | test_rng(); 135 | 136 | // terminate applet 137 | exit(); 138 | } 139 | -------------------------------------------------------------------------------- /trusted_applet_rust/main_arm.rs: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | // This is a minimal example for a GoTEE Trusted Applet written in Rust. 7 | // 8 | // For simplicity the example does not use any external crates or memory 9 | // allocator, though in a complex applet both might be desirable/required. 10 | 11 | #![no_std] 12 | #![no_main] 13 | 14 | use core::arch::asm; 15 | use core::fmt::{self, Write}; 16 | use core::panic::PanicInfo; 17 | use core::time::Duration; 18 | 19 | const SYS_EXIT: u32 = 0; 20 | const SYS_WRITE: u32 = 1; 21 | const SYS_NANOTIME: u32 = 2; 22 | const SYS_GETRANDOM: u32 = 3; 23 | 24 | struct Stdout {} 25 | 26 | macro_rules! print { 27 | ($($arg:tt)*) => { 28 | write!(&mut Stdout {}, $($arg)*).ok(); 29 | }; 30 | } 31 | 32 | macro_rules! log { 33 | ($fmt:expr) => { 34 | log_walltime(nanotime()); 35 | print!(concat!($fmt, "\r\n")) 36 | }; 37 | ($fmt:expr, $($arg:tt)*) => { 38 | log_walltime(nanotime()); 39 | print!(concat!($fmt, "\r\n"), $($arg)*) 40 | }; 41 | } 42 | 43 | #[panic_handler] 44 | fn panic(panic_info: &PanicInfo) -> ! { 45 | log!("applet panic, {:?})", panic_info); 46 | exit(); 47 | 48 | // this should be unreachable 49 | loop {} 50 | } 51 | 52 | fn log_walltime(ns: u64) { 53 | let epoch = Duration::from_nanos(ns).as_secs(); 54 | let ss = epoch % 60; 55 | let mm = (epoch / 60) % 60; 56 | let hh = (epoch / 3600) % 24; 57 | 58 | print!("{:02}:{:02}:{:02} ", hh, mm, ss); 59 | } 60 | 61 | fn exit() { 62 | unsafe { 63 | asm!( 64 | "swi 0", 65 | in("r0") SYS_EXIT, 66 | ); 67 | } 68 | } 69 | 70 | impl Write for Stdout { 71 | fn write_str(&mut self, s: &str) -> fmt::Result { 72 | for c in s.bytes() { 73 | unsafe { 74 | asm!( 75 | "swi 0", 76 | in("r0") SYS_WRITE, 77 | in("r1") c, 78 | ); 79 | } 80 | } 81 | Ok(()) 82 | } 83 | } 84 | 85 | fn nanotime() -> u64 { 86 | let ns_low: u32; 87 | let ns_high: u32; 88 | let ns: u64; 89 | 90 | unsafe { 91 | asm!( 92 | "swi 0", 93 | in("r0") SYS_NANOTIME, 94 | ); 95 | 96 | asm!( 97 | "", 98 | out("r0") ns_low, 99 | out("r1") ns_high, 100 | ); 101 | } 102 | 103 | ns = ((ns_high as u64) << 32) | (ns_low as u64); 104 | ns 105 | } 106 | 107 | fn getrandom(data: &mut [u8]) { 108 | unsafe { 109 | asm!( 110 | "swi 0", 111 | in("r0") SYS_GETRANDOM, 112 | in("r1") data.as_ptr(), 113 | in("r2") data.len(), 114 | ); 115 | } 116 | } 117 | 118 | fn test_rng() { 119 | let mut rng: [u8; 16] = [0; 16]; 120 | 121 | getrandom(&mut rng); 122 | 123 | log!( 124 | "applet obtained {:} random bytes from SM: {:x?}", 125 | rng.len(), 126 | rng 127 | ); 128 | } 129 | 130 | #[no_mangle] 131 | pub extern "C" fn _start() { 132 | log!("rust • TEE user applet"); 133 | 134 | // test syscall interface 135 | test_rng(); 136 | 137 | // terminate applet 138 | exit(); 139 | } 140 | -------------------------------------------------------------------------------- /trusted_os_sifive_u/cmd/handler.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package cmd 7 | 8 | import ( 9 | "bytes" 10 | "errors" 11 | "fmt" 12 | "io" 13 | "log" 14 | "regexp" 15 | "sort" 16 | "strings" 17 | "text/tabwriter" 18 | 19 | "golang.org/x/term" 20 | ) 21 | 22 | const ( 23 | separator = "-" 24 | separatorSize = 80 25 | ) 26 | 27 | type CmdFn func(term *term.Terminal, arg []string) (res string, err error) 28 | 29 | type Cmd struct { 30 | Name string 31 | Args int 32 | Pattern *regexp.Regexp 33 | Syntax string 34 | Help string 35 | Fn CmdFn 36 | } 37 | 38 | var Banner string 39 | var cmds = make(map[string]*Cmd) 40 | 41 | func Add(cmd Cmd) { 42 | cmds[cmd.Name] = &cmd 43 | } 44 | 45 | func msg(format string, args ...interface{}) { 46 | s := strings.Repeat(separator, 2) + " " 47 | s += fmt.Sprintf(format, args...) 48 | s += strings.Repeat(separator, separatorSize-len(s)) 49 | 50 | log.Println(s) 51 | } 52 | 53 | func confirm(term *term.Terminal) bool { 54 | term.SetPrompt("Are you sure? (y/n) ") 55 | defer term.SetPrompt(string(term.Escape.Red) + "> " + string(term.Escape.Reset)) 56 | 57 | input, err := term.ReadLine() 58 | 59 | if err != nil { 60 | return false 61 | } 62 | 63 | return input == "y" 64 | } 65 | 66 | func Help(term *term.Terminal) string { 67 | var help bytes.Buffer 68 | var names []string 69 | 70 | t := tabwriter.NewWriter(&help, 16, 8, 0, '\t', tabwriter.TabIndent) 71 | 72 | for name, _ := range cmds { 73 | names = append(names, name) 74 | } 75 | 76 | sort.Strings(names) 77 | 78 | for _, name := range names { 79 | _, _ = fmt.Fprintf(t, "%s\t%s\t # %s\n", cmds[name].Name, cmds[name].Syntax, cmds[name].Help) 80 | } 81 | 82 | _ = t.Flush() 83 | 84 | return string(term.Escape.Cyan) + help.String() + string(term.Escape.Reset) 85 | } 86 | 87 | func handle(term *term.Terminal, line string) (err error) { 88 | var match *Cmd 89 | var arg []string 90 | var res string 91 | 92 | for _, cmd := range cmds { 93 | if cmd.Pattern == nil { 94 | if cmd.Name == line { 95 | match = cmd 96 | break 97 | } 98 | } else if m := cmd.Pattern.FindStringSubmatch(line); len(m) > 0 && (len(m)-1 == cmd.Args) { 99 | match = cmd 100 | arg = m[1:] 101 | break 102 | } 103 | } 104 | 105 | if match == nil { 106 | return errors.New("unknown command, type `help`") 107 | } 108 | 109 | if res, err = match.Fn(term, arg); err != nil { 110 | return 111 | } 112 | 113 | fmt.Fprintln(term, res) 114 | 115 | return 116 | } 117 | 118 | func Handler(term *term.Terminal) { 119 | fmt.Fprintf(term, "%s\n\n", Banner) 120 | fmt.Fprintf(term, "%s\n", Help(term)) 121 | 122 | for { 123 | s, err := term.ReadLine() 124 | 125 | if err == io.EOF { 126 | break 127 | } 128 | 129 | if err != nil { 130 | log.Printf("readline error: %v", err) 131 | continue 132 | } 133 | 134 | if err = handle(term, s); err != nil { 135 | if err == io.EOF { 136 | break 137 | } 138 | 139 | log.Printf("command error: %v", err) 140 | } 141 | } 142 | } 143 | 144 | func SerialConsole(rw io.ReadWriter) { 145 | term := term.NewTerminal(rw, "") 146 | term.SetPrompt(string(term.Escape.Red) + "> " + string(term.Escape.Reset)) 147 | 148 | Handler(term) 149 | } 150 | -------------------------------------------------------------------------------- /trusted_os_usbarmory/cmd/handler.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package cmd 7 | 8 | import ( 9 | "bytes" 10 | "errors" 11 | "fmt" 12 | "io" 13 | "log" 14 | "regexp" 15 | "sort" 16 | "strings" 17 | "text/tabwriter" 18 | 19 | "golang.org/x/term" 20 | ) 21 | 22 | const ( 23 | separator = "-" 24 | separatorSize = 80 25 | ) 26 | 27 | type CmdFn func(term *term.Terminal, arg []string) (res string, err error) 28 | 29 | type Cmd struct { 30 | Name string 31 | Args int 32 | Pattern *regexp.Regexp 33 | Syntax string 34 | Help string 35 | Fn CmdFn 36 | } 37 | 38 | var Banner string 39 | var cmds = make(map[string]*Cmd) 40 | 41 | func Add(cmd Cmd) { 42 | cmds[cmd.Name] = &cmd 43 | } 44 | 45 | func msg(format string, args ...interface{}) { 46 | s := strings.Repeat(separator, 2) + " " 47 | s += fmt.Sprintf(format, args...) 48 | s += strings.Repeat(separator, separatorSize-len(s)) 49 | 50 | log.Println(s) 51 | } 52 | 53 | func confirm(term *term.Terminal) bool { 54 | term.SetPrompt("Are you sure? (y/n) ") 55 | defer term.SetPrompt(string(term.Escape.Red) + "> " + string(term.Escape.Reset)) 56 | 57 | input, err := term.ReadLine() 58 | 59 | if err != nil { 60 | return false 61 | } 62 | 63 | return input == "y" 64 | } 65 | 66 | func Help(term *term.Terminal) string { 67 | var help bytes.Buffer 68 | var names []string 69 | 70 | t := tabwriter.NewWriter(&help, 16, 8, 0, '\t', tabwriter.TabIndent) 71 | 72 | for name, _ := range cmds { 73 | names = append(names, name) 74 | } 75 | 76 | sort.Strings(names) 77 | 78 | for _, name := range names { 79 | _, _ = fmt.Fprintf(t, "%s\t%s\t # %s\n", cmds[name].Name, cmds[name].Syntax, cmds[name].Help) 80 | } 81 | 82 | _ = t.Flush() 83 | 84 | return string(term.Escape.Cyan) + help.String() + string(term.Escape.Reset) 85 | } 86 | 87 | func handle(term *term.Terminal, line string) (err error) { 88 | var match *Cmd 89 | var arg []string 90 | var res string 91 | 92 | for _, cmd := range cmds { 93 | if cmd.Pattern == nil { 94 | if cmd.Name == line { 95 | match = cmd 96 | break 97 | } 98 | } else if m := cmd.Pattern.FindStringSubmatch(line); len(m) > 0 && (len(m)-1 == cmd.Args) { 99 | match = cmd 100 | arg = m[1:] 101 | break 102 | } 103 | } 104 | 105 | if match == nil { 106 | return errors.New("unknown command, type `help`") 107 | } 108 | 109 | if res, err = match.Fn(term, arg); err != nil { 110 | return 111 | } 112 | 113 | fmt.Fprintln(term, res) 114 | 115 | return 116 | } 117 | 118 | func Handler(term *term.Terminal) { 119 | fmt.Fprintf(term, "%s\n\n", Banner) 120 | fmt.Fprintf(term, "%s\n", Help(term)) 121 | 122 | for { 123 | s, err := term.ReadLine() 124 | 125 | if err == io.EOF { 126 | break 127 | } 128 | 129 | if err != nil { 130 | log.Printf("readline error: %v", err) 131 | continue 132 | } 133 | 134 | if err = handle(term, s); err != nil { 135 | if err == io.EOF { 136 | break 137 | } 138 | 139 | log.Printf("command error: %v", err) 140 | } 141 | } 142 | } 143 | 144 | func SerialConsole(rw io.ReadWriter) { 145 | term := term.NewTerminal(rw, "") 146 | term.SetPrompt(string(term.Escape.Red) + "> " + string(term.Escape.Reset)) 147 | 148 | Handler(term) 149 | } 150 | -------------------------------------------------------------------------------- /trusted_os_usbarmory/internal/exec.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package gotee 7 | 8 | import ( 9 | "crypto/aes" 10 | "crypto/sha256" 11 | "errors" 12 | "log" 13 | "math/rand" 14 | "sync" 15 | 16 | usbarmory "github.com/usbarmory/tamago/board/usbarmory/mk2" 17 | "github.com/usbarmory/tamago/soc/nxp/imx6ul" 18 | 19 | "github.com/usbarmory/GoTEE/monitor" 20 | ) 21 | 22 | // TrustZone Watchdog interval (in ms) to force Non-Secure to Secure World 23 | // switching. 24 | const ( 25 | watchdogTimeout = 10000 26 | watchdogWarningInterval = 2000 27 | ) 28 | 29 | var nsBoot bool 30 | 31 | func GoTEE() (err error) { 32 | var wg sync.WaitGroup 33 | var ta *monitor.ExecCtx 34 | var os *monitor.ExecCtx 35 | 36 | if ta, err = loadApplet(false); err != nil { 37 | return 38 | } 39 | 40 | if os, err = loadNormalWorld(false); err != nil { 41 | return 42 | } 43 | 44 | nsBoot = true 45 | 46 | // test concurrent execution of: 47 | // Secure World PL1 (system/monitor mode) - secure OS (this program) 48 | // Secure World PL0 (user mode) - trusted applet 49 | // NonSecure World PL1 - main OS 50 | wg.Add(2) 51 | go run(ta, &wg) 52 | go run(os, &wg) 53 | 54 | log.Printf("SM waiting for applet and kernel") 55 | wg.Wait() 56 | 57 | usbarmory.LED("blue", false) 58 | 59 | if !imx6ul.Native { 60 | return 61 | } 62 | 63 | // re-launch Normal World with peripheral restrictions 64 | if os, err = loadNormalWorld(true); err != nil { 65 | return 66 | } 67 | 68 | log.Printf("SM re-launching kernel with TrustZone restrictions") 69 | run(os, nil) 70 | 71 | // test restricted peripheral in Secure World 72 | log.Printf("SM in Secure World is about to perform key derivation") 73 | 74 | var k []byte 75 | 76 | switch { 77 | case imx6ul.CAAM != nil: 78 | // set CAAM as Secure 79 | imx6ul.CAAM.SetOwner(true) 80 | 81 | k = make([]byte, sha256.Size) 82 | err = imx6ul.CAAM.DeriveKey(make([]byte, sha256.Size), k) 83 | case imx6ul.DCP != nil: 84 | k, err = imx6ul.DCP.DeriveKey(make([]byte, aes.BlockSize), make([]byte, aes.BlockSize), -1) 85 | } 86 | 87 | if err != nil { 88 | log.Printf("SM in Secure World failed to derive key (%v)", err) 89 | } else { 90 | log.Printf("SM in Secure World successfully derived key (%x)", k) 91 | } 92 | 93 | return 94 | } 95 | 96 | func Linux(device string) (err error) { 97 | var os *monitor.ExecCtx 98 | 99 | if nsBoot { 100 | return errors.New("previous Non-secure kernel run detected, reboot first to launch Linux") 101 | } 102 | 103 | if os, err = loadLinux(device); err != nil { 104 | return 105 | } 106 | 107 | log.Printf("SM enabling TrustZone Watchdog") 108 | enableTrustZoneWatchdog() 109 | 110 | log.Printf("SM launching Linux") 111 | run(os, nil) 112 | 113 | return 114 | } 115 | 116 | func fault(ctx *monitor.ExecCtx, faultPercentage float64) { 117 | if n := rand.Float64() * 100; n >= faultPercentage { 118 | return 119 | } 120 | 121 | log.Printf("!! injecting register fault !!") 122 | ctx.R0 += 1 123 | } 124 | 125 | func Lockstep(faultPercentage float64) (err error) { 126 | var once sync.Once 127 | var ta *monitor.ExecCtx 128 | 129 | if ta, err = loadApplet(true); err != nil { 130 | return 131 | } 132 | 133 | defer run(ta, nil) 134 | 135 | if faultPercentage <= 0 { 136 | return 137 | } 138 | 139 | primaryHandler := ta.Handler 140 | 141 | ta.Handler = func(ctx *monitor.ExecCtx) error { 142 | once.Do(func() { 143 | ta.Shadow.Handler = func(ctx *monitor.ExecCtx) error { 144 | fault(ctx, faultPercentage) 145 | return nil 146 | } 147 | }) 148 | 149 | return primaryHandler(ctx) 150 | } 151 | 152 | return 153 | } 154 | -------------------------------------------------------------------------------- /trusted_os_usbarmory/main.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package main 7 | 8 | import ( 9 | _ "embed" 10 | "fmt" 11 | "log" 12 | "os" 13 | "runtime" 14 | "time" 15 | _ "unsafe" 16 | 17 | usbarmory "github.com/usbarmory/tamago/board/usbarmory/mk2" 18 | "github.com/usbarmory/tamago/dma" 19 | "github.com/usbarmory/tamago/soc/nxp/imx6ul" 20 | 21 | "github.com/usbarmory/imx-usbnet" 22 | 23 | "github.com/usbarmory/GoTEE-example/internal/semihosting" 24 | "github.com/usbarmory/GoTEE-example/mem" 25 | "github.com/usbarmory/GoTEE-example/util" 26 | 27 | "github.com/usbarmory/GoTEE-example/trusted_os_usbarmory/cmd" 28 | "github.com/usbarmory/GoTEE-example/trusted_os_usbarmory/internal" 29 | ) 30 | 31 | const ( 32 | sshPort = 22 33 | IP = "10.0.0.1" 34 | MAC = "1a:55:89:a2:69:41" 35 | hostMAC = "1a:55:89:a2:69:42" 36 | ) 37 | 38 | // This example embeds the Trusted Applet and Main OS ELF binaries within the 39 | // Trusted OS executable, using Go embed package. 40 | // 41 | // The loading strategy is up to implementers, on the NXP i.MX6 the armory-boot 42 | // bootloader primitives can be used to create a bootable Trusted OS with 43 | // authenticated disk loading of applets and kernels, see loadLinux() and: 44 | // https://pkg.go.dev/github.com/usbarmory/armory-boot 45 | 46 | //go:embed assets/trusted_applet.elf 47 | var taELF []byte 48 | 49 | //go:embed assets/nonsecure_os_go.elf 50 | var osELF []byte 51 | 52 | //go:linkname ramStart runtime.ramStart 53 | var ramStart uint32 = mem.SecureStart 54 | 55 | //go:linkname ramSize runtime.ramSize 56 | var ramSize uint32 = mem.SecureSize 57 | 58 | func init() { 59 | log.SetFlags(log.Ltime) 60 | log.SetOutput(os.Stdout) 61 | 62 | mem.Init() 63 | 64 | // Move DMA region to prevent NonSecure access, alternatively 65 | // iRAM/OCRAM (default DMA region) can be locked down on its own (as it 66 | // is outside TZASC control). 67 | dma.Init(mem.SecureDMAStart, mem.SecureDMASize) 68 | 69 | if imx6ul.Native { 70 | switch imx6ul.Family { 71 | case imx6ul.IMX6UL: 72 | imx6ul.SetARMFreq(imx6ul.Freq528) 73 | imx6ul.CAAM.DeriveKeyMemory = dma.Default() 74 | 75 | imx6ul.BEE.Init() 76 | defer imx6ul.BEE.Lock() 77 | 78 | if err := imx6ul.BEE.Enable(mem.AppletPhysicalStart, 0); err != nil { 79 | log.Fatalf("SM could not activate BEE, %v", err) 80 | } 81 | case imx6ul.IMX6ULL: 82 | imx6ul.SetARMFreq(imx6ul.FreqMax) 83 | imx6ul.DCP.Init() 84 | imx6ul.DCP.DeriveKeyMemory = dma.Default() 85 | } 86 | 87 | debugConsole, _ := usbarmory.DetectDebugAccessory(250 * time.Millisecond) 88 | <-debugConsole 89 | } 90 | 91 | cmd.Banner = fmt.Sprintf("%s/%s (%s) • TEE security monitor (Secure World system/monitor)", runtime.GOOS, runtime.GOARCH, runtime.Version()) 92 | 93 | gotee.TA = taELF 94 | gotee.OS = osELF 95 | } 96 | 97 | func serialConsole() { 98 | gotee.Console = util.NewScreenConsole() 99 | cmd.SerialConsole(usbarmory.UART2) 100 | 101 | log.Printf("SM says goodbye") 102 | semihosting.Exit() 103 | } 104 | 105 | func main() { 106 | if !imx6ul.Native { 107 | serialConsole() 108 | } 109 | 110 | iface := usbnet.Interface{} 111 | 112 | if err := iface.Init(IP, MAC, hostMAC); err != nil { 113 | log.Fatalf("SM could not initialize USB networking, %v", err) 114 | } 115 | 116 | iface.EnableICMP() 117 | 118 | listener, err := iface.ListenerTCP4(sshPort) 119 | 120 | if err != nil { 121 | log.Fatalf("SM could not initialize SSH listener, %v", err) 122 | } 123 | 124 | gotee.Console = &util.Console{ 125 | Handler: cmd.Handler, 126 | Listener: listener, 127 | } 128 | 129 | if err = gotee.Console.Start(); err != nil { 130 | log.Fatalf("SM could not initialize SSH server, %v", err) 131 | } 132 | 133 | usbarmory.USB1.Init() 134 | usbarmory.USB1.DeviceMode() 135 | usbarmory.USB1.Reset() 136 | 137 | // never returns 138 | usbarmory.USB1.Start(iface.NIC.Device) 139 | } 140 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/dsoprea/go-ext4 v0.0.0-20190528173430-c13b09fc0ff8 h1:e3CYZInWqO0a3MWfD0WW/11Ki0qo3Fc1ZAHx0+whlhY= 2 | github.com/dsoprea/go-ext4 v0.0.0-20190528173430-c13b09fc0ff8/go.mod h1:UBig4B62vBWtudYo4RJPwdV5Lqo+oeh7AtSCmRIkRPc= 3 | github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd h1:l+vLbuxptsC6VQyQsfD7NnEC8BZuFpz45PgY+pH8YTg= 4 | github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd/go.mod h1:7I+3Pe2o/YSU88W0hWlm9S22W7XI1JFNJ86U0zPKMf8= 5 | github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= 6 | github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= 7 | github.com/go-errors/errors v1.0.2 h1:xMxH9j2fNg/L4hLn/4y3M0IUsn0M6Wbu/Uh9QlOfBh4= 8 | github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs= 9 | github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= 10 | github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= 11 | github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= 12 | github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= 13 | github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE= 14 | github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= 15 | github.com/u-root/u-root v0.14.0 h1:Ka4T10EEML7dQ5XDvO9c3MBN8z4nuSnGjcd1jmU2ivg= 16 | github.com/u-root/u-root v0.14.0/go.mod h1:hAyZorapJe4qzbLWlAkmSVCJGbfoU9Pu4jpJ1WMluqE= 17 | github.com/u-root/uio v0.0.0-20240209044354-b3d14b93376a h1:BH1SOPEvehD2kVrndDnGJiUF0TrBpNs+iyYocu6h0og= 18 | github.com/u-root/uio v0.0.0-20240209044354-b3d14b93376a/go.mod h1:P3a5rG4X7tI17Nn3aOIAYr5HbIMukwXG0urG0WuL8OA= 19 | github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= 20 | github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= 21 | github.com/usbarmory/GoTEE v0.0.0-20250811152814-d8456103e1fc h1:KcyXkuuX+gTpxqovZDwrOOe3ks4f+7eJXDq7dO9ucfc= 22 | github.com/usbarmory/GoTEE v0.0.0-20250811152814-d8456103e1fc/go.mod h1:Bti6xLAoyVCTXZDnbbOOHpWTVRpBxjZcIIJPoGiX0nw= 23 | github.com/usbarmory/armory-boot v0.0.0-20250313080757-07776e494cb3 h1:J74Up0b0QjHwPtXVOU/428zY5C72dQzV07QBod1iTU0= 24 | github.com/usbarmory/armory-boot v0.0.0-20250313080757-07776e494cb3/go.mod h1:sImXzIRRKl04CGGrOGFWH2a89G6/Bjxf62L08mg4bdU= 25 | github.com/usbarmory/imx-usbnet v0.0.0-20250123113617-d39929cd7171 h1:0xXzXU689aEIa/UQ1wByXPbk+PogCKMMFoW8rFodQlI= 26 | github.com/usbarmory/imx-usbnet v0.0.0-20250123113617-d39929cd7171/go.mod h1:zvzUu4SfzoCEDVnxzga81SoK3ezsW8gjxck2v1Ry1zw= 27 | github.com/usbarmory/tamago v0.0.0-20250811152003-24ca488864f4 h1:u3rQkiGOHWADiMSXILL/sZMOAjN/1esBVN7mzRY74TQ= 28 | github.com/usbarmory/tamago v0.0.0-20250811152003-24ca488864f4/go.mod h1:Fc6aZZ2A3CmERlc2rJR+IofEQHIo/pQZ8taC4qm7pUU= 29 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 30 | golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= 31 | golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= 32 | golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ= 33 | golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc= 34 | golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 35 | golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= 36 | golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= 37 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 38 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 39 | golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= 40 | golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 41 | golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= 42 | golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= 43 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 44 | golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= 45 | golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= 46 | gvisor.dev/gvisor v0.0.0-20240909175600-91fb8ad18db5 h1:hpXKYYLBqtz3Le2H17xbQsWhb254+QOGuuVS2orihjo= 47 | gvisor.dev/gvisor v0.0.0-20240909175600-91fb8ad18db5/go.mod h1:sxc3Uvk/vHcd3tj7/DHVBoR5wvWT/MmRq2pj7HRJnwU= 48 | -------------------------------------------------------------------------------- /util/ssh.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package util 7 | 8 | import ( 9 | "crypto/ecdsa" 10 | "crypto/elliptic" 11 | "crypto/rand" 12 | "encoding/binary" 13 | "fmt" 14 | "io" 15 | "log" 16 | "net" 17 | "os" 18 | 19 | "golang.org/x/crypto/ssh" 20 | "golang.org/x/term" 21 | ) 22 | 23 | // Console represents an SSH console instance. 24 | type Console struct { 25 | // Handler is the terminal command handler 26 | Handler func(*term.Terminal) 27 | // Term is the terminal instance 28 | Term *term.Terminal 29 | // Listener is the network listener 30 | Listener net.Listener 31 | } 32 | 33 | func (c *Console) handleChannel(newChannel ssh.NewChannel) { 34 | if t := newChannel.ChannelType(); t != "session" { 35 | _ = newChannel.Reject(ssh.UnknownChannelType, fmt.Sprintf("unknown channel type: %s", t)) 36 | return 37 | } 38 | 39 | conn, requests, err := newChannel.Accept() 40 | 41 | if err != nil { 42 | log.Printf("error accepting channel, %v", err) 43 | return 44 | } 45 | 46 | c.Term = term.NewTerminal(conn, "") 47 | c.Term.SetPrompt(string(c.Term.Escape.Red) + "> " + string(c.Term.Escape.Reset)) 48 | 49 | go func() { 50 | defer conn.Close() 51 | 52 | logWriter := log.Writer() 53 | 54 | log.SetOutput(io.MultiWriter(logWriter, c.Term)) 55 | defer log.SetOutput(logWriter) 56 | 57 | c.Handler(c.Term) 58 | 59 | log.Printf("closing ssh connection") 60 | }() 61 | 62 | go func() { 63 | for req := range requests { 64 | reqSize := len(req.Payload) 65 | 66 | switch req.Type { 67 | case "shell": 68 | // do not accept payload commands 69 | if len(req.Payload) == 0 { 70 | _ = req.Reply(true, nil) 71 | } 72 | case "pty-req": 73 | // p10, 6.2. Requesting a Pseudo-Terminal, RFC4254 74 | if reqSize < 4 { 75 | log.Printf("malformed pty-req request") 76 | continue 77 | } 78 | 79 | termVariableSize := int(req.Payload[3]) 80 | 81 | if reqSize < 4+termVariableSize+8 { 82 | log.Printf("malformed pty-req request") 83 | continue 84 | } 85 | 86 | w := binary.BigEndian.Uint32(req.Payload[4+termVariableSize:]) 87 | h := binary.BigEndian.Uint32(req.Payload[4+termVariableSize+4:]) 88 | 89 | _ = c.Term.SetSize(int(w), int(h)) 90 | _ = req.Reply(true, nil) 91 | case "window-change": 92 | // p10, 6.7. Window Dimension Change Message, RFC4254 93 | if reqSize < 8 { 94 | log.Printf("malformed window-change request") 95 | continue 96 | } 97 | 98 | w := binary.BigEndian.Uint32(req.Payload) 99 | h := binary.BigEndian.Uint32(req.Payload[4:]) 100 | 101 | _ = c.Term.SetSize(int(w), int(h)) 102 | } 103 | } 104 | }() 105 | } 106 | 107 | func (c *Console) handleChannels(chans <-chan ssh.NewChannel) { 108 | for newChannel := range chans { 109 | go c.handleChannel(newChannel) 110 | } 111 | } 112 | 113 | func (c *Console) listen(srv *ssh.ServerConfig) { 114 | for { 115 | conn, err := c.Listener.Accept() 116 | 117 | if err != nil { 118 | log.Printf("error accepting connection, %v", err) 119 | continue 120 | } 121 | 122 | sshConn, chans, reqs, err := ssh.NewServerConn(conn, srv) 123 | 124 | if err != nil { 125 | log.Printf("error accepting handshake, %v", err) 126 | continue 127 | } 128 | 129 | log.Printf("new ssh connection from %s (%s)", sshConn.RemoteAddr(), sshConn.ClientVersion()) 130 | 131 | go ssh.DiscardRequests(reqs) 132 | go c.handleChannels(chans) 133 | } 134 | } 135 | 136 | // Start instantiates an SSH console on the given listener. 137 | func (c *Console) Start() (err error) { 138 | srv := &ssh.ServerConfig{ 139 | NoClientAuth: true, 140 | } 141 | 142 | key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 143 | 144 | if err != nil { 145 | return fmt.Errorf("private key generation error: ", err) 146 | } 147 | 148 | signer, err := ssh.NewSignerFromKey(key) 149 | 150 | if err != nil { 151 | return fmt.Errorf("key conversion error: ", err) 152 | } 153 | 154 | log.Printf("starting ssh server (%s)", ssh.FingerprintSHA256(signer.PublicKey())) 155 | 156 | srv.AddHostKey(signer) 157 | 158 | go c.listen(srv) 159 | 160 | return 161 | } 162 | 163 | // New() instantiates a console on stdin/stdout. 164 | func NewScreenConsole() *Console { 165 | screen := struct { 166 | io.Reader 167 | io.Writer 168 | }{os.Stdin, os.Stdout} 169 | 170 | return &Console{ 171 | Term: term.NewTerminal(screen, ""), 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /trusted_os_usbarmory/cmd/debug.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package cmd 7 | 8 | import ( 9 | "debug/elf" 10 | "encoding/binary" 11 | "fmt" 12 | "unsafe" 13 | 14 | "golang.org/x/term" 15 | 16 | layout "github.com/usbarmory/GoTEE-example/mem" 17 | "github.com/usbarmory/GoTEE-example/util" 18 | ) 19 | 20 | func init() { 21 | Add(Cmd{ 22 | Name: "allgptr", 23 | Help: "memory forensics of applet goroutines", 24 | Fn: allgptrCmd, 25 | }) 26 | } 27 | 28 | type m struct { 29 | g0 *g 30 | morebuf gobuf 31 | } 32 | 33 | type gobuf struct { 34 | sp uint32 35 | pc uint32 36 | g *g 37 | ctxt uint32 38 | ret uint32 39 | lr uint32 40 | bp uint32 41 | } 42 | 43 | type stack struct { 44 | lo uintptr 45 | hi uintptr 46 | } 47 | 48 | type g struct { 49 | stack stack 50 | stackguard0 uintptr 51 | stackguard1 uintptr 52 | _panic uintptr 53 | _defer uintptr 54 | m *m 55 | sched gobuf 56 | syscallsp uintptr 57 | syscallpc uintptr 58 | stktopsp uintptr 59 | param uint 60 | atomicstatus uint 61 | stackLock uint32 62 | goid uint64 63 | schedlink uintptr 64 | waitsince int64 65 | waitreason uint8 66 | preempt bool 67 | preemptStop bool 68 | preemptShrink bool 69 | asyncSafePoint bool 70 | paniconfault bool 71 | gcscandone bool 72 | throwsplit bool 73 | activeStackChans bool 74 | 75 | noCopy struct{} 76 | value uint8 77 | 78 | raceignore int8 79 | sysblocktraced bool 80 | tracking bool 81 | trackingSeq uint8 82 | trackingStamp int64 83 | runnableTime int64 84 | sysexitticks int64 85 | traceseq uint64 86 | tracelastp uintptr 87 | lockedm uintptr 88 | sig uint32 89 | writebuf []byte 90 | sigcode0 uintptr 91 | sigcode1 uintptr 92 | sigpc uintptr 93 | gopc uintptr 94 | ancestors uintptr 95 | startpc uintptr 96 | } 97 | 98 | func withinAppletMemory(ptr uint32) bool { 99 | return (ptr >= layout.AppletVirtualStart && ptr <= (layout.AppletVirtualStart+layout.AppletSize)) 100 | } 101 | 102 | // allgptrCmd forensically profiles goroutines from Go runtime memory, this 103 | // allows the inspection of state from a separate Go runtime (i.e. isolated 104 | // from the one running this command) even after a warm reboot. 105 | // 106 | // The technique involves following the runtime.allgptr symbol to parse profile 107 | // information from memory. 108 | func allgptrCmd(term *term.Terminal, _ []string) (res string, err error) { 109 | var sym *elf.Symbol 110 | 111 | if sym, err = util.LookupSym("runtime.allgptr"); err != nil { 112 | return "", fmt.Errorf("could not find runtime.allgptr symbol, %v", err) 113 | } 114 | 115 | allgptr := (*uint32)(unsafe.Pointer(uintptr(sym.Value))) 116 | 117 | if !withinAppletMemory(*allgptr) { 118 | return "", fmt.Errorf("invalid allgptr (%x)", *allgptr) 119 | } 120 | 121 | if sym, err = util.LookupSym("runtime.allglen"); err != nil { 122 | return "", fmt.Errorf("could not find runtime.allglen symbol, %v", err) 123 | } 124 | 125 | allglen := (*uint32)(unsafe.Pointer(uintptr(sym.Value))) 126 | 127 | if sym, err = util.LookupSym("runtime.text"); err != nil { 128 | return "", fmt.Errorf("could not find runtime.text symbol, %v", err) 129 | } 130 | 131 | text := sym.Value 132 | 133 | if sym, err = util.LookupSym("runtime.etext"); err != nil { 134 | return "", fmt.Errorf("could not find runtime.etext symbol, %v", err) 135 | } 136 | 137 | etext := sym.Value 138 | 139 | for i := uint32(0); i < *allglen; i++ { 140 | gptr := (*uint32)(unsafe.Pointer(uintptr(*allgptr + i*4))) 141 | 142 | if !withinAppletMemory(*gptr) { 143 | fmt.Fprintf(term, "invalid gptr (%x)", *gptr) 144 | continue 145 | } 146 | 147 | g := (*g)(unsafe.Pointer(uintptr(*gptr))) 148 | 149 | fmt.Fprintf(term, "\ng[%d]: stack.lo:%x stack.hi:%x m:%x sched.sp:%x sched.pc:%x\n", i, g.stack.lo, g.stack.hi, g.m, g.sched.sp, g.sched.pc) 150 | 151 | if l, err := util.PCToLine(uint64(g.gopc)); err == nil { 152 | fmt.Fprintf(term, "\tgopc (%x): %s", g.gopc, l) 153 | } 154 | 155 | if g.m == nil { 156 | fmt.Fprintf(term, "\n") 157 | } else { 158 | fmt.Fprintf(term, " - goroutine was active, sweeping stack pointers\n") 159 | 160 | stack := mem(uint(g.stack.lo), int(g.stack.hi-g.stack.lo), nil) 161 | 162 | for i := 0; i < len(stack); i += 4 { 163 | try := uint64(binary.LittleEndian.Uint32(stack[i : i+4])) 164 | 165 | if try >= text && try <= etext { 166 | if l, err := util.PCToLine(try); err == nil { 167 | fmt.Fprintf(term, "\t%x\t%s\n", try, l) 168 | } 169 | } 170 | } 171 | } 172 | } 173 | 174 | return "", nil 175 | } 176 | -------------------------------------------------------------------------------- /trusted_os_usbarmory/internal/tz.go: -------------------------------------------------------------------------------- 1 | // Copyright (c) The GoTEE authors. All Rights Reserved. 2 | // 3 | // Use of this source code is governed by the license 4 | // that can be found in the LICENSE file. 5 | 6 | package gotee 7 | 8 | import ( 9 | "github.com/usbarmory/tamago/arm/tzc380" 10 | "github.com/usbarmory/tamago/soc/nxp/csu" 11 | "github.com/usbarmory/tamago/soc/nxp/imx6ul" 12 | 13 | "github.com/usbarmory/GoTEE-example/mem" 14 | ) 15 | 16 | func configureTrustZone(lock bool, wdog bool) (err error) { 17 | // grant NonSecure access to CP10 and CP11 18 | imx6ul.ARM.NonSecureAccessControl(1<<11 | 1<<10) 19 | 20 | if !imx6ul.Native { 21 | return 22 | } 23 | 24 | // grant NonSecure access to all peripherals 25 | for i := csu.CSL_MIN; i <= csu.CSL_MAX; i++ { 26 | if err = imx6ul.CSU.SetSecurityLevel(i, 0, csu.SEC_LEVEL_0, false); err != nil { 27 | return 28 | } 29 | 30 | if err = imx6ul.CSU.SetSecurityLevel(i, 1, csu.SEC_LEVEL_0, false); err != nil { 31 | return 32 | } 33 | } 34 | 35 | if imx6ul.CAAM != nil { 36 | // set CAAM as NonSecure 37 | imx6ul.CAAM.SetOwner(false) 38 | } 39 | 40 | // set default TZASC region (entire memory space) to NonSecure access 41 | if err = imx6ul.TZASC.EnableRegion(0, 0, 0, (1< /dev/null) 14 | 15 | SHELL = /bin/bash 16 | 17 | APP := "" 18 | TARGET ?= "usbarmory" 19 | TEXT_START := 0x80010000 # ramStart (defined in mem.go under relevant tamago/soc package) + 0x10000 20 | 21 | ifeq ($(TARGET),sifive_u) 22 | 23 | ifeq ($(MAKECMDGOALS),trusted_applet_go) 24 | ENTRY_POINT := _rt0_tamago_start 25 | else ifeq ($(MAKECMDGOALS),nonsecure_os_go) 26 | ENTRY_POINT := _rt0_tamago_start 27 | else 28 | ENTRY_POINT := _rt0_riscv64_tamago 29 | endif 30 | 31 | GOENV := GO_EXTLINK_ENABLED=0 CGO_ENABLED=0 GOOS=tamago GOARCH=riscv64 32 | QEMU ?= qemu-system-riscv64 -machine sifive_u -m 512M \ 33 | -nographic -monitor none -serial stdio -net none \ 34 | -semihosting \ 35 | -dtb $(CURDIR)/qemu.dtb \ 36 | -bios $(CURDIR)/trusted_os_$(TARGET)/bios/bios.bin 37 | 38 | ARCH = "riscv64" 39 | APPLET_START = 0x95010000 40 | RUST_LINKER = "riscv64-linux-gnu-ld" 41 | RUST_TARGET = "riscv64gc-unknown-none-elf" 42 | 43 | else 44 | 45 | GOENV := GO_EXTLINK_ENABLED=0 CGO_ENABLED=0 GOOS=tamago GOARM=7 GOARCH=arm 46 | ENTRY_POINT := _rt0_arm_tamago 47 | QEMU ?= qemu-system-arm -machine mcimx6ul-evk -cpu cortex-a7 -m 512M \ 48 | -nographic -monitor none -serial null -serial stdio -net none \ 49 | -semihosting 50 | 51 | BUILD_TAGS := ${BUILD_TAGS},syscall_nanotime # required for lockstep example 52 | ARCH = "arm" 53 | APPLET_START = 0x10010000 54 | RUST_LINKER = "arm-none-eabi-ld" 55 | RUST_TARGET = "armv7a-none-eabi" 56 | 57 | endif 58 | 59 | GOFLAGS = -tags ${TARGET},${BUILD_TAGS} -trimpath -ldflags "-T ${TEXT_START} -E ${ENTRY_POINT} -R 0x1000 -X 'main.Build=${BUILD}' -X 'main.Revision=${REV}'" 60 | RUSTFLAGS = -C linker=${RUST_LINKER} -C link-args="--Ttext=$(TEXT_START)" --target ${RUST_TARGET} 61 | 62 | .PHONY: clean qemu qemu-gdb trusted_applet_rust 63 | 64 | #### primary targets #### 65 | 66 | elf: $(APP).elf 67 | 68 | trusted_os: APP=trusted_os_$(TARGET) 69 | trusted_os: DIR=$(CURDIR)/trusted_os_$(TARGET) 70 | trusted_os: TEXT_START=0x90010000 71 | ifeq ($(TARGET),usbarmory) 72 | trusted_os: imx 73 | else 74 | trusted_os: elf 75 | endif 76 | 77 | trusted_os_signed: APP=trusted_os_$(TARGET) 78 | trusted_os_signed: DIR=$(CURDIR)/trusted_os_$(TARGET) 79 | trusted_os_signed: TEXT_START=0x90010000 80 | trusted_os_signed: imx_signed 81 | 82 | trusted_applet_go: APP=trusted_applet 83 | trusted_applet_go: DIR=$(CURDIR)/trusted_applet_go 84 | trusted_applet_go: TEXT_START=$(APPLET_START) 85 | trusted_applet_go: elf 86 | mkdir -p $(CURDIR)/trusted_os_$(TARGET)/assets 87 | cp $(CURDIR)/bin/trusted_applet.elf $(CURDIR)/trusted_os_$(TARGET)/assets 88 | 89 | trusted_applet_rust: TEXT_START=$(APPLET_START) 90 | trusted_applet_rust: 91 | cd $(CURDIR)/trusted_applet_rust && rustc ${RUSTFLAGS} -o $(CURDIR)/bin/trusted_applet.elf main_${ARCH}.rs 92 | mkdir -p $(CURDIR)/trusted_os_$(TARGET)/assets 93 | cp $(CURDIR)/bin/trusted_applet.elf $(CURDIR)/trusted_os_$(TARGET)/assets 94 | 95 | nonsecure_os_go: APP=nonsecure_os_go 96 | nonsecure_os_go: DIR=$(CURDIR)/nonsecure_os_go 97 | nonsecure_os_go: TEXT_START=0x80010000 98 | nonsecure_os_go: elf 99 | mkdir -p $(CURDIR)/trusted_os_$(TARGET)/assets 100 | cp $(CURDIR)/bin/nonsecure_os_go.elf $(CURDIR)/trusted_os_$(TARGET)/assets 101 | 102 | #### ARM targets #### 103 | 104 | imx: $(APP).imx 105 | 106 | imx_signed: $(APP)-signed.imx 107 | 108 | check_hab_keys: 109 | @if [ "${HAB_KEYS}" == "" ]; then \ 110 | echo 'You need to set the HAB_KEYS variable to the path of secure boot keys'; \ 111 | echo 'See https://github.com/usbarmory/usbarmory/wiki/Secure-boot-(Mk-II)'; \ 112 | exit 1; \ 113 | fi 114 | 115 | $(APP).bin: CROSS_COMPILE=arm-none-eabi- 116 | $(APP).bin: $(APP).elf 117 | $(CROSS_COMPILE)objcopy -j .text -j .rodata -j .shstrtab -j .typelink \ 118 | -j .itablink -j .gopclntab -j .go.buildinfo -j .noptrdata -j .data \ 119 | -j .bss --set-section-flags .bss=alloc,load,contents \ 120 | -j .noptrbss --set-section-flags .noptrbss=alloc,load,contents \ 121 | $(CURDIR)/bin/$(APP).elf -O binary $(CURDIR)/bin/$(APP).bin 122 | 123 | $(APP).imx: $(APP).bin $(APP).dcd 124 | @if [ "$(APP)" == "trusted_os_usbarmory" ]; then \ 125 | echo "## disabling TZASC bypass in DCD for pre-DDR initialization ##"; \ 126 | chmod 644 $(CURDIR)/bin/$(APP).dcd; \ 127 | echo "DATA 4 0x020e4024 0x00000001 # TZASC_BYPASS" >> $(CURDIR)/bin/$(APP).dcd; \ 128 | fi 129 | mkimage -n $(CURDIR)/bin/$(APP).dcd -T imximage -e $(TEXT_START) -d $(CURDIR)/bin/$(APP).bin $(CURDIR)/bin/$(APP).imx 130 | # Copy entry point from ELF file 131 | dd if=$(CURDIR)/bin/$(APP).elf of=$(CURDIR)/bin/$(APP).imx bs=1 count=4 skip=24 seek=4 conv=notrunc 132 | 133 | $(APP).dcd: check_tamago 134 | $(APP).dcd: GOMODCACHE=$(shell ${TAMAGO} env GOMODCACHE) 135 | $(APP).dcd: TAMAGO_PKG=$(shell grep "github.com/usbarmory/tamago v" go.mod | awk '{print $$1"@"$$2}') 136 | $(APP).dcd: dcd 137 | 138 | #### RISC-V targets #### 139 | 140 | qemu.dtb: GOMODCACHE=$(shell ${TAMAGO} env GOMODCACHE) 141 | qemu.dtb: TAMAGO_PKG=$(shell grep "github.com/usbarmory/tamago v" go.mod | awk '{print $$1"@"$$2}') 142 | qemu.dtb: 143 | echo $(GOMODCACHE) 144 | echo $(TAMAGO_PKG) 145 | dtc -I dts -O dtb $(GOMODCACHE)/$(TAMAGO_PKG)/board/qemu/sifive_u/qemu-riscv64-sifive_u.dts -o $(CURDIR)/qemu.dtb 2> /dev/null 146 | 147 | #### utilities #### 148 | 149 | check_tamago: 150 | @if [ "${TAMAGO}" == "" ] || [ ! -f "${TAMAGO}" ]; then \ 151 | echo 'You need to set the TAMAGO variable to a compiled version of https://github.com/usbarmory/tamago-go'; \ 152 | exit 1; \ 153 | fi 154 | 155 | dcd: 156 | cp -f $(GOMODCACHE)/$(TAMAGO_PKG)/board/usbarmory/mk2/imximage.cfg $(CURDIR)/bin/$(APP).dcd; \ 157 | 158 | clean: 159 | @rm -fr $(CURDIR)/bin/* $(CURDIR)/trusted_os_*/assets/* $(CURDIR)/qemu.dtb 160 | 161 | qemu: 162 | $(QEMU) -kernel $(CURDIR)/bin/trusted_os_$(TARGET).elf 163 | 164 | qemu-gdb: 165 | $(QEMU) -kernel $(CURDIR)/bin/trusted_os_$(TARGET).elf -S -s 166 | 167 | #### application target #### 168 | 169 | ifeq ($(TARGET),sifive_u) 170 | 171 | $(APP).elf: check_tamago qemu.dtb 172 | cd $(DIR) && $(GOENV) $(TAMAGO) build -tags ${BUILD_TAGS} $(GOFLAGS) -o $(CURDIR)/bin/$(APP).elf && \ 173 | RT0=$$(riscv64-linux-gnu-readelf -a $(CURDIR)/bin/$(APP).elf|grep -i 'Entry point' | cut -dx -f2) && \ 174 | echo ".equ RT0_RISCV64_TAMAGO, 0x$$RT0" > $(CURDIR)/trusted_os_$(TARGET)/bios/cfg.inc && \ 175 | cd $(CURDIR)/trusted_os_$(TARGET)/bios && ./build.sh 176 | 177 | else 178 | 179 | $(APP).elf: check_tamago 180 | cd $(DIR) && $(GOENV) $(TAMAGO) build -tags ${BUILD_TAGS} $(GOFLAGS) -o $(CURDIR)/bin/$(APP).elf 181 | 182 | endif 183 | 184 | #### HAB secure boot #### 185 | 186 | $(APP)-signed.imx: check_hab_keys $(APP).imx 187 | ${TAMAGO} install github.com/usbarmory/crucible/cmd/habtool@latest 188 | $(shell ${TAMAGO} env GOPATH)/bin/habtool \ 189 | -A ${HAB_KEYS}/CSF_1_key.pem \ 190 | -a ${HAB_KEYS}/CSF_1_crt.pem \ 191 | -B ${HAB_KEYS}/IMG_1_key.pem \ 192 | -b ${HAB_KEYS}/IMG_1_crt.pem \ 193 | -t ${HAB_KEYS}/SRK_1_2_3_4_table.bin \ 194 | -x 1 \ 195 | -s \ 196 | -i $(CURDIR)/bin/$(APP).imx \ 197 | -o $(CURDIR)/bin/$(APP).csf && \ 198 | cat $(CURDIR)/bin/$(APP).imx $(CURDIR)/bin/$(APP).csf > $(CURDIR)/bin/$(APP)-signed.imx 199 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Introduction 2 | ============ 3 | 4 | The [GoTEE](https://github.com/usbarmory/GoTEE) framework implements concurrent instantiation of 5 | [TamaGo](https://github.com/usbarmory/tamago) based unikernels in 6 | privileged and unprivileged modes, interacting with each other through monitor 7 | mode and custom system calls. 8 | 9 | With these capabilities GoTEE implements a 10 | [TamaGo](https://github.com/usbarmory/tamago) based Trusted Execution 11 | Environments (TEE), bringing Go memory safety, convenience and capabilities to 12 | bare metal execution within ARM TrustZone Secure World or RISC-V Supervisor 13 | Execution Environments. 14 | 15 | GoTEE can supervise pure Go, Rust or C based freestanding Trusted Applets, 16 | implementing the GoTEE API, as well as any operating system capable of running 17 | in ARM TrustZone Normal World or RISC-V S-mode such as Linux. 18 | 19 | 20 | 21 | Features 22 | ======== 23 | 24 | * [Isolated execution contexts](https://github.com/usbarmory/GoTEE/wiki/Trusted-OS-and-Applet-execution) for ARM User mode, TrustZone Normal World or RISC-V Supervisor Mode 25 | 26 | * [Opportunistic soft lockstep for fault detection](https://github.com/usbarmory/GoTEE/wiki/Examples#opportunistic-soft-lockstep) 27 | 28 | * [API for Trusted OS implementation](https://github.com/usbarmory/GoTEE/wiki/System-Calls#gotee-system-calls) (Syscall, JSON-RPC and exception handlers) 29 | 30 | Documentation 31 | ============= 32 | 33 | [![Go Reference](https://pkg.go.dev/badge/github.com/usbarmory/GoTEE.svg)](https://pkg.go.dev/github.com/usbarmory/GoTEE) 34 | 35 | The main documentation, which includes a tutorial, can be found on the 36 | [project wiki](https://github.com/usbarmory/GoTEE/wiki). 37 | 38 | The package API documentation can be found on 39 | [pkg.go.dev](https://pkg.go.dev/github.com/usbarmory/GoTEE). 40 | 41 | Supported hardware 42 | ================== 43 | 44 | The following table summarizes currently supported SoCs and boards. 45 | 46 | | SoC | Board | SoC package | Board package | 47 | |--------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------|--------------------------------------------------------------------------------------| 48 | | NXP i.MX6ULZ | [USB armory Mk II](https://github.com/usbarmory/usbarmory/wiki) | [imx6ul](https://github.com/usbarmory/tamago/tree/master/soc/nxp/imx6ul) | [usbarmory/mk2](https://github.com/usbarmory/tamago/tree/master/board/usbarmory) | 49 | | NXP i.MX6ULL | [MCIMX6ULL-EVK](https://www.nxp.com/design/development-boards/i-mx-evaluation-and-development-boards/evaluation-kit-for-the-i-mx-6ull-and-6ulz-applications-processor:MCIMX6ULL-EVK) | [imx6ul](https://github.com/usbarmory/tamago/tree/master/soc/nxp/imx6ul) | [mx6ullevk](https://github.com/usbarmory/tamago/tree/master/board/nxp/mx6ullevk) | 50 | | SiFive FU540 | [QEMU sifive_u](https://www.qemu.org/docs/master/system/riscv/sifive_u.html) | [fu540](https://github.com/usbarmory/tamago/tree/master/soc/sifive/fu540) | [qemu/sifive_u](https://github.com/usbarmory/tamago/tree/master/board/qemu/sifive_u) | 51 | 52 | Example application 53 | =================== 54 | 55 | In TEE nomenclature, the privileged unikernel is commonly referred to as 56 | Trusted OS, while the unprivileged one represents a Trusted Applet. 57 | 58 | The GoTEE [example](https://github.com/usbarmory/GoTEE-example) 59 | demonstrate concurrent operation of Go unikernels acting as Trusted OS, 60 | Trusted Applet and Main OS. 61 | 62 | > [!WARNING] 63 | > The Main OS can be any "rich" OS (e.g. Linux), TamaGo is simply 64 | > used for a self-contained example. The same applies to the Trusted Applet 65 | > which can be any bare metal application capable of running in user mode and 66 | > implementing GoTEE API, such as freestanding C or Rust programs. 67 | > 68 | > A Rust [example](https://github.com/usbarmory/GoTEE-example/tree/master/trusted_applet_rust) 69 | > can be used replacing `trusted_applet_go` with `trusted_applet_rust` when building. 70 | 71 | The example trusted OS/applet combination performs basic testing of concurrent 72 | execution of three [TamaGo](https://github.com/usbarmory/tamago) 73 | unikernels at different privilege levels: 74 | 75 | * Trusted OS (ARM: TZ Secure World system mode, RISC-V: M-mode) 76 | * Trusted Applet (ARM: TZ Secure World user mode, RISC-V: S-mode) 77 | * Main OS (ARM: TZ Normal World system mode, RISC-V: S-mode) 78 | 79 | The Main OS yields back with a monitor call. 80 | 81 | The Trusted Applet sleeps for 5 seconds before attempting to read Trusted OS 82 | memory, which triggers an exception handled by the supervisor which terminates 83 | the Trusted Applet. 84 | 85 | The GoTEE [syscall](https://github.com/usbarmory/GoTEE/blob/master/syscall/syscall.go) 86 | interface is implemented for communication between the Trusted OS and Trusted 87 | Applet. 88 | 89 | When launched on the [USB armory Mk II](https://github.com/usbarmory/usbarmory/wiki), 90 | the example application is reachable via SSH through 91 | [Ethernet over USB](https://github.com/usbarmory/usbarmory/wiki/Host-communication) 92 | (ECM protocol, supported on Linux and macOS hosts): 93 | 94 | ``` 95 | $ ssh gotee@10.0.0.1 96 | tamago/arm • TEE security monitor (Secure World system/monitor) 97 | 98 | allgptr # memory forensics of applet goroutines 99 | csl # show config security levels (CSL) 100 | csl # set config security level (CSL) 101 | dbg # show ARM debug permissions 102 | exit, quit # close session 103 | gotee # TrustZone example w/ TamaGo unikernels 104 | help # this help 105 | linux # boot NonSecure USB armory Debian base image 106 | lockstep # tandem applet example w/ fault injection 107 | peek # memory display (use with caution) 108 | poke # memory write (use with caution) 109 | reboot # reset device 110 | sa # show security access (SA) 111 | sa # set security access (SA) 112 | stack # stack trace of current goroutine 113 | stackall # stack trace of all goroutines 114 | 115 | > 116 | ``` 117 | 118 | The example can be launched with the `gotee` command which spawns the Main OS 119 | twice to demonstrate behaviour before and after TrustZone restrictions are in 120 | effect using real hardware peripherals. 121 | 122 | Additionally the `linux` command can be used to spawn the 123 | [USB armory Debian base image](https://github.com/usbarmory/usbarmory-debian-base_image) 124 | as Non-secure main OS. 125 | 126 | > [!NOTE] 127 | > Only USB armory Debian base image releases >= 20211129 are 128 | > supported for Non-secure operation. 129 | 130 | ![gotee](https://github.com/usbarmory/GoTEE/wiki/images/gotee.png) 131 | 132 | The example can be also executed under QEMU emulation. 133 | 134 | > [!NOTE] 135 | > Emulated runs perform partial tests due to lack of full 136 | > TrustZone/PMP support by QEMU. 137 | 138 | ``` 139 | make qemu 140 | ... 141 | > gotee 142 | 00:00:00 tamago/arm • TEE security monitor (Secure World system/monitor) 143 | 00:00:00 SM loaded applet addr:0x9c000000 entry:0x9c072740 size:4940275 144 | 00:00:00 SM loaded kernel addr:0x80000000 entry:0x8007100c size:4577643 145 | 00:00:00 SM waiting for applet and kernel 146 | 00:00:00 SM starting mode:USR sp:0x9e000000 pc:0x9c072740 ns:false 147 | 00:00:00 SM starting mode:SYS sp:0x00000000 pc:0x8007100c ns:true 148 | 00:00:00 tamago/arm (go1.19.1) • TEE user applet 149 | 00:00:00 tamago/arm (go1.19.1) • system/supervisor (Non-secure) 150 | 00:00:00 supervisor is about to yield back 151 | 00:00:00 SM stopped mode:SYS sp:0x8146bf54 lr:0x801937a4 pc:0x80193884 ns:true err:exit 152 | 00:00:00 applet obtained 16 random bytes from monitor: b4cc4764dd30291a52545b182313003c 153 | 00:00:00 applet requests echo via RPC: hello 154 | 00:00:00 applet received echo via RPC: hello 155 | 00:00:00 applet will sleep for 5 seconds 156 | 00:00:01 applet says 1 mississippi 157 | ... 158 | 00:00:05 applet says 5 mississippi 159 | 00:00:05 applet is about to read secure memory at 0x98010000 160 | 00:00:05 r0:98010000 r1:9c8240c0 r2:98010000 r3:00000000 161 | 00:00:05 r4:00000000 r5:00000000 r6:00000000 r7:9c86bec8 162 | 00:00:05 r8:00000007 r9:0000003d r10:9c8020f0 r11:9c342f41 cpsr:600001d7 (ABT) 163 | 00:00:05 r12:00000061 sp:9c86bf08 lr:9c1b1be8 pc:9c011330 spsr:600001d0 (USR) 164 | 00:00:05 SM stopped mode:USR sp:0x9c86bf08 lr:0x9c1b1be8 pc:0x9c011330 ns:false err:ABT 165 | ``` 166 | 167 | Building the compiler 168 | ===================== 169 | 170 | Build the [TamaGo compiler](https://github.com/usbarmory/tamago-go) 171 | (or use the [latest binary release](https://github.com/usbarmory/tamago-go/releases/latest)): 172 | 173 | ``` 174 | wget https://github.com/usbarmory/tamago-go/archive/refs/tags/latest.zip 175 | unzip latest.zip 176 | cd tamago-go-latest/src && ./all.bash 177 | cd ../bin && export TAMAGO=`pwd`/go 178 | ``` 179 | 180 | Building and executing on ARM targets 181 | ===================================== 182 | 183 | Build the example trusted applet and kernel executables as follows: 184 | 185 | ``` 186 | git clone https://github.com/usbarmory/GoTEE-example 187 | cd GoTEE-example && export TARGET=usbarmory && make nonsecure_os_go && make trusted_applet_go && make trusted_os 188 | ``` 189 | 190 | > [!NOTE] 191 | > Replace `trusted_applet_go` with `trusted_applet_rust` for a Rust 192 | > TA example, this requires Rust nightly and the `armv7a-none-eabi` toolchain. 193 | 194 | Final executables are created in the `bin` subdirectory, 195 | `trusted_os_usbarmory.imx` should be used for native execution. 196 | 197 | The following targets are available: 198 | 199 | | `TARGET` | Board | Executing and debugging | 200 | |-------------|------------------|----------------------------------------------------------------------------------------------------------| 201 | | `usbarmory` | USB armory Mk II | [usbarmory](https://github.com/usbarmory/tamago/tree/master/board/usbarmory#executing-and-debugging) | 202 | 203 | The targets support native (see relevant documentation links in the table above) 204 | as well as emulated execution (e.g. `make qemu`). 205 | 206 | Building and executing on RISC-V targets 207 | ======================================== 208 | 209 | Build the example trusted applet and kernel executables as follows: 210 | 211 | ``` 212 | git clone https://github.com/usbarmory/GoTEE-example 213 | cd GoTEE-example && export TARGET=sifive_u && make nonsecure_os_go && make trusted_applet_go && make trusted_os 214 | ``` 215 | 216 | > [!NOTE] 217 | > Replace `trusted_applet_go` with `trusted_applet_rust` for a Rust 218 | > TA example, this requires Rust nightly and the `riscv64gc-unknown-none-elf` 219 | > toolchain. 220 | 221 | Final executables are created in the `bin` subdirectory. 222 | 223 | Available targets: 224 | 225 | | `TARGET` | Board | Executing and debugging | 226 | |-------------|------------------|----------------------------------------------------------------------------------------------------------| 227 | | `sifive_u` | QEMU sifive_u | [sifive_u](https://github.com/usbarmory/tamago/tree/master/board/qemu/sifive_u#executing-and-debugging) | 228 | 229 | The target has only been tested with emulated execution (e.g. `make qemu`) 230 | 231 | Applications using GoTEE 232 | ======================== 233 | 234 | * [ArmoredWitness](https://github.com/transparency-dev/armored-witness) - cross-ecosystem witness network 235 | 236 | Authors 237 | ======= 238 | 239 | Andrea Barisani 240 | andrea@inversepath.com 241 | 242 | Andrej Rosano 243 | andrej@inversepath.com 244 | 245 | License 246 | ======= 247 | 248 | GoTEE | https://github.com/usbarmory/GoTEE 249 | Copyright (c) The GoTEE authors. All Rights Reserved. 250 | 251 | These source files are distributed under the BSD-style license found in the 252 | [LICENSE](https://github.com/usbarmory/GoTEE-example/blob/master/LICENSE) file. 253 | --------------------------------------------------------------------------------