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

  1. Fix the format string to print the parsed value (hygonKeyUsageInt) so you can actually see what was found.
  2. 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.
  3. Verify the blob length is at least 0x340 bytes before slicing (guards against short/HTML error pages being cached as hskCek).
  4. 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

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


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)