package module
Version: v0.0.7 Latest Latest

This package is not in the latest version of its module.

Go to latest
Published: Jun 7, 2023 License: GPL-2.0 Imports: 10 Imported by: 3


ci Go Reference

Tillitis TKey Client package

A Go package for controlling a Tillitis TKey, upload device apps, and communicate with it.

See the Go doc for tkeyclient for details on how to call the functions.

See apps repo for example client and device applications.

Release notes in

Licenses and SPDX tags

Unless otherwise noted, the project sources are licensed under the terms and conditions of the "GNU General Public License v2.0 only":

Copyright Tillitis AB.

These programs are free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2 only.

These programs are distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see:

See LICENSE for the full GPLv2-only license text.

External source code we have imported are isolated in their own directories. They may be released under other licenses. This is noted with a similar LICENSE file in every directory containing imported sources.

The project uses single-line references to Unique License Identifiers as defined by the Linux Foundation's SPDX project on its own source files, but not necessarily imported files. The line in each individual source file identifies the license applicable to that file.

The current set of valid, predefined SPDX identifiers can be found on the SPDX License List at:



Package tkeyclient provides a connection to a Tillitis TKey security stick. To create a new connection:

tk := tkeyclient.New()
err := tk.Connect(port)

Then you can start using it by asking it to identify itself:

nameVer, err := tk.GetNameVersion()

Or loading and starting an app on the stick:

err = tk.LoadAppFromFile(*fileName)

After this, you will have to switch to a new protocol specific to the app, see for instance the Go package for one such app specific protocol to speak to the signer app:

When writing your app specific protocol you might still want to use the framing protocol provided here. See NewFrameBuf() and ReadFrame().



