slackhq/nebula · error
pkcs11 module gave us a nil CKA_PUBLIC_KEY_INFO, and looking
Error message
pkcs11 module gave us a nil CKA_PUBLIC_KEY_INFO, and looking up the public key also failed: %w
What it means
GetPubKey prefers the CKA_PUBLIC_KEY_INFO attribute of the client's key object to reconstruct the public key. When that attribute is nil, it falls back to locating the public key object via findDeriveKey and wrapping that failure with this error, indicating both paths to obtain the public key failed.
Source
Thrown at pkclient/pkclient_cgo.go:213
if tmpKey == nil || len(tmpKey) == 0 {
return nil, fmt.Errorf("got an empty secret key")
}
secret := make([]byte, NoiseKeySize)
copy(secret[:], tmpKey[:NoiseKeySize])
return secret, nil
}
func (c *PKClient) GetPubKey() ([]byte, error) {
d, err := c.privKeyObj.Attribute(pkcs11.CKA_PUBLIC_KEY_INFO)
if err != nil {
return nil, err
}
if d != nil && len(d) > 0 {
return formatPubkeyFromPublicKeyInfoAttr(d)
}
c.pubKeyObj, err = c.findDeriveKey(c.id, c.label, false)
if err != nil {
return nil, fmt.Errorf("pkcs11 module gave us a nil CKA_PUBLIC_KEY_INFO, and looking up the public key also failed: %w", err)
}
d, err = c.pubKeyObj.Attribute(pkcs11.CKA_EC_POINT)
if err != nil {
return nil, fmt.Errorf("pkcs11 module gave us a nil CKA_PUBLIC_KEY_INFO, and reading CKA_EC_POINT also failed: %w", err)
}
if d == nil || len(d) < 1 {
return nil, fmt.Errorf("pkcs11 module gave us a nil or empty CKA_EC_POINT")
}
switch len(d) {
case 65: //length of 0x04 + len(X) + len(Y)
return d, nil
case 67: //as above, DER-encoded IIRC?
return d[2:], nil
default:
return nil, fmt.Errorf("unknown public key length: %d", len(d))
}
}
View on GitHub (pinned to dd8f660c0a)
Solutions
- Store/enable CKA_PUBLIC_KEY_INFO on the key object (or re-import with it) so the primary path works.
- Ensure a matching public key object with the same CKA_ID/CKA_LABEL exists on the token.
- Check findDeriveKey's search template attributes (CKA_CLASS=CKO_PUBLIC_KEY, CKA_DERIVE) match how the key was provisioned.
- Regenerate the keypair on the HSM with full public object attributes.
Example fix
// before: provision private key only pkcs11-tool --keypairgen --id 01 --label nebula --key-type EC:prime256v1 --usage-derive // after: also verify public object exists pkcs11-tool --list-objects --type pubkey --id 01
Defensive patterns
Strategy: validation
Validate before calling
// Before GetPubKey: confirm both key objects exist on the token
out, _ := exec.Command("pkcs11-tool", "--module", hsmPath, "--slot", slot,
"--login", "--pin", pin, "--list-objects").Output()
needPriv := strings.Contains(string(out), "Private Key")
needPub := strings.Contains(string(out), "Public Key")
if !needPriv || !needPub { return errors.New("token missing private or public key object") } Try / catch
pub, err := client.GetPubKey()
if err != nil {
if strings.Contains(err.Error(), "nil CKA_PUBLIC_KEY_INFO") {
return fmt.Errorf("HSM not fully provisioned (missing CKA_PUBLIC_KEY_INFO/public object): %w", err)
}
return err
} Prevention
- Provision keypairs with CKA_PUBLIC_KEY_INFO or a stored public key object.
- Use standard tooling (nebula-cert pkcs11 generates complete keypairs) instead of manual imports.
- Audit tokens with pkcs11-tool --list-objects as part of deployment health checks.
- Keep CKA_ID/CKA_LABEL consistent between private and public objects.
When it happens
Trigger: Calling GetPubKey (used by ca and signCert) on a token whose private key has no CKA_PUBLIC_KEY_INFO attribute AND no matching public key object can be found by id/label.
Common situations: Minimal HSM provisioning that only stored the private key without the public key object; vendor module that doesn't expose CKA_PUBLIC_KEY_INFO; id/label mismatch preventing the public key lookup; pkcs11-backed certificates where the public half was never stored.
Related errors
- failed to get public key: %w
- notImplemented
- error while creating PKCS#11 client: %w
- error while getting public key with PKCS#11: %w
- error while signing with PKCS#11: %w
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/52f01f61d08c4582.
Report an issue: GitHub.