OpenNHP/opennhp · error
key usage mismatch: got
Error message
key usage mismatch: got %d, want %d
What it means
verifyHygonCertInfo parses the key-usage field at offset 0x24..0x28 of a Hygon root (HRK) or HSK certificate blob as a little-endian uint32 and compares it with the expected keyUsage passed by the caller. If they differ it returns this mismatch error — a tampered, corrupted, or wrong-generation certificate blob. NOTE: the format string is buggy — it prints keyUsage twice instead of the parsed value ("got %d, want %d", keyUsage, keyUsage), so both numbers shown are the EXPECTED value.
Solutions
- Fix the format string to print the parsed value (hygonKeyUsageInt) so you can actually see what was found.
- Dump the certificate blob around offset 0x24 and confirm which Hygon generation it belongs to; ensure the hsk_cek download for that chipId returned the correct HSK certificate.
- Verify the blob length is at least 0x340 bytes before slicing (guards against short/HTML error pages being cached as hskCek).
- If a Hygon firmware update changed the certificate layout, update the hardcoded offsets/usages in verifyHygonCertInfo.
Example fix
// before
if hygonKeyUsageInt != keyUsage {
return fmt.Errorf("key usage mismatch: got %d, want %d", keyUsage, keyUsage)
}
// after
if hygonKeyUsageInt != keyUsage {
return fmt.Errorf("key usage mismatch: got %d, want %d", hygonKeyUsageInt, keyUsage)
} Defensive patterns
Strategy: validation
Validate before calling
func validHygonCertBlob(blob []byte) bool {
if len(blob) < 0x340 {
return false
}
usage := binary.LittleEndian.Uint32(blob[0x24:0x28])
return usage == 0x00 || usage == 0x13
} Type guard
func asHygonCert(b []byte) ([]byte, bool) {
if len(b) >= 0x340 && (binary.LittleEndian.Uint32(b[0x24:0x28]) == 0x00 || binary.LittleEndian.Uint32(b[0x24:0x28]) == 0x13) {
return b, true
}
return nil, false
} Try / catch
if err := attestation.Verify(ctx, evidence); err != nil {
if strings.Contains(err.Error(), "key usage mismatch") {
// wrong/corrupt Hygon cert blob: re-fetch CEK or reject the evidence as invalid
}
} Prevention
- Validate downloaded/cached certificate blob length and key fields before caching.
- Never cache an HTTP response body without confirming it is a real certificate (size + field sanity).
- Fix the logging bug so mismatches print the actual observed key usage.
- Pin per-generation Hygon certificate expectations and update them alongside firmware upgrades.
When it happens
Trigger: verifyCertChain calls verifyHygonCertInfo with expected usages 0 (HRK) and 0x13 (HSK); the error fires when the certificate blob's key-usage dword at 0x24 is not exactly that value — e.g. the downloaded hsk_cek for the chipId is not a valid HSK certificate, the HRK blob was corrupted, or memory offsets shifted due to a Hygon firmware/generation change.
Common situations: Attesting evidence from a different Hygon CPU generation than the blob downloaded for its chipId; truncated or corrupt certificate data (e.g. a slice shorter than 0x340 bytes being treated as hskData); manually supplied HRK that fails the hardcoded SM3 digest check earlier would fail first, so this usually indicates HSK/CEK data problems.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- curve id mismatch: got
- failed to unmarshal evidence
- unsupported key type, expect RSA
- JWT signing key is not initialized
- TEE public key is not found for specified token
AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07).
Data as JSON: /api/errors/2159fac78e308ba7.
Report an issue: GitHub.
Appendix: source
Thrown at nhp/core/verifier/csv/csv.go:419
// verify pek cert signature (self-signed)
cekIdLen := int(binary.LittleEndian.Uint16(cekData[0xa4:0xa6]))
if err := a.verifySm2SignatureWithId(
cekData[0x14:0x34], cekData[0x5c:0x7c],
pekData[0x41c:0x43c], pekData[0x464:0x484],
cekData[0xa6:0xa6+cekIdLen], pekData[:0x414],
); err != nil {
return err
}
return nil
}
func (a *Attestation) verifyHygonCertInfo(hrk []byte, curveId, keyUsage int, keyId []byte) error {
hygonKeyUsage := hrk[0x24:0x28]
hygonKeyUsageInt := int(binary.LittleEndian.Uint32(hygonKeyUsage))
if hygonKeyUsageInt != keyUsage {
return fmt.Errorf("key usage mismatch: got %d, want %d", keyUsage, keyUsage)
}
hygonCurveId := hrk[0x40:0x44]
hygonCurveIdInt := int(binary.LittleEndian.Uint32(hygonCurveId))
if hygonCurveIdInt != curveId {
return fmt.Errorf("curve id mismatch: got %d, want %d", curveId, curveId)
}
hygonCertifyingId := hrk[0x14:0x24]
if !bytes.Equal(hygonCertifyingId, keyId) {
return fmt.Errorf("certifying id mismatch: got %x, want %x", hygonCertifyingId, keyId)
}
return nil
}
func (a *Attestation) verifyCSVCertInfo(csvCert []byte, sigUsage int, sigAlgo int, keyUsage int, keyId []byte) error {
csvKeyUsage := csvCert[0x08:0x0C]View on GitHub (pinned to 6e04ca5ff0)