VYPR
Medium severity4.6NVD Advisory· Published Mar 20, 2026· Updated Apr 16, 2026

CVE-2026-32953

CVE-2026-32953

Description

Tillitis TKey Client package is a Go package for a TKey client. Versions 1.2.0 and below contain a critical bug in the tkeyclient Go module which causes 1 out of every 256 User Supplied Secrets (USS) to be silently ignored, producing the same Compound Device Identifier (CDI)—and thus the same key material—as if no USS is provided. This happens because a buffer index error overwrites the USS-enabled boolean with the first byte of the USS digest, so any USS whose hash starts with 0x00 is effectively discarded. This issue has been fixed in version 1.3.0. Users unable to upgrade immediately should switch to a USS whose hash does not begin with a zero byte.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/tillitis/tkeyclientGo
< 1.3.01.3.0

Affected products

1

Patches

1
4954dccf0287

Merge commit from fork

https://github.com/tillitis/tkeyclientMichael Cardell WiderkrantzMar 16, 2026via ghsa
2 files changed · +53 14
  • RELEASE.md+13 0 modified
    @@ -1,5 +1,18 @@
     # Release notes
     
    +## v1.3.0
    +
    +- Version v1.2.0 and earlier had a protocol vulnerability leaving some
    +  USSs unused. A CDI generated from use of this package might be
    +  changed since earlier versions! Read more here:
    +
    +  https://github.com/tillitis/tkeyclient/security/advisories/GHSA-4w7r-3222-8h6v
    +
    +Complete
    +[changelog](https://github.com/tillitis/tkeyclient/compare/v1.1.0...v1.2.0).
    +
    +- Adds new option function WithFullUss() for use with Connect().
    +
     ## v1.2.0
     
     - Detect new Castor USB VID/PID and older TKey models.
    
  • tkeyclient.go+40 14 modified
    @@ -66,8 +66,9 @@ const (
     // TillitisKey is a serial connection to a TKey and the commands that
     // the firmware supports.
     type TillitisKey struct {
    -	speed int
    -	conn  serial.Port
    +	speed        int
    +	conn         serial.Port
    +	forceFullUss bool
     }
     
     // New allocates a new TillitisKey. Use the Connect() method to
    @@ -77,18 +78,27 @@ func New() *TillitisKey {
     	return tk
     }
     
    +// Option to set serial speed. For use with Connect.
     func WithSpeed(speed int) func(*TillitisKey) {
     	return func(tk *TillitisKey) {
     		tk.speed = speed
     	}
     }
     
    +// Option to force use of 32 byte USS digest on Bellatrix and earlier. For use with Connect.
    +func WithFullUss() func(*TillitisKey) {
    +	return func(tk *TillitisKey) {
    +		tk.forceFullUss = true
    +	}
    +}
    +
     // Connect connects to a TKey serial port using the provided port
     // device and options.
     func (tk *TillitisKey) Connect(port string, options ...func(*TillitisKey)) error {
     	var err error
     
     	tk.speed = SerialSpeed
    +	tk.forceFullUss = false
     	for _, opt := range options {
     		opt(tk)
     	}
    @@ -287,17 +297,22 @@ func (tk TillitisKey) LoadAppFromFile(fileName string, secretPhrase []byte) erro
     	return tk.LoadApp(content, secretPhrase)
     }
     
    -// 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.
    +// LoadApp sends a device app in bin and optionally a User Supplied
    +// Secret digest to the TKey.
    +//
    +// After succesfully sending the device app it computes a digest over
    +// bin and compares it to what was returned from the TKey, returning
    +// an error if it isn't equal.
    +//
    +// The USS is a BLAKE2s digest of the secretPhrase argument. How much
    +// of the digest is used differs on different hardware:
    +//
    +//   - Bellatrix and earlier: last 31 bytes of the digest for backward
    +//     compatibility reasons.
     //
    -// 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.
    +//   - Castor and later: all 32 bytes used.
     //
    -// 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.
    +// Returns ErrResponseStatusNotOK if firmware is not detected.
     func (tk TillitisKey) LoadApp(bin []byte, secretPhrase []byte) error {
     	binLen := len(bin)
     	if binLen > AppMaxSize {
    @@ -306,8 +321,13 @@ func (tk TillitisKey) LoadApp(bin []byte, secretPhrase []byte) error {
     
     	le.Printf("app size: %v, 0x%x, 0b%b\n", binLen, binLen, binLen)
     
    -	err := tk.loadApp(binLen, secretPhrase)
    +	udi, err := tk.GetUDI()
     	if err != nil {
    +		// Probably not running firmware? Or communication error
    +		return err
    +	}
    +
    +	if err := tk.loadApp(binLen, secretPhrase, udi.ProductID); err != nil {
     		return err
     	}
     
    @@ -346,7 +366,7 @@ func (tk TillitisKey) LoadApp(bin []byte, secretPhrase []byte) error {
     }
     
     // loadApp sets the size and USS of the app to be loaded into the TKey.
    -func (tk TillitisKey) loadApp(size int, secretPhrase []byte) error {
    +func (tk TillitisKey) loadApp(size int, secretPhrase []byte, pid uint8) error {
     	id := 2
     	tx, err := NewFrameBuf(cmdLoadApp, id)
     	if err != nil {
    @@ -365,7 +385,13 @@ func (tk TillitisKey) loadApp(size int, secretPhrase []byte) error {
     		tx[6] = 1
     		// Hash user's phrase as USS
     		uss := blake2s.Sum256(secretPhrase)
    -		copy(tx[6:], uss[:])
    +
    +		if pid >= UDIPIDCastor || tk.forceFullUss {
    +			copy(tx[7:], uss[:])
    +		} else {
    +			// skip first byte for backwards compatibility, 31 byte uss
    +			copy(tx[7:], uss[1:])
    +		}
     	}
     
     	Dump("LoadApp tx", tx)
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.