Skip to content

crypto/mldsa: Sign panics with typed-nil *Options #80344

Description

@SphereDonout

Go version

go1.26.0 darwin/arm64

What did you do?

I called crypto/mldsa.(*PrivateKey).Sign with a typed-nil *mldsa.Options value.
Minimal reproducer:

package main

import (
	"crypto/mldsa"
)

func main() {
	sk, err := mldsa.GenerateKey(mldsa.MLDSA44())
	if err != nil {
		panic(err)
	}

	var opts *mldsa.Options
	_, _ = sk.Sign(nil, []byte("message"), opts)
}

The same issue also applies to SignDeterministic:

var opts *mldsa.Options
_, _ = sk.SignDeterministic([]byte("message"), opts)

What did you see happen?

The ordinary untyped nil case is handled:

if opts == nil {
	opts = &Options{}
}

However, a typed-nil (*mldsa.Options)(nil) stored in the crypto.SignerOpts interface is not equal to nil. The code then calls opts.HashFunc(), which succeeds because (*Options).HashFunc does not dereference the receiver. After that, this block type-asserts back to *Options and dereferences the nil pointer:

if opts, ok := opts.(*Options); ok {
	context = opts.Context
}

That causes a runtime panic instead of returning an error or treating the typed-nil options value like nil.

What did you expect to see?

I expected typed-nil *mldsa.Options to be handled consistently with nil options, or rejected cleanly without panicking.
For example, either of these behaviors would be reasonable:

var opts *mldsa.Options
sig, err := sk.Sign(nil, []byte("message"), opts)
// behaves like opts == nil

or:

var opts *mldsa.Options
sig, err := sk.Sign(nil, []byte("message"), opts)
// returns a non-nil error

The panic can be avoided by checking the asserted *Options value before reading Context, for example:

if opts, ok := opts.(*Options); ok && opts != nil {
	context = opts.Context
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    FixPendingIssues that have a fix which has not yet been reviewed or submitted.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions