evp: fix EVP_PKEY_cmp for EC keys after DER deserialization#9987
Conversation
There was a problem hiding this comment.
Pull request overview
Fixes wolfSSL_EVP_PKEY_cmp returning “not equal” for identical EC keys when one key was DER-deserialized without an embedded public key, aligning behavior with the expected OpenSSL-style key-material comparison semantics.
Changes:
- Sync EC
ecc_keyinternal state (inSet) before comparing inwolfSSL_EVP_PKEY_cmp. - For private-only EC imports, derive the public key before point comparison.
- Harden
wc_ecc_import_point_der_exby validating point type early and rejecting truncated compressed-point encodings.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| wolfcrypt/src/evp.c | Synces EC internal state and derives missing public key to make EC key comparisons succeed after DER deserialization. |
| wolfcrypt/src/ecc.c | Adds earlier input validation for EC point import and rejects invalid/truncated compressed encodings. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
LinuxJedi
left a comment
There was a problem hiding this comment.
@MarkAtwood please remove the Claude co-authored-by in the commit message.
5bb8c48 to
631cfa6
Compare
wolfSSL_EVP_PKEY_cmp returned 'not equal' for EC keys that were serialized to DER and deserialized back, even though the key material was identical. This happened because keys imported via RFC 5915 (ECPrivateKey) without the optional public key field had type ECC_PRIVATEKEY_ONLY, meaning the internal ecc_key.pubkey was not populated. The point comparison then failed against a key that did have a populated pubkey. Fix by deriving the public key from the private key via wc_ecc_make_pub() when the ecc_key type is ECC_PRIVATEKEY_ONLY before comparing. Also ensure SetECKeyInternal() is called when the internal representation is not yet synced from external BIGNUMs.
631cfa6 to
05f8d0b
Compare
|
Jenkins retest this please |
|
|
Co-Authored-By line was already removed in the current commit. The CHANGES_REQUESTED is stale — ready for re-review. |
Summary
wolfSSL_EVP_PKEY_cmpreturns "not equal" for EC keys that are identical but one was deserialized from DER. This breaks the OpenSSL API contract thatEVP_PKEY_cmpcompares key material regardless of how theEVP_PKEYobjects were constructed.Reproducer
Root Cause
Two issues compound:
1.
inSetnot checked before accessingecc->internalAfter
d2i_PrivateKeyord2i_ECPrivateKey, the external WOLFSSL_EC_KEY fields (BIGNUMs for private key, WOLFSSL_EC_POINT for public key) are populated, but the internal wolfCryptecc_keystruct may not be synced. TheinSetflag tracks this.wolfSSL_EVP_PKEY_cmpaccessedecc->internalwithout checkinginSetor callingSetECKeyInternalto sync.2. Private-only keys have empty
pubkeypointWhen
wc_EccPrivateKeyDecodeparses an RFC 5915ECPrivateKeythat omits the optional public key field (which is valid per the RFC), it callswc_ecc_import_private_key_exwithpub=NULL, pubSz=0. This setsecc_key.type = ECC_PRIVATEKEY_ONLYand leavesecc_key.pubkeyas all zeros. The comparison then compared a populated pubkey against zeros → "not equal".Fix
In the
WC_EVP_PKEY_ECcase ofwolfSSL_EVP_PKEY_cmp:SetECKeyInternal()ifinSet == 0to sync external → internal representationecc_key.type == ECC_PRIVATEKEY_ONLY, callwc_ecc_make_pub()to derive the public key from the private key before comparingThis ensures the comparison works regardless of how the key was constructed — generated, imported with public key, or imported private-only.
Test Plan
EVP_PKEY_cmpreturns matchEVP_PKEY_cmpreturns match