diff --git a/src/pk.c b/src/pk.c index dfc362f69..ba03fdeb5 100644 --- a/src/pk.c +++ b/src/pk.c @@ -9711,7 +9711,6 @@ void wolfSSL_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *point) #endif } -#ifndef HAVE_SELFTEST /* Convert EC point to hex string that as either uncompressed or compressed. * * ECC point compression types were not included in selftest ecc.h @@ -9788,12 +9787,12 @@ char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group, * odd. */ hex[0] = mp_isodd((mp_int*)point->Y->internal) ? - ECC_POINT_COMP_ODD : ECC_POINT_COMP_EVEN; + 0x03 : 0x02; /* No y-ordinate. */ } else { /* Put in uncompressed format byte. */ - hex[0] = ECC_POINT_UNCOMP; + hex[0] = 0x04; /* Calculate offset as leading zeros not encoded. */ i = 1 + 2 * sz - mp_unsigned_bin_size((mp_int*)point->Y->internal); /* Put in y-ordinate after x-ordinate. */ @@ -9824,7 +9823,117 @@ char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group, return hex; } -#endif /* HAVE_SELFTEST */ +static size_t hex_to_bytes(const char *hex, unsigned char *output, size_t sz) +{ + word32 i; + for (i = 0; i < sz; i++) + { + signed char ch1, ch2; + ch1 = HexCharToByte(hex[i * 2]); + ch2 = HexCharToByte(hex[i * 2 + 1]); + if ((ch1 < 0) || (ch2 < 0)) + { + WOLFSSL_MSG("hex_to_bytes: syntax error"); + return 0; + } + output[i] = (unsigned char)((ch1 << 4) + ch2); + } + return sz; +} + +WOLFSSL_EC_POINT*wolfSSL_EC_POINT_hex2point(const EC_GROUP *group, + const char *hex, WOLFSSL_EC_POINT*p, WOLFSSL_BN_CTX *ctx) +{ + /* for uncompressed mode */ + size_t str_sz; + BIGNUM *Gx = NULL; + BIGNUM *Gy = NULL; + char *strGx = NULL; + + /* for compressed mode */ + int key_sz; + byte *octGx = NULL; + + #define P_ALLOC 1 + int p_alloc = 0; + int ret; + + WOLFSSL_ENTER("wolfSSL_EC_POINT_hex2point"); + + if (group == NULL || hex == NULL || ctx == NULL) + return NULL; + + if (p == NULL) { + if ((p = wolfSSL_EC_POINT_new(group)) == NULL) { + WOLFSSL_MSG("wolfSSL_EC_POINT_new"); + goto err; + } + p_alloc = P_ALLOC; + } + + if (hex[0] == '0' && hex[1] == '4') { /* uncompressed mode */ + str_sz = ((wolfSSL_EC_GROUP_get_degree(group) + 7) / 8) * 2; + strGx = (char *)XMALLOC(str_sz + 1, NULL, DYNAMIC_TYPE_ECC); + if (strGx == NULL) { + WOLFSSL_MSG("malloc error"); + goto err; + } + + XMEMSET(strGx, 0x0, str_sz + 1); + XMEMCPY(strGx, hex + 2, str_sz); + + if (BN_hex2bn(&Gx, strGx) == 0) + goto err; + + if (BN_hex2bn(&Gy, hex + 2 + str_sz) == 0) + goto err; + + ret = wolfSSL_EC_POINT_set_affine_coordinates_GFp + (group, p, Gx, Gy, ctx); + + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_EC_POINT_set_affine_coordinates_GFp"); + goto err; + } + } + else if (hex[0] == '0' && (hex[1] == '2' || hex[1] == '3')) { + /* compressed mode */ + key_sz = ((wolfSSL_EC_GROUP_get_degree(group) + 7) / 8); + octGx = (byte *)XMALLOC(key_sz + 1, NULL, DYNAMIC_TYPE_ECC); + if (octGx == NULL) { + WOLFSSL_MSG("EEC_KEY_get_byte_size, XMALLOC"); + goto err; + } + octGx[0] = 0x03; + if (hex_to_bytes(hex + 2, octGx + 1, XSTRLEN(hex + 2) / 2) + != XSTRLEN(hex + 2) / 2) { + goto err; + } + if (wolfSSL_ECPoint_d2i(octGx, key_sz + 1, group, p) + != WOLFSSL_SUCCESS) { + goto err; + } + } + else + goto err; + + XFREE(strGx, NULL, DYNAMIC_TYPE_ECC); + XFREE(octGx, NULL, DYNAMIC_TYPE_ECC); + wolfSSL_BN_free(Gx); + wolfSSL_BN_free(Gy); + return p; + +err: + XFREE(strGx, NULL, DYNAMIC_TYPE_ECC); + XFREE(octGx, NULL, DYNAMIC_TYPE_ECC); + wolfSSL_BN_free(Gx); + wolfSSL_BN_free(Gy); + if (p_alloc) { + EC_POINT_free(p); + } + return NULL; + +} /* Encode the EC point as an uncompressed point in DER. * diff --git a/tests/api.c b/tests/api.c index d9c75f675..270e85256 100644 --- a/tests/api.c +++ b/tests/api.c @@ -59640,6 +59640,7 @@ static int test_wolfSSL_EC_POINT(void) EC_POINT* Gxy = NULL; EC_POINT* new_point = NULL; EC_POINT* set_point = NULL; + EC_POINT* get_point = NULL; EC_POINT* infinity = NULL; BIGNUM* k = NULL; BIGNUM* Gx = NULL; @@ -59657,6 +59658,14 @@ static int test_wolfSSL_EC_POINT(void) "77037D812DEB33A0F4A13945D898C296"; const char* kGy = "4FE342E2FE1A7F9B8EE7EB4A7C0F9E16" "2BCE33576B315ECECBB6406837BF51F5"; + const char* uncompG + = "046B17D1F2E12C4247F8BCE6E563A440F2" + "77037D812DEB33A0F4A13945D898C296" + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E16" + "2BCE33576B315ECECBB6406837BF51F5"; + const char* compG + = "036B17D1F2E12C4247F8BCE6E563A440F2" + "77037D812DEB33A0F4A13945D898C296"; #ifndef HAVE_SELFTEST EC_POINT *tmp = NULL; @@ -59665,10 +59674,6 @@ static int test_wolfSSL_EC_POINT(void) unsigned char* buf = NULL; unsigned char bufInf[1] = { 0x00 }; - const char* uncompG = "046B17D1F2E12C4247F8BCE6E563A440F2" - "77037D812DEB33A0F4A13945D898C296" - "4FE342E2FE1A7F9B8EE7EB4A7C0F9E16" - "2BCE33576B315ECECBB6406837BF51F5"; const unsigned char binUncompG[] = { 0x04, 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, @@ -59686,8 +59691,6 @@ static int test_wolfSSL_EC_POINT(void) 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5, }; - const char* compG = "036B17D1F2E12C4247F8BCE6E563A440F2" - "77037D812DEB33A0F4A13945D898C296"; #ifdef HAVE_COMP_KEY const unsigned char binCompG[] = { 0x03, 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, @@ -59912,7 +59915,6 @@ static int test_wolfSSL_EC_POINT(void) #endif XFREE(hexStr, NULL, DYNAMIC_TYPE_ECC); -#ifndef HAVE_SELFTEST /* Test point to hex */ ExpectNull(EC_POINT_point2hex(NULL, NULL, POINT_CONVERSION_UNCOMPRESSED, ctx)); @@ -59929,13 +59931,22 @@ static int test_wolfSSL_EC_POINT(void) hexStr = EC_POINT_point2hex(group, Gxy, POINT_CONVERSION_UNCOMPRESSED, ctx); ExpectNotNull(hexStr); ExpectStrEQ(hexStr, uncompG); + AssertNotNull(get_point = EC_POINT_hex2point(group, hexStr, NULL, ctx)); + AssertIntEQ(EC_POINT_cmp(group, Gxy, get_point, ctx), 0); XFREE(hexStr, NULL, DYNAMIC_TYPE_ECC); hexStr = EC_POINT_point2hex(group, Gxy, POINT_CONVERSION_COMPRESSED, ctx); ExpectNotNull(hexStr); ExpectStrEQ(hexStr, compG); + #ifdef HAVE_COMP_KEY + AssertNotNull(get_point = EC_POINT_hex2point + (group, hexStr, get_point, ctx)); + AssertIntEQ(EC_POINT_cmp(group, Gxy, get_point, ctx), 0); + #endif XFREE(hexStr, NULL, DYNAMIC_TYPE_ECC); + EC_POINT_free(get_point); +#ifndef HAVE_SELFTEST /* Test point to oct */ ExpectIntEQ(EC_POINT_point2oct(NULL, NULL, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, ctx), 0); diff --git a/wolfssl/openssl/ec.h b/wolfssl/openssl/ec.h index 23ef5e9a2..7a77210c6 100644 --- a/wolfssl/openssl/ec.h +++ b/wolfssl/openssl/ec.h @@ -306,12 +306,14 @@ WOLFSSL_API int wolfSSL_EC_POINT_is_at_infinity(const WOLFSSL_EC_GROUP *group, const WOLFSSL_EC_POINT *a); -#ifndef HAVE_SELFTEST WOLFSSL_API char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group, const WOLFSSL_EC_POINT* point, int form, WOLFSSL_BN_CTX* ctx); -#endif +WOLFSSL_API +WOLFSSL_EC_POINT *wolfSSL_EC_POINT_hex2point + (const WOLFSSL_EC_GROUP *group, const char *hex, + WOLFSSL_EC_POINT *p, WOLFSSL_BN_CTX *ctx); #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) @@ -395,9 +397,8 @@ typedef WOLFSSL_EC_BUILTIN_CURVE EC_builtin_curve; #define EC_KEY_set_conv_form wolfSSL_EC_KEY_set_conv_form #define EC_KEY_get_conv_form wolfSSL_EC_KEY_get_conv_form -#ifndef HAVE_SELFTEST - #define EC_POINT_point2hex wolfSSL_EC_POINT_point2hex -#endif +#define EC_POINT_point2hex wolfSSL_EC_POINT_point2hex +#define EC_POINT_hex2point wolfSSL_EC_POINT_hex2point #define EC_POINT_dump wolfSSL_EC_POINT_dump #define EC_get_builtin_curves wolfSSL_EC_get_builtin_curves