View Source
const (

	// Custom errors
	ErrNoDevice    = constError("no TKey connected")
	ErrManyDevices = constError("more than one TKey connected")
View Source
const (
	// Speed in bps for talking to the TKey
	SerialSpeed = 62500
	// Codes used in app proto responses
	StatusOK  = 0x00
	StatusBad = 0x01
View Source
const ErrResponseStatusNotOK = constError("response status not OK")


This section is empty.


func DetectSerialPort

func DetectSerialPort(verbose bool) (string, error)

DetectSerialPort tries to detect an inserted TKey and returns the device path if successful.

func Dump

func Dump(s string, d []byte)

Dump() hexdumps data in d with an explaining string s first. It expects d to contain the whole frame as sent on the wire, with the framing protocol header in the first byte.

func NewFrameBuf

func NewFrameBuf(cmd Cmd, id int) ([]byte, error)

NewFrameBuf allocates a buffer with the appropriate size for the command in cmd, including the framing protocol header byte. The cmd parameter is used to get the endpoint and command length, which together with id parameter are encoded as the header byte. The header byte is placed in the first byte in the returned buffer. The command code from cmd is placed in the buffer's second byte.

Header byte (used for both command and response frame):

Bit [7] (1 bit). Reserved - possible protocol version.

Bits [6..5] (2 bits). Frame ID tag.

Bits [4..3] (2 bits). Endpoint number:

00 == reserved
01 == HW in application_fpga
10 == FW in application_fpga
11 == SW (application) in application_fpga

Bit [2] (1 bit). Usage:

Command: Unused. MUST be zero.
Response: 0 == OK, 1 == Not OK (NOK)

Bits [1..0] (2 bits). Command/Response data length:

00 == 1 byte
01 == 4 bytes
10 == 32 bytes
11 == 128 bytes

Note that the number of bytes indicated by the command data length field does **not** include the header byte. This means that a complete command frame, with a header indicating a command length of 128 bytes, is 127 bytes in length.

func SilenceLogging

func SilenceLogging()

func WithSpeed

func WithSpeed(speed int) func(*TillitisKey)


type Cmd

type Cmd interface {
	Code() byte
	String() string

	CmdLen() CmdLen
	Endpoint() Endpoint

type CmdLen

type CmdLen byte

Length of command data that follows the first 1 byte frame header

const (
	CmdLen1   CmdLen = 0
	CmdLen4   CmdLen = 1
	CmdLen32  CmdLen = 2
	CmdLen128 CmdLen = 3

func (CmdLen) Bytelen

func (l CmdLen) Bytelen() int

Bytelen returns the number of bytes corresponding to the specific CmdLen value.

type Endpoint

type Endpoint byte
const (
	// destAFPGA endpoint = 1
	DestFW  Endpoint = 2
	DestApp Endpoint = 3

type FramingHdr

type FramingHdr struct {
	ID            byte
	Endpoint      Endpoint
	CmdLen        CmdLen
	ResponseNotOK bool

type NameVersion

type NameVersion struct {
	Name0   string
	Name1   string
	Version uint32

func (*NameVersion) Unpack

func (n *NameVersion) Unpack(raw []byte)

type SerialPort

type SerialPort struct {
	DevPath      string
	SerialNumber string

func GetSerialPorts

func GetSerialPorts() ([]SerialPort, error)

GetSerialPorts enumerates any existing TKey serial ports identified on the system.

type TillitisKey

type TillitisKey struct {
	// contains filtered or unexported fields

TillitisKey is a serial connection to a TKey and the commands that the firmware supports.

func New

func New() *TillitisKey

New allocates a new TillitisKey. Use the Connect() method to actually open a connection.

func (TillitisKey) Close

func (tk TillitisKey) Close() error

Close the connection to the TKey

func (*TillitisKey) Connect

func (tk *TillitisKey) Connect(port string, options ...func(*TillitisKey)) error

Connect connects to a TKey serial port using the provided port device and options.

func (TillitisKey) GetNameVersion

func (tk TillitisKey) GetNameVersion() (*NameVersion, error)

GetNameVersion gets the name and version from the TKey firmware

func (TillitisKey) GetUDI

func (tk TillitisKey) GetUDI() (*UDI, error)

GetUDI gets the UDI (Unique Device ID) from the TKey firmware

func (TillitisKey) LoadApp

func (tk TillitisKey) LoadApp(bin []byte, secretPhrase []byte) error

LoadApp loads the USS (User Supplied Secret), and contents of bin into the TKey, running the app after verifying that the digest calculated on the host is the same as the digest from the TKey.

The USS is a 32 bytes digest hashed from secretPhrase (which is provided by the user). If secretPhrase is an empty slice, 32 bytes of zeroes will be loaded as USS.

Loading USS is always done together with loading and running an app, because the host program can't otherwise be sure that the expected USS is used.

func (TillitisKey) LoadAppFromFile

func (tk TillitisKey) LoadAppFromFile(fileName string, secretPhrase []byte) error

LoadAppFromFile loads and runs a raw binary file from fileName into the TKey.

func (TillitisKey) ReadFrame

func (tk TillitisKey) ReadFrame(expectedResp Cmd, expectedID int) ([]byte, FramingHdr, error)

ReadFrame reads a response in the framing protocol. The header byte is first parsed. If the header has response status Not OK, ErrResponseStatusNotOK is returned. Header command length and endpoint are then checked against the expectedResp parameter, header ID is checked against expectedID. The response code (first byte after header) is also checked against the code in expectedResp. It returns the whole frame read, the parsed header byte, and any error separately.

func (TillitisKey) SetReadTimeout

func (tk TillitisKey) SetReadTimeout(seconds int) error

SetReadTimeout sets the timeout of the underlying serial connection to the TKey. Pass 0 seconds to not have any timeout. Note that the timeout implemented in the serial lib only works for simple Read(). E.g. io.ReadFull() will Read() until the buffer is full.

func (TillitisKey) Write

func (tk TillitisKey) Write(d []byte) error

type UDI

type UDI struct {
	Unnamed         uint8 // 4 bits, hardcoded to 0 by
	VendorID        uint16
	ProductID       uint8 // 6 bits
	ProductRevision uint8 // 6 bits
	Serial          uint32
	// contains filtered or unexported fields

Modelled after how (in tillitis-key1 repo) generates the UDI

func (*UDI) RawBytes

func (u *UDI) RawBytes() []byte

func (*UDI) String

func (u *UDI) String() string

func (*UDI) Unpack

func (u *UDI) Unpack(raw []byte)

Unpack unpacks the UDI parts from the raw 8 bytes (2 * 32-bit words) sent on the wire.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL