Skip to content

Frequently Asked Questions (FAQ)

Andrea Barisani edited this page Sep 10, 2024 · 59 revisions

What is TamaGo?

TamaGo is a framework that enables compilation and execution of unencumbered Go applications on bare metal ARM/RISC-V System-on-Chip (SoC) components.

The project spawns from the desire of reducing the attack surface of embedded systems firmware by removing any runtime dependency on C code and Operating Systems.

Why?

A lot of our custom USB armory projects entail developing Go applications executed under minimal Buildroot environments, typically we are asked to develop cryptocurrency wallets, HSMs, cryptographic provisioning dongles, secure storage, etc.

The USB armory and Go are perfect for such applications, but somewhat the burden of carrying over a full Linux kernel and runtime, albeit minimal, feels excessive and requires a fair deal of maintenance.

We love Go and we love for unencumbered Go applications to be executed without any C code supporting its execution, to decrease the overall attack surface, improve security and aid maintainability of the code.

For this reason TamaGo was born.

Why the name TamaGo?

In Japanese tamago (卵) means "egg", given that we are surrounding Go just with the bare metal the name seemed appropriate. When running under QEMU emulation I guess you can call it TamaGotchi \(^O^)/.

How do I perform I/O from my TamaGo application?

The imx6 USB driver supports enumeration and bulk endpoints, example use cases are Mass Storage, Ethernet with full TCP/IP stack integration, CCID, U2F, Serial.

The imx6 Ethernet driver supports physical Ethernet devices.

The imx6 UART driver supports serial communication, allowing on the USB armory Mk II console or Bluetooth communication.

What are the current limitations for compiled applications?

Nearly every standard Go application can be compiled/developed without limitations, see Compatibility for a few caveats.

Are interrupts supported?

Yes, there is support for interrupts on ARM.

What is the performance compared to Go running under a conventional OS?

As expected, performance is identical if not superior on a single core (for now there is no multi-core support in TamaGo).

So what can I do with it?

On the USB armory Mk II TamaGo is currently capable of perform cryptographic operations leveraging, other than Go own libraries, on the NXP DCP/CAAM hardware cryptographic accelerators.

The following applications provide some examples:

How does TamaGo differ from past/current similar efforts?

TinyGo

The wonderful TinyGo project targets microcontrollers with a new LLVM based Go compiler that minimizes the footprint of the resulting programs, to make them suitable for constrained MCU environments.

This entails that, inevitably, memory allocation, datatypes, and other Go specific behaviors are implemented in a different way and that the resulting language support differs from standard Go.

TamaGo modifications are minimal against the original Go compiler, runtime and the target application (only one import required), with a clean separation from other architectures.

The focus on more powerful hardware (SoC vs microcontrollers), with an extensive re-use of the original Go runtime and packages, entails that complete standard library support.

Embedded Go

The Embedded Go project is a quite new effort, with a very similar approach to TamaGo but which targets the ARMv7-M/Thumb2 architecture by adding new compiler support for it within the Go runtime.

Similarly to TamaGo it adds a specific GOOS=noos support but targeting microcontrollers, it supports threading (which is still not supported in TamaGo) and re-uses less existing Go runtime components than TamaGo.

The need to add a new GOARCH, in addition to the new GOOS and its threading re-implementation, makes it a somewhat more invasive (but with reasons!) patch than TamaGo other than currently targeting a different class of hardware.

eggos

The eggos project is a quite new effort, which targets x86 platforms. It re-uses the vanilla compiler by wrapping GOOS=linux required syscalls back to Go. It represents a cool novel approach to bare metal Go unikernels on x86.

Biscuit

The Biscuit research OS is a research project that provides a full OS kernel written in Go, therefore meant to run non-Go software underneath.

The project definitely inspired TamaGo as it proven the possibility of adapting the Go runtime, on amd64 hardware, for bare metal execution.

However Biscuit scope is far larger than TamaGo, which remains a focused effort to purely run a monolithic Go application on the bare metal, requiring a less invasive approach.

Unlike Biscuit, which hijacks the GOOS=linux support, TamaGo places strong emphasis on code re-use from existing architectures already included within the standard Go runtime while cleanly separating them with its own GOOS=tamago.

Additionally TamaGo does not require any C intermediate bootloader or 3rd party initial bootloader (such as U-Boot), both needed by Biscuit, as the compiled application can be natively executed.

See Internals for more information.

G.E.R.T.

The G.E.R.T. project is a Biscuit based modification which aims to achieve a similar goal to TamaGo.

The Go runtime modifications applied by G.E.R.T. are however fairly extensive for the required task, Biscuit concepts are adapted to the ARM architecture with a rather extensive overhaul of the runtime, also to include multi-threaded support which is not initially sought by TamaGo.

Unlike G.E.R.T, which hijacks the GOOS=linux support like Biscuit does, TamaGo places strong emphasis on code re-use from existing architectures already included within the standard Go runtime while cleanly separating them with its own GOOS=tamago.

Additionally TamaGo does not require any C intermediate bootloader or 3rd party initial bootloader (such as U-Boot), both needed by G.E.R.T., as the compiled application can be natively executed.

G.E.R.T. greatly inspired TamaGo in proving the feasibility of an ARM port of Biscuit, however TamaGo provides a much simpler implementation with minimal modifications to the Go runtime.

See Internals for more information.

Why Go and not Rust?

Well why not both? :)

Someone is already working on bare metal Rust for the USB armory Mk II.

The TamaGo project spawns from the desire of being able to use Go excellent cryptographic primitives on embedded systems, without carrying the burden of a full blown OS.

The TinyGo FAQ has an excellent response to this question.

Are there plans to get TamaGo merged upstream?

The TamaGo modifications as clean and isolated as possible to allow easy upstream merging, despite this the Go core team declined our proposals for official inclusion (#37503, #46802).

For now TamaGo patches against the standard Go distribution remain maintained as an out-of-tree port, with our commitment to consistently keep them up to date.

How can I debug applications?

On real hardware GDB and JTAG are available.

On emulated hardware, such as QEMU, GDB can also be used.

Additionally networked applications can use Go pprof as usual.

I want to compile on the USB armory Mk II itself, can I cross compile the TamaGo compiler for it to save time?

We prepare binary releases for this purpose, if you want to cross compile your own here's how to do it:

git clone https://github.com/usbarmory/tamago-go && \
cd tamago-go && git pull && git checkout latest && cd src && \
GOARCH=arm GOROOT_FINAL=/usr/local/tamago GOARM=7 ./make.bash && \
cd .. && mv bin/linux_arm/* bin/ && rmdir bin/linux_arm && \
rm -rf pkg/linux_amd64* && rm -rf pkg/tool/linux_amd64 && \
tar -c --transform 's+^./+/usr/local/tamago-go/+' --owner=0 --group=0 -f ../tamago-go$V.linux-armv7l.tar.gz -v -z --exclude .git .

How can I help?

Start developing drivers and send pull requests!

Can you provide commercial support for custom firmware, drivers, development?

Of course!

This is precisely what we do at WithSecure Foundry