{"record":{"id":"4d77ec6d127105ad","repo":"OpenNHP/opennhp","slug":"curve-id-mismatch-got-d-want-d","errorCode":null,"errorMessage":"curve id mismatch: got %d, want %d","messagePattern":"curve id mismatch: got (.+?), want (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nhp/core/verifier/csv/csv.go","lineNumber":425,"sourceCode":"\t); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\nfunc (a *Attestation) verifyHygonCertInfo(hrk []byte, curveId, keyUsage int, keyId []byte) error {\n\thygonKeyUsage := hrk[0x24:0x28]\n\n\thygonKeyUsageInt := int(binary.LittleEndian.Uint32(hygonKeyUsage))\n\tif hygonKeyUsageInt != keyUsage {\n\t\treturn fmt.Errorf(\"key usage mismatch: got %d, want %d\", keyUsage, keyUsage)\n\t}\n\n\thygonCurveId := hrk[0x40:0x44]\n\thygonCurveIdInt := int(binary.LittleEndian.Uint32(hygonCurveId))\n\tif hygonCurveIdInt != curveId {\n\t\treturn fmt.Errorf(\"curve id mismatch: got %d, want %d\", curveId, curveId)\n\t}\n\n\thygonCertifyingId := hrk[0x14:0x24]\n\tif !bytes.Equal(hygonCertifyingId, keyId) {\n\t\treturn fmt.Errorf(\"certifying id mismatch: got %x, want %x\", hygonCertifyingId, keyId)\n\t}\n\n\treturn nil\n}\n\nfunc (a *Attestation) verifyCSVCertInfo(csvCert []byte, sigUsage int, sigAlgo int, keyUsage int, keyId []byte) error {\n\tcsvKeyUsage := csvCert[0x08:0x0C]\n\tcsvKeyUsageInt := int(binary.LittleEndian.Uint32(csvKeyUsage))\n\tif csvKeyUsageInt != keyUsage {\n\t\treturn fmt.Errorf(\"key usage mismatch: got %d, want %d\", csvKeyUsageInt, sigUsage)\n\t}\n\n\tcsvSigUsage := csvCert[0x414:0x418]","sourceCodeStart":407,"sourceCodeEnd":443,"githubUrl":"https://github.com/OpenNHP/opennhp/blob/6e04ca5ff03222a699c24205cd4bf8fee9af7ffe/nhp/core/verifier/csv/csv.go#L407-L443","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Fix the format string to print hygonCurveIdInt so the actual observed curve id is visible.","Validate blob size and structure (length >= 0x340, plausible magic/fields) before caching/parsing to avoid misaligned offsets.","Re-fetch or replace the hskCek entry — clear any cached bogus value so the real certificate is downloaded again.","If the certificate layout changed with new Hygon firmware, update the offset constants (0x24, 0x40, 0x14) in verifyHygonCertInfo."],"exampleFix":"// before\nif hygonCurveIdInt != curveId {\n    return fmt.Errorf(\"curve id mismatch: got %d, want %d\", curveId, curveId)\n}\n// after\nif hygonCurveIdInt != curveId {\n    return fmt.Errorf(\"curve id mismatch: got %d, want %d\", hygonCurveIdInt, curveId)\n}","handlingStrategy":"validation","validationCode":"func validHygonCurve(blob []byte) bool {\n    if len(blob) < 0x340 {\n        return false\n    }\n    return binary.LittleEndian.Uint32(blob[0x40:0x44]) == 0x03\n}","typeGuard":"func asSM2HygonCert(b []byte) ([]byte, bool) {\n    if len(b) >= 0x44 && binary.LittleEndian.Uint32(b[0x40:0x44]) == 0x03 {\n        return b, true\n    }\n    return nil, false\n}","tryCatchPattern":"if err := attestation.Verify(ctx, evidence); err != nil {\n    if strings.Contains(err.Error(), \"curve id mismatch\") {\n        // cert blob is not the expected SM2 layout: clear cached CEK and re-fetch, else reject evidence\n    }\n}","preventionTips":["Sanity-check the curve-id dword (0x40) before trusting any Hygon cert blob.","Clear stale hskCek cache entries when the CA download may have returned non-certificate content.","Fix the logging bug so mismatches print the actual observed curve id.","Track Hygon firmware/certificate format changes and adjust hardcoded offsets."],"tags":["attestation","certificate-validation","parsing","logging-bug"],"backgroundTag":"schema-validation-failed","analyzedSha":"6e04ca5ff03222a699c24205cd4bf8fee9af7ffe","analyzedAt":"2026-09-07T15:44:59.941Z","contentChangedAt":"2026-09-07T15:44:59.941Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}