OpenNHP/opennhp · error

curve id mismatch: got

Error message

curve id mismatch: got %d, want %d

What it means

verifyHygonCertInfo parses the curve-id field at offset 0x40..0x44 of a Hygon HRK/HSK certificate blob as a little-endian uint32 and compares it to the expected curveId (0x03 = SM2 for both HRK and HSK calls). A mismatch means the certificate blob does not declare the expected SM2 curve, so signature verification would be meaningless. NOTE: the format string is buggy — it prints curveId twice instead of the parsed value, so both numbers shown are the EXPECTED value.

Solutions

  1. Fix the format string to print hygonCurveIdInt so the actual observed curve id is visible.
  2. Validate blob size and structure (length >= 0x340, plausible magic/fields) before caching/parsing to avoid misaligned offsets.
  3. Re-fetch or replace the hskCek entry — clear any cached bogus value so the real certificate is downloaded again.
  4. If the certificate layout changed with new Hygon firmware, update the offset constants (0x24, 0x40, 0x14) in verifyHygonCertInfo.

Example fix

// before
if hygonCurveIdInt != curveId {
    return fmt.Errorf("curve id mismatch: got %d, want %d", curveId, curveId)
}
// after
if hygonCurveIdInt != curveId {
    return fmt.Errorf("curve id mismatch: got %d, want %d", hygonCurveIdInt, curveId)
}
Defensive patterns

Strategy: validation

Validate before calling

func validHygonCurve(blob []byte) bool {
    if len(blob) < 0x340 {
        return false
    }
    return binary.LittleEndian.Uint32(blob[0x40:0x44]) == 0x03
}

Type guard

func asSM2HygonCert(b []byte) ([]byte, bool) {
    if len(b) >= 0x44 && binary.LittleEndian.Uint32(b[0x40:0x44]) == 0x03 {
        return b, true
    }
    return nil, false
}

Try / catch

if err := attestation.Verify(ctx, evidence); err != nil {
    if strings.Contains(err.Error(), "curve id mismatch") {
        // cert blob is not the expected SM2 layout: clear cached CEK and re-fetch, else reject evidence
    }
}

Prevention

When it happens

Trigger: verifyCertChain calls verifyHygonCertInfo expecting curveId 0x03; the error fires when the dword at 0x40 of the HRK or downloaded HSK blob is not 3 — e.g. a different/garbage certificate was downloaded for the chipId, the blob is truncated/shifted so offset 0x40 lands on other data, or a future Hygon format uses a different curve id.

Common situations: Cached hskCek entry polluted by a non-certificate response (e.g. HTML error page cached after a mis-handled 200); attesting mixed-generation Hygon evidence; layout changes in newer Hygon firmware certificates.

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/4d77ec6d127105ad. Report an issue: GitHub.

Appendix: source

Thrown at nhp/core/verifier/csv/csv.go:425

	); 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]
	csvKeyUsageInt := int(binary.LittleEndian.Uint32(csvKeyUsage))
	if csvKeyUsageInt != keyUsage {
		return fmt.Errorf("key usage mismatch: got %d, want %d", csvKeyUsageInt, sigUsage)
	}

	csvSigUsage := csvCert[0x414:0x418]

View on GitHub (pinned to 6e04ca5ff0)