openssl: Tests broken in master with enable-ec_nistp_64_gcc_128
I just noticed that with PR #9081 we introduced a regression in ectest.c.
This is related to #8615 which details the same failing backtrace, but was not triggered by the tests until PR #9081 was merged.
Until #8615 is addressed, my opinion is that the test here is asserting on something that we have not guaranteed in practice for a long time now:
Before #9081 It used to start with: https://github.com/openssl/openssl/blob/be1dc984e1a5938170188cbdb6e536f1e7ac1656/test/ectest.c#L1823
and the only reason it was working was that there aren’t multiple EC_METHODs defined for secp112r1.
NIST P-224, P-256 and P-521 differ because on supporting 64-bit platforms the optimized ec_nistp_64_gcc_128 can be enabled at compile time (and for P-256 we also have the nistz256 implementation on several platforms).
When the library is compiled with enable-ec_nistp_64_gcc_128, make test will fail at line https://github.com/openssl/openssl/blob/10c25644e362381844e0089504f0db42f029d855/test/ectest.c#L1826
this happens because, on https://github.com/openssl/openssl/blob/be1dc984e1a5938170188cbdb6e536f1e7ac1656/test/ectest.c#L1823 by default the optimized EC_METHOD will be used to create the returned EC_GROUP, but on line https://github.com/openssl/openssl/blob/be1dc984e1a5938170188cbdb6e536f1e7ac1656/test/ectest.c#L1825 the groups is created using the raw parameter values, not by name, resulting in an EC_GROUP associated with the generic EC_METHOD for prime fields.
https://github.com/openssl/openssl/blob/10c25644e362381844e0089504f0db42f029d855/test/ectest.c#L1826 will internally call https://github.com/openssl/openssl/blob/10c25644e362381844e0089504f0db42f029d855/crypto/ec/ec_lib.c#L539-L543
which in turn will call
and subsequently
which fails as group->meth and point->meth differ.
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 17 (17 by maintainers)
Commits related to this issue
- Temporary workaround for ectest.c for [extended tests] [extended tests] This is a temporary workaround for issue #9251, which contains a full discussion of the real problem. As a temporary workarou... — committed to romen/openssl by romen 5 years ago
- Temporary workaround for ectest.c for [extended tests] [extended tests] This is a temporary workaround for issue #9251, which contains a full discussion of the real problem. As a temporary workarou... — committed to openssl/openssl by romen 5 years ago
@romen Do you have any objections to me adding a PR to do this for now? - just so the build is not broken. I think we are aware of the issue.
Until very recently (#8555) we did not have a “lookup by parameters” function, only by NID. Actually even now the lookup functionality is not entirely there, but can be implemented with wrappers around
EC_GROUP_check_named_curve().Still there are 2 problems left with this:
EC_GROUPmust be created inEC_GROUP_new_from_ecparameters(), thenEC_GROUP_check_named_curve()must be called on it to get the NID for that curve if it is one of the supported named curves doing a lot ofBN_bn2hex()conversions and string comparisons, then an entirely newEC_GROUPmust be created to replace the generic one if an NID is returned;EC_GROUPs, one created using a name and the other using an alias, that will have 2 differentEC_GROUP->curve_namevalues and fail the comparison.It makes sense because how to compare 2 points belonging to the same
EC_GROUPobject is defined in the associatedEC_METHOD: https://github.com/openssl/openssl/blob/10c25644e362381844e0089504f0db42f029d855/crypto/ec/ec_lib.c#L893Different
EC_METHODs may store point coordinates in different forms (e.g. affine coordinates in simple methods, different flavours of projective in specialized methods) so only theEC_METHODthat created anEC_POINTknows how to read its coordinates.Comparing 2
EC_POINTs from the sameEC_GROUPandEC_METHODis in general a relatively inexpensive operation, and in general in most places our code seems to assume it is a programmer’s error to create anEC_POINTfrom aEC_GROUP/EC_METHODand then use functions from anotherEC_GROUP/EC_METHODto manipulate it.If we decide that
EC_POINT_cmp()has to support mixing-and-matching forEC_POINTobjects andEC_GROUP/EC_METHODobjects, then we need theEC_POINT_cmp()wrapper to actually take on that job, convert both points to a canonical form (e.g. affine coordinates) and compare the canonical representations instead. But then we have a catch-22 paradox, because to compare 2EC_GROUPs we need to eventually compare the 2 generators, but evaluatingEC_POINT_cmp()on 2EC_POINTs created from 2 non-trivially-identicalEC_GROUP/EC_METHODs generally should require, in addition to comparing their canonical representations, that they belong to the same elliptic curve group (as in the same equation with the same parameters and the same generator, rather than the sameEC_GROUPprogramming object). When callingEC_POINT_cmp()from withinEC_GROUP_cmp()the paradox is trivially solved becauseEC_GROUP_cmp()checks all the other parameters before comparing the generators, so whatEC_GROUP_cmp()should probably do is never callEC_POINT_cmp()but locally do conversion to affine coordinates and compare the resultingBIGNUMs. This comes at the cost of 4 extraBIGNUMallocations, 2 potentially computationally expensive conversions from projective to affine, and probably more computationally expensiveBN_cmp()in affine form than in projective form.Still I believe it’s a reasonable change, but it can happen only after we solve #8615 (potentailly a behavioural change in the public API) and the ambiguity of what exactly
EC_GROUP_cmp()should return: are twoEC_GROUPobjects identical if they represent the same identical mathematical abstraction or if they are compatible from a programming perspective?In the latter case the programmer can reasonably assume that
EC_POINTobjects belonging toEC_GROUPobjects for whichEC_GROUP_cmp() == trueare interoperable from a programming perspecitve. In the first case a programmer can only assume that they belong to the same mathematical abstraction, but nothing more, so he still needs to make sure to never mixEC_POINTs belonging (as in created by) to differentEC_GROUPs and to do conversions (EC_POINT_get_affine(group_a, point, x, y)+equivalent_point_in_group_b=EC_POINT_new(group_b)+EC_POINT_set_affine(group_b, equivalent_point_in_group_b, x, y)) before comparing points that belong to the same mathematical abstraction but to non-identicalEC_GROUPobjects.All of this has implications for internal use in
libcrypto,libsslandapps/*, and for external applications as well, because it directly affects key comparisons, which can have unexpected consequences in PKI evaluation (either through dedicated libcrypto functions or through direct manipulation at theEClayer) or on the state machine for handling protocols.The behaviour of
EC_GROUP_cmp()is not clearly defined (#8615): until that is clarified it’s really difficult to understand what needs to be fixed: documentation, implementations or tests? Currently (1.02, 1.1.0, 1.1.1) theECsubsystem is not directly manipulated byENGINES, which can at most define an alternativeEC(DSA|DH)_KEY_METHODto implement alternative keygen/derive/sign/verify methods but either implement their internalECstack or reuse the unmodified OpenSSL one (without much flexibility in expanding it as there is noEC_METHOD_new()nor setters no access to inject entries in the lookup tables, OID/ASN1 details, etc. If this is going to change with the transition to providers then yes, we need to clarify all the issues related to this and other documentation problems of EC to make sure we are internally consistent and have a clear contract for external implementations.