USB Armory MkII Tutorial 4
Published:
How to Use USB Armory Mk II (Part 4: GoTEE + Bear Metal Execution + Cache management)
Build GoTEE
export TARGET=usbarmory
# Update TamaGo Dependencies
# Try updating the TamaGo module to the latest version:
cd GoTEE-example/nonsecure_os_go
go get -u github.com/usbarmory/tamago@latest
go mod tidy
cd ..
make nonsecure_os_go
make trusted_applet_go
make trusted_os
Unplug and replug usbarmoy
cd ~/Desktop/GoTEE-example/bin
sudo $HOME/go/bin/armory-boot-usb -i trusted_os_usbarmory.imx
Bring up the USB network on your host
# find the new interface (often usb0 or an enx* name)
ip link
# result
# USB-Ethernet gadget is enx1a5589a26942 (that’s the typical “enx…” name Linux gives to USB NICs
enx1a5589a26942: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN mode DEFAULT group default qlen 1000
link/ether 1a:55:89:a2:69:42 brd ff:ff:ff:ff:ff:ff
# pick the USB NIC
IF=enx1a5589a26942
# clean slate + set your host IP
sudo ip addr flush dev $IF
sudo ip addr add 10.0.0.2/24 dev $IF
sudo ip link set $IF up
# quick check
ip addr show dev $IF
ping -c 3 10.0.0.1
If ping works, SSH in:
ssh gotee@10.0.0.1
ssh issue
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:MNlLQ8Py8VcK4h3RxDwak2BFxDO6asF9vFY2CY8fPdA.
Please contact your system administrator.
Add correct host key in /home/lizeren/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /home/lizeren/.ssh/known_hosts:8
remove with:
ssh-keygen -f "/home/lizeren/.ssh/known_hosts" -R "10.0.0.1"
Host key for 10.0.0.1 has changed and you have requested strict checking.
Host key verification failed.
GoTEE unikernel generates a new SSH host key each time you boot it, so it no longer matches the one stored from a previous session.
You can safely remove the old key and reconnect:
ssh-keygen -f "/home/lizeren/.ssh/known_hosts" -R "10.0.0.1"
Then try again:
ssh gotee@10.0.0.1
Go application: Cache + Performance Counter
add this code to nonsecure_os_go/ and named it cache_timer.go
//go:build tamago && arm
package main
import (
"github.com/usbarmory/tamago/arm"
)
func CacheTimerDemo() {
cpu := arm.CPU{}
cpu.EnableSMP()
cpu.EnableCache()
cpu.InitGenericTimers(0, 0)
start := cpu.Counter()
for i := 0; i < 1_000_000; i++ {}
end := cpu.Counter()
cpu.FlushDataCache()
cpu.FlushInstructionCache()
println("Cycle counter delta:", end-start)
}
now rebuild the GoTEE
cd GoTEE-example
export TARGET=usbarmory
make nonsecure_os_go
make trusted_applet_go
make trusted_os
#don't forget to unplug and replug the USB Armory
sudo $HOME/go/bin/armory-boot-usb -i bin/trusted_os_usbarmory.imx
# pick the USB NIC
IF=enx1a5589a26942
# clean slate + set your host IP
sudo ip addr flush dev $IF
sudo ip addr add 10.0.0.2/24 dev $IF
sudo ip link set $IF up
ssh-keygen -f "/home/lizeren/.ssh/known_hosts" -R "10.0.0.1"
ssh gotee@10.0.0.1
Now inside the GoTEE command shell, run
gotee # TrustZone example w/ TamaGo unikernels
Yuo should see the performance counter output.
Cycle counter delta: 35560
Examine cache disable
//go:build tamago && arm
package gotee
import (
"log"
"github.com/usbarmory/tamago/arm"
)
func CacheTimerDemo() {
cpu := arm.CPU{}
cpu.EnableSMP()
cpu.EnableCache()
cpu.InitGenericTimers(0, 0)
// Create a memory array to access
const arraySize = 1000
data := make([]uint32, arraySize)
// Initialize the array
for i := 0; i < arraySize; i++ {
data[i] = uint32(i)
}
// ===== Measure WITH cache enabled =====
log.Println("=== Testing WITH cache enabled ===")
start := cpu.Counter()
var sum uint32
for i := 0; i < 10000; i++ {
sum += data[i%arraySize] // Memory access
}
end := cpu.Counter()
cyclesWithCache := end - start
log.Println("Cycles WITH cache:", cyclesWithCache)
log.Println("Sum (to prevent optimization):", sum)
// ===== Disable cache and flush =====
log.Println("\n=== Disabling cache ===")
cpu.FlushDataCache()
cpu.FlushInstructionCache()
cpu.DisableCache()
log.Println("Cache disabled")
// ===== Measure WITHOUT cache =====
log.Println("\n=== Testing WITHOUT cache ===")
start = cpu.Counter()
sum = 0
for i := 0; i < 10000; i++ {
sum += data[i%arraySize] // Same memory access pattern
}
end = cpu.Counter()
cyclesWithoutCache := end - start
log.Println("Cycles WITHOUT cache:", cyclesWithoutCache)
log.Println("Sum (to prevent optimization):", sum)
// ===== Compare results =====
log.Println("\n=== Comparison ===")
log.Println("Cycles WITH cache: ", cyclesWithCache)
log.Println("Cycles WITHOUT cache:", cyclesWithoutCache)
if cyclesWithoutCache > cyclesWithCache {
slowdown := float64(cyclesWithoutCache) / float64(cyclesWithCache)
log.Printf("Cache disabled is %.2fx slower\n", slowdown)
}
// Get CPU mode
mode := cpu.Mode()
log.Println("CPU current mode is:", mode)
}
Flush + Reload
https://github.com/lizeren/usbarmory-gotee/blob/main/trusted_os_usbarmory/internal/cache_timer.go
