{"record":{"id":"165bfce3d9f56db4","repo":"kubernetes/kops","slug":"failed-to-sign-data-with-tpm-w","errorCode":null,"errorMessage":"failed to sign data with TPM: %w","messagePattern":"failed to sign data with TPM: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/gce/tpm/gcetpmsigner/tpmauthenticator.go","lineNumber":122,"sourceCode":"\t}\n\ttoken := &gcetpm.AuthToken{\n\t\tData:      payload,\n\t\tSignature: signature,\n\t}\n\n\tb, err := json.Marshal(token)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to marshal token: %w\", err)\n\t}\n\treturn gcetpm.GCETPMAuthenticationTokenPrefix + base64.StdEncoding.EncodeToString(b), nil\n}\n\n// tpmSign performs a TPM signature with the tpmKey, and sanity checks the result.\nfunc tpmSign(tpmKey *client.Key, payload []byte) ([]byte, error) {\n\tbeforeSign := time.Now()\n\tsignature, err := tpmKey.SignData(payload)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to sign data with TPM: %w\", err)\n\t}\n\n\tklog.Infof(\"TPM signing took %v\", time.Since(beforeSign))\n\n\treturn signature, nil\n}\n\nfunc debugToPEM(key crypto.PublicKey) string {\n\tvar b bytes.Buffer\n\tpkData, err := x509.MarshalPKIXPublicKey(key)\n\tif err != nil {\n\t\treturn fmt.Sprintf(\"{MarshalPKIXPublicKey failed: %v}\", err)\n\t}\n\tif err := pem.Encode(&b, &pem.Block{Type: \"PUBLIC KEY\", Bytes: pkData}); err != nil {\n\t\treturn fmt.Sprintf(\"{pem.Encode failed: %v}\", err)\n\t}\n\treturn b.String()\n}","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/gce/tpm/gcetpmsigner/tpmauthenticator.go#L104-L140","documentation":"tpmSign wraps client.Key.SignData, which asks the TPM 2.0 device to sign the token payload using the GCE RSA attestation key. Failure here means the TPM returned an error during the signing operation — the low-level go-attestation/tpm2 call failed even though the key handle was obtained.","triggerScenarios":"tpmKey.SignData(payload) errors: bad TPM parameter, out of memory/sessions in the TPM, transient device I/O error, or wrong key algorithm/padding configuration.","commonSituations":"Simultaneous TPM use by multiple daemons exhausting session slots; kernel tpm driver timeouts under load; TPM hierarchy or policy authorization failure; hardware TPM faults on aging nodes.","solutions":["Retry the operation; many TPM failures are transient","Check kernel logs (dmesg | grep -i tpm) for driver/hardware errors","Close leaked key/session handles to free TPM resources","Verify TPM is healthy (TPM self-test via go-attestation or tpm2 tools)","Recreate the GCE instance if the vTPM is persistently failing"],"exampleFix":"null","handlingStrategy":"retry","validationCode":"// verify TPM is operational before signing workload\nif err := runTPMSelfTest(); err != nil {\n    return fmt.Errorf(\"TPM unhealthy: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"sig, err := tpmSign(key, payload)\nif err != nil {\n    if isTransientTPMError(err) { // e.g. timeouts, busy\n        return retryWithBackoff(func() ([]byte, error) { return tpmSign(key, payload) })\n    }\n    return nil, err\n}","preventionTips":["Avoid concurrent TPM session exhaustion by limiting parallel signers","Monitor kernel TPM driver logs","Close key handles promptly (defer key.Close())","Replace nodes with repeated hardware TPM faults"],"tags":["tpm","signing","crypto","hardware"],"backgroundTag":"tpm-sign-operation-failed","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}