The branch OpenSSL_1_1_1-stable has been updated via 3c25ac2d2e614c16a8b76e0b863eb761ab436804 (commit) via f59967cb72a042a1ecb9e686f3494e4a6a38e173 (commit) via 6f6adf1d7bf44abfae96a52c791a69cf694fd7f8 (commit) from bd2931bf45bf35f1b3a3eb6ec4b4bb64fcdfdbfa (commit)
- Log ----------------------------------------------------------------- commit 3c25ac2d2e614c16a8b76e0b863eb761ab436804 Author: Nicola Tuveri <nic....@gmail.com> Date: Tue Nov 12 00:52:00 2019 +0200 Extend docs for EC_POINT conversion functions Add more explicit documentation about the relation between EC_POINT_point2oct(), EC_POINT_point2hex(), EC_POINT_point2bn() and their reverse. In particular highlight that EC_POINT_point2oct() and EC_POINT_oct2point() conform to, respectively, Sec. 2.3.3 and Sec. 2.3.4 of the SECG SEC 1 standard (which is the normative reference for the already mentioned RFC 5480), highlighting with a note how this affect the encoding/decoding of the point at infinity (which in contrast with any other valid generic point of a curve is assigned an exceptional fixed octet string encoding, i.e., 0x00). Reviewed-by: Matt Caswell <m...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/10329) (cherry picked from commit 3cc26f2eba8a8c16ac559e68c05c094d7ea6bd8b) commit f59967cb72a042a1ecb9e686f3494e4a6a38e173 Author: Nicola Tuveri <nic....@gmail.com> Date: Fri Nov 1 22:09:40 2019 +0200 Add self-test for EC_POINT_hex2point Adds tests for each curve to ensure that encodings obtained through EC_POINT_hex2point() can be fed to EC_POINT_point2hex() yielding a point identical to the one from which the encoding is generated. Reviewed-by: Matt Caswell <m...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/10329) (cherry picked from commit 35ed029b5a488924890fda2487c87f664361a33b) commit 6f6adf1d7bf44abfae96a52c791a69cf694fd7f8 Author: Nicola Tuveri <nic....@gmail.com> Date: Fri Nov 1 22:38:21 2019 +0200 Fix EC_POINT_bn2point() for BN_zero() EC_POINT_bn2point() rejected BIGNUMs with a zero value. This behavior indirectly caused failures when converting a point at infinity through EC_POINT_point2hex() and then back to a point with EC_POINT_hex2point(). With this change such BIGNUMs are treated like any other and exported to an octet buffer filled with zero. It is then EC_POINT_oct2point() (either the default implementation or the custom one in group->meth->oct2point) to determine if such encoding maps to a valid point (generally the point at infinity is encoded as 0x00). Fixes #10258 Reviewed-by: Matt Caswell <m...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/10329) (cherry picked from commit d47c10875656790d146f62ac3c437db54c58dbf7) ----------------------------------------------------------------------- Summary of changes: crypto/ec/ec_print.c | 4 +- doc/man3/EC_POINT_new.pod | 20 +++++++++ test/ectest.c | 103 +++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 124 insertions(+), 3 deletions(-) diff --git a/crypto/ec/ec_print.c b/crypto/ec/ec_print.c index f2525cbaa6..660fc400fb 100644 --- a/crypto/ec/ec_print.c +++ b/crypto/ec/ec_print.c @@ -39,13 +39,13 @@ EC_POINT *EC_POINT_bn2point(const EC_GROUP *group, EC_POINT *ret; if ((buf_len = BN_num_bytes(bn)) == 0) - return NULL; + buf_len = 1; if ((buf = OPENSSL_malloc(buf_len)) == NULL) { ECerr(EC_F_EC_POINT_BN2POINT, ERR_R_MALLOC_FAILURE); return NULL; } - if (!BN_bn2bin(bn, buf)) { + if (!BN_bn2binpad(bn, buf, buf_len)) { OPENSSL_free(buf); return NULL; } diff --git a/doc/man3/EC_POINT_new.pod b/doc/man3/EC_POINT_new.pod index 796f6666dd..8cadaa75f1 100644 --- a/doc/man3/EC_POINT_new.pod +++ b/doc/man3/EC_POINT_new.pod @@ -171,6 +171,26 @@ The functions EC_POINT_point2oct(), EC_POINT_oct2point(), EC_POINT_point2bn(), EC_POINT_bn2point(), EC_POINT_point2hex() and EC_POINT_hex2point() convert from and to EC_POINTs for the formats: octet, BIGNUM and hexadecimal respectively. +The function EC_POINT_point2oct() encodes the given curve point B<p> as an +octet string into the buffer B<buf> of size B<len>, using the specified +conversion form B<form>. +The encoding conforms with Sec. 2.3.3 of the SECG SEC 1 ("Elliptic Curve +Cryptography") standard. +Similarly the function EC_POINT_oct2point() decodes a curve point into B<p> from +the octet string contained in the given buffer B<buf> of size B<len>, conforming +to Sec. 2.3.4 of the SECG SEC 1 ("Elliptic Curve Cryptography") standard. + +The functions EC_POINT_point2hex() and EC_POINT_point2bn() convert a point B<p>, +respectively, to the hexadecimal or BIGNUM representation of the same +encoding of the function EC_POINT_point2oct(). +Vice versa, similarly to the function EC_POINT_oct2point(), the functions +EC_POINT_hex2point() and EC_POINT_point2bn() decode the hexadecimal or +BIGNUM representation into the EC_POINT B<p>. + +Notice that, according to the standard, the octet string encoding of the point +at infinity for a given curve is fixed to a single octet of value zero and that, +vice versa, a single octet of size zero is decoded as the point at infinity. + The function EC_POINT_point2oct() must be supplied with a buffer long enough to store the octet form. The return value provides the number of octets stored. Calling the function with a NULL buffer will not perform the conversion but diff --git a/test/ectest.c b/test/ectest.c index 136dc741eb..5c01cc95dd 100644 --- a/test/ectest.c +++ b/test/ectest.c @@ -1999,7 +1999,107 @@ static int cardinality_test(int n) BN_CTX_free(ctx); return ret; } -#endif + +/* + * Helper for ec_point_hex2point_test + * + * Self-tests EC_POINT_point2hex() against EC_POINT_hex2point() for the given + * (group,P) pair. + * + * If P is NULL use point at infinity. + */ +static ossl_inline +int ec_point_hex2point_test_helper(const EC_GROUP *group, const EC_POINT *P, + point_conversion_form_t form, + BN_CTX *bnctx) +{ + int ret = 0; + EC_POINT *Q = NULL, *Pinf = NULL; + char *hex = NULL; + + if (P == NULL) { + /* If P is NULL use point at infinity. */ + if (!TEST_ptr(Pinf = EC_POINT_new(group)) + || !TEST_true(EC_POINT_set_to_infinity(group, Pinf))) + goto err; + P = Pinf; + } + + if (!TEST_ptr(hex = EC_POINT_point2hex(group, P, form, bnctx)) + || !TEST_ptr(Q = EC_POINT_hex2point(group, hex, NULL, bnctx)) + || !TEST_int_eq(0, EC_POINT_cmp(group, Q, P, bnctx))) + goto err; + + /* + * The next check is most likely superfluous, as EC_POINT_cmp should already + * cover this. + * Nonetheless it increases the test coverage for EC_POINT_is_at_infinity, + * so we include it anyway! + */ + if (Pinf != NULL + && !TEST_true(EC_POINT_is_at_infinity(group, Q))) + goto err; + + ret = 1; + + err: + EC_POINT_free(Pinf); + OPENSSL_free(hex); + EC_POINT_free(Q); + + return ret; +} + +/* + * This test self-validates EC_POINT_hex2point() and EC_POINT_point2hex() + */ +static int ec_point_hex2point_test(int id) +{ + int ret = 0, nid; + EC_GROUP *group = NULL; + const EC_POINT *G = NULL; + EC_POINT *P = NULL; + BN_CTX * bnctx = NULL; + + /* Do some setup */ + nid = curves[id].nid; + if (!TEST_ptr(bnctx = BN_CTX_new()) + || !TEST_ptr(group = EC_GROUP_new_by_curve_name(nid)) + || !TEST_ptr(G = EC_GROUP_get0_generator(group)) + || !TEST_ptr(P = EC_POINT_dup(G, group))) + goto err; + + if (!TEST_true(ec_point_hex2point_test_helper(group, P, + POINT_CONVERSION_COMPRESSED, + bnctx)) + || !TEST_true(ec_point_hex2point_test_helper(group, NULL, + POINT_CONVERSION_COMPRESSED, + bnctx)) + || !TEST_true(ec_point_hex2point_test_helper(group, P, + POINT_CONVERSION_UNCOMPRESSED, + bnctx)) + || !TEST_true(ec_point_hex2point_test_helper(group, NULL, + POINT_CONVERSION_UNCOMPRESSED, + bnctx)) + || !TEST_true(ec_point_hex2point_test_helper(group, P, + POINT_CONVERSION_HYBRID, + bnctx)) + || !TEST_true(ec_point_hex2point_test_helper(group, NULL, + POINT_CONVERSION_HYBRID, + bnctx))) + goto err; + + ret = 1; + + err: + EC_POINT_free(P); + EC_GROUP_free(group); + BN_CTX_free(bnctx); + + return ret; +} + +#endif /* OPENSSL_NO_EC */ int setup_tests(void) { @@ -2025,6 +2125,7 @@ int setup_tests(void) ADD_ALL_TESTS(internal_curve_test_method, crv_len); ADD_ALL_TESTS(check_named_curve_from_ecparameters, crv_len); + ADD_ALL_TESTS(ec_point_hex2point_test, crv_len); #endif /* OPENSSL_NO_EC */ return 1; }